Core: Value float support

This commit is contained in:
Mirek Fidler 2023-10-29 20:58:52 +01:00
parent 42a65fc354
commit 5cb246126f
19 changed files with 371 additions and 55 deletions

122
autotest/Float/Etalon.log Normal file
View file

@ -0,0 +1,122 @@
* C:\upp\out\autotest\CLANGx64.Debug.Debug_Full\Float.exe 29.10.2023 20:57:55, user: cxl
===========
x = 0
IsNull(x) = false
v = 0
IsNumber(v) = true
(int)v = 0
(int64)v = 0
(bool)v = false
(double)v = 0
v == x = true
v == 1 = false
v > Value(1) = false
AsJSON(v) = 0
StoreAsJson(t) = {"x":0}
StoreAsXML(t) = <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE app>
<app>
<x value="0"/>
</app>
(float)ScanDouble(AsString(x)) = 0
===========
x = 0.23
IsNull(x) = false
v = 0.23
IsNumber(v) = true
(int)v = 0
(int64)v = 0
(bool)v = true
(double)v = 0.230000004172325
v == x = true
v == 1 = false
v > Value(1) = false
AsJSON(v) = 0.23
StoreAsJson(t) = {"x":0.23}
StoreAsXML(t) = <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE app>
<app>
<x value="0.23"/>
</app>
(float)ScanDouble(AsString(x)) = 0.23
===========
x = 1
IsNull(x) = false
v = 1
IsNumber(v) = true
(int)v = 1
(int64)v = 1
(bool)v = true
(double)v = 1
v == x = true
v == 1 = true
v > Value(1) = false
AsJSON(v) = 1
StoreAsJson(t) = {"x":1}
StoreAsXML(t) = <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE app>
<app>
<x value="1"/>
</app>
(float)ScanDouble(AsString(x)) = 1
===========
x = 1.23
IsNull(x) = false
v = 1.23
IsNumber(v) = true
(int)v = 1
(int64)v = 1
(bool)v = true
(double)v = 1.23000001907349
v == x = true
v == 1 = false
v > Value(1) = true
AsJSON(v) = 1.23
StoreAsJson(t) = {"x":1.23}
StoreAsXML(t) = <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE app>
<app>
<x value="1.23"/>
</app>
(float)ScanDouble(AsString(x)) = 1.23
===========
x = 51.23
IsNull(x) = false
v = 51.23
IsNumber(v) = true
(int)v = 51
(int64)v = 51
(bool)v = true
(double)v = 51.2299995422363
v == x = true
v == 1 = false
v > Value(1) = true
AsJSON(v) = 51.23
StoreAsJson(t) = {"x":51.23}
StoreAsXML(t) = <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE app>
<app>
<x value="51.23"/>
</app>
(float)ScanDouble(AsString(x)) = 51.23
===========
x =
IsNull(x) = true
v =
IsNumber(v) = true
(int)v =
(int64)v =
(bool)v = false
(double)v =
v == x = true
v == 1 = false
v > Value(1) = false
AsJSON(v) = null
StoreAsJson(t) = {"x":null}
StoreAsXML(t) = <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE app>
<app>
<x value=""/>
</app>
(float)ScanDouble(AsString(x)) =

10
autotest/Float/Float.upp Normal file
View file

@ -0,0 +1,10 @@
uses
Core;
file
Etalon.log,
main.cpp;
mainconfig
"" = "";

56
autotest/Float/main.cpp Normal file
View file

@ -0,0 +1,56 @@
#include <Core/Core.h>
using namespace Upp;
struct Foo {
float x;
void Jsonize(JsonIO& io) { io("x", x); }
void Xmlize(XmlIO& io) { io("x", x); }
};
CONSOLE_APP_MAIN
{
StdLogSetup(LOG_COUT|LOG_FILE);
auto Test = [&](float x) {
DLOG("===========");
DDUMP(x);
DDUMP(IsNull(x));
Value v = x;
DDUMP(v);
DDUMP(IsNumber(v));
DDUMP((int)v);
DDUMP((int64)v);
DDUMP((bool)v);
DDUMP((double)v);
DDUMP(v == x);
DDUMP(v == 1);
DDUMP(v > Value(1));
DDUMP(AsJSON(v));
Foo t, u, w;
t.x = x;
DDUMP(StoreAsJson(t));
LoadFromJson(u, StoreAsJson(t));
ASSERT(t.x == u.x);
DDUMP(StoreAsXML(t));
LoadFromXML(w, StoreAsXML(t));
ASSERT(t.x == w.x);
DDUMP((float)ScanDouble(AsString(x)));
ASSERT(x == (float)ScanDouble(AsString(x)));
ASSERT(v == (float)ScanDouble(AsString(x)));
};
Test(0);
Test(0.23);
Test(1);
Test(1.23);
Test(51.23);
Test(Null);
CheckLogEtalon();
}

View file

