Example #1
0
END_TEST


/**
 * The nature of vsnprintf makes it difficult to unit test using the
 * 'check' framework.  For now, since c_local_snprintf is written in terms
 * of c_locale_vsnprintf, if the "sn" test succeeds, we assume "vsn" is
 * correct.
 *
START_TEST (test_c_locale_vsnprintf)
{
}
END_TEST
*/


START_TEST (test_c_locale_strtod)
{
  const char *en = "2.72";
  char* lc;
  char *endptr;

  lc = setlocale(LC_ALL, "de_DE");

  /**
   * These tests will fail under some platforms because of a minimal 
   * setlocale() implementation (e.g. Cygwin (see setlocale manpage)) 
   * or limited number of default locales (e.g. Ubuntu based).
   * Thus these tests will be skipped when setlocale() returns
   * NULL.
   */
  if ( lc != NULL )
  {
    const char *de = "2,72";

    endptr = NULL;
    fail_unless( util_isEqual(strtod(de, &endptr), 2.72) );
    fail_unless( (endptr - de)       == 4    );
    fail_unless( errno != ERANGE             );
  }

  endptr = NULL;
  fail_unless( util_isEqual(c_locale_strtod(en, &endptr),2.72) );
  fail_unless( (endptr - en)                == 4    );
  fail_unless( errno != ERANGE                      );

  setlocale(LC_ALL, "C");
}
Example #2
0
/**
 * Reads either a TT_INTEGER or a TT_REAL from the FormulaTokenizer into
 * the given Token.  This is a supporting function for
 * FormulaTokenizer_nextToken().
 *
 * This function assumes the character ft->formula[ft->pos] is either a
 * period or a digit.  FormulaTokenizer_nextToken() ensures this
 * precondition before calling this function.
 *
 * Sign characters preceding the number are not recognized, but sign
 * characters in the exponent are recognized.
 *
 * A subtle error case:
 *
 * If the string starting with ft->formula[ft->pos] is some combination of
 * a '.', 'e|E' or '+|-' with no intervening digits, the token will be
 * marked as TT_UNKNOWN and t->value.ch set to ft->formula[ft->pos]
 * (a '.').
 */
void
FormulaTokenizer_getNumber (FormulaTokenizer_t *ft, Token_t *t)
{
  char c;
  char endchar;
  char *endptr;

  unsigned int start, stop, len;

  unsigned int exppos = 0;
  unsigned int endpos = 0;

  unsigned int seendot = 0;
  unsigned int seenexp = 0;
  unsigned int seensgn = 0;


  start = ft->pos;
  c     = ft->formula[ start ];

  /**
   * ([0-9]+\.?[0-9]*|\.[0-9]+)([eE][-+]?[0-9]+)?
   */
  while (1)
  {
    if (c == '.' && seendot == 0)
    {
      seendot = 1;
    }
    else if ((c == 'e' || c == 'E') && seenexp == 0)
    {
      seenexp = 1;
      exppos  = ft->pos;
    }
    else if ((c == '+' || c == '-') && seenexp == 1 && seensgn == 0)
    {
      seensgn = 1;
    }
    else if (c < '0' || c > '9')
    {
      endchar = c;
      endpos  = ft->pos;
      break;
    }

    c = ft->formula[ ++ft->pos ];
  }

  /**
   * Temporarily terminate ft->formula will a NULL at the character just
   * beyond the end of the number.  This prevents strtod() and strtol()
   * (below) from reading past the end of the number.
   *
   * This prevents at least one obscure bug where something like '3e 4' is
   * understood as one token 3e4 instead of two: 3e0 and 4.
   */
  ft->formula[ endpos ] = '\0';

  stop = ft->pos;
  len  = stop - start;

  /**
   * If the token is composed only of some combination of '.', 'e|E' or
   * '+|-' mark it as TT_UNKNOWN.  Otherwise, strtod() or strtol() should
   * be able to convert it, as all the syntax checking was performed above.
   */
  if (len == (seendot + seenexp + seensgn))
  {
    t->type     = TT_UNKNOWN;
    t->value.ch = ft->formula[start];
  }
  else if (seendot || seenexp)
  {
    /**
     * Temporarily "hide" the exponent part, so strtod below will convert
     * only the mantissa part.
     */
    if (seenexp)
    {
      c                     = ft->formula[ exppos ];
      ft->formula[ exppos ] = '\0';
    }

    t->type       = TT_REAL;
    t->value.real = c_locale_strtod(ft->formula + start, &endptr);

    /**
     * Convert the exponent part and "unhide" it.
     */
    if (seenexp)
    {
      t->type     = TT_REAL_E;
      t->exponent = strtol(ft->formula + exppos + 1, &endptr, 10);

      ft->formula[ exppos ] = c;
    }
  }
  else
  {
    t->type          = TT_INTEGER;
    t->value.integer = strtol(ft->formula + start, &endptr, 10);
  }

  /**
   * Restore the character overwritten above.
   */
  ft->formula[ endpos ] = endchar;
}