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 if(type && type.templateClass && type.templateClass == class(Container))
771 char * br = strchr(type.fullName, '<');
774 char className[1024];
775 strcpy(className, "Array");
776 strcat(className, br);
777 type = superFindClass(className, objectType.module);
781 // Find Member in Object Class
785 if(type && type.type == structClass)
789 value.p = (byte *)*object + offset;
790 memset(value.p, 0, type.structSize);
794 value.p = new0 byte[type.structSize];
802 if(eCON && ch != '=' && ch != ':')
804 f.Seek(seek-1, start);
807 if((ch == ':' || (eCON && ch == '=')) || (eCON && type && (prop || member)))
809 JSONResult itemResult = GetValue(type, value);
810 if(itemResult != syntaxError)
815 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
816 else if(itemResult == success)
821 // TOFIX: How to swiftly handle classes with base data type?
822 if(type.type == structClass)
824 else if(type.type == normalClass || type.type == noHeadClass)
826 void ** ptr = (void**)((byte *)*object + offset);
827 if(eClass_IsDerived(type, class(Container)) && *ptr)
829 Container container = (Container)*ptr;
835 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
837 *(double *)((byte *)*object + offset) = value.d;
839 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
841 *(float *)((byte *)*object + offset) = value.f;
843 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
844 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
846 *(uint64 *)((byte *)*object + offset) = value.ui64;
848 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
849 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
851 *(int *)((byte *)*object + offset) = value.i;
853 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
854 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
855 !strcmp(type.dataTypeString, "int16"))
857 *(short *)((byte *)*object + offset) = value.s;
859 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
860 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
862 *(char *)((byte *)*object + offset) = value.c;
866 *(void **)((byte *)*object + offset) = value.p;
869 else if(prop && prop.Set)
871 if(!strcmp(type.dataTypeString, "char *"))
873 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
877 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
879 // TOFIX: How to swiftly handle classes with base data type?
880 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
882 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
884 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
886 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
888 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
889 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
891 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
893 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
894 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
896 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
898 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
899 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
900 !strcmp(type.dataTypeString, "int16"))
902 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
904 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
905 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
907 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
911 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
917 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
919 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
925 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
926 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
932 result = syntaxError;
934 if(prop && type && type.type == structClass)
940 else if(ch && ch != '}' && ch != ',' && (!eCON || ch != ';'))
941 result = syntaxError;
951 else if(ch != ',' && (!eCON || ch != ';'))
952 result = syntaxError;
960 JSONResult GetNumber(Class type, DataValue value)
962 JSONResult result = success;
965 bool comment = false;
966 bool hexMode = false;
969 while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' ||
970 (c == 1 && tolower(ch) == 'x' && buffer[0] == '0') || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/' ||
971 (hexMode && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')))))
973 if(!comment && ch == '/')
982 result = syntaxError;
986 else if(comment && ch == '*')
995 result = syntaxError;
1001 if(c == 1 && ch == 'x' && buffer[0] == '0')
1005 if(!f.Getc(&ch)) break;
1010 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
1013 if(!f.Getc(&ch)) break;
1017 //if(strchr(buffer, '.'))
1018 if(result == syntaxError)
1020 if(!type) return success;
1021 result = syntaxError;
1023 // TOFIX: How to swiftly handle classes with base data type?
1024 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1026 value.d = strtod(buffer, null);
1029 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1031 value.f = (float)strtod(buffer, null);
1034 // TOFIX: int64 looks for class long long?
1035 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
1036 else if(!strcmp(type.dataTypeString, "int64"))
1038 value.i64 = strtol(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1041 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
1043 value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1046 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1048 value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1053 value.i = (int)strtol(buffer, null, eCON ? 0 : 10);
1057 if(result == success && type.type == unitClass)
1059 // Convert to reference unit
1061 for(prop = type.conversions.first; prop; prop = prop.next)
1063 bool refProp = false;
1064 if(!strcmp(prop.name, type.base.fullName))
1068 Class c = eSystem_FindClass(type.module, prop.name);
1070 c = eSystem_FindClass(type.module.application, prop.name);
1074 for(p = c.conversions.first; p; p = p.next)
1076 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
1086 if(prop.Set && prop.Get)
1088 const String dts = type.base.dataTypeString;
1089 if(!strcmp(dts, "double"))
1090 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
1091 else if(!strcmp(dts, "float"))
1092 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
1093 else if(!strcmp(dts, "int"))
1094 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
1095 else if(!strcmp(dts, "int64"))
1096 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
1097 else if(!strcmp(dts, "unsigned int"))
1098 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
1099 else if(!strcmp(dts, "uint64"))
1100 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
1110 JSONResult GetColorAlpha(String string, DataValue value)
1112 ColorAlpha color = 0;
1116 if(string[0] == '0' && string[1] == 'x')
1117 color = (uint)strtoul(string, null, 0);
1122 if((d = strchr(string, ',')))
1124 a = (byte)atoi(string);
1129 if(c.class::OnGetDataFromString(d))
1135 color = (uint)strtoul(string, null, 16);
1143 static bool WriteMap(File f, Class type, Map map, int indent, bool eCON)
1148 bool isFirst = true;
1149 MapIterator it { map = map };
1150 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
1156 MapNode n = (MapNode)it.pointer;
1161 for(i = 0; i<indent; i++) f.Puts(" ");
1162 WriteONObject(f, mapNodeClass, n, indent, eCON, eCON ? true : false);
1166 for(i = 0; i<indent; i++) f.Puts(" ");
1174 static bool WriteArray(File f, Class type, Container array, int indent, bool eCON)
1179 bool isFirst = true;
1180 Iterator it { array };
1181 Class arrayType = type.templateArgs[0].dataTypeClass;
1187 DataValue value { };
1188 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
1195 // TODO: Verify the matching between template type and uint64
1196 if(arrayType.type == structClass)
1198 value.p = (void *)(uintptr)t;
1200 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
1203 //value.d = *(double *)&t;
1205 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
1208 //value.f = *(float *)&t;
1210 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
1211 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
1215 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
1216 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
1220 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
1221 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
1222 !strcmp(arrayType.dataTypeString, "int16"))
1226 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
1227 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
1233 value.p = (void *)(uintptr)t;
1235 for(i = 0; i<indent; i++) f.Puts(" ");
1236 WriteValue(f, arrayType, value, indent, eCON);
1240 for(i = 0; i<indent; i++) f.Puts(" ");
1248 static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON, bool useHex)
1251 bool needClass = eCON;
1254 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1255 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
1256 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1257 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
1258 else if(!strcmp(type.dataTypeString, "int64"))
1259 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
1260 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
1263 sprintf(buffer, __runtimePlatform == win32 ? "0x%016I64X" : "0x%016llX", value.ui64);
1265 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
1267 else if(!strcmp(type.dataTypeString, "int"))
1268 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
1269 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
1272 sprintf(buffer, "0x%08X", value.ui);
1274 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
1276 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
1277 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
1278 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
1279 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
1280 else if(!strcmp(type.dataTypeString, "char"))
1281 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
1282 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
1283 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
1285 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))) ||
1286 (type.type == enumClass && !eCON);
1287 if(quote) f.Puts("\"");
1289 if(quote) f.Puts("\"");
1293 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent, bool eCON)
1296 char * string = buffer;
1297 ColorAlpha color = value.i;
1300 DefinedColor c = color;
1304 a.class::OnGetString(buffer, null, null);
1305 len = strlen(buffer);
1306 buffer[len++] = ',';
1307 buffer[len++] = ' ';
1311 if(!c.class::OnGetString(string, null, null))
1312 sprintf(buffer, "0x%x", color);
1321 static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCON)
1323 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
1330 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
1336 char * string = value.p;
1368 for(i = 0; i<indent; i++) f.Puts(" ");
1372 else if(b == sizeof(buffer)-2 || !ch)
1375 if(ch) buffer[b] = 0;
1389 char * string = value.p;
1408 else if(b == sizeof(buffer)-2 || !ch)
1411 if(ch) buffer[b] = 0;
1425 else if(!strcmp(type.name, "bool"))
1432 else if(!strcmp(type.name, "SetBool"))
1434 if(value.i == SetBool::true)
1436 else if(value.i == SetBool::false)
1441 else if(type.type == enumClass)
1442 WriteNumber(f, type, value, indent, eCON, false);
1443 else if(eClass_IsDerived(type, class(Map)))
1445 WriteMap(f, type, value.p, indent, eCON);
1447 else if(eClass_IsDerived(type, class(Container)))
1449 WriteArray(f, type, value.p, indent, eCON);
1451 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1453 WriteONObject(f, type, value.p, indent, eCON, false);
1455 else if(eClass_IsDerived(type, class(ColorAlpha)))
1457 WriteColorAlpha(f, type, value, indent, eCON);
1459 else if(type.type == bitClass)
1462 dataType = superFindClass(type.dataTypeString, type.module);
1463 WriteNumber(f, dataType, value, indent, eCON, true);
1465 else if(type.type == systemClass || type.type == unitClass)
1467 WriteNumber(f, type, value, indent, eCON, false);
1472 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1474 bool result = false;
1477 result = WriteONObject(f, objectType, object, indent, false, false);
1483 public bool WriteECONObject(File f, Class objectType, void * object, int indent)
1485 bool result = false;
1488 result = WriteONObject(f, objectType, object, indent, true, false);
1494 static bool WriteONObject(File f, Class objectType, void * object, int indent, bool eCON, bool omitDefaultIdentifier)
1498 const char * string = null;
1500 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1504 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1508 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1509 if(string[0] == '\"')
1520 Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType;
1523 bool isFirst = true;
1524 Class mapKeyClass = null, mapDataClass = null;
1526 List<Class> bases { };
1528 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1530 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1531 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1534 if(eCON && _class != objectType && eClass_IsDerived(_class, objectType))
1536 f.Puts(_class.name);
1543 for(baseClass = _class; baseClass; baseClass = baseClass.base)
1545 if(baseClass.isInstanceClass || !baseClass.base)
1547 bases.Insert(null, baseClass);
1550 for(baseClass : bases)
1552 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1554 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1557 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1559 DataValue value { };
1560 bool isTemplateArg = false;
1563 if(mapKeyClass && !strcmp(prop.name, "key"))
1565 isTemplateArg = true;
1568 else if(mapDataClass && !strcmp(prop.name, "value"))
1570 isTemplateArg = true;
1571 type = mapDataClass;
1574 type = superFindClass(prop.dataTypeString, _class.module);
1577 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1580 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1582 // TOFIX: How to swiftly handle classes with base data type?
1583 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1585 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1587 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1589 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1591 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1592 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1594 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1596 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1597 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1599 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1601 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1602 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1603 !strcmp(type.dataTypeString, "int16"))
1605 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1607 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1608 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1610 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1613 else if(type.type == structClass)
1615 value.p = new0 byte[type.structSize];
1616 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1621 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1623 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1626 if(!isFirst) f.Puts(",\n");
1627 for(c = 0; c<indent; c++) f.Puts(" ");
1632 f.Putc((char)toupper(prop.name[0]));
1633 f.Puts(prop.name+1);
1636 else if(!omitDefaultIdentifier)
1641 WriteValue(f, type, value, indent, eCON);
1643 if(type.type == structClass)
1650 DataMember member = (DataMember)prop;
1651 DataValue value { };
1653 Class type = superFindClass(member.dataTypeString, _class.module);
1654 offset = member._class.offset + member.offset;
1658 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1660 if(type.type == structClass)
1661 value.p = (void *)((byte *)object + offset);
1663 value.p = *(void **)((byte *)object + offset);
1667 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1669 value.d = *(double *)((byte *)object + offset);
1671 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1673 value.f = *(float *)((byte *)object + offset);
1675 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1676 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1678 value.ui64 = *(uint64 *)((byte *)object + offset);
1680 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1681 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1683 value.i = *(int *)((byte *)object + offset);
1684 if(!strcmp(type.name, "bool") || type.type == enumClass)
1688 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1689 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1690 !strcmp(type.dataTypeString, "int16"))
1692 value.s = *(short *)((byte *)object + offset);
1694 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1695 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1697 value.c = *(char *)((byte *)object + offset);
1701 value.i = *(int *)((byte *)object + offset);
1704 if(!isFirst) f.Puts(",\n");
1705 for(c = 0; c<indent; c++) f.Puts(" ");
1710 f.Putc((char)toupper(member.name[0]));
1711 f.Puts(member.name+1);
1714 else if(!omitDefaultIdentifier)
1716 f.Puts(member.name);
1719 WriteValue(f, type, value, indent, eCON);
1730 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");
1738 static Class superFindClass(const String name, Module alternativeModule)
1740 Class _class = eSystem_FindClass(__thisModule, name);
1741 if(!_class && alternativeModule)
1742 _class = eSystem_FindClass(alternativeModule, name);
1744 _class = eSystem_FindClass(__thisModule.application, name);
1748 static bool isSubclass(Class type, const String name)
1750 Class _class = superFindClass(name, type.module);
1751 if(eClass_IsDerived(_class, type))