mirror of https://git.wuffs.org/MWCC
894 lines
20 KiB
C
894 lines
20 KiB
C
|
#include <MacHeadersMach-O>
|
||
|
#include "CInt64.h"
|
||
|
|
||
|
const CInt64 cint64_negone = {0xFFFFFFFF, 0xFFFFFFFF};
|
||
|
const CInt64 cint64_zero = {0, 0};
|
||
|
const CInt64 cint64_one = {0, 1};
|
||
|
const CInt64 cint64_max = {0x7FFFFFFF, 0xFFFFFFFF};
|
||
|
const CInt64 cint64_min = {0x80000000, 0};
|
||
|
|
||
|
#define SHIFT_LEFT_ONE(a, b) do { a <<= 1; if (b & 0x80000000) { a |= 1; } b <<= 1; } while(0)
|
||
|
|
||
|
void CInt64_Init() {
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Not(CInt64 input) {
|
||
|
CInt64 output;
|
||
|
unsigned char c;
|
||
|
|
||
|
c = (input.a == 0 && input.b == 0);
|
||
|
CInt64_SetLong(&output, c);
|
||
|
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Inv(CInt64 input) {
|
||
|
CInt64 output;
|
||
|
output.a = ~input.a;
|
||
|
output.b = ~input.b;
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Add(CInt64 lhs, CInt64 rhs) {
|
||
|
if (lhs.b & 0x80000000) {
|
||
|
if (rhs.b & 0x80000000) {
|
||
|
lhs.b += rhs.b;
|
||
|
lhs.a += 1;
|
||
|
} else {
|
||
|
lhs.b += rhs.b;
|
||
|
if (!(lhs.b & 0x80000000))
|
||
|
lhs.a += 1;
|
||
|
}
|
||
|
} else {
|
||
|
if (rhs.b & 0x80000000) {
|
||
|
lhs.b += rhs.b;
|
||
|
if (!(lhs.b & 0x80000000))
|
||
|
lhs.a += 1;
|
||
|
} else {
|
||
|
lhs.b += rhs.b;
|
||
|
}
|
||
|
}
|
||
|
lhs.a += rhs.a;
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Neg(CInt64 input) {
|
||
|
CInt64 result;
|
||
|
result = CInt64_Add(CInt64_Inv(input), cint64_one);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Sub(CInt64 lhs, CInt64 rhs) {
|
||
|
lhs = CInt64_Add(lhs, CInt64_Neg(rhs));
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_MulU(CInt64 lhs, CInt64 rhs) {
|
||
|
CInt64 result;
|
||
|
CInt64 work1;
|
||
|
unsigned long aaaa;
|
||
|
unsigned long bbbb;
|
||
|
unsigned long cccc;
|
||
|
unsigned long dddd;
|
||
|
unsigned long eeee;
|
||
|
|
||
|
aaaa = rhs.b;
|
||
|
result.a = result.b = 0;
|
||
|
bbbb = lhs.b;
|
||
|
cccc = rhs.a;
|
||
|
dddd = rhs.b;
|
||
|
|
||
|
while (bbbb != 0) {
|
||
|
if (bbbb & 1) {
|
||
|
work1.a = cccc;
|
||
|
work1.b = dddd;
|
||
|
result = CInt64_Add(result, work1);
|
||
|
}
|
||
|
cccc <<= 1;
|
||
|
if (dddd & 0x80000000)
|
||
|
cccc |= 1;
|
||
|
dddd <<= 1;
|
||
|
bbbb >>= 1;
|
||
|
}
|
||
|
|
||
|
eeee = lhs.a;
|
||
|
while (eeee != 0 && aaaa != 0) {
|
||
|
if (eeee & 1)
|
||
|
result.a += aaaa;
|
||
|
aaaa <<= 1;
|
||
|
eeee >>= 1;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Mul(CInt64 lhs, CInt64 rhs) {
|
||
|
if (CInt64_IsNegative(&rhs)) {
|
||
|
if (CInt64_IsNegative(&lhs)) {
|
||
|
return CInt64_MulU(CInt64_Neg(lhs), CInt64_Neg(rhs));
|
||
|
}
|
||
|
return CInt64_Neg(CInt64_MulU(lhs, CInt64_Neg(rhs)));
|
||
|
}
|
||
|
if (CInt64_IsNegative(&lhs)) {
|
||
|
return CInt64_Neg(CInt64_MulU(CInt64_Neg(lhs), rhs));
|
||
|
}
|
||
|
return CInt64_MulU(lhs, rhs);
|
||
|
}
|
||
|
|
||
|
void CInt64_DivMod(const CInt64 *lhs, const CInt64 *rhs, CInt64 *pDiv, CInt64 *pMod) {
|
||
|
unsigned char bad;
|
||
|
unsigned long workA;
|
||
|
unsigned long workB;
|
||
|
unsigned long leftA;
|
||
|
unsigned long leftB;
|
||
|
unsigned long rightA;
|
||
|
unsigned long rightB;
|
||
|
unsigned long outA;
|
||
|
unsigned long outB;
|
||
|
CInt64 work;
|
||
|
int counter;
|
||
|
|
||
|
bad = (rhs->a == 0) && (rhs->b == 0);
|
||
|
if (!bad) {
|
||
|
workA = 0;
|
||
|
workB = 0;
|
||
|
leftA = lhs->a;
|
||
|
leftB = lhs->b;
|
||
|
rightA = rhs->a;
|
||
|
rightB = rhs->b;
|
||
|
outA = 0;
|
||
|
outB = 0;
|
||
|
counter = 0;
|
||
|
|
||
|
do {
|
||
|
workA <<= 1;
|
||
|
if (workB & 0x80000000)
|
||
|
workA |= 1;
|
||
|
workB <<= 1;
|
||
|
if (leftA & 0x80000000)
|
||
|
workB |= 1;
|
||
|
leftA <<= 1;
|
||
|
if (leftB & 0x80000000)
|
||
|
leftA |= 1;
|
||
|
leftB <<= 1;
|
||
|
|
||
|
outA <<= 1;
|
||
|
if (outB & 0x80000000)
|
||
|
outA |= 1;
|
||
|
outB <<= 1;
|
||
|
|
||
|
if (workA <= rightA) {
|
||
|
if (workA != rightA)
|
||
|
continue;
|
||
|
if (workB < rightB)
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
outB |= 1;
|
||
|
|
||
|
work.a = workA;
|
||
|
work.b = workB;
|
||
|
work = CInt64_Sub(work, *rhs);
|
||
|
workA = work.a;
|
||
|
workB = work.b;
|
||
|
} while (++counter < 64);
|
||
|
|
||
|
if (pDiv) {
|
||
|
pDiv->a = outA;
|
||
|
pDiv->b = outB;
|
||
|
}
|
||
|
if (pMod) {
|
||
|
pMod->a = workA;
|
||
|
pMod->b = workB;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Div(CInt64 lhs, CInt64 rhs) {
|
||
|
CInt64 result;
|
||
|
if (CInt64_IsNegative(&rhs)) {
|
||
|
rhs = CInt64_Neg(rhs);
|
||
|
if (CInt64_IsNegative(&lhs)) {
|
||
|
lhs = CInt64_Neg(lhs);
|
||
|
CInt64_DivMod(&lhs, &rhs, &result, 0);
|
||
|
return result;
|
||
|
} else {
|
||
|
CInt64_DivMod(&lhs, &rhs, &result, 0);
|
||
|
return CInt64_Neg(result);
|
||
|
}
|
||
|
} else {
|
||
|
if (CInt64_IsNegative(&lhs)) {
|
||
|
lhs = CInt64_Neg(lhs);
|
||
|
CInt64_DivMod(&lhs, &rhs, &result, 0);
|
||
|
return CInt64_Neg(result);
|
||
|
} else {
|
||
|
CInt64_DivMod(&lhs, &rhs, &result, 0);
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_DivU(CInt64 lhs, CInt64 rhs) {
|
||
|
CInt64 result;
|
||
|
CInt64_DivMod(&lhs, &rhs, &result, 0);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Mod(CInt64 lhs, CInt64 rhs) {
|
||
|
CInt64 result;
|
||
|
if (CInt64_IsNegative(&lhs)) {
|
||
|
lhs = CInt64_Neg(lhs);
|
||
|
if (CInt64_IsNegative(&rhs))
|
||
|
rhs = CInt64_Neg(rhs);
|
||
|
CInt64_DivMod(&lhs, &rhs, 0, &result);
|
||
|
return CInt64_Neg(result);
|
||
|
} else {
|
||
|
if (CInt64_IsNegative(&rhs))
|
||
|
rhs = CInt64_Neg(rhs);
|
||
|
CInt64_DivMod(&lhs, &rhs, 0, &result);
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_ModU(CInt64 lhs, CInt64 rhs) {
|
||
|
CInt64 result;
|
||
|
CInt64_DivMod(&lhs, &rhs, 0, &result);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Shl(CInt64 lhs, CInt64 rhs) {
|
||
|
int counter;
|
||
|
unsigned long a;
|
||
|
unsigned long b;
|
||
|
|
||
|
if (rhs.a == 0 && rhs.b < 64) {
|
||
|
a = lhs.a;
|
||
|
b = lhs.b;
|
||
|
for (counter = rhs.b; counter != 0; --counter) {
|
||
|
a <<= 1;
|
||
|
if (b & 0x80000000)
|
||
|
a |= 1;
|
||
|
b <<= 1;
|
||
|
}
|
||
|
lhs.a = a;
|
||
|
lhs.b = b;
|
||
|
} else {
|
||
|
lhs.a = 0;
|
||
|
lhs.b = 0;
|
||
|
}
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Shr(CInt64 lhs, CInt64 rhs) {
|
||
|
int counter;
|
||
|
long a;
|
||
|
unsigned long b;
|
||
|
|
||
|
if (rhs.a == 0 && rhs.b < 64) {
|
||
|
a = lhs.a;
|
||
|
b = lhs.b;
|
||
|
for (counter = rhs.b; counter != 0; --counter) {
|
||
|
b >>= 1;
|
||
|
if (a & 1)
|
||
|
b |= 0x80000000;
|
||
|
a >>= 1;
|
||
|
}
|
||
|
lhs.a = a;
|
||
|
lhs.b = b;
|
||
|
} else {
|
||
|
if (lhs.a & 0x80000000) {
|
||
|
lhs.a = 0xFFFFFFFF;
|
||
|
lhs.b = 0xFFFFFFFF;
|
||
|
} else {
|
||
|
lhs.a = 0;
|
||
|
lhs.b = 0;
|
||
|
}
|
||
|
}
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_ShrU(CInt64 lhs, CInt64 rhs) {
|
||
|
int counter;
|
||
|
unsigned long a;
|
||
|
unsigned long b;
|
||
|
|
||
|
if (rhs.a == 0 && rhs.b < 64) {
|
||
|
a = lhs.a;
|
||
|
b = lhs.b;
|
||
|
for (counter = rhs.b; counter != 0; --counter) {
|
||
|
b >>= 1;
|
||
|
if (a & 1)
|
||
|
b |= 0x80000000;
|
||
|
a >>= 1;
|
||
|
}
|
||
|
lhs.a = a;
|
||
|
lhs.b = b;
|
||
|
} else {
|
||
|
lhs.a = 0;
|
||
|
lhs.b = 0;
|
||
|
}
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
int CInt64_UnsignedCompare(const CInt64 *lhs, const CInt64 *rhs) {
|
||
|
if (lhs->a == rhs->a) {
|
||
|
if (lhs->b < rhs->b)
|
||
|
return -1;
|
||
|
else
|
||
|
return lhs->b > rhs->b;
|
||
|
} else {
|
||
|
return ((unsigned long) lhs->a < rhs->a) ? -1 : 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int CInt64_SignedCompare(const CInt64 *lhs, const CInt64 *rhs) {
|
||
|
CInt64 lhs_;
|
||
|
CInt64 rhs_;
|
||
|
|
||
|
lhs_ = CInt64_Xor(*lhs, cint64_min);
|
||
|
rhs_ = CInt64_Xor(*rhs, cint64_min);
|
||
|
return CInt64_UnsignedCompare(&lhs_, &rhs_);
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_Less(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_SignedCompare(&lhs, &rhs) < 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_LessU(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_UnsignedCompare(&lhs, &rhs) < 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_Greater(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_SignedCompare(&lhs, &rhs) > 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_GreaterU(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_UnsignedCompare(&lhs, &rhs) > 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_LessEqual(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_SignedCompare(&lhs, &rhs) <= 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_LessEqualU(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_UnsignedCompare(&lhs, &rhs) <= 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_GreaterEqual(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_SignedCompare(&lhs, &rhs) >= 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_GreaterEqualU(CInt64 lhs, CInt64 rhs) {
|
||
|
return CInt64_UnsignedCompare(&lhs, &rhs) >= 0;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_Equal(CInt64 lhs, CInt64 rhs) {
|
||
|
return lhs.a == rhs.a && lhs.b == rhs.b;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_NotEqual(CInt64 lhs, CInt64 rhs) {
|
||
|
return lhs.a != rhs.a || lhs.b != rhs.b;
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_IsInRange(CInt64 value, short len) {
|
||
|
CInt64 bound;
|
||
|
|
||
|
if (value.a & 0x80000000) {
|
||
|
switch (len) {
|
||
|
case 1:
|
||
|
bound.b = 0xFFFFFF80;
|
||
|
bound.a = 0xFFFFFFFF;
|
||
|
break;
|
||
|
case 2:
|
||
|
bound.b = 0xFFFF8000;
|
||
|
bound.a = 0xFFFFFFFF;
|
||
|
break;
|
||
|
case 4:
|
||
|
bound.b = 0x80000000;
|
||
|
bound.a = 0xFFFFFFFF;
|
||
|
break;
|
||
|
case 8:
|
||
|
return 1;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
return CInt64_GreaterEqual(value, bound);
|
||
|
} else {
|
||
|
switch (len) {
|
||
|
case 1:
|
||
|
bound.b = 0x7F;
|
||
|
bound.a = 0;
|
||
|
break;
|
||
|
case 2:
|
||
|
bound.b = 0x7FFF;
|
||
|
bound.a = 0;
|
||
|
break;
|
||
|
case 4:
|
||
|
bound.b = 0x7FFFFFFF;
|
||
|
bound.a = 0;
|
||
|
break;
|
||
|
case 8:
|
||
|
return 1;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
return CInt64_LessEqual(value, bound);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned char CInt64_IsInURange(CInt64 value, short len) {
|
||
|
switch (len) {
|
||
|
case 1:
|
||
|
return value.a == 0 && (value.b & 0xFFFFFF00) == 0;
|
||
|
case 2:
|
||
|
return value.a == 0 && (value.b & 0xFFFF0000) == 0;
|
||
|
case 4:
|
||
|
return value.a == 0;
|
||
|
case 8:
|
||
|
return 1;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_And(CInt64 lhs, CInt64 rhs) {
|
||
|
lhs.a &= rhs.a;
|
||
|
lhs.b &= rhs.b;
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Xor(CInt64 lhs, CInt64 rhs) {
|
||
|
lhs.a ^= rhs.a;
|
||
|
lhs.b ^= rhs.b;
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
CInt64 CInt64_Or(CInt64 lhs, CInt64 rhs) {
|
||
|
lhs.a |= rhs.a;
|
||
|
lhs.b |= rhs.b;
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertInt32(CInt64 *i) {
|
||
|
CInt64_Extend32(i);
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertUInt32(CInt64 *i) {
|
||
|
CInt64_SetULong(i, (unsigned long) i->b);
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertInt16(CInt64 *i) {
|
||
|
i->b = (short) i->b;
|
||
|
CInt64_Extend32(i);
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertUInt16(CInt64 *i) {
|
||
|
CInt64_SetULong(i, (unsigned short) i->b);
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertInt8(CInt64 *i) {
|
||
|
i->b = (char) i->b;
|
||
|
CInt64_Extend32(i);
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertUInt8(CInt64 *i) {
|
||
|
CInt64_SetULong(i, (unsigned char) i->b);
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertUFromLongDouble(CInt64 *pResult, double value) {
|
||
|
union { float f; unsigned long l; } cvt;
|
||
|
unsigned long a, b;
|
||
|
float threshold;
|
||
|
int bits;
|
||
|
|
||
|
if (value <= 0.0) {
|
||
|
pResult->a = 0;
|
||
|
pResult->b = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
cvt.l = 0x5F800000;
|
||
|
if (value >= cvt.f) {
|
||
|
pResult->a = 0xFFFFFFFF;
|
||
|
pResult->b = 0xFFFFFFFF;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
a = b = 0;
|
||
|
for (bits = 63; bits >= 0; bits--) {
|
||
|
a <<= 1;
|
||
|
if (b & 0x80000000)
|
||
|
a |= 1;
|
||
|
b <<= 1;
|
||
|
|
||
|
if ((short) bits == 0) {
|
||
|
threshold = 1.0f;
|
||
|
} else {
|
||
|
cvt.l = (((short) bits + 127) & 255) << 23;
|
||
|
threshold = cvt.f;
|
||
|
}
|
||
|
|
||
|
if (threshold <= value) {
|
||
|
b |= 1;
|
||
|
value -= threshold;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pResult->a = a;
|
||
|
pResult->b = b;
|
||
|
}
|
||
|
|
||
|
void CInt64_ConvertFromLongDouble(CInt64 *pResult, double value) {
|
||
|
if (value < 0.0) {
|
||
|
CInt64_ConvertUFromLongDouble(pResult, -value);
|
||
|
*pResult = CInt64_Neg(*pResult);
|
||
|
} else {
|
||
|
CInt64_ConvertUFromLongDouble(pResult, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double CInt64_ConvertUToLongDouble(const CInt64 *value) {
|
||
|
unsigned char bad;
|
||
|
unsigned long work;
|
||
|
int counter;
|
||
|
double result;
|
||
|
|
||
|
bad = (value->a == 0) && (value->b == 0);
|
||
|
if (bad) {
|
||
|
return 0.0;
|
||
|
} else {
|
||
|
result = 0.0;
|
||
|
|
||
|
work = value->a;
|
||
|
if (work != 0) {
|
||
|
for (counter = 0; counter < 32; counter++) {
|
||
|
result += result;
|
||
|
if (work & 0x80000000)
|
||
|
result += 1.0;
|
||
|
work <<= 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
counter = 0;
|
||
|
work = value->b;
|
||
|
for (; counter < 32; counter++) {
|
||
|
result += result;
|
||
|
if (work & 0x80000000)
|
||
|
result += 1.0;
|
||
|
work <<= 1;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double CInt64_ConvertToLongDouble(const CInt64 *value) {
|
||
|
CInt64 tmp;
|
||
|
if (value->a & 0x80000000) {
|
||
|
tmp = CInt64_Neg(*value);
|
||
|
return -CInt64_ConvertUToLongDouble(&tmp);
|
||
|
} else {
|
||
|
return CInt64_ConvertUToLongDouble(value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *CInt64_ScanOctString(CInt64 *pResult, char *str, unsigned char *pFail) {
|
||
|
int ch;
|
||
|
CInt64 tmp;
|
||
|
unsigned long a;
|
||
|
unsigned long b;
|
||
|
|
||
|
*pFail = 0;
|
||
|
pResult->a = pResult->b = 0;
|
||
|
|
||
|
while ((ch = *str) >= '0' && *str <= '7') {
|
||
|
a = pResult->a;
|
||
|
b = pResult->b;
|
||
|
if (a & 0xE0000000)
|
||
|
*pFail = 1;
|
||
|
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
|
||
|
pResult->a = a;
|
||
|
pResult->b = b;
|
||
|
|
||
|
CInt64_SetLong(&tmp, ch - '0');
|
||
|
*pResult = CInt64_Add(*pResult, tmp);
|
||
|
++str;
|
||
|
}
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
char *CInt64_ScanDecString(CInt64 *pResult, char *str, unsigned char *pFail) {
|
||
|
int ch;
|
||
|
CInt64 tmp;
|
||
|
unsigned long a;
|
||
|
unsigned long b;
|
||
|
|
||
|
*pFail = 0;
|
||
|
pResult->a = pResult->b = 0;
|
||
|
|
||
|
while ((ch = *str) >= '0' && *str <= '9') {
|
||
|
a = pResult->a;
|
||
|
b = pResult->b;
|
||
|
if (a & 0xE0000000)
|
||
|
*pFail = 1;
|
||
|
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
tmp.a = a;
|
||
|
tmp.b = b;
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
pResult->a = a;
|
||
|
pResult->b = b;
|
||
|
|
||
|
if (CInt64_IsNegative(pResult)) {
|
||
|
*pResult = CInt64_Add(*pResult, tmp);
|
||
|
if (!CInt64_IsNegative(pResult))
|
||
|
*pFail = 1;
|
||
|
} else {
|
||
|
*pResult = CInt64_Add(*pResult, tmp);
|
||
|
}
|
||
|
|
||
|
CInt64_SetLong(&tmp, ch - '0');
|
||
|
if (CInt64_IsNegative(pResult)) {
|
||
|
*pResult = CInt64_Add(*pResult, tmp);
|
||
|
if (!CInt64_IsNegative(pResult))
|
||
|
*pFail = 1;
|
||
|
} else {
|
||
|
*pResult = CInt64_Add(*pResult, tmp);
|
||
|
}
|
||
|
|
||
|
++str;
|
||
|
}
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
char *CInt64_ScanHexString(CInt64 *pResult, char *str, unsigned char *pFail) {
|
||
|
/* NOT MATCHING */
|
||
|
int digit;
|
||
|
CInt64 tmp;
|
||
|
unsigned long a;
|
||
|
unsigned long b;
|
||
|
|
||
|
*pFail = 0;
|
||
|
pResult->a = pResult->b = 0;
|
||
|
|
||
|
for (;;) {
|
||
|
if ((digit = str[0]) >= '0' && digit <= '9')
|
||
|
digit = digit - '0';
|
||
|
else if (digit >= 'A' && digit <= 'F')
|
||
|
digit = digit - 'A' + 10;
|
||
|
else if (digit >= 'a' && digit <= 'f')
|
||
|
digit = digit - 'a' + 10;
|
||
|
else
|
||
|
break;
|
||
|
|
||
|
a = pResult->a;
|
||
|
b = pResult->b;
|
||
|
++str;
|
||
|
|
||
|
if (a & 0xF0000000)
|
||
|
*pFail = 1;
|
||
|
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
|
||
|
pResult->a = a;
|
||
|
pResult->b = b;
|
||
|
|
||
|
CInt64_SetLong(&tmp, (char) digit);
|
||
|
*pResult = CInt64_Add(*pResult, tmp);
|
||
|
}
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
char *CInt64_ScanBinString(CInt64 *pResult, char *str, unsigned char *pFail) {
|
||
|
char digit;
|
||
|
unsigned long a;
|
||
|
unsigned long b;
|
||
|
|
||
|
*pFail = 0;
|
||
|
pResult->a = pResult->b = 0;
|
||
|
|
||
|
for (;;) {
|
||
|
if (*str == '0')
|
||
|
digit = 0;
|
||
|
else if (*str == '1')
|
||
|
digit = 1;
|
||
|
else
|
||
|
break;
|
||
|
|
||
|
a = pResult->a;
|
||
|
b = pResult->b;
|
||
|
++str;
|
||
|
|
||
|
if (a & 0x80000000)
|
||
|
*pFail = 1;
|
||
|
|
||
|
SHIFT_LEFT_ONE(a, b);
|
||
|
|
||
|
pResult->a = a;
|
||
|
pResult->b = b;
|
||
|
|
||
|
if (digit == 1)
|
||
|
*pResult = CInt64_Add(*pResult, cint64_one);
|
||
|
}
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
char *CInt64_ScanAsmNumber(CInt64 *pResult, char *str, unsigned char *pFail) {
|
||
|
unsigned char isMaybeBin;
|
||
|
unsigned char isOct;
|
||
|
unsigned char isMaybeDec;
|
||
|
unsigned char isBin;
|
||
|
char *p;
|
||
|
|
||
|
isMaybeBin = 1;
|
||
|
isOct = *str == '0';
|
||
|
isMaybeDec = 1;
|
||
|
isBin = 0;
|
||
|
p = str;
|
||
|
|
||
|
for (;;) {
|
||
|
if (*p == 0)
|
||
|
break;
|
||
|
|
||
|
if (strchr("01", p[0])) {
|
||
|
if (isBin)
|
||
|
isMaybeBin = 0;
|
||
|
} else if (strchr("bB", p[0])) {
|
||
|
isBin = 1;
|
||
|
isMaybeDec = 0;
|
||
|
isOct = 0;
|
||
|
} else if (strchr("234567", p[0])) {
|
||
|
isMaybeBin = 0;
|
||
|
} else if (strchr("89", p[0])) {
|
||
|
isOct = 0;
|
||
|
isMaybeBin = 0;
|
||
|
} else if (strchr("acdefACEDF", p[0])) {
|
||
|
isMaybeDec = 0;
|
||
|
isMaybeBin = 0;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
++p;
|
||
|
}
|
||
|
|
||
|
if (isMaybeBin && isBin) {
|
||
|
return CInt64_ScanBinString(pResult, str, pFail) + 1;
|
||
|
} else if (p[0] == 'h' || p[0] == 'H') {
|
||
|
return CInt64_ScanHexString(pResult, str, pFail) + 1;
|
||
|
} else if (isOct) {
|
||
|
return CInt64_ScanOctString(pResult, str, pFail);
|
||
|
} else if (isMaybeDec) {
|
||
|
return CInt64_ScanDecString(pResult, str, pFail);
|
||
|
} else {
|
||
|
*pFail = 1;
|
||
|
return p;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int CInt64_PrintDec(char *output, CInt64 value) {
|
||
|
int length;
|
||
|
CInt64 rem;
|
||
|
CInt64 divisor;
|
||
|
char buf[40];
|
||
|
char *bufp;
|
||
|
|
||
|
length = 0;
|
||
|
if (CInt64_IsNegative(&value)) {
|
||
|
value = CInt64_Neg(value);
|
||
|
*output = '-';
|
||
|
length++;
|
||
|
output++;
|
||
|
}
|
||
|
|
||
|
if (!CInt64_IsZero(&value)) {
|
||
|
divisor.b = 10;
|
||
|
divisor.a = 0;
|
||
|
|
||
|
bufp = buf;
|
||
|
for (;;) {
|
||
|
rem = CInt64_ModU(value, divisor);
|
||
|
*(bufp++) = rem.b + '0';
|
||
|
value = CInt64_DivU(value, divisor);
|
||
|
if (CInt64_IsZero(&value) != 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
while (--bufp >= buf) {
|
||
|
*(output++) = *bufp;
|
||
|
length++;
|
||
|
}
|
||
|
} else {
|
||
|
*(output++) = '0';
|
||
|
length++;
|
||
|
}
|
||
|
|
||
|
*output = 0;
|
||
|
return length;
|
||
|
}
|
||
|
|
||
|
int CInt64_PrintHex(char *output, CInt64 value) {
|
||
|
int length;
|
||
|
CInt64 rem;
|
||
|
CInt64 shift;
|
||
|
CInt64 mask;
|
||
|
char buf[32];
|
||
|
char *bufp;
|
||
|
|
||
|
length = 0;
|
||
|
if (!CInt64_IsZero(&value)) {
|
||
|
shift.b = 4;
|
||
|
shift.a = 0;
|
||
|
mask.b = 0xF;
|
||
|
mask.a = 0;
|
||
|
|
||
|
bufp = buf;
|
||
|
for (;;) {
|
||
|
rem = CInt64_And(value, mask);
|
||
|
if ((long) rem.b >= 10)
|
||
|
*(bufp++) = rem.b + 'A';
|
||
|
else
|
||
|
*(bufp++) = rem.b + '0';
|
||
|
value = CInt64_ShrU(value, shift);
|
||
|
if (CInt64_IsZero(&value) != 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
while (--bufp >= buf) {
|
||
|
*(output++) = *bufp;
|
||
|
length++;
|
||
|
}
|
||
|
} else {
|
||
|
*(output++) = '0';
|
||
|
length++;
|
||
|
}
|
||
|
|
||
|
*output = 0;
|
||
|
return length;
|
||
|
}
|
||
|
|
||
|
int CInt64_PrintBin(char *output, CInt64 value) {
|
||
|
int length;
|
||
|
CInt64 rem;
|
||
|
char buf[64];
|
||
|
char *bufp;
|
||
|
|
||
|
length = 0;
|
||
|
if (!CInt64_IsZero(&value)) {
|
||
|
bufp = buf;
|
||
|
for (;;) {
|
||
|
rem = CInt64_And(value, cint64_one);
|
||
|
if (CInt64_Equal(rem, cint64_one))
|
||
|
*(bufp++) = '1';
|
||
|
else
|
||
|
*(bufp++) = '0';
|
||
|
value = CInt64_ShrU(value, cint64_one);
|
||
|
if (CInt64_IsZero(&value) != 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
while (--bufp >= buf) {
|
||
|
*(output++) = *bufp;
|
||
|
length++;
|
||
|
}
|
||
|
} else {
|
||
|
*(output++) = '0';
|
||
|
length++;
|
||
|
}
|
||
|
|
||
|
*output = 0;
|
||
|
return length;
|
||
|
}
|