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/Util.c
|
||||||
src/String/Int.c
|
src/String/Int.c
|
||||||
src/String/Float.c
|
src/String/Float.c
|
||||||
src/String/Core.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(BH_HEADER
|
set(BH_HEADER
|
||||||
@@ -107,7 +106,6 @@ set(BH_HEADER
|
|||||||
include/BH/Queue.h
|
include/BH/Queue.h
|
||||||
include/BH/Util.h
|
include/BH/Util.h
|
||||||
include/BH/Thread.h
|
include/BH/Thread.h
|
||||||
include
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(BH_SOURCE_DUMMY
|
set(BH_SOURCE_DUMMY
|
||||||
|
|||||||
@@ -6,27 +6,9 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees dynamically allocated \a string.
|
* 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
|
||||||
* \param string String pointer
|
* length (if it's provided).
|
||||||
*/
|
|
||||||
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 supported:
|
* Formats supported:
|
||||||
* - Scientific or fixed format ('g' or 'G')
|
* - 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.
|
* This function follows IEEE 754 round to even to break ties during rounding.
|
||||||
*
|
*
|
||||||
|
* \param string String
|
||||||
|
* \param size String size
|
||||||
* \param value Value
|
* \param value Value
|
||||||
* \param format Format
|
* \param format Format
|
||||||
* \param precision Precision
|
* \param precision Precision
|
||||||
|
* \param actual Written size (optional)
|
||||||
*
|
*
|
||||||
* \return On success, returns new string pointer.
|
* \return On success, returns zero.
|
||||||
* \return On failure, returns NULL pointer.
|
* \return On failure, returns error code.
|
||||||
*/
|
*/
|
||||||
char *BH_StringFromDouble(double value,
|
int BH_StringFromDouble(char *string,
|
||||||
|
size_t size,
|
||||||
|
double value,
|
||||||
char format,
|
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);
|
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
|
* Reads \a string containing value in specified \a base, optionally reports
|
||||||
* \a size amount of characters consumed and returns the result value.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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.
|
* \a size amount of characters consumed and returns the result value.
|
||||||
*
|
*
|
||||||
* If base is 0, function will automaticly detect input base by the prefix:
|
* 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 8 if prefix is 0
|
||||||
* - Base 16 if prefix is 0x
|
* - Base 16 if prefix is 0x
|
||||||
* - Base 10 in other cases
|
* - 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
|
#define RELATIVE 2
|
||||||
|
|
||||||
|
|
||||||
|
struct Buffer
|
||||||
|
{
|
||||||
|
char *data;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DragonState
|
struct DragonState
|
||||||
{
|
{
|
||||||
BInt r;
|
BInt r;
|
||||||
@@ -100,9 +107,8 @@ static void dragonFixup(struct DragonState *state,
|
|||||||
|
|
||||||
|
|
||||||
static void dragonRound(struct DragonState *state,
|
static void dragonRound(struct DragonState *state,
|
||||||
char *buffer,
|
struct Buffer *buffer,
|
||||||
int *k,
|
int *k,
|
||||||
int *size,
|
|
||||||
int high,
|
int high,
|
||||||
int low,
|
int low,
|
||||||
char s)
|
char s)
|
||||||
@@ -110,7 +116,7 @@ static void dragonRound(struct DragonState *state,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Preconditions */
|
/* Preconditions */
|
||||||
assert(state != NULL && buffer != NULL && k != NULL && size != NULL);
|
assert(state != NULL && buffer != NULL && k != NULL);
|
||||||
assert(s >= '0' && s <= '9');
|
assert(s >= '0' && s <= '9');
|
||||||
|
|
||||||
/* Check if rounding up required */
|
/* Check if rounding up required */
|
||||||
@@ -126,14 +132,14 @@ static void dragonRound(struct DragonState *state,
|
|||||||
/* Perform rounding up */
|
/* Perform rounding up */
|
||||||
if (!low)
|
if (!low)
|
||||||
{
|
{
|
||||||
for (i = *size; i && buffer[i - 1] == '9'; i--)
|
for (i = buffer->size; i && buffer->data[i - 1] == '9'; i--)
|
||||||
buffer[i - 1] = '0';
|
buffer->data[i - 1] = '0';
|
||||||
|
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
buffer[i - 1]++;
|
buffer->data[i - 1]++;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer[0] = '1';
|
buffer->data[0] = '1';
|
||||||
(*k)++;
|
(*k)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,8 +149,7 @@ static void dragonRound(struct DragonState *state,
|
|||||||
static void dragon(double value,
|
static void dragon(double value,
|
||||||
int precision,
|
int precision,
|
||||||
int mode,
|
int mode,
|
||||||
char *buffer,
|
struct Buffer *buffer,
|
||||||
int *size,
|
|
||||||
int *k)
|
int *k)
|
||||||
{
|
{
|
||||||
struct DragonState state;
|
struct DragonState state;
|
||||||
@@ -153,17 +158,17 @@ static void dragon(double value,
|
|||||||
char s;
|
char s;
|
||||||
|
|
||||||
/* Preconditions */
|
/* Preconditions */
|
||||||
assert(buffer != NULL && size != NULL && k != NULL);
|
assert(buffer != NULL && k != NULL);
|
||||||
assert(mode == NORMAL || mode == ABSOLUTE || mode == RELATIVE);
|
assert(mode == NORMAL || mode == ABSOLUTE || mode == RELATIVE);
|
||||||
assert(precision >= 0);
|
assert(precision >= 0);
|
||||||
|
|
||||||
*k = 0;
|
*k = 0;
|
||||||
*size = low = high = 0;
|
buffer->size = low = high = 0;
|
||||||
|
|
||||||
/* If value is zero - do nothing */
|
/* If value is zero - do nothing */
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
buffer[(*size)++] = '0';
|
buffer->data[buffer->size++] = '0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +204,7 @@ static void dragon(double value,
|
|||||||
s = '0';
|
s = '0';
|
||||||
if (state.tmp[0].size)
|
if (state.tmp[0].size)
|
||||||
s += state.tmp[0].data[0];
|
s += state.tmp[0].data[0];
|
||||||
buffer[(*size)++] = s;
|
buffer->data[buffer->size++] = s;
|
||||||
|
|
||||||
if (mode == NORMAL)
|
if (mode == NORMAL)
|
||||||
{
|
{
|
||||||
@@ -210,38 +215,40 @@ static void dragon(double value,
|
|||||||
BIntAdd(&state.tmp[1], &state.mp, &state.tmp[3]);
|
BIntAdd(&state.tmp[1], &state.mp, &state.tmp[3]);
|
||||||
low = BIntCompare(&state.tmp[1], &state.mm) < 0;
|
low = BIntCompare(&state.tmp[1], &state.mm) < 0;
|
||||||
high = BIntCompare(&state.tmp[3], &state.tmp[2]) > 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;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!state.r.size || state.k == state.cutoff || *size >= BUFSIZE)
|
if (!state.r.size || state.k == state.cutoff || buffer->size >= BUFSIZE)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round digits if required */
|
/* 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 precision,
|
||||||
int sign,
|
int sign,
|
||||||
int k,
|
int k,
|
||||||
int size)
|
size_t *actual)
|
||||||
{
|
{
|
||||||
char *result, *current;
|
char *current;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Preconditions */
|
/* Preconditions */
|
||||||
assert(buffer != NULL);
|
assert(output != NULL && input != NULL);
|
||||||
assert(size < BUFSIZE);
|
assert(input->size < BUFSIZE);
|
||||||
|
assert(sign == 0 || sign == 1);
|
||||||
|
|
||||||
result = malloc(MAX(0, k) + 5 + sign + precision);
|
/* Check that output buffer has enough space */
|
||||||
current = result;
|
current = output->data;
|
||||||
if (!result)
|
if (output->size < (size_t)(MAX(0, k) + 4 + precision))
|
||||||
return NULL;
|
return BH_ERROR;
|
||||||
|
|
||||||
/* Add sign */
|
/* Add sign */
|
||||||
if (sign)
|
if (sign)
|
||||||
@@ -262,8 +269,8 @@ static char *formatF(char *buffer,
|
|||||||
/* Add digits */
|
/* Add digits */
|
||||||
for (i = 0; k >= -precision; i++, k--)
|
for (i = 0; k >= -precision; i++, k--)
|
||||||
{
|
{
|
||||||
if (i < size)
|
if (i < (int)input->size)
|
||||||
*(current++) = buffer[i];
|
*(current++) = input->data[i];
|
||||||
else
|
else
|
||||||
*(current++) = '0';
|
*(current++) = '0';
|
||||||
|
|
||||||
@@ -272,38 +279,41 @@ static char *formatF(char *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*(current++) = 0;
|
*(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 precision,
|
||||||
int sign,
|
int sign,
|
||||||
int k,
|
int k,
|
||||||
int size,
|
int upper,
|
||||||
int upper)
|
size_t *actual)
|
||||||
{
|
{
|
||||||
char *result, *current;
|
char *current;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Preconditions */
|
/* Preconditions */
|
||||||
assert(buffer != NULL);
|
assert(input != NULL && output != NULL);
|
||||||
assert(size < BUFSIZE);
|
assert(input->size < BUFSIZE);
|
||||||
assert(sign == 0 || sign == 1);
|
assert(sign == 0 || sign == 1);
|
||||||
assert(upper == 0 || upper == 1);
|
assert(upper == 0 || upper == 1);
|
||||||
|
|
||||||
result = malloc(9 + sign + precision);
|
current = output->data;
|
||||||
current = result;
|
if (output->size < (size_t)(9 + precision))
|
||||||
if (!result)
|
return BH_ERROR;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Add sign and digits */
|
/* Add sign and digits */
|
||||||
if (sign)
|
if (sign)
|
||||||
*(current++) = '-';
|
*(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)
|
if (i == 0 && precision > 0)
|
||||||
*(current++) = '.';
|
*(current++) = '.';
|
||||||
}
|
}
|
||||||
@@ -323,106 +333,137 @@ static char *formatE(char *buffer,
|
|||||||
*(current++) = '+';
|
*(current++) = '+';
|
||||||
|
|
||||||
/* Convert exponent to digits and add them */
|
/* 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;
|
k = k / 10;
|
||||||
}
|
}
|
||||||
for (; size; size--)
|
for (; i; i--)
|
||||||
*(current++) = buffer[size - 1];
|
*(current++) = input->data[i - 1];
|
||||||
|
|
||||||
*(current++) = 0;
|
*(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 precision,
|
||||||
int sign)
|
int sign,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
char buffer[BUFSIZE];
|
char buffer[BUFSIZE];
|
||||||
int size, k;
|
struct Buffer input;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
input.data = buffer;
|
||||||
|
input.size = 0;
|
||||||
|
|
||||||
/* Call Dragon4 and format the digits */
|
/* Call Dragon4 and format the digits */
|
||||||
if (precision < 0)
|
if (precision < 0)
|
||||||
dragon(value, 0, NORMAL, buffer, &size, &k);
|
dragon(value, 0, NORMAL, &input, &k);
|
||||||
else
|
else
|
||||||
dragon(value, precision, ABSOLUTE, buffer, &size, &k);
|
dragon(value, precision, ABSOLUTE, &input, &k);
|
||||||
|
|
||||||
if (precision < 0)
|
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 precision,
|
||||||
int upper,
|
int upper,
|
||||||
int sign)
|
int sign,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
char buffer[BUFSIZE];
|
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 */
|
/* Adjust precision and call Dragon4 to generate digits */
|
||||||
if (precision < 0)
|
if (precision < 0)
|
||||||
dragon(value, 0, NORMAL, buffer, &size, &k);
|
dragon(value, 0, NORMAL, &input, &k);
|
||||||
else
|
else
|
||||||
dragon(value, (precision + 1), RELATIVE, buffer, &size, &k);
|
dragon(value, (precision + 1), RELATIVE, &input, &k);
|
||||||
|
|
||||||
if (precision < 0)
|
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 precision,
|
||||||
int upper,
|
int upper,
|
||||||
int sign)
|
int sign,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
char buffer[BUFSIZE];
|
char buffer[BUFSIZE];
|
||||||
int size, k, fixed;
|
struct Buffer input;
|
||||||
|
int k, fixed;
|
||||||
|
|
||||||
|
input.data = buffer;
|
||||||
|
input.size = 0;
|
||||||
if (precision == 0)
|
if (precision == 0)
|
||||||
precision = 1;
|
precision = 1;
|
||||||
|
|
||||||
/* Call Dragon4 to generate digits */
|
/* Call Dragon4 to generate digits */
|
||||||
if (precision < 0)
|
if (precision < 0)
|
||||||
{
|
{
|
||||||
dragon(value, 0, NORMAL, buffer, &size, &k);
|
dragon(value, 0, NORMAL, &input, &k);
|
||||||
fixed = k >= -4 && k <= (size - 1);
|
fixed = k >= -4 && k <= (int)(input.size - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dragon(value, precision, RELATIVE, buffer, &size, &k);
|
dragon(value, precision, RELATIVE, &input, &k);
|
||||||
fixed = k >= -4 && k < precision;
|
fixed = k >= -4 && k < precision;
|
||||||
|
|
||||||
/* Remove trailing zeros and adjust 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)
|
if (fixed)
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
precision = MAX(0, size - 1);
|
precision = MAX(0, (int)input.size - 1);
|
||||||
return formatE(buffer, precision, sign, k, size, upper);
|
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,
|
char format,
|
||||||
int precision)
|
int precision,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
static const char *infStrings[] = { "inf", "-inf", "INF", "-INF" };
|
static const char *infStrings[] = { "inf", "-inf", "INF", "-INF" };
|
||||||
static const char *nanStrings[] = { "nan", "NAN" };
|
static const char *nanStrings[] = { "nan", "NAN" };
|
||||||
int sign, type, upper;
|
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);
|
type = BH_ClassifyDouble(value);
|
||||||
upper = isupper(format) > 0;
|
upper = isupper(format) > 0;
|
||||||
@@ -433,16 +474,27 @@ char *BH_StringFromDouble(double value,
|
|||||||
|
|
||||||
/* Handle NaN and Inf */
|
/* Handle NaN and Inf */
|
||||||
if (type == BH_FP_INFINITE)
|
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)
|
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')
|
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')
|
else if (format == 'e' || format == 'E')
|
||||||
return generateE(value, precision, upper, sign);
|
return generateE(&output, value, precision, upper, sign, actual);
|
||||||
else
|
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;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle zero input */
|
/* Zero or exponent too low */
|
||||||
if (count == 0)
|
if (!count || e < -329)
|
||||||
{
|
|
||||||
if (sign)
|
|
||||||
return -0.0;
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exponent too low */
|
|
||||||
if (e < -329)
|
|
||||||
{
|
{
|
||||||
if (sign)
|
if (sign)
|
||||||
return -0.0;
|
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 \
|
int BH_StringFromInt8s(char *string,
|
||||||
char tmp[sizeof(value) * CHAR_BIT + 1]; char *current, *end, *result; \
|
size_t size,
|
||||||
int sign; end = tmp + sizeof(tmp); current = end; sign = 0; \
|
int8_t value,
|
||||||
if (value < 0) { sign = 1; value = -value; } while (value) { \
|
int base,
|
||||||
*(--current) = digits[value % base]; value /= base; } \
|
size_t *actual)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
TEMPLATE_IMPL
|
#include "ToIntS.inl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *BH_StringFromInt16s(int16_t value,
|
int BH_StringFromInt16s(char *string,
|
||||||
int base)
|
size_t size,
|
||||||
|
int16_t value,
|
||||||
|
int base,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
TEMPLATE_IMPL
|
#include "ToIntS.inl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *BH_StringFromInt32s(int32_t value,
|
int BH_StringFromInt32s(char *string,
|
||||||
int base)
|
size_t size,
|
||||||
|
int32_t value,
|
||||||
|
int base,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
TEMPLATE_IMPL
|
#include "ToIntS.inl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *BH_StringFromInt64s(int64_t value,
|
int BH_StringFromInt64s(char *string,
|
||||||
int base)
|
size_t size,
|
||||||
|
int64_t value,
|
||||||
|
int base,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
TEMPLATE_IMPL
|
#include "ToIntS.inl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#undef TEMPLATE_IMPL
|
int BH_StringFromInt8u(char *string,
|
||||||
#define TEMPLATE_IMPL \
|
size_t size,
|
||||||
char tmp[sizeof(value) * CHAR_BIT]; char *current, *end, *result; \
|
uint8_t value,
|
||||||
end = tmp + sizeof(tmp); current = end; while (value) { \
|
int base,
|
||||||
*(--current) = digits[value % base]; value /= base; } \
|
size_t *actual)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
TEMPLATE_IMPL
|
#include "ToIntU.inl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *BH_StringFromInt16u(uint16_t value,
|
int BH_StringFromInt16u(char *string,
|
||||||
int base)
|
size_t size,
|
||||||
|
uint16_t value,
|
||||||
|
int base,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
TEMPLATE_IMPL
|
#include "ToIntU.inl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *BH_StringFromInt32u(uint32_t value,
|
int BH_StringFromInt32u(char *string,
|
||||||
int base)
|
size_t size,
|
||||||
|
uint32_t value,
|
||||||
|
int base,
|
||||||
|
size_t *actual)
|
||||||
{
|
{
|
||||||
TEMPLATE_IMPL
|
#include "ToIntU.inl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *BH_StringFromInt64u(uint64_t value,
|
int BH_StringFromInt64u(char *string,
|
||||||
int base)
|
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,
|
int8_t BH_StringToInt8s(const char *string,
|
||||||
size_t *size,
|
size_t *size,
|
||||||
int base)
|
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,
|
size_t *size,
|
||||||
int base)
|
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,
|
size_t *size,
|
||||||
int base)
|
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,
|
size_t *size,
|
||||||
int base)
|
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,
|
size_t *size,
|
||||||
int base)
|
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,
|
size_t *size,
|
||||||
int base)
|
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,
|
size_t *size,
|
||||||
int base)
|
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,
|
size_t *size,
|
||||||
int base)
|
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,
|
int precision,
|
||||||
const char *ref)
|
const char *ref)
|
||||||
{
|
{
|
||||||
|
char str[2000];
|
||||||
int result;
|
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);
|
result = strcmp(str, ref);
|
||||||
if (result)
|
if (result)
|
||||||
printf("Value: %.17g\tReference: %s\tGot: %s\n", value, ref, str);
|
printf("Value: %.17g\tReference: %s\tGot: %s\n", value, ref, str);
|
||||||
|
|
||||||
BH_StringFree(str);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,15 +29,13 @@ static int roundtripString(double value,
|
|||||||
int format)
|
int format)
|
||||||
{
|
{
|
||||||
double result;
|
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);
|
result = BH_StringToDouble(str, NULL);
|
||||||
if (result != value)
|
if (result != value)
|
||||||
printf("Value: %.17g\tGot: %.17g\tStr: %s\n", value, result, str);
|
printf("Value: %.17g\tGot: %.17g\tStr: %s\n", value, result, str);
|
||||||
|
|
||||||
BH_StringFree(str);
|
|
||||||
|
|
||||||
return result != value;
|
return result != value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +263,7 @@ BH_UNIT_TEST(ShortestRoundTrip)
|
|||||||
|
|
||||||
BH_UNIT_TEST(Parity)
|
BH_UNIT_TEST(Parity)
|
||||||
{
|
{
|
||||||
char buffer[16], output[2000];
|
char buffer[2000], output[2000];
|
||||||
uint64_t frac;
|
uint64_t frac;
|
||||||
double value;
|
double value;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
@@ -285,18 +281,15 @@ BH_UNIT_TEST(Parity)
|
|||||||
|
|
||||||
for (k = 0; k < 18; k++)
|
for (k = 0; k < 18; k++)
|
||||||
{
|
{
|
||||||
char *str;
|
|
||||||
|
|
||||||
sprintf(buffer, "%%.%dg", k);
|
sprintf(buffer, "%%.%dg", k);
|
||||||
str = BH_StringFromDouble(value, 'g', k);
|
|
||||||
sprintf(output, buffer, value);
|
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_FAIL("Strings aren't equal");
|
||||||
}
|
}
|
||||||
BH_StringFree(str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,48 +4,40 @@
|
|||||||
|
|
||||||
BH_UNIT_TEST(Int8)
|
BH_UNIT_TEST(Int8)
|
||||||
{
|
{
|
||||||
char *str;
|
char str[9];
|
||||||
size_t size;
|
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(BH_StringToInt8s(str, &size, 16) == -13);
|
||||||
BH_VERIFY(size == 2);
|
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(BH_StringToInt8s(str, &size, 10) == -13);
|
||||||
BH_VERIFY(size == 3);
|
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(BH_StringToInt8s(str, &size, 8) == -13);
|
||||||
BH_VERIFY(size == 3);
|
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(BH_StringToInt8s(str, &size, 2) == -13);
|
||||||
BH_VERIFY(size == 5);
|
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(BH_StringToInt8u(str, &size, 16) == 200);
|
||||||
BH_VERIFY(size == 2);
|
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(BH_StringToInt8u(str, &size, 10) == 200);
|
||||||
BH_VERIFY(size == 3);
|
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(BH_StringToInt8u(str, &size, 8) == 200);
|
||||||
BH_VERIFY(size == 3);
|
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(BH_StringToInt8u(str, &size, 2) == 200);
|
||||||
BH_VERIFY(size == 8);
|
BH_VERIFY(size == 8);
|
||||||
BH_StringFree(str);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -53,48 +45,40 @@ BH_UNIT_TEST(Int8)
|
|||||||
|
|
||||||
BH_UNIT_TEST(Int16)
|
BH_UNIT_TEST(Int16)
|
||||||
{
|
{
|
||||||
char *str;
|
char str[17];
|
||||||
size_t size;
|
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(BH_StringToInt16s(str, &size, 16) == -1234);
|
||||||
BH_VERIFY(size == 4);
|
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(BH_StringToInt16s(str, &size, 10) == -1234);
|
||||||
BH_VERIFY(size == 5);
|
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(BH_StringToInt16s(str, &size, 8) == -1234);
|
||||||
BH_VERIFY(size == 5);
|
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(BH_StringToInt16s(str, &size, 2) == -1234);
|
||||||
BH_VERIFY(size == 12);
|
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(BH_StringToInt16u(str, &size, 16) == 43210);
|
||||||
BH_VERIFY(size == 4);
|
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(BH_StringToInt16u(str, &size, 10) == 43210);
|
||||||
BH_VERIFY(size == 5);
|
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(BH_StringToInt16u(str, &size, 8) == 43210);
|
||||||
BH_VERIFY(size == 6);
|
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(BH_StringToInt16u(str, &size, 2) == 43210);
|
||||||
BH_VERIFY(size == 16);
|
BH_VERIFY(size == 16);
|
||||||
BH_StringFree(str);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -102,48 +86,40 @@ BH_UNIT_TEST(Int16)
|
|||||||
|
|
||||||
BH_UNIT_TEST(Int32)
|
BH_UNIT_TEST(Int32)
|
||||||
{
|
{
|
||||||
char *str;
|
char str[33];
|
||||||
size_t size;
|
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(BH_StringToInt32s(str, &size, 16) == -1234567890l);
|
||||||
BH_VERIFY(size == 9);
|
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(BH_StringToInt32s(str, &size, 10) == -1234567890l);
|
||||||
BH_VERIFY(size == 11);
|
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(BH_StringToInt32s(str, &size, 8) == -1234567890l);
|
||||||
BH_VERIFY(size == 12);
|
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(BH_StringToInt32s(str, &size, 2) == -1234567890l);
|
||||||
BH_VERIFY(size == 32);
|
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(BH_StringToInt32u(str, &size, 16) == 3456789012ul);
|
||||||
BH_VERIFY(size == 8);
|
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(BH_StringToInt32u(str, &size, 10) == 3456789012ul);
|
||||||
BH_VERIFY(size == 10);
|
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(BH_StringToInt32u(str, &size, 8) == 3456789012ul);
|
||||||
BH_VERIFY(size == 11);
|
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(BH_StringToInt32u(str, &size, 2) == 3456789012ul);
|
||||||
BH_VERIFY(size == 32);
|
BH_VERIFY(size == 32);
|
||||||
BH_StringFree(str);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user