7 __attribute__((unused)) static void UnusedFunction()
10 a.OnGetDataFromString(null);
11 a.OnGetString(null, 0, 0);
14 extern int __ecereVMethodID_class_OnGetDataFromString;
15 extern int __ecereVMethodID_class_OnGetString;
16 extern int __ecereVMethodID_class_OnFree;
19 public enum JSONResult { syntaxError, success, typeMismatch, noItem };
21 public enum SetBool : uint
23 unset, false, true /*; // Syntax error! */
25 /*public property bool // NOT WORKING!
27 set { return value ? true : false; }
28 get { return (this == true); }
33 public class JSONParser
41 while(!f.Eof() && (!ch || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'))
47 JSONResult GetValue(Class type, DataValue value)
49 JSONResult result = syntaxError;
55 result = GetString(&string);
59 if(type && (!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *")))
63 else if(type && type.type == enumClass)
65 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, &value.i, string))
68 result = typeMismatch;
71 else if(type && (prop = eClass_FindProperty(type, "String", type.module)))
73 // TOFIX: Add more conversion property support... Expecting void * compatible here
74 value.p = ((void *(*)())(void *)prop.Set)(string);
78 else if(type && (type.type == structClass))
80 if(((bool (*)(void *, void *, const char *))(void *)type._vTbl[__ecereVMethodID_class_OnGetDataFromString])(type, value.p, string))
83 result = typeMismatch;
89 result = typeMismatch;
96 result = GetArray(type, &array);
98 if(type && eClass_IsDerived(type, class(Container)))
107 result = typeMismatch;
110 else if(ch == '-' || isdigit(ch))
112 result = GetNumber(type, value);
116 void * object = value.p;
117 result = GetObject(type, &object);
120 if(type.type == structClass);
121 else if(type && (type.type == normalClass || type.type == noHeadClass || type.type == bitClass))
127 result = typeMismatch;
128 ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, object);
136 while(c < sizeof(buffer)-1 && isalpha(ch))
139 if(!f.Getc(&ch)) break;
146 if(!strcmp(type.name, "bool"))
148 if(!strcmpi(buffer, "false")) value.i = 0;
149 else if(!strcmpi(buffer, "true")) value.i = 1;
151 result = typeMismatch;
153 else if(!strcmp(type.name, "SetBool"))
155 if(!strcmpi(buffer, "false")) value.i = SetBool::false;
156 else if(!strcmpi(buffer, "true")) value.i = SetBool::true;
158 result = typeMismatch;
160 else if(!strcmpi(buffer, "null"))
165 result = typeMismatch;
168 result = typeMismatch;
170 else if(ch == '}' || ch == ']')
175 JSONResult GetArray(Class type, Container * array)
177 JSONResult result = syntaxError;
182 *array = eInstance_New(type);
187 Class arrayType = null;
188 JSONResult itemResult;
190 if(eClass_IsDerived(type, class(Container)))
192 arrayType = type.templateArgs[0].dataTypeClass;
195 itemResult = GetValue(arrayType, value);
196 if(itemResult == success)
198 // TODO: Verify the matching between template type and uint64
200 if(arrayType.type == structClass)
202 t = (uint64) value.p;
204 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
206 t = *(uint64 *)&value.d;
208 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
210 t = *(uint *)&value.f;
212 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
213 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
217 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
218 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
222 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
223 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
224 !strcmp(arrayType.dataTypeString, "int16"))
228 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
229 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
237 ((void *(*)(void *, uint64))(void *)array->Add)(*array, t);
241 if(itemResult == typeMismatch)
244 PrintLn("Warning: Incompatible value for array value, expected ", (String)arrayType.name);
246 else if(itemResult == noItem)
252 if(result != syntaxError)
254 if(ch != ']' && ch != ',')
264 result = syntaxError;
272 JSONResult GetString(String * string)
274 JSONResult result = syntaxError;
275 Array<char> buffer { minAllocSize = 256 };
276 bool escaped = false;
284 if(ch == '\\' && !escaped)
290 if(ch == 'b') ch = '\b';
291 else if(ch == 'f') ch = '\f';
292 else if(ch == 'n') ch = '\n';
293 else if(ch == 'r') ch = '\r';
294 else if(ch == 't') ch = '\t';
311 if(buffer.minAllocSize < buffer.count)
312 buffer.minAllocSize *= 2;
316 *string = CopyString(buffer.array);
324 public JSONResult GetObject(Class objectType, void ** object)
326 JSONResult result = syntaxError;
327 if(objectType.type != structClass)
333 if(objectType && (objectType.type == noHeadClass || objectType.type == normalClass))
335 *object = eInstance_New(objectType);
337 else if(objectType && objectType.type != structClass)
339 *object = eSystem_New(objectType.typeSize);
346 if(GetString(&string))
348 DataMember member = null;
349 Property prop = null;
354 string[0] = (char)tolower(string[0]);
355 member = eClass_FindDataMember(objectType, string, objectType.module, null, null);
358 type = eSystem_FindClass(__thisModule, member.dataTypeString);
360 type = eSystem_FindClass(__thisModule.application, member.dataTypeString);
364 prop = eClass_FindProperty(objectType, string, objectType.module);
367 type = eSystem_FindClass(__thisModule, prop.dataTypeString);
369 type = eSystem_FindClass(__thisModule.application, prop.dataTypeString);
372 PrintLn("Warning: member ", string, " not found in class ", (String)objectType.name);
375 // Find Member in Object Class
379 if(type && type.type == structClass)
381 value.p = (byte *)*object + member._class.offset + member.offset;
387 JSONResult itemResult = GetValue(type, value);
388 if(itemResult != syntaxError)
394 PrintLn("warning: Unresolved data type ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
396 else if(itemResult == success)
401 // TOFIX: How to swiftly handle classes with base data type?
402 if(type.type == structClass)
404 else if(type.type == normalClass || type.type == noHeadClass)
406 void ** ptr = (void**)((byte *)*object + member._class.offset + member.offset);
407 if(eClass_IsDerived(type, class(Container)) && *ptr)
409 Container container = (Container)*ptr;
415 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
417 *(double *)((byte *)*object + member._class.offset + member.offset) = value.d;
419 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
421 *(float *)((byte *)*object + member._class.offset + member.offset) = value.f;
423 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
424 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
426 *(uint64 *)((byte *)*object + member._class.offset + member.offset) = value.ui64;
428 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
429 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
431 *(int *)((byte *)*object + member._class.offset + member.offset) = value.i;
433 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
434 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
435 !strcmp(type.dataTypeString, "int16"))
437 *(short *)((byte *)*object + member._class.offset + member.offset) = value.s;
439 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
440 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
442 *(char *)((byte *)*object + member._class.offset + member.offset) = value.c;
446 *(void **)((byte *)*object + member._class.offset + member.offset) = value.p;
449 else if(prop && prop.Set)
451 if(!strcmp(type.dataTypeString, "char *"))
453 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
456 // TOFIX: How to swiftly handle classes with base data type?
457 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
459 ((void (*)(void *, double))(void *)prop.Set)(*object, value.d);
461 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
463 ((void (*)(void *, float))(void *)prop.Set)(*object, value.f);
465 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
466 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
468 ((void (*)(void *, uint64))(void *)prop.Set)(*object, value.ui64);
470 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
471 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
473 ((void (*)(void *, int))(void *)prop.Set)(*object, value.i);
475 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
476 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
477 !strcmp(type.dataTypeString, "int16"))
479 ((void (*)(void *, short))(void *)prop.Set)(*object, value.s);
481 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
482 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
484 ((void (*)(void *, char))(void *)prop.Set)(*object, value.c);
488 ((void (*)(void *, void *))(void *)prop.Set)(*object, value.p);
494 PrintLn("Warning: Incompatible value for ", member ? (String)member.name : (String)prop.name,
495 ", expected ", member ? (String)member.dataTypeString : (String)prop.dataTypeString);
501 result = syntaxError;
505 result = syntaxError;
516 result = syntaxError;
524 JSONResult GetNumber(Class type, DataValue value)
526 JSONResult result = syntaxError;
529 while(c < sizeof(buffer)-1 && (ch == '-' || ch == '.' || tolower(ch) == 'e' || ch == '+' || isdigit(ch)))
532 if(!f.Getc(&ch)) break;
535 //if(strchr(buffer, '.'))
537 // TOFIX: How to swiftly handle classes with base data type?
538 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
540 value.d = strtod(buffer, null);
543 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
545 value.f = (float)strtod(buffer, null);
548 // TOFIX: int64 looks for class long long?
549 //else if(type == class(int64) || !strcmp(type.dataTypeString, "int64"))
550 else if(!strcmp(type.dataTypeString, "int64"))
552 value.i64 = strtol(buffer, null, 10); // TOFIX: 64 bit support
555 else if(type == class(uint64) || !strcmp(type.dataTypeString, "uint64"))
557 value.ui64 = strtol(buffer, null, 10); // TOFIX: 64 bit support
562 value.i = strtol(buffer, null, 10);
569 bool WriteArray(File f, Class type, Container array, int indent)
575 Iterator it { array };
576 Class arrayType = type.templateArgs[0].dataTypeClass;
583 uint64 t = ((uint64(*)(void *, void *))(void *)array.GetData)(array, it.pointer);
590 // TODO: Verify the matching between template type and uint64
591 if(arrayType.type == structClass)
595 else if(arrayType == class(double) || !strcmp(arrayType.dataTypeString, "double"))
597 value.d = *(double *)&t;
599 else if(arrayType == class(float) || !strcmp(arrayType.dataTypeString, "float"))
601 value.f = *(float *)&t;
603 else if(arrayType.typeSize == sizeof(int64) || !strcmp(arrayType.dataTypeString, "int64") ||
604 !strcmp(arrayType.dataTypeString, "unsigned int64") || !strcmp(arrayType.dataTypeString, "uint64"))
608 else if(arrayType.typeSize == sizeof(int) || !strcmp(arrayType.dataTypeString, "int") ||
609 !strcmp(arrayType.dataTypeString, "unsigned int") || !strcmp(arrayType.dataTypeString, "uint"))
613 else if(arrayType.typeSize == sizeof(short int) || !strcmp(arrayType.dataTypeString, "short") ||
614 !strcmp(arrayType.dataTypeString, "unsigned short") || !strcmp(arrayType.dataTypeString, "uint16") ||
615 !strcmp(arrayType.dataTypeString, "int16"))
619 else if(arrayType.typeSize == sizeof(byte) || !strcmp(arrayType.dataTypeString, "char") ||
620 !strcmp(arrayType.dataTypeString, "unsigned char") || !strcmp(arrayType.dataTypeString, "byte"))
628 for(i = 0; i<indent; i++) f.Puts(" ");
629 WriteValue(f, arrayType, value, indent);
633 for(i = 0; i<indent; i++) f.Puts(" ");
641 bool WriteNumber(File f, Class type, DataValue value, int indent)
644 bool needClass = false;
646 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
647 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.d, buffer, 0, &needClass);
648 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
649 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.f, buffer, null, &needClass);
650 else if(!strcmp(type.dataTypeString, "int64"))
651 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i64, buffer, null, &needClass);
652 else if(!strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || type.typeSize == sizeof(int64))
653 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui64, buffer, null, &needClass);
654 else if(!strcmp(type.dataTypeString, "int"))
655 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.i, buffer, null, &needClass);
656 else if(!strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint") || type.typeSize == sizeof(int))
657 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.ui, buffer, null, &needClass);
658 else if(!strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "int16"))
659 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.s, buffer, null, &needClass);
660 else if(!strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || type.typeSize == sizeof(short int))
661 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.us, buffer, null, &needClass);
662 else if(!strcmp(type.dataTypeString, "char"))
663 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.c, buffer, null, &needClass);
664 else if(!strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte") || type.typeSize == sizeof(byte))
665 ((const char *(*)(void *, void *, char *, void *, bool *))(void *)type._vTbl[__ecereVMethodID_class_OnGetString])(type, &value.uc, buffer, null, &needClass);
670 bool WriteValue(File f, Class type, DataValue value, int indent)
672 if(!strcmp(type.name, "String") || !strcmp(type.dataTypeString, "char *"))
675 //if(strchr(value.p, '\"') || strchr(value.p, '\\'))
680 char * string = value.p;
699 else if(b == sizeof(buffer)-2 || !ch)
702 if(ch) buffer[b] = 0;
715 else if(!strcmp(type.name, "bool"))
722 else if(!strcmp(type.name, "SetBool"))
724 if(value.i == SetBool::true)
726 else if(value.i == SetBool::false)
731 else if(type.type == enumClass)
734 WriteNumber(f, type, value, indent);
737 else if(eClass_IsDerived(type, class(Container)))
739 WriteArray(f, type, value.p, indent);
741 else if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || type.type == bitClass)
743 _WriteJSONObject(f, type, value.p, indent);
745 else if(type.type == systemClass)
747 WriteNumber(f, type, value, indent);
752 public bool WriteJSONObject(File f, Class objectType, void * object, int indent)
757 result = _WriteJSONObject(f, objectType, object, indent);
763 static bool _WriteJSONObject(File f, Class objectType, void * object, int indent)
767 const char * string = null;
769 if(objectType._vTbl[__ecereVMethodID_class_OnGetString] != objectType.base._vTbl[__ecereVMethodID_class_OnGetString])
773 string = ((const char *(*)())(void *)objectType._vTbl[__ecereVMethodID_class_OnGetString])(objectType, object, buffer, null, null);
777 // TOCHECK: ProjectNode.ec why do we add quotes in OnGetString there?
778 if(string[0] == '\"')
796 for(prop = objectType.membersAndProperties.first; prop; prop = prop.next)
798 if(prop.memberAccess != publicAccess || (prop.isProperty && (!prop.Set || !prop.Get))) continue;
801 if(!prop.conversion && (!prop.IsSet || prop.IsSet(object)))
804 Class type = eSystem_FindClass(__thisModule, prop.dataTypeString);
806 type = eSystem_FindClass(__thisModule.application, prop.dataTypeString);
808 PrintLn("warning: Unresolved data type ", (String)prop.dataTypeString);
811 // TOFIX: How to swiftly handle classes with base data type?
812 if(type == class(double) || !strcmp(type.dataTypeString, "double"))
814 value.d = ((double (*)(void *))(void *)prop.Get)(object);
816 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
818 value.f = ((float (*)(void *))(void *)prop.Get)(object);
820 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
821 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
823 value.ui64 = ((uint64 (*)(void *))(void *)prop.Get)(object);
825 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
826 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
828 value.i = ((int (*)(void *))(void *)prop.Get)(object);
830 else if(type.typeSize == sizeof(short int) || !strcmp(type.dataTypeString, "short") ||
831 !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
832 !strcmp(type.dataTypeString, "int16"))
834 value.s = ((short (*)(void *))(void *)prop.Get)(object);
836 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
837 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
839 value.c = ((char (*)(void *))(void *)prop.Get)(object);
843 value.p = ((void *(*)(void *))(void *)prop.Get)(object);
846 if(!isFirst) f.Puts(",\n");
847 for(c = 0; c<indent; c++) f.Puts(" ");
850 f.Putc((char)toupper(prop.name[0]));
853 WriteValue(f, type, value, indent);
860 DataMember member = (DataMember)prop;
862 Class type = eSystem_FindClass(__thisModule, member.dataTypeString);
864 type = eSystem_FindClass(__thisModule.application, member.dataTypeString);
868 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass || !strcmp(type.name, "String"))
870 if(type.type == structClass)
871 value.p = (void *)((byte *)object + member._class.offset + member.offset);
873 value.p = *(void **)((byte *)object + member._class.offset + member.offset);
877 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
879 value.d = *(double *)((byte *)object + member._class.offset + member.offset);
881 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
883 value.f = *(float *)((byte *)object + member._class.offset + member.offset);
885 else if(type.typeSize == sizeof(int64) || !strcmp(type.dataTypeString, "int64") ||
886 !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
888 value.ui64 = *(uint64 *)((byte *)object + member._class.offset + member.offset);
890 else if(type.typeSize == sizeof(int) || !strcmp(type.dataTypeString, "int") ||
891 !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
893 value.i = *(int *)((byte *)object + member._class.offset + member.offset);
894 if(!strcmp(type.name, "bool") || type.type == enumClass)
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 value.s = *(short *)((byte *)object + member._class.offset + member.offset);
904 else if(type.typeSize == sizeof(byte) || !strcmp(type.dataTypeString, "char") ||
905 !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
907 value.c = *(char *)((byte *)object + member._class.offset + member.offset);
911 value.i = *(int *)((byte *)object + member._class.offset + member.offset);
914 if(!isFirst) f.Puts(",\n");
915 for(c = 0; c<indent; c++) f.Puts(" ");
918 f.Putc((char)toupper(member.name[0]));
919 f.Puts(member.name+1);
921 WriteValue(f, type, value, indent);
929 for(c = 0; c<indent; c++) f.Puts(" "); f.Puts("}");