142 lines
2.6 KiB
C
142 lines
2.6 KiB
C
|
|
#include <assert.h>
|
|
|
|
#include <debug.h>
|
|
|
|
#include <misc/wcindex.h>
|
|
|
|
#include <extern/gmp/mini-mpq.h>
|
|
|
|
#include "struct.h"
|
|
#include "set_str.h"
|
|
|
|
void number_set_str(
|
|
struct number* this,
|
|
const wchar_t* text)
|
|
{
|
|
// "text" might be binary, octal, hexadecimal, or a float.
|
|
// "text" might contain a decimal point. Hopefully just one.
|
|
ENTER;
|
|
|
|
assert(text);
|
|
assert(*text);
|
|
|
|
dpvws(text);
|
|
|
|
mpq_t base;
|
|
|
|
mpq_init(base);
|
|
|
|
const wchar_t* start = text;
|
|
|
|
if (*start != L'0')
|
|
{
|
|
mpq_set_ui(base, 10, 1);
|
|
}
|
|
else switch (start[1])
|
|
{
|
|
case L'x':
|
|
mpq_set_ui(base, 16, 1), start += 2;
|
|
break;
|
|
|
|
case L'b':
|
|
mpq_set_ui(base, 2, 1), start += 2;
|
|
break;
|
|
|
|
default:
|
|
mpq_set_ui(base, 8, 1);
|
|
break;
|
|
}
|
|
|
|
mpq_ptr result = this->number;
|
|
|
|
// initalize result to 0.
|
|
mpq_set_ui(result, 0, 1);
|
|
|
|
const wchar_t* dot = wcindex(text, L'.');
|
|
|
|
// parse whole number:
|
|
{
|
|
const wchar_t* end = dot ? dot - 1 : start + wcslen(start) - 1;
|
|
|
|
assert(start <= end);
|
|
|
|
mpq_t multiplier, digit;
|
|
|
|
mpq_init(multiplier);
|
|
mpq_init(digit);
|
|
|
|
mpq_set_ui(multiplier, 1, 1);
|
|
|
|
while (start <= end)
|
|
{
|
|
wchar_t e = *end--;
|
|
|
|
dpvc(e);
|
|
|
|
assert(e >= L'0');
|
|
|
|
mpq_set_ui(digit, (unsigned) (e - '0'), 1);
|
|
|
|
mpq_mul(digit, digit, multiplier);
|
|
|
|
mpq_add(result, result, digit);
|
|
|
|
mpq_mul(multiplier, multiplier, base);
|
|
}
|
|
|
|
mpq_clear(multiplier);
|
|
mpq_clear(digit);
|
|
}
|
|
|
|
if (dot)
|
|
{
|
|
const wchar_t* moving = dot + 1;
|
|
|
|
dpvws(moving);
|
|
|
|
mpq_t multiplier, digit;
|
|
|
|
mpq_init(multiplier);
|
|
mpq_init(digit);
|
|
|
|
mpq_set_ui(multiplier, 1, 1);
|
|
|
|
mpq_div(multiplier, multiplier, base);
|
|
|
|
while (*moving)
|
|
{
|
|
wchar_t e = *moving++;
|
|
|
|
dpvwc(e);
|
|
|
|
assert(e >= '0');
|
|
|
|
mpq_set_ui(digit, (unsigned) (e - '0'), 1);
|
|
|
|
mpq_mul(digit, digit, multiplier);
|
|
|
|
mpq_add(result, result, digit);
|
|
|
|
mpq_div(multiplier, multiplier, base);
|
|
}
|
|
|
|
mpq_clear(multiplier);
|
|
mpq_clear(digit);
|
|
}
|
|
|
|
mpq_clear(base);
|
|
|
|
EXIT;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|