@ -409,6 +409,19 @@ String FormatDoubleN(double x)
return String(h, FormatDouble_(h, x, 15, FD_TOLERANCE(6)|FD_MINIMAL_EXP));
}
String FormatFloat(float x)
{
char h[512];
return String(h, FormatDouble_(h, x, 7, FD_TOLERANCE(6)|FD_MINIMAL_EXP|FD_SPECIAL));
}
String FormatFloatN(float x)
{
char h[512];
return String(h, FormatDouble_(h, x, 7, FD_TOLERANCE(6)|FD_MINIMAL_EXP));
}
char *FormatG(char *t, double x, int precision, dword flags)
{
return FormatDouble_(t, x, precision, flags);

View file

@ -265,12 +265,14 @@ const int INT_NULL = INT_MIN;
const int64 INT64_NULL = INT64_MIN;
constexpr double DOUBLE_NULL = -std::numeric_limits<double>::infinity();
constexpr float FLOAT_NULL = -std::numeric_limits<float>::infinity();
class Nuller {
public:
operator int() const { return INT_NULL; }
operator int64() const { return INT64_NULL; }
operator double() const { return DOUBLE_NULL; }
operator float() const { return FLOAT_NULL; }
operator bool() const { return false; }
Nuller() {}
@ -285,6 +287,7 @@ template <class T> bool IsNull(const T& x) { return x.IsNullInstance(); }
template<> inline bool IsNull(const int& i) { return i == INT_NULL; }
template<> inline bool IsNull(const int64& i) { return i == INT64_NULL; }
template<> inline bool IsNull(const double& r) { return !(std::abs(r) < std::numeric_limits<double>::infinity()); }
template<> inline bool IsNull(const float& r) { return !(std::abs(r) < std::numeric_limits<float>::infinity()); }
template<> inline bool IsNull(const bool& r ) { return false; }
#include "Heap.h"

View file

@ -61,8 +61,8 @@ String FormatDouble(double x);
String FormatDoubleN(double x);
inline String FormatFloat(float x) { return FormatDouble(x, 7, FD_TOLERANCE(6)|FD_MINIMAL_EXP|FD_SPECIAL); }
inline String FormatFloatN(float x) { return FormatDouble(x, 7, FD_TOLERANCE(6)|FD_MINIMAL_EXP); }
String FormatFloat(float x);
String FormatFloatN(float x);
String FormatDate(Date date, const char *format, int language = 0);
String FormatTime(Time time, const char *format, int language = 0);

View file

@ -143,9 +143,11 @@ String AsJSON(const Value& v, const String& sep, bool pretty)
if(IsNumber(v) && (IsNull(v) || IsNaN((double)v)))
return "null";
if(v.GetType() == INT_V)
return Format("%d", (int)v);
return FormatInt((int)v);
if(v.GetType() == BOOL_V)
return (bool)v ? "true" : "false";
if(v.GetType() == FLOAT_V)
return FormatG((double)v, 7);
if(IsNumber(v))
return FormatG((double)v, 15);
if(IsString(v))
@ -196,6 +198,31 @@ template<> void Jsonize(JsonIO& io, double& var)
io.Set(var);
}
template<> void Jsonize(JsonIO& io, float& var)
{
if(io.IsLoading()) {
const Value& v = io.Get();
if(IsNull(v)) {
var = Null;
return;
}
if(IsNumber(v)) {
var = io.Get();
return;
}
if(IsString(v)) {
double h = ScanDouble((String)v);
if(!IsNull(h)) {
var = (float)h;
return;
}
}
throw JsonizeError("number expected");
}
else
io.Set(var);
}
template<> void Jsonize(JsonIO& io, int& var)
{
double v = IntDbl(var);
@ -388,4 +415,4 @@ String sJsonFile(const char *file)
return file ? String(file) : ConfigFile(GetExeTitle() + ".json");
}
}
}

View file

