// Pocket Post Pet用 stdio.h

#include <windows.h>

#include "ppp_stdio.h"

#define MAX_OPEN_FILE 16

//#define USE_DEBUGLOG

static int first_init = 1;
void DEBUGLOG( char * str , ... );

typedef struct _FILE_HANDLE {
	int    use;
	HANDLE fp;
	int    eof;
	int    error;
} FILE_HANDLE;
	
FILE_HANDLE	FH[MAX_OPEN_FILE];

void DEBUGLOG( char * str , ... )
{
#ifdef USE_DEBUGLOG
	HANDLE fp;
	int ret;
	int rcount;
	va_list marker;
	char buf[1024];
	TCHAR fname[1024];
	TCHAR * bufptr;

	GetModuleFileName(GetModuleHandle(NULL),fname,1023);
    if ((bufptr=_tcsrchr(fname,_T('\\'))) != NULL ) *bufptr = NULL;
	_tcscat( fname, _T("\\debug.log") );
	fp = CreateFile(
				fname , 
				GENERIC_WRITE,
				0,					// no shared
				NULL,				// set NULL
				OPEN_ALWAYS,
				FILE_ATTRIBUTE_NORMAL |	FILE_FLAG_RANDOM_ACCESS,
				0 );

	SetFilePointer(fp, 0,NULL,FILE_END );

	va_start( marker, str );     /* 可変個の引数の初期化 */
	vsprintf( buf,str,marker );
	va_end( marker );

	ret = WriteFile( fp, buf, strlen(buf), &rcount, NULL ); 

	CloseHandle( fp );

#endif
}

FILE * ppp_fopen(const char * name, const char * type)
{
	int i;
	int dwDesiredAccess;
	int dwCreationDispostion;
	wchar_t	wname[512];
    int ret;

	DEBUGLOG("ppp_fopen start name[%s]\n",name);

	if( first_init ){
		first_init = 0;
		memset( FH, '\0', sizeof(FILE_HANDLE) * MAX_OPEN_FILE );
	}

	if (type[0]=='w' ) { 
		DEBUGLOG("ppp_fopen type[w] \n");
		dwDesiredAccess = GENERIC_WRITE;	
		dwCreationDispostion = OPEN_ALWAYS;		
	}else if( type[0]=='r' ){
		if( type[1]=='+' ){
			DEBUGLOG("ppp_fopen type[r] \n");
			dwDesiredAccess = GENERIC_READ + GENERIC_WRITE;
		}else{
			DEBUGLOG("ppp_fopen type[r+] \n");
			dwDesiredAccess = GENERIC_READ;
		}
		dwCreationDispostion = OPEN_EXISTING;
	}else if (type[0]=='a' ) { 
		DEBUGLOG("ppp_fopen type[a] \n");
		dwDesiredAccess = GENERIC_WRITE;
		dwCreationDispostion = OPEN_ALWAYS;
	}else{
		DEBUGLOG("ppp_fopen type[unknown] \n");
		return NULL;
	}

	for( i =1;i<MAX_OPEN_FILE;i++ ){
		if( !FH[i].use ) break;
	}
	DEBUGLOG("ppp_fopen FH[%d] \n", i);

    ret = MultiByteToWideChar( CP_ACP,0, name,-1,wname,511 );
//	mbstowcs( wname, name, 512 );

	FH[i].fp = CreateFile( wname, 
				dwDesiredAccess,
				0,					// no shared
				NULL,				// set NULL
				dwCreationDispostion,
				FILE_ATTRIBUTE_NORMAL |	FILE_FLAG_RANDOM_ACCESS,
				0 );
	DEBUGLOG("ppp_fopen CreateFile[%d]\n", FH[i].fp);
	if( FH[i].fp > 0 ){
		FH[i].use=1;
		FH[i].eof=0;
		FH[i].error=0;
	}else{
		DEBUGLOG("ppp_fopen error end\n");
		return (FILE *)NULL;
	}

	if( type[0]=='a' ) {
		ppp_fseek( (FILE *)i, 0, SEEK_END );
	}

	DEBUGLOG("ppp_fopen end\n");
	return (FILE *) i;
}

int cdecl ppp_fclose(FILE * fp)
{
	DEBUGLOG("ppp_fclose start FH[%d]\n", (int)fp );
	CloseHandle( FH[(int)fp].fp );
	FH[(int)fp].use = 0;
	FH[(int)fp].eof = 0;
	FH[(int)fp].error = 0;
	DEBUGLOG("ppp_fclose end \n");
	return 0;
}

