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 if(type.type == structClass || type.type == normalClass || type.type == noHeadClass)
170 void * object = value.p;
171 result = GetObject(type, &object);
174 if(type && type.type == structClass);
179 else if(type.type == bitClass)
182 result = GetObject(type, (void **)&object);
188 void * object = value.p;
189 result = GetObject(type, &object);
192 result = typeMismatch;
194 ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, object);
198 else if(isalpha(ch) || ch == '_')
203 if(GetIdentifier(&string, null))
206 if(eCON && type && (type.type == enumClass || type.type == unitClass))
208 // should this be set by calling __ecereVMethodID_class_OnGetDataFromString ?
209 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
212 result = typeMismatch;
214 else if(type && !strcmp(type.name, "bool"))
216 if(!strcmpi(string, "false")) value.i = 0;
217 else if(!strcmpi(string, "true")) value.i = 1;
219 result = typeMismatch;
221 else if(type && !strcmp(type.name, "SetBool"))
223 if(!strcmpi(string, "false")) value.i = SetBool::false;
224 else if(!strcmpi(string, "true")) value.i = SetBool::true;
226 result = typeMismatch;
228 else if(type && !strcmpi(string, "null"))
230 if(type.type != structClass)
233 else if(isSubclass(type, string))
235 void * object = value.p;
236 Class subtype = superFindClass(string, type.module);
238 result = GetObject(subtype, &object);
241 if(subtype && subtype.type == structClass);
242 else if(subtype && (subtype.type == normalClass || subtype.type == noHeadClass || subtype.type == bitClass))
248 result = typeMismatch;
250 ((void (*)(void *, void *))(void *)subtype._vTbl[__ecereVMethodID_class_OnFree])(subtype, object);
255 result = typeMismatch;
263 while(c < sizeof(buffer)-1 && (isalpha(ch) || isdigit(ch) || ch == '_'))
266 if(!f.Getc(&ch)) break;
273 if(!strcmp(type.name, "bool"))
275 if(!strcmpi(buffer, "false")) value.i = 0;
276 else if(!strcmpi(buffer, "true")) value.i = 1;
278 result = typeMismatch;
280 else if(!strcmp(type.name, "SetBool"))
282 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
283 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
285 result = typeMismatch;
287 else if(!strcmpi(buffer, "null"))
289 if(type.type != structClass)
293 result = typeMismatch;
296 result = typeMismatch;
299 else if(ch == '}' || ch == ']')
301 if(result == typeMismatch)
302 PrintLn("Warning: Value type mismatch");
306 JSONResult GetArray(Class type, Container * array)
308 JSONResult result = syntaxError;
313 *array = eInstance_New(type);
318 Class arrayType = null;
319 JSONResult itemResult;
321 if(eClass_IsDerived(type, class(Container)))
323 arrayType = type.templateArgs[0].dataTypeClass;
326 if(arrayType && arrayType.type == structClass)
327 value.p = new0 byte[arrayType.structSize];
328 itemResult = GetValue(arrayType, value);
329 if(itemResult == success)
331 // TODO: Verify the matching between template type and uint64
333 if(arrayType.type == structClass)
335 t = (uint64)(uintptr)value.p;
337 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
339 t = value.ui64; //*(uint64 *)&value.d;
341 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
343 t = value.ui; //f*(uint *)&value.f;
345 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
346 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
350 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
351 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
355 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
356 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
357 !strcmp(arrayType.dataTypeString, "int16"))
361 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
362 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
368 t = (uint64)(uintptr)value.p;
370 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
372 if(arrayType && arrayType.type == structClass)
377 if(itemResult == typeMismatch)
380 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
382 else if(itemResult == noItem)
388 if(result != syntaxError)
390 if(ch != ']' && ch != ',')
400 result = syntaxError;
408 JSONResult GetMap(Class type, Map * map)
410 JSONResult result = syntaxError;
415 Class mapNodeType = type.templateArgs[0].dataTypeClass;
416 Class keyType = mapNodeType.templateArgs[0].dataTypeClass;
417 Property keyProp = null;
418 if(keyType && !strcmp(keyType.dataTypeString, "char *"))
419 keyProp = eClass_FindProperty(mapNodeType, "key", mapNodeType.module);
421 *map = eInstance_New(type);
428 JSONResult itemResult;
430 itemResult = GetValue(mapNodeType, value);
431 if(itemResult == success)
433 String s = keyProp ? ((void * (*)(void *))(void *)keyProp.Get)(value.p) : null;
434 ((void *(*)(void *, uint64))(void *)map->Add)(*map, (uint64)(uintptr)value.p);
435 // Must free String keys here
440 if(itemResult == typeMismatch)
443 PrintLn("Warning: Incompatible value for array value, expected ", (String)mapNodeType.name);
445 else if(itemResult == noItem)
451 if(result != syntaxError)
453 if(ch != ']' && ch != ',')
463 result = syntaxError;
471 JSONResult GetIdentifier(String * string, bool * wasQuoted)
473 JSONResult result = syntaxError;
474 Array<char> buffer { minAllocSize = 256 };
475 bool comment = false;
487 if(!comment && ch == '/')
497 result = syntaxError;
503 result = syntaxError;
507 else if(comment && ch == '*')
519 result = syntaxError;
523 else if(ch == '\"' || (!quoted && !comment && ch && !isalpha(ch) && !isdigit(ch) && ch != '_'))
525 if(quoted && ch == '\"' && wasQuoted)
529 else if(!comment && ch)
532 if(buffer.minAllocSize < buffer.count)
533 buffer.minAllocSize *= 2;
536 if(result != syntaxError)
539 *string = CopyString(buffer.array);
542 if(ch != ',' && ch != '}' && ch != ';' && ch != '/' && ch != '=' && ch != ':')
547 JSONResult GetString(String * string)
549 JSONResult result = syntaxError;
550 Array<char> buffer { minAllocSize = 256 };
551 bool escaped = false;
555 if(ch == '\"' || eCON)
559 if(ch == '\\' && !escaped)
565 if(ch == 'b') ch = '\b';
566 else if(ch == 'f') ch = '\f';
567 else if(ch == 'n') ch = '\n';
568 else if(ch == 'r') ch = '\r';
569 else if(ch == 't') ch = '\t';
581 else if(eCON && ch == '\"')
585 bool lineComment = false;
586 bool comment = false;
592 if(!lineComment && !comment && pch == '/')
599 else if(lineComment && ch == '\n')
601 else if(comment && pch == '*' && ch == '/')
603 else if(ch == '=' || ch == ':' || ch == ';' || ch == ',' || ch == ']' || ch == '}')
618 f.Seek(seekback, current);
622 else if((!eCON && ch == '\"'))
629 if(buffer.minAllocSize < buffer.count)
630 buffer.minAllocSize *= 2;
635 *string = CopyString(buffer.array);
639 if(ch != ',' && ch != '}' && (!eCON || (ch != ';' && ch != '/')))
644 public JSONResult GetObject(Class objectType, void ** object)
646 JSONResult result = syntaxError;
647 if(!objectType || objectType.type != structClass)
649 if(objectType && objectType.type == bitClass)
650 *(uint64 *)object = 0;
657 Class mapKeyClass = null, mapDataClass = null;
658 Class curClass = null;
659 DataMember curMember = null;
660 DataMember subMemberStack[256];
661 int subMemberStackPos = 0;
664 if(objectType.type == bitClass)
666 switch(objectType.typeSize)
668 case 1: bits = (byte )*(uint64 *)object; break;
669 case 2: bits = (uint16)*(uint64 *)object; break;
670 case 4: bits = (uint32)*(uint64 *)object; break;
671 case 8: bits = (uint64)*(uint64 *)object; break;
675 if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
677 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
678 mapDataClass = objectType.templateArgs[2].dataTypeClass;
682 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
683 *object = eInstance_New(objectType);
688 bool wasQuoted = false;
693 SkipExtraSemicolon();
699 if(eCON ? GetIdentifier(&string, &wasQuoted) : GetString(&string))
701 DataMember member = null;
702 Property prop = null;
705 bool isTemplateArg = false;
710 prop = null; member = null;
711 if(ch == '=' || ch == ':')
714 string[0] = (char)tolower(string[0]);
717 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
718 if(!curMember) break;
719 if(!strcmp(curMember.name, string))
724 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
727 prop = curMember.isProperty ? (Property)curMember : null;
728 member = curMember.isProperty ? null : curMember;
730 if(mapKeyClass && !strcmp(prop ? prop.name : member.name, "key"))
733 isTemplateArg = true;
736 else if(mapDataClass && !strcmp(prop ? prop.name : member.name, "value"))
739 isTemplateArg = true;
741 offset = member._class.offset + member.offset;
744 type = superFindClass(prop.dataTypeString, objectType.module);
747 type = superFindClass(member.dataTypeString, objectType.module);
748 offset = member._class.offset + member.offset;
753 if(ch == '=' || ch == ':')
754 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
756 PrintLn("Warning: default member assignment: no more members");
759 if(objectType && !eCON)
761 string[0] = (char)tolower(string[0]);
762 if(mapKeyClass && !strcmp(string, "key"))
764 prop = eClass_FindProperty(objectType, "key", objectType.module);
766 isTemplateArg = true;
769 else if(mapDataClass && !strcmp(string, "value"))
771 prop = eClass_FindProperty(objectType, "value", objectType.module);
773 isTemplateArg = true;
777 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
780 type = superFindClass(member.dataTypeString, objectType.module);
781 offset = member._class.offset + member.offset;
785 prop = eClass_FindProperty(objectType, string, objectType.module);
787 type = superFindClass(prop.dataTypeString, objectType.module);
789 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
793 if(type && type.templateClass && type.templateClass == class(Container))
795 char * br = strchr(type.fullName, '<');
798 char className[1024];
799 strcpy(className, "Array");
800 strcat(className, br);
801 type = superFindClass(className, objectType.module);
805 // Find Member in Object Class
809 if(type && type.type == structClass)
813 value.p = (byte *)*object + offset;
814 memset(value.p, 0, type.structSize);
818 value.p = new0 byte[type.structSize];
826 if(eCON && ch != '=' && ch != ':')
828 f.Seek(seek-1, start);
831 if((ch == ':' || (eCON && ch == '=')) || (eCON && type && (prop || member)))
833 JSONResult itemResult = GetValue(type, value);
834 if(itemResult != syntaxError)
839 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
840 else if(itemResult == success)
842 BitMember bitMember = objectType.type == bitClass ? (BitMember) member : null;
846 // TOFIX: How to swiftly handle classes with base data type?
847 if(type.type == structClass)
849 else if(type.type == normalClass || type.type == noHeadClass)
851 void ** ptr = (void**)((byte *)*object + offset);
852 if(eClass_IsDerived(type, class(Container)) && *ptr)
854 Container container = (Container)*ptr;
860 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
862 if(objectType.type != bitClass)
864 *(double *)((byte *)*object + offset) = value.d;
867 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
869 if(objectType.type != bitClass)
871 *(float *)((byte *)*object + offset) = value.f;
874 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
875 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
877 if(objectType.type == bitClass)
879 bits &= ~bitMember.mask;
880 bits |= (value.ui64 << bitMember.pos) & bitMember.mask;
884 *(uint64 *)((byte *)*object + offset) = value.ui64;
887 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
888 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
890 if(objectType.type == bitClass)
892 bits &= ~bitMember.mask;
893 bits |= (value.ui << bitMember.pos) & bitMember.mask;
897 *(int *)((byte *)*object + offset) = value.i;
900 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
901 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
902 !strcmp(type.dataTypeString, "int16"))
904 if(objectType.type == bitClass)
906 bits &= ~bitMember.mask;
907 bits |= (value.us << bitMember.pos) & bitMember.mask;
911 *(short *)((byte *)*object + offset) = value.s;
914 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
915 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
917 if(objectType.type == bitClass)
919 bits &= ~bitMember.mask;
920 bits |= (value.uc << bitMember.pos) & bitMember.mask;
924 *(char *)((byte *)*object + offset) = value.c;
929 if(objectType.type != bitClass)
930 *(void **)((byte *)*object + offset) = value.p;
933 else if(prop && prop.Set)
935 if(objectType.type == bitClass)
937 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
939 switch(objectType.typeSize)
942 switch(type.typeSize)
944 case 1: ((byte (*)(byte, byte)) (void *)prop.Set)((byte)bits, value.uc); break;
945 case 2: ((byte (*)(byte, uint16))(void *)prop.Set)((byte)bits, value.us); break;
946 case 4: ((byte (*)(byte, uint32))(void *)prop.Set)((byte)bits, value.ui); break;
947 case 8: ((byte (*)(byte, uint64))(void *)prop.Set)((byte)bits, value.ui64); break;
951 switch(type.typeSize)
953 case 1: ((uint16 (*)(uint16, byte)) (void *)prop.Set)((uint16)bits, value.uc); break;
954 case 2: ((uint16 (*)(uint16, uint16))(void *)prop.Set)((uint16)bits, value.us); break;
955 case 4: ((uint16 (*)(uint16, uint32))(void *)prop.Set)((uint16)bits, value.ui); break;
956 case 8: ((uint16 (*)(uint16, uint64))(void *)prop.Set)((uint16)bits, value.ui64); break;
960 switch(type.typeSize)
962 case 1: ((uint32 (*)(uint32, byte)) (void *)prop.Set)((uint32)bits, value.uc); break;
963 case 2: ((uint32 (*)(uint32, uint16))(void *)prop.Set)((uint32)bits, value.us); break;
964 case 4: ((uint32 (*)(uint32, uint32))(void *)prop.Set)((uint32)bits, value.ui); break;
965 case 8: ((uint32 (*)(uint32, uint64))(void *)prop.Set)((uint32)bits, value.ui64); break;
969 switch(type.typeSize)
971 case 1: ((uint64 (*)(uint64, byte)) (void *)prop.Set)((uint64)bits, value.uc); break;
972 case 2: ((uint64 (*)(uint64, uint16))(void *)prop.Set)((uint64)bits, value.us); break;
973 case 4: ((uint64 (*)(uint64, uint32))(void *)prop.Set)((uint64)bits, value.ui); break;
974 case 8: ((uint64 (*)(uint64, uint64))(void *)prop.Set)((uint64)bits, value.ui64); break;
980 ; // TODO: Generate error
982 else if(!strcmp(type.dataTypeString, "char *"))
984 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
988 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
990 // TOFIX: How to swiftly handle classes with base data type?
991 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
993 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
995 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
997 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
999 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1000 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1002 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
1004 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1005 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1007 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
1009 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1010 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1011 !strcmp(type.dataTypeString, "int16"))
1013 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
1015 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1016 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1018 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
1022 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
1028 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
1030 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
1036 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
1037 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
1043 result = syntaxError;
1045 if(prop && type && type.type == structClass)
1051 else if(ch && ch != '}' && ch != ',' && (!eCON || ch != ';'))
1052 result = syntaxError;
1062 else if(ch != ',' && (!eCON || ch != ';'))
1063 result = syntaxError;
1067 if(objectType.type == bitClass)
1069 switch(objectType.typeSize)
1071 case 1: *(uint64 *)object = (byte) bits; break;
1072 case 2: *(uint64 *)object = (uint16) bits; break;
1073 case 4: *(uint64 *)object = (uint32) bits; break;
1074 case 8: *(uint64 *)object = (uint64) bits; break;
1082 JSONResult GetNumber(Class type, DataValue value)
1084 JSONResult result = success;
1087 bool comment = false;
1088 bool hexMode = false;
1091 while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' ||
1092 (c == 1 && tolower(ch) == 'x' && buffer[0] == '0') || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/' ||
1093 (hexMode && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')))))
1095 if(!comment && ch == '/')
1104 result = syntaxError;
1108 else if(comment && ch == '*')
1117 result = syntaxError;
1123 if(c == 1 && ch == 'x' && buffer[0] == '0')
1127 if(!f.Getc(&ch)) break;
1132 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
1135 if(!f.Getc(&ch)) break;
1139 //if(strchr(buffer, '.'))
1140 if(result == syntaxError)
1142 if(!type) return success;
1143 result = syntaxError;
1145 // TOFIX: How to swiftly handle classes with base data type?
1146 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1148 value.d = strtod(buffer, null);
1151 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1153 value.f = (float)strtod(buffer, null);
1156 // TOFIX: int64 looks for class long long?
1157 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
1158 else if(!strcmp(type.dataTypeString, "int64"))
1160 value.i64 = strtol(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1163 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
1165 value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1168 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1170 value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1175 value.i = (int)strtol(buffer, null, eCON ? 0 : 10);
1179 if(result == success && type.type == unitClass)
1181 // Convert to reference unit
1183 for(prop = type.conversions.first; prop; prop = prop.next)
1185 bool refProp = false;
1186 if(!strcmp(prop.name, type.base.fullName))
1190 Class c = eSystem_FindClass(type.module, prop.name);
1192 c = eSystem_FindClass(type.module.application, prop.name);
1196 for(p = c.conversions.first; p; p = p.next)
1198 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
1208 if(prop.Set && prop.Get)
1210 const String dts = type.base.dataTypeString;
1211 if(!strcmp(dts, "double"))
1212 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
1213 else if(!strcmp(dts, "float"))
1214 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
1215 else if(!strcmp(dts, "int"))
1216 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
1217 else if(!strcmp(dts, "int64"))
1218 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
1219 else if(!strcmp(dts, "unsigned int"))
1220 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
1221 else if(!strcmp(dts, "uint64"))
1222 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
1232 JSONResult GetColorAlpha(String string, DataValue value)
1234 ColorAlpha color = 0;
1238 if(string[0] == '0' && string[1] == 'x')
1239 color = (uint)strtoul(string, null, 0);
1244 if((d = strchr(string, ',')))
1246 a = (byte)atoi(string);
1251 if(c.class::OnGetDataFromString(d))
1257 color = (uint)strtoul(string, null, 16);
1265 static bool WriteMap(File f, Class type, Map map, int indent, bool eCON)
1270 bool isFirst = true;
1271 MapIterator it { map = map };
1272 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
1278 MapNode n = (MapNode)it.pointer;
1283 for(i = 0; i<indent; i++) f.Puts(" ");
1284 WriteONObject(f, mapNodeClass, n, indent, eCON, eCON ? true : false);
1288 for(i = 0; i<indent; i++) f.Puts(" ");
1296 static bool WriteArray(File f, Class type, Container array, int indent, bool eCON)
1301 bool isFirst = true;
1302 Iterator it { array };
1303 Class arrayType = type.templateArgs[0].dataTypeClass;
1309 DataValue value { };
1310 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
1317 // TODO: Verify the matching between template type and uint64
1318 if(arrayType.type == structClass)
1320 value.p = (void *)(uintptr)t;
1322 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
1325 //value.d = *(double *)&t;
1327 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
1330 //value.f = *(float *)&t;
1332 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
1333 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
1337 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
1338 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
1342 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
1343 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
1344 !strcmp(arrayType.dataTypeString, "int16"))
1348 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
1349 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
1355 value.p = (void *)(uintptr)t;
1357 for(i = 0; i<indent; i++) f.Puts(" ");
1358 WriteValue(f, arrayType, value, indent, eCON);
1362 for(i = 0; i<indent; i++) f.Puts(" ");
1370 static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON, bool useHex)
1373 bool needClass = eCON;
1376 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1377 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
1378 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1379 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
1380 else if(!strcmp(type.dataTypeString, "int64"))
1381 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
1382 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
1385 sprintf(buffer, __runtimePlatform == win32 ? "0x%016I64X" : "0x%016llX", value.ui64);
1387 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
1389 else if(!strcmp(type.dataTypeString, "int"))
1390 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
1391 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
1394 sprintf(buffer, "0x%08X", value.ui);
1396 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
1398 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
1399 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
1400 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
1401 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
1402 else if(!strcmp(type.dataTypeString, "char"))
1403 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
1404 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
1405 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
1407 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))) ||
1408 (type.type == enumClass && !eCON);
1409 if(quote) f.Puts("\"");
1411 if(quote) f.Puts("\"");
1415 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent, bool eCON)
1418 char * string = buffer;
1419 ColorAlpha color = value.i;
1422 DefinedColor c = color;
1426 a.class::OnGetString(buffer, null, null);
1427 len = strlen(buffer);
1428 buffer[len++] = ',';
1429 buffer[len++] = ' ';
1433 if(!c.class::OnGetString(string, null, null))
1434 sprintf(buffer, "0x%x", color);
1443 static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCON)
1445 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
1452 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
1458 char * string = value.p;
1490 for(i = 0; i<indent; i++) f.Puts(" ");
1494 else if(b == sizeof(buffer)-2 || !ch)
1497 if(ch) buffer[b] = 0;
1511 char * string = value.p;
1530 else if(b == sizeof(buffer)-2 || !ch)
1533 if(ch) buffer[b] = 0;
1547 else if(!strcmp(type.name, "bool"))
1554 else if(!strcmp(type.name, "SetBool"))
1556 if(value.i == SetBool::true)
1558 else if(value.i == SetBool::false)
1563 else if(type.type == enumClass)
1564 WriteNumber(f, type, value, indent, eCON, false);
1565 else if(eClass_IsDerived(type, class(Map)))
1567 WriteMap(f, type, value.p, indent, eCON);
1569 else if(eClass_IsDerived(type, class(Container)))
1571 WriteArray(f, type, value.p, indent, eCON);
1573 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1575 WriteONObject(f, type, value.p, indent, eCON, false);
1577 else if(eClass_IsDerived(type, class(ColorAlpha)))
1579 WriteColorAlpha(f, type, value, indent, eCON);
1581 else if(type.type == bitClass)
1584 dataType = superFindClass(type.dataTypeString, type.module);
1585 WriteNumber(f, dataType, value, indent, eCON, true);
1587 else if(type.type == systemClass || type.type == unitClass)
1589 WriteNumber(f, type, value, indent, eCON, false);
1594 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1596 bool result = false;
1599 result = WriteONObject(f, objectType, object, indent, false, false);
1605 public bool WriteECONObject(File f, Class objectType, void * object, int indent)
1607 bool result = false;
1610 result = WriteONObject(f, objectType, object, indent, true, false);
1616 static bool WriteONObject(File f, Class objectType, void * object, int indent, bool eCON, bool omitDefaultIdentifier)
1620 const char * string = null;
1622 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1626 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1630 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1631 if(string[0] == '\"')
1642 Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType;
1645 bool isFirst = true;
1646 Class mapKeyClass = null, mapDataClass = null;
1648 List<Class> bases { };
1650 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1652 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1653 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1656 if(eCON && _class != objectType && eClass_IsDerived(_class, objectType))
1658 f.Puts(_class.name);
1665 for(baseClass = _class; baseClass; baseClass = baseClass.base)
1667 if(baseClass.isInstanceClass || !baseClass.base)
1669 bases.Insert(null, baseClass);
1672 for(baseClass : bases)
1674 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1676 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1679 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1681 DataValue value { };
1682 bool isTemplateArg = false;
1685 if(mapKeyClass && !strcmp(prop.name, "key"))
1687 isTemplateArg = true;
1690 else if(mapDataClass && !strcmp(prop.name, "value"))
1692 isTemplateArg = true;
1693 type = mapDataClass;
1696 type = superFindClass(prop.dataTypeString, _class.module);
1699 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1702 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1704 // TOFIX: How to swiftly handle classes with base data type?
1705 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1707 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1709 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1711 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1713 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1714 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1716 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1718 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1719 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1721 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1723 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1724 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1725 !strcmp(type.dataTypeString, "int16"))
1727 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1729 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1730 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1732 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1735 else if(type.type == structClass)
1737 value.p = new0 byte[type.structSize];
1738 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1743 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1745 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1748 if(!isFirst) f.Puts(",\n");
1749 for(c = 0; c<indent; c++) f.Puts(" ");
1754 f.Putc((char)toupper(prop.name[0]));
1755 f.Puts(prop.name+1);
1758 else if(!omitDefaultIdentifier)
1763 WriteValue(f, type, value, indent, eCON);
1765 if(type.type == structClass)
1772 DataMember member = (DataMember)prop;
1773 DataValue value { };
1775 Class type = superFindClass(member.dataTypeString, _class.module);
1776 offset = member._class.offset + member.offset;
1780 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1782 if(type.type == structClass)
1783 value.p = (void *)((byte *)object + offset);
1785 value.p = *(void **)((byte *)object + offset);
1789 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1791 value.d = *(double *)((byte *)object + offset);
1793 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1795 value.f = *(float *)((byte *)object + offset);
1797 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1798 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1800 value.ui64 = *(uint64 *)((byte *)object + offset);
1802 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1803 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1805 value.i = *(int *)((byte *)object + offset);
1806 if(!strcmp(type.name, "bool") || type.type == enumClass)
1810 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1811 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1812 !strcmp(type.dataTypeString, "int16"))
1814 value.s = *(short *)((byte *)object + offset);
1816 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1817 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1819 value.c = *(char *)((byte *)object + offset);
1823 value.i = *(int *)((byte *)object + offset);
1826 if(!isFirst) f.Puts(",\n");
1827 for(c = 0; c<indent; c++) f.Puts(" ");
1832 f.Putc((char)toupper(member.name[0]));
1833 f.Puts(member.name+1);
1836 else if(!omitDefaultIdentifier)
1838 f.Puts(member.name);
1841 WriteValue(f, type, value, indent, eCON);
1852 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");
1860 static Class superFindClass(const String name, Module alternativeModule)
1862 Class _class = eSystem_FindClass(__thisModule, name);
1863 if(!_class && alternativeModule)
1864 _class = eSystem_FindClass(alternativeModule, name);
1866 _class = eSystem_FindClass(__thisModule.application, name);
1870 static bool isSubclass(Class type, const String name)
1872 Class _class = superFindClass(name, type.module);
1873 if(eClass_IsDerived(_class, type))