blob: 10d66bb8aeba2baefa7fb30a834420be514786ab [file] [edit]
/*
* Copyright © 2019-2026 Ebrahim Byagowi
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
*/
#include <cmath>
#include <cstdlib>
#include "hb.hh"
#include "hb-number.hh"
static void
test_parse_int ()
{
{
const char str[] = "123";
const char *pp = str;
const char *end = str + 3;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp - str == 3);
hb_always_assert (end - pp == 0);
hb_always_assert (!*end);
}
{
const char str[] = "-123";
const char *pp = str;
const char *end = str + 4;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == -123);
hb_always_assert (pp - str == 4);
hb_always_assert (end - pp == 0);
hb_always_assert (!*end);
}
/* Leading whitespace */
{
const char str[] = " 123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp == end);
}
{
const char str[] = "\t123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp == end);
}
{
const char str[] = "\n123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp == end);
}
{
const char str[] = " -123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == -123);
hb_always_assert (pp == end);
}
/* Leading '+' sign */
{
const char str[] = "+123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp == end);
}
{
const char str[] = "+0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 0);
hb_always_assert (pp == end);
}
/* Leading zeros are decimal, not octal (base is passed as 10) */
{
const char str[] = "007";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 7);
hb_always_assert (pp == end);
}
/* Negative zero */
{
const char str[] = "-0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 0);
hb_always_assert (pp == end);
}
/* Partial parse: stops at first non-digit */
{
const char str[] = "123abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp == str + 3);
}
/* INT_MAX / INT_MIN (fits in long on every supported platform) */
{
const char str[] = "2147483647";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 2147483647);
hb_always_assert (pp == end);
}
{
const char str[] = "-2147483648";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == -2147483647 - 1);
hb_always_assert (pp == end);
}
/* Failures: no digits */
{
const char str[] = " ";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
{
const char str[] = "+";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
}
{
const char str[] = "-";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
}
{
const char str[] = "abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
}
/* Multiple signs fail */
{
const char str[] = "++1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
}
{
const char str[] = "--1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
}
{
const char str[] = "+-1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
}
{
const char str[] = "-+1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
}
/* whole_buffer: leading whitespace ok, trailing content rejected,
* and *pp / *pv are left untouched on failure */
{
const char str[] = " 123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv, true));
hb_always_assert (pv == 123);
hb_always_assert (pp == end);
}
{
const char str[] = "123abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv, true));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
{
/* 10 digits > INT_MAX. The old strtol-based implementation silently
* truncated on 64-bit platforms (long is 64-bit) but rejected on
* 32-bit; the new implementation rejects uniformly. */
const char str[] = "9999999999"; /* 10 digits, > INT_MAX */
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* INT_MAX / INT_MIN - exactly representable */
{
const char str[] = "2147483647";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 2147483647);
hb_always_assert (pp == end);
}
{
const char str[] = "-2147483648";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == -2147483647 - 1); /* not -2147483648, that's UB as an int literal */
hb_always_assert (pp == end);
}
/* One past INT_MAX - must fail */
{
const char str[] = "2147483648";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* One past INT_MIN - must fail */
{
const char str[] = "-2147483649";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* Same for signed */
{
const char str[] = "9999999999999999999999999999999999999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
{
/* Verify *pv and *pp are untouched when a range check rejects. */
const char str[] = "9999999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 42;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 42);
}
/* Whitespace between sign and digits is not allowed */
{
const char str[] = "- 123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* Plus zero, for symmetry with the -0 case */
{
const char str[] = "+0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 0);
hb_always_assert (pp == end);
}
/* Sign alone plus trailing whitespace still fails */
{
const char str[] = "- ";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
int pv = 99;
hb_always_assert (!hb_parse_int (&pp, end, &pv));
hb_always_assert (pv == 99);
}
}
static void
test_parse_uint ()
{
{
const char str[] = "123";
const char *pp = str;
const char *end = str + strlen (str);
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp - str == 3);
hb_always_assert (end - pp == 0);
hb_always_assert (!*end);
}
{
const char str[] = "12F";
const char *pp = str;
const char *end = str + 3;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 0x12F);
hb_always_assert (pp - str == 3);
hb_always_assert (end - pp == 0);
hb_always_assert (!*end);
}
{
const char str[] = "12Fq";
const char *pp = str;
const char *end = str + 4;
unsigned int pv;
hb_always_assert (!hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (hb_parse_uint (&pp, end, &pv, false, 16));
hb_always_assert (pv == 0x12F);
hb_always_assert (pp - str == 3);
hb_always_assert (end - pp == 1);
hb_always_assert (!*end);
}
{
const char str[] = "123";
const char *pp = str;
hb_always_assert (ARRAY_LENGTH (str) == 4);
const char *end = str + ARRAY_LENGTH (str);
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp - str == 3);
hb_always_assert (end - pp == 1);
}
{
const char str[] = "123\0";
const char *pp = str;
hb_always_assert (ARRAY_LENGTH (str) == 5);
const char *end = str + ARRAY_LENGTH (str);
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp - str == 3);
hb_always_assert (end - pp == 2);
}
{
const char str[] = "123V";
const char *pp = str;
hb_always_assert (ARRAY_LENGTH (str) == 5);
const char *end = str + ARRAY_LENGTH (str);
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp - str == 3);
hb_always_assert (end - pp == 2);
}
{
const char str[] = "123abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv, true));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* Leading whitespace */
{
const char str[] = " 123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp == end);
}
{
const char str[] = "\t123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 123);
hb_always_assert (pp == end);
}
/* Leading zeros (still decimal when base is 10) */
{
const char str[] = "007";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 7);
hb_always_assert (pp == end);
}
{
const char str[] = "000";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 0);
hb_always_assert (pp == end);
}
/* UINT_MAX */
{
const char str[] = "4294967295";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 4294967295u);
hb_always_assert (pp == end);
}
/* Negative wraps in two's complement (matches strtoul on unsigned) */
{
const char str[] = "-1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 4294967295u);
hb_always_assert (pp == end);
}
{
const char str[] = "-0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 0);
hb_always_assert (pp == end);
}
/* Base 2 */
{
const char str[] = "1010";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 2));
hb_always_assert (pv == 10);
hb_always_assert (pp == end);
}
{
const char str[] = "11111111";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 2));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
{
const char str[] = "12";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
/* '2' is not a base-2 digit; parse stops at index 1 */
hb_always_assert (hb_parse_uint (&pp, end, &pv, false, 2));
hb_always_assert (pv == 1);
hb_always_assert (pp == str + 1);
}
/* Base 8 */
{
const char str[] = "777";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 8));
hb_always_assert (pv == 511);
hb_always_assert (pp == end);
}
{
const char str[] = "010";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 8));
hb_always_assert (pv == 8);
hb_always_assert (pp == end);
}
/* Base 16, with and without 0x prefix, mixed case */
{
const char str[] = "FF";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
{
const char str[] = "ff";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
{
const char str[] = "Ff";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
{
const char str[] = "0xFF";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
{
const char str[] = "0XFF";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
/* Base 36 */
{
const char str[] = "Z";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 36));
hb_always_assert (pv == 35);
hb_always_assert (pp == end);
}
{
const char str[] = "z";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 36));
hb_always_assert (pv == 35);
hb_always_assert (pp == end);
}
{
const char str[] = "10";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 36));
hb_always_assert (pv == 36);
hb_always_assert (pp == end);
}
/* Failures */
{
const char str[] = "abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
/* 'a' isn't a decimal digit; whole parse fails */
hb_always_assert (!hb_parse_uint (&pp, end, &pv, false, 10));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
{
const char str[] = "+";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
}
{
const char str[] = "-";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
}
{
const char str[] = "";
const char *pp = str;
const char *end = str;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
}
{
const char str[] = "0XFF";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
{
const char str[] = "0xff";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 255);
hb_always_assert (pp == end);
}
{
const char str[] = "0x0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 0);
hb_always_assert (pp == end);
}
/* "0x" alone: consume only the 0, leave the x */
{
const char str[] = "0x";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, false, 16));
hb_always_assert (pv == 0);
hb_always_assert (pp == str + 1);
}
/* "0xG": 0 is consumed, xG left */
{
const char str[] = "0xG";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, false, 16));
hb_always_assert (pv == 0);
hb_always_assert (pp == str + 1);
}
/* Negative with prefix */
{
const char str[] = "-0xFF";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == (unsigned) -255);
hb_always_assert (pp == end);
}
/* Prefix rule doesn't fire for base 10 */
{
const char str[] = "0xFF";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, false, 10));
hb_always_assert (pv == 0);
hb_always_assert (pp == str + 1);
}
{
/* 10 digits > UINT_MAX. The old strtol-based implementation silently
* truncated on 64-bit platforms (unsigned long is 64-bit) but rejected on
* 32-bit; the new implementation rejects uniformly. */
const char str[] = "9999999999"; /* 10 digits, > UINT_MAX */
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* UINT_MAX - exactly representable */
{
const char str[] = "4294967295";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 4294967295u);
hb_always_assert (pp == end);
}
/* One past UINT_MAX - must fail (currently truncates to 0) */
{
const char str[] = "4294967296";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* 20 digits, way past UINT_MAX */
{
const char str[] = "99999999999999999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* 40 digits, past the old 32-byte stack buffer */
{
const char str[] = "9999999999999999999999999999999999999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* 0xFFFFFFFF = UINT_MAX */
{
const char str[] = "0xFFFFFFFF";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 4294967295u);
hb_always_assert (pp == end);
}
/* 0x100000000 = UINT_MAX + 1 */
{
const char str[] = "0x100000000";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* 13 'Z's = 36^13 - 1, comfortably > UINT64_MAX would need ~12 digits */
{
const char str[] = "ZZZZZZZZZZZZZZ"; /* 14 Z's */
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv, true, 36));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
{
const char str[] = "9999999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 42;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 42);
}
/* Negative values whose magnitude exceeds UINT_MAX must fail, not wrap */
{
const char str[] = "-4294967296";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99);
}
/* INT_MIN magnitude as unsigned: wraps to 0x80000000 */
{
const char str[] = "-2147483648";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 2147483648u);
hb_always_assert (pp == end);
}
/* Mixed case in base 36 */
{
const char str[] = "Az";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 36));
hb_always_assert (pv == 10 * 36 + 35);
hb_always_assert (pp == end);
}
/* Whitespace between sign and digits is not allowed */
{
const char str[] = "- 1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv = 99;
hb_always_assert (!hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 99);
}
/* "0x" prefix is case-insensitive but only for base 16 */
{
const char str[] = "0X10";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, true, 16));
hb_always_assert (pv == 16);
hb_always_assert (pp == end);
}
/* A second "0x" is not consumed as a prefix */
{
const char str[] = "0x0x10";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv, false, 16));
hb_always_assert (pv == 0);
hb_always_assert (pp == str + 3);
}
/* Null byte stops the scan (end passed at NUL) */
{
const char str[] = "12\0F";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
unsigned int pv;
hb_always_assert (hb_parse_uint (&pp, end, &pv));
hb_always_assert (pv == 12);
hb_always_assert (pp == str + 2);
}
}
/* Tolerate 1 ULP difference. Needed because 32-bit x86 (x87) computes
* at 80-bit precision and rounds to 64-bit on store, which can differ
* from a directly-rounded decimal literal by one ULP. */
static inline bool
almost_equal (double a, double b)
{
return fabs (a - b) <= fabs (a) * 2 * DBL_EPSILON;
}
static void
test_parse_double (void)
{
{
const char str[] = ".123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str);
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert ((int) roundf (pv * 1000.) == 123);
hb_always_assert (pp - str == 4);
hb_always_assert (end - pp == 1);
}
{
const char str[] = "0.123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert ((int) roundf (pv * 1000.) == 123);
hb_always_assert (pp - str == 5);
hb_always_assert (end - pp == 0);
}
{
const char str[] = "0.123e0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert ((int) roundf (pv * 1000.) == 123);
hb_always_assert (pp - str == 7);
hb_always_assert (end - pp == 0);
}
{
const char str[] = "123e-3";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert ((int) roundf (pv * 1000.) == 123);
hb_always_assert (pp - str == 6);
hb_always_assert (end - pp == 0);
}
{
const char str[] = ".000123e+3";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert ((int) roundf (pv * 1000.) == 123);
hb_always_assert (pp - str == 10);
hb_always_assert (end - pp == 0);
}
{
const char str[] = "-.000000123e6";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert ((int) roundf (pv * 1000.) == -123);
hb_always_assert (pp - str == 13);
hb_always_assert (end - pp == 0);
}
{
const char str[] = "-1.23E-1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert ((int) roundf (pv * 1000.) == -123);
hb_always_assert (pp - str == 8);
hb_always_assert (end - pp == 0);
}
{
const char str[] = "1e512";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (std::isinf (pv) && pv > 0);
}
{
const char str[] = "1e600";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (std::isinf (pv) && pv > 0);
}
{
const char str[] = "1e-512";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 0.0);
}
{
const char str[] = "1e-600";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 0.0);
}
{
const char str[] = "0.9999999999999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.0);
}
{
const char str[] = "0.499999999999999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 0.5);
}
{
const char str[] = "1e";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.0);
hb_always_assert (pp == str + 1);
}
{
const char str[] = "1e+";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.0);
hb_always_assert (pp == str + 1);
}
{
const char str[] = "-";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99);
}
{
const char str[] = ".";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99);
}
{
const char str[] = "1e-";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.0);
hb_always_assert (pp == str + 1);
}
{
const char str[] = "-1e";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == -1.0);
hb_always_assert (pp == str + 2);
}
{
const char str[] = "+";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
}
{
const char str[] = "-.";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
}
// But be careful with fractional parts
{
const char str[] = "1.";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 1.0);
hb_always_assert (pp == end);
}
{
const char str[] = "1.abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.0);
hb_always_assert (pp == str + 2); // at least "1." was consumed
}
{
const char str[] = "abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99.0);
}
{
const char str[] = "";
const char *pp = str;
const char *end = str;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99.0);
}
{
const char str[] = " \t 123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 123.0);
hb_always_assert (pp == end);
}
{
const char str[] = "-0.0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 0.0 && std::signbit (pv));
}
{
const char str[] = "1.5E10";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 1.5e10);
}
{
const char str[] = "1.5E+10";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 1.5e10);
}
{
const char str[] = "1e308";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv > 0 && pv <= DBL_MAX);
}
{
const char str[] = "1e309";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (std::isinf (pv) && pv > 0);
}
{
const char str[] = "1e-309";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv > 0.0 && pv < DBL_MIN);
hb_always_assert (pv == strtod (str, nullptr));
}
{
const char str[] = "5e-324";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv > 0.0 && pv < DBL_MIN);
hb_always_assert (pv == strtod (str, nullptr));
}
{
const char str[] = "1e+5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 100000.0);
}
{
const char str[] = "1E5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 100000.0);
}
{
const char str[] = "123abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 123.0);
hb_always_assert (pp == str + 3);
}
{
const char str[] = "123abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (!hb_parse_double (&pp, end, &pv, true));
}
{
const char str[] = "-1.5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == -1.5);
}
{
const char str[] = "1.5E-10";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (almost_equal (pv, 1.5e-10));
}
{
const char str[] = "-.5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == -0.5);
}
{
const char str[] = "500";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 500.0);
}
{
const char str[] = "-7.5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == -7.5);
}
{
const char str[] = "123 ";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (!hb_parse_double (&pp, end, &pv, true));
}
{
const char str[] = " 123";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 123.0);
}
{
const char str[] = "+1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 1.0);
}
{
const char str[] = "+1.5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 1.5);
}
{
const char str[] = "--1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99.0);
}
{
const char str[] = "+-1";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99.0);
}
{
const char str[] = "0e5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 0.0);
}
{
const char str[] = "1.5e";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.5);
hb_always_assert (pp == str + 3);
}
{
const char str[] = "1.5e+";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.5);
hb_always_assert (pp == str + 3);
}
{
const char str[] = "1e9999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == DBL_MAX);
}
{
const char str[] = "-1e9999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == -DBL_MAX);
}
{
const char str[] = "1e-9999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == .0);
hb_always_assert (pv == strtod (str, nullptr));
}
{
const char str[] = "-1e-9999999";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == -.0);
hb_always_assert (pv == -strtod (str, nullptr));
}
{
const char str[] = "1e-400";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 0.0);
}
{
const char str[] = "007";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 7.0);
}
{
const char str[] = "0.0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 0.0 && !std::signbit (pv));
}
{
const char str[] = "NaN";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99.0);
}
{
const char str[] = "inf";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99.0);
}
{
const char str[] = "1..5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.0);
hb_always_assert (pp == str + 2); // Don't consume ending ".5"
}
{
const char str[] = "1.5.5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.5);
hb_always_assert (pp == str + 3); // Don't consume ending ".5"
}
{
const char str[] = " ";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 99.0);
}
{
const char str[] = " abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 99.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 99.0);
}
{
const char str[] = "1.7976931348623157e308";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv >= DBL_MAX || std::isinf (pv));
hb_always_assert (pp == end);
}
{
const char str[] = "99999999999999999999"; // 20 nines
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv >= 1e19 && pv <= 1.1e20);
hb_always_assert (pp == end);
}
{
const char str[] = "1.e5";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 100000.0);
hb_always_assert (pp == end);
}
/* Exponent with leading zeros */
{
const char str[] = "1e005";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 100000.0);
hb_always_assert (pp == end);
}
{
const char str[] = "1e-005";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (almost_equal (pv, 1e-5));
hb_always_assert (pp == end);
}
/* Bare -0 (no decimal) preserves the sign, matching strtod */
{
const char str[] = "-0";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv == 0.0 && std::signbit (pv));
hb_always_assert (pp == end);
}
/* Long mantissa followed by an exponent */
{
const char str[] = "12345678901234567890e-10";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pv > 1.234e9 && pv < 1.235e9);
hb_always_assert (pp == end);
}
/* whole_buffer failure must not touch *pv */
{
const char str[] = "123abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 42.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv, true));
hb_always_assert (pp == str);
hb_always_assert (pv == 42.0);
}
/* Same for no-match failure */
{
const char str[] = "abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv = 42.0;
hb_always_assert (!hb_parse_double (&pp, end, &pv));
hb_always_assert (pp == str);
hb_always_assert (pv == 42.0);
}
/* Exponent followed by trailing content */
{
const char str[] = "1e5abc";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 100000.0);
hb_always_assert (pp == str + 3);
}
/* Same with a sign in the exponent */
{
const char str[] = "1e+5x";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 100000.0);
hb_always_assert (pp == str + 4);
}
/* Malformed exponent followed by content: should stop at the 'e' */
{
const char str[] = "1ex";
const char *pp = str;
const char *end = str + ARRAY_LENGTH (str) - 1;
double pv;
hb_always_assert (hb_parse_double (&pp, end, &pv));
hb_always_assert (pv == 1.0);
hb_always_assert (pp == str + 1);
}
}
int
main (int argc, char **argv)
{
test_parse_double ();
test_parse_int ();
test_parse_uint ();
return 0;
}