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