size_t ppp_fread(void *buffer, size_t size, size_t count, FILE * fp )
{
	BOOL ret;
	DWORD rcount;
	DEBUGLOG("ppp_fread start FH[%d]\n", (int)fp );

	ret = ReadFile( FH[(int)fp].fp , buffer, size * count, &rcount, NULL );
	if( ret ){
		DEBUGLOG("ppp_fread normal end ret[%d]\n", (size_t)rcount/size );
		return (size_t)rcount/size;
	}else{
		DEBUGLOG("ppp_fread error? end ret[0]\n" );
		return 0;
	}
}

size_t ppp_fwrite( const void *buffer, size_t size, size_t count, FILE *fp )
{
	BOOL ret;
	DWORD rcount;

	DEBUGLOG("ppp_fwrite start ret[%d]\n", (int)fp );

	ret = WriteFile( FH[(int)fp].fp, buffer, size * count, &rcount, NULL ); 
	if( ret ){
		DEBUGLOG("ppp_fwrite normal end ret[%d]\n", (size_t)rcount/size );
		return (size_t)rcount/size;
	}else{
		DEBUGLOG("ppp_fwrite error? end ret[0]\n");
		return 0;
	}
}

int ppp_fseek( FILE *stream, long offset, int origin )
{
	DWORD ret;
	DWORD mmethod; 

	DEBUGLOG("ppp_fseek start FH[%d]\n", (int)stream );
	
	switch( origin ){
		case SEEK_SET : mmethod = FILE_BEGIN;	break;
		case SEEK_CUR : mmethod = FILE_CURRENT;	break;
		case SEEK_END : mmethod = FILE_END;		break;
	}

	ret = SetFilePointer( FH[(int)stream].fp, offset, NULL, mmethod );

	if( ret != 0xFFFFFFFF ){	
		DEBUGLOG("ppp_fseek normal end ret[0]\n" );
		FH[(int)stream].eof = 0;
		FH[(int)stream].error = 0;
		return 0;
	}else{
		DEBUGLOG("ppp_fseek error end ret[1]\n" );
		return 1;
	}
}

int ppp_rewind( FILE *stream )
{
	return ppp_fseek( stream, 0, FILE_BEGIN );
}

int ppp_fscanf(FILE * fp, const char * first , ...)
{
	DEBUGLOG( "fscanf function is not impliment.\n" );
	return 0;
}

int ppp_fprintf(FILE * fp, const char * first, ...)
{
	va_list marker;
	char buf[1024];
	DEBUGLOG("ppp_fprintf start FH[%d]\n",(int)fp );

	va_start( marker, first );     /* 可変個の引数の初期化 */
	vsprintf( buf,first,marker );
	va_end( marker );

	ppp_fwrite( buf, 1, strlen(buf),fp );
	DEBUGLOG("ppp_fprintf end\n" );
	return 0;
}

int ppp_fgetc( FILE * fp )
{
	DWORD ret;
	DWORD rcount;
	char buffer;

	DEBUGLOG("ppp_fgetc start FH[%d]\n",(int)fp );
	
	ret = ReadFile( FH[(int)fp].fp , &buffer, 1, &rcount, NULL );
	if( ret ){
		if(rcount > 0){
			DEBUGLOG("ppp_fgetc end ret[%d]\n", (int)buffer );
			return (int)buffer;
		} else {
			DEBUGLOG("ppp_fgetc end ret[EOF]\n" );
		}
	}else{
		DEBUGLOG("ppp_fgetc error end\n" );
		FH[(int)fp].error = 1;
	}
	FH[(int)fp].eof = 1;
	return EOF;
}

char * ppp_fgets( char * str , int n, FILE * fp )
{
	DWORD ret;
	int i;
	int rcount;

	DEBUGLOG("ppp_fgets start FH[%d]\n",(int)fp );

	str[0] = '\0';
	for(i=0;i<n-1;i++){
		ret = ReadFile( FH[(int)fp].fp , &str[i], 1, &rcount, NULL );
		if( ret ){
			if(rcount<1){
				str[i]='\0';
				FH[(int)fp].eof = 1;
				break;
			}
			if(str[i]=='\n'){
				str[i+1] = '\0';
				break;
			}
		}else{
			str[0]='\0';
			FH[(int)fp].eof = 1;
			FH[(int)fp].error = 1;
			break;
		}
	}
	if( i == n-1 ) str[i] = '\0';

	DEBUGLOG("ppp_fgets end ret[%s]\n",str );
	if( str[0] == '\0' ) return NULL;
					else return str;
}

