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
47 bool lineComment = false;
49 while(!f.Eof() && (!ch || lineComment || comment || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '/'))
53 if(!lineComment && !comment && pch == '/')
60 else if(lineComment && ch == '\n')
62 else if(comment && pch == '*' && ch == '/')
68 while(!f.Eof() && (!ch || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '/'))
75 void SkipExtraSemicolon()
77 while(!f.Eof() && (!ch || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == ';'))
83 JSONResult GetValue(Class type, DataValue value)
85 JSONResult result = syntaxError;
91 result = GetString(&string);
95 if(type && (!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *")))
99 else if(type && (type.type == enumClass || type.type == unitClass))
101 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
104 result = typeMismatch;
107 else if(type && (prop = eClass_FindProperty(type, "String", type.module)))
109 // TOFIX: Add more conversion property support... Expecting void * compatible here
110 value.p = ((void *(*)())(void *)prop.Set)(string);
114 else if(type && eClass_IsDerived(type, class(ColorAlpha)))
116 result = GetColorAlpha(string, value);
119 else if(type && (type.type == structClass))
121 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, value.p, string))
124 result = typeMismatch;
130 result = typeMismatch;
137 if(type && eClass_IsDerived(type, class(Map)))
139 result = GetMap(type, (Map *)&array);
142 result = GetArray(type, &array);
144 if(result == success && type && eClass_IsDerived(type, class(Container)))
153 if(result != success)
154 result = typeMismatch;
157 else if(ch == '-' || isdigit(ch))
159 result = GetNumber(type, value);
163 void * object = value.p;
164 result = GetObject(type, &object);
167 if(type && type.type == structClass);
168 else if(type && (type.type == normalClass || type.type == noHeadClass || type.type == bitClass))
174 result = typeMismatch;
176 ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, object);
185 if(GetIdentifier(&string, null))
188 if(eCON && (type.type == enumClass || type.type == unitClass))
190 // should this be set by calling __ecereVMethodID_class_OnGetDataFromString ?
191 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
194 result = typeMismatch;
196 else if(type && !strcmp(type.name, "bool"))
198 if(!strcmpi(string, "false")) value.i = 0;
199 else if(!strcmpi(string, "true")) value.i = 1;
201 result = typeMismatch;
203 else if(type && !strcmp(type.name, "SetBool"))
205 if(!strcmpi(string, "false")) value.i = SetBool::false;
206 else if(!strcmpi(string, "true")) value.i = SetBool::true;
208 result = typeMismatch;
210 else if(type && !strcmpi(string, "null"))
212 if(type.type != structClass)
215 else if(isSubclass(string, type))
217 void * object = value.p;
218 Class subtype = eSystem_SuperFindClass(string, type.module);
220 result = GetObject(subtype, &object);
223 if(subtype && subtype.type == structClass);
224 else if(subtype && (subtype.type == normalClass || subtype.type == noHeadClass || subtype.type == bitClass))
230 result = typeMismatch;
232 ((void (*)(void *, void *))(void *)subtype._vTbl[__ecereVMethodID_class_OnFree])(subtype, object);
237 result = typeMismatch;
245 while(c < sizeof(buffer)-1 && isalpha(ch))
248 if(!f.Getc(&ch)) break;
255 if(!strcmp(type.name, "bool"))
257 if(!strcmpi(buffer, "false")) value.i = 0;
258 else if(!strcmpi(buffer, "true")) value.i = 1;
260 result = typeMismatch;
262 else if(!strcmp(type.name, "SetBool"))
264 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
265 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
267 result = typeMismatch;
269 else if(!strcmpi(buffer, "null"))
271 if(type.type != structClass)
275 result = typeMismatch;
278 result = typeMismatch;
281 else if(ch == '}' || ch == ']')
283 if(result == typeMismatch)
284 PrintLn("Warning: Value type mismatch");
288 JSONResult GetArray(Class type, Container * array)
290 JSONResult result = syntaxError;
295 *array = eInstance_New(type);
300 Class arrayType = null;
301 JSONResult itemResult;
303 if(eClass_IsDerived(type, class(Container)))
305 arrayType = type.templateArgs[0].dataTypeClass;
308 if(arrayType && arrayType.type == structClass)
309 value.p = new0 byte[arrayType.structSize];
310 itemResult = GetValue(arrayType, value);
311 if(itemResult == success)
313 // TODO: Verify the matching between template type and uint64
315 if(arrayType.type == structClass)
317 t = (uint64)(uintptr)value.p;
319 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
321 t = value.ui64; //*(uint64 *)&value.d;
323 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
325 t = value.ui; //f*(uint *)&value.f;
327 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
328 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
332 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
333 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
337 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
338 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
339 !strcmp(arrayType.dataTypeString, "int16"))
343 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
344 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
350 t = (uint64)(uintptr)value.p;
352 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
354 if(arrayType && arrayType.type == structClass)
359 if(itemResult == typeMismatch)
362 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
364 else if(itemResult == noItem)
370 if(result != syntaxError)
372 if(ch != ']' && ch != ',')
382 result = syntaxError;
390 JSONResult GetMap(Class type, Map * map)
392 JSONResult result = syntaxError;
397 Class mapNodeType = type.templateArgs[0].dataTypeClass;
398 Class keyType = mapNodeType.templateArgs[0].dataTypeClass;
399 Property keyProp = null;
400 if(keyType && !strcmp(keyType.dataTypeString, "char *"))
401 keyProp = eClass_FindProperty(mapNodeType, "key", mapNodeType.module);
403 *map = eInstance_New(type);
410 JSONResult itemResult;
412 itemResult = GetValue(mapNodeType, value);
413 if(itemResult == success)
415 String s = keyProp ? ((void * (*)(void *))(void *)keyProp.Get)(value.p) : null;
416 ((void *(*)(void *, uint64))(void *)map->Add)(*map, (uint64)(uintptr)value.p);
417 // Must free String keys here
422 if(itemResult == typeMismatch)
425 PrintLn("Warning: Incompatible value for array value, expected ", (String)mapNodeType.name);
427 else if(itemResult == noItem)
433 if(result != syntaxError)
435 if(ch != ']' && ch != ',')
445 result = syntaxError;
453 JSONResult GetIdentifier(String * string, bool * wasQuoted)
455 JSONResult result = syntaxError;
456 Array<char> buffer { minAllocSize = 256 };
457 bool comment = false;
469 if(!comment && ch == '/')
479 result = syntaxError;
485 result = syntaxError;
489 else if(comment && ch == '*')
501 result = syntaxError;
505 else if(ch == '\"' || (!comment && ch && !isalpha(ch)))
507 if(quoted && ch == '\"' && wasQuoted)
511 else if(!comment && ch)
514 if(buffer.minAllocSize < buffer.count)
515 buffer.minAllocSize *= 2;
518 if(result != syntaxError)
521 *string = CopyString(buffer.array);
524 if(ch != ',' && ch != '}' && ch != ';' && ch != '/' && ch != '=')
529 JSONResult GetString(String * string)
531 JSONResult result = syntaxError;
532 Array<char> buffer { minAllocSize = 256 };
533 bool escaped = false;
537 if(ch == '\"' || eCON)
541 if(ch == '\\' && !escaped)
547 if(ch == 'b') ch = '\b';
548 else if(ch == 'f') ch = '\f';
549 else if(ch == 'n') ch = '\n';
550 else if(ch == 'r') ch = '\r';
551 else if(ch == 't') ch = '\t';
563 else if(eCON && ch == '\"')
567 bool lineComment = false;
568 bool comment = false;
574 if(!lineComment && !comment && pch == '/')
581 else if(lineComment && ch == '\n')
583 else if(comment && pch == '*' && ch == '/')
585 else if(ch == '=' || ch == ';' || ch == ',' || ch == '}')
600 f.Seek(seekback, current);
604 else if((!eCON && ch == '\"'))
611 if(buffer.minAllocSize < buffer.count)
612 buffer.minAllocSize *= 2;
617 *string = CopyString(buffer.array);
621 if(ch != ',' && ch != '}' && (!eCON || (ch != ';' && ch != '/')))
626 public JSONResult GetObject(Class objectType, void ** object)
628 JSONResult result = syntaxError;
629 if(!objectType || objectType.type != structClass)
634 Class mapKeyClass = null, mapDataClass = null;
635 Class curClass = null;
636 DataMember curMember = null;
637 DataMember subMemberStack[256];
638 int subMemberStackPos = 0;
640 if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
642 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
643 mapDataClass = objectType.templateArgs[2].dataTypeClass;
647 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
649 *object = eInstance_New(objectType);
651 else if(objectType && objectType.type != structClass)
653 *object = eSystem_New(objectType.typeSize);
659 bool wasQuoted = false;
664 SkipExtraSemicolon();
670 if(eCON ? GetIdentifier(&string, &wasQuoted) : GetString(&string))
672 DataMember member = null;
673 Property prop = null;
676 bool isTemplateArg = false;
681 prop = null; member = null;
686 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
687 if(!curMember) break;
688 if(!strcmp(curMember.name, string))
693 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
696 prop = curMember.isProperty ? (Property)curMember : null;
697 member = curMember.isProperty ? null : curMember;
699 if(mapKeyClass && !strcmp(prop ? prop.name : member.name, "key"))
702 isTemplateArg = true;
705 else if(mapDataClass && !strcmp(prop ? prop.name : member.name, "value"))
708 isTemplateArg = true;
710 offset = member._class.offset + member.offset;
713 type = eSystem_SuperFindClass(prop.dataTypeString, objectType.module);
716 type = eSystem_SuperFindClass(member.dataTypeString, objectType.module);
717 offset = member._class.offset + member.offset;
723 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
725 PrintLn("Warning: default member assignment: no more members");
728 if(objectType && !eCON)
730 string[0] = (char)tolower(string[0]);
731 if(mapKeyClass && !strcmp(string, "key"))
733 prop = eClass_FindProperty(objectType, "key", objectType.module);
735 isTemplateArg = true;
738 else if(mapDataClass && !strcmp(string, "value"))
740 prop = eClass_FindProperty(objectType, "value", objectType.module);
742 isTemplateArg = true;
746 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
749 type = eSystem_SuperFindClass(member.dataTypeString, objectType.module);
750 offset = member._class.offset + member.offset;
754 prop = eClass_FindProperty(objectType, string, objectType.module);
756 type = eSystem_SuperFindClass(prop.dataTypeString, objectType.module);
758 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
762 // Find Member in Object Class
766 if(type && type.type == structClass)
770 value.p = (byte *)*object + offset;
771 memset(value.p, 0, type.structSize);
775 value.p = new0 byte[type.structSize];
783 if(eCON && ch != '=')
785 f.Seek(seek-1, start);
788 if(ch == (eCON ? '=' : ':') || (eCON && type && (prop || member)))
790 JSONResult itemResult = GetValue(type, value);
791 if(itemResult != syntaxError)
796 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
797 else if(itemResult == success)
802 // TOFIX: How to swiftly handle classes with base data type?
803 if(type.type == structClass)
805 else if(type.type == normalClass || type.type == noHeadClass)
807 void ** ptr = (void**)((byte *)*object + offset);
808 if(eClass_IsDerived(type, class(Container)) && *ptr)
810 Container container = (Container)*ptr;
816 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
818 *(double *)((byte *)*object + offset) = value.d;
820 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
822 *(float *)((byte *)*object + offset) = value.f;
824 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
825 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
827 *(uint64 *)((byte *)*object + offset) = value.ui64;
829 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
830 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
832 *(int *)((byte *)*object + offset) = value.i;
834 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
835 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
836 !strcmp(type.dataTypeString, "int16"))
838 *(short *)((byte *)*object + offset) = value.s;
840 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
841 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
843 *(char *)((byte *)*object + offset) = value.c;
847 *(void **)((byte *)*object + offset) = value.p;
850 else if(prop && prop.Set)
852 if(!strcmp(type.dataTypeString, "char *"))
854 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
858 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
860 // TOFIX: How to swiftly handle classes with base data type?
861 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
863 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
865 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
867 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
869 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
870 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
872 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
874 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
875 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
877 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
879 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
880 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
881 !strcmp(type.dataTypeString, "int16"))
883 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
885 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
886 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
888 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
892 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
898 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
900 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
906 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
907 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
913 result = syntaxError;
915 if(prop && type && type.type == structClass)
921 else if(ch && ch != '}' && ch != ',' && (!eCON || ch != ';'))
922 result = syntaxError;
932 else if(ch != ',' && (!eCON || ch != ';'))
933 result = syntaxError;
941 JSONResult GetNumber(Class type, DataValue value)
943 JSONResult result = success;
946 bool comment = false;
949 while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' ||
950 tolower(ch) == 'x' || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/'))
952 if(!comment && ch == '/')
961 result = syntaxError;
965 else if(comment && ch == '*')
974 result = syntaxError;
980 if(!f.Getc(&ch)) break;
985 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
988 if(!f.Getc(&ch)) break;
992 //if(strchr(buffer, '.'))
993 if(result == syntaxError)
995 if(!type) return success;
996 result = syntaxError;
998 // TOFIX: How to swiftly handle classes with base data type?
999 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1001 value.d = strtod(buffer, null);
1004 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1006 value.f = (float)strtod(buffer, null);
1009 // TOFIX: int64 looks for class long long?
1010 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
1011 else if(!strcmp(type.dataTypeString, "int64"))
1013 value.i64 = strtol(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1016 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
1018 value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1021 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int"))
1023 value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1028 value.i = (int)strtol(buffer, null, eCON ? 0 : 10);
1032 if(result == success && type.type == unitClass)
1034 // Convert to reference unit
1036 for(prop = type.conversions.first; prop; prop = prop.next)
1038 bool refProp = false;
1039 if(!strcmp(prop.name, type.base.fullName))
1043 Class c = eSystem_FindClass(type.module, prop.name);
1045 c = eSystem_FindClass(type.module.application, prop.name);
1049 for(p = c.conversions.first; p; p = p.next)
1051 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
1061 if(prop.Set && prop.Get)
1063 const String dts = type.base.dataTypeString;
1064 if(!strcmp(dts, "double"))
1065 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
1066 else if(!strcmp(dts, "float"))
1067 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
1068 else if(!strcmp(dts, "int"))
1069 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
1070 else if(!strcmp(dts, "int64"))
1071 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
1072 else if(!strcmp(dts, "unsigned int"))
1073 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
1074 else if(!strcmp(dts, "uint64"))
1075 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
1085 JSONResult GetColorAlpha(String string, DataValue value)
1087 ColorAlpha color = 0;
1091 if(string[0] == '0' && string[1] == 'x')
1092 color = (uint)strtoul(string, null, 0);
1097 if((d = strchr(string, ',')))
1099 a = (byte)atoi(string);
1104 if(c.class::OnGetDataFromString(d))
1110 color = (uint)strtoul(string, null, 16);
1118 static bool WriteMap(File f, Class type, Map map, int indent, bool eCON)
1123 bool isFirst = true;
1124 MapIterator it { map = map };
1125 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
1131 MapNode n = (MapNode)it.pointer;
1136 for(i = 0; i<indent; i++) f.Puts(" ");
1137 WriteONObject(f, mapNodeClass, n, indent, eCON, eCON ? true : false);
1141 for(i = 0; i<indent; i++) f.Puts(" ");
1149 static bool WriteArray(File f, Class type, Container array, int indent, bool eCON)
1154 bool isFirst = true;
1155 Iterator it { array };
1156 Class arrayType = type.templateArgs[0].dataTypeClass;
1162 DataValue value { };
1163 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
1170 // TODO: Verify the matching between template type and uint64
1171 if(arrayType.type == structClass)
1173 value.p = (void *)(uintptr)t;
1175 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
1178 //value.d = *(double *)&t;
1180 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
1183 //value.f = *(float *)&t;
1185 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
1186 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
1190 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
1191 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
1195 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
1196 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
1197 !strcmp(arrayType.dataTypeString, "int16"))
1201 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
1202 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
1208 value.p = (void *)(uintptr)t;
1210 for(i = 0; i<indent; i++) f.Puts(" ");
1211 WriteValue(f, arrayType, value, indent, eCON);
1215 for(i = 0; i<indent; i++) f.Puts(" ");
1223 static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON)
1226 bool needClass = eCON;
1229 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1230 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
1231 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1232 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
1233 else if(!strcmp(type.dataTypeString, "int64"))
1234 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
1235 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
1236 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
1237 else if(!strcmp(type.dataTypeString, "int"))
1238 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
1239 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
1240 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
1241 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
1242 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
1243 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
1244 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
1245 else if(!strcmp(type.dataTypeString, "char"))
1246 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
1247 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
1248 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
1250 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' ')));
1251 if(quote) f.Puts("\"");
1253 if(quote) f.Puts("\"");
1257 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent, bool eCON)
1260 char * string = buffer;
1261 ColorAlpha color = value.i;
1264 DefinedColor c = color;
1268 a.class::OnGetString(buffer, null, null);
1269 len = strlen(buffer);
1270 buffer[len++] = ',';
1271 buffer[len++] = ' ';
1275 if(!c.class::OnGetString(string, null, null))
1276 sprintf(buffer, "0x%x", color);
1285 static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCON)
1287 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
1294 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
1300 char * string = value.p;
1332 for(i = 0; i<indent; i++) f.Puts(" ");
1336 else if(b == sizeof(buffer)-2 || !ch)
1339 if(ch) buffer[b] = 0;
1353 char * string = value.p;
1372 else if(b == sizeof(buffer)-2 || !ch)
1375 if(ch) buffer[b] = 0;
1389 else if(!strcmp(type.name, "bool"))
1396 else if(!strcmp(type.name, "SetBool"))
1398 if(value.i == SetBool::true)
1400 else if(value.i == SetBool::false)
1405 else if(type.type == enumClass)
1409 WriteNumber(f, type, value, indent, eCON);
1413 else if(eClass_IsDerived(type, class(Map)))
1415 WriteMap(f, type, value.p, indent, eCON);
1417 else if(eClass_IsDerived(type, class(Container)))
1419 WriteArray(f, type, value.p, indent, eCON);
1421 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1423 WriteONObject(f, type, value.p, indent, eCON, false);
1425 else if(eClass_IsDerived(type, class(ColorAlpha)))
1427 WriteColorAlpha(f, type, value, indent, eCON);
1429 else if(type.type == bitClass)
1432 dataType = eSystem_SuperFindClass(type.dataTypeString, type.module);
1433 WriteNumber(f, dataType, value, indent, eCON);
1435 else if(type.type == systemClass || type.type == unitClass)
1437 WriteNumber(f, type, value, indent, eCON);
1442 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1444 bool result = false;
1447 result = WriteONObject(f, objectType, object, indent, false, false);
1453 public bool WriteECONObject(File f, Class objectType, void * object, int indent)
1455 bool result = false;
1458 result = WriteONObject(f, objectType, object, indent, true, false);
1464 static bool WriteONObject(File f, Class objectType, void * object, int indent, bool eCON, bool omitDefaultIdentifier)
1468 const char * string = null;
1470 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1474 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1478 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1479 if(string[0] == '\"')
1490 Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType;
1493 bool isFirst = true;
1494 Class mapKeyClass = null, mapDataClass = null;
1496 List<Class> bases { };
1498 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1500 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1501 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1504 if(eCON && _class != objectType && eClass_IsDerived(_class, objectType))
1506 f.Puts(_class.name);
1513 for(baseClass = _class; baseClass; baseClass = baseClass.base)
1515 if(baseClass.isInstanceClass || !baseClass.base)
1517 bases.Insert(null, baseClass);
1520 for(baseClass : bases)
1522 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1524 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1527 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1529 DataValue value { };
1530 bool isTemplateArg = false;
1533 if(mapKeyClass && !strcmp(prop.name, "key"))
1535 isTemplateArg = true;
1538 else if(mapDataClass && !strcmp(prop.name, "value"))
1540 isTemplateArg = true;
1541 type = mapDataClass;
1544 type = eSystem_SuperFindClass(prop.dataTypeString, _class.module);
1547 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1550 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1552 // TOFIX: How to swiftly handle classes with base data type?
1553 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1555 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1557 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1559 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1561 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1562 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1564 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1566 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1567 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1569 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1571 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1572 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1573 !strcmp(type.dataTypeString, "int16"))
1575 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1577 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1578 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1580 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1583 else if(type.type == structClass)
1585 value.p = new0 byte[type.structSize];
1586 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1591 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1593 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1596 if(!isFirst) f.Puts(",\n");
1597 for(c = 0; c<indent; c++) f.Puts(" ");
1602 f.Putc((char)toupper(prop.name[0]));
1603 f.Puts(prop.name+1);
1606 else if(!omitDefaultIdentifier)
1611 WriteValue(f, type, value, indent, eCON);
1613 if(type.type == structClass)
1620 DataMember member = (DataMember)prop;
1621 DataValue value { };
1623 Class type = eSystem_SuperFindClass(member.dataTypeString, _class.module);
1624 offset = member._class.offset + member.offset;
1628 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1630 if(type.type == structClass)
1631 value.p = (void *)((byte *)object + offset);
1633 value.p = *(void **)((byte *)object + offset);
1637 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1639 value.d = *(double *)((byte *)object + offset);
1641 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1643 value.f = *(float *)((byte *)object + offset);
1645 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1646 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1648 value.ui64 = *(uint64 *)((byte *)object + offset);
1650 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1651 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1653 value.i = *(int *)((byte *)object + offset);
1654 if(!strcmp(type.name, "bool") || type.type == enumClass)
1658 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1659 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1660 !strcmp(type.dataTypeString, "int16"))
1662 value.s = *(short *)((byte *)object + offset);
1664 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1665 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1667 value.c = *(char *)((byte *)object + offset);
1671 value.i = *(int *)((byte *)object + offset);
1674 if(!isFirst) f.Puts(",\n");
1675 for(c = 0; c<indent; c++) f.Puts(" ");
1680 f.Putc((char)toupper(member.name[0]));
1681 f.Puts(member.name+1);
1684 else if(!omitDefaultIdentifier)
1686 f.Puts(member.name);
1689 WriteValue(f, type, value, indent, eCON);
1700 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");
1708 static Class eSystem_SuperFindClass(const String name, Module alternativeModule)
1710 Class _class = eSystem_FindClass(__thisModule, name);
1711 if(!_class && alternativeModule)
1712 _class = eSystem_FindClass(alternativeModule, name);
1714 _class = eSystem_FindClass(__thisModule.application, name);
1718 static bool isSubclass(const String name, Class type)
1720 Class _class = eSystem_SuperFindClass(name, type.module);
1721 if(eClass_IsDerived(_class, type))