ecere/com/dataTypes: Fixed IDE crashes caused by recomputing type size for Strings
[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 = 1.17549435082228750e-38f;
21 public define MAXFLOAT = 3.40282346638528860e+38f;
22 public define MINDOUBLE = 2.2250738585072014e-308;
23 public define MAXDOUBLE = 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(0);
63    a.OnCompare(0);
64    a.OnSaveEdit(null,0);
65    a.OnEdit(null,null,0,0,0,20,0);
66    a.OnGetDataFromString(null);
67 }
68
69 #define uint _uint
70 #include <stdarg.h>
71 #include <stdio.h>
72 #undef uint
73
74 default:
75 FILE *eC_stdout(void);
76 FILE *eC_stderr(void);
77
78 bool Float_isNan(float n);
79 bool Float_isInf(float n);
80 int Float_signBit(float n);
81 float Float_nan(void);
82 float Float_inf(void);
83
84 bool Double_isNan(double n);
85 bool Double_isInf(double n);
86 int Double_signBit(double n);
87 double Double_nan(void);
88 double Double_inf(void);
89
90 extern int __ecereVMethodID_class_OnGetString;
91 extern int __ecereVMethodID_class_OnGetDataFromString;
92 extern int __ecereVMethodID_class_OnCompare;
93 extern int __ecereVMethodID_class_OnSerialize;
94 extern int __ecereVMethodID_class_OnUnserialize;
95 extern int __ecereVMethodID_class_OnCopy;
96 public:
97
98 #if defined(ECERE_BOOTSTRAP) || defined(ECERE_STATIC)
99 #define dllexport
100 #endif
101
102 // TOFIX: Declaration ordering (Required on gcc 3.4.5)
103 dllexport void eSystem_Delete(void * memory);
104
105 public class IOChannel
106 {
107 public:
108    virtual uint WriteData(byte * data, uint numBytes);
109    virtual uint ReadData(byte * data, uint numBytes);
110
111    dllexport void Serialize(typed_object data)
112    {
113       data.OnSerialize(this);
114    }
115
116    dllexport void Unserialize(typed_object & data)
117    {
118       data.OnUnserialize(this);
119    }
120
121    dllexport void Put(typed_object data)
122    {
123       data.OnSerialize(this);
124    }
125
126    dllexport void Get(typed_object & data)
127    {
128       data.OnUnserialize(this);
129    }
130 };
131
132 public class SerialBuffer : IOChannel
133 {
134 public:
135    byte * _buffer;
136    uint count;
137    uint _size;
138    uint pos;
139
140    uint WriteData(byte * bytes, uint numBytes)
141    {
142       if(this != null)
143       {
144          if(count + numBytes > _size)
145          {
146             _size = count + numBytes;
147             _size += _size/2;
148             _buffer = renew _buffer byte[_size];
149          }
150          memcpy(_buffer + count, bytes, numBytes);
151          count += numBytes;
152          return numBytes;
153       }
154       return 0;
155    }
156
157    uint ReadData(byte * bytes, uint numBytes)
158    {
159       if(this != null)
160       {
161          int read = Min(numBytes, count - pos);
162          memcpy(bytes, _buffer + pos, read);
163          pos += read;
164          return read;
165       }
166       return 0;
167    }
168
169    ~SerialBuffer()
170    {
171       Free();
172    }
173
174    dllexport void Free()
175    {
176       if(this)
177       {
178          delete _buffer;
179          count = 0;
180          _size = 0;
181          pos = 0;
182       }
183    }
184
185    // TODO: THIS IS VERY BAD!
186    property byte * buffer
187    {
188       get { return _buffer + pos; }
189       set { _buffer = value; }
190    }
191
192    property uint size
193    {
194       get { return count - pos; }
195       set { count = value; }
196    }
197 };
198
199 /*static */char * Enum_OnGetString(Class _class, int * data, char * tempString, void * fieldData, bool * needClass)
200 {
201    NamedLink item = null;
202    Class b;
203    for(b = _class; !item && b && b.type == enumClass; b = b.base)
204    {
205       EnumClassData enumeration = (EnumClassData)b.data;
206       for(item = enumeration.values.first; item; item = item.next)
207          if((int)item.data == *data)
208             break;
209    }
210    if(item)
211    {
212       strcpy(tempString, item.name);
213       if(!needClass || !*needClass)
214          tempString[0] = (char)toupper(tempString[0]);
215       return tempString;
216       //return item.name;
217    }
218    else
219       return null;
220 }
221
222 static bool Enum_OnGetDataFromString(Class _class, int * data, char * string)
223 {
224    NamedLink item = null;
225    Class b;
226    for(b = _class; !item && b && b.type == enumClass; b = b.base)
227    {
228       EnumClassData enumeration = (EnumClassData)_class.data;
229       for(item = enumeration.values.first; item; item = item.next)
230       {
231          if(item.name && !strcmpi(item.name, string))
232             break;
233       }
234    }
235    if(item)
236    {
237       *data = (int)item.data;
238       return true;
239    }
240    else
241       return Integer_OnGetDataFromString(_class, data, string);
242    return false;
243 }
244
245 static void OnFree(Class _class, void * data)
246 {
247    if(_class.templateClass) _class = _class.templateClass;
248    if(_class.type == normalClass)
249    {
250       // eInstance_Delete(data);
251       eInstance_DecRef(data);
252    }
253    else if(_class.type == noHeadClass && data)
254    {
255       while(_class && _class.type == noHeadClass)
256       {
257          if(_class.Destructor)
258             _class.Destructor(data);
259          _class = _class.base;
260       }
261       delete data;
262    }
263 }
264
265 static int DataMember_OnCompare(DataMember parentMember, void * data1, void * data2)
266 {
267    DataMember member;
268    Module module = parentMember._class.module;
269    for(member = parentMember.members.first; member; member = member.next)
270    {
271       int memberResult = 0;
272       if(member.type == normalMember)
273       {
274          Class memberType = member.dataTypeClass;
275
276          if(!memberType)
277             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
278          if(!memberType)
279             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
280
281          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
282          {
283             memberResult = ((int (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnCompare])(memberType,
284                (byte *)data1 + member.offset,
285                (byte *)data2 + member.offset);
286             if(memberResult)
287                return memberResult;
288          }
289          else
290          {
291             DataValue value1, value2;
292             value1.i = *(int *)((byte *)data1 + member.offset);
293             value2.i = *(int *)((byte *)data2 + member.offset);
294             memberResult = ((int (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnCompare])(memberType, &value1, &value2);
295             if(memberResult)
296                return memberResult;
297          }
298       }
299       else
300       {
301          memberResult = DataMember_OnCompare(member,
302             (byte *)data1 + member.offset,
303             (byte *)data2 + member.offset);
304          if(memberResult)
305             return memberResult;
306       }
307    }
308    return 0;
309 }
310
311 static int OnCompare(Class _class, void * data1, void * data2)
312 {
313    Module module = _class.module;
314    if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
315    {
316       if(data1 && data2)
317       {
318          // NOTE: Comparing from top class down here... might want to reverse it
319          for(; _class && _class.type != systemClass; _class = _class.base)
320          {
321             DataMember member;
322
323             // TESTING THIS HERE...
324             if(_class.noExpansion)
325             {
326                if(data1 > data2) return 1;
327                else if(data1 < data2) return -1;
328                else
329                   return 0;
330             }
331
332             for(member = _class.membersAndProperties.first; member; member = member.next)
333             {
334                int memberResult = 0;
335                if(member.id < 0) continue;
336                if(member.isProperty || member.type == normalMember)
337                {
338                   Class memberType = member.dataTypeClass;
339
340                   if(!memberType)
341                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
342                   /*
343                   if(!memberType)
344                      memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
345                   */
346                   if(memberType)
347                   {
348                      if(member.isProperty)
349                      {
350                         Property prop = (Property)member;
351                         if(!prop.conversion && prop.Get && prop.Set)
352                         {
353                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
354                            {
355                               if(!strcmp(memberType.dataTypeString, "char *"))
356                               {
357                                  String a = ((String(*)(void *))(void *)prop.Get)(data1);
358                                  String b = ((String(*)(void *))(void *)prop.Get)(data2);
359                                  memberResult = ((int (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnCompare])(memberType, a, b);
360                               }
361                            }
362                            else
363                            {
364                               DataValue value1, value2;
365                               if(!strcmp(memberType.dataTypeString, "float"))
366                               {
367                                  value1.f = ((float(*)(void *))(void *)prop.Get)(data1);
368                                  value2.f = ((float(*)(void *))(void *)prop.Get)(data2);
369                               }
370                               else
371                               {
372                                  value1.i = ((int(*)(void*))(void *)prop.Get)(data1);
373                                  value2.i = ((int(*)(void*))(void *)prop.Get)(data2);
374                               }
375                               memberResult = ((int (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnCompare])(memberType, &value1, &value2);
376                            }
377                         }
378                      }
379                      else
380                      {
381                         if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
382                         {
383                            if(memberType.type == normalClass || memberType.type == noHeadClass)
384                            {
385                               // TESTING THIS!
386                               memberResult = ((int (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnCompare])(memberType,
387                                  *(void **)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)),
388                                  *(void **)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)));
389                            }
390                            else
391                            {
392                               memberResult = ((int (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnCompare])(memberType,
393                                  (byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset),
394                                  (byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
395                            }
396                         }
397                         else
398                         {
399                            DataValue value1, value2;
400                            if(memberType.typeSize == 8)
401                            {
402                               value1.ui64 = *(uint64 *)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
403                               value2.ui64 = *(uint64 *)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
404                            }
405                            else
406                            {
407                               value1.i = *(int *)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
408                               value2.i = *(int *)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
409                            }
410                            memberResult = ((int (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnCompare])(memberType, &value1, &value2);
411                         }
412                      }
413                   }
414                   else
415                   {
416                      // printf("Unknown type\n");
417                   }
418                }
419                else
420                {
421                   memberResult = DataMember_OnCompare(member,
422                      (byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset),
423                      (byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
424                }
425                if(memberResult)
426                   return memberResult;
427             }
428          }
429       }
430       else if(!data1 && data2)
431          return 1;
432       else if(data1 && !data2)
433          return -1;
434    }
435    else if(_class.type == unitClass)
436    {
437       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
438       return ((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, data1, data2);
439    }
440    else
441    {
442       int result = 0;
443       if(data1 && data2)
444       {
445          if(_class.typeSize == 8)
446          {
447             if(*(uint64 *)data1 > *(uint64 *)data2)
448                result = 1;
449             else if(*(uint64 *)data1 < *(uint64 *)data2)
450                result = -1;
451          }
452          else
453          {
454             if(*(uint *)data1 > *(uint *)data2)
455                result = 1;
456             else if(*(uint *)data1 < *(uint *)data2)
457                result = -1;
458          }
459       }
460       else if(!data1 && data2)
461          return 1;
462       else if(data1 && !data2)
463          return -1;
464       return result;
465    }
466    return 0;
467 }
468
469 static char * OnGetString(Class _class, void * data, char * tempString, void * fieldData, bool * needClass)
470 {
471    // WHY DOES _class.module NOT SEEM TO WORK?
472    Module module = _class.templateClass ? _class.templateClass.module : _class.module;
473    if(_class.type == normalClass && _class.base && !_class.base.base)
474    {
475       if(sizeof(uintsize) == 8)
476          return UInt64Hex_OnGetString(_class, (void *)&data, tempString, fieldData, needClass);
477       else
478          return UIntegerHex_OnGetString(_class, (void *)&data, tempString, fieldData, needClass);
479    }
480    else if(_class.type == enumClass)
481    {
482       return Enum_OnGetString(_class, data, tempString, fieldData, needClass);
483    }
484    else if(_class.type == unitClass)
485    {
486       Class dataType;
487       Property prop;
488       for(prop = _class.conversions.first; prop; prop = prop.next)
489       {
490          bool refProp = false;
491          Class c;
492          if(!strcmp(prop.name, _class.base.fullName))
493             refProp = true;
494          else if( (c = eSystem_FindClass(_class.module, prop.name) ) )
495          {
496             Property p;
497             for(p = c.conversions.first; p; p = p.next)
498             {
499                if(!strcmp(p.name, _class.base.fullName) && !p.Set && !p.Get)
500                {
501                   refProp = true;
502                   break;
503                }
504             }
505          }
506          if(refProp)
507          {
508             if(prop.Set && prop.Get)
509             {
510                String dts = _class.base.dataTypeString;
511                if(!strcmp(dts, "double"))
512                {
513                   double d = ((double(*)(double))(void *)prop.Set)(*(double *)data);
514                   return ((char *(*)(void *, void *, char *, void *, bool *))(void *)class(double)._vTbl[__ecereVMethodID_class_OnGetString])(class(double), &d, tempString, fieldData, needClass);
515                }
516                else if(!strcmp(dts, "float"))
517                {
518                   float d = ((float(*)(float))(void *)prop.Set)(*(float *)data);
519                   return ((char *(*)(void *, void *, char *, void *, bool *))(void *)class(float)._vTbl[__ecereVMethodID_class_OnGetString])(class(float), &d, tempString, fieldData, needClass);
520                }
521                else if(!strcmp(dts, "int"))
522                {
523                   int d = ((int(*)(int))(void *)prop.Set)(*(int *)data);
524                   return ((char *(*)(void *, void *, char *, void *, bool *))(void *)class(int)._vTbl[__ecereVMethodID_class_OnGetString])(class(int), &d, tempString, fieldData, needClass);
525                }
526                else if(!strcmp(dts, "int64"))
527                {
528                   int64 d = ((int64(*)(int64))(void *)prop.Set)(*(int64 *)data);
529                   return ((char *(*)(void *, void *, char *, void *, bool *))(void *)class(int64)._vTbl[__ecereVMethodID_class_OnGetString])(class(int64), &d, tempString, fieldData, needClass);
530                }
531             }
532             else
533                break;
534          }
535       }
536       dataType = eSystem_FindClass(module, _class.dataTypeString);
537       return ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, data, tempString, fieldData, needClass);
538    }
539    else
540    {
541       bool atMember = true;
542       bool prev = false;
543       Class mainClass = _class;
544       _class = null;
545       tempString[0] = '\0';
546       if(!data && (mainClass.type == normalClass || mainClass.type == noHeadClass)) return tempString;
547
548       while(_class != mainClass)
549       {
550          DataMember member;
551          Class lastClass = _class;
552
553          for(_class = mainClass; _class.base != lastClass && _class.base.type != systemClass; _class = _class.base);
554
555          for(member = _class.membersAndProperties.first; member; member = member.next)
556          {
557             char memberString[1024];
558             Class memberType = member.dataTypeClass;
559             char * name = member.name;
560             if(member.id < 0) continue;
561
562             memberString[0] = 0;
563
564             if(!memberType)
565                memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
566             if(!memberType)
567                memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
568
569             if(member.isProperty)
570             {
571                Property prop = (Property) member;
572
573                if(!prop.conversion && prop.Get && prop.Set && (!prop.IsSet || prop.IsSet(data)))
574                {
575                   if(memberType.type != structClass && (memberType.type != normalClass || !strcmp(memberType.dataTypeString, "char *")) && memberType.type != bitClass && data)
576                   {
577                      DataValue value = { 0 };
578                      if(!strcmp(prop.dataTypeString, "float"))
579                      {
580                         value.f = ((float(*)(void *))(void *)prop.Get)(data);
581                         if(value.f)
582                         {
583                            bool needClass = true;
584                            char * result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, &value, memberString, null, &needClass);
585                            if(result && result != memberString)
586                               strcpy(memberString, result);
587                            // TESTING THIS HERE
588                            if(strchr(memberString, '.'))
589                               strcat(memberString, "f");
590                         }
591                      }
592                      else if(memberType.type == normalClass || memberType.type == noHeadClass)
593                      {
594                         value.p = ((void *(*)(void *))(void *)prop.Get)(data);
595                         if(value.p || prop.IsSet)
596                         {
597                            bool needClass = true;
598                            char * result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType,
599                               (memberType.type == normalClass) ? value.p : &value, memberString, null, &needClass);
600                            if(result && result != memberString)
601                               strcpy(memberString, result);
602                         }
603                      }
604                      else
605                      {
606                         value.i = ((int(*)(void *))(void *)prop.Get)(data);
607                         if(value.i || prop.IsSet)
608                         {
609                            bool needClass = true;
610                            char * result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, &value, memberString, null, &needClass);
611                            if(result && result != memberString)
612                               strcpy(memberString, result);
613                         }
614                      }
615                   }
616                }
617             }
618             else
619             {
620                if(member.type == normalMember)
621                {
622                   if(memberType.type == structClass || memberType.type == normalClass)
623                   {
624                      char internalMemberString[1024];
625                      byte * memberData = ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
626                      int c;
627                      uint typeSize = (memberType.type == normalClass) ? memberType.typeSize : memberType.structSize;
628                      for(c = 0; c < typeSize; c++)
629                         if(memberData[c])
630                            break;
631                      if(c < typeSize)
632                      {
633                         bool needClass = true;
634                         char * result;
635                         if(memberType.type == normalClass)
636                            result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, *(Instance *)memberData, internalMemberString, null, &needClass);
637                         else
638                            result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, memberData, internalMemberString, null, &needClass);
639                         if(needClass && strcmp(memberType.dataTypeString, "char *"))
640                         {
641                            //strcpy(memberString, memberType.name);
642                            strcat(memberString, "{ ");
643                            if(result) strcat(memberString, result);
644                            strcat(memberString, " }");
645                         }
646                         else if(result)
647                            strcpy(memberString, result);
648                      }
649                   }
650                   //else if(_class /*memberType*/.type != bitClass)
651                   else // if(_class /*memberType*/.type != bitClass)
652                   {
653                      DataValue value = { 0 };
654                      if(_class.type == bitClass)
655                      {
656                         BitMember bitMember = (BitMember) member;
657                         // TODO: Check if base type is 32 or 64 bit
658
659                         //value.ui = (((uint)data & bitMember.mask) >> bitMember.pos);
660                         value.ui64 = ((*(uint*)data & bitMember.mask) >> bitMember.pos);
661                         if(value.ui64)
662                         {
663                            bool needClass = true;
664                            char internalMemberString[1024];
665                            char * result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, &value, internalMemberString, null, &needClass);
666
667                            if(needClass && memberType.type != systemClass && memberType.type != enumClass && memberType.type != unitClass)
668                            {
669                               //strcpy(memberString, memberType.name);
670                               strcat(memberString, " { ");
671                               if(result) strcat(memberString, result);
672                               strcat(memberString, " }");
673                            }
674                            else if(result)
675                               strcpy(memberString, result);
676                            /*
677                            if(result && memberString != result)
678                               strcpy(memberString, result);
679                            */
680                         }
681                      }
682                      else if(!memberType.noExpansion)
683                      {
684                         // TOCHECK: Is this still right??
685                         if(memberType.typeSize <= 4)
686                         {
687                            value.i = *(int *)((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
688                            if(value.i)
689                            {
690                               bool needClass = true;
691                               char * result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, &value, memberString, null, &needClass);
692                               if(result && memberString != result)
693                                  strcpy(memberString, result);
694                            }
695                         }
696                         else
697                         {
698                            bool needClass = true;
699                            char * result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)), memberString, null, &needClass);
700                            if(result && memberString != result)
701                               strcpy(memberString, result);
702                         }
703                      }
704                   }
705                   /*else
706                   {
707                      char internalMemberString[1024];
708                      byte * memberData = ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
709                      bool needClass = true;
710                      char * result;
711                      result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetString])(memberType, memberData, internalMemberString, null, &needClass);
712                      if(needClass)
713                      {
714                         //strcpy(memberString, memberType.name);
715                         strcat(memberString, "{ ");
716                         if(result) strcat(memberString, result);
717                         strcat(memberString, " }");
718                      }
719                      else if(result)
720                         strcpy(memberString, result);
721                   }*/
722                }
723                // MemberUnion
724                // MemberStruct
725             }
726             // TODO: Fix atID stuff
727             if(memberString[0])
728             {
729                if(prev)
730                   strcat(tempString, ", ");
731                if(!atMember || !strcmp(memberType.name, "bool"))
732                {
733                   strcat(tempString, name);
734                   strcat(tempString, " = ");
735                }
736
737                if(!strcmp(memberType.name, "char *"))
738                {
739                   int len = strlen(tempString);
740                   int c;
741                   strcat(tempString, "\"");
742                   len ++;
743                   for(c = 0; memberString[c]; c++)
744                   {
745                      if(memberString[c] == '\"')
746                      {
747                         strcat(tempString, "\\\"");
748                         len+=2;
749                      }
750                      else if(memberString[c] == '\\')
751                      {
752                         strcat(tempString, "\\\\");
753                         len+=2;
754                      }
755                      else
756                      {
757                         tempString[len++] = memberString[c];
758                         tempString[len] = 0;
759                      }
760                   }
761                   strcat(tempString, "\"");
762                }
763                else
764                   strcat(tempString, memberString);
765                atMember = true;
766
767                prev = true;
768             }
769             else if(member && (!member.isProperty || !((Property)member).conversion))
770                atMember = false;
771          }
772       }
773    }
774    return tempString;
775 }
776
777 static bool OnGetDataFromString(Class _class, void ** data, char * string)
778 {
779    bool result;
780    Module module = _class.module;
781    if(_class.type == enumClass)
782       result = Enum_OnGetDataFromString(_class, (int *)data, string);
783    else if(_class.type == unitClass)
784    {
785       Class dataType;
786       Property prop;
787       for(prop = _class.conversions.first; prop; prop = prop.next)
788       {
789          bool refProp = false;
790          Class c;
791          if(!strcmp(prop.name, _class.base.fullName))
792             refProp = true;
793          else if( (c = eSystem_FindClass(_class.module, prop.name) ) )
794          {
795             Property p;
796             for(p = c.conversions.first; p; p = p.next)
797             {
798                if(!strcmp(p.name, _class.base.fullName) && !p.Set && !p.Get)
799                {
800                   refProp = true;
801                   break;
802                }
803             }
804          }
805          if(refProp)
806          {
807             if(prop.Set && prop.Get)
808             {
809                String dts = _class.base.dataTypeString;
810                if(!strcmp(dts, "double"))
811                {
812                   double d;
813                   bool result = ((bool (*)(void *, void *, const char *))(void *)class(double)._vTbl[__ecereVMethodID_class_OnGetDataFromString])(class(double), &d, string);
814                   *(double *)data =((double(*)(double))(void *)prop.Get)(d);
815                   return result;
816                }
817                else if(!strcmp(dts, "float"))
818                {
819                   float d;
820                   bool result = ((bool (*)(void *, void *, const char *))(void *)class(float)._vTbl[__ecereVMethodID_class_OnGetDataFromString])(class(float), &d, string);
821                   *(float *)data = ((float(*)(float))(void *)prop.Get)(d);
822                   return result;
823                }
824                else if(!strcmp(dts, "int"))
825                {
826                   int d;
827                   bool result = ((bool (*)(void *, void *, const char *))(void *)class(int)._vTbl[__ecereVMethodID_class_OnGetDataFromString])(class(int), &d, string);
828                   *(int *)data = ((int(*)(int))(void *)prop.Get)(d);
829                   return result;
830                }
831                else if(!strcmp(dts, "int64"))
832                {
833                   int64 d;
834                   bool result = ((bool (*)(void *, void *, const char *))(void *)class(int64)._vTbl[__ecereVMethodID_class_OnGetDataFromString])(class(int64), &d, string);
835                   *(int64 *)data = ((int64(*)(int64))(void *)prop.Get)(d);
836                   return result;
837                }
838             }
839             else
840                break;
841          }
842       }
843       dataType = eSystem_FindClass(module, _class.dataTypeString);
844       return ((bool (*)(void *, void *, const char *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetDataFromString])(dataType, data, string);
845    }
846    else if(!string[0] && _class.type == normalClass)
847    {
848       // result = false;  // Why was this data = null commented?
849       *data = null;
850       return true;
851    }
852    else
853    {
854       int c;
855       char memberName[1024];
856       char memberString[10240];
857       int count = 0;
858       bool quoted = false;
859       int brackets = 0;
860       char ch;
861       bool escape = false;
862       bool gotChar;
863       uint memberOffset;
864       Class curClass = null;
865       DataMember curMember = null;
866       DataMember subMemberStack[256];
867       int subMemberStackPos = 0;
868
869       result = true;
870
871       if(_class.type == noHeadClass || _class.type == normalClass)
872       {
873          data = *data = eInstance_New(_class);
874          if(_class.type == normalClass)
875             ((Instance)data)._refCount++;
876       }
877       else if(/*_class.type == noHeadClass || */_class.type == structClass)
878          memset(data, 0, _class.structSize);
879       // Bit classes cleared outside?
880
881       memberName[0] = '\0';
882
883       for(c = 0; string[c] && count < sizeof(memberString); )
884       {
885          bool found = false;
886          DataMember thisMember = null;
887
888          brackets = 0;
889          gotChar = false;
890          for(; (ch = string[c]) && count < sizeof(memberString); c++)
891          {
892             if(ch == '\"' && !escape)
893             {
894                quoted ^= true;
895             }
896             else if(quoted)
897             {
898                if(!escape && ch == '\\')
899                {
900                   escape = true;
901                }
902                else
903                {
904                   memberString[count++] = ch;
905                   escape = false;
906                }
907             }
908             // TOFIX: OnGetDataFromString is far from ready as a generic object notation reader...
909             // 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
910             // Is it used by the compiler?
911             else if(ch == ' ') // || ch == '\n' || ch == '\t' || ch == '\r')
912             {
913                if(gotChar)
914                   memberString[count++] = ch;
915             }
916             else if(ch == ',')
917             {
918                if(brackets)
919                {
920                   memberString[count++] = ch;
921                }
922                else
923                {
924                   c++;
925                   break;
926                }
927             }
928             else if(ch == '{')
929             {
930                // If bracket is not initialization
931                if(gotChar && !brackets)
932                {
933                   count = 0;
934                   gotChar = false;
935                }
936
937                if(brackets)
938                {
939                   memberString[count++] = ch;
940                   gotChar = true;
941                }
942                brackets++;
943             }
944             else if(ch == '}')
945             {
946                brackets--;
947                if(brackets)
948                {
949                   gotChar = true;
950                   memberString[count++] = ch;
951                }
952             }
953             else if(ch == '=')
954             {
955                if(brackets)
956                {
957                   memberString[count++] = ch;
958                }
959                else
960                {
961                   memberString[count] = '\0';
962                   //TrimLSpaces(memberString, memberName);
963                   //TrimRSpaces(memberName, memberString);
964                   //strcpy(memberName, memberString);
965
966                   TrimRSpaces(memberString, memberName);
967                   count = 0;
968                   gotChar = false;
969                }
970             }
971             else
972             {
973                memberString[count++] = ch;
974                gotChar = true;
975             }
976          }
977
978          memberString[count] = '\0';
979          TrimRSpaces(memberString, memberString);
980
981          if(memberName[0])
982          {
983             DataMember _subMemberStack[256];
984             int _subMemberStackPos = 0;
985
986             thisMember = eClass_FindDataMemberAndOffset(_class, memberName, &memberOffset, _class.module, _subMemberStack, &_subMemberStackPos);
987
988             if(!thisMember)
989                thisMember = (DataMember)eClass_FindProperty(_class, memberName, _class.module);
990             if(thisMember)
991             {
992                if(thisMember.memberAccess == publicAccess)
993                {
994                   curMember = thisMember;
995                   curClass = thisMember._class;
996                   memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
997                   subMemberStackPos = _subMemberStackPos;
998                }
999                found = true;
1000             }
1001          }
1002          else
1003          {
1004             eClass_FindNextMember(_class, &curClass, (DataMember *)&curMember, subMemberStack, &subMemberStackPos);
1005             thisMember = curMember;
1006             if(thisMember)
1007             {
1008                found = true;
1009                eClass_FindDataMemberAndOffset(_class, thisMember.name, &memberOffset, _class.module, null, null);
1010             }
1011          }
1012          if(found)
1013          {
1014             Class memberType = thisMember.dataTypeClass;
1015
1016             if(!memberType)
1017                memberType = thisMember.dataTypeClass = eSystem_FindClass(module, thisMember.dataTypeString);
1018             if(!memberType)
1019                memberType = thisMember.dataTypeClass = eSystem_FindClass(module, "int");
1020             if(memberType.type == structClass)
1021             {
1022                if(thisMember)
1023                {
1024                   if(!((bool (*)(void *, void *, const char *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString])(memberType,
1025                      (byte *)data + (((thisMember._class.type == normalClass) ? thisMember._class.offset : 0) + memberOffset), memberString))
1026                      result = false;
1027                }
1028             }
1029             else
1030             {
1031                DataValue value = { 0 };
1032                // Patch for hotKey crash ( #556 )
1033                // Key has a member KeyCode, which inherits from Key
1034                // We don't want KeyCode to use its base class OnGetDataFromString
1035                if(memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString] == _class._vTbl[__ecereVMethodID_class_OnGetDataFromString])
1036                {
1037                   if(!OnGetDataFromString(memberType, &value, memberString))
1038                      result = false;
1039                }
1040                else if(!((bool (*)(void *, void *, const char *))(void *)memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString])(memberType, &value, memberString))
1041                   result = false;
1042                if(thisMember && !thisMember.isProperty)
1043                {
1044                   if(_class.type == bitClass)
1045                   {
1046                      BitMember bitMember = (BitMember) thisMember;
1047                      // TODO: Check if bit _class is 32 or 64 bit
1048                      *(uint *)data = (uint32)(((*(uint *)data & ~bitMember.mask)) | ((value.ui64<<bitMember.pos)&bitMember.mask));
1049                   }
1050                   else
1051                      *(int *)((byte *)data + (((thisMember._class.type == normalClass) ? thisMember._class.offset : 0) + thisMember.offset)) = value.i;
1052                }
1053                else if(thisMember.isProperty && ((Property)thisMember).Set)
1054                {
1055                   if(memberType.type == noHeadClass || memberType.type == normalClass || memberType.type == structClass)
1056                      ((void (*)(void *, void *))(void *)((Property)thisMember).Set)(data, value.p);
1057                   else
1058                      ((void (*)(void *, int))(void *)((Property)thisMember).Set)(data, value.i);
1059                }
1060             }
1061          }
1062          else
1063             result = false;
1064
1065          count = 0;
1066          memberName[0] = '\0';
1067       }
1068    }
1069    return result;
1070 }
1071
1072 static void OnCopy(Class _class, void ** data, void * newData)
1073 {
1074    // TO IMPROVE: Inherit from Unit class for better performance?
1075    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
1076    {
1077       Class dataType = eSystem_FindClass(_class.module, _class.dataTypeString);
1078       if(dataType)
1079          ((void (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCopy])(dataType, data, newData);
1080    }
1081    else if(_class.type != structClass && (_class.type != systemClass || _class.byValueSystemClass))
1082    {
1083       *data = newData;
1084    }
1085    // Here we have either a structClass or a systemClass
1086    else if(newData)
1087       memcpy(data, newData, _class.typeSize);
1088    else
1089       memset(data, 0, _class.typeSize);
1090 }
1091
1092 static int DataMember_OnSerialize(DataMember parentMember, void * data, IOChannel channel)
1093 {
1094    DataMember member;
1095    Module module = parentMember._class.module;
1096    for(member = parentMember.members.first; member; member = member.next)
1097    {
1098       if(member.type == normalMember)
1099       {
1100          Class memberType = member.dataTypeClass;
1101
1102          if(!memberType)
1103             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1104          if(!memberType)
1105             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
1106
1107          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1108          {
1109             ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnSerialize])(memberType, (byte *)data + member.offset, channel);
1110          }
1111          else
1112          {
1113             DataValue value;
1114             value.i = *(int *)((byte *)data + member.offset);
1115             ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnSerialize])(memberType, &value, channel);
1116          }
1117       }
1118       else
1119       {
1120          DataMember_OnSerialize(member, (byte *)data + member.offset, channel);
1121       }
1122    }
1123    return 0;
1124 }
1125
1126 static void OnSerialize(Class _class, void * data, IOChannel channel)
1127 {
1128    Module module = _class.module;
1129    // TO IMPROVE: Inherit from Unit class for better performance?
1130    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
1131    {
1132       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
1133       if(dataType)
1134          ((void (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnSerialize])(dataType, data, channel);
1135    }
1136    else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
1137    {
1138       //if(data)
1139       {
1140          Class lastClass = null;
1141          while(lastClass != _class)
1142          {
1143             DataMember member;
1144             Class c;
1145             for(c = _class; c && (!c.base || c.base.type != systemClass) && c.base != lastClass; c = c.base);
1146             lastClass = c;
1147
1148             for(member = c.membersAndProperties.first; member; member = member.next)
1149             {
1150                if(member.id < 0) continue;
1151                if(member.isProperty || member.type == normalMember)
1152                {
1153                   Class memberType = member.dataTypeClass;
1154
1155                   if(!memberType)
1156                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1157                   if(memberType)
1158                   {
1159                      if(member.isProperty)
1160                      {
1161                         /*Property prop = (Property)member;
1162                         if(!prop.conversion && prop.Get && prop.Set)
1163                         {
1164                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1165                            {
1166
1167                            }
1168                            else
1169                            {
1170                               DataValue value;
1171                               if(!strcmp(memberType.dataTypeString, "float"))
1172                               {
1173                                  value.f = ((float(*)())(void *)prop.Get)(data);
1174                               }
1175                               else
1176                               {
1177                                  value.i = prop.Get(data);
1178                               }
1179                               ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnSerialize])(memberType, &value, channel);
1180                            }
1181                         }*/
1182                      }
1183                      else
1184                      {
1185                         if(!strcmp(memberType.name, "String") || memberType.type == normalClass || memberType.type == noHeadClass)
1186                         {
1187                            ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnSerialize])(memberType, data ? (*(void **)((byte *)data + member._class.offset + member.offset)) : null, channel);
1188                         }
1189                         else
1190                            ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnSerialize])(memberType, data ? (((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset))) : null, channel);
1191                      }
1192                   }
1193                   else
1194                   {
1195                      // printf("Unknown type\n");
1196                   }
1197                }
1198                else
1199                {
1200                   DataMember_OnSerialize(member, data ? ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)) : null, channel);
1201                }
1202             }
1203          }
1204       }
1205    }
1206 }
1207
1208 static int DataMember_OnUnserialize(DataMember parentMember, void * data, IOChannel channel)
1209 {
1210    DataMember member;
1211    Module module = parentMember._class.module;
1212    for(member = parentMember.members.first; member; member = member.next)
1213    {
1214       if(member.type == normalMember)
1215       {
1216          Class memberType = member.dataTypeClass;
1217
1218          if(!memberType)
1219             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1220          if(!memberType)
1221             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
1222
1223          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1224          {
1225             ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnUnserialize])(memberType, (byte *)data + member.offset, channel);
1226          }
1227          else
1228          {
1229             DataValue value;
1230             ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnUnserialize])(memberType, &value, channel);
1231             *(int *)((byte *)data + member.offset) = value.i;
1232          }
1233       }
1234       else
1235       {
1236          DataMember_OnUnserialize(member, (byte *)data + member.offset, channel);
1237       }
1238    }
1239    return 0;
1240 }
1241
1242 static void OnUnserialize(Class _class, void ** data, IOChannel channel)
1243 {
1244    Module module = _class.module;
1245    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
1246    {
1247       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
1248       if(dataType)
1249          ((void (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnUnserialize])(dataType, data, channel);
1250    }
1251    else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
1252    {
1253       if(data)
1254       {
1255          Class lastClass = null;
1256          if(_class.type == normalClass || _class.type == noHeadClass)
1257          {
1258             // TOFIX: Seriously!?!?? Fix me!
1259             data = *data = eInstance_New(_class);
1260             if(_class.type == normalClass)
1261                ((Instance)data)._refCount++;
1262          }
1263          else if(/*_class.type == noHeadClass || */_class.type == structClass)
1264             memset(data, 0, _class.structSize);
1265
1266          while(lastClass != _class)
1267          {
1268             DataMember member;
1269             Class c;
1270             for(c = _class; c && (!c.base || c.base.type != systemClass) && c.base != lastClass; c = c.base);
1271             lastClass = c;
1272
1273             for(member = c.membersAndProperties.first; member; member = member.next)
1274             {
1275                if(member.id < 0) continue;
1276                if(member.isProperty || member.type == normalMember)
1277                {
1278                   Class memberType = member.dataTypeClass;
1279
1280                   if(!memberType)
1281                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1282                   if(memberType)
1283                   {
1284                      if(member.isProperty)
1285                      {
1286                         /*Property prop = (Property)member;
1287                         if(!prop.conversion && prop.Get && prop.Set)
1288                         {
1289                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1290                            {
1291
1292                            }
1293                            else
1294                            {
1295                               DataValue value;
1296                               ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnUnserialize])(memberType, &value, channel);
1297                               prop.Set(data, value.i);
1298                            }
1299                         }*/
1300                      }
1301                      else
1302                         ((void (*)(void *, void *, void *))(void *)memberType._vTbl[__ecereVMethodID_class_OnUnserialize])(memberType,
1303                            (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1304                   }
1305                   else
1306                   {
1307                      // printf("Unknown type\n");
1308                   }
1309                }
1310                else
1311                {
1312                   DataMember_OnUnserialize(member, (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1313                }
1314             }
1315          }
1316       }
1317    }
1318 }
1319
1320 // Integer
1321 static int Integer_OnCompare(Class _class, int * data1, int * data2)
1322 {
1323    int result = 0;
1324    if(!data1 && !data2) result = 0;
1325    else if(data1 && !data2) result = 1;
1326    else if(!data1 && data2) result = -1;
1327    else if(*data1 > *data2) result = 1;
1328    else if(*data1 < *data2) result = -1;
1329    return result;
1330 }
1331
1332 /*static */char * Integer_OnGetString(Class _class, int * data, char * string, void * fieldData, bool * needClass)
1333 {
1334    sprintf(string, "%d", *data);
1335    return string;
1336 }
1337
1338 static bool Integer_OnGetDataFromString(Class _class, int * data, char * string)
1339 {
1340    char * end;
1341    int result = strtol(string, &end, 0);
1342
1343    if(end > string)
1344    {
1345       *data = result;
1346       return true;
1347    }
1348    return false;
1349 }
1350
1351 static char * Int16_OnGetString(Class _class, short * data, char * string, void * fieldData, bool * needClass)
1352 {
1353    sprintf(string, "%d", (int)*data);
1354    return string;
1355 }
1356
1357 static bool Int16_OnGetDataFromString(Class _class, short * data, char * string)
1358 {
1359    char * end;
1360    short result = (short)strtol(string, &end, 0);
1361
1362    if(end > string)
1363    {
1364       *data = result;
1365       return true;
1366    }
1367    return false;
1368 }
1369
1370 static int Int16_OnCompare(Class _class, short * data1, short * data2)
1371 {
1372    int result = 0;
1373    if(!data1 && !data2) result = 0;
1374    else if(data1 && !data2) result = 1;
1375    else if(!data1 && data2) result = -1;
1376    else if(*data1 > *data2) result = 1;
1377    else if(*data1 < *data2) result = -1;
1378    return result;
1379 }
1380
1381 static int UInteger_OnCompare(Class _class, unsigned int * data1, unsigned int * data2)
1382 {
1383    int result = 0;
1384    if(!data1 && !data2) result = 0;
1385    else if(data1 && !data2) result = 1;
1386    else if(!data1 && data2) result = -1;
1387    else if(*data1 > *data2) result = 1;
1388    else if(*data1 < *data2) result = -1;
1389    return result;
1390 }
1391
1392 static char * UInteger_OnGetString(Class _class, unsigned int * data, char * string, void * fieldData, bool * needClass)
1393 {
1394    sprintf(string, "%u", *data);
1395    return string;
1396 }
1397
1398 static int UInt16_OnCompare(Class _class, uint16 * data1, unsigned int * data2)
1399 {
1400    int result = 0;
1401    if(!data1 && !data2) result = 0;
1402    else if(data1 && !data2) result = 1;
1403    else if(!data1 && data2) result = -1;
1404    else if(*data1 > *data2) result = 1;
1405    else if(*data1 < *data2) result = -1;
1406    return result;
1407 }
1408
1409 static char * UInt16_OnGetString(Class _class, uint16 * data, char * string, void * fieldData, bool * needClass)
1410 {
1411    sprintf(string, "%u", (uint)*data);
1412    return string;
1413 }
1414
1415
1416 static char * UIntegerHex_OnGetString(Class _class, unsigned int * data, char * string, void * fieldData, bool * needClass)
1417 {
1418    sprintf(string, "%x", *data);
1419    return string;
1420 }
1421
1422 static bool UInteger_OnGetDataFromString(Class _class, unsigned int * data, char * string)
1423 {
1424    char * end;
1425    uint result = (uint)strtoul(string, &end, 0);
1426    if(end > string)
1427    {
1428       *data = result;
1429       return true;
1430    }
1431    return false;
1432 }
1433
1434 static bool UInt16_OnGetDataFromString(Class _class, uint16 * data, char * string)
1435 {
1436    char * end;
1437    uint16 result = (uint16)strtoul(string, &end, 0);
1438    if(end > string)
1439    {
1440       *data = result;
1441       return true;
1442    }
1443    return false;
1444 }
1445
1446 static int Byte_OnCompare(Class _class, byte * data1, byte * data2)
1447 {
1448    int result = 0;
1449    if(!data1 && !data2) result = 0;
1450    else if(data1 && !data2) result = 1;
1451    else if(!data1 && data2) result = -1;
1452    else if(*data1 > *data2) result = 1;
1453    else if(*data1 < *data2) result = -1;
1454    return result;
1455 }
1456
1457 static char * Byte_OnGetString(Class _class, byte * data, char * string, void * fieldData, bool * needClass)
1458 {
1459    sprintf(string, "%u", (int)*data);
1460    return string;
1461 }
1462
1463 static char * Char_OnGetString(Class _class, char * data, char * string, void * fieldData, bool * needClass)
1464 {
1465    if(needClass && *needClass)
1466    {
1467       char ch = *data;
1468       if(ch == '\t')      strcpy(string, "'\t'");
1469       else if(ch == '\n') strcpy(string, "'\n'");
1470       else if(ch == '\r') strcpy(string, "'\r'");
1471       else if(ch == '\a') strcpy(string, "'\a'");
1472       else if(ch == '\\') strcpy(string, "'\\'");
1473       else if(ch < 32 || ch >= 127)    sprintf(string, "'\o'", ch);
1474       else sprintf(string, "'%c'", ch);
1475    }
1476    else
1477       sprintf(string, "%c", *data);
1478    return string;
1479 }
1480
1481 static bool Byte_OnGetDataFromString(Class _class, byte * data, char * string)
1482 {
1483    char * end;
1484    byte result = (byte)strtoul(string, &end, 0);
1485    if(end > string)
1486    {
1487       *data = result;
1488       return true;
1489    }
1490    return false;
1491 }
1492
1493 static int Int64_OnCompare(Class _class, int64 * data1, int64 * data2)
1494 {
1495    int result = 0;
1496    if(!data1 && !data2) result = 0;
1497    else if(data1 && !data2) result = 1;
1498    else if(!data1 && data2) result = -1;
1499    else if(*data1 > *data2) result = 1;
1500    else if(*data1 < *data2) result = -1;
1501    return result;
1502 }
1503
1504 static int UInt64_OnCompare(Class _class, uint64 * data1, uint64 * data2)
1505 {
1506    int result = 0;
1507    if(!data1 && !data2) result = 0;
1508    else if(data1 && !data2) result = 1;
1509    else if(!data1 && data2) result = -1;
1510    else if(*data1 > *data2) result = 1;
1511    else if(*data1 < *data2) result = -1;
1512    return result;
1513 }
1514
1515 static int IntPtr64_OnCompare(Class _class, int64 data1, int64 data2)
1516 {
1517    int result = 0;
1518    if(data1 > data2) result = 1;
1519    else if(data1 < data2) result = -1;
1520    return result;
1521 }
1522
1523 static int IntPtr32_OnCompare(Class _class, int data1, int data2)
1524 {
1525    int result = 0;
1526    if(data1 > data2) result = 1;
1527    else if(data1 < data2) result = -1;
1528    return result;
1529 }
1530
1531 static int UIntPtr64_OnCompare(Class _class, uint64 data1, uint64 data2)
1532 {
1533    int result = 0;
1534    if(data1 > data2) result = 1;
1535    else if(data1 < data2) result = -1;
1536    return result;
1537 }
1538
1539 static int UIntPtr32_OnCompare(Class _class, uint32 data1, uint32 data2)
1540 {
1541    int result = 0;
1542    if(data1 > data2) result = 1;
1543    else if(data1 < data2) result = -1;
1544    return result;
1545 }
1546
1547 static char * Int64_OnGetString(Class _class, int64 * data, char * string, void * fieldData, bool * needClass)
1548 {
1549    sprintf(string, FORMAT64D, *data);
1550    return string;
1551 }
1552
1553 static char * UInt64_OnGetString(Class _class, uint64 * data, char * string, void * fieldData, bool * needClass)
1554 {
1555    sprintf(string, FORMAT64U, *data);
1556    return string;
1557 }
1558
1559 static char * UInt64Hex_OnGetString(Class _class, uint64 * data, char * string, void * fieldData, bool * needClass)
1560 {
1561    sprintf(string, FORMAT64HEX, *data);
1562    return string;
1563 }
1564
1565 static char * UIntPtr64_OnGetString(Class _class, uint64 data, char * string, void * fieldData, bool * needClass)
1566 {
1567    return UInt64Hex_OnGetString(_class, &data, string, fieldData, needClass);
1568 }
1569
1570 static char * UIntPtr32_OnGetString(Class _class, uint data, char * string, void * fieldData, bool * needClass)
1571 {
1572    return UIntegerHex_OnGetString(_class, &data, string, fieldData, needClass);
1573 }
1574
1575 static char * IntPtr64_OnGetString(Class _class, uint64 data, char * string, void * fieldData, bool * needClass)
1576 {
1577    return Int64_OnGetString(_class, &data, string, fieldData, needClass);
1578 }
1579
1580 static char * IntPtr32_OnGetString(Class _class, uint data, char * string, void * fieldData, bool * needClass)
1581 {
1582    return Integer_OnGetString(_class, &data, string, fieldData, needClass);
1583 }
1584
1585 static bool Int64_OnGetDataFromString(Class _class, uint64 * data, char * string)
1586 {
1587    char * end;
1588    uint64 result = _strtoi64(string, &end, 0);
1589    if(end > string)
1590    {
1591       *data = result;
1592       return true;
1593    }
1594    return false;
1595 }
1596
1597 static bool UInt64_OnGetDataFromString(Class _class, uint64 * data, char * string)
1598 {
1599    char * end;
1600    uint64 result = _strtoui64(string, &end, 0);
1601    if(end > string)
1602    {
1603       *data = result;
1604       return true;
1605    }
1606    return false;
1607 }
1608
1609 /*static */void Byte_OnSerialize(Class _class, byte * data, IOChannel channel)
1610 {
1611    channel.WriteData(data, 1);
1612 }
1613
1614 /*static */void Byte_OnUnserialize(Class _class, byte * data, IOChannel channel)
1615 {
1616    if(channel.ReadData(data, 1) != 1)
1617       *data = 0;
1618 }
1619
1620 /*static */void Int_OnSerialize(Class _class, int * data, IOChannel channel)
1621 {
1622    byte bytes[4];
1623    PUTXDWORD(bytes, * data);
1624    channel.WriteData(bytes, 4);
1625 }
1626
1627 /*static */void IntPtr32_OnSerialize(Class _class, int data, IOChannel channel)
1628 {
1629    byte bytes[4];
1630    PUTXDWORD(bytes, data);
1631    channel.WriteData(bytes, 4);
1632 }
1633
1634 /*static */void Int_OnUnserialize(Class _class, int * data, IOChannel channel)
1635 {
1636    byte bytes[4];
1637    if(channel.ReadData(bytes, 4) == 4)
1638       *data = GETXDWORD(bytes);
1639    else
1640       *data = 0;
1641 }
1642
1643 /*static */void Enum_OnSerialize(Class _class, int * data, IOChannel channel)
1644 {
1645    Class dataType = strcmp(_class.dataTypeString, "int") ? eSystem_FindClass(_class.module, _class.dataTypeString) : null;
1646    if(dataType)
1647       ((void (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnSerialize])(dataType, data, channel);
1648    else
1649       Int_OnSerialize(_class, data, channel);
1650 }
1651
1652 /*static */void Enum_OnUnserialize(Class _class, int * data, IOChannel channel)
1653 {
1654    Class dataType = strcmp(_class.dataTypeString, "int") ? eSystem_FindClass(_class.module, _class.dataTypeString) : null;
1655    if(dataType)
1656       ((void (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnUnserialize])(dataType, data, channel);
1657    else
1658       Int_OnUnserialize(_class, data, channel);
1659 }
1660
1661 /*static */void Int64_OnSerialize(Class _class, int64 * data, IOChannel channel)
1662 {
1663    byte bytes[8];
1664    PUTXQWORD(bytes, * data);
1665    channel.WriteData(bytes, 8);
1666 }
1667
1668 static void IntPtr64_OnSerialize(Class _class, int64 data, IOChannel channel)
1669 {
1670    byte bytes[8];
1671    PUTXQWORD(bytes, data);
1672    channel.WriteData(bytes, 8);
1673 }
1674
1675 /*static */void Int64_OnUnserialize(Class _class, int64 * data, IOChannel channel)
1676 {
1677    byte bytes[8];
1678    if(channel.ReadData(bytes, 8) == 8)
1679       *data = GETXQWORD(bytes);
1680    else
1681       *data = 0;
1682 }
1683
1684 /*static */void Word_OnSerialize(Class _class, uint16 * data, IOChannel channel)
1685 {
1686    byte bytes[2];
1687    PUTXWORD(bytes, * data);
1688    channel.WriteData(bytes, 2);
1689 }
1690
1691 /*static */void Word_OnUnserialize(Class _class, uint16 * data, IOChannel channel)
1692 {
1693    byte bytes[2];
1694    if(channel.ReadData(bytes, 2) == 2)
1695       *data = GETXWORD(bytes);
1696    else
1697       *data = 0;
1698 }
1699
1700 static void RegisterClass_Integer(Module module)
1701 {
1702    Class integerClass = eSystem_RegisterClass(normalClass, "int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1703    integerClass.type = systemClass;
1704    delete integerClass.dataTypeString;
1705    integerClass.dataTypeString = CopyString("int");
1706    integerClass.structSize = 0;
1707    integerClass.typeSize = sizeof(int);
1708
1709    eClass_AddMethod(integerClass, "OnCompare", null, Integer_OnCompare, publicAccess);
1710    eClass_AddMethod(integerClass, "OnGetString", null, Integer_OnGetString, publicAccess);
1711    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer_OnGetDataFromString, publicAccess);
1712    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1713    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1714
1715    integerClass = eSystem_RegisterClass(normalClass, "int64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1716    integerClass.type = systemClass;
1717    integerClass.structSize = 0;
1718    integerClass.typeSize = sizeof(int64);
1719    delete integerClass.dataTypeString;
1720    integerClass.dataTypeString = CopyString("int64");
1721    eClass_AddMethod(integerClass, "OnGetString", null, Int64_OnGetString, publicAccess);
1722    eClass_AddMethod(integerClass, "OnCompare", null, Int64_OnCompare, publicAccess);
1723    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Int64_OnGetDataFromString, publicAccess);
1724    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1725    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1726
1727    integerClass = eSystem_RegisterClass(normalClass, "uint", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1728    integerClass.type = systemClass;
1729    delete integerClass.dataTypeString;
1730    integerClass.dataTypeString = CopyString("unsigned int");
1731    integerClass.structSize = 0;
1732    integerClass.typeSize = sizeof(uint);
1733    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1734    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1735    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1736    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1737    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1738
1739    integerClass = eSystem_RegisterClass(normalClass, "unsigned int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1740    integerClass.type = systemClass;
1741    delete integerClass.dataTypeString;
1742    integerClass.dataTypeString = CopyString("unsigned int");
1743    integerClass.structSize = 0;
1744    integerClass.typeSize = sizeof(uint);
1745
1746    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1747    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1748    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1749    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1750    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1751
1752    integerClass = eSystem_RegisterClass(normalClass, "uint16", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1753    integerClass.type = systemClass;
1754    delete integerClass.dataTypeString;
1755    integerClass.dataTypeString = CopyString("unsigned short");
1756    integerClass.structSize = 0;
1757    integerClass.typeSize = sizeof(uint16);
1758
1759    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1760    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1761    eClass_AddMethod(integerClass, "OnCompare", null, UInt16_OnCompare, publicAccess);
1762    eClass_AddMethod(integerClass, "OnGetString", null, UInt16_OnGetString, publicAccess);
1763    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInt16_OnGetDataFromString, publicAccess);
1764
1765    integerClass = eSystem_RegisterClass(normalClass, "short", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1766    integerClass.type = systemClass;
1767    delete integerClass.dataTypeString;
1768    integerClass.dataTypeString = CopyString("short");
1769    integerClass.structSize = 0;
1770    integerClass.typeSize = sizeof(short);
1771
1772    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1773    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1774    eClass_AddMethod(integerClass, "OnCompare", null, Int16_OnCompare, publicAccess);
1775    eClass_AddMethod(integerClass, "OnGetString", null, Int16_OnGetString, publicAccess);
1776    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Int16_OnGetDataFromString, publicAccess);
1777
1778    /*
1779    integerClass = eSystem_RegisterClass(normalClass, "uint32", null, 0, 0, null, null, module, baseSystemAccess);
1780    integerClass.type = systemClass;
1781    delete integerClass.dataTypeString;
1782    integerClass.dataTypeString = CopyString("uint32");
1783    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1784    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1785    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1786    */
1787    integerClass = eSystem_RegisterClass(normalClass, "uint32", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
1788    integerClass.type = systemClass;
1789    delete integerClass.dataTypeString;
1790    integerClass.dataTypeString = CopyString("unsigned int");
1791    integerClass.structSize = 0;
1792    integerClass.typeSize = sizeof(uint32);
1793
1794    integerClass = eSystem_RegisterClass(normalClass, "uint64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1795    integerClass.type = systemClass;
1796    delete integerClass.dataTypeString;
1797    integerClass.dataTypeString = CopyString("uint64");
1798    integerClass.structSize = 0;
1799    integerClass.typeSize = sizeof(uint64);
1800    eClass_AddMethod(integerClass, "OnGetString", null, UInt64_OnGetString, publicAccess);
1801    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInt64_OnGetDataFromString, publicAccess);
1802    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1803    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1804    eClass_AddMethod(integerClass, "OnCompare", null, UInt64_OnCompare, publicAccess);
1805
1806    integerClass = eSystem_RegisterClass(normalClass, "byte", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1807    integerClass.type = systemClass;
1808    delete integerClass.dataTypeString;
1809    integerClass.dataTypeString = CopyString("unsigned char");
1810    integerClass.structSize = 0;
1811    integerClass.typeSize = sizeof(byte);
1812    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1813    eClass_AddMethod(integerClass, "OnGetString", null, Byte_OnGetString, publicAccess);
1814    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1815    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1816    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1817
1818    integerClass = eSystem_RegisterClass(normalClass, "char", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1819    integerClass.type = systemClass;
1820    delete integerClass.dataTypeString;
1821    integerClass.dataTypeString = CopyString("char");
1822    integerClass.structSize = 0;
1823    integerClass.typeSize = sizeof(char);
1824    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1825    eClass_AddMethod(integerClass, "OnGetString", null, Char_OnGetString, publicAccess);
1826    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1827    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1828    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1829
1830    integerClass = eSystem_RegisterClass(normalClass, "intsize", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1831    integerClass.type = systemClass;
1832    delete integerClass.dataTypeString;
1833    integerClass.dataTypeString = CopyString("ssize_t");
1834    integerClass.structSize = 0;
1835    integerClass.typeSize = sizeof(intsize);
1836    if(sizeof(intsize) == 8)
1837    {
1838       eClass_AddMethod(integerClass, "OnGetString", null, Int64_OnGetString, publicAccess);
1839       eClass_AddMethod(integerClass, "OnGetDataFromString", null, Int64_OnGetDataFromString, publicAccess);
1840       eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1841       eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1842       eClass_AddMethod(integerClass, "OnCompare", null, Int64_OnCompare, publicAccess);
1843    }
1844    else
1845    {
1846       eClass_AddMethod(integerClass, "OnCompare", null, Integer_OnCompare, publicAccess);
1847       eClass_AddMethod(integerClass, "OnGetString", null, Integer_OnGetString, publicAccess);
1848       eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer_OnGetDataFromString, publicAccess);
1849       eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1850       eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1851    }
1852
1853    integerClass = eSystem_RegisterClass(normalClass, "uintsize", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1854    integerClass.type = systemClass;
1855    delete integerClass.dataTypeString;
1856    integerClass.dataTypeString = CopyString("size_t");
1857    integerClass.structSize = 0;
1858    integerClass.typeSize = sizeof(uintsize);
1859    if(sizeof(uintsize) == 8)
1860    {
1861       eClass_AddMethod(integerClass, "OnGetString", null, UInt64Hex_OnGetString, publicAccess);
1862       eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInt64_OnGetDataFromString, publicAccess);
1863       eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1864       eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1865       eClass_AddMethod(integerClass, "OnCompare", null, UInt64_OnCompare, publicAccess);
1866    }
1867    else
1868    {
1869       eClass_AddMethod(integerClass, "OnGetString", null, UIntegerHex_OnGetString, publicAccess);
1870       eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1871       eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1872       eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1873       eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1874    }
1875
1876    integerClass = eSystem_RegisterClass(normalClass, "uintptr", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1877    integerClass.type = systemClass;
1878    delete integerClass.dataTypeString;
1879    integerClass.dataTypeString = CopyString("uintptr_t");
1880    integerClass.structSize = 0;
1881    integerClass.typeSize = sizeof(uintptr);
1882    integerClass.byValueSystemClass = true;
1883    if(sizeof(uintptr) == 8)
1884    {
1885       eClass_AddMethod(integerClass, "OnGetString", null, UIntPtr64_OnGetString, publicAccess);
1886       eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInt64_OnGetDataFromString, publicAccess);
1887       eClass_AddMethod(integerClass, "OnSerialize", null, IntPtr64_OnSerialize, publicAccess);
1888       eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1889       eClass_AddMethod(integerClass, "OnCompare", null, UIntPtr64_OnCompare, publicAccess);
1890    }
1891    else
1892    {
1893       eClass_AddMethod(integerClass, "OnGetString", null, UIntPtr32_OnGetString, publicAccess);
1894       eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1895       eClass_AddMethod(integerClass, "OnSerialize", null, IntPtr32_OnSerialize, publicAccess);
1896       eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1897       eClass_AddMethod(integerClass, "OnCompare", null, UIntPtr32_OnCompare, publicAccess);
1898    }
1899
1900    integerClass = eSystem_RegisterClass(normalClass, "intptr", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1901    integerClass.type = systemClass;
1902    delete integerClass.dataTypeString;
1903    integerClass.dataTypeString = CopyString("intptr_t");
1904    integerClass.structSize = 0;
1905    integerClass.typeSize = sizeof(intptr);
1906    integerClass.byValueSystemClass = true;
1907    if(sizeof(intptr) == 8)
1908    {
1909       eClass_AddMethod(integerClass, "OnGetString", null, IntPtr64_OnGetString, publicAccess);
1910       eClass_AddMethod(integerClass, "OnGetDataFromString", null, Int64_OnGetDataFromString, publicAccess);
1911       eClass_AddMethod(integerClass, "OnSerialize", null, IntPtr64_OnSerialize, publicAccess);
1912       eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1913       eClass_AddMethod(integerClass, "OnCompare", null, IntPtr64_OnCompare, publicAccess);
1914    }
1915    else
1916    {
1917       eClass_AddMethod(integerClass, "OnGetString", null, IntPtr32_OnGetString, publicAccess);
1918       eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer_OnGetDataFromString, publicAccess);
1919       eClass_AddMethod(integerClass, "OnSerialize", null, IntPtr32_OnSerialize, publicAccess);
1920       eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1921       eClass_AddMethod(integerClass, "OnCompare", null, IntPtr32_OnCompare, publicAccess);
1922    }
1923 }
1924
1925 // Float
1926 static int Float_OnCompare(Class _class, float * data1, float * data2)
1927 {
1928    int result = 0;
1929    if(!data1 && !data2) result = 0;
1930    else if(data1 && !data2) result = 1;
1931    else if(!data1 && data2) result = -1;
1932    else if(*data1 > *data2) result = 1;
1933    else if(*data1 < *data2) result = -1;
1934    return result;
1935 }
1936
1937 static char * Float_OnGetString(Class _class, float * data, char * string, void * fieldData, bool * needClass)
1938 {
1939    float f = *data;
1940    if(f.isInf)
1941    {
1942       if(f.signBit)
1943          strcpy(string, "-inf");
1944       else
1945          strcpy(string, "inf");
1946    }
1947    else if(f.isNan)
1948    {
1949       if(f.signBit)
1950          strcpy(string, "-nan");
1951       else
1952          strcpy(string, "nan");
1953    }
1954    else
1955    {
1956       int c;
1957       int last = 0;
1958       int numDigits = 7, num = 1;
1959       char format[10];
1960       while(numDigits && num < f) numDigits--, num *= 10;
1961       sprintf(format, "%%.%df", numDigits);
1962
1963       //sprintf(string, "%f", f);
1964       sprintf(string, format, f);
1965
1966       c = strlen(string)-1;
1967       for( ; c >= 0; c--)
1968       {
1969          if(string[c] != '0')
1970             last = Max(last, c);
1971          if(string[c] == '.')
1972          {
1973             if(last == c)
1974                string[c] = 0;
1975             else
1976                string[last+1] = 0;
1977             break;
1978          }
1979       }
1980    }
1981    return string;
1982 }
1983
1984 static bool Float_OnGetDataFromString(Class _class, float * data, char * string)
1985 {
1986    char * end;
1987    float result = (float)strtod(string, &end);
1988    //*data = atof(string);
1989    if(end > string)
1990    {
1991       *data = result;
1992       return true;
1993    }
1994    return false;
1995 }
1996
1997 static void Float_OnSerialize(Class _class, float * data, IOChannel channel)
1998 {
1999    byte bytes[4];
2000    PUTXDWORD(bytes, * (uint *)data);
2001    channel.WriteData(bytes, 4);
2002 }
2003
2004 static void Float_OnUnserialize(Class _class, float * data, IOChannel channel)
2005 {
2006    byte bytes[4];
2007    if(channel.ReadData(bytes, 4) == 4)
2008       *(uint *)data = GETXDWORD(bytes);
2009    else
2010       *data = 0;
2011 }
2012
2013 static void RegisterClass_Float(Module module)
2014 {
2015    Class floatClass = eSystem_RegisterClass(normalClass, "float", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
2016    floatClass.type = systemClass;
2017    delete floatClass.dataTypeString;
2018    floatClass.dataTypeString = CopyString("float");
2019    floatClass.structSize = 0;
2020    floatClass.typeSize = sizeof(float);
2021    eClass_AddMethod(floatClass, "OnCompare", null, Float_OnCompare, publicAccess);
2022    eClass_AddMethod(floatClass, "OnGetString", null, Float_OnGetString, publicAccess);
2023    eClass_AddMethod(floatClass, "OnGetDataFromString", null, Float_OnGetDataFromString, publicAccess);
2024    eClass_AddMethod(floatClass, "OnSerialize", null, Float_OnSerialize, publicAccess);
2025    eClass_AddMethod(floatClass, "OnUnserialize", null, Float_OnUnserialize, publicAccess);
2026
2027    eClass_AddMethod(floatClass, "nan", "float ::nan(void)", Float_nan, publicAccess);
2028    eClass_AddMethod(floatClass, "inf", "float ::inf(void)", Float_inf, publicAccess);
2029
2030    eClass_AddProperty(floatClass, "isNan", "bool", null, Float_isNan, publicAccess);
2031    eClass_AddProperty(floatClass, "isInf", "bool", null, Float_isInf, publicAccess);
2032    eClass_AddProperty(floatClass, "signBit", "int", null, Float_signBit, publicAccess);
2033 }
2034
2035 // Double
2036 static int Double_OnCompare(Class _class, double * data1, double * data2)
2037 {
2038    int result = 0;
2039    if(!data1 && !data2) result = 0;
2040    else if(data1 && !data2) result = 1;
2041    else if(!data1 && data2) result = -1;
2042    else if(*data1 > *data2) result = 1;
2043    else if(*data1 < *data2) result = -1;
2044    return result;
2045 }
2046
2047 static char * Double_OnGetString(Class _class, double * data, char * string, void * fieldData, bool * needClass)
2048 {
2049    double f = *data;
2050    if(f.isInf)
2051    {
2052       if(f.signBit)
2053          strcpy(string, "-inf");
2054       else
2055          strcpy(string, "inf");
2056    }
2057    else if(f.isNan)
2058    {
2059       if(f.signBit)
2060          strcpy(string, "-nan");
2061       else
2062          strcpy(string, "nan");
2063    }
2064    else
2065    {
2066       int c;
2067       int last = 0;
2068       //sprintf(string, "%.20f", f);
2069       if(runtimePlatform == win32)
2070       // sprintf(string, "%.16g", f);
2071          sprintf(string, "%.15g", f);
2072       else
2073          sprintf(string, "%.13lf", f);
2074
2075       c = strlen(string)-1;
2076       for( ; c >= 0; c--)
2077       {
2078          if(string[c] != '0')
2079             last = Max(last, c);
2080          if(string[c] == '.')
2081          {
2082             if(last == c)
2083                string[c] = 0;
2084             else
2085                string[last+1] = 0;
2086             break;
2087          }
2088       }
2089    }
2090    return string;
2091 }
2092
2093 static bool Double_OnGetDataFromString(Class _class, double * data, char * string)
2094 {
2095    char * end;
2096    double result;
2097    //*data = (double)strtod(string, null);
2098    result = strtod(string, &end);
2099    if(end > string)
2100    {
2101       *data = result;
2102       return true;
2103
2104     }
2105     return false;
2106 }
2107
2108 static void Double_OnSerialize(Class _class, double * data, IOChannel channel)
2109 {
2110    byte bytes[8];
2111    PUTXQWORD(bytes, * (uint64 *)data);
2112    channel.WriteData(bytes, 8);
2113 }
2114
2115 static void Double_OnUnserialize(Class _class, double * data, IOChannel channel)
2116 {
2117    byte bytes[8];
2118    if(channel.ReadData(bytes, 8) == 8)
2119       *(uint64 *)data = GETXQWORD(bytes);
2120    else
2121       *data = 0;
2122 }
2123
2124 static void RegisterClass_Double(Module module)
2125 {
2126    Class doubleClass = eSystem_RegisterClass(normalClass, "double", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
2127    doubleClass.type = systemClass;
2128    delete doubleClass.dataTypeString;
2129    doubleClass.dataTypeString = CopyString("double");
2130    doubleClass.structSize = 0;
2131    doubleClass.typeSize = sizeof(double);
2132    eClass_AddMethod(doubleClass, "OnCompare", null, Double_OnCompare, publicAccess);
2133    eClass_AddMethod(doubleClass, "OnGetString", null, Double_OnGetString, publicAccess);
2134    eClass_AddMethod(doubleClass, "OnGetDataFromString", null, Double_OnGetDataFromString, publicAccess);
2135    eClass_AddMethod(doubleClass, "OnSerialize", null, Double_OnSerialize, publicAccess);
2136    eClass_AddMethod(doubleClass, "OnUnserialize", null, Double_OnUnserialize, publicAccess);
2137
2138    eClass_AddProperty(doubleClass, "isNan", "bool", null, Double_isNan, publicAccess);
2139    eClass_AddProperty(doubleClass, "isInf", "bool", null, Double_isInf, publicAccess);
2140    eClass_AddProperty(doubleClass, "signBit", "int", null, Double_signBit, publicAccess);
2141
2142    eClass_AddMethod(doubleClass, "nan", "double ::nan(void)", Double_nan, publicAccess);
2143    eClass_AddMethod(doubleClass, "inf", "double ::inf(void)", Double_inf, publicAccess);
2144 }
2145
2146 public struct StaticString
2147 {
2148    char string[1];
2149
2150    void OnSerialize(IOChannel channel)
2151    {
2152       int len = this ? strlen(string) : 0;
2153       channel.WriteData(this ? string : "", len+1);
2154    }
2155
2156    void OnUnserialize(IOChannel channel)
2157    {
2158       if(this)
2159       {
2160          int c;
2161          uint size;
2162
2163          for(c = 0; channel.ReadData(&string[c], 1) && string[c]; c++);
2164          string[c++] = '\0';
2165       }
2166    }
2167
2168    int OnCompare(StaticString string2)
2169    {
2170       int result = 0;
2171       if(this && string2)
2172          result = strcmpi(string, string2.string);
2173       else if(!this && string2)
2174          result = -1;   // INVERTED THESE 2 CASES
2175       else if(this && !string2)
2176          result = 1;
2177       return result;
2178    }
2179
2180    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
2181    {
2182       return (char *)(this ? string : null); // Cast for memguard
2183    }
2184
2185    void OnFree()
2186    {
2187    }
2188 };
2189
2190 static void String_OnCopy(Class _class, char ** data, char * newData)
2191 {
2192    if(newData)
2193    {
2194       int len = strlen(newData);
2195       if(len)
2196       {
2197          *data = eSystem_New(len+1);
2198          memcpy(*data, newData, len+1);
2199       }
2200       else
2201          *data = null;
2202    }
2203    else
2204       *data = null;
2205 }
2206
2207 static bool String_OnGetDataFromString(Class _class, char ** data, char * newData)
2208 {
2209    if(newData)
2210    {
2211       int len = strlen(newData);
2212       if(len)
2213       {
2214          *data = eSystem_New(len+1);
2215          memcpy(*data, newData, len+1);
2216       }
2217       else
2218          *data = null;
2219    }
2220    return true;
2221 }
2222
2223 /*static */int String_OnCompare(Class _class, char * string1, char * string2)
2224 {
2225    int result = 0;
2226    if(string1 && string2)
2227       result = strcmpi(string1, string2);
2228    else if(!string1 && string2)
2229       result = 1;
2230    else if(string1 && !string2)
2231       result = -1;
2232    return result;
2233 }
2234
2235 static char * String_OnGetString(Class _class, char * string, char * tempString, void * fieldData, bool * needClass)
2236 {
2237    return string;
2238 }
2239
2240 static void String_OnFree(Class _class, char * string)
2241 {
2242    if(string)
2243    {
2244       eSystem_Delete(string);
2245    }
2246 }
2247
2248 static void String_OnSerialize(Class _class, char * string, IOChannel channel)
2249 {
2250    int len = string ? strlen(string) : 0;
2251    channel.WriteData(string ? string : "", len+1);
2252 }
2253
2254 static void String_OnUnserialize(Class _class, char * * string, IOChannel channel)
2255 {
2256    if(string)
2257    {
2258       int c;
2259       uint size = 64;
2260
2261       *string = new char[size];
2262       for(c = 0; channel.ReadData(&(*string)[c], 1) && (*string)[c]; c++)
2263       {
2264          if(c == size - 1)
2265          {
2266             size += size / 2;
2267             *string = renew *string char[size];
2268          }
2269       }
2270       (*string)[c++] = '\0';
2271       if(!UTF8Validate(*string))
2272       {
2273          char * newString = new char[c*2];
2274          ISO8859_1toUTF8(*string, newString, c*2);
2275          delete *string;
2276          *string = renew newString char[strlen(newString)+1];
2277       }
2278       else
2279          *string = renew *string char[c];
2280    }
2281 }
2282
2283 static void RegisterClass_String(Module module)
2284 {
2285    Class stringClass = eSystem_RegisterClass(normalClass, "char *", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
2286    delete stringClass.dataTypeString;
2287    stringClass.dataTypeString = CopyString("char *");
2288    stringClass.structSize = 0;
2289    stringClass.computeSize = false;
2290
2291    eClass_AddMethod(stringClass, "OnCompare", null, String_OnCompare, publicAccess);
2292    eClass_AddMethod(stringClass, "OnCopy", null, String_OnCopy, publicAccess);
2293    eClass_AddMethod(stringClass, "OnFree", null, String_OnFree, publicAccess);
2294    eClass_AddMethod(stringClass, "OnGetString", null, String_OnGetString, publicAccess);
2295    eClass_AddMethod(stringClass, "OnGetDataFromString", null, String_OnGetDataFromString, publicAccess);
2296    eClass_AddMethod(stringClass, "OnSerialize", null, String_OnSerialize, publicAccess);
2297    eClass_AddMethod(stringClass, "OnUnserialize", null, String_OnUnserialize, publicAccess);
2298    // eClass_AddProperty(stringClass, null, "Class", null, String_GetClass, publicAccess);
2299
2300    stringClass = eSystem_RegisterClass(normalClass, "String", "char *", 0, 0, null, null, module, baseSystemAccess, publicAccess);
2301    stringClass.structSize = 0;
2302    stringClass.computeSize = false;
2303    eClass_AddProperty(stringClass, null, "char *", null, null, publicAccess);
2304 }
2305
2306 void InitializeDataTypes1(Module module)
2307 {
2308    Class baseClass = eSystem_FindClass(module, "class");
2309
2310    eClass_AddVirtualMethod(baseClass, "OnDisplay", "void typed_object::OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)", null, publicAccess);
2311    eClass_AddVirtualMethod(baseClass, "OnCompare", "int typed_object::OnCompare(any_object object)", OnCompare, publicAccess);
2312    eClass_AddVirtualMethod(baseClass, "OnCopy", "void typed_object&::OnCopy(any_object newData)", OnCopy, publicAccess);
2313    eClass_AddVirtualMethod(baseClass, "OnFree", "void typed_object::OnFree(void)", OnFree, publicAccess);
2314    eClass_AddVirtualMethod(baseClass, "OnGetString", "char * typed_object::OnGetString(char * tempString, void * fieldData, bool * needClass)", OnGetString, publicAccess);
2315    eClass_AddVirtualMethod(baseClass, "OnGetDataFromString", "bool typed_object&::OnGetDataFromString(char * string)", OnGetDataFromString, publicAccess);
2316    eClass_AddVirtualMethod(baseClass, "OnEdit", "Window typed_object::OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)", null, publicAccess);
2317    eClass_AddVirtualMethod(baseClass, "OnSerialize", "void typed_object::OnSerialize(IOChannel channel)", OnSerialize, publicAccess);
2318    eClass_AddVirtualMethod(baseClass, "OnUnserialize", "void typed_object&::OnUnserialize(IOChannel channel)", OnUnserialize, publicAccess);
2319    eClass_AddVirtualMethod(baseClass, "OnSaveEdit", "bool typed_object&::OnSaveEdit(Window window, void * object)", null, publicAccess);
2320 }
2321
2322 void InitializeDataTypes(Module module)
2323 {
2324    Class enumClass = eSystem_FindClass(module, "enum");
2325
2326    eClass_AddMethod(enumClass, "OnSerialize", null, Enum_OnSerialize, publicAccess);
2327    eClass_AddMethod(enumClass, "OnUnserialize", null, Enum_OnUnserialize, publicAccess);
2328
2329    // Data Types
2330    RegisterClass_Integer(module);
2331    RegisterClass_Float(module);
2332    RegisterClass_Double(module);
2333    RegisterClass_String(module);
2334 }
2335
2336 public int PrintStdArgsToBuffer(char * buffer, int maxLen, typed_object object, va_list args)
2337 {
2338    int len = 0;
2339    // TOFIX: OnGetString will need a maxLen as well
2340    char * result = object.OnGetString(buffer, null, null);
2341    if(result)
2342    {
2343       len = strlen(result);
2344       if(len >= maxLen) len = maxLen-1;
2345       if(result != buffer)
2346          memcpy(buffer, result, len);
2347    }
2348    while(true)
2349    {
2350       Class _class = null;
2351       void * data = null;
2352
2353       _class = va_arg(args, void *);
2354       if(!_class) break;
2355       data = va_arg(args, void *);
2356       if(data)
2357       {
2358          // TOFIX: OnGetString will need a maxLen as well
2359          result = ((char *(*)(void *, void *, char *, void *, bool *))(void *)_class._vTbl[__ecereVMethodID_class_OnGetString])(_class, data, buffer + len, null, null);
2360          if(result)
2361          {
2362             int newLen = strlen(result);
2363             if(len + newLen >= maxLen) newLen = maxLen-1-len;
2364             if(result != buffer + len)
2365                memcpy(buffer + len, result, newLen);
2366             len += newLen;
2367          }
2368       }
2369    }
2370    buffer[len] = 0;
2371    return len;
2372 }
2373
2374 public int PrintBuf(char * buffer, int maxLen, typed_object object, ...)
2375 {
2376    va_list args;
2377    int len;
2378    va_start(args, object);
2379    len = PrintStdArgsToBuffer(buffer, maxLen, object, args);
2380    va_end(args);
2381    return len;
2382 }
2383
2384 public int PrintLnBuf(char * buffer, int maxLen, typed_object object, ...)
2385 {
2386    va_list args;
2387    int len;
2388    va_start(args, object);
2389    len = PrintStdArgsToBuffer(buffer, maxLen-1, object, args);
2390    buffer[len++] = '\n';
2391    buffer[len] = '\0';
2392    va_end(args);
2393    return len;
2394 }
2395
2396 public char * PrintString(typed_object object, ...)
2397 {
2398    char buffer[4096];
2399    va_list args;
2400    char * string;
2401    int len;
2402    va_start(args, object);
2403    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
2404    string = new char[len + 1];
2405    memcpy(string, buffer, len + 1);
2406    va_end(args);
2407    return string;
2408 }
2409
2410 public char * PrintLnString(typed_object object, ...)
2411 {
2412    char buffer[4096];
2413    va_list args;
2414    char * string;
2415    int len;
2416    va_start(args, object);
2417    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
2418    string = new char[len + 2];
2419    memcpy(string, buffer, len);
2420    string[len++] = '\n';
2421    string[len] = '\0';
2422    va_end(args);
2423    return string;
2424 }
2425
2426 #if defined(__ANDROID__)
2427 #include <android/log.h>
2428 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "ecere-app", __VA_ARGS__))
2429 #endif
2430
2431 public void PrintLn(typed_object object, ...)
2432 {
2433    va_list args;
2434    char buffer[4096];
2435    va_start(args, object);
2436    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
2437    va_end(args);
2438 #if defined(__ANDROID__) && !defined(ECERE_NOFILE)
2439    LOGI("%s", buffer);
2440 #else
2441    puts(buffer);
2442 #endif
2443 }
2444
2445 public void Print(typed_object object, ...)
2446 {
2447    va_list args;
2448    char buffer[4096];
2449    va_start(args, object);
2450    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
2451    va_end(args);
2452    fputs(buffer, eC_stdout());
2453 }