7 __attribute__((unused)) static void UnusedFunction()
10 a.OnGetDataFromString(null);
11 a.OnGetString(null, 0, 0);
14 extern int __ecereVMethodID_class_OnGetDataFromString;
15 extern int __ecereVMethodID_class_OnGetString;
16 extern int __ecereVMethodID_class_OnFree;
19 public enum JSONResult { syntaxError, success, typeMismatch, noItem };
21 public enum SetBool : uint
25 /*public property bool // NOT WORKING!
27 set { return value ? true : false; }
28 get { return (this == true); }
33 public class JSONParser
41 while(!f.Eof() && (!ch || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '/'))
47 JSONResult GetValue(Class type, DataValue value)
49 JSONResult result = syntaxError;
55 result = GetString(&string);
59 if(type && (!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *")))
63 else if(type && (type.type == enumClass || type.type == unitClass))
65 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
68 result = typeMismatch;
71 else if(type && (prop = eClass_FindProperty(type, "String", type.module)))
73 // TOFIX: Add more conversion property support... Expecting void * compatible here
74 value.p = ((void *(*)())(void *)prop.Set)(string);
78 else if(type && eClass_IsDerived(type, class(ColorAlpha)))
80 result = GetColorAlpha(string, value);
82 else if(type && (type.type == structClass))
84 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, value.p, string))
87 result = typeMismatch;
93 result = typeMismatch;
100 if(type && eClass_IsDerived(type, class(Map)))
102 result = GetMap(type, (Map *)&array);
105 result = GetArray(type, &array);
107 if(result == success && type && eClass_IsDerived(type, class(Container)))
116 if(result != success)
117 result = typeMismatch;
120 else if(ch == '-' || isdigit(ch))
122 result = GetNumber(type, value);
126 void * object = value.p;
127 result = GetObject(type, &object);
130 if(type && type.type == structClass);
131 else if(type && (type.type == normalClass || type.type == noHeadClass || type.type == bitClass))
137 result = typeMismatch;
139 ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, object);
147 while(c < sizeof(buffer)-1 && isalpha(ch))
150 if(!f.Getc(&ch)) break;
157 if(!strcmp(type.name, "bool"))
159 if(!strcmpi(buffer, "false")) value.i = 0;
160 else if(!strcmpi(buffer, "true")) value.i = 1;
162 result = typeMismatch;
164 else if(!strcmp(type.name, "SetBool"))
166 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
167 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
169 result = typeMismatch;
171 else if(!strcmpi(buffer, "null"))
173 if(type.type != structClass)
177 result = typeMismatch;
180 result = typeMismatch;
182 else if(ch == '}' || ch == ']')
187 JSONResult GetArray(Class type, Container * array)
189 JSONResult result = syntaxError;
194 *array = eInstance_New(type);
199 Class arrayType = null;
200 JSONResult itemResult;
202 if(eClass_IsDerived(type, class(Container)))
204 arrayType = type.templateArgs[0].dataTypeClass;
207 if(arrayType && arrayType.type == structClass)
208 value.p = new0 byte[arrayType.structSize];
209 itemResult = GetValue(arrayType, value);
210 if(itemResult == success)
212 // TODO: Verify the matching between template type and uint64
214 if(arrayType.type == structClass)
216 t = (uint64)(uintptr)value.p;
218 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
220 t = value.ui64; //*(uint64 *)&value.d;
222 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
224 t = value.ui; //f*(uint *)&value.f;
226 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
227 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
231 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
232 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
236 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
237 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
238 !strcmp(arrayType.dataTypeString, "int16"))
242 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
243 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
249 t = (uint64)(uintptr)value.p;
251 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
253 if(arrayType && arrayType.type == structClass)
258 if(itemResult == typeMismatch)
261 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
263 else if(itemResult == noItem)
269 if(result != syntaxError)
271 if(ch != ']' && ch != ',')
281 result = syntaxError;
289 JSONResult GetMap(Class type, Map * map)
291 JSONResult result = syntaxError;
296 Class mapNodeType = type.templateArgs[0].dataTypeClass;
297 Class keyType = mapNodeType.templateArgs[0].dataTypeClass;
298 Property keyProp = null;
299 if(keyType && !strcmp(keyType.dataTypeString, "char *"))
300 keyProp = eClass_FindProperty(mapNodeType, "key", mapNodeType.module);
302 *map = eInstance_New(type);
309 JSONResult itemResult;
311 itemResult = GetValue(mapNodeType, value);
312 if(itemResult == success)
314 String s = keyProp ? ((void * (*)(void *))(void *)keyProp.Get)(value.p) : null;
315 ((void *(*)(void *, uint64))(void *)map->Add)(*map, (uint64)(uintptr)value.p);
316 // Must free String keys here
321 if(itemResult == typeMismatch)
324 PrintLn("Warning: Incompatible value for array value, expected ", (String)mapNodeType.name);
326 else if(itemResult == noItem)
332 if(result != syntaxError)
334 if(ch != ']' && ch != ',')
344 result = syntaxError;
352 JSONResult GetString(String * string)
354 JSONResult result = syntaxError;
355 Array<char> buffer { minAllocSize = 256 };
356 bool escaped = false;
364 if(ch == '\\' && !escaped)
370 if(ch == 'b') ch = '\b';
371 else if(ch == 'f') ch = '\f';
372 else if(ch == 'n') ch = '\n';
373 else if(ch == 'r') ch = '\r';
374 else if(ch == 't') ch = '\t';
391 if(buffer.minAllocSize < buffer.count)
392 buffer.minAllocSize *= 2;
396 *string = CopyString(buffer.array);
400 if(ch != ',' && ch != '}')
405 public JSONResult GetObject(Class objectType, void ** object)
407 JSONResult result = syntaxError;
408 if(!objectType || objectType.type != structClass)
413 Class mapKeyClass = null, mapDataClass = null;
415 if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
417 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
418 mapDataClass = objectType.templateArgs[2].dataTypeClass;
422 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
424 *object = eInstance_New(objectType);
426 else if(objectType && objectType.type != structClass)
428 *object = eSystem_New(objectType.typeSize);
435 if(GetString(&string))
437 DataMember member = null;
438 Property prop = null;
441 bool isTemplateArg = false;
446 string[0] = (char)tolower(string[0]);
447 if(mapKeyClass && !strcmp(string, "key"))
449 prop = eClass_FindProperty(objectType, "key", objectType.module);
451 isTemplateArg = true;
454 else if(mapDataClass && !strcmp(string, "value"))
456 prop = eClass_FindProperty(objectType, "value", objectType.module);
458 isTemplateArg = true;
462 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
465 type = eSystem_FindClass(__thisModule, member.dataTypeString);
467 type = eSystem_FindClass(objectType.module, member.dataTypeString);
469 type = eSystem_FindClass(__thisModule.application, member.dataTypeString);
471 offset = member._class.offset + member.offset;
475 prop = eClass_FindProperty(objectType, string, objectType.module);
478 type = eSystem_FindClass(__thisModule, prop.dataTypeString);
480 type = eSystem_FindClass(objectType.module, prop.dataTypeString);
482 type = eSystem_FindClass(__thisModule.application, prop.dataTypeString);
485 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
489 // Find Member in Object Class
493 if(type && type.type == structClass)
497 value.p = (byte *)*object + offset;
498 memset(value.p, 0, type.structSize);
502 value.p = new0 byte[type.structSize];
509 JSONResult itemResult = GetValue(type, value);
510 if(itemResult != syntaxError)
516 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
518 else if(itemResult == success)
523 // TOFIX: How to swiftly handle classes with base data type?
524 if(type.type == structClass)
526 else if(type.type == normalClass || type.type == noHeadClass)
528 void ** ptr = (void**)((byte *)*object + offset);
529 if(eClass_IsDerived(type, class(Container)) && *ptr)
531 Container container = (Container)*ptr;
537 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
539 *(double *)((byte *)*object + offset) = value.d;
541 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
543 *(float *)((byte *)*object + offset) = value.f;
545 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
546 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
548 *(uint64 *)((byte *)*object + offset) = value.ui64;
550 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
551 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
553 *(int *)((byte *)*object + offset) = value.i;
555 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
556 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
557 !strcmp(type.dataTypeString, "int16"))
559 *(short *)((byte *)*object + offset) = value.s;
561 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
562 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
564 *(char *)((byte *)*object + offset) = value.c;
568 *(void **)((byte *)*object + offset) = value.p;
571 else if(prop && prop.Set)
573 if(!strcmp(type.dataTypeString, "char *"))
575 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
579 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
581 // TOFIX: How to swiftly handle classes with base data type?
582 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
584 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
586 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
588 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
590 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
591 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
593 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
595 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
596 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
598 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
600 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
601 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
602 !strcmp(type.dataTypeString, "int16"))
604 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
606 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
607 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
609 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
613 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
619 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
621 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
627 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
628 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
634 result = syntaxError;
636 if(prop && type && type.type == structClass)
642 else if(ch && ch != '}' && ch != ',')
643 result = syntaxError;
654 result = syntaxError;
662 JSONResult GetNumber(Class type, DataValue value)
664 JSONResult result = syntaxError;
667 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
670 if(!f.Getc(&ch)) break;
673 //if(strchr(buffer, '.'))
674 if(!type) return success;
676 // TOFIX: How to swiftly handle classes with base data type?
677 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
679 value.d = strtod(buffer, null);
682 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
684 value.f = (float)strtod(buffer, null);
687 // TOFIX: int64 looks for class long long?
688 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
689 else if(!strcmp(type.dataTypeString, "int64"))
691 value.i64 = strtol(buffer, null, 10); // TOFIX: 64 bit support
694 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
696 value.ui64 = strtoul(buffer, null, 10); // TOFIX: 64 bit support
699 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int"))
701 value.ui = (uint)strtoul(buffer, null, 10); // TOFIX: 64 bit support
706 value.i = (int)strtol(buffer, null, 10);
710 if(result == success && type.type == unitClass)
712 // Convert to reference unit
714 for(prop = type.conversions.first; prop; prop = prop.next)
716 bool refProp = false;
717 if(!strcmp(prop.name, type.base.fullName))
721 Class c = eSystem_FindClass(type.module, prop.name);
723 c = eSystem_FindClass(type.module.application, prop.name);
727 for(p = c.conversions.first; p; p = p.next)
729 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
739 if(prop.Set && prop.Get)
741 const String dts = type.base.dataTypeString;
742 if(!strcmp(dts, "double"))
743 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
744 else if(!strcmp(dts, "float"))
745 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
746 else if(!strcmp(dts, "int"))
747 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
748 else if(!strcmp(dts, "int64"))
749 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
750 else if(!strcmp(dts, "unsigned int"))
751 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
752 else if(!strcmp(dts, "uint64"))
753 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
763 JSONResult GetColorAlpha(String string, DataValue value)
765 ColorAlpha color = 0;
769 if(string[0] == '0' && string[1] == 'x')
770 color = (uint)strtoul(string, null, 0);
775 if((d = strchr(string, ',')))
777 a = (byte)atoi(string);
782 if(c.class::OnGetDataFromString(d))
788 color = (uint)strtoul(string, null, 16);
796 bool WriteMap(File f, Class type, Map map, int indent)
802 MapIterator it { map = map };
803 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
809 MapNode n = (MapNode)it.pointer;
814 for(i = 0; i<indent; i++) f.Puts(" ");
815 _WriteJSONObject(f, mapNodeClass, n, indent);
819 for(i = 0; i<indent; i++) f.Puts(" ");
827 bool WriteArray(File f, Class type, Container array, int indent)
833 Iterator it { array };
834 Class arrayType = type.templateArgs[0].dataTypeClass;
841 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
848 // TODO: Verify the matching between template type and uint64
849 if(arrayType.type == structClass)
851 value.p = (void *)(uintptr)t;
853 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
856 //value.d = *(double *)&t;
858 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
861 //value.f = *(float *)&t;
863 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
864 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
868 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
869 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
873 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
874 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
875 !strcmp(arrayType.dataTypeString, "int16"))
879 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
880 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
886 value.p = (void *)(uintptr)t;
888 for(i = 0; i<indent; i++) f.Puts(" ");
889 WriteValue(f, arrayType, value, indent);
893 for(i = 0; i<indent; i++) f.Puts(" ");
901 bool WriteNumber(File f, Class type, DataValue value, int indent)
904 bool needClass = false;
907 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
908 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
909 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
910 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
911 else if(!strcmp(type.dataTypeString, "int64"))
912 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
913 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
914 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
915 else if(!strcmp(type.dataTypeString, "int"))
916 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
917 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
918 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
919 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
920 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
921 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
922 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
923 else if(!strcmp(type.dataTypeString, "char"))
924 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
925 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
926 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
928 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' ')));
929 if(quote) f.Puts("\"");
931 if(quote) f.Puts("\"");
935 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent)
938 char * string = buffer;
939 ColorAlpha color = value.i;
942 DefinedColor c = color;
946 a.class::OnGetString(buffer, null, null);
947 len = strlen(buffer);
953 if(!c.class::OnGetString(string, null, null))
954 sprintf(buffer, "0x%x", color);
961 bool WriteValue(File f, Class type, DataValue value, int indent)
963 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
970 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
975 char * string = value.p;
994 else if(b == sizeof(buffer)-2 || !ch)
997 if(ch) buffer[b] = 0;
1011 else if(!strcmp(type.name, "bool"))
1018 else if(!strcmp(type.name, "SetBool"))
1020 if(value.i == SetBool::true)
1022 else if(value.i == SetBool::false)
1027 else if(type.type == enumClass)
1030 WriteNumber(f, type, value, indent);
1033 else if(eClass_IsDerived(type, class(Map)))
1035 WriteMap(f, type, value.p, indent);
1037 else if(eClass_IsDerived(type, class(Container)))
1039 WriteArray(f, type, value.p, indent);
1041 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1043 _WriteJSONObject(f, type, value.p, indent);
1045 else if(eClass_IsDerived(type, class(ColorAlpha)))
1047 WriteColorAlpha(f, type, value, indent);
1049 else if(type.type == bitClass)
1052 dataType = eSystem_FindClass(__thisModule, type.dataTypeString);
1054 dataType = eSystem_FindClass(type.module, type.dataTypeString);
1056 dataType = eSystem_FindClass(__thisModule.application, type.dataTypeString);
1057 WriteNumber(f, dataType, value, indent);
1059 else if(type.type == systemClass || type.type == unitClass)
1061 WriteNumber(f, type, value, indent);
1066 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1068 bool result = false;
1071 result = _WriteJSONObject(f, objectType, object, indent);
1077 static bool _WriteJSONObject(File f, Class objectType, void * object, int indent)
1081 const char * string = null;
1083 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1087 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1091 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1092 if(string[0] == '\"')
1105 bool isFirst = true;
1106 Class mapKeyClass = null, mapDataClass = null;
1108 List<Class> bases { };
1110 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1112 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1113 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1119 for(baseClass = objectType; baseClass; baseClass = baseClass.base)
1121 if(baseClass.isInstanceClass || !baseClass.base)
1123 bases.Insert(null, baseClass);
1126 for(baseClass : bases)
1128 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1130 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1133 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1135 DataValue value { };
1136 bool isTemplateArg = false;
1139 if(mapKeyClass && !strcmp(prop.name, "key"))
1141 isTemplateArg = true;
1144 else if(mapDataClass && !strcmp(prop.name, "value"))
1146 isTemplateArg = true;
1147 type = mapDataClass;
1150 type = eSystem_FindClass(__thisModule, prop.dataTypeString);
1153 type = eSystem_FindClass(objectType.module, prop.dataTypeString);
1155 type = eSystem_FindClass(__thisModule.application, prop.dataTypeString);
1157 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1160 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1162 // TOFIX: How to swiftly handle classes with base data type?
1163 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1165 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1167 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1169 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1171 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1172 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1174 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1176 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1177 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1179 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1181 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1182 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1183 !strcmp(type.dataTypeString, "int16"))
1185 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1187 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1188 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1190 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1193 else if(type.type == structClass)
1195 value.p = new0 byte[type.structSize];
1196 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1201 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1203 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1206 if(!isFirst) f.Puts(",\n");
1207 for(c = 0; c<indent; c++) f.Puts(" ");
1210 f.Putc((char)toupper(prop.name[0]));
1211 f.Puts(prop.name+1);
1213 WriteValue(f, type, value, indent);
1215 if(type.type == structClass)
1222 DataMember member = (DataMember)prop;
1223 DataValue value { };
1225 Class type = eSystem_FindClass(__thisModule, member.dataTypeString);
1227 type = eSystem_FindClass(objectType.module, member.dataTypeString);
1229 type = eSystem_FindClass(__thisModule.application, member.dataTypeString);
1231 offset = member._class.offset + member.offset;
1235 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1237 if(type.type == structClass)
1238 value.p = (void *)((byte *)object + offset);
1240 value.p = *(void **)((byte *)object + offset);
1244 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1246 value.d = *(double *)((byte *)object + offset);
1248 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1250 value.f = *(float *)((byte *)object + offset);
1252 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1253 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1255 value.ui64 = *(uint64 *)((byte *)object + offset);
1257 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1258 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1260 value.i = *(int *)((byte *)object + offset);
1261 if(!strcmp(type.name, "bool") || type.type == enumClass)
1265 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1266 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1267 !strcmp(type.dataTypeString, "int16"))
1269 value.s = *(short *)((byte *)object + offset);
1271 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1272 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1274 value.c = *(char *)((byte *)object + offset);
1278 value.i = *(int *)((byte *)object + offset);
1281 if(!isFirst) f.Puts(",\n");
1282 for(c = 0; c<indent; c++) f.Puts(" ");
1285 f.Putc((char)toupper(member.name[0]));
1286 f.Puts(member.name+1);
1288 WriteValue(f, type, value, indent);
1299 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");