ecere/DataTypes: missing channel argument in OnUnserialize
[sdk] / ecere / src / com / dataTypes.ec
1 namespace com;
2
3 #if defined(ECERE_BOOTSTRAP)
4 #define dllexport
5 #endif
6
7 import "instance"
8
9 default extern Platform runtimePlatform;
10
11 // Limit Definitions
12 public define MAXBYTE = 0xff;
13 public define MAXWORD = 0xffff;
14 public define MININT = ((int)0x80000000);
15 public define MAXINT = ((int)0x7fffffff);
16 public define MININT64 = ((int64)0x8000000000000000LL);
17 public define MAXINT64 = ((int64)0x7fffffffffffffffLL);
18 public define MAXDWORD = 0xffffffff;
19 public define MAXQWORD = 0xffffffffffffffffLL;
20 public define MINFLOAT = ((float)1.17549435082228750e-38);
21 public define MAXFLOAT = ((float)3.40282346638528860e+38);
22 public define MINDOUBLE = ((double) 2.2250738585072014e-308);
23 public define MAXDOUBLE = ((double) 1.7976931348623158e+308);
24
25 public define FORMAT64HEXLL  = (GetRuntimePlatform() == win32) ? "0x%I64XLL" : "0x%llXLL";
26 public define FORMAT64HEX    = (GetRuntimePlatform() == win32) ? "0x%I64X" : "0x%llX";
27 public define FORMAT64DLL    = (GetRuntimePlatform() == win32) ? "%I64dLL" : "%lldLL";
28 public define FORMAT64D      = (GetRuntimePlatform() == win32) ? "%I64d" : "%lld";
29 public define FORMAT64U      = (GetRuntimePlatform() == win32) ? "%I64u" : "%llu";
30
31 #define PUTXWORD(b, w) \
32    (b)[0] = (byte)(((w) >> 8) & 0xFF); \
33    (b)[1] = (byte)(((w)     ) & 0xFF);
34
35 #define GETXWORD(b) (uint16)(((b)[0] << 8) | (b)[1])
36
37 #define PUTXDWORD(b, d) \
38    (b)[0] = (byte)(((d) >> 24) & 0xFF); \
39    (b)[1] = (byte)(((d) >> 16) & 0xFF); \
40    (b)[2] = (byte)(((d) >> 8)  & 0xFF); \
41    (b)[3] = (byte)( (d)        & 0xFF);
42
43 #define GETXDWORD(b) (uint32)(((b)[0] << 24) | ((b)[1] << 16) | ((b)[2] << 8) | (b)[3])
44
45 #define PUTXQWORD(b, d) \
46    (b)[0] = (byte)(((d) >> 56) & 0xFF); \
47    (b)[1] = (byte)(((d) >> 48) & 0xFF); \
48    (b)[2] = (byte)(((d) >> 40) & 0xFF); \
49    (b)[3] = (byte)(((d) >> 32) & 0xFF); \
50    (b)[4] = (byte)(((d) >> 24) & 0xFF); \
51    (b)[5] = (byte)(((d) >> 16) & 0xFF); \
52    (b)[6] = (byte)(((d) >> 8)  & 0xFF); \
53    (b)[7] = (byte)( (d)        & 0xFF);
54
55 #define GETXQWORD(b) (uint64)(((uint64)(b)[0] << 56) | ((uint64)(b)[1] << 48) | ((uint64)(b)[2] << 40) | ((uint64)(b)[3] << 32) | ((uint64)(b)[4] << 24) | ((b)[5] << 16) | ((b)[6] << 8) | (b)[7])
56
57 static void UnusedFunction()
58 {
59    int a;
60    a.OnGetString(0,0,0);
61    a.OnFree();
62    a.OnCopy(null);
63    a.OnCompare(null);
64    a.OnSaveEdit(null,0);
65    a.OnEdit(null,null,0,0,0,0,0);
66    a.OnDisplay(null,0,0,0,0,null,null);
67    a.OnGetDataFromString(null);
68 }
69
70 default:
71 extern int __ecereVMethodID_class_OnGetString;
72 extern int __ecereVMethodID_class_OnGetDataFromString;
73 extern int __ecereVMethodID_class_OnCompare;
74 extern int __ecereVMethodID_class_OnSerialize;
75 extern int __ecereVMethodID_class_OnUnserialize;
76 extern int __ecereVMethodID_class_OnCopy;
77 public:
78
79 // TOFIX: Declaration ordering
80 dllexport void eSystem_Delete(void * memory);
81
82 public class IOChannel
83 {
84 public:
85    virtual uint WriteData(byte * data, uint numBytes);
86    virtual uint ReadData(byte * data, uint numBytes);
87
88    dllexport void Serialize(typed_object data)
89    {
90       data.OnSerialize(this);
91    }
92
93    dllexport void Unserialize(typed_object & data)
94    {
95       data.OnUnserialize(this);
96    }
97
98    dllexport void Put(typed_object data)
99    {
100       data.OnSerialize(this);
101    }
102
103    dllexport void Get(typed_object & data)
104    {
105       data.OnUnserialize(this);
106    }
107 };
108
109 public class SerialBuffer : IOChannel
110 {
111 public:
112    byte * _buffer;
113    uint count;
114    uint _size;
115    uint pos;
116
117    uint WriteData(byte * bytes, uint numBytes)
118    {
119       if(this != null)
120       {
121          if(count + numBytes > _size)
122          {
123             _size = count + numBytes;
124             _size += _size/2;
125             _buffer = renew _buffer byte[_size];
126          }
127          memcpy(_buffer + count, bytes, numBytes);
128          count += numBytes;
129          return numBytes;
130       }
131       return 0;
132    }
133
134    uint ReadData(byte * bytes, uint numBytes)
135    {
136       if(this != null)
137       {
138          int read = Min(numBytes, count - pos);
139          memcpy(bytes, _buffer + pos, read);
140          pos += read;
141          return read;
142       }
143       return 0;
144    }
145
146    ~SerialBuffer()
147    {
148       Free();
149    }
150
151    dllexport void Free()
152    {
153       if(this)
154       {
155          delete _buffer;
156          count = 0;
157          _size = 0;
158          pos = 0;
159       }
160    }
161
162    // TODO: THIS IS VERY BAD!
163    property byte * buffer
164    {
165       get { return _buffer + pos; }
166       set { _buffer = value; }
167    }
168
169    property uint size
170    {
171       get { return count - pos; }
172       set { count = value; }
173    }
174 };
175
176 /*static */char * Enum_OnGetString(Class _class, int * data, char * tempString, void * fieldData, bool * needClass)
177 {
178    EnumClassData enumeration = (EnumClassData)_class.data;
179    NamedLink item;
180    for(item = enumeration.values.first; item; item = item.next)
181       if((int)item.data == *data)
182          break;
183    if(item)
184    {
185       strcpy(tempString, item.name);
186       if(!needClass || !*needClass)
187          tempString[0] = (char)toupper(tempString[0]);
188       return tempString;
189       //return item.name;
190    }
191    else
192       return null;
193 }
194
195 static bool Enum_OnGetDataFromString(Class _class, int * data, char * string)
196 {
197    EnumClassData enumeration = (EnumClassData)_class.data;
198    NamedLink item;
199    for(item = enumeration.values.first; item; item = item.next)
200    {
201       if(item.name && !strcmpi(item.name, string))
202          break;
203    }
204    if(item)
205    {
206       *data = (int)item.data;
207       return true;
208    }
209    else
210       return Integer_OnGetDataFromString(_class, data, string);
211    return false;
212 }
213
214 static void OnFree(Class _class, void * data)
215 {
216    if(_class.templateClass) _class = _class.templateClass;
217    if(_class.type == normalClass)
218    {
219       // eInstance_Delete(data);
220       eInstance_DecRef(data);
221    }
222    else if(_class.type == noHeadClass && data)
223    {
224       while(_class && _class.type == noHeadClass)
225       {
226          if(_class.Destructor)
227             _class.Destructor(data);
228          _class = _class.base;
229       }
230       delete data;
231    }
232 }
233
234 static int DataMember_OnCompare(DataMember parentMember, void * data1, void * data2)
235 {
236    DataMember member;
237    Module module = parentMember._class.module;
238    for(member = parentMember.members.first; member; member = member.next)
239    {
240       int memberResult = 0;
241       if(member.type == normalMember)
242       {
243          Class memberType = member.dataTypeClass;
244
245          if(!memberType)
246             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
247          if(!memberType)
248             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
249
250          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
251          {
252             memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, 
253                (byte *)data1 + member.offset, 
254                (byte *)data2 + member.offset);
255             if(memberResult)
256                return memberResult;
257          }
258          else
259          {
260             DataValue value1, value2;
261             value1.i = *(int *)((byte *)data1 + member.offset);
262             value2.i = *(int *)((byte *)data2 + member.offset);
263             memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, &value1, &value2);
264             if(memberResult)
265                return memberResult;
266          }
267       }
268       else
269       {
270          memberResult = DataMember_OnCompare(member, 
271             (byte *)data1 + member.offset, 
272             (byte *)data2 + member.offset);
273          if(memberResult)
274             return memberResult;
275       }
276    }
277    return 0;
278 }
279
280 static int OnCompare(Class _class, void * data1, void * data2)
281 {
282    Module module = _class.module;
283    if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
284    {
285       if(data1 && data2)
286       {
287          // NOTE: Comparing from top class down here... might want to reverse it
288          for(; _class && _class.type != systemClass; _class = _class.base)
289          {
290             DataMember member;
291
292             // TESTING THIS HERE...
293             if(_class.noExpansion)
294             {
295                if(data1 > data2) return 1;
296                else if(data1 < data2) return -1;
297                else
298                   return 0;
299             }
300
301             for(member = _class.membersAndProperties.first; member; member = member.next)
302             {
303                int memberResult = 0;
304                if(member.isProperty || member.type == normalMember)
305                {
306                   Class memberType = member.dataTypeClass;
307                         
308                   if(!memberType)
309                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
310                   /*
311                   if(!memberType)
312                      memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
313                   */
314                   if(memberType)
315                   {
316                      if(member.isProperty)
317                      {
318                         Property prop = (Property)member;
319                         if(!prop.conversion && prop.Get && prop.Set)
320                         {
321                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
322                            {
323                               if(!strcmp(memberType.dataTypeString, "char *"))
324                               {
325                                  String a = ((String(*)())(void *)prop.Get)(data1);
326                                  String b = ((String(*)())(void *)prop.Get)(data2);
327                                  memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, a, b);
328                               }
329                            }
330                            else
331                            {
332                               DataValue value1, value2;
333                               if(!strcmp(memberType.dataTypeString, "float"))
334                               {
335                                  value1.f = ((float(*)())(void *)prop.Get)(data1);
336                                  value2.f = ((float(*)())(void *)prop.Get)(data2);
337                               }
338                               else
339                               {
340                                  value1.i = prop.Get(data1);
341                                  value2.i = prop.Get(data2);
342                               }
343                               memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, &value1, &value2);
344                            }
345                         }
346                      }
347                      else
348                      {
349                         if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
350                         {
351                            if(memberType.type == normalClass || memberType.type == noHeadClass)
352                            {
353                               // TESTING THIS!
354                               memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, 
355                                  *(void **)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)), 
356                                  *(void **)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)));
357                            }
358                            else
359                            {
360                               memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, 
361                                  (byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), 
362                                  (byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
363                            }
364                         }
365                         else
366                         {
367                            DataValue value1, value2;
368                            if(memberType.typeSize == 8)
369                            {
370                               value1.ui64 = *(uint64 *)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
371                               value2.ui64 = *(uint64 *)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
372                            }
373                            else
374                            {
375                               value1.i = *(int *)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
376                               value2.i = *(int *)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
377                            }
378                            memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, &value1, &value2);
379                         }
380                      }
381                   }
382                   else
383                   {
384                      // printf("Unknown type\n");
385                   }
386                }
387                else
388                {
389                   memberResult = DataMember_OnCompare(member, 
390                      (byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), 
391                      (byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
392                }
393                if(memberResult)
394                   return memberResult;
395             }
396          }
397       }
398       else if(!data1 && data2)
399          return 1;
400       else if(data1 && !data2)
401          return -1;
402    }
403    else if(_class.type == unitClass)
404    {
405       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
406       return dataType._vTbl[__ecereVMethodID_class_OnCompare](dataType, data1, data2);
407    }
408    else
409    {
410       int result = 0;
411       if(data1 && data2)
412       {
413          if(*(void **)data1 > *(void **)data2)
414             result = 1;
415          else if(*(void **)data1 < *(void **)data2)
416             result = -1;
417       }
418       else if(!data1 && data2)
419          return 1;
420       else if(data1 && !data2)
421          return -1;
422       return result;
423    }
424    return 0;
425 }
426
427 static char * OnGetString(Class _class, void * data, char * tempString, void * fieldData, bool * needClass)
428 {
429    // WHY DOES _class.module NOT SEEM TO WORK?
430    Module module = _class.templateClass ? _class.templateClass.module : _class.module;
431    if(_class.type == enumClass)
432    {
433       return Enum_OnGetString(_class, data, tempString, fieldData, needClass);
434    }
435    else if(_class.type == unitClass)
436    {
437       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
438       return (char *)dataType._vTbl[__ecereVMethodID_class_OnGetString](dataType, data, tempString, fieldData, needClass);
439    }
440    else
441    {
442       bool atMember = true;
443       bool prev = false;
444       Class mainClass = _class;
445       _class = null;
446       tempString[0] = '\0';
447       if(!data && (mainClass.type == normalClass || mainClass.type == noHeadClass)) return tempString;
448
449       while(_class != mainClass)
450       {
451          DataMember member;
452          Class lastClass = _class;
453
454          for(_class = mainClass; _class.base != lastClass && _class.base.type != systemClass; _class = _class.base);
455
456          for(member = _class.membersAndProperties.first; member; member = member.next)
457          {
458             char memberString[1024];
459             Class memberType = member.dataTypeClass;
460             char * name = member.name;
461                   
462             memberString[0] = 0;
463
464             if(!memberType)
465                memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
466             if(!memberType)
467                memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
468
469             if(member.isProperty)
470             {
471                Property prop = (Property) member;
472
473                if(!prop.conversion && prop.Get && prop.Set && (!prop.IsSet || prop.IsSet(data)))
474                {
475                   if(memberType.type != structClass && (memberType.type != normalClass || !strcmp(memberType.dataTypeString, "char *")) && memberType.type != bitClass && data)
476                   {
477                      DataValue value = { 0 };
478                      if(!strcmp(prop.dataTypeString, "float"))
479                      {
480                         value.f = ((float(*)())(void *)prop.Get)(data);
481                         if(value.f)
482                         {
483                            bool needClass = true;
484                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, &value, memberString, null, &needClass);
485                            if(result && result != memberString)
486                               strcpy(memberString, result);
487                            // TESTING THIS HERE
488                            if(strchr(memberString, '.'))
489                               strcat(memberString, "f");
490                         }
491                      }
492                      else
493                      {
494                         value.i = prop.Get(data);
495                         if(value.i || prop.IsSet)
496                         {
497                            bool needClass = true;
498                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, 
499                               (memberType.type == normalClass) ? value.p : &value, memberString, null, &needClass);
500                            if(result && result != memberString)
501                               strcpy(memberString, result);
502                         }
503                      }
504                   }
505                }
506             }
507             else
508             {
509                if(member.type == normalMember)
510                {
511                   if(memberType.type == structClass || memberType.type == normalClass)
512                   {
513                      char internalMemberString[1024];
514                      byte * memberData = ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
515                      int c;
516                      for(c = 0; c < memberType.structSize; c++)
517                         if(memberData[c])
518                            break;
519                      if(c < memberType.structSize)
520                      {
521                         bool needClass = true;
522                         char * result;
523                         if(memberType.type == normalClass)
524                            result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, *(Instance *)memberData, internalMemberString, null, &needClass);
525                         else
526                            result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, memberData, internalMemberString, null, &needClass);
527                         if(needClass)
528                         {
529                            //strcpy(memberString, memberType.name);
530                            strcat(memberString, "{ ");
531                            if(result) strcat(memberString, result);
532                            strcat(memberString, " }");
533                         }
534                         else if(result)
535                            strcpy(memberString, result);
536                      }
537                   }
538                   //else if(_class /*memberType*/.type != bitClass)
539                   else // if(_class /*memberType*/.type != bitClass)
540                   {
541                      DataValue value = { 0 };
542                      if(_class.type == bitClass)
543                      {
544                         BitMember bitMember = (BitMember) member;
545                         // TODO: Check if base type is 32 or 64 bit
546
547                         //value.ui = (((uint)data & bitMember.mask) >> bitMember.pos);
548                         value.ui64 = ((*(uint*)data & bitMember.mask) >> bitMember.pos);
549                         if(value.ui64)
550                         {
551                            bool needClass = true;
552                            char internalMemberString[1024];
553                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, &value, internalMemberString, null, &needClass);
554
555                            if(needClass && memberType.type != systemClass && memberType.type != enumClass && memberType.type != unitClass)
556                            {
557                               //strcpy(memberString, memberType.name);
558                               strcat(memberString, " { ");
559                               if(result) strcat(memberString, result);
560                               strcat(memberString, " }");
561                            }
562                            else if(result)
563                               strcpy(memberString, result);
564                            /*
565                            if(result && memberString != result)
566                               strcpy(memberString, result);
567                            */
568                         }
569                      }
570                      else if(!memberType.noExpansion)
571                      {
572                         // TOCHECK: Is this still right??
573                         if(memberType.typeSize <= 4)
574                         {
575                            value.i = *(int *)((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
576                            if(value.i)
577                            {
578                               bool needClass = true;
579                               char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, &value, memberString, null, &needClass);
580                               if(result && memberString != result)
581                                  strcpy(memberString, result);
582                            }
583                         }
584                         else
585                         {
586                            bool needClass = true;
587                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)), memberString, null, &needClass);
588                            if(result && memberString != result)
589                               strcpy(memberString, result);
590                         }
591                      }
592                   }
593                   /*else
594                   {
595                      char internalMemberString[1024];
596                      byte * memberData = ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
597                      bool needClass = true;
598                      char * result;
599                      result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, memberData, internalMemberString, null, &needClass);
600                      if(needClass)
601                      {
602                         //strcpy(memberString, memberType.name);
603                         strcat(memberString, "{ ");
604                         if(result) strcat(memberString, result);
605                         strcat(memberString, " }");
606                      }
607                      else if(result)
608                         strcpy(memberString, result);
609                   }*/
610                }
611                // MemberUnion
612                // MemberStruct
613             }
614             // TODO: Fix atID stuff
615             if(memberString[0])
616             {
617                if(prev)
618                   strcat(tempString, ", ");
619                if(!atMember || !strcmp(memberType.name, "bool"))
620                {
621                   strcat(tempString, name);
622                   strcat(tempString, " = ");
623                }
624
625                if(!strcmp(memberType.name, "char *"))
626                {
627                   int len = strlen(tempString);
628                   int c;
629                   strcat(tempString, "\"");
630                   len ++;
631                   for(c = 0; memberString[c]; c++)
632                   {
633                      if(memberString[c] == '\"')
634                      {
635                         strcat(tempString, "\\\"");
636                         len+=2;
637                      }
638                      else if(memberString[c] == '\\')
639                      {
640                         strcat(tempString, "\\\\");
641                         len+=2;
642                      }
643                      else
644                      {
645                         tempString[len++] = memberString[c];
646                         tempString[len] = 0;
647                      }
648                   }                              
649                   strcat(tempString, "\"");
650                }
651                else
652                   strcat(tempString, memberString);
653                atMember = true;
654
655                prev = true;
656             }
657             else if(member && (!member.isProperty || !((Property)member).conversion))
658                atMember = false;
659          }
660       }
661    }
662    return tempString;
663 }
664
665 static bool OnGetDataFromString(Class _class, void ** data, char * string)
666 {
667    bool result;
668    Module module = _class.module;
669    if(_class.type == enumClass)
670       result = Enum_OnGetDataFromString(_class, (int *)data, string);
671    else if(_class.type == unitClass)
672    {
673       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
674       return dataType._vTbl[__ecereVMethodID_class_OnGetDataFromString](dataType, data, string);
675    }
676    else if(!string[0] && _class.type == normalClass)
677    {
678       // result = false;  // Why was this data = null commented?
679       *data = null;
680       return true;
681    }
682    else
683    {
684       int c;
685       char memberName[1024];
686       char memberString[10240];
687       int count = 0;
688       bool quoted = false;
689       int brackets = 0;
690       char ch;
691       bool escape = false;
692       bool gotChar;
693       uint memberOffset;
694       Class curClass = null;
695       DataMember curMember = null;
696       DataMember subMemberStack[256];
697       int subMemberStackPos = 0;
698
699       result = true;
700
701       if(_class.type == noHeadClass || _class.type == normalClass) 
702       {
703          data = *data = eInstance_New(_class);
704          if(_class.type == normalClass) 
705             ((Instance)data)._refCount++;
706       }
707       else if(/*_class.type == noHeadClass || */_class.type == structClass) 
708          memset(data, 0, _class.structSize);
709       // Bit classes cleared outside?
710
711       memberName[0] = '\0';
712
713       for(c = 0; string[c] && count < sizeof(memberString); )
714       {
715          bool found = false;
716          DataMember thisMember = null;
717
718          brackets = 0;
719          gotChar = false;
720          for(; (ch = string[c]) && count < sizeof(memberString); c++)
721          {
722             if(ch == '\"' && !escape)
723             {
724                quoted ^= true;
725             }
726             else if(quoted)
727             {
728                if(!escape && ch == '\\')
729                {
730                   escape = true;
731                }
732                else
733                {
734                   memberString[count++] = ch;
735                   escape = false;
736                }
737             }
738             // TOFIX: OnGetDataFromString is far from ready as a generic object notation reader...
739             // It has mostly been tested/used for entering data in the IDE's property sheet, as well as for parsing code in the Code Editor
740             // Is it used by the compiler?
741             else if(ch == ' ') // || ch == '\n' || ch == '\t' || ch == '\r')
742             {
743                if(gotChar) 
744                   memberString[count++] = ch;
745             }
746             else if(ch == ',')
747             {
748                if(brackets)
749                {
750                   memberString[count++] = ch;
751                }
752                else
753                {
754                   c++;
755                   break;
756                }
757             }
758             else if(ch == '{')
759             {
760                // If bracket is not initialization
761                if(gotChar && !brackets) 
762                {
763                   count = 0;
764                   gotChar = false;
765                }
766
767                if(brackets)
768                {
769                   memberString[count++] = ch;
770                   gotChar = true;
771                }
772                brackets++;
773             }
774             else if(ch == '}')
775             {
776                brackets--;
777                if(brackets)
778                {
779                   gotChar = true;
780                   memberString[count++] = ch;
781                }
782             }
783             else if(ch == '=')
784             {
785                if(brackets)
786                {
787                   memberString[count++] = ch;
788                }
789                else
790                {
791                   memberString[count] = '\0';
792                   //TrimLSpaces(memberString, memberName);
793                   //TrimRSpaces(memberName, memberString);
794                   //strcpy(memberName, memberString);
795             
796                   TrimRSpaces(memberString, memberName);
797                   count = 0;
798                   gotChar = false;
799                }
800             }
801             else
802             {
803                memberString[count++] = ch;
804                gotChar = true;
805             }
806          }
807
808          memberString[count] = '\0';
809          TrimRSpaces(memberString, memberString);
810
811          if(memberName[0])
812          {
813             DataMember _subMemberStack[256];
814             int _subMemberStackPos = 0;
815
816             thisMember = eClass_FindDataMemberAndOffset(_class, memberName, &memberOffset, _class.module, _subMemberStack, &_subMemberStackPos);
817
818             if(!thisMember)
819                thisMember = (DataMember)eClass_FindProperty(_class, memberName, _class.module);
820             if(thisMember)
821             {
822                if(thisMember.memberAccess == publicAccess)
823                {
824                   curMember = thisMember;
825                   curClass = thisMember._class;
826                   memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
827                   subMemberStackPos = _subMemberStackPos;
828                }
829                found = true;
830             }
831          }
832          else
833          {
834             eClass_FindNextMember(_class, &curClass, (DataMember *)&curMember, subMemberStack, &subMemberStackPos);
835             thisMember = curMember;
836             if(thisMember)
837             {
838                found = true;
839                eClass_FindDataMemberAndOffset(_class, thisMember.name, &memberOffset, _class.module, null, null);
840             }
841          }
842          if(found)
843          {
844             Class memberType = thisMember.dataTypeClass;
845             
846             if(!memberType)
847                memberType = thisMember.dataTypeClass = eSystem_FindClass(module, thisMember.dataTypeString);
848             if(!memberType)
849                memberType = thisMember.dataTypeClass = eSystem_FindClass(module, "int");
850             if(memberType.type == structClass)
851             {
852                if(thisMember)
853                {
854                   if(!memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString](memberType, 
855                      (byte *)data + (((thisMember._class.type == normalClass) ? thisMember._class.offset : 0) + memberOffset), memberString))
856                      result = false;
857                }
858             }
859             else
860             {
861                DataValue value = { 0 };
862                // Patch for hotKey crash ( #556 )
863                // Key has a member KeyCode, which inherits from Key
864                // We don't want KeyCode to use its base class OnGetDataFromString
865                if(memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString] == _class._vTbl[__ecereVMethodID_class_OnGetDataFromString])
866                {
867                   if(!OnGetDataFromString(memberType, &value, memberString))
868                      result = false;
869                }
870                else if(!memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString](memberType, &value, memberString))
871                   result = false;
872                if(thisMember && !thisMember.isProperty)
873                {
874                   if(_class.type == bitClass)
875                   {
876                      BitMember bitMember = (BitMember) thisMember;
877                      // TODO: Check if bit _class is 32 or 64 bit
878                      *(uint *)data = (uint32)(((*(uint *)data & ~bitMember.mask)) | ((value.ui64<<bitMember.pos)&bitMember.mask));
879                   }
880                   else
881                      *(int *)((byte *)data + (((thisMember._class.type == normalClass) ? thisMember._class.offset : 0) + thisMember.offset)) = value.i;
882                }
883                else if(thisMember.isProperty && ((Property)thisMember).Set)
884                   ((Property)thisMember).Set(data, value.i);
885             }
886          }
887          else
888             result = false;
889             
890          count = 0;
891          memberName[0] = '\0';
892       }
893    }
894    return result;
895 }
896
897 static void OnCopy(Class _class, void ** data, void * newData)
898 {
899    // TO IMPROVE: Inherit from Unit class for better performance?
900    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
901    {
902       Class dataType = eSystem_FindClass(_class.module, _class.dataTypeString);
903       if(dataType)
904          dataType._vTbl[__ecereVMethodID_class_OnCopy](dataType, data, newData);
905    }
906    else if(_class.type != structClass && _class.type != systemClass)
907    {
908       *data = newData;
909    }
910    // Here we have either a structClass or a systemClass
911    else if(newData)
912       memcpy(data, newData, _class.typeSize);
913    else
914       memset(data, 0, _class.typeSize);
915 }
916
917 static int DataMember_OnSerialize(DataMember parentMember, void * data, IOChannel channel)
918 {
919    DataMember member;
920    Module module = parentMember._class.module;
921    for(member = parentMember.members.first; member; member = member.next)
922    {
923       if(member.type == normalMember)
924       {
925          Class memberType = member.dataTypeClass;
926
927          if(!memberType)
928             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
929          if(!memberType)
930             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
931
932          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
933          {
934             memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, (byte *)data + member.offset, channel);
935          }
936          else
937          {
938             DataValue value;
939             value.i = *(int *)((byte *)data + member.offset);
940             memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, &value);
941          }
942       }
943       else
944       {
945          DataMember_OnSerialize(member, (byte *)data + member.offset, channel);
946       }
947    }
948    return 0;
949 }
950
951 static void OnSerialize(Class _class, void * data, IOChannel channel)
952 {
953    Module module = _class.module;
954    // TO IMPROVE: Inherit from Unit class for better performance?
955    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
956    {
957       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
958       if(dataType)
959          dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, data, channel);
960    }
961    else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
962    {
963       //if(data)
964       {
965          Class lastClass = null;
966          while(lastClass != _class)
967          {
968             DataMember member;
969             for(; _class && (!_class.base || _class.base.type != systemClass) && _class != lastClass; _class = _class.base);
970             lastClass = _class;
971
972             for(member = _class.membersAndProperties.first; member; member = member.next)
973             {
974                if(member.isProperty || member.type == normalMember)
975                {
976                   Class memberType = member.dataTypeClass;
977                         
978                   if(!memberType)
979                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
980                   if(memberType)
981                   {
982                      if(member.isProperty)
983                      {
984                         /*Property prop = (Property)member;
985                         if(!prop.conversion && prop.Get && prop.Set)
986                         {
987                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
988                            {
989
990                            }
991                            else
992                            {
993                               DataValue value;
994                               if(!strcmp(memberType.dataTypeString, "float"))
995                               {
996                                  value.f = ((float(*)())(void *)prop.Get)(data);
997                               }
998                               else
999                               {
1000                                  value.i = prop.Get(data);
1001                               }
1002                               memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, &value, channel);
1003                            }
1004                         }*/
1005                      }
1006                      else
1007                      {
1008                         if(!strcmp(memberType.name, "String") || memberType.type == normalClass || memberType.type == noHeadClass)
1009                         {
1010                            memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, data ? (*(void **)((byte *)data + member._class.offset + member.offset)) : null, channel);
1011                         }
1012                         else
1013                            memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, data ? (((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset))) : null, channel);
1014                      }
1015                   }
1016                   else
1017                   {
1018                      // printf("Unknown type\n");
1019                   }
1020                }
1021                else
1022                {
1023                   DataMember_OnSerialize(member, data ? ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)) : null, channel);
1024                }
1025             }
1026          }
1027       }
1028    }
1029 }
1030
1031 static int DataMember_OnUnserialize(DataMember parentMember, void * data, IOChannel channel)
1032 {
1033    DataMember member;
1034    Module module = parentMember._class.module;
1035    for(member = parentMember.members.first; member; member = member.next)
1036    {
1037       if(member.type == normalMember)
1038       {
1039          Class memberType = member.dataTypeClass;
1040
1041          if(!memberType)
1042             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1043          if(!memberType)
1044             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
1045
1046          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1047          {
1048             memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, (byte *)data + member.offset, channel);
1049          }
1050          else
1051          {
1052             DataValue value;
1053             memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, &value, channel);  // channel was missing here?
1054             *(int *)((byte *)data + member.offset) = value.i;
1055          }
1056       }
1057       else
1058       {
1059          DataMember_OnUnserialize(member, (byte *)data + member.offset, channel);
1060       }
1061    }
1062    return 0;
1063 }
1064  
1065 static void OnUnserialize(Class _class, void ** data, IOChannel channel)
1066 {
1067    Module module = _class.module;
1068    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
1069    {
1070       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
1071       if(dataType)
1072          dataType._vTbl[__ecereVMethodID_class_OnUnserialize](dataType, data, channel);
1073    }
1074    else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
1075    {
1076       if(data)
1077       {
1078          Class lastClass = null;
1079          if(_class.type == normalClass || _class.type == noHeadClass)
1080          {
1081             // TOFIX: Seriously!?!?? Fix me!
1082             data = *data = eInstance_New(_class);
1083             if(_class.type == normalClass) 
1084                ((Instance)data)._refCount++;
1085          }
1086          else if(/*_class.type == noHeadClass || */_class.type == structClass) 
1087             memset(data, 0, _class.structSize);
1088
1089          while(lastClass != _class)
1090          {
1091             DataMember member;
1092             for(; _class && (!_class.base || _class.base.type != systemClass) && _class != lastClass; _class = _class.base);
1093             lastClass = _class;
1094
1095             for(member = _class.membersAndProperties.first; member; member = member.next)
1096             {
1097                if(member.isProperty || member.type == normalMember)
1098                {
1099                   Class memberType = member.dataTypeClass;
1100                         
1101                   if(!memberType)
1102                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1103                   if(memberType)
1104                   {
1105                      if(member.isProperty)
1106                      {
1107                         /*Property prop = (Property)member;
1108                         if(!prop.conversion && prop.Get && prop.Set)
1109                         {
1110                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1111                            {
1112
1113                            }
1114                            else
1115                            {
1116                               DataValue value;
1117                               memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, &value, channel);
1118                               prop.Set(data, value.i);
1119                            }
1120                         }*/
1121                      }
1122                      else
1123                         memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, 
1124                            (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1125                   }
1126                   else
1127                   {
1128                      // printf("Unknown type\n");
1129                   }
1130                }
1131                else
1132                {
1133                   DataMember_OnUnserialize(member, (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1134                }
1135             }
1136          }
1137       }
1138    }
1139 }
1140
1141 // Integer
1142 static int Integer_OnCompare(Class _class, int * data1, int * data2)
1143 {
1144    int result = 0;
1145    if(*data1 > *data2)
1146       result = 1;
1147    else if(*data1 < *data2)
1148       result = -1;
1149    return result;
1150 }
1151
1152 /*static */char * Integer_OnGetString(Class _class, int * data, char * string, void * fieldData, bool * needClass)
1153 {
1154    sprintf(string, "%d", *data);
1155    return string;
1156 }
1157
1158 static bool Integer_OnGetDataFromString(Class _class, int * data, char * string)
1159 {
1160    char * end;
1161    int result = strtol(string, &end, 0);
1162
1163    if(end > string)
1164    {
1165       *data = result;
1166       return true;
1167    }
1168    return false;
1169 }
1170
1171 static int UInteger_OnCompare(Class _class, unsigned int * data1, unsigned int * data2)
1172 {
1173    int result = 0;
1174    if(data1 && !data2)
1175       result = 1;
1176    else if(!data1 && data2)
1177       result = -1;
1178    else if(!data1 && !data2)
1179       result = 0;
1180    else if(*data1 > *data2)
1181       result = 1;
1182    else if(*data1 < *data2)
1183       result = -1;
1184    return result;
1185 }
1186
1187 static char * UInteger_OnGetString(Class _class, unsigned int * data, char * string, void * fieldData, bool * needClass)
1188 {
1189    sprintf(string, "%u", *data);
1190    return string;
1191 }
1192
1193 static bool UInteger_OnGetDataFromString(Class _class, unsigned int * data, char * string)
1194 {
1195    char * end;
1196    uint result = strtoul(string, &end, 0);
1197    if(end > string)
1198    {
1199       *data = result;
1200       return true;
1201    }
1202    return false;
1203 }
1204
1205 static int Byte_OnCompare(Class _class, byte * data1, byte * data2)
1206 {
1207    int result = 0;
1208    if(*data1 > *data2)
1209       result = 1;
1210    else if(*data1 < *data2)
1211       result = -1;
1212    return result;
1213 }
1214
1215 static char * Byte_OnGetString(Class _class, byte * data, char * string, void * fieldData, bool * needClass)
1216 {
1217    sprintf(string, "%u", (int)*data);
1218    return string;
1219 }
1220
1221 static char * Char_OnGetString(Class _class, char * data, char * string, void * fieldData, bool * needClass)
1222 {
1223    if(needClass && *needClass)
1224    {
1225       char ch = *data;
1226       if(ch == '\t')      strcpy(string, "'\t'");
1227       else if(ch == '\n') strcpy(string, "'\n'");
1228       else if(ch == '\r') strcpy(string, "'\r'");
1229       else if(ch == '\a') strcpy(string, "'\a'");
1230       else if(ch == '\\') strcpy(string, "'\\'");
1231       else if(ch < 32 || ch >= 127)    sprintf(string, "'\o'", ch);
1232       else sprintf(string, "'%c'", ch);
1233    }
1234    else
1235       sprintf(string, "%c", *data);
1236    return string;
1237 }
1238
1239 static bool Byte_OnGetDataFromString(Class _class, byte * data, char * string)
1240 {
1241    char * end;
1242    byte result = (byte)strtoul(string, &end, 0);
1243    if(end > string)
1244    {
1245       *data = result;
1246       return true;
1247    }
1248    return false;
1249 }
1250
1251 static char * Int64_OnGetString(Class _class, int64 * data, char * string, void * fieldData, bool * needClass)
1252 {
1253    sprintf(string, FORMAT64D, *data);
1254    return string;
1255 }
1256
1257 static char * UInt64_OnGetString(Class _class, uint64 * data, char * string, void * fieldData, bool * needClass)
1258 {
1259    sprintf(string, FORMAT64U, *data);
1260    return string;
1261 }
1262
1263 /*static */void Byte_OnSerialize(Class _class, byte * data, IOChannel channel)
1264 {
1265    channel.WriteData(data, 1);
1266 }
1267
1268 /*static */void Byte_OnUnserialize(Class _class, byte * data, IOChannel channel)
1269 {
1270    if(channel.ReadData(data, 1) != 1)
1271       *data = 0;
1272 }
1273
1274
1275 /*static */void Int_OnSerialize(Class _class, int * data, IOChannel channel)
1276 {
1277    byte bytes[4];
1278    PUTXDWORD(bytes, * data);
1279    channel.WriteData(bytes, 4);
1280 }
1281
1282 /*static */void Int_OnUnserialize(Class _class, int * data, IOChannel channel)
1283 {
1284    byte bytes[4];
1285    if(channel.ReadData(bytes, 4) == 4)
1286       *data = GETXDWORD(bytes);   
1287    else
1288       *data = 0;
1289 }
1290
1291 /*static */void Int64_OnSerialize(Class _class, int64 * data, IOChannel channel)
1292 {
1293    byte bytes[8];
1294    PUTXQWORD(bytes, * data);
1295    channel.WriteData(bytes, 8);
1296 }
1297
1298 /*static */void Int64_OnUnserialize(Class _class, int64 * data, IOChannel channel)
1299 {
1300    byte bytes[8];
1301    if(channel.ReadData(bytes, 8) == 8)
1302       *data = GETXQWORD(bytes);   
1303    else
1304       *data = 0;
1305 }
1306
1307 /*static */void Word_OnSerialize(Class _class, uint16 * data, IOChannel channel)
1308 {
1309    byte bytes[2];
1310    PUTXWORD(bytes, * data);
1311    channel.WriteData(bytes, 2);
1312 }
1313
1314 /*static */void Word_OnUnserialize(Class _class, uint16 * data, IOChannel channel)
1315 {
1316    byte bytes[2];
1317    if(channel.ReadData(bytes, 2) == 2)
1318       *data = GETXWORD(bytes);   
1319    else
1320       *data = 0;
1321 }
1322
1323 static void RegisterClass_Integer(Module module)
1324 {
1325    Class integerClass = eSystem_RegisterClass(normalClass, "int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1326    integerClass.type = systemClass;
1327    delete integerClass.dataTypeString;
1328    integerClass.dataTypeString = CopyString("int");
1329    integerClass.structSize = 0;
1330    integerClass.typeSize = sizeof(int);
1331    
1332    eClass_AddMethod(integerClass, "OnCompare", null, Integer_OnCompare, publicAccess);
1333    eClass_AddMethod(integerClass, "OnGetString", null, Integer_OnGetString, publicAccess);
1334    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer_OnGetDataFromString, publicAccess);
1335    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1336    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1337
1338    integerClass = eSystem_RegisterClass(normalClass, "int64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1339    integerClass.type = systemClass;
1340    integerClass.structSize = 0;
1341    integerClass.typeSize = sizeof(int64);
1342    delete integerClass.dataTypeString;
1343    integerClass.dataTypeString = CopyString("int64");
1344    eClass_AddMethod(integerClass, "OnGetString", null, Int64_OnGetString, publicAccess);
1345
1346    /*
1347    eClass_AddMethod(integerClass, "OnCompare", null, Integer64_OnCompare, publicAccess);
1348    eClass_AddMethod(integerClass, "OnGetString", null, Integer64_OnGetString, publicAccess);
1349    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer64_OnGetDataFromString, publicAccess);
1350    */
1351    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1352    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1353
1354    integerClass = eSystem_RegisterClass(normalClass, "uint", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1355    integerClass.type = systemClass;
1356    delete integerClass.dataTypeString;
1357    integerClass.dataTypeString = CopyString("unsigned int");
1358    integerClass.structSize = 0;
1359    integerClass.typeSize = sizeof(uint);
1360    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1361    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1362    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1363    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1364    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1365
1366    integerClass = eSystem_RegisterClass(normalClass, "unsigned int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1367    integerClass.type = systemClass;
1368    delete integerClass.dataTypeString;
1369    integerClass.dataTypeString = CopyString("unsigned int");
1370    integerClass.structSize = 0;
1371    integerClass.typeSize = sizeof(uint);
1372
1373    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1374    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1375    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1376    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1377    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1378
1379    integerClass = eSystem_RegisterClass(normalClass, "uint16", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1380    integerClass.type = systemClass;
1381    delete integerClass.dataTypeString;
1382    integerClass.dataTypeString = CopyString("unsigned short");
1383    integerClass.structSize = 0;
1384    integerClass.typeSize = sizeof(uint16);
1385
1386    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1387    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1388
1389    integerClass = eSystem_RegisterClass(normalClass, "short", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1390    integerClass.type = systemClass;
1391    delete integerClass.dataTypeString;
1392    integerClass.dataTypeString = CopyString("short");
1393    integerClass.structSize = 0;
1394    integerClass.typeSize = sizeof(short);
1395
1396    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1397    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1398
1399    /*
1400    integerClass = eSystem_RegisterClass(normalClass, "uint32", null, 0, 0, null, null, module, baseSystemAccess);
1401    integerClass.type = systemClass;
1402    delete integerClass.dataTypeString;
1403    integerClass.dataTypeString = CopyString("uint32");
1404    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1405    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1406    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1407    */
1408    integerClass = eSystem_RegisterClass(normalClass, "uint32", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
1409    integerClass.type = systemClass;
1410    delete integerClass.dataTypeString;
1411    integerClass.dataTypeString = CopyString("unsigned int");
1412    integerClass.structSize = 0;
1413    integerClass.typeSize = sizeof(uint32);
1414
1415    integerClass = eSystem_RegisterClass(normalClass, "uint64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1416    integerClass.type = systemClass;
1417    delete integerClass.dataTypeString;
1418    integerClass.dataTypeString = CopyString("uint64");
1419    integerClass.structSize = 0;
1420    integerClass.typeSize = sizeof(uint64);
1421    eClass_AddMethod(integerClass, "OnGetString", null, UInt64_OnGetString, publicAccess);
1422    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1423    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1424
1425    integerClass = eSystem_RegisterClass(normalClass, "byte", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1426    integerClass.type = systemClass;
1427    delete integerClass.dataTypeString;
1428    integerClass.dataTypeString = CopyString("unsigned char");
1429    integerClass.structSize = 0;
1430    integerClass.typeSize = sizeof(byte);
1431    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1432    eClass_AddMethod(integerClass, "OnGetString", null, Byte_OnGetString, publicAccess);
1433    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1434    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1435    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1436
1437    integerClass = eSystem_RegisterClass(normalClass, "char", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1438    integerClass.type = systemClass;
1439    delete integerClass.dataTypeString;
1440    integerClass.dataTypeString = CopyString("char");
1441    integerClass.structSize = 0;
1442    integerClass.typeSize = sizeof(char);
1443    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1444    eClass_AddMethod(integerClass, "OnGetString", null, Char_OnGetString, publicAccess);
1445    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1446    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1447    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1448 }
1449
1450 // Float
1451 static int Float_OnCompare(Class _class, float * data1, float * data2)
1452 {
1453    int result = 0;
1454    if(*data1 > *data2)
1455       result = 1;
1456    else if(*data1 < *data2)
1457       result = -1;
1458    return result;
1459 }
1460
1461 static char * Float_OnGetString(Class _class, float * data, char * string, void * fieldData, bool * needClass)
1462 {
1463    int c;
1464    int last = 0;
1465    int numDigits = 7, num = 1;
1466    char format[10];
1467    while(numDigits && num < *data) numDigits--, num *= 10;
1468    sprintf(format, "%%.%df", numDigits);
1469
1470    //sprintf(string, "%f", *data);
1471    sprintf(string, format, *data);
1472
1473    c = strlen(string)-1;
1474    for( ; c >= 0; c--)
1475    {
1476       if(string[c] != '0') 
1477          last = Max(last, c);
1478       if(string[c] == '.')
1479       {
1480          if(last == c)
1481             string[c] = 0;
1482          else
1483             string[last+1] = 0;
1484          break;
1485       }
1486    }
1487    return string;
1488 }
1489
1490 static bool Float_OnGetDataFromString(Class _class, float * data, char * string)
1491 {
1492    char * end;
1493    float result = (float)strtod(string, &end);
1494    //*data = atof(string);
1495    if(end > string)
1496    {
1497       *data = result;
1498       return true;
1499    }
1500    return false;
1501 }
1502
1503 static void Float_OnSerialize(Class _class, float * data, IOChannel channel)
1504 {
1505    byte bytes[4];
1506    PUTXDWORD(bytes, * (uint *)data);
1507    channel.WriteData(bytes, 4);
1508 }
1509
1510 static void Float_OnUnserialize(Class _class, float * data, IOChannel channel)
1511 {
1512    byte bytes[4];
1513    if(channel.ReadData(bytes, 4) == 4)
1514       *(uint *)data = GETXDWORD(bytes);   
1515    else
1516       *data = 0;
1517 }
1518
1519 static void RegisterClass_Float(Module module)
1520 {
1521    Class floatClass = eSystem_RegisterClass(normalClass, "float", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1522    floatClass.type = systemClass;
1523    delete floatClass.dataTypeString;
1524    floatClass.dataTypeString = CopyString("float");
1525    floatClass.structSize = 0;
1526    floatClass.typeSize = sizeof(float);
1527    eClass_AddMethod(floatClass, "OnCompare", null, Float_OnCompare, publicAccess);
1528    eClass_AddMethod(floatClass, "OnGetString", null, Float_OnGetString, publicAccess);
1529    eClass_AddMethod(floatClass, "OnGetDataFromString", null, Float_OnGetDataFromString, publicAccess);
1530    eClass_AddMethod(floatClass, "OnSerialize", null, Float_OnSerialize, publicAccess);
1531    eClass_AddMethod(floatClass, "OnUnserialize", null, Float_OnUnserialize, publicAccess);
1532 }
1533
1534 // Double
1535 static int Double_OnCompare(Class _class, double * data1, double * data2)
1536 {
1537    int result = 0;
1538    if(*data1 > *data2)
1539       result = 1;
1540    else if(*data1 < *data2)
1541       result = -1;
1542    return result;
1543 }
1544
1545 static char * Double_OnGetString(Class _class, double * data, char * string, void * fieldData, bool * needClass)
1546 {
1547    int c;
1548    int last = 0;
1549    //sprintf(string, "%.20f", *data);
1550    if(runtimePlatform == win32)
1551    // sprintf(string, "%.16g", *data);
1552       sprintf(string, "%.15g", *data);
1553    else
1554       sprintf(string, "%.13lf", *data);
1555
1556    c = strlen(string)-1;
1557    for( ; c >= 0; c--)
1558    {
1559       if(string[c] != '0') 
1560          last = Max(last, c);
1561       if(string[c] == '.')
1562       {
1563          if(last == c)
1564             string[c] = 0;
1565          else
1566             string[last+1] = 0;
1567          break;
1568       }
1569    }
1570    return string;
1571 }
1572
1573 static bool Double_OnGetDataFromString(Class _class, double * data, char * string)
1574 {
1575    char * end;
1576    double result;
1577    //*data = (double)strtod(string, null);
1578    result = strtod(string, &end);
1579    if(end > string)
1580    {
1581       *data = result;
1582       return true;
1583    
1584     }
1585     return false;
1586 }
1587
1588 static void Double_OnSerialize(Class _class, double * data, IOChannel channel)
1589 {
1590    byte bytes[8];
1591    PUTXQWORD(bytes, * (uint64 *)data);
1592    channel.WriteData(bytes, 8);
1593 }
1594
1595 static void Double_OnUnserialize(Class _class, double * data, IOChannel channel)
1596 {
1597    byte bytes[8];
1598    if(channel.ReadData(bytes, 8) == 8)
1599       *(uint64 *)data = GETXQWORD(bytes);
1600    else
1601       *data = 0;
1602 }
1603
1604 static void RegisterClass_Double(Module module)
1605 {
1606    Class doubleClass = eSystem_RegisterClass(normalClass, "double", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1607    doubleClass.type = systemClass;
1608    delete doubleClass.dataTypeString;
1609    doubleClass.dataTypeString = CopyString("double");
1610    doubleClass.structSize = 0;
1611    doubleClass.typeSize = sizeof(double);
1612    eClass_AddMethod(doubleClass, "OnCompare", null, Double_OnCompare, publicAccess);
1613    eClass_AddMethod(doubleClass, "OnGetString", null, Double_OnGetString, publicAccess);
1614    eClass_AddMethod(doubleClass, "OnGetDataFromString", null, Double_OnGetDataFromString, publicAccess);
1615    eClass_AddMethod(doubleClass, "OnSerialize", null, Double_OnSerialize, publicAccess);
1616    eClass_AddMethod(doubleClass, "OnUnserialize", null, Double_OnUnserialize, publicAccess);
1617 }
1618
1619 public struct StaticString
1620 {
1621    char string[1];
1622
1623    void OnSerialize(IOChannel channel)
1624    {
1625       int len = this ? strlen(string) : 0;
1626       channel.WriteData(this ? string : "", len+1);
1627    }
1628
1629    void OnUnserialize(IOChannel channel)
1630    {
1631       if(this)
1632       {
1633          int c;
1634          uint size;
1635
1636          for(c = 0; channel.ReadData(&string[c], 1) && string[c]; c++);
1637          string[c++] = '\0';
1638       }
1639    }
1640
1641    int OnCompare(StaticString string2)
1642    {
1643       int result = 0;
1644       if(this && string2)
1645          result = strcmpi(string, string2.string);
1646       else if(!this && string2)
1647          result = -1;   // INVERTED THESE 2 CASES
1648       else if(this && !string2)
1649          result = 1;
1650       return result;
1651    }
1652
1653    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1654    {
1655       return (char *)(this ? string : null); // Cast for memguard
1656    }
1657
1658    void OnFree()
1659    {
1660    }
1661 };
1662
1663 static void String_OnCopy(Class _class, char ** data, char * newData)
1664 {
1665    if(newData)
1666    {
1667       int len = strlen(newData);
1668       if(len)
1669       {
1670          *data = eSystem_New(len+1);
1671          memcpy(*data, newData, len+1);
1672       }
1673       else
1674          *data = null;
1675    }
1676    else
1677       *data = null;
1678 }
1679
1680 static bool String_OnGetDataFromString(Class _class, char ** data, char * newData)
1681 {
1682    if(newData)
1683    {
1684       int len = strlen(newData);
1685       if(len)
1686       {
1687          *data = eSystem_New(len+1);
1688          memcpy(*data, newData, len+1);
1689       }
1690       else
1691          *data = null;
1692    }
1693    return true;
1694 }
1695  
1696 /*static */int String_OnCompare(Class _class, char * string1, char * string2)
1697 {
1698    int result = 0;
1699    if(string1 && string2)
1700       result = strcmpi(string1, string2);
1701    else if(!string1 && string2)
1702       result = 1;
1703    else if(string1 && !string2)
1704       result = -1;
1705    return result;
1706 }
1707
1708 static char * String_OnGetString(Class _class, char * string, char * tempString, void * fieldData, bool * needClass)
1709 {
1710    return string;
1711 }
1712
1713 static void String_OnFree(Class _class, char * string)
1714 {
1715    if(string) 
1716    {
1717       eSystem_Delete(string);
1718    }
1719 }
1720
1721 static void String_OnSerialize(Class _class, char * string, IOChannel channel)
1722 {
1723    int len = string ? strlen(string) : 0;
1724    channel.WriteData(string ? string : "", len+1);
1725 }
1726
1727 static void String_OnUnserialize(Class _class, char * * string, IOChannel channel)
1728 {
1729    if(string)
1730    {
1731       int c;
1732       uint size = 64;
1733
1734       *string = new char[size];
1735       for(c = 0; channel.ReadData(&(*string)[c], 1) && (*string)[c]; c++)
1736       {
1737          if(c == size - 1)
1738          {
1739             size += size / 2;
1740             *string = renew *string char[size];
1741          }
1742       }
1743       (*string)[c++] = '\0';
1744       if(!UTF8Validate(*string))
1745       {
1746          char * newString = new char[c*2];
1747          ISO8859_1toUTF8(*string, newString, c*2);
1748          delete *string;
1749          *string = renew newString char[strlen(newString)+1];
1750       }
1751       else
1752          *string = renew *string char[c];
1753    }
1754 }
1755
1756 static void RegisterClass_String(Module module)
1757 {
1758    Class stringClass = eSystem_RegisterClass(normalClass, "char *", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1759    delete stringClass.dataTypeString;
1760    stringClass.dataTypeString = CopyString("char *");
1761    stringClass.structSize = 0;
1762    
1763    eClass_AddMethod(stringClass, "OnCompare", null, String_OnCompare, publicAccess);
1764    eClass_AddMethod(stringClass, "OnCopy", null, String_OnCopy, publicAccess);
1765    eClass_AddMethod(stringClass, "OnFree", null, String_OnFree, publicAccess);
1766    eClass_AddMethod(stringClass, "OnGetString", null, String_OnGetString, publicAccess);
1767    eClass_AddMethod(stringClass, "OnGetDataFromString", null, String_OnGetDataFromString, publicAccess);
1768    eClass_AddMethod(stringClass, "OnSerialize", null, String_OnSerialize, publicAccess);
1769    eClass_AddMethod(stringClass, "OnUnserialize", null, String_OnUnserialize, publicAccess); 
1770    // eClass_AddProperty(stringClass, null, "Class", null, String_GetClass, publicAccess);
1771
1772    stringClass = eSystem_RegisterClass(normalClass, "String", "char *", 0, 0, null, null, module, baseSystemAccess, publicAccess);
1773    stringClass.structSize = 0;
1774    eClass_AddProperty(stringClass, null, "char *", null, null, publicAccess);
1775 }
1776
1777 void InitializeDataTypes1(Module module)
1778 {
1779    Class baseClass = eSystem_FindClass(module, "class");
1780
1781    eClass_AddVirtualMethod(baseClass, "OnDisplay", "void typed_object::OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)", null, publicAccess);
1782    eClass_AddVirtualMethod(baseClass, "OnCompare", "int typed_object::OnCompare(any_object object)", OnCompare, publicAccess);
1783    eClass_AddVirtualMethod(baseClass, "OnCopy", "void typed_object&::OnCopy(any_object newData)", OnCopy, publicAccess);
1784    eClass_AddVirtualMethod(baseClass, "OnFree", "void typed_object::OnFree(void)", OnFree, publicAccess);
1785    eClass_AddVirtualMethod(baseClass, "OnGetString", "char * typed_object::OnGetString(char * tempString, void * fieldData, bool * needClass)", OnGetString, publicAccess);
1786    eClass_AddVirtualMethod(baseClass, "OnGetDataFromString", "bool typed_object&::OnGetDataFromString(char * string)", OnGetDataFromString, publicAccess);
1787    eClass_AddVirtualMethod(baseClass, "OnEdit", "Window typed_object::OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)", null, publicAccess);
1788    eClass_AddVirtualMethod(baseClass, "OnSerialize", "void typed_object::OnSerialize(IOChannel channel)", OnSerialize, publicAccess);
1789    eClass_AddVirtualMethod(baseClass, "OnUnserialize", "void typed_object&::OnUnserialize(IOChannel channel)", OnUnserialize, publicAccess);
1790    eClass_AddVirtualMethod(baseClass, "OnSaveEdit", "bool typed_object&::OnSaveEdit(Window window, void * object)", null, publicAccess);
1791 }
1792
1793 void InitializeDataTypes(Module module)
1794 {
1795    Class enumClass = eSystem_FindClass(module, "enum");
1796
1797    eClass_AddMethod(enumClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1798    eClass_AddMethod(enumClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1799
1800    // Data Types
1801    RegisterClass_Integer(module);
1802    RegisterClass_Float(module);
1803    RegisterClass_Double(module);
1804    RegisterClass_String(module);
1805 }
1806
1807 #include <stdarg.h>
1808 #include <stdio.h>
1809
1810 public int PrintStdArgsToBuffer(char * buffer, int maxLen, typed_object object, va_list args)
1811 {
1812    int len = 0;
1813    // TOFIX: OnGetString will need a maxLen as well
1814    char * result = object.OnGetString(buffer, null, null);
1815    if(result)
1816    {
1817       len = strlen(result);
1818       if(len >= maxLen) len = maxLen-1;
1819       if(result != buffer)
1820          memcpy(buffer, result, len);
1821    }
1822    while(true)
1823    {
1824       Class _class = null;
1825       void * data = null;
1826
1827       _class = va_arg(args, void *);
1828       if(!_class) break;
1829       data = va_arg(args, void *);
1830       if(data)
1831       {
1832          // TOFIX: OnGetString will need a maxLen as well
1833          result = (char *)_class._vTbl[__ecereVMethodID_class_OnGetString](_class, data, buffer + len, null, null);
1834          if(result)
1835          {
1836             int newLen = strlen(result);
1837             if(len + newLen >= maxLen) newLen = maxLen-1-len;
1838             if(result != buffer + len)
1839                memcpy(buffer + len, result, newLen);
1840             len += newLen;              
1841          }
1842       }
1843    }
1844    buffer[len] = 0;
1845    return len;
1846 }
1847
1848 public int PrintBuf(char * buffer, int maxLen, typed_object object, ...)
1849 {
1850    va_list args;
1851    int len;
1852    va_start(args, object);
1853    len = PrintStdArgsToBuffer(buffer, maxLen, object, args);
1854    va_end(args);
1855    return len;
1856 }
1857
1858 public int PrintLnBuf(char * buffer, int maxLen, typed_object object, ...)
1859 {
1860    va_list args;
1861    int len;
1862    va_start(args, object);
1863    len = PrintStdArgsToBuffer(buffer, maxLen-1, object, args);
1864    buffer[len++] = '\n';
1865    buffer[len] = '\0';
1866    va_end(args);
1867    return len;
1868 }
1869
1870 public char * PrintString(typed_object object, ...)
1871 {
1872    char buffer[4096];
1873    va_list args;
1874    char * string;
1875    int len;
1876    va_start(args, object);
1877    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1878    string = new char[len + 1];
1879    memcpy(string, buffer, len + 1);
1880    va_end(args);
1881    return string;
1882 }
1883
1884 public char * PrintLnString(typed_object object, ...)
1885 {
1886    char buffer[4096];
1887    va_list args;
1888    char * string;
1889    int len;
1890    va_start(args, object);
1891    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1892    string = new char[len + 2];
1893    memcpy(string, buffer, len);
1894    string[len++] = '\n';
1895    string[len] = '\0';
1896    va_end(args);
1897    return string;
1898 }
1899
1900 public void PrintLn(typed_object object, ...)
1901 {
1902    va_list args;
1903    char buffer[4096];
1904    va_start(args, object);
1905    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1906    va_end(args);
1907    puts(buffer);
1908 }
1909
1910 public void Print(typed_object object, ...)
1911 {
1912    va_list args;
1913    char buffer[4096];
1914    va_start(args, object);
1915    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1916    va_end(args);
1917    fputs(buffer, stdout);
1918 }