Esempio n. 1
0
/*****************************************************************************
 * ReadSect0() -- Review 12/2002
 *
 * Arthur Taylor / MDL
 *
 * PURPOSE
 *   Looks for the next GRIB message, by looking for the keyword "GRIB".  It
 * expects the message in "expect" bytes from the start, but could find the
 * message in "expect2" bytes or 0 bytes from the start.  Returns -1 if it
 * can't find "GRIB", 1 if "GRIB" is not 0, "expect", or "expect2" bytes from
 * the start.
 *   It stores the bytes it reads (a max of "expect") upto but not including
 * the 'G' in "GRIB" in wmo.
 *
 *   After it finds section 0, it then parses the 16 bytes that make up
 * section 0 so that it can return the length of the entire GRIB message.
 *
 *   When done, it sets fp to point to the end of Sect0.
 *
 *   The reason for this procedure is so that we can read in the size of the
 * grib message, and thus allocate enough memory to read the message in before
 * making it Big endian, and passing it to the library for unpacking.
 *
 * ARGUMENTS
 *       fp = A pointer to an opened file in which to read.
 *            When done, this points to the start of section 1. (Input/Output)
 *     buff = The data between messages. (Input/Output)
 *  buffLen = The length of buff (Output)
 *    limit = How many bytes to read before giving up and stating it is not
 *            a proper message.  (-1 means no limit). (Input)
 *    sect0 = The read in Section 0 (as seen on disk). (Output)
 *  gribLen = Length of this GRIB message. (Output)
 *  version = 1 if GRIB1 message, 2 if GRIB2 message, -1 if TDLP message.
 *            (Output)
 *   expect = The expected number of bytes to find "GRIB" in. (Input)
 *  expect2 = The second possible number of bytes to find "GRIB" in. (Input)
 *      wmo = Assumed allocated to be at least size "expect".
 *            Holds the bytes before the first "GRIB" message.
 *            expect should be > expect2, but is up to caller (Output)
 *   wmoLen = Length of wmo (total number of bytes read - SECT0LEN_WORD * 4).
 *            (Output)
 *
 * FILES/DATABASES:
 *   An already opened "GRIB2" File
 *
 * RETURNS: int (could use errSprintf())
 *  1 = Length of wmo was != 0 and was != expect
 *  0 = OK
 * -1 = Couldn't find "GRIB" part of message.
 * -2 = Ran out of file while reading this section.
 * -3 = Grib version was not 1 or 2.
 * -4 = Most significant sInt4 of GRIB length was not 0
 * -5 = Grib message length was <= 16 (can't be smaller than just sect 0)
 *
 * HISTORY
 *   9/2002 Arthur Taylor (MDL/RSIS): Created.
 *  11/2002 AAT: Combined with ReadWMOHeader
 *  12/2002 (TK,AC,TB,&MS): Code Review.
 *   1/2003 AAT: Bug found. wmo access out of bounds of expect when setting
 *          the /0 element, if wmoLen > expect.
 *   4/2003 AAT: Added ability to handle GRIB version 1.
 *   5/2003 AAT: Added limit option.
 *   8/2003 AAT: Removed dependence on offset, and fileLen.
 *  10/2004 AAT: Modified to allow for TDLP files
 *
 * NOTES
 * 1a) 1196575042L == ASCII representation of "GRIB" (GRIB in MSB)
 * 1b) 1112101447L == ASCII representation of "BIRG" (GRIB in LSB)
 * 1c) 1413762128L == ASCII representation of "TDLP" (TDLP in MSB)
 * 1d) 1347175508L == ASCII representation of "PLDT" (TDLP in LSB)
 * 2) Takes advantage of the wordType to check that the edition is correct.
 * 3) May want to return prodType.
 * 4) WMO_HEADER_ORIG_LEN was added for backward compatibility... should be
 *    removed when we no longer use old format. (say in a year from 11/2002)
 *
 *****************************************************************************
 */
