Refactor strings (avoid using dynamically allocated memory)
Refactored strings functions to make them use supplied string instead of allocating new ones. Additionally, split String/Int.c into several files to avoid define mess that was present before.
This commit is contained in:
@@ -94,7 +94,6 @@ set(BH_SOURCE
|
||||
src/Util.c
|
||||
src/String/Int.c
|
||||
src/String/Float.c
|
||||
src/String/Core.c
|
||||
)
|
||||
|
||||
set(BH_HEADER
|
||||
@@ -107,7 +106,6 @@ set(BH_HEADER
|
||||
include/BH/Queue.h
|
||||
include/BH/Util.h
|
||||
include/BH/Thread.h
|
||||
include
|
||||
)
|
||||
|
||||
set(BH_SOURCE_DUMMY
|
||||
|
||||
@@ -6,27 +6,9 @@
|
||||
|
||||
|
||||
/**
|
||||
* Frees dynamically allocated \a string.
|
||||
*
|
||||
* \param string String pointer
|
||||
*/
|
||||
void BH_StringFree(char *string);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a copy of the input \a string.
|
||||
*
|
||||
* \param string String pointer
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringCopy(const char *string);
|
||||
|
||||
|
||||
/**
|
||||
* Formats a double \a value into a string using the provided \a format and
|
||||
* \a precision.
|
||||
* Formats a double \a value into a zero terminated \a string (limited by
|
||||
* \a size) using the provided \a format and \a precision and stores \a actual
|
||||
* length (if it's provided).
|
||||
*
|
||||
* Formats supported:
|
||||
* - Scientific or fixed format ('g' or 'G')
|
||||
@@ -38,16 +20,182 @@ char *BH_StringCopy(const char *string);
|
||||
*
|
||||
* This function follows IEEE 754 round to even to break ties during rounding.
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param format Format
|
||||
* \param precision Precision
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
char *BH_StringFromDouble(double value,
|
||||
int BH_StringFromDouble(char *string,
|
||||
size_t size,
|
||||
double value,
|
||||
char format,
|
||||
int precision);
|
||||
int precision,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats signed 8-bit \a value into a \a string (limited by \a size) with
|
||||
* provided \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt8s(char *string,
|
||||
size_t size,
|
||||
int8_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats signed 16-bit \a value into a \a string (limited by \a size) with
|
||||
* provided \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt16s(char *string,
|
||||
size_t size,
|
||||
int16_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats signed 32-bit \a value into a \a string (limited by \a size) with
|
||||
* provided \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt32s(char *string,
|
||||
size_t size,
|
||||
int32_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats signed 64-bit \a value into a \a string (limited by \a size) with
|
||||
* provided \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt64s(char *string,
|
||||
size_t size,
|
||||
int64_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 8-bit \a value into a \a string (limited by \a size) with
|
||||
* provides \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt8u(char *string,
|
||||
size_t size,
|
||||
uint8_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 16-bit \a value into a \a string (limited by \a size) with
|
||||
* provides \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt16u(char *string,
|
||||
size_t size,
|
||||
uint16_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 32-bit \a value into a \a string (limited by \a size) with
|
||||
* provided \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt32u(char *string,
|
||||
size_t size,
|
||||
uint32_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 64-bit \a value into a \a string (limited by \a size) with
|
||||
* provided \a base and stores \a actual length (if it's provided).
|
||||
*
|
||||
* \param string String
|
||||
* \param size String size
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
* \param actual Written size (optional)
|
||||
*
|
||||
* \return On success, returns zero.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
int BH_StringFromInt64u(char *string,
|
||||
size_t size,
|
||||
uint64_t value,
|
||||
int base,
|
||||
size_t *actual);
|
||||
|
||||
|
||||
/**
|
||||
@@ -65,114 +213,12 @@ double BH_StringToDouble(const char *string,
|
||||
size_t *size);
|
||||
|
||||
|
||||
/**
|
||||
* Formats signed 8bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt8s(int8_t value,
|
||||
int base);
|
||||
|
||||
|
||||
/**
|
||||
* Formats signed 16bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt16s(int16_t value,
|
||||
int base);
|
||||
|
||||
|
||||
/**
|
||||
* Formats signed 32bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt32s(int32_t value,
|
||||
int base);
|
||||
|
||||
/**
|
||||
* Formats signed 64bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt64s(int64_t value,
|
||||
int base);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 8bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt8u(uint8_t value,
|
||||
int base);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 16bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt16u(uint16_t value,
|
||||
int base);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 32bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt32u(uint32_t value,
|
||||
int base);
|
||||
|
||||
|
||||
/**
|
||||
* Formats unsigned 64bit \a value into string with the specified \a base.
|
||||
*
|
||||
* \param value Value
|
||||
* \param base Base
|
||||
*
|
||||
* \return On success, returns new string pointer.
|
||||
* \return On failure, returns NULL pointer.
|
||||
*/
|
||||
char *BH_StringFromInt64u(uint64_t value,
|
||||
int base);
|
||||
|
||||
|
||||
/**
|
||||
* Reads \a string containing value in specified \a base, optionally reports
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
@@ -194,6 +240,7 @@ int8_t BH_StringToInt8s(const char *string,
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
@@ -215,6 +262,7 @@ int16_t BH_StringToInt16s(const char *string,
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
@@ -236,6 +284,7 @@ int32_t BH_StringToInt32s(const char *string,
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
@@ -257,6 +306,7 @@ int64_t BH_StringToInt64s(const char *string,
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
@@ -278,6 +328,7 @@ uint8_t BH_StringToInt8u(const char *string,
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
@@ -299,6 +350,7 @@ uint16_t BH_StringToInt16u(const char *string,
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
@@ -320,6 +372,7 @@ uint32_t BH_StringToInt32u(const char *string,
|
||||
* \a size amount of characters consumed and returns the result value.
|
||||
*
|
||||
* If base is 0, function will automaticly detect input base by the prefix:
|
||||
* - Base 2 if prefix is 0b
|
||||
* - Base 8 if prefix is 0
|
||||
* - Base 16 if prefix is 0x
|
||||
* - Base 10 in other cases
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <BH/String.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void BH_StringFree(char *string)
|
||||
{
|
||||
free(string);
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringCopy(const char *string)
|
||||
{
|
||||
char *result;
|
||||
|
||||
result = malloc(strlen(string) + 1);
|
||||
if (result)
|
||||
strcpy(result, string);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -22,6 +22,13 @@
|
||||
#define RELATIVE 2
|
||||
|
||||
|
||||
struct Buffer
|
||||
{
|
||||
char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
|
||||
struct DragonState
|
||||
{
|
||||
BInt r;
|
||||
@@ -100,9 +107,8 @@ static void dragonFixup(struct DragonState *state,
|
||||
|
||||
|
||||
static void dragonRound(struct DragonState *state,
|
||||
char *buffer,
|
||||
struct Buffer *buffer,
|
||||
int *k,
|
||||
int *size,
|
||||
int high,
|
||||
int low,
|
||||
char s)
|
||||
@@ -110,7 +116,7 @@ static void dragonRound(struct DragonState *state,
|
||||
int i;
|
||||
|
||||
/* Preconditions */
|
||||
assert(state != NULL && buffer != NULL && k != NULL && size != NULL);
|
||||
assert(state != NULL && buffer != NULL && k != NULL);
|
||||
assert(s >= '0' && s <= '9');
|
||||
|
||||
/* Check if rounding up required */
|
||||
@@ -126,14 +132,14 @@ static void dragonRound(struct DragonState *state,
|
||||
/* Perform rounding up */
|
||||
if (!low)
|
||||
{
|
||||
for (i = *size; i && buffer[i - 1] == '9'; i--)
|
||||
buffer[i - 1] = '0';
|
||||
for (i = buffer->size; i && buffer->data[i - 1] == '9'; i--)
|
||||
buffer->data[i - 1] = '0';
|
||||
|
||||
if (i > 0)
|
||||
buffer[i - 1]++;
|
||||
buffer->data[i - 1]++;
|
||||
else
|
||||
{
|
||||
buffer[0] = '1';
|
||||
buffer->data[0] = '1';
|
||||
(*k)++;
|
||||
}
|
||||
}
|
||||
@@ -143,8 +149,7 @@ static void dragonRound(struct DragonState *state,
|
||||
static void dragon(double value,
|
||||
int precision,
|
||||
int mode,
|
||||
char *buffer,
|
||||
int *size,
|
||||
struct Buffer *buffer,
|
||||
int *k)
|
||||
{
|
||||
struct DragonState state;
|
||||
@@ -153,17 +158,17 @@ static void dragon(double value,
|
||||
char s;
|
||||
|
||||
/* Preconditions */
|
||||
assert(buffer != NULL && size != NULL && k != NULL);
|
||||
assert(buffer != NULL && k != NULL);
|
||||
assert(mode == NORMAL || mode == ABSOLUTE || mode == RELATIVE);
|
||||
assert(precision >= 0);
|
||||
|
||||
*k = 0;
|
||||
*size = low = high = 0;
|
||||
buffer->size = low = high = 0;
|
||||
|
||||
/* If value is zero - do nothing */
|
||||
if (!value)
|
||||
{
|
||||
buffer[(*size)++] = '0';
|
||||
buffer->data[buffer->size++] = '0';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -199,7 +204,7 @@ static void dragon(double value,
|
||||
s = '0';
|
||||
if (state.tmp[0].size)
|
||||
s += state.tmp[0].data[0];
|
||||
buffer[(*size)++] = s;
|
||||
buffer->data[buffer->size++] = s;
|
||||
|
||||
if (mode == NORMAL)
|
||||
{
|
||||
@@ -210,38 +215,40 @@ static void dragon(double value,
|
||||
BIntAdd(&state.tmp[1], &state.mp, &state.tmp[3]);
|
||||
low = BIntCompare(&state.tmp[1], &state.mm) < 0;
|
||||
high = BIntCompare(&state.tmp[3], &state.tmp[2]) > 0;
|
||||
if (low || high || state.k == state.cutoff || *size >= BUFSIZE)
|
||||
if (low || high || state.k == state.cutoff || buffer->size >= BUFSIZE)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!state.r.size || state.k == state.cutoff || *size >= BUFSIZE)
|
||||
if (!state.r.size || state.k == state.cutoff || buffer->size >= BUFSIZE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Round digits if required */
|
||||
dragonRound(&state, buffer, k, size, high, low, s);
|
||||
dragonRound(&state, buffer, k, high, low, s);
|
||||
}
|
||||
|
||||
|
||||
static char *formatF(char *buffer,
|
||||
static int formatF(struct Buffer *output,
|
||||
struct Buffer *input,
|
||||
int precision,
|
||||
int sign,
|
||||
int k,
|
||||
int size)
|
||||
size_t *actual)
|
||||
{
|
||||
char *result, *current;
|
||||
char *current;
|
||||
int i;
|
||||
|
||||
/* Preconditions */
|
||||
assert(buffer != NULL);
|
||||
assert(size < BUFSIZE);
|
||||
assert(output != NULL && input != NULL);
|
||||
assert(input->size < BUFSIZE);
|
||||
assert(sign == 0 || sign == 1);
|
||||
|
||||
result = malloc(MAX(0, k) + 5 + sign + precision);
|
||||
current = result;
|
||||
if (!result)
|
||||
return NULL;
|
||||
/* Check that output buffer has enough space */
|
||||
current = output->data;
|
||||
if (output->size < (size_t)(MAX(0, k) + 4 + precision))
|
||||
return BH_ERROR;
|
||||
|
||||
/* Add sign */
|
||||
if (sign)
|
||||
@@ -262,8 +269,8 @@ static char *formatF(char *buffer,
|
||||
/* Add digits */
|
||||
for (i = 0; k >= -precision; i++, k--)
|
||||
{
|
||||
if (i < size)
|
||||
*(current++) = buffer[i];
|
||||
if (i < (int)input->size)
|
||||
*(current++) = input->data[i];
|
||||
else
|
||||
*(current++) = '0';
|
||||
|
||||
@@ -272,38 +279,41 @@ static char *formatF(char *buffer,
|
||||
}
|
||||
|
||||
*(current++) = 0;
|
||||
return result;
|
||||
if (actual)
|
||||
*actual = current - output->data;
|
||||
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *formatE(char *buffer,
|
||||
static int formatE(struct Buffer *output,
|
||||
struct Buffer *input,
|
||||
int precision,
|
||||
int sign,
|
||||
int k,
|
||||
int size,
|
||||
int upper)
|
||||
int upper,
|
||||
size_t *actual)
|
||||
{
|
||||
char *result, *current;
|
||||
char *current;
|
||||
int i;
|
||||
|
||||
/* Preconditions */
|
||||
assert(buffer != NULL);
|
||||
assert(size < BUFSIZE);
|
||||
assert(input != NULL && output != NULL);
|
||||
assert(input->size < BUFSIZE);
|
||||
assert(sign == 0 || sign == 1);
|
||||
assert(upper == 0 || upper == 1);
|
||||
|
||||
result = malloc(9 + sign + precision);
|
||||
current = result;
|
||||
if (!result)
|
||||
return NULL;
|
||||
current = output->data;
|
||||
if (output->size < (size_t)(9 + precision))
|
||||
return BH_ERROR;
|
||||
|
||||
/* Add sign and digits */
|
||||
if (sign)
|
||||
*(current++) = '-';
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
for (i = 0; i < (int)input->size; i++)
|
||||
{
|
||||
*(current++) = buffer[i];
|
||||
*(current++) = input->data[i];
|
||||
if (i == 0 && precision > 0)
|
||||
*(current++) = '.';
|
||||
}
|
||||
@@ -323,106 +333,137 @@ static char *formatE(char *buffer,
|
||||
*(current++) = '+';
|
||||
|
||||
/* Convert exponent to digits and add them */
|
||||
for (size = 0; k || size < 2; size++)
|
||||
for (i = 0; k || i < 2; i++)
|
||||
{
|
||||
buffer[size] = '0' + k % 10;
|
||||
input->data[i] = '0' + k % 10;
|
||||
k = k / 10;
|
||||
}
|
||||
for (; size; size--)
|
||||
*(current++) = buffer[size - 1];
|
||||
for (; i; i--)
|
||||
*(current++) = input->data[i - 1];
|
||||
|
||||
*(current++) = 0;
|
||||
return result;
|
||||
if (actual)
|
||||
*actual = current - output->data;
|
||||
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *generateF(double value,
|
||||
static int generateF(struct Buffer *output,
|
||||
double value,
|
||||
int precision,
|
||||
int sign)
|
||||
int sign,
|
||||
size_t *actual)
|
||||
{
|
||||
char buffer[BUFSIZE];
|
||||
int size, k;
|
||||
struct Buffer input;
|
||||
int k;
|
||||
|
||||
input.data = buffer;
|
||||
input.size = 0;
|
||||
|
||||
/* Call Dragon4 and format the digits */
|
||||
if (precision < 0)
|
||||
dragon(value, 0, NORMAL, buffer, &size, &k);
|
||||
dragon(value, 0, NORMAL, &input, &k);
|
||||
else
|
||||
dragon(value, precision, ABSOLUTE, buffer, &size, &k);
|
||||
dragon(value, precision, ABSOLUTE, &input, &k);
|
||||
|
||||
if (precision < 0)
|
||||
precision = MAX(0, size - k - 1);
|
||||
precision = MAX(0, (int)input.size - k - 1);
|
||||
|
||||
return formatF(buffer, precision, sign, k, size);
|
||||
return formatF(output, &input, precision, sign, k, actual);
|
||||
}
|
||||
|
||||
|
||||
static char *generateE(double value,
|
||||
static int generateE(struct Buffer *output,
|
||||
double value,
|
||||
int precision,
|
||||
int upper,
|
||||
int sign)
|
||||
int sign,
|
||||
size_t *actual)
|
||||
{
|
||||
char buffer[BUFSIZE];
|
||||
int size, k;
|
||||
struct Buffer input;
|
||||
int k;
|
||||
|
||||
input.data = buffer;
|
||||
input.size = 0;
|
||||
|
||||
/* Adjust precision and call Dragon4 to generate digits */
|
||||
if (precision < 0)
|
||||
dragon(value, 0, NORMAL, buffer, &size, &k);
|
||||
dragon(value, 0, NORMAL, &input, &k);
|
||||
else
|
||||
dragon(value, (precision + 1), RELATIVE, buffer, &size, &k);
|
||||
dragon(value, (precision + 1), RELATIVE, &input, &k);
|
||||
|
||||
if (precision < 0)
|
||||
precision = size - 1;
|
||||
precision = input.size - 1;
|
||||
|
||||
return formatE(buffer, precision, sign, k, size, upper);
|
||||
return formatE(output, &input, precision, sign, k, upper, actual);
|
||||
}
|
||||
|
||||
|
||||
static char *generateG(double value,
|
||||
static int generateG(struct Buffer *output,
|
||||
double value,
|
||||
int precision,
|
||||
int upper,
|
||||
int sign)
|
||||
int sign,
|
||||
size_t *actual)
|
||||
{
|
||||
char buffer[BUFSIZE];
|
||||
int size, k, fixed;
|
||||
struct Buffer input;
|
||||
int k, fixed;
|
||||
|
||||
input.data = buffer;
|
||||
input.size = 0;
|
||||
if (precision == 0)
|
||||
precision = 1;
|
||||
|
||||
/* Call Dragon4 to generate digits */
|
||||
if (precision < 0)
|
||||
{
|
||||
dragon(value, 0, NORMAL, buffer, &size, &k);
|
||||
fixed = k >= -4 && k <= (size - 1);
|
||||
dragon(value, 0, NORMAL, &input, &k);
|
||||
fixed = k >= -4 && k <= (int)(input.size - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dragon(value, precision, RELATIVE, buffer, &size, &k);
|
||||
dragon(value, precision, RELATIVE, &input, &k);
|
||||
fixed = k >= -4 && k < precision;
|
||||
|
||||
/* Remove trailing zeros and adjust precision */
|
||||
for (; size && precision > 0 && buffer[size - 1] == '0'; size--, precision--);
|
||||
for (; input.size && precision > 0 && buffer[input.size - 1] == '0'; input.size--, precision--);
|
||||
}
|
||||
|
||||
if (fixed)
|
||||
{
|
||||
precision = MAX(0, size - k - 1);
|
||||
return formatF(buffer, precision, sign, k, size);
|
||||
precision = MAX(0, (int)input.size - k - 1);
|
||||
return formatF(output, &input, precision, sign, k, actual);
|
||||
}
|
||||
else
|
||||
{
|
||||
precision = MAX(0, size - 1);
|
||||
return formatE(buffer, precision, sign, k, size, upper);
|
||||
precision = MAX(0, (int)input.size - 1);
|
||||
return formatE(output, &input, precision, sign, k, upper, actual);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringFromDouble(double value,
|
||||
int BH_StringFromDouble(char *string,
|
||||
size_t size,
|
||||
double value,
|
||||
char format,
|
||||
int precision)
|
||||
int precision,
|
||||
size_t *actual)
|
||||
{
|
||||
static const char *infStrings[] = { "inf", "-inf", "INF", "-INF" };
|
||||
static const char *nanStrings[] = { "nan", "NAN" };
|
||||
int sign, type, upper;
|
||||
struct Buffer output;
|
||||
|
||||
output.data = string;
|
||||
output.size = size;
|
||||
|
||||
/* Buffer is less then 5 characters */
|
||||
if (size < 5)
|
||||
return BH_ERROR;
|
||||
|
||||
type = BH_ClassifyDouble(value);
|
||||
upper = isupper(format) > 0;
|
||||
@@ -433,16 +474,27 @@ char *BH_StringFromDouble(double value,
|
||||
|
||||
/* Handle NaN and Inf */
|
||||
if (type == BH_FP_INFINITE)
|
||||
return BH_StringCopy(infStrings[upper * 2 + sign]);
|
||||
{
|
||||
memcpy(string, infStrings[upper * 2 + sign], 4 + sign);
|
||||
if (actual)
|
||||
*actual = 4 + sign;
|
||||
return BH_OK;
|
||||
}
|
||||
else if (type == BH_FP_NAN)
|
||||
return BH_StringCopy(nanStrings[upper]);
|
||||
{
|
||||
memcpy(string, nanStrings[upper], 4);
|
||||
if (actual)
|
||||
*actual = 4;
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
/* Do the formating */
|
||||
if (format == 'g' || format == 'G')
|
||||
return generateG(value, precision, upper, sign);
|
||||
return generateG(&output, value, precision, upper, sign, actual);
|
||||
else if (format == 'e' || format == 'E')
|
||||
return generateE(value, precision, upper, sign);
|
||||
return generateE(&output, value, precision, upper, sign, actual);
|
||||
else
|
||||
return generateF(value, precision, sign);
|
||||
return generateF(&output, value, precision, sign, actual);
|
||||
}
|
||||
|
||||
|
||||
@@ -593,16 +645,8 @@ double BH_StringToDouble(const char *string,
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Handle zero input */
|
||||
if (count == 0)
|
||||
{
|
||||
if (sign)
|
||||
return -0.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Exponent too low */
|
||||
if (e < -329)
|
||||
/* Zero or exponent too low */
|
||||
if (!count || e < -329)
|
||||
{
|
||||
if (sign)
|
||||
return -0.0;
|
||||
|
||||
34
src/String/FromInt.inl
Normal file
34
src/String/FromInt.inl
Normal file
@@ -0,0 +1,34 @@
|
||||
int sign, flag = 0;
|
||||
signed char sym;
|
||||
|
||||
/* Check for valid base and zero out read size */
|
||||
result = 0;
|
||||
if (size)
|
||||
*size = 0;
|
||||
if (base != 0 && (base < 2 || base > 36))
|
||||
return 0;
|
||||
|
||||
/* Handle space, sign and base */
|
||||
skipSpace(&string, size);
|
||||
handleSign(&string, size, &sign);
|
||||
guessBase(&string, size, &base);
|
||||
|
||||
/* Read digits */
|
||||
while(*string)
|
||||
{
|
||||
sym = *(string++);
|
||||
sym = lookup[(unsigned int)sym];
|
||||
if (sym >= base || sym == -1)
|
||||
break;
|
||||
|
||||
if (size)
|
||||
(*size)++;
|
||||
result = result * base + sym;
|
||||
flag = 1;
|
||||
}
|
||||
|
||||
/* Zero out size on error */
|
||||
if (!result && !flag && size)
|
||||
*size = 0;
|
||||
|
||||
return result * sign;
|
||||
130
src/String/Int.c
130
src/String/Int.c
@@ -80,98 +80,92 @@ static void guessBase(const char **string,
|
||||
}
|
||||
|
||||
|
||||
#define TEMPLATE_IMPL \
|
||||
char tmp[sizeof(value) * CHAR_BIT + 1]; char *current, *end, *result; \
|
||||
int sign; end = tmp + sizeof(tmp); current = end; sign = 0; \
|
||||
if (value < 0) { sign = 1; value = -value; } while (value) { \
|
||||
*(--current) = digits[value % base]; value /= base; } \
|
||||
if (sign) { *(--current) = '-'; } result = malloc(end - current + 1); \
|
||||
if (!result) { return NULL; } memcpy(result, current, end - current); \
|
||||
result[end - current] = 0; return result;
|
||||
|
||||
|
||||
char *BH_StringFromInt8s(int8_t value,
|
||||
int base)
|
||||
int BH_StringFromInt8s(char *string,
|
||||
size_t size,
|
||||
int8_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntS.inl"
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringFromInt16s(int16_t value,
|
||||
int base)
|
||||
int BH_StringFromInt16s(char *string,
|
||||
size_t size,
|
||||
int16_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntS.inl"
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringFromInt32s(int32_t value,
|
||||
int base)
|
||||
int BH_StringFromInt32s(char *string,
|
||||
size_t size,
|
||||
int32_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntS.inl"
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringFromInt64s(int64_t value,
|
||||
int base)
|
||||
int BH_StringFromInt64s(char *string,
|
||||
size_t size,
|
||||
int64_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntS.inl"
|
||||
}
|
||||
|
||||
|
||||
#undef TEMPLATE_IMPL
|
||||
#define TEMPLATE_IMPL \
|
||||
char tmp[sizeof(value) * CHAR_BIT]; char *current, *end, *result; \
|
||||
end = tmp + sizeof(tmp); current = end; while (value) { \
|
||||
*(--current) = digits[value % base]; value /= base; } \
|
||||
result = malloc(end - current + 1); if (!result) { return NULL; } \
|
||||
memcpy(result, current, end - current); result[end - current] = 0; \
|
||||
return result;
|
||||
|
||||
|
||||
char *BH_StringFromInt8u(uint8_t value,
|
||||
int base)
|
||||
int BH_StringFromInt8u(char *string,
|
||||
size_t size,
|
||||
uint8_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntU.inl"
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringFromInt16u(uint16_t value,
|
||||
int base)
|
||||
int BH_StringFromInt16u(char *string,
|
||||
size_t size,
|
||||
uint16_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntU.inl"
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringFromInt32u(uint32_t value,
|
||||
int base)
|
||||
int BH_StringFromInt32u(char *string,
|
||||
size_t size,
|
||||
uint32_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntU.inl"
|
||||
}
|
||||
|
||||
|
||||
char *BH_StringFromInt64u(uint64_t value,
|
||||
int base)
|
||||
int BH_StringFromInt64u(char *string,
|
||||
size_t size,
|
||||
uint64_t value,
|
||||
int base,
|
||||
size_t *actual)
|
||||
{
|
||||
TEMPLATE_IMPL
|
||||
#include "ToIntU.inl"
|
||||
}
|
||||
|
||||
|
||||
#undef TEMPLATE_IMPL
|
||||
#define TEMPLATE_IMPL(type) \
|
||||
type result = 0; int sign, flag = 0; signed char sym; if (size) *size = 0; \
|
||||
if (base != 0 && (base < 2 || base > 36)) { return 0; } \
|
||||
skipSpace(&string, size); handleSign(&string, size, &sign); \
|
||||
guessBase(&string, size, &base); while(*string) { sym = *(string++); \
|
||||
sym = lookup[(unsigned int)sym]; if (sym >= base || sym == -1) { break; } \
|
||||
if (size) { (*size)++; } result = result * base + sym; flag = 1; } \
|
||||
if (!result && !flag && size) { *size = 0; } return result * sign;
|
||||
|
||||
|
||||
int8_t BH_StringToInt8s(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(int8_t)
|
||||
int8_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +173,8 @@ int16_t BH_StringToInt16s(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(int16_t)
|
||||
int16_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +182,8 @@ int32_t BH_StringToInt32s(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(int32_t)
|
||||
int32_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +191,8 @@ int64_t BH_StringToInt64s(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(int64_t)
|
||||
int64_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +200,8 @@ uint8_t BH_StringToInt8u(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(uint8_t)
|
||||
uint8_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +209,8 @@ uint16_t BH_StringToInt16u(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(uint16_t)
|
||||
uint16_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +218,8 @@ uint32_t BH_StringToInt32u(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(uint32_t)
|
||||
uint32_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
@@ -227,8 +227,6 @@ uint64_t BH_StringToInt64u(const char *string,
|
||||
size_t *size,
|
||||
int base)
|
||||
{
|
||||
TEMPLATE_IMPL(uint64_t)
|
||||
uint64_t result;
|
||||
#include "FromInt.inl"
|
||||
}
|
||||
|
||||
|
||||
#undef TEMPLATE_IMPL
|
||||
|
||||
37
src/String/ToIntS.inl
Normal file
37
src/String/ToIntS.inl
Normal file
@@ -0,0 +1,37 @@
|
||||
char tmp[sizeof(value) * CHAR_BIT + 2];
|
||||
char *current, *end;
|
||||
int sign;
|
||||
|
||||
end = tmp + sizeof(tmp);
|
||||
current = end;
|
||||
sign = 0;
|
||||
|
||||
/* Check for sign */
|
||||
if (value < 0)
|
||||
{
|
||||
sign = 1;
|
||||
value = -value;
|
||||
}
|
||||
|
||||
/* Fill buffer from the end */
|
||||
*(--current) = 0;
|
||||
while (value)
|
||||
{
|
||||
*(--current) = digits[value % base];
|
||||
value /= base;
|
||||
}
|
||||
|
||||
/* Append sign */
|
||||
if (sign)
|
||||
*(--current) = '-';
|
||||
|
||||
/* Check that string have space for the result */
|
||||
if (size < (size_t)(end - current))
|
||||
return BH_ERROR;
|
||||
|
||||
/* Copy data */
|
||||
memcpy(string, current, end - current);
|
||||
if (actual)
|
||||
*actual = end - current;
|
||||
|
||||
return BH_OK;
|
||||
23
src/String/ToIntU.inl
Normal file
23
src/String/ToIntU.inl
Normal file
@@ -0,0 +1,23 @@
|
||||
char tmp[sizeof(value) * CHAR_BIT + 1];
|
||||
char *current, *end;
|
||||
end = tmp + sizeof(tmp);
|
||||
current = end;
|
||||
|
||||
/* Fill buffer from the end */
|
||||
*(--current) = 0;
|
||||
while (value)
|
||||
{
|
||||
*(--current) = digits[value % base];
|
||||
value /= base;
|
||||
}
|
||||
|
||||
/* Check that string have space for the result */
|
||||
if (size < (size_t)(end - current))
|
||||
return BH_ERROR;
|
||||
|
||||
/* Copy data */
|
||||
memcpy(string, current, end - current);
|
||||
if (actual)
|
||||
*actual = end - current;
|
||||
|
||||
return BH_OK;
|
||||
@@ -13,16 +13,14 @@ static int compareString(double value,
|
||||
int precision,
|
||||
const char *ref)
|
||||
{
|
||||
char str[2000];
|
||||
int result;
|
||||
char *str;
|
||||
|
||||
str = BH_StringFromDouble(value, format, precision);
|
||||
BH_VERIFY(BH_StringFromDouble(str, 2000, value, format, precision, NULL) == BH_OK);
|
||||
result = strcmp(str, ref);
|
||||
if (result)
|
||||
printf("Value: %.17g\tReference: %s\tGot: %s\n", value, ref, str);
|
||||
|
||||
BH_StringFree(str);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -31,15 +29,13 @@ static int roundtripString(double value,
|
||||
int format)
|
||||
{
|
||||
double result;
|
||||
char *str;
|
||||
char str[2000];
|
||||
|
||||
str = BH_StringFromDouble(value, format, -1);
|
||||
BH_VERIFY(BH_StringFromDouble(str, 2000, value, format, -1, NULL) == BH_OK);
|
||||
result = BH_StringToDouble(str, NULL);
|
||||
if (result != value)
|
||||
printf("Value: %.17g\tGot: %.17g\tStr: %s\n", value, result, str);
|
||||
|
||||
BH_StringFree(str);
|
||||
|
||||
return result != value;
|
||||
}
|
||||
|
||||
@@ -267,7 +263,7 @@ BH_UNIT_TEST(ShortestRoundTrip)
|
||||
|
||||
BH_UNIT_TEST(Parity)
|
||||
{
|
||||
char buffer[16], output[2000];
|
||||
char buffer[2000], output[2000];
|
||||
uint64_t frac;
|
||||
double value;
|
||||
int i, j, k;
|
||||
@@ -285,18 +281,15 @@ BH_UNIT_TEST(Parity)
|
||||
|
||||
for (k = 0; k < 18; k++)
|
||||
{
|
||||
char *str;
|
||||
|
||||
sprintf(buffer, "%%.%dg", k);
|
||||
str = BH_StringFromDouble(value, 'g', k);
|
||||
sprintf(output, buffer, value);
|
||||
BH_VERIFY(BH_StringFromDouble(buffer, 2000, value, 'g', k, NULL) == BH_OK);
|
||||
|
||||
if (strcmp(str, output))
|
||||
if (strcmp(buffer, output))
|
||||
{
|
||||
printf("(%.17g) (%d) %s vs %s\n", value, k, str, output);
|
||||
printf("(%.17g) (%d) %s vs %s\n", value, k, buffer, output);
|
||||
BH_FAIL("Strings aren't equal");
|
||||
}
|
||||
BH_StringFree(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,48 +4,40 @@
|
||||
|
||||
BH_UNIT_TEST(Int8)
|
||||
{
|
||||
char *str;
|
||||
char str[9];
|
||||
size_t size;
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8s(-13, 16));
|
||||
BH_VERIFY(BH_StringFromInt8s(str, 9, -13, 16, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8s(str, &size, 16) == -13);
|
||||
BH_VERIFY(size == 2);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8s(-13, 10));
|
||||
BH_VERIFY(BH_StringFromInt8s(str, 9, -13, 10, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8s(str, &size, 10) == -13);
|
||||
BH_VERIFY(size == 3);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8s(-13, 8));
|
||||
BH_VERIFY(BH_StringFromInt8s(str, 9, -13, 8, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8s(str, &size, 8) == -13);
|
||||
BH_VERIFY(size == 3);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8s(-13, 2));
|
||||
BH_VERIFY(BH_StringFromInt8s(str, 9, -13, 2, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8s(str, &size, 2) == -13);
|
||||
BH_VERIFY(size == 5);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8u(200, 16));
|
||||
BH_VERIFY(BH_StringFromInt8u(str, 9, 200, 16, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8u(str, &size, 16) == 200);
|
||||
BH_VERIFY(size == 2);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8u(200, 10));
|
||||
BH_VERIFY(BH_StringFromInt8u(str, 9, 200, 10, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8u(str, &size, 10) == 200);
|
||||
BH_VERIFY(size == 3);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8u(200, 8));
|
||||
BH_VERIFY(BH_StringFromInt8u(str, 9, 200, 8, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8u(str, &size, 8) == 200);
|
||||
BH_VERIFY(size == 3);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt8u(200, 2));
|
||||
BH_VERIFY(BH_StringFromInt8u(str, 9, 200, 2, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt8u(str, &size, 2) == 200);
|
||||
BH_VERIFY(size == 8);
|
||||
BH_StringFree(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -53,48 +45,40 @@ BH_UNIT_TEST(Int8)
|
||||
|
||||
BH_UNIT_TEST(Int16)
|
||||
{
|
||||
char *str;
|
||||
char str[17];
|
||||
size_t size;
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16s(-1234, 16));
|
||||
BH_VERIFY(BH_StringFromInt16s(str, 17, -1234, 16, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16s(str, &size, 16) == -1234);
|
||||
BH_VERIFY(size == 4);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16s(-1234, 10));
|
||||
BH_VERIFY(BH_StringFromInt16s(str, 17, -1234, 10, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16s(str, &size, 10) == -1234);
|
||||
BH_VERIFY(size == 5);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16s(-1234, 8));
|
||||
BH_VERIFY(BH_StringFromInt16s(str, 17, -1234, 8, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16s(str, &size, 8) == -1234);
|
||||
BH_VERIFY(size == 5);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16s(-1234, 2));
|
||||
BH_VERIFY(BH_StringFromInt16s(str, 17, -1234, 2, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16s(str, &size, 2) == -1234);
|
||||
BH_VERIFY(size == 12);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16u(43210, 16));
|
||||
BH_VERIFY(BH_StringFromInt16u(str, 17, 43210, 16, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16u(str, &size, 16) == 43210);
|
||||
BH_VERIFY(size == 4);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16u(43210, 10));
|
||||
BH_VERIFY(BH_StringFromInt16u(str, 17, 43210, 10, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16u(str, &size, 10) == 43210);
|
||||
BH_VERIFY(size == 5);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16u(43210, 8));
|
||||
BH_VERIFY(BH_StringFromInt16u(str, 17, 43210, 8, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16u(str, &size, 8) == 43210);
|
||||
BH_VERIFY(size == 6);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt16u(43210, 2));
|
||||
BH_VERIFY(BH_StringFromInt16u(str, 17, 43210, 2, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt16u(str, &size, 2) == 43210);
|
||||
BH_VERIFY(size == 16);
|
||||
BH_StringFree(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -102,48 +86,40 @@ BH_UNIT_TEST(Int16)
|
||||
|
||||
BH_UNIT_TEST(Int32)
|
||||
{
|
||||
char *str;
|
||||
char str[33];
|
||||
size_t size;
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 16));
|
||||
BH_VERIFY(BH_StringFromInt32s(str, 33, -1234567890l, 16, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32s(str, &size, 16) == -1234567890l);
|
||||
BH_VERIFY(size == 9);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 10));
|
||||
BH_VERIFY(BH_StringFromInt32s(str, 33, -1234567890l, 10, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32s(str, &size, 10) == -1234567890l);
|
||||
BH_VERIFY(size == 11);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 8));
|
||||
BH_VERIFY(BH_StringFromInt32s(str, 33, -1234567890l, 8, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32s(str, &size, 8) == -1234567890l);
|
||||
BH_VERIFY(size == 12);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32s(-1234567890l, 2));
|
||||
BH_VERIFY(BH_StringFromInt32s(str, 33, -1234567890l, 2, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32s(str, &size, 2) == -1234567890l);
|
||||
BH_VERIFY(size == 32);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 16));
|
||||
BH_VERIFY(BH_StringFromInt32u(str, 33, 3456789012ul, 16, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32u(str, &size, 16) == 3456789012ul);
|
||||
BH_VERIFY(size == 8);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 10));
|
||||
BH_VERIFY(BH_StringFromInt32u(str, 33, 3456789012ul, 10, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32u(str, &size, 10) == 3456789012ul);
|
||||
BH_VERIFY(size == 10);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 8));
|
||||
BH_VERIFY(BH_StringFromInt32u(str, 33, 3456789012ul, 8, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32u(str, &size, 8) == 3456789012ul);
|
||||
BH_VERIFY(size == 11);
|
||||
BH_StringFree(str);
|
||||
|
||||
BH_VERIFY(str = BH_StringFromInt32u(3456789012ul, 2));
|
||||
BH_VERIFY(BH_StringFromInt32u(str, 33, 3456789012ul, 2, NULL) == BH_OK);
|
||||
BH_VERIFY(BH_StringToInt32u(str, &size, 2) == 3456789012ul);
|
||||
BH_VERIFY(size == 32);
|
||||
BH_StringFree(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user