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 == enumClass || type.type == unitClass))
195 // should this be set by calling __ecereVMethodID_class_OnGetDataFromString ?
196 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
199 result = typeMismatch;
201 else if(type && !strcmp(type.name, "bool"))
203 if(!strcmpi(string, "false")) value.i = 0;
204 else if(!strcmpi(string, "true")) value.i = 1;
206 result = typeMismatch;
208 else if(type && !strcmp(type.name, "SetBool"))
210 if(!strcmpi(string, "false")) value.i = SetBool::false;
211 else if(!strcmpi(string, "true")) value.i = SetBool::true;
213 result = typeMismatch;
215 else if(type && !strcmpi(string, "null"))
217 if(type.type != structClass)
220 else if(isSubclass(type, string))
222 void * object = value.p;
223 Class subtype = superFindClass(string, type.module);
225 result = GetObject(subtype, &object);
228 if(subtype && subtype.type == structClass);
229 else if(subtype && (subtype.type == normalClass || subtype.type == noHeadClass || subtype.type == bitClass))
235 result = typeMismatch;
237 ((void (*)(void *, void *))(void *)subtype._vTbl[__ecereVMethodID_class_OnFree])(subtype, object);
242 result = typeMismatch;
250 while(c < sizeof(buffer)-1 && (isalpha(ch) || isdigit(ch) || ch == '_'))
253 if(!f.Getc(&ch)) break;
260 if(!strcmp(type.name, "bool"))
262 if(!strcmpi(buffer, "false")) value.i = 0;
263 else if(!strcmpi(buffer, "true")) value.i = 1;
265 result = typeMismatch;
267 else if(!strcmp(type.name, "SetBool"))
269 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
270 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
272 result = typeMismatch;
274 else if(!strcmpi(buffer, "null"))
276 if(type.type != structClass)
280 result = typeMismatch;
283 result = typeMismatch;
286 else if(ch == '}' || ch == ']')
288 if(result == typeMismatch)
289 PrintLn("Warning: Value type mismatch");
293 JSONResult GetArray(Class type, Container * array)
295 JSONResult result = syntaxError;
300 *array = eInstance_New(type);
305 Class arrayType = null;
306 JSONResult itemResult;
308 if(eClass_IsDerived(type, class(Container)))
310 arrayType = type.templateArgs[0].dataTypeClass;
313 if(arrayType && arrayType.type == structClass)
314 value.p = new0 byte[arrayType.structSize];
315 itemResult = GetValue(arrayType, value);
316 if(itemResult == success)
318 // TODO: Verify the matching between template type and uint64
320 if(arrayType.type == structClass)
322 t = (uint64)(uintptr)value.p;
324 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
326 t = value.ui64; //*(uint64 *)&value.d;
328 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
330 t = value.ui; //f*(uint *)&value.f;
332 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
333 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
337 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
338 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
342 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
343 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
344 !strcmp(arrayType.dataTypeString, "int16"))
348 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
349 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
355 t = (uint64)(uintptr)value.p;
357 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
359 if(arrayType && arrayType.type == structClass)
364 if(itemResult == typeMismatch)
367 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
369 else if(itemResult == noItem)
375 if(result != syntaxError)
377 if(ch != ']' && ch != ',')
387 result = syntaxError;
395 JSONResult GetMap(Class type, Map * map)
397 JSONResult result = syntaxError;
402 Class mapNodeType = type.templateArgs[0].dataTypeClass;
403 Class keyType = mapNodeType.templateArgs[0].dataTypeClass;
404 Property keyProp = null;
405 if(keyType && !strcmp(keyType.dataTypeString, "char *"))
406 keyProp = eClass_FindProperty(mapNodeType, "key", mapNodeType.module);
408 *map = eInstance_New(type);
415 JSONResult itemResult;
417 itemResult = GetValue(mapNodeType, value);
418 if(itemResult == success)
420 String s = keyProp ? ((void * (*)(void *))(void *)keyProp.Get)(value.p) : null;
421 ((void *(*)(void *, uint64))(void *)map->Add)(*map, (uint64)(uintptr)value.p);
422 // Must free String keys here
427 if(itemResult == typeMismatch)
430 PrintLn("Warning: Incompatible value for array value, expected ", (String)mapNodeType.name);
432 else if(itemResult == noItem)
438 if(result != syntaxError)
440 if(ch != ']' && ch != ',')
450 result = syntaxError;
458 JSONResult GetIdentifier(String * string, bool * wasQuoted)
460 JSONResult result = syntaxError;
461 Array<char> buffer { minAllocSize = 256 };
462 bool comment = false;
474 if(!comment && ch == '/')
484 result = syntaxError;
490 result = syntaxError;
494 else if(comment && ch == '*')
506 result = syntaxError;
510 else if(ch == '\"' || (!quoted && !comment && ch && !isalpha(ch) && !isdigit(ch) && ch != '_'))
512 if(quoted && ch == '\"' && wasQuoted)
516 else if(!comment && ch)
519 if(buffer.minAllocSize < buffer.count)
520 buffer.minAllocSize *= 2;
523 if(result != syntaxError)
526 *string = CopyString(buffer.array);
529 if(ch != ',' && ch != '}' && ch != ';' && ch != '/' && ch != '=' && ch != ':')
534 JSONResult GetString(String * string)
536 JSONResult result = syntaxError;
537 Array<char> buffer { minAllocSize = 256 };
538 bool escaped = false;
542 if(ch == '\"' || eCON)
546 if(ch == '\\' && !escaped)
552 if(ch == 'b') ch = '\b';
553 else if(ch == 'f') ch = '\f';
554 else if(ch == 'n') ch = '\n';
555 else if(ch == 'r') ch = '\r';
556 else if(ch == 't') ch = '\t';
568 else if(eCON && ch == '\"')
572 bool lineComment = false;
573 bool comment = false;
579 if(!lineComment && !comment && pch == '/')
586 else if(lineComment && ch == '\n')
588 else if(comment && pch == '*' && ch == '/')
590 else if(ch == '=' || ch == ':' || ch == ';' || ch == ',' || ch == ']' || ch == '}')
605 f.Seek(seekback, current);
609 else if((!eCON && ch == '\"'))
616 if(buffer.minAllocSize < buffer.count)
617 buffer.minAllocSize *= 2;
622 *string = CopyString(buffer.array);
626 if(ch != ',' && ch != '}' && (!eCON || (ch != ';' && ch != '/')))
631 public JSONResult GetObject(Class objectType, void ** object)
633 JSONResult result = syntaxError;
634 if(!objectType || objectType.type != structClass)
639 Class mapKeyClass = null, mapDataClass = null;
640 Class curClass = null;
641 DataMember curMember = null;
642 DataMember subMemberStack[256];
643 int subMemberStackPos = 0;
645 if(objectType && objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
647 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
648 mapDataClass = objectType.templateArgs[2].dataTypeClass;
652 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
654 *object = eInstance_New(objectType);
656 else if(objectType && objectType.type != structClass)
658 *object = eSystem_New(objectType.typeSize);
664 bool wasQuoted = false;
669 SkipExtraSemicolon();
675 if(eCON ? GetIdentifier(&string, &wasQuoted) : GetString(&string))
677 DataMember member = null;
678 Property prop = null;
681 bool isTemplateArg = false;
686 prop = null; member = null;
687 if(ch == '=' || ch == ':')
690 string[0] = (char)tolower(string[0]);
693 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
694 if(!curMember) break;
695 if(!strcmp(curMember.name, string))
700 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
703 prop = curMember.isProperty ? (Property)curMember : null;
704 member = curMember.isProperty ? null : curMember;
706 if(mapKeyClass && !strcmp(prop ? prop.name : member.name, "key"))
709 isTemplateArg = true;
712 else if(mapDataClass && !strcmp(prop ? prop.name : member.name, "value"))
715 isTemplateArg = true;
717 offset = member._class.offset + member.offset;
720 type = superFindClass(prop.dataTypeString, objectType.module);
723 type = superFindClass(member.dataTypeString, objectType.module);
724 offset = member._class.offset + member.offset;
729 if(ch == '=' || ch == ':')
730 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
732 PrintLn("Warning: default member assignment: no more members");
735 if(objectType && !eCON)
737 string[0] = (char)tolower(string[0]);
738 if(mapKeyClass && !strcmp(string, "key"))
740 prop = eClass_FindProperty(objectType, "key", objectType.module);
742 isTemplateArg = true;
745 else if(mapDataClass && !strcmp(string, "value"))
747 prop = eClass_FindProperty(objectType, "value", objectType.module);
749 isTemplateArg = true;
753 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
756 type = superFindClass(member.dataTypeString, objectType.module);
757 offset = member._class.offset + member.offset;
761 prop = eClass_FindProperty(objectType, string, objectType.module);
763 type = superFindClass(prop.dataTypeString, objectType.module);
765 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
769 // Find Member in Object Class
773 if(type && type.type == structClass)
777 value.p = (byte *)*object + offset;
778 memset(value.p, 0, type.structSize);
782 value.p = new0 byte[type.structSize];
790 if(eCON && ch != '=' && ch != ':')
792 f.Seek(seek-1, start);
795 if((ch == ':' || (eCON && ch == '=')) || (eCON && type && (prop || member)))
797 JSONResult itemResult = GetValue(type, value);
798 if(itemResult != syntaxError)
803 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
804 else if(itemResult == success)
809 // TOFIX: How to swiftly handle classes with base data type?
810 if(type.type == structClass)
812 else if(type.type == normalClass || type.type == noHeadClass)
814 void ** ptr = (void**)((byte *)*object + offset);
815 if(eClass_IsDerived(type, class(Container)) && *ptr)
817 Container container = (Container)*ptr;
823 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
825 *(double *)((byte *)*object + offset) = value.d;
827 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
829 *(float *)((byte *)*object + offset) = value.f;
831 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
832 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
834 *(uint64 *)((byte *)*object + offset) = value.ui64;
836 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
837 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
839 *(int *)((byte *)*object + offset) = value.i;
841 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
842 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
843 !strcmp(type.dataTypeString, "int16"))
845 *(short *)((byte *)*object + offset) = value.s;
847 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
848 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
850 *(char *)((byte *)*object + offset) = value.c;
854 *(void **)((byte *)*object + offset) = value.p;
857 else if(prop && prop.Set)
859 if(!strcmp(type.dataTypeString, "char *"))
861 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
865 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
867 // TOFIX: How to swiftly handle classes with base data type?
868 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
870 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
872 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
874 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
876 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
877 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
879 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
881 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
882 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
884 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
886 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
887 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
888 !strcmp(type.dataTypeString, "int16"))
890 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
892 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
893 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
895 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
899 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
905 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
907 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
913 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
914 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
920 result = syntaxError;
922 if(prop && type && type.type == structClass)
928 else if(ch && ch != '}' && ch != ',' && (!eCON || ch != ';'))
929 result = syntaxError;
939 else if(ch != ',' && (!eCON || ch != ';'))
940 result = syntaxError;
948 JSONResult GetNumber(Class type, DataValue value)
950 JSONResult result = success;
953 bool comment = false;
956 while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' ||
957 tolower(ch) == 'x' || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/'))
959 if(!comment && ch == '/')
968 result = syntaxError;
972 else if(comment && ch == '*')
981 result = syntaxError;
987 if(!f.Getc(&ch)) break;
992 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
995 if(!f.Getc(&ch)) break;
999 //if(strchr(buffer, '.'))
1000 if(result == syntaxError)
1002 if(!type) return success;
1003 result = syntaxError;
1005 // TOFIX: How to swiftly handle classes with base data type?
1006 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1008 value.d = strtod(buffer, null);
1011 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1013 value.f = (float)strtod(buffer, null);
1016 // TOFIX: int64 looks for class long long?
1017 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
1018 else if(!strcmp(type.dataTypeString, "int64"))
1020 value.i64 = strtol(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1023 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
1025 value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1028 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int"))
1030 value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1035 value.i = (int)strtol(buffer, null, eCON ? 0 : 10);
1039 if(result == success && type.type == unitClass)
1041 // Convert to reference unit
1043 for(prop = type.conversions.first; prop; prop = prop.next)
1045 bool refProp = false;
1046 if(!strcmp(prop.name, type.base.fullName))
1050 Class c = eSystem_FindClass(type.module, prop.name);
1052 c = eSystem_FindClass(type.module.application, prop.name);
1056 for(p = c.conversions.first; p; p = p.next)
1058 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
1068 if(prop.Set && prop.Get)
1070 const String dts = type.base.dataTypeString;
1071 if(!strcmp(dts, "double"))
1072 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
1073 else if(!strcmp(dts, "float"))
1074 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
1075 else if(!strcmp(dts, "int"))
1076 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
1077 else if(!strcmp(dts, "int64"))
1078 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
1079 else if(!strcmp(dts, "unsigned int"))
1080 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
1081 else if(!strcmp(dts, "uint64"))
1082 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
1092 JSONResult GetColorAlpha(String string, DataValue value)
1094 ColorAlpha color = 0;
1098 if(string[0] == '0' && string[1] == 'x')
1099 color = (uint)strtoul(string, null, 0);
1104 if((d = strchr(string, ',')))
1106 a = (byte)atoi(string);
1111 if(c.class::OnGetDataFromString(d))
1117 color = (uint)strtoul(string, null, 16);
1125 static bool WriteMap(File f, Class type, Map map, int indent, bool eCON)
1130 bool isFirst = true;
1131 MapIterator it { map = map };
1132 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
1138 MapNode n = (MapNode)it.pointer;
1143 for(i = 0; i<indent; i++) f.Puts(" ");
1144 WriteONObject(f, mapNodeClass, n, indent, eCON, eCON ? true : false);
1148 for(i = 0; i<indent; i++) f.Puts(" ");
1156 static bool WriteArray(File f, Class type, Container array, int indent, bool eCON)
1161 bool isFirst = true;
1162 Iterator it { array };
1163 Class arrayType = type.templateArgs[0].dataTypeClass;
1169 DataValue value { };
1170 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
1177 // TODO: Verify the matching between template type and uint64
1178 if(arrayType.type == structClass)
1180 value.p = (void *)(uintptr)t;
1182 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
1185 //value.d = *(double *)&t;
1187 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
1190 //value.f = *(float *)&t;
1192 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
1193 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
1197 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
1198 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
1202 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
1203 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
1204 !strcmp(arrayType.dataTypeString, "int16"))
1208 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
1209 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
1215 value.p = (void *)(uintptr)t;
1217 for(i = 0; i<indent; i++) f.Puts(" ");
1218 WriteValue(f, arrayType, value, indent, eCON);
1222 for(i = 0; i<indent; i++) f.Puts(" ");
1230 static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON)
1233 bool needClass = eCON;
1236 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1237 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
1238 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1239 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
1240 else if(!strcmp(type.dataTypeString, "int64"))
1241 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
1242 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
1243 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
1244 else if(!strcmp(type.dataTypeString, "int"))
1245 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
1246 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
1247 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
1248 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
1249 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
1250 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
1251 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
1252 else if(!strcmp(type.dataTypeString, "char"))
1253 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
1254 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
1255 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
1257 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))) ||
1258 (type.type == enumClass && !eCON);
1259 if(quote) f.Puts("\"");
1261 if(quote) f.Puts("\"");
1265 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent, bool eCON)
1268 char * string = buffer;
1269 ColorAlpha color = value.i;
1272 DefinedColor c = color;
1276 a.class::OnGetString(buffer, null, null);
1277 len = strlen(buffer);
1278 buffer[len++] = ',';
1279 buffer[len++] = ' ';
1283 if(!c.class::OnGetString(string, null, null))
1284 sprintf(buffer, "0x%x", color);
1293 static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCON)
1295 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
1302 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
1308 char * string = value.p;
1340 for(i = 0; i<indent; i++) f.Puts(" ");
1344 else if(b == sizeof(buffer)-2 || !ch)
1347 if(ch) buffer[b] = 0;
1361 char * string = value.p;
1380 else if(b == sizeof(buffer)-2 || !ch)
1383 if(ch) buffer[b] = 0;
1397 else if(!strcmp(type.name, "bool"))
1404 else if(!strcmp(type.name, "SetBool"))
1406 if(value.i == SetBool::true)
1408 else if(value.i == SetBool::false)
1413 else if(type.type == enumClass)
1414 WriteNumber(f, type, value, indent, eCON);
1415 else if(eClass_IsDerived(type, class(Map)))
1417 WriteMap(f, type, value.p, indent, eCON);
1419 else if(eClass_IsDerived(type, class(Container)))
1421 WriteArray(f, type, value.p, indent, eCON);
1423 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1425 WriteONObject(f, type, value.p, indent, eCON, false);
1427 else if(eClass_IsDerived(type, class(ColorAlpha)))
1429 WriteColorAlpha(f, type, value, indent, eCON);
1431 else if(type.type == bitClass)
1434 dataType = superFindClass(type.dataTypeString, type.module);
1435 WriteNumber(f, dataType, value, indent, eCON);
1437 else if(type.type == systemClass || type.type == unitClass)
1439 WriteNumber(f, type, value, indent, eCON);
1444 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1446 bool result = false;
1449 result = WriteONObject(f, objectType, object, indent, false, false);
1455 public bool WriteECONObject(File f, Class objectType, void * object, int indent)
1457 bool result = false;
1460 result = WriteONObject(f, objectType, object, indent, true, false);
1466 static bool WriteONObject(File f, Class objectType, void * object, int indent, bool eCON, bool omitDefaultIdentifier)
1470 const char * string = null;
1472 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1476 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1480 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1481 if(string[0] == '\"')
1492 Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType;
1495 bool isFirst = true;
1496 Class mapKeyClass = null, mapDataClass = null;
1498 List<Class> bases { };
1500 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1502 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1503 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1506 if(eCON && _class != objectType && eClass_IsDerived(_class, objectType))
1508 f.Puts(_class.name);
1515 for(baseClass = _class; baseClass; baseClass = baseClass.base)
1517 if(baseClass.isInstanceClass || !baseClass.base)
1519 bases.Insert(null, baseClass);
1522 for(baseClass : bases)
1524 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1526 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1529 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1531 DataValue value { };
1532 bool isTemplateArg = false;
1535 if(mapKeyClass && !strcmp(prop.name, "key"))
1537 isTemplateArg = true;
1540 else if(mapDataClass && !strcmp(prop.name, "value"))
1542 isTemplateArg = true;
1543 type = mapDataClass;
1546 type = superFindClass(prop.dataTypeString, _class.module);
1549 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1552 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1554 // TOFIX: How to swiftly handle classes with base data type?
1555 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1557 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1559 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1561 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1563 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1564 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1566 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1568 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1569 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1571 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1573 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1574 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1575 !strcmp(type.dataTypeString, "int16"))
1577 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1579 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1580 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1582 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1585 else if(type.type == structClass)
1587 value.p = new0 byte[type.structSize];
1588 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1593 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1595 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1598 if(!isFirst) f.Puts(",\n");
1599 for(c = 0; c<indent; c++) f.Puts(" ");
1604 f.Putc((char)toupper(prop.name[0]));
1605 f.Puts(prop.name+1);
1608 else if(!omitDefaultIdentifier)
1613 WriteValue(f, type, value, indent, eCON);
1615 if(type.type == structClass)
1622 DataMember member = (DataMember)prop;
1623 DataValue value { };
1625 Class type = superFindClass(member.dataTypeString, _class.module);
1626 offset = member._class.offset + member.offset;
1630 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1632 if(type.type == structClass)
1633 value.p = (void *)((byte *)object + offset);
1635 value.p = *(void **)((byte *)object + offset);
1639 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1641 value.d = *(double *)((byte *)object + offset);
1643 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1645 value.f = *(float *)((byte *)object + offset);
1647 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1648 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1650 value.ui64 = *(uint64 *)((byte *)object + offset);
1652 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1653 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1655 value.i = *(int *)((byte *)object + offset);
1656 if(!strcmp(type.name, "bool") || type.type == enumClass)
1660 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1661 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1662 !strcmp(type.dataTypeString, "int16"))
1664 value.s = *(short *)((byte *)object + offset);
1666 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1667 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1669 value.c = *(char *)((byte *)object + offset);
1673 value.i = *(int *)((byte *)object + offset);
1676 if(!isFirst) f.Puts(",\n");
1677 for(c = 0; c<indent; c++) f.Puts(" ");
1682 f.Putc((char)toupper(member.name[0]));
1683 f.Puts(member.name+1);
1686 else if(!omitDefaultIdentifier)
1688 f.Puts(member.name);
1691 WriteValue(f, type, value, indent, eCON);
1702 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");
1710 static Class superFindClass(const String name, Module alternativeModule)
1712 Class _class = eSystem_FindClass(__thisModule, name);
1713 if(!_class && alternativeModule)
1714 _class = eSystem_FindClass(alternativeModule, name);
1716 _class = eSystem_FindClass(__thisModule.application, name);
1720 static bool isSubclass(Class type, const String name)
1722 Class _class = superFindClass(name, type.module);
1723 if(eClass_IsDerived(_class, type))