int ReadSECT0 (DataSource &fp, char **buff, uInt4 *buffLen, sInt4 limit,
               sInt4 sect0[SECT0LEN_WORD], uInt4 *gribLen, int *version)
{
   typedef union {
      sInt4 li;
      unsigned char buffer[4];
   } wordType;

   uChar gribMatch = 0; /* Counts how many letters in GRIB we've matched. */
   uChar tdlpMatch = 0; /* Counts how many letters in TDLP we've matched. */
   wordType word;       /* Used to check that the edition is correct. */
   uInt4 curLen;        /* Where we currently are in buff. */
   uInt4 i;             /* Used to loop over the first few char's */
   uInt4 stillNeed;     /* Number of bytes still needed to get 1st 8 bytes of 
                         * message into memory. */

   /* Get first 8 bytes.  If GRIB we don't care.  If TDLP, this is the length 
    * of record.  Read at least 1 record (length + 2 * 8) + 8 (next record
    * length) + 8 bytes before giving up. */
   curLen = 8;
   if (*buffLen < curLen) {
      *buffLen = curLen;
      *buff = (char *) realloc ((void *) *buff, *buffLen * sizeof (char));
   }
   if (fp.DataSourceFread(*buff, sizeof (char), curLen) != curLen) {
      errSprintf ("ERROR: Couldn't find 'GRIB' or 'TDLP'\n");
      return -1;
   }
/*
   Can't do the following because we don't know if the file is a GRIB file or
   not, or if it was a FORTRAN file.
   if (limit > 0) {
      MEMCPY_BIG (&recLen, *buff, 4);
      limit = (limit > recLen + 32) ? limit : recLen + 32;
   }
*/
   while ((tdlpMatch != 4) && (gribMatch != 4)) {
      for (i = curLen - 8; i + 3 < curLen; i++) {
         if ((*buff)[i] == 'G') {
            if (((*buff)[i + 1] == 'R') && ((*buff)[i + 2] == 'I') &&
                ((*buff)[i + 3] == 'B')) {
               gribMatch = 4;
               break;
            }
         } else if ((*buff)[i] == 'T') {
            if (((*buff)[i + 1] == 'D') && ((*buff)[i + 2] == 'L') &&
                ((*buff)[i + 3] == 'P')) {
               tdlpMatch = 4;
               break;
            }
         }
      }
      stillNeed = i - (curLen - 8);
      /* Read enough of message to have the first 8 bytes (including ID). */
      if (stillNeed != 0) {
         curLen += stillNeed;
         if ((limit >= 0) && (curLen > (size_t) limit)) {
            errSprintf ("ERROR: Couldn't find type in %ld bytes\n", limit);
            return -1;
         }
         if (*buffLen < curLen) {
            *buffLen = curLen;
            *buff = (char *) realloc ((void *) *buff,
                                      *buffLen * sizeof (char));
         }
         if (fp.DataSourceFread((*buff) + (curLen - stillNeed), sizeof (char), stillNeed) != stillNeed) {
            errSprintf ("ERROR: Ran out of file reading SECT0\n");
            return -1;
         }
      }
   }

   /* curLen and (*buff) hold 8 bytes of section 0. */
   curLen -= 8;
   memcpy (&(sect0[0]), (*buff) + curLen, 4);
#ifdef DEBUG
#ifdef LITTLE_ENDIAN
   myAssert ((sect0[0] == 1112101447L) || (sect0[0] == 1347175508L));
#else
   myAssert ((sect0[0] == 1196575042L) || (sect0[0] == 1413762128L));
#endif
#endif
   memcpy (&(sect0[1]), *buff + curLen + 4, 4);
   /* Make sure we don't pass back part of "GRIB" in the buffer. */
   (*buff)[curLen] = '\0';
   *buffLen = curLen;

   word.li = sect0[1];
   if (tdlpMatch == 4) {
      if (word.buffer[3] != 0) {
         errSprintf ("ERROR: unexpected version of TDLP in SECT0\n");
         return -2;
      }
      *version = -1;
      /* Find out the GRIB Message Length */
      *gribLen = GRIB_UNSIGN_INT3 (word.buffer[0], word.buffer[1],
                                   word.buffer[2]);
      /* Min message size: GRIB1=52, TDLP=59, GRIB2=86. */
      if (*gribLen < 59) {
         errSprintf ("TDLP length %ld was < 59?\n", *gribLen);
         return -5;
      }
   } else if (word.buffer[3] == 1) {
      *version = 1;
      /* Find out the GRIB Message Length */
      *gribLen = GRIB_UNSIGN_INT3 (word.buffer[0], word.buffer[1],
                                   word.buffer[2]);
      /* Min message size: GRIB1=52, TDLP=59, GRIB2=86. */
      if (*gribLen < 52) {
         errSprintf ("GRIB1 length %ld was < 52?\n", *gribLen);
         return -5;
      }
   } else if (word.buffer[3] == 2) {
      *version = 2;
      /* Make sure we still have enough file for the rest of section 0. */
      if (fp.DataSourceFread(sect0 + 2, sizeof (sInt4), 2) != 2) {
         errSprintf ("ERROR: Ran out of file reading SECT0\n");
         return -2;
      }
      if (sect0[2] != 0) {
         errSprintf ("Most significant sInt4 of GRIB length was not 0?\n");
         errSprintf ("This is either an error, or we have a single GRIB "
                     "message which is larger than 2^31 = 2,147,283,648 "
                     "bytes.\n");
         return -4;
      }
#ifdef LITTLE_ENDIAN
      revmemcpy (gribLen, &(sect0[3]), sizeof (sInt4));
#else
      *gribLen = sect0[3];
#endif
   } else {
      errSprintf ("ERROR: Not TDLPack, and Grib edition is not 1 or 2\n");
      return -3;
   }
   return 0;
}
Esempio n. 2
0
/*****************************************************************************
 * AllocSprintf() -- Arthur Taylor / MDL (Review 12/2002)
 *
 * PURPOSE
 *   Based on minprintf (see K&R C book (2nd edition) page 156.  This code
 * tries to provide some of the functionality of sprintf, while at the same
 * time it handles the memory allocation.
 *   In addition, it provides a %S option, which allows one to pass in an
 * array of strings, and get back a comma delimited string.
 *
 * ARGUMENTS
 *     Ptr = An array of data that is of size LenBuff. (Input/Output)
 * LenBuff = The allocated length of Ptr. (Input/Output)
 *     fmt = Format similar to the one used by sprintf to define how to
 *           print the message (Input)
 *      ap = argument list initialized by a call to va_start.  Contains the
 *           data needed by fmt. (Input)
 *
 * RETURNS: void
 *
 *  9/2002 Arthur Taylor (MDL/RSIS): Created.
 * 12/2002 (RY,FC,MA,&TB): Code Review.
 * 12/2002 AAT: Fixed the mallocSprintf ("") error.
 *  2/2003 AAT: increased bufpart[80] to bufpart[330] because the largest
 *         64 bit double is: +1.7E+308, and I want 20 "slots" for stuff
 *         after the decimal place. There is the possibility of "Long
 *         doubles" (80 bits) which would have a max of: +3.4E+4932, but
 *         that is excessive for now.
 *  2/2004 AAT: if lenBuff != 0, switch from ipos-- to strlen (buffer);
 *  3/2004 AAT: Added %c option.
 * 11/2005 AAT: Added %e option.
 *  1/2006 AAT: Found a bug with multiple errSprintf.  Doesn't seem to be
 *              able to handle lenBuff > strlen(buffer) when procedure is
 *              first called.  Something like format = "aaa%s", lenBuff = 3,
 *              buff = 'n' would result in 'naaa__<string>', instead of
 *              'naaa<string>'.  Simple solution set lenBuff = strlen (buff).
 *              better solution: Maybe calculate correct place for ipos
 *              before switch.
 *
 * NOTES
 * Supported formats:
 *  %0.4f => float, double
 *  %03d %ld %10ld => int, sInt4.
 *  %s => Null terminated char string. (no range specification)
 *  %S => take a char ** and turn it into a comma delimited string.
 *
 * Assumes that no individual float or int will be more than 80 characters
 * Assumes that no % option is more than 20 char.
 *****************************************************************************
 */
