#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "base_fnx.h"


//common base functions source code

//*****************************************************************
//*****************************************************************
int   fget_line(FILE *fp_in, char *line, int n) //****************
{ // get line from input file
  // and drops the LF at the end ('0x0a')
  // returns #bytes read in
  // returns -1 if no line (=EOF)

	line[0]=0; // set to NULL length
	fgets(line,n,fp_in); // reads up to a Newline = '\n' = LF = 0x0a
	n = strlen(line);  // n=#actual char read in
	if ( n<1) return(-1);  // did not read in any line
	
	n--; // point to the last char

	//while ( (line[n]=='\r') || (line[n]=='\n') && (n>-1) ) 
	while ( ( (line[n]<' ') || (line[n]>'~') ) && (n>-1) ) 
	{ // 0x0a = \n = Newline = LF, 0x0d = \r = CR
		line[n--] = 0; // set =NULL & decrement #bytes
		// printf("%d ",n);
	}
    n = strlen(line);
    // printf(">%d\n",n);
	return(n);
} //*** end fget_line *********************************************

int   YesNo(void) // returns TRUE if Y or y is given *******************
{ // scanf() requires Y or N followed by CR.
  // The function then clears CR from the stack
  char ch = 'q';
  int   yes;

  // read in a character until we get a legal value
  while ( ( ch != 'N') && (ch != 'Y') )
  {  printf("(Y/N) ");
     ch = getchar();
     while ( ch == '\n' ) ch = getchar(); // flush old CR's
     // scanf("%c",&ch);
     ch = toupper(ch); // convert to upper case
  }
  yes = (ch=='Y');
  ch = getchar(); // this clears out the remaining CR from the stack
  return(yes);
} // end YesNo ********************************************************

char ch_l2u ( char ch ) //*****************************************************
{ // convert lower case to upper
  
  if ( ch>='a' && ch<='z' )
       ch -= 32; // convert to upper
       
  return(ch);
} //***************************************************************************

int   get_substr( char *str, char *out, int   imax) //*************************
{ // read in from the str, passing up blank spaces,
  // and return the first sub-str to out[]
  // returns # of char read from str,
  // so subsequent calls can parse the line
  // returns 0 if NO substring was found
  
  int   i=0, k=0, n, valid;
  
  n = strlen(str);
  out[0] = 0; // set to NULL str
  
  do //================================================================
  {  // look for a valid char
     valid = ( str[i]>' ' ) && ( str[i] < 127 );
     if (!valid) i++; // if no good, look for the next
  }  while ( i<n && !valid ); //=======================================
  
 if (!valid) return( 0 ); // nothing to parse!
  
  while ( valid && i<n && k<imax) //===================================
  {  // then found a valid char, keep reading
     out[k++] = str[i++]; 
     if (i<n) valid = ( str[i]>' ' ) && ( str[i] < 127 );
  } //=================================================================
  // i=next blank char into str
  out[k] = 0; // append the NULL char

  return( i );
} //***************************************************************************

int   read_ints( char *str, int imax, int *x ) //******************************
{ // read up to imax values and store into x
  // returns # of values actually read
  
  int   i=0;  // number actually read in
  int   k=0, n;
  char  s[40]; // sub-string of answer
  

  do //======================================================
  { // read in until not valid
    n = get_substr( &str[k], s, 40);  //read in a substring
    //cprintf("%d  %s___%s\n",n, &str[k], s );
    
    if (n>0) //----------------------------------------
    { // then we did read in a substr
      k += n; // next entry into str to start searching
      n = strlen(s); // substr length
      if (n>0) // verifies it is a valid substr
      { //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
         n = sscanf(s,"%d",&x[i]); // read in the value
         // cprintf("__%d %s %d\n",i,s,x[i] );
         if (n==1) i++; //yes, read in OK
      } //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
    } //-----------------------------------------------
    // n=0 if no string, or illegal number
    
  }  while (n>0 && i<imax ); //==============================
  
  return( i );
} //***************************************************************************


int   read_floats( char *str, int imax, float *x ) //**************************
{ // read up to imax values and store into x
  // returns # of values actually read
  
  int   i=0;  // number actually read in
  int   k=0, n;
  char  s[40]; // sub-string of answer
  float y;
  

  do //======================================================
  { // read in until not valid
    n = get_substr( &str[k], s, 40);  //read in a substring
    //cprintf("%d  %s___%s\n",n, &str[k], s );
    
    if (n>0) //----------------------------------------
    { // then we did read in a substr
      k += n; // next entry into str to start searching
      n = strlen(s); // substr length
      if (n>0) // verifies it is a valid substr
      { //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
         n = sscanf(s,"%f",&y ); // read in the value
         
         if (n==1) 
         {
           x[i] = y;
           //printf("__%d %s %f\n",i,s,x[i] );
           i++; //yes, read in OK
         }
         else
         { printf("Bad float read: %d %s\n",i, s); }
      } //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
    } //-----------------------------------------------
    // n=0 if no string, or illegal number
    
  }  while (n>0 && i<imax ); //==============================
  
  return( i );
} //***************************************************************************

