8 __attribute__((unused)) static void UnusedFunction()
11 a.OnGetDataFromString(null);
12 a.OnGetString(null, 0, 0);
15 extern int __ecereVMethodID_class_OnGetDataFromString;
16 extern int __ecereVMethodID_class_OnGetString;
17 extern int __ecereVMethodID_class_OnFree;
20 public enum JSONResult { syntaxError, success, typeMismatch, noItem };
22 public enum SetBool : uint
26 /*public property bool // NOT WORKING!
28 set { return value ? true : false; }
29 get { return (this == true); }
34 public class JSONParser
42 while(!f.Eof() && (!ch || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'))
48 JSONResult GetValue(Class type, DataValue value)
50 JSONResult result = syntaxError;
56 result = GetString(&string);
60 if(type && (!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *")))
64 else if(type && (type.type == enumClass || type.type == unitClass))
66 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
69 result = typeMismatch;
72 else if(type && (prop = eClass_FindProperty(type, "String", type.module)))
74 // TOFIX: Add more conversion property support... Expecting void * compatible here
75 value.p = ((void *(*)())(void *)prop.Set)(string);
79 else if(type && eClass_IsDerived(type, class(ColorAlpha)))
81 result = GetColorAlpha(string, value);
84 else if(type && (type.type == structClass))
86 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, value.p, string))
89 result = typeMismatch;
95 result = typeMismatch;
102 if(type && eClass_IsDerived(type, class(Map)))
104 result = GetMap(type, (Map *)&array);
107 result = GetArray(type, &array);
109 if(result == success && type && eClass_IsDerived(type, class(Container)))
118 if(result != success)
119 result = typeMismatch;
122 else if(ch == '-' || isdigit(ch))
124 result = GetNumber(type, value);
128 void * object = value.p;
129 result = GetObject(type, &object);
132 if(type && type.type == structClass);
133 else if(type && (type.type == normalClass || type.type == noHeadClass || type.type == bitClass))
139 result = typeMismatch;
141 ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, object);
149 while(c < sizeof(buffer)-1 && isalpha(ch))
152 if(!f.Getc(&ch)) break;
159 if(!strcmp(type.name, "bool"))
161 if(!strcmpi(buffer, "false")) value.i = 0;
162 else if(!strcmpi(buffer, "true")) value.i = 1;
164 result = typeMismatch;
166 else if(!strcmp(type.name, "SetBool"))
168 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
169 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
171 result = typeMismatch;
173 else if(!strcmpi(buffer, "null"))
175 if(type.type != structClass)
179 result = typeMismatch;
182 result = typeMismatch;
184 else if(ch == '}' || ch == ']')
189 JSONResult GetArray(Class type, Container * array)
191 JSONResult result = syntaxError;
196 *array = eInstance_New(type);
201 Class arrayType = null;
202 JSONResult itemResult;
204 if(eClass_IsDerived(type, class(Container)))
206 arrayType = type.templateArgs[0].dataTypeClass;
209 if(arrayType && arrayType.type == structClass)
210 value.p = new0 byte[arrayType.structSize];
211 itemResult = GetValue(arrayType, value);
212 if(itemResult == success)
214 // TODO: Verify the matching between template type and uint64
216 if(arrayType.type == structClass)
218 t = (uint64)(uintptr)value.p;
220 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
222 t = value.ui64; //*(uint64 *)&value.d;
224 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
226 t = value.ui; //f*(uint *)&value.f;
228 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
229 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
233 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
234 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
238 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
239 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
240 !strcmp(arrayType.dataTypeString, "int16"))
244 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
245 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
251 t = (uint64)(uintptr)value.p;
253 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
255 if(arrayType && arrayType.type == structClass)
260 if(itemResult == typeMismatch)
263 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
265 else if(itemResult == noItem)
271 if(result != syntaxError)
273 if(ch != ']' && ch != ',')
283 result = syntaxError;
291 JSONResult GetMap(Class type, Map * map)
293 JSONResult result = syntaxError;
298 Class mapNodeType = type.templateArgs[0].dataTypeClass;
299 Class keyType = mapNodeType.templateArgs[0].dataTypeClass;
300 Property keyProp = null;
301 if(keyType && !strcmp(keyType.dataTypeString, "char *"))
302 keyProp = eClass_FindProperty(mapNodeType, "key", mapNodeType.module);
304 *map = eInstance_New(type);
311 JSONResult itemResult;
313 itemResult = GetValue(mapNodeType, value);
314 if(itemResult == success)
316 String s = keyProp ? ((void * (*)(void *))(void *)keyProp.Get)(value.p) : null;
317 ((void *(*)(void *, uint64))(void *)map->Add)(*map, (uint64)(uintptr)value.p);
318 // Must free String keys here
323 if(itemResult == typeMismatch)
326 PrintLn("Warning: Incompatible value for array value, expected ", (String)mapNodeType.name);
328 else if(itemResult == noItem)
334 if(result != syntaxError)
336 if(ch != ']' && ch != ',')
346 result = syntaxError;
354 JSONResult GetString(String * string)
356 JSONResult result = syntaxError;
357 Array<char> buffer { minAllocSize = 256 };
358 bool escaped = false;
366 if(ch == '\\' && !escaped)
372 if(ch == 'b') ch = '\b';
373 else if(ch == 'f') ch = '\f';
374 else if(ch == 'n') ch = '\n';
375 else if(ch == 'r') ch = '\r';
376 else if(ch == 't') ch = '\t';
393 if(buffer.minAllocSize < buffer.count)
394 buffer.minAllocSize *= 2;
398 *string = CopyString(buffer.array);
402 if(ch != ',' && ch != '}')
407 public JSONResult GetObject(Class objectType, void ** object)
409 JSONResult result = syntaxError;
410 if(!objectType || objectType.type != structClass)
415 Class mapKeyClass = null, mapDataClass = null;
417 if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
419 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
420 mapDataClass = objectType.templateArgs[2].dataTypeClass;
424 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
426 *object = eInstance_New(objectType);
428 else if(objectType && objectType.type != structClass)
430 *object = eSystem_New(objectType.typeSize);
437 if(GetString(&string))
439 DataMember member = null;
440 Property prop = null;
443 bool isTemplateArg = false;
448 string[0] = (char)tolower(string[0]);
449 if(mapKeyClass && !strcmp(string, "key"))
451 prop = eClass_FindProperty(objectType, "key", objectType.module);
453 isTemplateArg = true;
456 else if(mapDataClass && !strcmp(string, "value"))
458 prop = eClass_FindProperty(objectType, "value", objectType.module);
460 isTemplateArg = true;
464 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
467 type = eSystem_FindClass(__thisModule, member.dataTypeString);
469 type = eSystem_FindClass(objectType.module, member.dataTypeString);
471 type = eSystem_FindClass(__thisModule.application, member.dataTypeString);
473 offset = member._class.offset + member.offset;
477 prop = eClass_FindProperty(objectType, string, objectType.module);
480 type = eSystem_FindClass(__thisModule, prop.dataTypeString);
482 type = eSystem_FindClass(objectType.module, prop.dataTypeString);
484 type = eSystem_FindClass(__thisModule.application, prop.dataTypeString);
487 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
491 // Find Member in Object Class
495 if(type && type.type == structClass)
499 value.p = (byte *)*object + offset;
500 memset(value.p, 0, type.structSize);
504 value.p = new0 byte[type.structSize];
511 JSONResult itemResult = GetValue(type, value);
512 if(itemResult != syntaxError)
518 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
520 else if(itemResult == success)
525 // TOFIX: How to swiftly handle classes with base data type?
526 if(type.type == structClass)
528 else if(type.type == normalClass || type.type == noHeadClass)
530 void ** ptr = (void**)((byte *)*object + offset);
531 if(eClass_IsDerived(type, class(Container)) && *ptr)
533 Container container = (Container)*ptr;
539 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
541 *(double *)((byte *)*object + offset) = value.d;
543 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
545 *(float *)((byte *)*object + offset) = value.f;
547 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
548 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
550 *(uint64 *)((byte *)*object + offset) = value.ui64;
552 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
553 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
555 *(int *)((byte *)*object + offset) = value.i;
557 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
558 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
559 !strcmp(type.dataTypeString, "int16"))
561 *(short *)((byte *)*object + offset) = value.s;
563 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
564 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
566 *(char *)((byte *)*object + offset) = value.c;
570 *(void **)((byte *)*object + offset) = value.p;
573 else if(prop && prop.Set)
575 if(!strcmp(type.dataTypeString, "char *"))
577 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
581 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
583 // TOFIX: How to swiftly handle classes with base data type?
584 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
586 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
588 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
590 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
592 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
593 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
595 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
597 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
598 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
600 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
602 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
603 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
604 !strcmp(type.dataTypeString, "int16"))
606 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
608 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
609 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
611 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
615 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
621 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
623 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
629 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
630 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
636 result = syntaxError;
638 if(prop && type && type.type == structClass)
644 else if(ch && ch != '}' && ch != ',')
645 result = syntaxError;
656 result = syntaxError;
664 JSONResult GetNumber(Class type, DataValue value)
666 JSONResult result = syntaxError;
669 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
672 if(!f.Getc(&ch)) break;
675 //if(strchr(buffer, '.'))
676 if(!type) return success;
678 // TOFIX: How to swiftly handle classes with base data type?
679 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
681 value.d = strtod(buffer, null);
684 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
686 value.f = (float)strtod(buffer, null);
689 // TOFIX: int64 looks for class long long?
690 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
691 else if(!strcmp(type.dataTypeString, "int64"))
693 value.i64 = strtol(buffer, null, 10); // TOFIX: 64 bit support
696 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
698 value.ui64 = strtoul(buffer, null, 10); // TOFIX: 64 bit support
701 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int"))
703 value.ui = (uint)strtoul(buffer, null, 10); // TOFIX: 64 bit support
708 value.i = (int)strtol(buffer, null, 10);
712 if(result == success && type.type == unitClass)
714 // Convert to reference unit
716 for(prop = type.conversions.first; prop; prop = prop.next)
718 bool refProp = false;
719 if(!strcmp(prop.name, type.base.fullName))
723 Class c = eSystem_FindClass(type.module, prop.name);
725 c = eSystem_FindClass(type.module.application, prop.name);
729 for(p = c.conversions.first; p; p = p.next)
731 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
741 if(prop.Set && prop.Get)
743 const String dts = type.base.dataTypeString;
744 if(!strcmp(dts, "double"))
745 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
746 else if(!strcmp(dts, "float"))
747 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
748 else if(!strcmp(dts, "int"))
749 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
750 else if(!strcmp(dts, "int64"))
751 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
752 else if(!strcmp(dts, "unsigned int"))
753 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
754 else if(!strcmp(dts, "uint64"))
755 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
765 JSONResult GetColorAlpha(String string, DataValue value)
767 ColorAlpha color = 0;
771 if(string[0] == '0' && string[1] == 'x')
772 color = (uint)strtoul(string, null, 0);
777 if((d = strchr(string, ',')))
779 a = (byte)atoi(string);
784 if(c.class::OnGetDataFromString(d))
790 color = (uint)strtoul(string, null, 16);
798 bool WriteMap(File f, Class type, Map map, int indent)
804 MapIterator it { map = map };
805 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
811 MapNode n = (MapNode)it.pointer;
816 for(i = 0; i<indent; i++) f.Puts(" ");
817 _WriteJSONObject(f, mapNodeClass, n, indent);
821 for(i = 0; i<indent; i++) f.Puts(" ");
829 bool WriteArray(File f, Class type, Container array, int indent)
835 Iterator it { array };
836 Class arrayType = type.templateArgs[0].dataTypeClass;
843 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
850 // TODO: Verify the matching between template type and uint64
851 if(arrayType.type == structClass)
853 value.p = (void *)(uintptr)t;
855 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
858 //value.d = *(double *)&t;
860 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
863 //value.f = *(float *)&t;
865 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
866 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
870 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
871 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
875 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
876 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
877 !strcmp(arrayType.dataTypeString, "int16"))
881 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
882 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
888 value.p = (void *)(uintptr)t;
890 for(i = 0; i<indent; i++) f.Puts(" ");
891 WriteValue(f, arrayType, value, indent);
895 for(i = 0; i<indent; i++) f.Puts(" ");
903 bool WriteNumber(File f, Class type, DataValue value, int indent)
906 bool needClass = false;
909 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
910 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
911 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
912 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
913 else if(!strcmp(type.dataTypeString, "int64"))
914 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
915 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
916 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
917 else if(!strcmp(type.dataTypeString, "int"))
918 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
919 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
920 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
921 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
922 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
923 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
924 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
925 else if(!strcmp(type.dataTypeString, "char"))
926 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
927 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
928 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
930 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' ')));
931 if(quote) f.Puts("\"");
933 if(quote) f.Puts("\"");
937 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent)
940 char * string = buffer;
941 ColorAlpha color = value.i;
944 DefinedColor c = color;
948 a.class::OnGetString(buffer, null, null);
949 len = strlen(buffer);
955 if(!c.class::OnGetString(string, null, null))
956 sprintf(buffer, "0x%x", color);
963 bool WriteValue(File f, Class type, DataValue value, int indent)
965 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
972 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
977 char * string = value.p;
996 else if(b == sizeof(buffer)-2 || !ch)
999 if(ch) buffer[b] = 0;
1013 else if(!strcmp(type.name, "bool"))
1020 else if(!strcmp(type.name, "SetBool"))
1022 if(value.i == SetBool::true)
1024 else if(value.i == SetBool::false)
1029 else if(type.type == enumClass)
1032 WriteNumber(f, type, value, indent);
1035 else if(eClass_IsDerived(type, class(Map)))
1037 WriteMap(f, type, value.p, indent);
1039 else if(eClass_IsDerived(type, class(Container)))
1041 WriteArray(f, type, value.p, indent);
1043 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1045 _WriteJSONObject(f, type, value.p, indent);
1047 else if(eClass_IsDerived(type, class(ColorAlpha)))
1049 WriteColorAlpha(f, type, value, indent);
1051 else if(type.type == bitClass)
1054 dataType = eSystem_FindClass(__thisModule, type.dataTypeString);
1056 dataType = eSystem_FindClass(type.module, type.dataTypeString);
1058 dataType = eSystem_FindClass(__thisModule.application, type.dataTypeString);
1059 WriteNumber(f, dataType, value, indent);
1061 else if(type.type == systemClass || type.type == unitClass)
1063 WriteNumber(f, type, value, indent);
1068 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1070 bool result = false;
1073 result = _WriteJSONObject(f, objectType, object, indent);
1079 static bool _WriteJSONObject(File f, Class objectType, void * object, int indent)
1083 const char * string = null;
1085 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1089 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1093 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1094 if(string[0] == '\"')
1107 bool isFirst = true;
1108 Class mapKeyClass = null, mapDataClass = null;
1110 List<Class> bases { };
1112 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1114 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1115 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1121 for(baseClass = objectType; baseClass; baseClass = baseClass.base)
1123 if(baseClass.isInstanceClass || !baseClass.base)
1125 bases.Insert(null, baseClass);
1128 for(baseClass : bases)
1130 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1132 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1135 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1137 DataValue value { };
1138 bool isTemplateArg = false;
1141 if(mapKeyClass && !strcmp(prop.name, "key"))
1143 isTemplateArg = true;
1146 else if(mapDataClass && !strcmp(prop.name, "value"))
1148 isTemplateArg = true;
1149 type = mapDataClass;
1152 type = eSystem_FindClass(__thisModule, prop.dataTypeString);
1155 type = eSystem_FindClass(objectType.module, prop.dataTypeString);
1157 type = eSystem_FindClass(__thisModule.application, prop.dataTypeString);
1159 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1162 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1164 // TOFIX: How to swiftly handle classes with base data type?
1165 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1167 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1169 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1171 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1173 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1174 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1176 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1178 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1179 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1181 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1183 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1184 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1185 !strcmp(type.dataTypeString, "int16"))
1187 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1189 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1190 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1192 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1195 else if(type.type == structClass)
1197 value.p = new0 byte[type.structSize];
1198 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1203 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1205 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1208 if(!isFirst) f.Puts(",\n");
1209 for(c = 0; c<indent; c++) f.Puts(" ");
1212 f.Putc((char)toupper(prop.name[0]));
1213 f.Puts(prop.name+1);
1215 WriteValue(f, type, value, indent);
1217 if(type.type == structClass)
1224 DataMember member = (DataMember)prop;
1225 DataValue value { };
1227 Class type = eSystem_FindClass(__thisModule, member.dataTypeString);
1229 type = eSystem_FindClass(objectType.module, member.dataTypeString);
1231 type = eSystem_FindClass(__thisModule.application, member.dataTypeString);
1233 offset = member._class.offset + member.offset;
1237 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1239 if(type.type == structClass)
1240 value.p = (void *)((byte *)object + offset);
1242 value.p = *(void **)((byte *)object + offset);
1246 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1248 value.d = *(double *)((byte *)object + offset);
1250 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1252 value.f = *(float *)((byte *)object + offset);
1254 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1255 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1257 value.ui64 = *(uint64 *)((byte *)object + offset);
1259 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1260 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1262 value.i = *(int *)((byte *)object + offset);
1263 if(!strcmp(type.name, "bool") || type.type == enumClass)
1267 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1268 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1269 !strcmp(type.dataTypeString, "int16"))
1271 value.s = *(short *)((byte *)object + offset);
1273 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1274 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1276 value.c = *(char *)((byte *)object + offset);
1280 value.i = *(int *)((byte *)object + offset);
1283 if(!isFirst) f.Puts(",\n");
1284 for(c = 0; c<indent; c++) f.Puts(" ");
1287 f.Putc((char)toupper(member.name[0]));
1288 f.Puts(member.name+1);
1290 WriteValue(f, type, value, indent);
1301 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");