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 == '\"' || (!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 != '=')
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 == '}')
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;
691 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
692 if(!curMember) break;
693 if(!strcmp(curMember.name, string))
698 eClass_FindNextMember(objectType, &curClass, &curMember, subMemberStack, &subMemberStackPos);
701 prop = curMember.isProperty ? (Property)curMember : null;
702 member = curMember.isProperty ? null : curMember;
704 if(mapKeyClass && !strcmp(prop ? prop.name : member.name, "key"))
707 isTemplateArg = true;
710 else if(mapDataClass && !strcmp(prop ? prop.name : member.name, "value"))
713 isTemplateArg = true;
715 offset = member._class.offset + member.offset;
718 type = superFindClass(prop.dataTypeString, objectType.module);
721 type = superFindClass(member.dataTypeString, objectType.module);
722 offset = member._class.offset + member.offset;
728 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
730 PrintLn("Warning: default member assignment: no more members");
733 if(objectType && !eCON)
735 string[0] = (char)tolower(string[0]);
736 if(mapKeyClass && !strcmp(string, "key"))
738 prop = eClass_FindProperty(objectType, "key", objectType.module);
740 isTemplateArg = true;
743 else if(mapDataClass && !strcmp(string, "value"))
745 prop = eClass_FindProperty(objectType, "value", objectType.module);
747 isTemplateArg = true;
751 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
754 type = superFindClass(member.dataTypeString, objectType.module);
755 offset = member._class.offset + member.offset;
759 prop = eClass_FindProperty(objectType, string, objectType.module);
761 type = superFindClass(prop.dataTypeString, objectType.module);
763 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
767 // Find Member in Object Class
771 if(type && type.type == structClass)
775 value.p = (byte *)*object + offset;
776 memset(value.p, 0, type.structSize);
780 value.p = new0 byte[type.structSize];
788 if(eCON && ch != '=')
790 f.Seek(seek-1, start);
793 if(ch == (eCON ? '=' : ':') || (eCON && type && (prop || member)))
795 JSONResult itemResult = GetValue(type, value);
796 if(itemResult != syntaxError)
801 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
802 else if(itemResult == success)
807 // TOFIX: How to swiftly handle classes with base data type?
808 if(type.type == structClass)
810 else if(type.type == normalClass || type.type == noHeadClass)
812 void ** ptr = (void**)((byte *)*object + offset);
813 if(eClass_IsDerived(type, class(Container)) && *ptr)
815 Container container = (Container)*ptr;
821 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
823 *(double *)((byte *)*object + offset) = value.d;
825 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
827 *(float *)((byte *)*object + offset) = value.f;
829 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
830 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
832 *(uint64 *)((byte *)*object + offset) = value.ui64;
834 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
835 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
837 *(int *)((byte *)*object + offset) = value.i;
839 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
840 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
841 !strcmp(type.dataTypeString, "int16"))
843 *(short *)((byte *)*object + offset) = value.s;
845 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
846 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
848 *(char *)((byte *)*object + offset) = value.c;
852 *(void **)((byte *)*object + offset) = value.p;
855 else if(prop && prop.Set)
857 if(!strcmp(type.dataTypeString, "char *"))
859 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
863 else if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
865 // TOFIX: How to swiftly handle classes with base data type?
866 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
868 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
870 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
872 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
874 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
875 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
877 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
879 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
880 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
882 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
884 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
885 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
886 !strcmp(type.dataTypeString, "int16"))
888 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
890 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
891 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
893 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
897 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
903 ((void (*)(void *, uint64))(void *)prop.Set)(*object, (uint64)(uintptr)value.p);
905 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
911 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
912 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
918 result = syntaxError;
920 if(prop && type && type.type == structClass)
926 else if(ch && ch != '}' && ch != ',' && (!eCON || ch != ';'))
927 result = syntaxError;
937 else if(ch != ',' && (!eCON || ch != ';'))
938 result = syntaxError;
946 JSONResult GetNumber(Class type, DataValue value)
948 JSONResult result = success;
951 bool comment = false;
954 while(c < sizeof(buffer)-1 && (comment || ch == '-' || ch == '.' || tolower(ch) == 'f' ||
955 tolower(ch) == 'x' || tolower(ch) == 'e' || ch == '+' || isdigit(ch) || ch == '/'))
957 if(!comment && ch == '/')
966 result = syntaxError;
970 else if(comment && ch == '*')
979 result = syntaxError;
985 if(!f.Getc(&ch)) break;
990 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
993 if(!f.Getc(&ch)) break;
997 //if(strchr(buffer, '.'))
998 if(result == syntaxError)
1000 if(!type) return success;
1001 result = syntaxError;
1003 // TOFIX: How to swiftly handle classes with base data type?
1004 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1006 value.d = strtod(buffer, null);
1009 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1011 value.f = (float)strtod(buffer, null);
1014 // TOFIX: int64 looks for class long long?
1015 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
1016 else if(!strcmp(type.dataTypeString, "int64"))
1018 value.i64 = strtol(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1021 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
1023 value.ui64 = strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1026 else if(type == class(uint) || !strcmp(type.dataTypeString, "unsigned int"))
1028 value.ui = (uint)strtoul(buffer, null, eCON ? 0 : 10); // TOFIX: 64 bit support
1033 value.i = (int)strtol(buffer, null, eCON ? 0 : 10);
1037 if(result == success && type.type == unitClass)
1039 // Convert to reference unit
1041 for(prop = type.conversions.first; prop; prop = prop.next)
1043 bool refProp = false;
1044 if(!strcmp(prop.name, type.base.fullName))
1048 Class c = eSystem_FindClass(type.module, prop.name);
1050 c = eSystem_FindClass(type.module.application, prop.name);
1054 for(p = c.conversions.first; p; p = p.next)
1056 if(!strcmp(p.name, type.base.fullName) && !p.Set && !p.Get)
1066 if(prop.Set && prop.Get)
1068 const String dts = type.base.dataTypeString;
1069 if(!strcmp(dts, "double"))
1070 value.d = ((double(*)(double))(void *)prop.Get)(value.d);
1071 else if(!strcmp(dts, "float"))
1072 value.f = ((float(*)(float))(void *)prop.Get)(value.f);
1073 else if(!strcmp(dts, "int"))
1074 value.i = ((int(*)(int))(void *)prop.Get)(value.i);
1075 else if(!strcmp(dts, "int64"))
1076 value.i64 = ((int64(*)(int64))(void *)prop.Get)(value.i64);
1077 else if(!strcmp(dts, "unsigned int"))
1078 value.ui = ((uint(*)(uint))(void *)prop.Get)(value.ui);
1079 else if(!strcmp(dts, "uint64"))
1080 value.ui64 = ((uint64(*)(uint64))(void *)prop.Get)(value.ui64);
1090 JSONResult GetColorAlpha(String string, DataValue value)
1092 ColorAlpha color = 0;
1096 if(string[0] == '0' && string[1] == 'x')
1097 color = (uint)strtoul(string, null, 0);
1102 if((d = strchr(string, ',')))
1104 a = (byte)atoi(string);
1109 if(c.class::OnGetDataFromString(d))
1115 color = (uint)strtoul(string, null, 16);
1123 static bool WriteMap(File f, Class type, Map map, int indent, bool eCON)
1128 bool isFirst = true;
1129 MapIterator it { map = map };
1130 Class mapNodeClass = map._class.templateArgs[0].dataTypeClass;
1136 MapNode n = (MapNode)it.pointer;
1141 for(i = 0; i<indent; i++) f.Puts(" ");
1142 WriteONObject(f, mapNodeClass, n, indent, eCON, eCON ? true : false);
1146 for(i = 0; i<indent; i++) f.Puts(" ");
1154 static bool WriteArray(File f, Class type, Container array, int indent, bool eCON)
1159 bool isFirst = true;
1160 Iterator it { array };
1161 Class arrayType = type.templateArgs[0].dataTypeClass;
1167 DataValue value { };
1168 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
1175 // TODO: Verify the matching between template type and uint64
1176 if(arrayType.type == structClass)
1178 value.p = (void *)(uintptr)t;
1180 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
1183 //value.d = *(double *)&t;
1185 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
1188 //value.f = *(float *)&t;
1190 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
1191 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
1195 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
1196 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
1200 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
1201 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
1202 !strcmp(arrayType.dataTypeString, "int16"))
1206 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
1207 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
1213 value.p = (void *)(uintptr)t;
1215 for(i = 0; i<indent; i++) f.Puts(" ");
1216 WriteValue(f, arrayType, value, indent, eCON);
1220 for(i = 0; i<indent; i++) f.Puts(" ");
1228 static bool WriteNumber(File f, Class type, DataValue value, int indent, bool eCON)
1231 bool needClass = eCON;
1234 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1235 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
1236 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1237 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
1238 else if(!strcmp(type.dataTypeString, "int64"))
1239 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
1240 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
1241 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
1242 else if(!strcmp(type.dataTypeString, "int"))
1243 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
1244 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
1245 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
1246 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
1247 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
1248 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
1249 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
1250 else if(!strcmp(type.dataTypeString, "char"))
1251 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
1252 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
1253 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
1255 quote = (type.type == unitClass && ((buffer[0] != '.' && !isdigit(buffer[0])) || strchr(buffer, ' '))) ||
1256 (type.type == enumClass && !eCON);
1257 if(quote) f.Puts("\"");
1259 if(quote) f.Puts("\"");
1263 public bool WriteColorAlpha(File f, Class type, DataValue value, int indent, bool eCON)
1266 char * string = buffer;
1267 ColorAlpha color = value.i;
1270 DefinedColor c = color;
1274 a.class::OnGetString(buffer, null, null);
1275 len = strlen(buffer);
1276 buffer[len++] = ',';
1277 buffer[len++] = ' ';
1281 if(!c.class::OnGetString(string, null, null))
1282 sprintf(buffer, "0x%x", color);
1291 static bool WriteValue(File f, Class type, DataValue value, int indent, bool eCON)
1293 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
1300 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
1306 char * string = value.p;
1338 for(i = 0; i<indent; i++) f.Puts(" ");
1342 else if(b == sizeof(buffer)-2 || !ch)
1345 if(ch) buffer[b] = 0;
1359 char * string = value.p;
1378 else if(b == sizeof(buffer)-2 || !ch)
1381 if(ch) buffer[b] = 0;
1395 else if(!strcmp(type.name, "bool"))
1402 else if(!strcmp(type.name, "SetBool"))
1404 if(value.i == SetBool::true)
1406 else if(value.i == SetBool::false)
1411 else if(type.type == enumClass)
1412 WriteNumber(f, type, value, indent, eCON);
1413 else if(eClass_IsDerived(type, class(Map)))
1415 WriteMap(f, type, value.p, indent, eCON);
1417 else if(eClass_IsDerived(type, class(Container)))
1419 WriteArray(f, type, value.p, indent, eCON);
1421 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
1423 WriteONObject(f, type, value.p, indent, eCON, false);
1425 else if(eClass_IsDerived(type, class(ColorAlpha)))
1427 WriteColorAlpha(f, type, value, indent, eCON);
1429 else if(type.type == bitClass)
1432 dataType = superFindClass(type.dataTypeString, type.module);
1433 WriteNumber(f, dataType, value, indent, eCON);
1435 else if(type.type == systemClass || type.type == unitClass)
1437 WriteNumber(f, type, value, indent, eCON);
1442 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
1444 bool result = false;
1447 result = WriteONObject(f, objectType, object, indent, false, false);
1453 public bool WriteECONObject(File f, Class objectType, void * object, int indent)
1455 bool result = false;
1458 result = WriteONObject(f, objectType, object, indent, true, false);
1464 static bool WriteONObject(File f, Class objectType, void * object, int indent, bool eCON, bool omitDefaultIdentifier)
1468 const char * string = null;
1470 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
1474 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
1478 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
1479 if(string[0] == '\"')
1490 Class _class = (eCON && objectType.type == normalClass) ? ((Instance)object)._class : objectType;
1493 bool isFirst = true;
1494 Class mapKeyClass = null, mapDataClass = null;
1496 List<Class> bases { };
1498 if(objectType.templateClass && eClass_IsDerived(objectType.templateClass, class(MapNode)))
1500 mapKeyClass = objectType.templateArgs[0].dataTypeClass;
1501 mapDataClass = objectType.templateArgs[2].dataTypeClass;
1504 if(eCON && _class != objectType && eClass_IsDerived(_class, objectType))
1506 f.Puts(_class.name);
1513 for(baseClass = _class; baseClass; baseClass = baseClass.base)
1515 if(baseClass.isInstanceClass || !baseClass.base)
1517 bases.Insert(null, baseClass);
1520 for(baseClass : bases)
1522 for(prop = baseClass.membersAndProperties.first; prop; prop = prop.next)
1524 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
1527 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
1529 DataValue value { };
1530 bool isTemplateArg = false;
1533 if(mapKeyClass && !strcmp(prop.name, "key"))
1535 isTemplateArg = true;
1538 else if(mapDataClass && !strcmp(prop.name, "value"))
1540 isTemplateArg = true;
1541 type = mapDataClass;
1544 type = superFindClass(prop.dataTypeString, _class.module);
1547 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
1550 if(type.type == enumClass || type.type == bitClass || type.type == unitClass || type.type == systemClass)
1552 // TOFIX: How to swiftly handle classes with base data type?
1553 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1555 value.d = ((double (*)(void *))(void *)prop.Get)(object);
1557 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1559 value.f = ((float (*)(void *))(void *)prop.Get)(object);
1561 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1562 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1564 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
1566 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1567 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1569 value.i = ((int (*)(void *))(void *)prop.Get)(object);
1571 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1572 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1573 !strcmp(type.dataTypeString, "int16"))
1575 value.s = ((short (*)(void *))(void *)prop.Get)(object);
1577 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1578 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1580 value.c = ((char (*)(void *))(void *)prop.Get)(object);
1583 else if(type.type == structClass)
1585 value.p = new0 byte[type.structSize];
1586 ((void (*)(void *, void *))(void *)prop.Get)(object, value.p);
1591 value.p = (void *)(uintptr)((uint64 (*)(void *))(void *)prop.Get)(object);
1593 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
1596 if(!isFirst) f.Puts(",\n");
1597 for(c = 0; c<indent; c++) f.Puts(" ");
1602 f.Putc((char)toupper(prop.name[0]));
1603 f.Puts(prop.name+1);
1606 else if(!omitDefaultIdentifier)
1611 WriteValue(f, type, value, indent, eCON);
1613 if(type.type == structClass)
1620 DataMember member = (DataMember)prop;
1621 DataValue value { };
1623 Class type = superFindClass(member.dataTypeString, _class.module);
1624 offset = member._class.offset + member.offset;
1628 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
1630 if(type.type == structClass)
1631 value.p = (void *)((byte *)object + offset);
1633 value.p = *(void **)((byte *)object + offset);
1637 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
1639 value.d = *(double *)((byte *)object + offset);
1641 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
1643 value.f = *(float *)((byte *)object + offset);
1645 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
1646 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
1648 value.ui64 = *(uint64 *)((byte *)object + offset);
1650 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
1651 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
1653 value.i = *(int *)((byte *)object + offset);
1654 if(!strcmp(type.name, "bool") || type.type == enumClass)
1658 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
1659 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
1660 !strcmp(type.dataTypeString, "int16"))
1662 value.s = *(short *)((byte *)object + offset);
1664 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
1665 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
1667 value.c = *(char *)((byte *)object + offset);
1671 value.i = *(int *)((byte *)object + offset);
1674 if(!isFirst) f.Puts(",\n");
1675 for(c = 0; c<indent; c++) f.Puts(" ");
1680 f.Putc((char)toupper(member.name[0]));
1681 f.Puts(member.name+1);
1684 else if(!omitDefaultIdentifier)
1686 f.Puts(member.name);
1689 WriteValue(f, type, value, indent, eCON);
1700 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");
1708 static Class superFindClass(const String name, Module alternativeModule)
1710 Class _class = eSystem_FindClass(__thisModule, name);
1711 if(!_class && alternativeModule)
1712 _class = eSystem_FindClass(alternativeModule, name);
1714 _class = eSystem_FindClass(__thisModule.application, name);
1718 static bool isSubclass(Class type, const String name)
1720 Class _class = superFindClass(name, type.module);
1721 if(eClass_IsDerived(_class, type))