int   read_floats_dbg( char *str, int imax, float *x ) //**********************
{ // read up to imax values and store into x
  // returns # of values actually read
  
  int   i=0;  // number actually read in
  int   k=0, n;
  char  s[40]; // sub-string of answer
  float y; //tmp
  

  do //======================================================
  { // read in until not valid
    n = get_substr( &str[k], s, 40);  //read in a substring
    //printf("%d  %s___%s\n",n, &str[k], s );
    
    if (n>0) //----------------------------------------
    { // then we did read in a substr
      k += n; // next entry into str to start searching
      n = strlen(s); // substr length
      if (n>0) // verifies it is a valid substr
      { //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
         n = sscanf(s,"%f",&y ); // read in the value
         
         if (n==1) 
         {
           x[i] = y;
           printf("__%d %s %f\n",i,s,x[i] );
           i++; //yes, read in OK
         }
         else
         { printf("Bad float read: %d %s\n",i, s); }
      } //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
    } //-----------------------------------------------
    // n=0 if no string, or illegal number
    
  }  while (n>0 && i<imax ); //==============================
  
  return( i );
} //***************************************************************************


void chomp_end( char line[] ) //**************************************
{ // remove non-char values at the end-of-line
  int n, nogood;
  char ch;
  
  n = strlen(line);
  n--; // point to the last char
  if (n<1) { line[0]=0; return; }
  do { // do the following until no-good
    ch = line[n];
    nogood = ( ch<'!' || ch>'}'  ); // then not valid
    if (nogood) 
    { line[n] = 0; // set to null
      n--; // decrement pointer
    }
  } while ( n>0 && nogood );
  return;
} // end chomp_end ***************************************************

// *********************************************************************
void blankfill( char in[], int nout )
{ // fill the rest of in[] with blanks to nout
  int i,n;
  
  n=strlen(in);
  // for (i=0;i<n;i++)      out[i] = in[i];  // copy over
  for (i=n;i<nout;i++)   in[i] = ' '; // fill with blanks
  in[nout] = 0;  // end with NULL
  
  return;
} // end blankfill *****************************************************

// *********************************************************************
void charfill( char in[], int nout, char f )
{ // fill the rest of in[] with the char f to nout
  int i,n;
  
  n=strlen(in);
  for (i=n;i<nout;i++)   in[i] = f; // fill with f
  in[nout] = 0;  // end with NULL
  
  return;
} // end charfill *****************************************************


//*******************************************************************
//*******************************************************************
//*******************************************************************
int yearday(int dd, char mo[], int yr) //****************************
{   // return the julian year-day for dd, mo, yr
    int  mday[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    char  *ms[12] = { "Jan","Feb","Mar","Apr","May","Jun",
                       "Jul","Aug","Sep","Oct","Nov","Dec" };
    int i=0, match, day, n;
    
    do { // do until a month match ------------------------------
       match = strncmp(mo, ms[i],3);
       if (match != 0) i++; // look for next one
    } while ( match!=0 && i<12 ); //-----------------------------
    
    if ( match !=0 ) return(0); // no match!
    
    n=i; //=index of month
    for (day=0, i=0; i<n; i++)  day += mday[i]; // accum #days
    day += dd + checkleap(n,yr); // add on day-of-month + leap-year
    
    return(day);
} //******************************************************************
    
int checkleap(int m, int yr) // **************************************
{   //returns 1 if iyr is a leap year, and month>1
    if ( m<2)       return 0; // January or Feb, don't add 1
    if ( yr%4 != 0) return 0;
    
    if ( ( yr%100 != 0) || ( yr%400 == 0 ) )
       return 1;
    else
       return 0;
}  //end *************************************************************


//GPS week # functions ***********************************************
//********************************************************************
int gps_wkday_2_yd( int wk, int dd, int *year, int *yd )
{ // wk = week number:
  //    wk= 1, day=0 = 06 Jan 1980 (Sunday).
  //    wk= 0, day=0 = 22 Aug 1999 (Sunday), Rollover from wk=1023.
  // dd = week-day: 0=Sunday...6=Saturday
  // year = Year (returned value).
  // yd = Julian year-day: Jan1 = 1 (to be consistent w/above).
  // RETURNS:
  // 0 = no error.
  
  int nd; // #-of-days
  int yr;  // guess of year (starts at wk=0)
  int nday; // #of days in yr
  int stat=0;  
  
  if ( wk<0 || wk>2048 ) // bad week # -------------------
  { //printf("Bad GPS week # = %d\n",wk);
    return(1);
  } //----------------------------------------------------
  
  if ( dd<0 || dd>1023 ) // bad weekday ------------------
  { //printf("Bad GPS week Day = %d\n",dd);
    return(1);
  } //----------------------------------------------------
  
  nd = wk*7 + dd; // #of days since 22 Aug 1999..
  if ( wk<990   ) //----------------------------------
  { // we're in the 1999-2018 rollover period
    nd +=234; // 234 = yd for 22 Aug 1999.
    yr = 1999; // 1st guess at the year
    nday = 365; // # of days in 1999
    if ( checkleap(12,yr) ) nday++;
  } else //------------------------------------------
  { // we're at the tail-end of pre-1999
    // OR wk has rolled-over, and it's counting from 1980
    nd += 6; // 06 Jan 1980
    yr = 1980;
    nday = 365;
    if ( checkleap(12,yr) ) nday++;
  } // end if..else ---------------------------------
  
  
  while (nd > nday) //------------------------------------
  { // past the present yr
    nd = nd - nday; // remove #of days of the last year
    yr++; // increment the year
    nday = 365;
    if (checkleap(12,yr) ) nday++; // an extra day
    // nday=# of days in the present year
  } //----------------------------------------------------
  
  // nd should now by the julian day
  *yd = nd;
  // and yr is the present year
  *year = yr;
  
  // printf("%4d %3d\n",yr, nd);
  return(0); // 0 = no error
} //******************************************************************

//**** end ********************************************************************
//*****************************************************************************

