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 ECONParser : JSONParser
39 public class JSONParser
52 bool lineComment = false;
54 while(!f.Eof() && (!ch || lineComment || comment || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '/'))
58 if(!lineComment && !comment && pch == '/')
65 else if(lineComment && ch == '\n')
67 else if(comment && pch == '*' && ch == '/')
73 while(!f.Eof() && (!ch || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '/'))
80 void SkipExtraSemicolon()
82 while(!f.Eof() && (!ch || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == ';'))
88 JSONResult GetValue(Class type, DataValue value)
90 JSONResult result = syntaxError;
96 result = GetString(&string);
100 if(type && (!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *")))
104 else if(type && (type.type == enumClass || type.type == unitClass))
106 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
109 result = typeMismatch;
112 else if(type && (prop = eClass_FindProperty(type, "String", type.module)))
114 // TOFIX: Add more conversion property support... Expecting void * compatible here
115 value.p = ((void *(*)())(void *)prop.Set)(string);
119 else if(type && eClass_IsDerived(type, class(ColorAlpha)))
121 result = GetColorAlpha(string, value);
124 else if(type && (type.type == structClass))
126 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, value.p, string))
129 result = typeMismatch;
135 result = typeMismatch;
142 if(type && eClass_IsDerived(type, class(Map)))
144 result = GetMap(type, (Map *)&array);
147 result = GetArray(type, &array);
149 if(result == success && type && eClass_IsDerived(type, class(Container)))
158 if(result != success)
159 result = typeMismatch;
162 else if(ch == '-' || isdigit(ch))
164 result = GetNumber(type, value);
168 void * object = value.p;
169 result = GetObject(type, &object);
172 if(type && type.type == structClass);
173 else if(type && (type.type == normalClass || type.type == noHeadClass || type.type == bitClass))
179 result = typeMismatch;
181 ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, object);
185 else if(isalpha(ch) || ch == '_')
190 if(GetIdentifier(&string, null))
193 if(eCON && type && (type.type == enumClass || type.type == unitClass))
195 // should this be set by calling __ecereVMethodID_class_OnGetDataFromString ?
196 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
199 result = typeMismatch;
201 else if(type && !strcmp(type.name, "bool"))
203 if(!strcmpi(string, "false")) value.i = 0;
204 else if(!strcmpi(string, "true")) value.i = 1;
206 result = typeMismatch;
208 else if(type && !strcmp(type.name, "SetBool"))
210 if(!strcmpi(string, "false")) value.i = SetBool::false;
211 else if(!strcmpi(string, "true")) value.i = SetBool::true;
213 result = typeMismatch;
215 else if(type && !strcmpi(string, "null"))
217 if(type.type != structClass)
220 else if(isSubclass(type, string))
222 void * object = value.p;
223 Class subtype = superFindClass(string, type.module);
225 result = GetObject(subtype, &object);
228 if(subtype && subtype.type == structClass);
229 else if(subtype && (subtype.type == normalClass || subtype.type == noHeadClass || subtype.type == bitClass))
235 result = typeMismatch;
237 ((void (*)(void *, void *))(void *)subtype._vTbl[__ecereVMethodID_class_OnFree])(subtype, object);
242 result = typeMismatch;
250 while(c < sizeof(buffer)-1 && (isalpha(ch) || isdigit(ch) || ch == '_'))
253 if(!f.Getc(&ch)) break;
260 if(!strcmp(type.name, "bool"))
262 if(!strcmpi(buffer, "false")) value.i = 0;
263 else if(!strcmpi(buffer, "true")) value.i = 1;
265 result = typeMismatch;
267 else if(!strcmp(type.name, "SetBool"))
269 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
270 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
272 result = typeMismatch;
274 else if(!strcmpi(buffer, "null"))
276 if(type.type != structClass)
280 result = typeMismatch;
283 result = typeMismatch;
286 else if(ch == '}' || ch == ']')
288 if(result == typeMismatch)
289 PrintLn("Warning: Value type mismatch");
293 JSONResult GetArray(Class type, Container * array)
295 JSONResult result = syntaxError;
300 *array = eInstance_New(type);
305 Class arrayType = null;
306 JSONResult itemResult;
308 if(eClass_IsDerived(type, class(Container)))
310 arrayType = type.templateArgs[0].dataTypeClass;
313 if(arrayType && arrayType.type == structClass)
314 value.p = new0 byte[arrayType.structSize];
315 itemResult = GetValue(arrayType, value);
316 if(itemResult == success)
318 // TODO: Verify the matching between template type and uint64
320 if(arrayType.type == structClass)
322 t = (uint64)(uintptr)value.p;
324 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
326 t = value.ui64; //*(uint64 *)&value.d;
328 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
330 t = value.ui; //f*(uint *)&value.f;
332 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
333 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
337 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
338 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
342 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
343 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
344 !strcmp(arrayType.dataTypeString, "int16"))
348 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
349 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
355 t = (uint64)(uintptr)value.p;
357 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
359 if(arrayType && arrayType.type == structClass)
364 if(itemResult == typeMismatch)
367 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
369 else if(itemResult == noItem)
375 if(result != syntaxError)
377 if(ch != ']' && ch != ',')
387 result = syntaxError;
395 JSONResult GetMap(Class type, Map * map)
397 JSONResult result = syntaxError;
402 Class mapNodeType = type.templateArgs[0].dataTypeClass;
403 Class keyType = mapNodeType.templateArgs[0].dataTypeClass;
404 Property keyProp = null;
405 if(keyType && !strcmp(keyType.dataTypeString, "char *"))
406 keyProp = eClass_FindProperty(mapNodeType, "key", mapNodeType.module);
408 *map = eInstance_New(type);
415 JSONResult itemResult;
417 itemResult = GetValue(mapNodeType, value);
418 if(itemResult == success)
420 String s = keyProp ? ((void * (*)(void *))(void *)keyProp.Get)(value.p) : null;
421 ((void *(*)(void *, uint64))(void *)map->Add)(*map, (uint64)(uintptr)value.p);
422 // Must free String keys here
427 if(itemResult == typeMismatch)
430 PrintLn("Warning: Incompatible value for array value, expected ", (String)mapNodeType.name);
432 else if(itemResult == noItem)
438 if(result != syntaxError)
440 if(ch != ']' && ch != ',')
450 result = syntaxError;
458 JSONResult GetIdentifier(String * string, bool * wasQuoted)
460 JSONResult result = syntaxError;
461 Array<char> buffer { minAllocSize = 256 };
462 bool comment = false;
474 if(!comment && ch == '/')
484 result = syntaxError;
490 result = syntaxError;
494 else if(comment && ch == '*')
506 result = syntaxError;
510 else if(ch == '\"' || (!quoted && !comment && ch && !isalpha(ch) && !isdigit(ch) && ch != '_'))
512 if(quoted && ch == '\"' && wasQuoted)
516 else if(!comment && ch)
519 if(buffer.minAllocSize < buffer.count)
520 buffer.minAllocSize *= 2;
523 if(result != syntaxError)
526 *string = CopyString(buffer.array);
529 if(ch != ',' && ch != '}' && ch != ';' && ch != '/' && ch != '=' && ch != ':')
534 JSONResult GetString(String * string)
536 JSONResult result = syntaxError;
537 Array<char> buffer { minAllocSize = 256 };
538 bool escaped = false;
542 if(ch == '\"' || eCON)
546 if(ch == '\\' && !escaped)
552 if(ch == 'b') ch = '\b';
553 else if(ch == 'f') ch = '\f';
554 else if(ch == 'n') ch = '\n';
555 else if(ch == 'r') ch = '\r';
556 else if(ch == 't') ch = '\t';
568 else if(eCON && ch == '\"')
572 bool lineComment = false;
573 bool comment = false;
579 if(!lineComment && !comment && pch == '/')
586 else if(lineComment && ch == '\n')
588 else if(comment && pch == '*' && ch == '/')
590 else if(ch == '=' || ch == ':' || ch == ';' || ch == ',' || ch == ']' || ch == '}')
605 f.Seek(seekback, current);
609 else if((!eCON && ch == '\"'))
616 if(buffer.minAllocSize < buffer.count)
617 buffer.minAllocSize *= 2;
622 *string = CopyString(buffer.array);
626 if(ch != ',' && ch != '}' && (!eCON || (ch != ';' && ch != '/')))
631 public JSONResult GetObject(Class objectType, void ** object)
633 JSONResult result = syntaxError;
634 if(!objectType || objectType.type != structClass)
639 Class mapKeyClass = null, mapDataClass = null;
640 Class curClass = null;
641 DataMember curMember = null;
642 DataMember subMemberStack[256];
643 int subMemberStackPos = 0;
645 if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
647 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
648 mapDataClass = objectType.templateArgs[2].dataTypeClass;
652 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
654 *object = eInstance_New(objectType);
656 else if(objectType && objectType.type != structClass)
658 *object = eSystem_New(objectType.typeSize);
664 bool wasQuoted = false;
669 SkipExtraSemicolon();
675 if(eCON ? GetIdentifier(&string, &wasQuoted) : GetString(&string))
677 DataMember member = null;
678 Property prop = null;
681 bool isTemplateArg = false;
686 prop = null; member = null;
687 if(ch == '=' || ch == ':')
690 string[0] = (char)tolower(string[0]);
693 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
694 if(!curMember) break;
695 if(!strcmp(curMember.name, string))
700 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
703 prop = curMember.isProperty ? (Property)curMember : null;
704 member = curMember.isProperty ? null : curMember;
706 if(mapKeyClass && !strcmp(prop ? prop.name : member.name, "key"))
709 isTemplateArg = true;
712 else if(mapDataClass && !strcmp(prop ? prop.name : member.name, "value"))
715 isTemplateArg = true;
717 offset = member._class.offset + member.offset;
720 type = superFindClass(prop.dataTypeString, objectType.module);
723 type = superFindClass(member.dataTypeString, objectType.module);
724 offset = member._class.offset + member.offset;
729 if(ch == '=' || ch == ':')
730 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
732 PrintLn("Warning: default member assignment: no more members");
735 if(objectType && !eCON)
737 string[0] = (char)tolower(string[0]);
738 if(mapKeyClass && !strcmp(string, "key"))
740 prop = eClass_FindProperty(objectType, "key", objectType.module);
742 isTemplateArg = true;
745 else if(mapDataClass && !strcmp(string, "value"))
747 prop = eClass_FindProperty(objectType, "value", objectType.module);
749 isTemplateArg = true;
753 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
756 type = superFindClass(member.dataTypeString, objectType.module);
757 offset = member._class.offset + member.offset;
761 prop = eClass_FindProperty(objectType, string, objectType.module);
763 type = superFindClass(prop.dataTypeString, objectType.module);
765 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
769 // Find Member in Object Class
773 if(type && type.type == structClass)
777 value.p = (byte *)*object + offset;
778 memset(value.p, 0, type.structSize);
782 value.p = new0 byte[type.structSize];
790 if(eCON && ch != '=' && ch != ':')
792 f.Seek(seek-1, start);
795 if((ch == ':' || (eCON && ch == '=')) || (eCON && type && (prop || member)))
797 JSONResult itemResult = GetValue(type, value);
798 if(itemResult != syntaxError)
803 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
804 else if(itemResult == success)
809 // TOFIX: How to swiftly handle classes with base data type?
810 if(type.type == structClass)
812 else if(type.type == normalClass || type.type == noHeadClass)
814 void ** ptr = (void**)((byte *)*object + offset);
815 if(eClass_IsDerived(type, class(Container)) && *ptr)
817 Container container = (Container)*ptr;
823 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
825 *(double *)((byte *)*object + offset) = value.d;
827 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
829 *(float *)((byte *)*object + offset) = value.f;
831 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
832 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
834 *(uint64 *)((byte *)*object + offset) = value.ui64;
836 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
837 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
839 *(int *)((byte *)*object + offset) = value.i;
841 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
842 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
843 !strcmp(type.dataTypeString, "int16"))
845 *(short *)((byte *)*object + offset) = value.s;
847 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
848 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
850 *(char *)((byte *)*object + offset) = value.c;
854 *(void **)((byte *)*object + offset) = value.p;
857 else if(prop && prop.Set)
859 if(!strcmp(type.dataTypeString, "char *"))
861 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
865 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
867 // TOFIX: How to swiftly handle classes with base data type?
868 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
870 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
872 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
874 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
876 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
877 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
879 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
881 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
882 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
884 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
886 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
887 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
888 !strcmp(type.dataTypeString, "int16"))
890 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
892 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
893 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
895 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
899 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
905 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
907 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
913 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
914 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
920 result = syntaxError;
922 if(prop && type && type.type == structClass)
928 else if(ch && ch != '}' && ch != ',' && (!eCON || ch != ';'))
929 result = syntaxError;
939 else if(ch != ',' && (!eCON || ch != ';'))
940 result = syntaxError;
948 JSONResult GetNumber(Class type, DataValue value)
950 JSONResult result = success;
953 bool comment = false;
954 bool hexMode = false;
957 while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' ||
958 (c == 1 && tolower(ch) == 'x' && buffer[0] == '0') || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/' ||
959 (hexMode && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')))))
961 if(!comment && ch == '/')
970 result = syntaxError;
974 else if(comment && ch == '*')
983 result = syntaxError;
989 if(c == 1 && ch == 'x' && buffer[0] == '0')
993 if(!f.Getc(&ch)) break;
998 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
1001 if(!f.Getc(&ch)) break;
1005 //if(strchr(buffer, '.'))
1006 if(result == syntaxError)
1008 if(!type) return success;
1009 result = syntaxError;
1011 // TOFIX: How to swiftly handle classes with base data type?
1012 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1014 value.d = strtod(buffer, null);
1017 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1019 value.f = (float)strtod(buffer, null);
1022 // TOFIX: int64 looks for class long long?
1023 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
1024 else if(!strcmp(type.dataTypeString, "int64"))
1026 value.i64 = strtol(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1029 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
1031 value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1034 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1036 value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1041 value.i = (int)strtol(buffer, null, eCON ? 0 : 10);
1045 if(result == success && type.type == unitClass)
1047 // Convert to reference unit
1049 for(prop = type.conversions.first; prop; prop = prop.next)
1051 bool refProp = false;
1052 if(!strcmp(prop.name, type.base.fullName))
1056 Class c = eSystem_FindClass(type.module, prop.name);
1058 c = eSystem_FindClass(type.module.application, prop.name);
1062 for(p = c.conversions.first; p; p = p.next)
1064 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
1074 if(prop.Set && prop.Get)
1076 const String dts = type.base.dataTypeString;
1077 if(!strcmp(dts, "double"))
1078 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
1079 else if(!strcmp(dts, "float"))
1080 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
1081 else if(!strcmp(dts, "int"))
1082 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
1083 else if(!strcmp(dts, "int64"))
1084 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
1085 else if(!strcmp(dts, "unsigned int"))
1086 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
1087 else if(!strcmp(dts, "uint64"))
1088 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
1098 JSONResult GetColorAlpha(String string, DataValue value)
1100 ColorAlpha color = 0;
1104 if(string[0] == '0' && string[1] == 'x')
1105 color = (uint)strtoul(string, null, 0);
1110 if((d = strchr(string, ',')))
1112 a = (byte)atoi(string);
1117 if(c.class::OnGetDataFromString(d))
1123 color = (uint)strtoul(string, null, 16);
1131 static bool WriteMap(File f, Class type, Map map, int indent, bool eCON)
1136 bool isFirst = true;
1137 MapIterator it { map = map };
1138 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
1144 MapNode n = (MapNode)it.pointer;
1149 for(i = 0; i<indent; i++) f.Puts(" ");
1150 WriteONObject(f, mapNodeClass, n, indent, eCON, eCON ? true : false);
1154 for(i = 0; i<indent; i++) f.Puts(" ");
1162 static bool WriteArray(File f, Class type, Container array, int indent, bool eCON)
1167 bool isFirst = true;
1168 Iterator it { array };
1169 Class arrayType = type.templateArgs[0].dataTypeClass;
1175 DataValue value { };
1176 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
1183 // TODO: Verify the matching between template type and uint64
1184 if(arrayType.type == structClass)
1186 value.p = (void *)(uintptr)t;
1188 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
1191 //value.d = *(double *)&t;
1193 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
1196 //value.f = *(float *)&t;
1198 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
1199 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
1203 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
1204 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
1208 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
1209 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
1210 !strcmp(arrayType.dataTypeString, "int16"))
1214 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
1215 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
1221 value.p = (void *)(uintptr)t;
1223 for(i = 0; i<indent; i++) f.Puts(" ");
1224 WriteValue(f, arrayType, value, indent, eCON);
1228 for(i = 0; i<indent; i++) f.Puts(" ");
1236 static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON, bool useHex)
1239 bool needClass = eCON;
1242 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1243 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
1244 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1245 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
1246 else if(!strcmp(type.dataTypeString, "int64"))
1247 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
1248 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
1251 sprintf(buffer, __runtimePlatform == win32 ? "0x%016I64X" : "0x%016llX", value.ui64);
1253 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
1255 else if(!strcmp(type.dataTypeString, "int"))
1256 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
1257 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
1260 sprintf(buffer, "0x%08X", value.ui);
1262 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
1264 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
1265 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
1266 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
1267 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
1268 else if(!strcmp(type.dataTypeString, "char"))
1269 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
1270 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
1271 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
1273 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))) ||
1274 (type.type == enumClass && !eCON);
1275 if(quote) f.Puts("\"");
1277 if(quote) f.Puts("\"");
1281 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent, bool eCON)
1284 char * string = buffer;
1285 ColorAlpha color = value.i;
1288 DefinedColor c = color;
1292 a.class::OnGetString(buffer, null, null);
1293 len = strlen(buffer);
1294 buffer[len++] = ',';
1295 buffer[len++] = ' ';
1299 if(!c.class::OnGetString(string, null, null))
1300 sprintf(buffer, "0x%x", color);
1309 static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCON)
1311 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
1318 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
1324 char * string = value.p;
1356 for(i = 0; i<indent; i++) f.Puts(" ");
1360 else if(b == sizeof(buffer)-2 || !ch)
1363 if(ch) buffer[b] = 0;
1377 char * string = value.p;
1396 else if(b == sizeof(buffer)-2 || !ch)
1399 if(ch) buffer[b] = 0;
1413 else if(!strcmp(type.name, "bool"))
1420 else if(!strcmp(type.name, "SetBool"))
1422 if(value.i == SetBool::true)
1424 else if(value.i == SetBool::false)
1429 else if(type.type == enumClass)
1430 WriteNumber(f, type, value, indent, eCON, false);
1431 else if(eClass_IsDerived(type, class(Map)))
1433 WriteMap(f, type, value.p, indent, eCON);
1435 else if(eClass_IsDerived(type, class(Container)))
1437 WriteArray(f, type, value.p, indent, eCON);
1439 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1441 WriteONObject(f, type, value.p, indent, eCON, false);
1443 else if(eClass_IsDerived(type, class(ColorAlpha)))
1445 WriteColorAlpha(f, type, value, indent, eCON);
1447 else if(type.type == bitClass)
1450 dataType = superFindClass(type.dataTypeString, type.module);
1451 WriteNumber(f, dataType, value, indent, eCON, true);
1453 else if(type.type == systemClass || type.type == unitClass)
1455 WriteNumber(f, type, value, indent, eCON, false);
1460 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1462 bool result = false;
1465 result = WriteONObject(f, objectType, object, indent, false, false);
1471 public bool WriteECONObject(File f, Class objectType, void * object, int indent)
1473 bool result = false;
1476 result = WriteONObject(f, objectType, object, indent, true, false);
1482 static bool WriteONObject(File f, Class objectType, void * object, int indent, bool eCON, bool omitDefaultIdentifier)
1486 const char * string = null;
1488 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1492 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1496 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1497 if(string[0] == '\"')
1508 Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType;
1511 bool isFirst = true;
1512 Class mapKeyClass = null, mapDataClass = null;
1514 List<Class> bases { };
1516 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1518 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1519 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1522 if(eCON && _class != objectType && eClass_IsDerived(_class, objectType))
1524 f.Puts(_class.name);
1531 for(baseClass = _class; baseClass; baseClass = baseClass.base)
1533 if(baseClass.isInstanceClass || !baseClass.base)
1535 bases.Insert(null, baseClass);
1538 for(baseClass : bases)
1540 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1542 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1545 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1547 DataValue value { };
1548 bool isTemplateArg = false;
1551 if(mapKeyClass && !strcmp(prop.name, "key"))
1553 isTemplateArg = true;
1556 else if(mapDataClass && !strcmp(prop.name, "value"))
1558 isTemplateArg = true;
1559 type = mapDataClass;
1562 type = superFindClass(prop.dataTypeString, _class.module);
1565 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1568 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1570 // TOFIX: How to swiftly handle classes with base data type?
1571 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1573 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1575 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1577 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1579 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1580 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1582 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1584 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1585 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1587 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1589 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1590 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1591 !strcmp(type.dataTypeString, "int16"))
1593 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1595 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1596 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1598 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1601 else if(type.type == structClass)
1603 value.p = new0 byte[type.structSize];
1604 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1609 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1611 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1614 if(!isFirst) f.Puts(",\n");
1615 for(c = 0; c<indent; c++) f.Puts(" ");
1620 f.Putc((char)toupper(prop.name[0]));
1621 f.Puts(prop.name+1);
1624 else if(!omitDefaultIdentifier)
1629 WriteValue(f, type, value, indent, eCON);
1631 if(type.type == structClass)
1638 DataMember member = (DataMember)prop;
1639 DataValue value { };
1641 Class type = superFindClass(member.dataTypeString, _class.module);
1642 offset = member._class.offset + member.offset;
1646 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1648 if(type.type == structClass)
1649 value.p = (void *)((byte *)object + offset);
1651 value.p = *(void **)((byte *)object + offset);
1655 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1657 value.d = *(double *)((byte *)object + offset);
1659 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1661 value.f = *(float *)((byte *)object + offset);
1663 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1664 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1666 value.ui64 = *(uint64 *)((byte *)object + offset);
1668 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1669 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1671 value.i = *(int *)((byte *)object + offset);
1672 if(!strcmp(type.name, "bool") || type.type == enumClass)
1676 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1677 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1678 !strcmp(type.dataTypeString, "int16"))
1680 value.s = *(short *)((byte *)object + offset);
1682 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1683 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1685 value.c = *(char *)((byte *)object + offset);
1689 value.i = *(int *)((byte *)object + offset);
1692 if(!isFirst) f.Puts(",\n");
1693 for(c = 0; c<indent; c++) f.Puts(" ");
1698 f.Putc((char)toupper(member.name[0]));
1699 f.Puts(member.name+1);
1702 else if(!omitDefaultIdentifier)
1704 f.Puts(member.name);
1707 WriteValue(f, type, value, indent, eCON);
1718 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");
1726 static Class superFindClass(const String name, Module alternativeModule)
1728 Class _class = eSystem_FindClass(__thisModule, name);
1729 if(!_class && alternativeModule)
1730 _class = eSystem_FindClass(alternativeModule, name);
1732 _class = eSystem_FindClass(__thisModule.application, name);
1736 static bool isSubclass(Class type, const String name)
1738 Class _class = superFindClass(name, type.module);
1739 if(eClass_IsDerived(_class, type))