@ -3,6 +3,7 @@ Value ParseJSON(const char *s);
inline String AsJSON(int i) { return IsNull(i) ? "null" : AsString(i); }
inline String AsJSON(double n) { return IsNull(n) ? "null" : AsString(n); }
inline String AsJSON(float f) { return IsNull(f) ? "null" : AsString(f); }
inline String AsJSON(bool b) { return b ? "true" : "false"; }
inline String AsJSON(const String& s) { return AsCString(s, INT_MAX, NULL, ASCSTRING_JSON); }
inline String AsJSON(const WString& s) { return AsCString(s.ToString(), INT_MAX, NULL, ASCSTRING_JSON); }
@ -26,10 +27,11 @@ public:
operator String() const { return ToString(); }
operator bool() const { return text.GetCount(); }
Json& operator()(const char *key, const Value& value) { return CatRaw(key, AsJSON(value)); }
Json& operator()(const char *key, int i) { return CatRaw(key, AsJSON(i)); }
Json& operator()(const char *key, double n) { return CatRaw(key, AsJSON(n)); }
Json& operator()(const char *key, float f) { return CatRaw(key, AsJSON(f)); }
Json& operator()(const char *key, bool b) { return CatRaw(key, AsJSON(b)); }
Json& operator()(const char *key, Date d) { return CatRaw(key, AsJSON(d)); }
Json& operator()(const char *key, Time t) { return CatRaw(key, AsJSON(t)); }
@ -38,11 +40,12 @@ public:
Json& operator()(const char *key, const char *s) { return CatRaw(key, AsJSON(s)); }
Json& operator()(const char *key, const Json& object) { return CatRaw(key, ~object); }
Json& operator()(const char *key, const JsonArray& array);
Json() {}
Json(const char *key, const Value& value) { CatRaw(key, AsJSON(value)); }
Json(const char *key, int i) { CatRaw(key, AsJSON(i)); }
Json(const char *key, double n) { CatRaw(key, AsJSON(n)); }
Json(const char *key, float f) { CatRaw(key, AsJSON(f)); }
Json(const char *key, bool b) { CatRaw(key, AsJSON(b)); }
Json(const char *key, Date d) { CatRaw(key, AsJSON(d)); }
Json(const char *key, Time t) { CatRaw(key, AsJSON(t)); }
@ -62,12 +65,13 @@ public:
String ToString() const { return "[" + text + "]"; }
String operator~() const { return ToString(); }
operator String() const { return ToString(); }
operator bool() const { return text.GetCount(); }
JsonArray& operator<<(const Value& value) { return CatRaw(AsJSON(value)); }
JsonArray& operator<<(int i) { return CatRaw(AsJSON(i)); }
JsonArray& operator<<(double n) { return CatRaw(AsJSON(n)); }
JsonArray& operator<<(float f) { return CatRaw(AsJSON(f)); }
JsonArray& operator<<(bool b) { return CatRaw(AsJSON(b)); }
JsonArray& operator<<(Date d) { return CatRaw(AsJSON(d)); }
JsonArray& operator<<(Time t) { return CatRaw(AsJSON(t)); }
@ -76,7 +80,7 @@ public:
JsonArray& operator<<(const char *s) { return CatRaw(AsJSON(s)); }
JsonArray& operator<<(const Json& object) { return CatRaw(~object); }
JsonArray& operator<<(const JsonArray& array) { return CatRaw(~array); }
JsonArray() {}
};
@ -93,10 +97,10 @@ class JsonIO {
public:
bool IsLoading() const { return src; }
bool IsStoring() const { return !src; }
const Value& Get() const { ASSERT(IsLoading()); return *src; }
void Set(const Value& v) { ASSERT(IsStoring() && !map); tgt = v; }
Value Get(const char *key) { ASSERT(IsLoading()); return (*src)[key]; }
void Set(const char *key, const Value& v);
@ -117,7 +121,7 @@ public:
template <class T, class X>
JsonIO& Array(const char *key, T& value, X item_jsonize, const char * = NULL);
JsonIO(const Value& src) : src(&src) {}
JsonIO() { src = NULL; }
};
@ -311,6 +315,7 @@ template<> void Jsonize(JsonIO& io, byte& var);
template<> void Jsonize(JsonIO& io, int16& var);
template<> void Jsonize(JsonIO& io, int64& var);
template<> void Jsonize(JsonIO& io, double& var);
template<> void Jsonize(JsonIO& io, float& var);
template<> void Jsonize(JsonIO& io, bool& var);
template<> void Jsonize(JsonIO& io, String& var);
template<> void Jsonize(JsonIO& io, WString& var);
@ -464,7 +469,7 @@ struct LambdaIzeVar {
void Jsonize(JsonIO& io) { ize(io); }
void Xmlize(XmlIO& io) { ize(io); }
LambdaIzeVar(IZE& ize) : ize(ize) {}
};
@ -473,4 +478,4 @@ void LambdaIze(IO& io, const char *id, IZE ize)
{
LambdaIzeVar<IZE> var(ize);
io(id, var);
}
}

View file