int ppp_fputc(int c,  FILE * fp )
{
	int ret;
	int rcount;
	unsigned char buf = (unsigned char)c;
	ret = WriteFile( FH[(int)fp].fp , &buf, 1, &rcount, NULL );
	if( ret ){
		if( rcount ){
			return c;
		}
	}
	return EOF;
}

int ppp_ftell( FILE * fp )
{
	return SetFilePointer(FH[(int)fp].fp, 0,NULL,FILE_CURRENT );
}

int ppp_feof( FILE * fp )
{
	return FH[(int)fp].eof;
}

int ppp_ferror( FILE * fp )
{
	return FH[(int)fp].error;
}

int ppp_GetFileSize( FILE * fp )
{
	DWORD len;
		
	len = GetFileSize( FH[(int)fp].fp, NULL );
	return len;
}


void * ppp_calloc( size_t num, size_t siz)
{
	void * ret;
	ret = malloc( num*siz );
	memset( ret,0,num*siz );
	return ret;
}

char * ppp_strrchr(const char * buf, int chr)
{
	size_t cnt;
	char *p;

	if( (cnt = strlen(buf)) ==(size_t)0 ) return NULL;
	p =(char*)buf + cnt;
	while(p>=buf){
		if(*p == chr) return p;
		p--;
	}
	return NULL;
}

char * ppp_mbsrchr(const unsigned char * buf, unsigned int chr)
{
	size_t cnt;
	unsigned char *p;

	if( (cnt = strlen(buf)) ==(size_t)0 ) return NULL;
	p =(unsigned char*)buf + cnt;
	while(p>=buf){
        if(p-1>=buf){
            if(IsDBCSLeadByte( (BYTE)*(p-1) ) ){
                if((unsigned int)(*(p-1)<<8)+*(p) == chr ) return p-1;
            }
        }
		if(*p == chr) return p;
		p--;
	}
	return NULL;
}

int ppp_islower(int a )
{
	if( (a>='a')&&(a<='z') ) return 1;
	return 0;
}

int ppp_isupper(int a )
{
	if( (a>='A')&&(a<='Z') ) return 1;
	return 0;
}

int ppp_isdigit(int a )
{
	if( (a>='0')&&(a<='9') ) return 1;
	return 0;
}

int ppp_isalpha(int a )
{
  if( ppp_islower(a) ) return 1;
  if( ppp_isupper(a) ) return 1;
  return 0;
}

int ppp_isgraph( int a )
{
  if( a >= 0x20 && a < 0x7F ) return 1;
  return 0;
}

void ppp_strupr(char * a )
{
    while( *a!='\0' ){
        if(!IsDBCSLeadByte(*a)){
            if( ppp_islower(*a) ) *a-=0x20;
            a++;
        }else{
            a+=2;
        }
    }
}

char * ppp_strrstr(char * a, char * b )
{
    char * ptr;
    
    if ((ptr=strrchr(a, '.' ))!=NULL){
        if( strcmp( ptr,b)!=0 ){
            ptr = NULL;
        }
    }
    return ptr;
}
int ppp_atoi(const char *s)
{
	int a = 0;
    int sign = 0;

    while(*s == ' ') s++;

    if (*s == '0')
	{
		s++;
		if (*s == 'x' || *s == 'X')
		{
			s++;
			while (*s)
			{
				if (isdigit(*s))
					a = (a<<4) + *s - '0';
				else if (strchr("ABCDEF", *s))
					a = (a<<4) + *s - 'A' + 10;
				else if (strchr("abcdef", *s))
					a = (a<<4) + *s - 'a' + 10;
				else return a;
				s++;
			}
			return a;
		}
/*		while (*s)
		{
			if (strchr("01234567", *s))
				a = (a<<3) + *s - '0';
			else return a;
			s++;
		}
		return a;
*/
    }
	if (*s == '-') sign = 1;
	while (*s)
	{
		if (isdigit(*s))
			a = (a*10) + *s - '0';
		else break;
		s++;
	}
	if(sign) return -a;
	    else return  a;
}
