X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ecere%2Fsrc%2Fsys%2FJSON.ec;h=a34a7e27617a130f68a89713017bf4593ae14fba;hb=87a86086a30c85c65de3a8eb9f5ee6ceec6b4b69;hp=8310d1ea5218c9cb82d518eda7cd1e367db11c9d;hpb=e61aa66f20117fdc3df44d54b35d655d6fc433cf;p=sdk diff --git a/ecere/src/sys/JSON.ec b/ecere/src/sys/JSON.ec index 8310d1e..a34a7e2 100644 --- a/ecere/src/sys/JSON.ec +++ b/ecere/src/sys/JSON.ec @@ -31,11 +31,16 @@ public enum SetBool : uint }; +public class ECONParser : JSONParser +{ + eCON = true; +} + public class JSONParser { public: File f; - char pch; +private: char ch; bool eCON; @@ -160,16 +165,29 @@ public: } else if(ch == '{') { - void * object = value.p; - result = GetObject(type, &object); - if(result) + if(type.type == structClass || type.type == normalClass || type.type == noHeadClass) { - if(type && type.type == structClass); - else if(type && (type.type == normalClass || type.type == noHeadClass || type.type == bitClass)) + void * object = value.p; + result = GetObject(type, &object); + if(result) { - value.p = object; + if(type && type.type == structClass); + else + value.p = object; } - else + } + else if(type.type == bitClass) + { + uint64 object = 0; + result = GetObject(type, (void **)&object); + if(result) + value.ui64 = object; + } + else + { + void * object = value.p; + result = GetObject(type, &object); + if(result) { result = typeMismatch; if(type) @@ -177,7 +195,7 @@ public: } } } - else if(isalpha(ch)) + else if(isalpha(ch) || ch == '_') { if(eCON) { @@ -185,7 +203,7 @@ public: if(GetIdentifier(&string, null)) { result = success; - if(eCON && (type.type == enumClass || type.type == unitClass)) + if(eCON && type && (type.type == enumClass || type.type == unitClass)) { // should this be set by calling __ecereVMethodID_class_OnGetDataFromString ? if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string)) @@ -212,10 +230,10 @@ public: if(type.type != structClass) value.p = 0; } - else if(isSubclass(string, type)) + else if(isSubclass(type, string)) { void * object = value.p; - Class subtype = eSystem_SuperFindClass(string, type.module); + Class subtype = superFindClass(string, type.module); SkipEmpty(); result = GetObject(subtype, &object); if(result) @@ -242,7 +260,7 @@ public: { char buffer[256]; int c = 0; - while(c < sizeof(buffer)-1 && isalpha(ch)) + while(c < sizeof(buffer)-1 && (isalpha(ch) || isdigit(ch) || ch == '_')) { buffer[c++] = ch; if(!f.Getc(&ch)) break; @@ -502,7 +520,7 @@ public: break; } } - else if(ch == '\"' || (!comment && ch && !isalpha(ch))) + else if(ch == '\"' || (!quoted && !comment && ch && !isalpha(ch) && !isdigit(ch) && ch != '_')) { if(quoted && ch == '\"' && wasQuoted) *wasQuoted = true; @@ -521,7 +539,7 @@ public: *string = CopyString(buffer.array); } delete buffer; - if(ch != ',' && ch != '}' && ch != ';' && ch != '/' && ch != '=') + if(ch != ',' && ch != '}' && ch != ';' && ch != '/' && ch != '=' && ch != ':') ch = 0; return result; } @@ -582,7 +600,7 @@ public: lineComment = false; else if(comment && pch == '*' && ch == '/') comment = false; - else if(ch == '=' || ch == ';' || ch == ',' || ch == '}') + else if(ch == '=' || ch == ':' || ch == ';' || ch == ',' || ch == ']' || ch == '}') { ch = 0; seekback = -1; @@ -627,7 +645,12 @@ public: { JSONResult result = syntaxError; if(!objectType || objectType.type != structClass) - *object = null; + { + if(objectType && objectType.type == bitClass) + *(uint64 *)object = 0; + else + *object = null; + } SkipEmpty(); if(ch == '{') { @@ -636,6 +659,18 @@ public: DataMember curMember = null; DataMember subMemberStack[256]; int subMemberStackPos = 0; + uint64 bits = 0; + + if(objectType.type == bitClass) + { + switch(objectType.typeSize) + { + case 1: bits = (byte )*(uint64 *)object; break; + case 2: bits = (uint16)*(uint64 *)object; break; + case 4: bits = (uint32)*(uint64 *)object; break; + case 8: bits = (uint64)*(uint64 *)object; break; + } + } if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode))) { @@ -645,13 +680,7 @@ public: result = success; if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass)) - { *object = eInstance_New(objectType); - } - else if(objectType && objectType.type != structClass) - { - *object = eSystem_New(objectType.typeSize); - } while(result) { @@ -679,8 +708,10 @@ public: { SkipEmpty(); prop = null; member = null; - if(ch == '=') + if(ch == '=' || ch == ':') { + if(wasQuoted) + string[0] = (char)tolower(string[0]); while(1) { eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos); @@ -710,16 +741,16 @@ public: offset = member._class.offset + member.offset; } else if(prop) - type = eSystem_SuperFindClass(prop.dataTypeString, objectType.module); + type = superFindClass(prop.dataTypeString, objectType.module); else if(member) { - type = eSystem_SuperFindClass(member.dataTypeString, objectType.module); + type = superFindClass(member.dataTypeString, objectType.module); offset = member._class.offset + member.offset; } } else { - if(ch == '=') + if(ch == '=' || ch == ':') PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name); else PrintLn("Warning: default member assignment: no more members"); @@ -746,19 +777,31 @@ public: member = eClass_FindDataMember(objectType, string, objectType.module, null, null); if(member) { - type = eSystem_SuperFindClass(member.dataTypeString, objectType.module); + type = superFindClass(member.dataTypeString, objectType.module); offset = member._class.offset + member.offset; } else if(!member) { prop = eClass_FindProperty(objectType, string, objectType.module); if(prop) - type = eSystem_SuperFindClass(prop.dataTypeString, objectType.module); + type = superFindClass(prop.dataTypeString, objectType.module); else PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name); } } } + if(type && type.templateClass && type.templateClass == class(Container)) + { + char * br = strchr(type.fullName, '<'); + if(br) + { + char className[1024]; + strcpy(className, "Array"); + strcat(className, br); + type = superFindClass(className, objectType.module); + } + } + // Find Member in Object Class { DataValue value { }; @@ -780,12 +823,12 @@ public: ch = 0; SkipEmpty(); } - if(eCON && ch != '=') + if(eCON && ch != '=' && ch != ':') { f.Seek(seek-1, start); ch = 0; } - if(ch == (eCON ? '=' : ':') || (eCON && type && (prop || member))) + if((ch == ':' || (eCON && ch == '=')) || (eCON && type && (prop || member))) { JSONResult itemResult = GetValue(type, value); if(itemResult != syntaxError) @@ -796,6 +839,7 @@ public: PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString); else if(itemResult == success) { + BitMember bitMember = objectType.type == bitClass ? (BitMember) member : null; // Set value if(member) { @@ -815,41 +859,127 @@ public: } else if(type == class(double) || !strcmp(type.dataTypeString, "double")) { - *(double *)((byte *)*object + offset) = value.d; + if(objectType.type != bitClass) + { + *(double *)((byte *)*object + offset) = value.d; + } } else if(type == class(float) || !strcmp(type.dataTypeString, "float")) { - *(float *)((byte *)*object + offset) = value.f; + if(objectType.type != bitClass) + { + *(float *)((byte *)*object + offset) = value.f; + } } else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64")) { - *(uint64 *)((byte *)*object + offset) = value.ui64; + if(objectType.type == bitClass) + { + bits &= ~bitMember.mask; + bits |= (value.ui64 << bitMember.pos) & bitMember.mask; + } + else + { + *(uint64 *)((byte *)*object + offset) = value.ui64; + } } else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint")) { - *(int *)((byte *)*object + offset) = value.i; + if(objectType.type == bitClass) + { + bits &= ~bitMember.mask; + bits |= (value.ui << bitMember.pos) & bitMember.mask; + } + else + { + *(int *)((byte *)*object + offset) = value.i; + } } else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || !strcmp(type.dataTypeString, "int16")) { - *(short *)((byte *)*object + offset) = value.s; + if(objectType.type == bitClass) + { + bits &= ~bitMember.mask; + bits |= (value.us << bitMember.pos) & bitMember.mask; + } + else + { + *(short *)((byte *)*object + offset) = value.s; + } } else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte")) { - *(char *)((byte *)*object + offset) = value.c; + if(objectType.type == bitClass) + { + bits &= ~bitMember.mask; + bits |= (value.uc << bitMember.pos) & bitMember.mask; + } + else + { + *(char *)((byte *)*object + offset) = value.c; + } } else { - *(void **)((byte *)*object + offset) = value.p; + if(objectType.type != bitClass) + *(void **)((byte *)*object + offset) = value.p; } } else if(prop && prop.Set) { - if(!strcmp(type.dataTypeString, "char *")) + if(objectType.type == bitClass) + { + if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass) + { + switch(objectType.typeSize) + { + case 1: + switch(type.typeSize) + { + case 1: ((byte (*)(byte, byte)) (void *)prop.Set)((byte)bits, value.uc); break; + case 2: ((byte (*)(byte, uint16))(void *)prop.Set)((byte)bits, value.us); break; + case 4: ((byte (*)(byte, uint32))(void *)prop.Set)((byte)bits, value.ui); break; + case 8: ((byte (*)(byte, uint64))(void *)prop.Set)((byte)bits, value.ui64); break; + } + break; + case 2: + switch(type.typeSize) + { + case 1: ((uint16 (*)(uint16, byte)) (void *)prop.Set)((uint16)bits, value.uc); break; + case 2: ((uint16 (*)(uint16, uint16))(void *)prop.Set)((uint16)bits, value.us); break; + case 4: ((uint16 (*)(uint16, uint32))(void *)prop.Set)((uint16)bits, value.ui); break; + case 8: ((uint16 (*)(uint16, uint64))(void *)prop.Set)((uint16)bits, value.ui64); break; + } + break; + case 4: + switch(type.typeSize) + { + case 1: ((uint32 (*)(uint32, byte)) (void *)prop.Set)((uint32)bits, value.uc); break; + case 2: ((uint32 (*)(uint32, uint16))(void *)prop.Set)((uint32)bits, value.us); break; + case 4: ((uint32 (*)(uint32, uint32))(void *)prop.Set)((uint32)bits, value.ui); break; + case 8: ((uint32 (*)(uint32, uint64))(void *)prop.Set)((uint32)bits, value.ui64); break; + } + break; + case 8: + switch(type.typeSize) + { + case 1: ((uint64 (*)(uint64, byte)) (void *)prop.Set)((uint64)bits, value.uc); break; + case 2: ((uint64 (*)(uint64, uint16))(void *)prop.Set)((uint64)bits, value.us); break; + case 4: ((uint64 (*)(uint64, uint32))(void *)prop.Set)((uint64)bits, value.ui); break; + case 8: ((uint64 (*)(uint64, uint64))(void *)prop.Set)((uint64)bits, value.ui64); break; + } + break; + } + } + else + ; // TODO: Generate error + } + else if(!strcmp(type.dataTypeString, "char *")) { ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p); if(!isKey) @@ -933,6 +1063,17 @@ public: result = syntaxError; } } + + if(objectType.type == bitClass) + { + switch(objectType.typeSize) + { + case 1: *(uint64 *)object = (byte) bits; break; + case 2: *(uint64 *)object = (uint16) bits; break; + case 4: *(uint64 *)object = (uint32) bits; break; + case 8: *(uint64 *)object = (uint64) bits; break; + } + } } ch = 0; return result; @@ -944,10 +1085,12 @@ public: char buffer[256]; int c = 0; bool comment = false; + bool hexMode = false; if(eCON) { while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' || - tolower(ch) == 'x' || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/')) + (c == 1 && tolower(ch) == 'x' && buffer[0] == '0') || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/' || + (hexMode && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))))) { if(!comment && ch == '/') { @@ -976,7 +1119,11 @@ public: } } else if(!comment) + { + if(c == 1 && ch == 'x' && buffer[0] == '0') + hexMode = true; buffer[c++] = ch; + } if(!f.Getc(&ch)) break; } } @@ -1018,7 +1165,7 @@ public: value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support result = success; } - else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int")) + else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint")) { value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support result = success; @@ -1220,7 +1367,7 @@ static bool WriteArray(File f, Class type, Container array, int indent, bool eCO return true; } -static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON) +static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON, bool useHex) { char buffer[1024]; bool needClass = eCON; @@ -1233,11 +1380,21 @@ static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eC else if(!strcmp(type.dataTypeString, "int64")) ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass); else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64)) - ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass); + { + if(useHex) + sprintf(buffer, __runtimePlatform == win32 ? "0x%016I64X" : "0x%016llX", value.ui64); + else + ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass); + } else if(!strcmp(type.dataTypeString, "int")) ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass); else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int)) - ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass); + { + if(useHex) + sprintf(buffer, "0x%08X", value.ui); + else + ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass); + } else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16")) ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass); else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int)) @@ -1247,7 +1404,8 @@ static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eC else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte)) ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass); - quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))); + quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))) || + (type.type == enumClass && !eCON); if(quote) f.Puts("\""); f.Puts(buffer); if(quote) f.Puts("\""); @@ -1403,13 +1561,7 @@ static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCO f.Puts("unset"); } else if(type.type == enumClass) - { - if(!eCON) - f.Puts("\""); - WriteNumber(f, type, value, indent, eCON); - if(!eCON) - f.Puts("\""); - } + WriteNumber(f, type, value, indent, eCON, false); else if(eClass_IsDerived(type, class(Map))) { WriteMap(f, type, value.p, indent, eCON); @@ -1429,12 +1581,12 @@ static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCO else if(type.type == bitClass) { Class dataType; - dataType = eSystem_SuperFindClass(type.dataTypeString, type.module); - WriteNumber(f, dataType, value, indent, eCON); + dataType = superFindClass(type.dataTypeString, type.module); + WriteNumber(f, dataType, value, indent, eCON, true); } else if(type.type == systemClass || type.type == unitClass) { - WriteNumber(f, type, value, indent, eCON); + WriteNumber(f, type, value, indent, eCON, false); } return true; } @@ -1487,7 +1639,7 @@ static bool WriteONObject(File f, Class objectType, void * object, int indent, b } else { - Class _class = eCON ? ((Instance)object)._class : objectType; + Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType; Property prop; int c; bool isFirst = true; @@ -1541,7 +1693,7 @@ static bool WriteONObject(File f, Class objectType, void * object, int indent, b type = mapDataClass; } else - type = eSystem_SuperFindClass(prop.dataTypeString, _class.module); + type = superFindClass(prop.dataTypeString, _class.module); if(!type) PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString); @@ -1620,7 +1772,7 @@ static bool WriteONObject(File f, Class objectType, void * object, int indent, b DataMember member = (DataMember)prop; DataValue value { }; uint offset; - Class type = eSystem_SuperFindClass(member.dataTypeString, _class.module); + Class type = superFindClass(member.dataTypeString, _class.module); offset = member._class.offset + member.offset; if(type) @@ -1705,7 +1857,7 @@ static bool WriteONObject(File f, Class objectType, void * object, int indent, b return true; } -static Class eSystem_SuperFindClass(const String name, Module alternativeModule) +static Class superFindClass(const String name, Module alternativeModule) { Class _class = eSystem_FindClass(__thisModule, name); if(!_class && alternativeModule) @@ -1715,9 +1867,9 @@ static Class eSystem_SuperFindClass(const String name, Module alternativeModule) return _class; } -static bool isSubclass(const String name, Class type) +static bool isSubclass(Class type, const String name) { - Class _class = eSystem_SuperFindClass(name, type.module); + Class _class = superFindClass(name, type.module); if(eClass_IsDerived(_class, type)) return true; return false;