@ -194,6 +194,7 @@ int Value::GetOtherInt() const
if(IsNull()) return Null;
return data.IsSpecial(BOOL_V) ? (int)GetSmall<bool>() :
data.IsSpecial(INT64_V) ? (int)GetSmall<int64>() :
data.IsSpecial(FLOAT_V) ? (float)GetSmall<float>() :
(int)GetSmall<double>();
}
@ -202,6 +203,7 @@ int64 Value::GetOtherInt64() const
if(IsNull()) return Null;
return data.IsSpecial(BOOL_V) ? (int64)GetSmall<bool>() :
data.IsSpecial(INT_V) ? (int64)GetSmall<int>() :
data.IsSpecial(FLOAT_V) ? (float)GetSmall<float>() :
(int64)GetSmall<double>();
}
@ -210,14 +212,25 @@ double Value::GetOtherDouble() const
if(IsNull()) return Null;
return data.IsSpecial(BOOL_V) ? (double)GetSmall<bool>() :
data.IsSpecial(INT_V) ? (double)GetSmall<int>() :
data.IsSpecial(FLOAT_V) ? (float)GetSmall<float>() :
(double)GetSmall<int64>();
}
float Value::GetOtherFloat() const
{
if(IsNull()) return Null;
return data.IsSpecial(BOOL_V) ? (float)GetSmall<bool>() :
data.IsSpecial(INT_V) ? (float)GetSmall<int>() :
data.IsSpecial(DOUBLE_V) ? (float)GetSmall<double>() :
(float)GetSmall<int64>();
}
bool Value::GetOtherBool() const
{
if(IsNull()) return Null;
return data.IsSpecial(DOUBLE_V) ? (bool)GetSmall<double>() :
data.IsSpecial(INT_V) ? (bool)GetSmall<int>() :
data.IsSpecial(FLOAT_V) ? (float)GetSmall<float>() :
(bool)GetSmall<int64>();
}
@ -264,6 +277,7 @@ String Value::GetName(dword type)
SVO_FN(s_String, String);
SVO_FN(s_int, int);
SVO_FN(s_double, double);
SVO_FN(s_float, float);
SVO_FN(s_int64, int64);
SVO_FN(s_bool, bool);
SVO_FN(s_date, Date);
@ -307,6 +321,7 @@ Value::Sval *Value::svo[256] = {
&s_bool, //BOOL_V = 11;
NULL, //VALUEMAP_V = 12;
&s_float, //FLOAT_V = 13;
};
Value::Void *ValueArrayDataCreate()
@ -329,6 +344,7 @@ void Value::RegisterStd()
Value::AddName(STRING_V, "String");
Value::AddName(INT_V, "int");
Value::AddName(DOUBLE_V, "double");
Value::AddName(FLOAT_V, "float");
Value::AddName(VOID_V, "void");
Value::AddName(DATE_V, "Date");
Value::AddName(TIME_V, "Time");
@ -719,6 +735,7 @@ String Value::GetName() const
static Tuple<byte, const char *> tp[] = {
{ (byte)INT_V, "int" },
{ (byte)DOUBLE_V, "double" },
{ (byte)FLOAT_V, "float" },
{ (byte)VOIDV, "void" },
{ (byte)DATE_V, "Date" },
{ (byte)TIME_V, "Time" },
@ -757,4 +774,4 @@ String GetErrorText(const Value& v) {
return ((RichValueRep<String> *)v.GetVoidPtr())->Get();
}
}
}

View file

