/******************************************************************************
 * program:     rasimg library                                                *
 * function:    Common file utilities.   				      *
 * modul:       img_futi.c                                                    *
 * licency:     GPL or LGPL                                                   *
 ******************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#include "stringa.h"
#include "img_futi.h"

#if (!defined(__UNIX__) && defined(__GNUC__)) || defined(__BORLANDC__)
 #include <io.h>
#endif


#ifdef FileSize
 #if FileSize==1
  #undef FileSize
 #endif
#endif


#ifndef FileSize
/** Return a size of a file. filelength() is not available in UNIX.
 * @param[in]	f	Opened file. File position is preserved.
 * @return	File size detected or 0. */
long FileSize(FILE *f)
{
#if defined(__UNIX__) || defined(_MSC_VER)
  long pos,len;
  if((pos=ftell(f))<0) return(0);
  fseek(f,0,SEEK_END);
  len=ftell(f);
  fseek(f,pos,SEEK_SET);
  return(len);
#else
  return(filelength(fileno(f)));
#endif
}
#endif


/** This function reads integer value from a file stream.
 * @param[in]	  F	    File stream used for reading numbers.
 * @param[in,out] pch       Character that is already read from the stream.
 *                          When NULL function attempts to do ::ungetc().
 * @param[out]    isvalid   Validity flag, use NULL when not care.*/
long ReadInt(FILE *F, char *pch, bool *isvalid)
{
char ch;
long n;
char sign = 0;

  n=0;
  if(pch) ch=*pch;
     else ch=' ';

  while(isspace(ch)||ch==0)
    {
    ch = fgetc(F);
    if(feof(F))
      {
      if(isvalid) *isvalid=false;
      return 0;
      }
    if(ch=='\n' || ch=='\r')
      {
      if(pch) *pch=ch;
        else ungetc(ch,F);
      if(isvalid) *isvalid=false;
      return 0;
      }
    }

  if(ch=='-') 
    {
    ch = fgetc(F);
    sign = 1;
    }

  if(!isdigit(ch))
    {
    if(pch) *pch=ch;
      else ungetc(ch,F);
    if(isvalid) *isvalid = false;
    return 0;
    }

  while(isdigit(ch))
    {
    n = 10*n+(ch-'0');
    ch = fgetc(F);
    if(feof(F)) goto ExitFunc;
    }

  if(pch) *pch=ch;
    else ungetc(ch,F);

ExitFunc:
  if(isvalid) *isvalid=true;
return(sign?-n:n);
}


/** This function reads double value from a file stream.
 * @param[in]	  F	    File stream used for reading numbers.
 * @param[in,out] pch       Character that is already read from the stream, NULL is tolerated.
 * @return	Value read. */
double ReadDouble(FILE *F, char *pch)
{
  int i;
  char ch, arr[32];

  if(pch!=NULL)
  {
    ch = *pch;
  }
  else
  {
    i = fgetc(F);
    if(i==EOF) return 0;
    ch = i;
  }

  i = 0;
  while(isdigit(ch) || ch=='.' || ch=='e' || ch=='E' || ch=='+' || ch=='-')
  {
    arr[i] = ch;
    i++;

    ch = fgetc(F);
    if(feof(F)) break;
  }

 if(pch) *pch=ch;
     else ungetc(ch,F);

 if(i>0)
 {
   arr[i] = 0;
   return atof(arr);
 } 
 return 0;
}


/** Reads one textual word from file. */
void ReadWord(FILE *F, char *data, int SizeLimit, char *pch)
{
unsigned char ch;
long n;

  if(data==NULL) return;
  n=0;
  if(pch) ch=*pch;
     else ch=' ';

  while(isspace(ch) || ch==0)
     {
     ch=fgetc(F);
     if(feof(F)) goto EndOfFile;
     }

  while(!isspace(ch))
	{
	if(n>=SizeLimit) break;
	data[n]=ch;
	n++;
	ch=fgetc(F);
	if(feof(F)) break;
	}

  if(pch) *pch=ch;
    else ungetc(ch,F);

EndOfFile:
  if(n<SizeLimit) data[n]=0;
return;
}


/** Reads up to end of line. */
void readln(FILE *f, char *pch)
{
char ch;
  if(pch) ch=*pch;
     else ch=' ';
  while(ch!=10 && ch!=13 && !feof(f))
    {
    ch=fgetc(f);
    }
  if(pch) *pch=ch;
}


/**This function reads one line from the text file and store it to the string.
 * @param[in]	MaxStrSize	Maximal extent of string, 0 means no limit.*/
string & fGets2(FILE *f, string & pstr, long MaxStrSize)
{
  char c;

  pstr.erase();
  while(!feof(f))
     {
     c = getc(f);
     if(c == '\n') break;
     if(c == '\r') continue;
     if((unsigned char)c == 0xFF)
	if(feof(f)) break;	//Fix the situation, when 0xFF is read before eof

     pstr += c;
     if(MaxStrSize>0)
        if(--MaxStrSize==0) break;
     }

 return(pstr);
}


unsigned char ReadxByte(FILE *F)
{
char c;
unsigned char B;
  do		// rewind to number beginning
    {
    if(feof(F)) return 0;
    c = toupper(fgetc(F));
    } while(!isxdigit(c));

  if(c>='A')
    B = (c- 'A' + 10) << 4;
  else
    B = (c-'0') << 4;

  c = toupper(fgetc(F));
  c -= '0';
  if(c>=10) c+= -'A'+'0' + 10;
  B |= c;
  return B;
}