static void AllocSprintf (char **Ptr, size_t *LenBuff, const char *fmt,
                          va_list ap)
{
   char *buffer = *Ptr; /* Local copy of Ptr. */
   size_t lenBuff = *LenBuff; /* Local copy of LenBuff. */
   const char *p;       /* Points to % char in % option. */
   const char *p1;      /* Points to end of % option. */
   char bufpart[330];   /* Used for formating the int / float options. */
   char format[20];     /* Used to store the % option. */
   char *sval;          /* For pulling strings off va_list. */
   char **Sval;         /* For pulling lists of strings off va_list. */
   size_t slen;         /* Length of used part of temp. */
   char f_inLoop;       /* Flag to state whether we got into %S , loop. */
   char flag;           /* If they have a l,L,h in string. */
   /* size_t ipos = *LenBuff; *//* The current index to start storing data. */
   size_t ipos;         /* The current index to start storing data. */
   int c_type;          /* Used when handling %c option. */

   myAssert (sizeof (char) == 1);

   if ((fmt == NULL) || (strlen (fmt) == 0)) {
      return;
   }
   p = fmt;
   /* If lenBuff = 0, then make room for the '\0' character. */
   if (lenBuff == 0) {
      lenBuff++;
      buffer = (char *) realloc ((void *) buffer, lenBuff);
      /* Added following 1 line on 1/2006 */
      ipos = 0;
   } else {
      /* Added following 3 lines on 1/2006 */
      myAssert (lenBuff >= strlen (buffer) + 1);
      lenBuff = strlen (buffer) + 1;
      ipos = lenBuff - 1;
/*     ipos = strlen (buffer); */
   }
   while (p < fmt + strlen (fmt)) {
      p1 = p;
      p = strchr (p1, '%');
      /* Handle simple case when no more % in format string. */
      if (p == NULL) {
         /* No more format strings; copy rest of format and return */
         lenBuff += strlen (p1);
         buffer = (char *) realloc ((void *) buffer, lenBuff);
         strcpy (buffer + ipos, p1);
         goto done;
      }
      /* Handle data up to the current % in format string. */
      lenBuff += p - p1;
      buffer = (char *) realloc ((void *) buffer, lenBuff);
      strncpy (buffer + ipos, p1, p - p1);
      ipos = lenBuff - 1;
      /* Start dealing with % of format. */
      p1 = p + strspn (p + 1, "0123456789.");
      p1++;
      /* p1 points to first letter after %. */
      switch (*p1) {
         case 'h':
         case 'l':
         case 'L':
            flag = *p1;
            p1++;
            break;
         case '\0':
            /* Handle improper use of '%' for example: '%##' */
            lenBuff += p1 - p - 1;
            buffer = (char *) realloc ((void *) buffer, lenBuff);
            strncpy (buffer + ipos, p + 1, p1 - p - 1);
            goto done;
         default:
            flag = ' ';
      }
      if ((p1 - p + 1) > (int) (sizeof (format)) - 1) {
         /* Protect against overflow of format string. */
         lenBuff += p1 - p + 1;
         buffer = (char *) realloc ((void *) buffer, lenBuff);
         strncpy (buffer + ipos, p, p1 - p + 1);
         ipos = lenBuff - 1;
      } else {
         strncpy (format, p, p1 - p + 1);
         format[p1 - p + 1] = '\0';
         switch (*p1) {
            case 'd':
               switch (flag) {
                  case 'l':
                  case 'L':
                     sprintf (bufpart, format, va_arg (ap, sInt4));
                     break;
                     /* 
                      * gcc warning for 'h': "..." promotes short int to
                      * int.  Could get rid of 'h' option but decided to
                      * leave it in since we might have a different
                      * compiler.
                      */
/*
              case 'h':
                sprintf (bufpart, format, va_arg(ap, short int));
                break;
*/
                  default:
                     sprintf (bufpart, format, va_arg (ap, int));
               }
               slen = strlen (bufpart);
               lenBuff += slen;
               buffer = (char *) realloc ((void *) buffer, lenBuff);
               strncpy (buffer + ipos, bufpart, slen);
               ipos = lenBuff - 1;
               break;
            case 'f':
               sprintf (bufpart, format, va_arg (ap, double));
               slen = strlen (bufpart);
               lenBuff += slen;
               buffer = (char *) realloc ((void *) buffer, lenBuff);
               strncpy (buffer + ipos, bufpart, slen);
               ipos = lenBuff - 1;
               break;
            case 'e':
               sprintf (bufpart, format, va_arg (ap, double));
               slen = strlen (bufpart);
               lenBuff += slen;
               buffer = (char *) realloc ((void *) buffer, lenBuff);
               strncpy (buffer + ipos, bufpart, slen);
               ipos = lenBuff - 1;
               break;
            case 'g':
               sprintf (bufpart, format, va_arg (ap, double));
               slen = strlen (bufpart);
               lenBuff += slen;
               buffer = (char *) realloc ((void *) buffer, lenBuff);
               strncpy (buffer + ipos, bufpart, slen);
               ipos = lenBuff - 1;
               break;
            case 'c':
               c_type = va_arg (ap, int);
               lenBuff += 1;
               buffer = (char *) realloc ((void *) buffer, lenBuff);
               buffer[ipos] = (char) c_type;
               buffer[ipos + 1] = '\0';
               ipos = lenBuff - 1;
               break;
            case 's':
               if ((p1 - p) == 1) {
                  sval = va_arg (ap, char *);
/*    printf (":: sval :: '%s'\n", sval);*/
                  slen = strlen (sval);
                  lenBuff += slen;
                  buffer = (char *) realloc ((void *) buffer, lenBuff);
                  strncpy (buffer + ipos, sval, slen);
                  ipos = lenBuff - 1;
                  break;
               }
               /* Intentionally fall through. */
            case 'S':
               if ((p1 - p) == 1) {
                  f_inLoop = 0;
                  for (Sval = va_arg (ap, char **); *Sval; Sval++) {
                     slen = strlen (*Sval);
                     lenBuff += slen + 1;
                     buffer = (char *) realloc ((void *) buffer, lenBuff);
                     strcpy (buffer + ipos, *Sval);
                     strcat (buffer + ipos + slen, ",");
                     ipos = lenBuff - 1;
                     f_inLoop = 1;
                  }
                  if (f_inLoop) {
                     lenBuff--;
                     buffer[lenBuff] = '\0';
                     ipos = lenBuff - 1;
                  }
                  break;
               }
               /* Intentionally fall through. */
            default:
               lenBuff += p1 - p;
               buffer = (char *) realloc ((void *) buffer, lenBuff);
               strncpy (buffer + ipos, p + 1, p1 - p);
               ipos = lenBuff - 1;
         }
      }
//Testing mine
int main() {
	
	int i, j, r, passes, choice1, choice2;
	int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, 
	       sea_hag, tribute, smithy};
	int supply[16] = {0,1,2,3,4,5,6,7,10,11,13,14,17,19,21,22};
	
	struct gameState G;
	r = initializeGame(2, k, 2, &G);
		assert(r == 0);
	
	//Try upgrading to every card
	for (i = 1; i < 4; i++) {
		for (j = 0; j < 16; j++) {
			r = initializeGame(2, k, 2, &G);
			assert(r == 0);
			
			G.hand[0][0] = mine;
			G.hand[0][1] = copper;
			G.hand[0][2] = silver;
			G.hand[0][3] = gold;
			G.hand[0][4] = smithy;
			G.handCount[0] = 5;
			G.numActions = 1;
			choice1 = i;
			choice2 = supply[j];
			
			//Only allow to upgrade the treasure card
			r = playCard(0, choice1, choice2, 0, &G);
			
			passes = 1;
			if (choice1 == copper &&
				(choice2 != copper || choice2 != silver) &&
				r == 0) {
				printf("Illegal move %d: traded in %d for %d. -- ", r, choice1, supply[j]);
				printf("Cost of copper is %d, and cost of %d is %d\n", getCost(copper), i, getCost(i));
				passes = 0;
			}
			if (choice1 == silver &&
				(choice2 != silver || choice2 != gold) &&
				r == 0) {
				printf("Illegal move %d: traded in %d for %d. -- ", r, choice1, supply[j]);
				printf("Cost of copper is %d, and cost of %d is %d\n", getCost(silver), i, getCost(G.hand[0][i]));
				passes = 0;
			}
			if (choice1 == silver &&
				(choice2 != silver || choice2 != gold) &&
				r == 0) {
				printf("Illegal move %d: traded in %d for %d. -- ", r, choice1, supply[j]);
				printf("Cost of copper is %d, and cost of %d is %d\n", getCost(silver), i, getCost(G.hand[0][i]));
				passes = 0;
			}
			if (choice1 == gold &&
				choice2 != gold &&
				r == 0) {
				printf("Illegal move %d: traded in %d for %d. -- ", r, choice1, supply[j]);
				printf("Cost of copper is %d, and cost of %d is %d\n", getCost(silver), i, getCost(G.hand[0][i]));
				passes = 0;
			}
		}
	}
	
	myAssert(passes);
	
	return 0;
}