@ -34,6 +34,7 @@ const dword INT64_V = 10;
const dword BOOL_V = 11;
const dword VALUEMAP_V = 12;
const dword FLOAT_V = 13;
const dword UNKNOWN_V = (dword)0xffffffff;
@ -43,6 +44,7 @@ inline dword ValueTypeNo(const T *) { return StaticTypeNo<T>() +
template<> inline dword ValueTypeNo(const int*) { return INT_V; }
template<> inline dword ValueTypeNo(const int64*) { return INT64_V; }
template<> inline dword ValueTypeNo(const double*) { return DOUBLE_V; }
template<> inline dword ValueTypeNo(const float*) { return FLOAT_V; }
template<> inline dword ValueTypeNo(const bool*) { return BOOL_V; }
template<> inline dword ValueTypeNo(const String*) { return STRING_V; }
template<> inline dword ValueTypeNo(const WString*) { return WSTRING_V; }
@ -55,7 +57,7 @@ class ValueType : public B {
public:
static dword ValueTypeNo() { return type == UNKNOWN_V ? StaticTypeNo<T>() + 0x8000000 : type; }
friend dword ValueTypeNo(const T*) { return T::ValueTypeNo(); }
bool IsNullInstance() const { return false; }
void Serialize(Stream& s) { NEVER(); }
void Xmlize(XmlIO& xio) { NEVER(); }
@ -65,7 +67,7 @@ public:
String ToString() const { return typeid(T).name(); }
int Compare(const T&) const { NEVER(); return 0; }
int PolyCompare(const Value&) const { NEVER(); return 0; }
operator ValueTypeRef();
};
@ -115,7 +117,7 @@ public:
int (*Compare)(const void *p1, const void *p2);
int (*PolyCompare)(const void *p1, const Value& p2);
};
protected:
enum { STRING = 0, REF = 255, VOIDV = 3 };
@ -123,7 +125,7 @@ protected:
static Sval *svo[256];
static Index<String>& NameNdx();
static Index<dword>& TypeNdx();
static void AddName(dword type, const char *name);
static int GetType(const char *name);
static String GetName(dword type);
@ -154,10 +156,11 @@ protected:
T& GetSmallRaw() const;
template <class T>
T& GetSmall() const;
int GetOtherInt() const;
int64 GetOtherInt64() const;
double GetOtherDouble() const;
float GetOtherFloat() const;
bool GetOtherBool() const;
Date GetOtherDate() const;
Time GetOtherTime() const;
@ -165,23 +168,23 @@ protected:
hash_t GetOtherHashValue() const;
bool IsPolyEqual(const Value& v) const;
enum VSMALL { SMALL };
template <class T>
Value(const T& value, VSMALL);
template <class T> friend Value SvoToValue(const T& x);
String GetName() const;
int PolyCompare(const Value& v) const;
int Compare2(const Value& v) const;
Vector<Value>& UnShareArray();
const Vector<Value>& GetVA() const;
#if defined(_DEBUG) && defined(COMPILER_GCC)
uint32 magic[4];
void Magic() { magic[0] = 0xc436d851; magic[1] = 0x72f67c76; magic[2] = 0x3e5e10fd; magic[3] = 0xc90d370b; }
@ -202,7 +205,7 @@ public:
static void Register(const char *name = NULL);
template <class T>
static void SvoRegister(const char *name = NULL);
dword GetType() const;
bool IsError() const { return GetType() == ERROR_V; }
bool IsVoid() const { return Is(VOIDV) || IsError(); }
@ -220,19 +223,20 @@ public:
operator Date() const { return Is(DATE_V) ? GetSmallRaw<Date>() : GetOtherDate(); }
operator Time() const { return Is(TIME_V) ? GetSmallRaw<Time>() : GetOtherTime(); }
operator double() const { return Is(DOUBLE_V) ? GetSmallRaw<double>() : GetOtherDouble(); }
operator float() const { return float(Is(DOUBLE_V) ? GetSmallRaw<double>() : GetOtherDouble()); }
operator float() const { return Is(FLOAT_V) ? GetSmallRaw<float>() : GetOtherFloat(); }
operator int() const { return Is(INT_V) ? GetSmallRaw<int>() : GetOtherInt(); }
operator int64() const { return Is(INT64_V) ? GetSmallRaw<int64>() : GetOtherInt64(); }
operator bool() const { return Is(BOOL_V) ? GetSmallRaw<bool>() : GetOtherBool(); }
std::string ToStd() const { return operator String().ToStd(); }
std::wstring ToWStd() const { return operator WString().ToStd(); }
Value(const String& s) : data(s) { Magic(); }
Value(const WString& s);
Value(const char *s) : data(s) { Magic(); }
Value(int i) : data(i, INT_V, String::SPECIAL) { Magic(); }
Value(int64 i) : data(i, INT64_V, String::SPECIAL) { Magic(); }
Value(double d) : data(d, DOUBLE_V, String::SPECIAL) { Magic(); }
Value(float d) : data(d, FLOAT_V, String::SPECIAL) { Magic(); }
Value(bool b) : data(b, BOOL_V, String::SPECIAL) { Magic(); }
Value(Date d) : data(d, DATE_V, String::SPECIAL) { Magic(); }
Value(Time t) : data(t, TIME_V, String::SPECIAL) { Magic(); }
@ -243,7 +247,7 @@ public:
bool operator==(const Value& v) const;
bool operator!=(const Value& v) const { return !operator==(v); }
bool IsSame(const Value& v) const;
int Compare(const Value& v) const;
bool operator<=(const Value& x) const { return Compare(x) <= 0; }
bool operator>=(const Value& x) const { return Compare(x) >= 0; }
@ -262,13 +266,13 @@ public:
Value& operator=(const Value& v);
Value(const Value& v);
int GetCount() const;
const Value& operator[](int i) const;
const Value& operator[](const String& key) const;
const Value& operator[](const char *key) const;
const Value& operator[](const Id& key) const;
Value& At(int i);
Value& operator()(int i) { return At(i); }
void Add(const Value& src);
@ -346,6 +350,7 @@ inline bool operator!=(T x, const Value& v) { return v.Is<VT>() ? (VT)v != x :
VALUE_COMPARE(int)
VALUE_COMPARE(int64)
VALUE_COMPARE(double)
VALUE_COMPARE(float)
VALUE_COMPARE(bool)
VALUE_COMPARE(Date)
VALUE_COMPARE(Time)
@ -367,7 +372,7 @@ inline bool IsDateTimeValueTypeNo(int q) { return (dword)q == DATE_V || (dword)q
inline bool IsVoid(const Value& v) { return v.IsVoid(); }
inline bool IsError(const Value& v) { return v.IsError(); }
inline bool IsString(const Value& v) { return v.Is<String>() || v.Is<WString>(); }
inline bool IsNumber(const Value& v) { return v.Is<double>() || v.Is<int>() || v.Is<int64>() || v.Is<bool>(); }
inline bool IsNumber(const Value& v) { return v.Is<double>() || v.Is<float>() || v.Is<int>() || v.Is<int64>() || v.Is<bool>(); }
inline bool IsDateTime(const Value& v) { return v.Is<Date>() || v.Is<Time>(); }
inline bool IsValueArray(const Value& v) { return v.GetType() == VALUEARRAY_V || v.GetType() == VALUEMAP_V; }
inline bool IsValueMap(const Value& v) { return IsValueArray(v); }

View file

@ -12,6 +12,7 @@ Value::Value(const Value& v)
template<>
inline bool IsPolyEqual(const bool& x, const Value& v) {
return v.Is<double>() && int(x) == double(v)
|| v.Is<float>() && int(x) == float(v)
|| v.Is<int64>() && int(x) == int64(v)
|| v.Is<int>() && int(x) == int(v);
}
@ -19,6 +20,7 @@ inline bool IsPolyEqual(const bool& x, const Value& v) {
template<>
inline bool IsPolyEqual(const int& x, const Value& v) {
return v.Is<double>() && x == double(v)
|| v.Is<float>() && x == float(v)
|| v.Is<int64>() && x == int64(v);
}
@ -79,6 +81,11 @@ inline int PolyCompare(const double& x, const Value& v) {
return IsNumber(v) ? SgnCompare((double)x, (double)v) : 0;
}
template<>
inline int PolyCompare(const float& x, const Value& v) {
return IsNumber(v) ? SgnCompare((double)x, (double)v) : 0;
}
template<>
inline int PolyCompare(const Date& x, const Value& v) {
return v.Is<Time>() && SgnCompare(ToTime(x), Time(v));
@ -106,6 +113,13 @@ inline hash_t ValueGetHashValue(const double& x) {
return UPP::GetHashValue(x);
}
template<>
inline hash_t ValueGetHashValue(const float& x) {
if(x >= (float)INT64_MIN && x <= (float)INT64_MAX && (int64)x == x)
return UPP::GetHashValue((int64)x); // we want this to be equal to other number types
return UPP::GetHashValue(x);
}
template<>
inline hash_t ValueGetHashValue(const Date& x) {
return UPP::GetHashValue(ToTime(x));
@ -125,10 +139,10 @@ public:
enum VPICK { PICK };
enum VDEEP { DEEP };
const T& Get() const { return v; }
T& Get() { return v; }
RawValueRep(const T& v) : v(v) {}
RawValueRep(T&& v, VPICK) : v(pick(v)) {}
RawValueRep(const T& v, VDEEP) : v(v, 1) {}
@ -274,6 +288,8 @@ int Value::Compare(const Value& v) const
return SgnCompare(GetSmallRaw<int>(), v.GetSmallRaw<int>());
if(Is(DOUBLE_V) && v.Is(DOUBLE_V))
return SgnCompare(GetSmallRaw<double>(), v.GetSmallRaw<double>());
if(Is(FLOAT_V) && v.Is(FLOAT_V))
return SgnCompare(GetSmallRaw<float>(), v.GetSmallRaw<float>());
return Compare2(v);
}

View file

@ -19,6 +19,7 @@ Ref::Ref(WString& s) { ptr = &s; m = &Single< StdRef<WString> >(); }
Ref::Ref(int& i) { ptr = &i; m = &Single< StdRef<int> >(); }
Ref::Ref(int64& i) { ptr = &i; m = &Single< StdRef<int64> >(); }
Ref::Ref(double& d) { ptr = &d; m = &Single< StdRef<double> >(); }
Ref::Ref(float& f) { ptr = &f; m = &Single< StdRef<float> >(); }
Ref::Ref(bool& b) { ptr = &b; m = &Single< StdRef<bool> >(); }
Ref::Ref(Date& d) { ptr = &d; m = &Single< StdRef<Date> >(); }
Ref::Ref(Time& t) { ptr = &t; m = &Single< StdRef<Time> >(); }
@ -652,5 +653,4 @@ INITBLOCK
Value::Register<Rectf>("Rectf");
}
}
}

View file

@ -4,12 +4,14 @@ inline const String& Nvl(const String& a, const String& b) { return IsNull(a
inline int Nvl(int a, int b) { return IsNull(a) ? b : a; }
inline int64 Nvl(int64 a, int64 b) { return IsNull(a) ? b : a; }
inline double Nvl(double a, double b) { return IsNull(a) ? b : a; }
inline float Nvl(float a, float b) { return IsNull(a) ? b : a; }
inline Date Nvl(Date a, Date b) { return IsNull(a) ? b : a; }
inline Time Nvl(Time a, Time b) { return IsNull(a) ? b : a; }
inline int Nvl(int a) { return Nvl(a, 0); }
inline int64 Nvl(int64 a) { return Nvl(a, (int64)0); }
inline double Nvl(double a) { return Nvl(a, 0.0); }
inline float Nvl(float a) { return Nvl(a, 0.0f); }
template <class T>
inline T Nvl(T a, T b, T c) { return Nvl(Nvl(a, b), c); }
@ -143,6 +145,7 @@ public:
Ref(int& i);
Ref(int64& i);
Ref(double& d);
Ref(float& f);
Ref(bool& b);
Ref(Date& d);
Ref(Time& t);
@ -163,6 +166,7 @@ inline WString& RefWString(Ref f) { return GetRef<WString>(f); }
inline int& RefInt(Ref f) { return GetRef<int>(f); }
inline int64& RefInt64(Ref f) { return GetRef<int64>(f); }
inline double& RefDouble(Ref f) { return GetRef<double>(f); }
inline float& RefFloat(Ref f) { return GetRef<float>(f); }
inline bool& RefBool(Ref f) { return GetRef<bool>(f); }
inline Date& RefDate(Ref f) { return GetRef<Date>(f); }
inline Time& RefTime(Ref f) { return GetRef<Time>(f); }
@ -218,7 +222,7 @@ class ValueArray : public ValueType<ValueArray, VALUEARRAY_V, Moveable<ValueArra
};
struct NullData : Data {};
Data *data;
static Vector<Value> VoidData;
Vector<Value>& Create();
@ -246,7 +250,7 @@ public:
ValueArray(const Nuller&) { Init0(); }
bool IsNullInstance() const { return IsEmpty(); }
void Clear();
void SetCount(int n);
void SetCount(int n, const Value& v);
@ -267,7 +271,7 @@ public:
void Append(const ValueArray& va) { Insert(GetCount(), va); }
const Value& operator[](int i) const { return Get(i); }
Value& At(int i);
hash_t GetHashValue() const { return data->GetHashValue(); }
@ -278,7 +282,7 @@ public:
bool operator==(const ValueArray& v) const;
bool operator!=(const ValueArray& v) const { return !operator==(v); }
int Compare(const ValueArray& b) const;
bool operator<=(const ValueArray& x) const { return Compare(x) <= 0; }
bool operator>=(const ValueArray& x) const { return Compare(x) >= 0; }
@ -381,7 +385,7 @@ public:
void Add(const char *key, const Value& value) { Add(Value(key), value); }
void Add(int key, const Value& value) { Add(Value(key), value); }
void Add(Id key, const Value& value) { Add(Value(key.ToString()), value); }
ValueMap& operator()(const Value& key, const Value& value) { Add(key, value); return *this; }
ValueMap& operator()(const String& key, const Value& value) { Add(Value(key), value); return *this; }
ValueMap& operator()(const char *key, const Value& value) { Add(Value(key), value); return *this; }
@ -412,7 +416,7 @@ public:
ValueArray GetValues() const { return data->value; }
operator ValueArray() const { return GetValues(); }
VectorMap<Value, Value> Pick();
const Value& operator[](const Value& key) const { return data->Get(key); }
@ -428,7 +432,7 @@ public:
Value& operator()(const int key) { return operator()(Value(key)); }
Value& operator()(const Id& key) { return operator()(Value(key.ToString())); }
Value& At(int i) { return UnShare().At(i); }
Value GetAndClear(const Value& key);
hash_t GetHashValue() const { return data->GetHashValue(); }

View file

@ -173,6 +173,11 @@ XmlTag& XmlTag::operator()(const char *attr, double q)
return operator()(attr, AsString(q));
}
XmlTag& XmlTag::operator()(const char *attr, float q)
{
return operator()(attr, AsString(q));
}
force_inline
String XmlParser::Convert(StringBuffer& b)
{
@ -681,6 +686,13 @@ double XmlParser::Double(const char *id, double def) const
return q < 0 ? def : ScanDouble(attr[q]);
}
float XmlParser::Float(const char *id, float def) const
{
if(id == attr1) return (float)ScanDouble(attrval1);
int q = attr.Find(id);
return q < 0 ? def : (float)ScanDouble(attr[q]);
}
bool XmlParser::IsText()
{
if(npreserve || preserveall)

View file

@ -22,13 +22,14 @@ public:
String Text(const String& s, byte charset = CHARSET_DEFAULT) { return Text(~s, charset); }
String PreservedText(const char *s, byte charset = CHARSET_DEFAULT);
String PreservedText(const String& s, byte charset = CHARSET_DEFAULT) { return PreservedText(~s, charset); }
String GetBegin() const { return tag + '>'; }
String GetEnd() const { return end; }
XmlTag& operator()(const char *attr, const char *val);
XmlTag& operator()(const char *attr, int q);
XmlTag& operator()(const char *attr, double q);
XmlTag& operator()(const char *attr, float q);
XmlTag() {}
XmlTag(const char *tag) { Tag(tag); }
@ -51,7 +52,7 @@ class XmlParser {
CHUNK = 16384
#endif
};
struct Nesting {
Nesting(String tag = Null, bool blanks = false) : tag(tag), preserve_blanks(blanks) {}
String tag;
@ -82,7 +83,7 @@ class XmlParser {
bool raw;
int line;
byte acharset;
byte scharset;
@ -104,7 +105,7 @@ class XmlParser {
public:
void SkipWhites();
void RegisterEntity(const String& id, const String& text);
bool IsEof();
@ -137,6 +138,7 @@ public:
String operator[](const char *id) const { return attr1 == id ? attrval1 : attr.Get(id, Null); }
int Int(const char *id, int def = Null) const;
double Double(const char *id, double def = Null) const;
float Float(const char *id, float def = Null) const;
bool IsText();
String PeekText() { return cdata; }
@ -226,13 +228,13 @@ public:
XmlNode& SetAttr(const char *id, int val);
void SetAttrs(VectorMap<String, String>&& a);
void Shrink();
rval_default(XmlNode);
XmlNode(const XmlNode& n, int);
XmlNode() { type = XML_DOC; }
typedef Array<XmlNode>::ConstIterator ConstIterator;
@ -290,4 +292,4 @@ enum {
void AsXML(Stream& out, const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY);
String AsXML(const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY);
bool AsXMLFile(const char *path, const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY);
bool AsXMLFile(const char *path, const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY);

View file

@ -62,7 +62,7 @@ template<> void XmlAttrLoad(dword& var, const String& text)
template<> String XmlAttrStore(const double& var)
{
return FormatG(var, 15);
return AsString(var);
}
template<> void XmlAttrLoad(double& var, const String& text)
@ -70,6 +70,16 @@ template<> void XmlAttrLoad(double& var, const String& text)
var = ScanDouble(text);
}
template<> String XmlAttrStore(const float& var)
{
return AsString(var);
}
template<> void XmlAttrLoad(float& var, const String& text)
{
var = ScanDouble(text);
}
template<> String XmlAttrStore(const dword& var)
{
return AsString(var);
@ -147,6 +157,7 @@ template<> String XmlAttrStore(const Time& var) {
VALUE_XMLIZE(int);
VALUE_XMLIZE(dword);
VALUE_XMLIZE(double);
VALUE_XMLIZE(float);
VALUE_XMLIZE(bool);
VALUE_XMLIZE(int16);
VALUE_XMLIZE(int64);
@ -254,6 +265,11 @@ void StoreJsonValue(XmlIO& xio, const Value& v)
Xmlize(xio, b);
}
else
if(v.GetType() == FLOAT_V) {
float f = v;
Xmlize(xio, f);
}
else
if(IsNumber(v)) {
double h = v;
Xmlize(xio, h);
@ -293,4 +309,4 @@ Value LoadJsonValue(const XmlNode& n)
return m;
}
}
}

View file

@ -61,7 +61,7 @@ public:
XmlIO Add() { XmlIO m(node.Add(), IsLoading(), userdata); return m; }
XmlIO Add(const char *id) { XmlIO m(node.Add(id), IsLoading(), userdata); return m; }
XmlIO GetAdd(const char *id) { XmlIO m(node.GetAdd(id), IsLoading(), userdata); return m; }
void SetUserData(const Value& v) { userdata = v; }
Value GetUserData() const { return userdata; }
@ -81,6 +81,8 @@ template<> void XmlAttrLoad(dword& var, const String& text);
template<> String XmlAttrStore(const dword& var);
template<> void XmlAttrLoad(double& var, const String& text);
template<> String XmlAttrStore(const double& var);
template<> void XmlAttrLoad(float& var, const String& text);
template<> String XmlAttrStore(const float& var);
template<> void XmlAttrLoad(bool& var, const String& text);
template<> String XmlAttrStore(const bool& var);
template <> void XmlAttrLoad(int16& var, const String& text);
@ -99,6 +101,7 @@ template<> void Xmlize(XmlIO& xml, WString& var);
template<> void Xmlize(XmlIO& xml, int& var);
template<> void Xmlize(XmlIO& xml, dword& var);
template<> void Xmlize(XmlIO& xml, double& var);
template<> void Xmlize(XmlIO& xml, float& var);
template<> void Xmlize(XmlIO& xml, bool& var);
template<> void Xmlize(XmlIO& xml, Date& var);
template<> void Xmlize(XmlIO& xml, Time& var);

View file

@ -182,6 +182,9 @@ sonIO][@(0.0.255) `&]_[*@3 io], [_^int16^ int16][@(0.0.255) `&]_[*@3 var])&]
sonIO][@(0.0.255) `&]_[*@3 io], [_^int64^ int64][@(0.0.255) `&]_[*@3 var])&]
[s5;:Jsonize`(JsonIO`&`,double`&`): [@(0.0.255) template]_<>_[@(0.0.255) void]_[* Jsonize](
[_^JsonIO^ JsonIO][@(0.0.255) `&]_[*@3 io], [@(0.0.255) double`&]_[*@3 var])&]
[s5;:Upp`:`:Jsonize`(Upp`:`:JsonIO`&`,float`&`): [@(0.0.255) template]<>
[@(0.0.255) void] [* Jsonize](JsonIO[@(0.0.255) `&] io, [@(0.0.255) float`&]
var)&]
[s5;:Jsonize`(JsonIO`&`,bool`&`): [@(0.0.255) template]_<>_[@(0.0.255) void]_[* Jsonize]([_^JsonIO^ J
sonIO][@(0.0.255) `&]_[*@3 io], [@(0.0.255) bool`&]_[*@3 var])&]
[s5;:Jsonize`(JsonIO`&`,String`&`): [@(0.0.255) template]_<>_[@(0.0.255) void]_[* Jsonize](
@ -208,8 +211,7 @@ data type.&]
which leads to somewhat unnatural results when key [%-*@4 K] is
String or WString. [%-* StringMap ]alternative variant encodes
map as JSON object with keys equal to map keys.&]
[s3;%% &]
[s3;%% &]
[s3; &]
[s4;%% &]
[s5;:JsonizeBySerialize`(JsonIO`&`,T`&`): [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T]>
_[@(0.0.255) void]_[* JsonizeBySerialize]([_^JsonIO^ JsonIO][@(0.0.255) `&]_[*@3 jio],

View file

@ -70,6 +70,9 @@ har]_`*[*@3 val])&]
ator()]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 attr], [@(0.0.255) int]_[*@3 q])&]
[s5;:XmlTag`:`:operator`(`)`(const char`*`,double`): [_^XmlTag^ XmlTag][@(0.0.255) `&]_[* o
perator()]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 attr], [@(0.0.255) double]_[*@3 q])&]
[s5;:Upp`:`:XmlTag`:`:operator`(`)`(const char`*`,float`): XmlTag[@(0.0.255) `&]
operator()([@(0.0.255) const] [@(0.0.255) char] [@(0.0.255) `*]attr,
[@(0.0.255) float] q)&]
[s2;%% These methods add XML tag attributes.&]
[s3;%% &]
[s0;%% &]