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)))
160 else if(ch == '-' || isdigit(ch))
162 result = GetNumber(type, value);
166 if(type.type == structClass || type.type == normalClass || type.type == noHeadClass)
168 void * object = value.p;
169 result = GetObject(type, &object);
172 if(type && type.type == structClass);
177 else if(type.type == bitClass)
180 result = GetObject(type, (void **)&object);
186 void * object = value.p;
187 result = GetObject(type, &object);
190 result = typeMismatch;
192 ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, object);
196 else if(isalpha(ch) || ch == '_')
201 if(GetIdentifier(&string, null))
204 if(eCON && type && (type.type == enumClass || type.type == unitClass))
206 // should this be set by calling __ecereVMethodID_class_OnGetDataFromString ?
207 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
210 result = typeMismatch;
212 else if(type && !strcmp(type.name, "bool"))
214 if(!strcmpi(string, "false")) value.i = 0;
215 else if(!strcmpi(string, "true")) value.i = 1;
217 result = typeMismatch;
219 else if(type && !strcmp(type.name, "SetBool"))
221 if(!strcmpi(string, "false")) value.i = SetBool::false;
222 else if(!strcmpi(string, "true")) value.i = SetBool::true;
224 result = typeMismatch;
226 else if(type && !strcmpi(string, "null"))
228 if(type.type != structClass)
231 else if(isSubclass(type, string))
233 void * object = value.p;
234 Class subtype = superFindClass(string, type.module);
236 result = GetObject(subtype, &object);
239 if(subtype && subtype.type == structClass);
240 else if(subtype && (subtype.type == normalClass || subtype.type == noHeadClass || subtype.type == bitClass))
246 result = typeMismatch;
248 ((void (*)(void *, void *))(void *)subtype._vTbl[__ecereVMethodID_class_OnFree])(subtype, object);
253 result = typeMismatch;
261 while(c < sizeof(buffer)-1 && (isalpha(ch) || isdigit(ch) || ch == '_'))
264 if(!f.Getc(&ch)) break;
271 if(!strcmp(type.name, "bool"))
273 if(!strcmpi(buffer, "false")) value.i = 0;
274 else if(!strcmpi(buffer, "true")) value.i = 1;
276 result = typeMismatch;
278 else if(!strcmp(type.name, "SetBool"))
280 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
281 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
283 result = typeMismatch;
285 else if(!strcmpi(buffer, "null"))
287 if(type.type != structClass)
291 result = typeMismatch;
294 result = typeMismatch;
297 else if(ch == '}' || ch == ']')
299 if(result == typeMismatch)
300 PrintLn("Warning: Value type mismatch");
304 JSONResult GetArray(Class type, Container * array)
306 JSONResult result = syntaxError;
311 *array = eInstance_New(type);
316 Class arrayType = null;
317 JSONResult itemResult;
319 if(eClass_IsDerived(type, class(Container)))
321 arrayType = type.templateArgs[0].dataTypeClass;
324 if(arrayType && arrayType.type == structClass)
325 value.p = new0 byte[arrayType.structSize];
326 itemResult = GetValue(arrayType, value);
327 if(itemResult == success)
329 // TODO: Verify the matching between template type and uint64
331 if(arrayType.type == structClass)
333 t = (uint64)(uintptr)value.p;
335 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
337 t = value.ui64; //*(uint64 *)&value.d;
339 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
341 t = value.ui; //f*(uint *)&value.f;
343 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
344 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
348 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
349 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
353 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
354 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
355 !strcmp(arrayType.dataTypeString, "int16"))
359 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
360 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
366 t = (uint64)(uintptr)value.p;
368 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
370 if(arrayType && arrayType.type == structClass)
375 if(itemResult == typeMismatch)
378 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
380 else if(itemResult == noItem)
386 if(result != syntaxError)
388 if(ch != ']' && ch != ',')
398 result = syntaxError;
406 JSONResult GetMap(Class type, Map * map)
408 JSONResult result = syntaxError;
413 Class mapNodeType = type.templateArgs[0].dataTypeClass;
414 Class keyType = mapNodeType.templateArgs[0].dataTypeClass;
415 Property keyProp = null;
416 if(keyType && !strcmp(keyType.dataTypeString, "char *"))
417 keyProp = eClass_FindProperty(mapNodeType, "key", mapNodeType.module);
419 *map = eInstance_New(type);
426 JSONResult itemResult;
428 itemResult = GetValue(mapNodeType, value);
429 if(itemResult == success)
431 String s = keyProp ? ((void * (*)(void *))(void *)keyProp.Get)(value.p) : null;
432 ((void *(*)(void *, uint64))(void *)map->Add)(*map, (uint64)(uintptr)value.p);
433 // Must free String keys here
438 if(itemResult == typeMismatch)
441 PrintLn("Warning: Incompatible value for array value, expected ", (String)mapNodeType.name);
443 else if(itemResult == noItem)
449 if(result != syntaxError)
451 if(ch != ']' && ch != ',')
461 result = syntaxError;
469 JSONResult GetIdentifier(String * string, bool * wasQuoted)
471 JSONResult result = syntaxError;
472 Array<char> buffer { minAllocSize = 256 };
473 bool comment = false;
485 if(!comment && ch == '/')
495 result = syntaxError;
501 result = syntaxError;
505 else if(comment && ch == '*')
517 result = syntaxError;
521 else if(ch == '\"' || (!quoted && !comment && ch && !isalpha(ch) && !isdigit(ch) && ch != '_'))
523 if(quoted && ch == '\"' && wasQuoted)
527 else if(!comment && ch)
530 if(buffer.minAllocSize < buffer.count)
531 buffer.minAllocSize *= 2;
534 if(result != syntaxError)
537 *string = CopyString(buffer.array);
540 if(ch != ',' && ch != '}' && ch != ';' && ch != '/' && ch != '=' && ch != ':')
545 JSONResult GetString(String * string)
547 JSONResult result = syntaxError;
548 Array<char> buffer { minAllocSize = 256 };
549 bool escaped = false;
553 if(ch == '\"' || eCON)
557 if(ch == '\\' && !escaped)
563 if(ch == 'b') ch = '\b';
564 else if(ch == 'f') ch = '\f';
565 else if(ch == 'n') ch = '\n';
566 else if(ch == 'r') ch = '\r';
567 else if(ch == 't') ch = '\t';
579 else if(eCON && ch == '\"')
583 bool lineComment = false;
584 bool comment = false;
590 if(!lineComment && !comment && pch == '/')
597 else if(lineComment && ch == '\n')
599 else if(comment && pch == '*' && ch == '/')
601 else if(ch == '=' || ch == ':' || ch == ';' || ch == ',' || ch == ']' || ch == '}')
616 f.Seek(seekback, current);
620 else if((!eCON && ch == '\"'))
627 if(buffer.minAllocSize < buffer.count)
628 buffer.minAllocSize *= 2;
633 *string = CopyString(buffer.array);
637 if(ch != ',' && ch != '}' && (!eCON || (ch != ';' && ch != '/')))
642 public JSONResult GetObject(Class objectType, void ** object)
644 JSONResult result = syntaxError;
645 if(!objectType || objectType.type != structClass)
647 if(objectType && objectType.type == bitClass)
648 *(uint64 *)object = 0;
655 Class mapKeyClass = null, mapDataClass = null;
656 Class curClass = null;
657 DataMember curMember = null;
658 DataMember subMemberStack[256];
659 int subMemberStackPos = 0;
662 if(objectType.type == bitClass)
664 switch(objectType.typeSize)
666 case 1: bits = (byte )*(uint64 *)object; break;
667 case 2: bits = (uint16)*(uint64 *)object; break;
668 case 4: bits = (uint32)*(uint64 *)object; break;
669 case 8: bits = (uint64)*(uint64 *)object; break;
673 if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
675 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
676 mapDataClass = objectType.templateArgs[2].dataTypeClass;
680 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
681 *object = eInstance_New(objectType);
686 bool wasQuoted = false;
691 SkipExtraSemicolon();
697 if(eCON ? GetIdentifier(&string, &wasQuoted) : GetString(&string))
699 DataMember member = null;
700 Property prop = null;
703 bool isTemplateArg = false;
708 prop = null; member = null;
709 if(ch == '=' || ch == ':')
712 string[0] = (char)tolower(string[0]);
715 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
716 if(!curMember) break;
717 if(!strcmp(curMember.name, string))
722 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
725 prop = curMember.isProperty ? (Property)curMember : null;
726 member = curMember.isProperty ? null : curMember;
728 if(mapKeyClass && !strcmp(prop ? prop.name : member.name, "key"))
731 isTemplateArg = true;
734 else if(mapDataClass && !strcmp(prop ? prop.name : member.name, "value"))
737 isTemplateArg = true;
739 offset = member._class.offset + member.offset;
742 type = superFindClass(prop.dataTypeString, objectType.module);
745 type = superFindClass(member.dataTypeString, objectType.module);
746 offset = member._class.offset + member.offset;
751 if(ch == '=' || ch == ':')
752 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
754 PrintLn("Warning: default member assignment: no more members");
757 if(objectType && !eCON)
759 string[0] = (char)tolower(string[0]);
760 if(mapKeyClass && !strcmp(string, "key"))
762 prop = eClass_FindProperty(objectType, "key", objectType.module);
764 isTemplateArg = true;
767 else if(mapDataClass && !strcmp(string, "value"))
769 prop = eClass_FindProperty(objectType, "value", objectType.module);
771 isTemplateArg = true;
775 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
778 type = superFindClass(member.dataTypeString, objectType.module);
779 offset = member._class.offset + member.offset;
783 prop = eClass_FindProperty(objectType, string, objectType.module);
785 type = superFindClass(prop.dataTypeString, objectType.module);
787 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
791 if(type && type.templateClass && type.templateClass == class(Container))
793 char * br = strchr(type.fullName, '<');
796 char className[1024];
797 strcpy(className, "Array");
798 strcat(className, br);
799 type = superFindClass(className, objectType.module);
803 // Find Member in Object Class
807 if(type && type.type == structClass)
811 value.p = (byte *)*object + offset;
812 memset(value.p, 0, type.structSize);
816 value.p = new0 byte[type.structSize];
824 if(eCON && ch != '=' && ch != ':')
826 f.Seek(seek-1, start);
829 if((ch == ':' || (eCON && ch == '=')) || (eCON && type && (prop || member)))
831 JSONResult itemResult = GetValue(type, value);
832 if(itemResult != syntaxError)
837 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
838 else if(itemResult == success)
840 BitMember bitMember = objectType.type == bitClass ? (BitMember) member : null;
844 // TOFIX: How to swiftly handle classes with base data type?
845 if(type.type == structClass)
847 else if(type.type == normalClass || type.type == noHeadClass)
849 void ** ptr = (void**)((byte *)*object + offset);
850 if(eClass_IsDerived(type, class(Container)) && *ptr)
852 Container container = (Container)*ptr;
858 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
860 if(objectType.type != bitClass)
862 *(double *)((byte *)*object + offset) = value.d;
865 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
867 if(objectType.type != bitClass)
869 *(float *)((byte *)*object + offset) = value.f;
872 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
873 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
875 if(objectType.type == bitClass)
877 bits &= ~bitMember.mask;
878 bits |= (value.ui64 << bitMember.pos) & bitMember.mask;
882 *(uint64 *)((byte *)*object + offset) = value.ui64;
885 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
886 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
888 if(objectType.type == bitClass)
890 bits &= ~bitMember.mask;
891 bits |= (value.ui << bitMember.pos) & bitMember.mask;
895 *(int *)((byte *)*object + offset) = 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 if(objectType.type == bitClass)
904 bits &= ~bitMember.mask;
905 bits |= (value.us << bitMember.pos) & bitMember.mask;
909 *(short *)((byte *)*object + offset) = value.s;
912 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
913 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
915 if(objectType.type == bitClass)
917 bits &= ~bitMember.mask;
918 bits |= (value.uc << bitMember.pos) & bitMember.mask;
922 *(char *)((byte *)*object + offset) = value.c;
927 if(objectType.type != bitClass)
928 *(void **)((byte *)*object + offset) = value.p;
931 else if(prop && prop.Set)
933 if(objectType.type == bitClass)
935 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
937 switch(objectType.typeSize)
940 switch(type.typeSize)
942 case 1: ((byte (*)(byte, byte)) (void *)prop.Set)((byte)bits, value.uc); break;
943 case 2: ((byte (*)(byte, uint16))(void *)prop.Set)((byte)bits, value.us); break;
944 case 4: ((byte (*)(byte, uint32))(void *)prop.Set)((byte)bits, value.ui); break;
945 case 8: ((byte (*)(byte, uint64))(void *)prop.Set)((byte)bits, value.ui64); break;
949 switch(type.typeSize)
951 case 1: ((uint16 (*)(uint16, byte)) (void *)prop.Set)((uint16)bits, value.uc); break;
952 case 2: ((uint16 (*)(uint16, uint16))(void *)prop.Set)((uint16)bits, value.us); break;
953 case 4: ((uint16 (*)(uint16, uint32))(void *)prop.Set)((uint16)bits, value.ui); break;
954 case 8: ((uint16 (*)(uint16, uint64))(void *)prop.Set)((uint16)bits, value.ui64); break;
958 switch(type.typeSize)
960 case 1: ((uint32 (*)(uint32, byte)) (void *)prop.Set)((uint32)bits, value.uc); break;
961 case 2: ((uint32 (*)(uint32, uint16))(void *)prop.Set)((uint32)bits, value.us); break;
962 case 4: ((uint32 (*)(uint32, uint32))(void *)prop.Set)((uint32)bits, value.ui); break;
963 case 8: ((uint32 (*)(uint32, uint64))(void *)prop.Set)((uint32)bits, value.ui64); break;
967 switch(type.typeSize)
969 case 1: ((uint64 (*)(uint64, byte)) (void *)prop.Set)((uint64)bits, value.uc); break;
970 case 2: ((uint64 (*)(uint64, uint16))(void *)prop.Set)((uint64)bits, value.us); break;
971 case 4: ((uint64 (*)(uint64, uint32))(void *)prop.Set)((uint64)bits, value.ui); break;
972 case 8: ((uint64 (*)(uint64, uint64))(void *)prop.Set)((uint64)bits, value.ui64); break;
978 ; // TODO: Generate error
980 else if(!strcmp(type.dataTypeString, "char *"))
982 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
986 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
988 // TOFIX: How to swiftly handle classes with base data type?
989 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
991 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
993 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
995 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
997 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
998 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1000 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
1002 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1003 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1005 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
1007 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1008 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1009 !strcmp(type.dataTypeString, "int16"))
1011 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
1013 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1014 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1016 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
1020 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
1026 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
1028 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
1034 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
1035 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
1041 result = syntaxError;
1043 if(prop && type && type.type == structClass)
1049 else if(ch && ch != '}' && ch != ',' && (!eCON || ch != ';'))
1050 result = syntaxError;
1060 else if(ch != ',' && (!eCON || ch != ';'))
1061 result = syntaxError;
1065 if(objectType.type == bitClass)
1067 switch(objectType.typeSize)
1069 case 1: *(uint64 *)object = (byte) bits; break;
1070 case 2: *(uint64 *)object = (uint16) bits; break;
1071 case 4: *(uint64 *)object = (uint32) bits; break;
1072 case 8: *(uint64 *)object = (uint64) bits; break;
1080 JSONResult GetNumber(Class type, DataValue value)
1082 JSONResult result = success;
1085 bool comment = false;
1086 bool hexMode = false;
1089 while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' ||
1090 (c == 1 && tolower(ch) == 'x' && buffer[0] == '0') || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/' ||
1091 (hexMode && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')))))
1093 if(!comment && ch == '/')
1102 result = syntaxError;
1106 else if(comment && ch == '*')
1115 result = syntaxError;
1121 if(c == 1 && ch == 'x' && buffer[0] == '0')
1125 if(!f.Getc(&ch)) break;
1130 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
1133 if(!f.Getc(&ch)) break;
1137 //if(strchr(buffer, '.'))
1138 if(result == syntaxError)
1140 if(!type) return success;
1141 result = syntaxError;
1143 // TOFIX: How to swiftly handle classes with base data type?
1144 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1146 value.d = strtod(buffer, null);
1149 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1151 value.f = (float)strtod(buffer, null);
1154 // TOFIX: int64 looks for class long long?
1155 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
1156 else if(!strcmp(type.dataTypeString, "int64"))
1158 value.i64 = strtol(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1161 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
1163 value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1166 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1168 value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1173 value.i = (int)strtol(buffer, null, eCON ? 0 : 10);
1177 if(result == success && type.type == unitClass)
1179 // Convert to reference unit
1181 for(prop = type.conversions.first; prop; prop = prop.next)
1183 bool refProp = false;
1184 if(!strcmp(prop.name, type.base.fullName))
1188 Class c = eSystem_FindClass(type.module, prop.name);
1190 c = eSystem_FindClass(type.module.application, prop.name);
1194 for(p = c.conversions.first; p; p = p.next)
1196 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
1206 if(prop.Set && prop.Get)
1208 const String dts = type.base.dataTypeString;
1209 if(!strcmp(dts, "double"))
1210 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
1211 else if(!strcmp(dts, "float"))
1212 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
1213 else if(!strcmp(dts, "int"))
1214 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
1215 else if(!strcmp(dts, "int64"))
1216 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
1217 else if(!strcmp(dts, "unsigned int"))
1218 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
1219 else if(!strcmp(dts, "uint64"))
1220 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
1230 JSONResult GetColorAlpha(String string, DataValue value)
1232 ColorAlpha color = 0;
1236 if(string[0] == '0' && string[1] == 'x')
1237 color = (uint)strtoul(string, null, 0);
1242 if((d = strchr(string, ',')))
1244 a = (byte)atoi(string);
1249 if(c.class::OnGetDataFromString(d))
1255 color = (uint)strtoul(string, null, 16);
1263 static bool WriteMap(File f, Class type, Map map, int indent, bool eCON)
1268 bool isFirst = true;
1269 MapIterator it { map = map };
1270 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
1276 MapNode n = (MapNode)it.pointer;
1281 for(i = 0; i<indent; i++) f.Puts(" ");
1282 WriteONObject(f, mapNodeClass, n, indent, eCON, eCON ? true : false);
1286 for(i = 0; i<indent; i++) f.Puts(" ");
1294 static bool WriteArray(File f, Class type, Container array, int indent, bool eCON)
1299 bool isFirst = true;
1300 Iterator it { array };
1301 Class arrayType = type.templateArgs[0].dataTypeClass;
1307 DataValue value { };
1308 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
1315 // TODO: Verify the matching between template type and uint64
1316 if(arrayType.type == structClass)
1318 value.p = (void *)(uintptr)t;
1320 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
1323 //value.d = *(double *)&t;
1325 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
1328 //value.f = *(float *)&t;
1330 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
1331 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
1335 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
1336 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
1340 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
1341 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
1342 !strcmp(arrayType.dataTypeString, "int16"))
1346 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
1347 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
1353 value.p = (void *)(uintptr)t;
1355 for(i = 0; i<indent; i++) f.Puts(" ");
1356 WriteValue(f, arrayType, value, indent, eCON);
1360 for(i = 0; i<indent; i++) f.Puts(" ");
1368 static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON, bool useHex)
1371 bool needClass = eCON;
1374 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1375 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
1376 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1377 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
1378 else if(!strcmp(type.dataTypeString, "int64"))
1379 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
1380 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
1383 sprintf(buffer, __runtimePlatform == win32 ? "0x%016I64X" : "0x%016llX", value.ui64);
1385 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
1387 else if(!strcmp(type.dataTypeString, "int"))
1388 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
1389 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
1392 sprintf(buffer, "0x%08X", value.ui);
1394 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
1396 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
1397 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
1398 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
1399 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
1400 else if(!strcmp(type.dataTypeString, "char"))
1401 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
1402 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
1403 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
1405 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))) ||
1406 (type.type == enumClass && !eCON);
1407 if(quote) f.Puts("\"");
1409 if(quote) f.Puts("\"");
1413 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent, bool eCON)
1416 char * string = buffer;
1417 ColorAlpha color = value.i;
1420 DefinedColor c = color;
1424 a.class::OnGetString(buffer, null, null);
1425 len = strlen(buffer);
1426 buffer[len++] = ',';
1427 buffer[len++] = ' ';
1431 if(!c.class::OnGetString(string, null, null))
1432 sprintf(buffer, "0x%x", color);
1441 static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCON)
1443 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
1450 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
1456 char * string = value.p;
1482 else if(c >= 4 && ch == '>' && string[c-2] == 'r' && string[c-3] == 'b' && string[c-4] == '<')
1484 // Add an automatic newline for <br> as this is how we imported documentor data...
1489 for(i = 0; i<indent; i++) f.Puts(" ");
1499 for(i = 0; i<indent; i++) f.Puts(" ");
1503 else if(b == sizeof(buffer)-2 || !ch)
1506 if(ch) buffer[b] = 0;
1520 char * string = value.p;
1539 else if(b == sizeof(buffer)-2 || !ch)
1542 if(ch) buffer[b] = 0;
1556 else if(!strcmp(type.name, "bool"))
1563 else if(!strcmp(type.name, "SetBool"))
1565 if(value.i == SetBool::true)
1567 else if(value.i == SetBool::false)
1572 else if(type.type == enumClass)
1573 WriteNumber(f, type, value, indent, eCON, false);
1574 else if(eClass_IsDerived(type, class(Map)))
1576 WriteMap(f, type, value.p, indent, eCON);
1578 else if(eClass_IsDerived(type, class(Container)))
1580 WriteArray(f, type, value.p, indent, eCON);
1582 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1584 WriteONObject(f, type, value.p, indent, eCON, false);
1586 else if(eClass_IsDerived(type, class(ColorAlpha)))
1588 WriteColorAlpha(f, type, value, indent, eCON);
1590 else if(type.type == bitClass)
1593 dataType = superFindClass(type.dataTypeString, type.module);
1594 WriteNumber(f, dataType, value, indent, eCON, true);
1596 else if(type.type == systemClass || type.type == unitClass)
1598 WriteNumber(f, type, value, indent, eCON, false);
1603 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1605 bool result = false;
1608 result = WriteONObject(f, objectType, object, indent, false, false);
1614 public bool WriteECONObject(File f, Class objectType, void * object, int indent)
1616 bool result = false;
1619 result = WriteONObject(f, objectType, object, indent, true, false);
1625 static bool WriteONObject(File f, Class objectType, void * object, int indent, bool eCON, bool omitDefaultIdentifier)
1629 const char * string = null;
1631 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1635 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1639 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1640 if(string[0] == '\"')
1651 Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType;
1654 bool isFirst = true;
1655 Class mapKeyClass = null, mapDataClass = null;
1657 List<Class> bases { };
1659 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1661 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1662 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1665 if(eCON && _class != objectType && eClass_IsDerived(_class, objectType))
1667 f.Puts(_class.name);
1674 for(baseClass = _class; baseClass; baseClass = baseClass.base)
1676 if(baseClass.isInstanceClass || !baseClass.base)
1678 bases.Insert(null, baseClass);
1681 for(baseClass : bases)
1683 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1685 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1688 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1690 DataValue value { };
1691 bool isTemplateArg = false;
1694 if(mapKeyClass && !strcmp(prop.name, "key"))
1696 isTemplateArg = true;
1699 else if(mapDataClass && !strcmp(prop.name, "value"))
1701 isTemplateArg = true;
1702 type = mapDataClass;
1705 type = superFindClass(prop.dataTypeString, _class.module);
1708 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1711 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1713 // TOFIX: How to swiftly handle classes with base data type?
1714 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1716 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1718 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1720 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1722 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1723 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1725 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1727 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1728 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1730 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1732 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1733 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1734 !strcmp(type.dataTypeString, "int16"))
1736 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1738 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1739 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1741 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1744 else if(type.type == structClass)
1746 value.p = new0 byte[type.structSize];
1747 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1752 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1754 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1757 if(!isFirst) f.Puts(",\n");
1758 for(c = 0; c<indent; c++) f.Puts(" ");
1763 f.Putc((char)toupper(prop.name[0]));
1764 f.Puts(prop.name+1);
1767 else if(!omitDefaultIdentifier)
1772 WriteValue(f, type, value, indent, eCON);
1774 if(type.type == structClass)
1781 DataMember member = (DataMember)prop;
1782 DataValue value { };
1784 Class type = superFindClass(member.dataTypeString, _class.module);
1785 offset = member._class.offset + member.offset;
1789 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1791 if(type.type == structClass)
1792 value.p = (void *)((byte *)object + offset);
1794 value.p = *(void **)((byte *)object + offset);
1798 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1800 value.d = *(double *)((byte *)object + offset);
1802 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1804 value.f = *(float *)((byte *)object + offset);
1806 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1807 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1809 value.ui64 = *(uint64 *)((byte *)object + offset);
1811 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1812 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1814 value.i = *(int *)((byte *)object + offset);
1815 if(!strcmp(type.name, "bool") || type.type == enumClass)
1819 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1820 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1821 !strcmp(type.dataTypeString, "int16"))
1823 value.s = *(short *)((byte *)object + offset);
1825 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1826 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1828 value.c = *(char *)((byte *)object + offset);
1832 value.i = *(int *)((byte *)object + offset);
1835 if(!isFirst) f.Puts(",\n");
1836 for(c = 0; c<indent; c++) f.Puts(" ");
1841 f.Putc((char)toupper(member.name[0]));
1842 f.Puts(member.name+1);
1845 else if(!omitDefaultIdentifier)
1847 f.Puts(member.name);
1850 WriteValue(f, type, value, indent, eCON);
1861 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");
1869 static Class superFindClass(const String name, Module alternativeModule)
1871 Class _class = eSystem_FindClass(__thisModule, name);
1872 if(!_class && alternativeModule)
1873 _class = eSystem_FindClass(alternativeModule, name);
1875 _class = eSystem_FindClass(__thisModule.application, name);
1879 static bool isSubclass(Class type, const String name)
1881 Class _class = superFindClass(name, type.module);
1882 if(eClass_IsDerived(_class, type))