c6896f8eee79339a792144d8a93395afe25e59a8
[platform/upstream/syncevolution.git] / src / synthesis / src / sysync / itemfield.h
1 /*
2  *  File:         itemfield.h
3  *
4  *  Author:       Lukas Zeller (luz@plan44.ch)
5  *
6  *  TItemField
7  *    Abstract class, holds a single field value
8  *  TStringField, TIntegerField, TTelephoneField, TTimeStampField etc.
9  *    Implementations of field types
10  *
11  *  Copyright (c) 2001-2011 by Synthesis AG + plan44.ch
12  *
13  *  2001-08-08 : luz : created
14  *
15  */
16
17 #ifndef ItemField_H
18 #define ItemField_H
19
20 // includes
21 #include "sysync_globs.h"
22 #include "sysync_utils.h"
23
24 #include "engineinterface.h"
25
26 #include <string>
27
28 #ifdef ARRAYFIELD_SUPPORT
29 #include <vector>
30 #endif
31
32 namespace sysync {
33
34 extern cAppCharP const ItemFieldTypeNames[numFieldTypes];
35
36 extern const TPropDataTypes devInfPropTypes[numFieldTypes];
37
38
39 #ifndef NO64BITINT
40 typedef sInt64 fieldinteger_t;
41 #define StrToFieldinteger(s,i) StrToLongLong(s,i)
42 #else
43 typedef sInt32 fieldinteger_t;
44 #define StrToFieldinteger(s,i) StrToLong(s,i)
45 #endif
46
47 // our own implementation for dynamic casts for Items without needing RTTI
48 #define ITEMFIELD_DYNAMIC_CAST_PTR(ty,tyid,src) (src->isBasedOn(tyid) ? static_cast<ty *>(src) : NULL)
49
50
51 // basically abstract class, but can be used to represent EMPTY and ASSIGNED values
52 class TItemField
53 {
54 public:
55   TItemField();
56   virtual ~TItemField();
57   #ifdef ARRAYFIELD_SUPPORT
58   // check array
59   virtual bool isArray(void) const { return false; }
60   virtual TItemField *getArrayField(sInt16 aArrIdx, bool /* aExistingOnly */=false) { return aArrIdx==0 ? this : NULL; };
61   virtual sInt16 arraySize(void) const { return 1; } // non-array has one element
62   virtual TItemFieldTypes getElementType(void) const { return getType(); } // non array element is same as base type
63   #else
64   // non-virtual versions if we have no array fields at all
65   bool isArray(void) const { return false; }
66   TItemField *getArrayField(sInt16 aArrIdx, bool aExistingOnly=false) { return aArrIdx==0 ? this : NULL; };
67   sInt16 arraySize(void) const { return 1; } // non-array has one element
68   TItemFieldTypes getElementType(void) const { return getType(); }
69   #endif
70   // changelog support
71   #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
72   virtual uInt16 getDataCRC(uInt16 crc=0) { return crc; }; // base class is always empty
73   #endif
74   // access to type
75   virtual TItemFieldTypes getType(void) const { return fty_none; } // no real type
76   virtual TItemFieldTypes getCalcType(void) const { return getType(); };
77   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_none; };
78   virtual bool elementsBasedOn(TItemFieldTypes aFieldType) const { return isBasedOn(aFieldType); };
79   // dependency on a local ID
80   virtual void setParentLocalID(cAppCharP /* aParentLocalID */) { /* nop */ };
81   // access to field contents
82   #ifdef STREAMFIELD_SUPPORT
83   // - stream interface (default implementation accesses string representation of field)
84   virtual void resetStream(size_t aPos=0);
85   virtual size_t getStreamSize(void) { return getStringSize(); };
86   virtual size_t getStreamPos(void) const { return fStreamPos; };
87   virtual size_t readStream(void *aBuffer, size_t aMaxBytes);
88   virtual size_t writeStream(void *aBuffer, size_t aNumBytes);
89   void appendStream(void) { resetStream(getStreamSize()); };
90   #endif
91   virtual bool hasProxy(void) { return false; }; // normal fields don't have a proxy
92   // - as string
93   virtual void setAsString(cAppCharP /* aString */) { fAssigned=true; }; // basic setter, this one must be derived for all non-string descendants
94   virtual void setAsString(cAppCharP aString, size_t aLen);
95   virtual void setAsString(const string &aString) { setAsString(aString.c_str(),aString.size()); };
96   virtual void getAsString(string &aString) { aString.erase(); }; // empty string by default
97   virtual void appendToString(string &aString, size_t aMaxLen=0) { string s; getAsString(s); if (aMaxLen) aString.append(s,0,aMaxLen); else aString.append(s); }; // generic append
98   virtual cAppCharP getCStr(void) { return NULL; } // only real strings can return CStr (used for PalmOS optimization)
99   virtual void getAsNormalizedString(string &aString) { getAsString(aString); };
100   virtual size_t getStringSize(void);
101   // - as boolean (default: non-empty is true)
102   virtual bool getAsBoolean(void) { return !isEmpty(); };
103   virtual void setAsBoolean(bool aBool) { if (aBool) setAsString("1"); else assignEmpty(); };
104   // - as integer
105   virtual fieldinteger_t getAsInteger(void);
106   virtual void setAsInteger(fieldinteger_t aInteger);
107   // some string operations
108   // - append string/char
109   virtual void appendString(cAppCharP /* aString */, size_t /* aMaxChars */) { /* nop */ };
110   void appendString(cAppCharP aString) { appendString(aString,strlen(aString)); };
111   void appendString(const string &aString) { appendString(aString.c_str(),aString.size()); };
112   void appendChar(const char aChar) { appendString(&aChar,1); };
113   // - check if specified value is contained in myself
114   virtual bool contains(TItemField &aItemField, bool aCaseInsensitive);
115   // - find string in contents
116   virtual sInt16 findInString(cAppCharP /* aString */, bool /* aCaseInsensitive */) { return -1; };
117   // - check if specified field is shortened version of this one
118   virtual bool isShortVers(TItemField & /* aItemField */, sInt32 /* aOthersMax */) { return false; };
119   // - assignment
120   virtual bool isAssigned(void) { return fAssigned; };
121   bool isUnassigned(void) { return !isAssigned(); };
122   virtual void unAssign(void) { fAssigned=false; };
123   // empty is NOT always same as unassigned; e.g. for strings empty can be empty string assigned
124   virtual bool isEmpty(void) { return getType()==fty_none ? true : isUnassigned(); }
125   // - make assigned, but empty (explicit "" string assigned)
126   virtual void assignEmpty(void) { fAssigned=true; };
127   // assignment
128   virtual TItemField& operator=(TItemField &aItemField);
129   // field comparison
130   bool operator==(TItemField &aItem) { return compareWith(aItem)==0; }
131   bool operator!=(TItemField &aItem) { return compareWith(aItem)!=0; }
132   bool operator>(TItemField &aItem) { return compareWith(aItem)>0; }
133   bool operator>=(TItemField &aItem) { return compareWith(aItem)>=0; }
134   bool operator<(TItemField &aItem) { return compareWith(aItem)<0; }
135   bool operator<=(TItemField &aItem) { return compareWith(aItem)<=0; }
136   // append (default to appending string value of other field)
137   virtual void append(TItemField &aItemField);
138   // merge fields
139   virtual bool merge(TItemField & /* aItemField */, const char /* aSep */=0) { return false; /* nop */ };
140   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem,
141   // SYSYNC_NOT_COMPARABLE if not comparable at all or not equal and no ordering known
142   virtual sInt16 compareWith(TItemField & /* aItemField */, bool =false /* aCaseInsensitive */) { return SYSYNC_NOT_COMPARABLE; };
143   // debug support
144   #ifdef SYDEBUG
145   virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen); // show field contents as string for debug output
146   #endif
147 protected:
148   // assigned flag
149   bool fAssigned;
150   #ifdef STREAMFIELD_SUPPORT
151   // stream position
152   size_t fStreamPos;
153   #endif
154 }; // TItemField
155
156 typedef TItemField *TItemFieldP;
157
158
159
160 #ifdef ARRAYFIELD_SUPPORT
161
162 typedef std::vector<TItemField *> TFieldArray;
163
164 // array field, contains a list of fields of TItemFields
165 class TArrayField : public TItemField
166 {
167   typedef TItemField inherited;
168 public:
169   TArrayField(TItemFieldTypes aLeafFieldType, GZones *aGZonesP);
170   virtual ~TArrayField();
171   // check array
172   virtual bool isArray(void) const { return true; }
173   virtual TItemField *getArrayField(sInt16 aArrIdx, bool aExistingOnly=false);
174   virtual sInt16 arraySize(void) const { return fArray.size(); } // return size of array
175   // changelog support
176   #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
177   virtual uInt16 getDataCRC(uInt16 crc=0);
178   #endif
179   // access to type
180   virtual TItemFieldTypes getType(void) const { return fty_none; } // array has no type
181   virtual TItemFieldTypes getElementType(void) const { return fLeafFieldType; } // type of leaf fields (accessible even if array is empty)
182   virtual bool elementsBasedOn(TItemFieldTypes aFieldType) const;
183   // some string operations
184   // - assignment
185   virtual bool isAssigned(void) { return !isEmpty() || fAssigned; }; // empty, but explicitly assigned so is assigned as well
186   virtual void unAssign(void); // clear all elements and clear fAssigned
187   // - append string to array = append string as last element of array
188   virtual void appendString(cAppCharP aString, size_t aMaxChars);
189   // empty is array with no elements
190   virtual bool isEmpty(void) { return arraySize()==0; };
191   // - make assigned
192   virtual void assignEmpty(void) { unAssign(); fAssigned = true; }; // assigning emptyness must make isAssigned true!
193   // assignment
194   virtual TItemField& operator=(TItemField &aItemField);
195   // check if specified value is contained in myself
196   virtual bool contains(TItemField &aItemField, bool aCaseInsensitive);
197   // append (default to appending value of other field as a new array element)
198   virtual void append(TItemField &aItemField);
199   // merge fields
200   virtual bool merge(TItemField & /* aItemField */, const char /* aSep */=0) { return false; /* nop */ };
201   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem,
202   // SYSYNC_NOT_COMPARABLE if not comparable at all or not equal and no ordering known
203   virtual sInt16 compareWith(TItemField &aItemField, bool aCaseInsensitive=false);
204   // debug support
205   #ifdef SYDEBUG
206   virtual size_t StringObjFieldAppend(string &s, uInt16); // show field contents as string for debug output
207   #endif
208 protected:
209   // type of contained leaf fields
210   TItemFieldTypes fLeafFieldType;
211   // first field, is instantiated with array to allow type comparisons
212   TItemField *fFirstField;
213   // Zones for fields
214   GZones *fGZonesP;
215   // actual field vector
216   TFieldArray fArray;
217 }; // TArrayField
218 #endif
219
220
221 #ifndef STREAMFIELD_SUPPORT
222   #define PULLFROMPROXY
223   #define DELETEPROXY
224   #define PROXYINSTALLED false
225 #else
226   #define PULLFROMPROXY pullFromProxy()
227   #define DELETEPROXY setBlobProxy(NULL)
228   #define PROXYINSTALLED (fBlobProxyP!=NULL)
229
230 // forward
231 class TStringField;
232
233 // abstract Proxy object for Blob contents, allows loading a BLOB from DB at the moment it is
234 // actually required.
235 // Intended to be derived by database implementations
236 class TBlobProxy
237 {
238 public:
239   TBlobProxy() { fUsage=1; } // initial creator also gets owner
240   virtual ~TBlobProxy() {};
241   // - returns size of entire blob
242   virtual size_t getBlobSize(TStringField *aFieldP) = 0;
243   // - read from Blob from specified stream position and update stream pos
244   virtual size_t readBlobStream(TStringField *aFieldP, size_t &aPos, void *aBuffer, size_t aMaxBytes) = 0;
245   // - dependency on a local ID
246   virtual void setParentLocalID(cAppCharP aParentLocalID) { /* nop */ };
247   // - usage control
248   void link(void) { fUsage++; };
249   static void unlink(TBlobProxy *&aProxyP) { if (aProxyP) { if (--(aProxyP->fUsage) == 0) delete aProxyP; aProxyP=NULL; } };
250 private:
251   uInt16 fUsage;
252 }; // TBlobProxy
253
254 #endif
255
256
257 // string field.
258 // Note that a string can also be a string of binary data,
259 // not only a NUL-terminated string (as used in derived blob class)
260 class TStringField: public TItemField
261 {
262   typedef TItemField inherited;
263   friend class TBlobProxy;
264 public:
265   TStringField();
266   virtual ~TStringField();
267   // access to type
268   virtual TItemFieldTypes getType(void) const { return fty_string; };
269   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_string ? true : TItemField::isBasedOn(aFieldType); };
270   // changelog support
271   #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
272   virtual uInt16 getDataCRC(uInt16 crc=0);
273   #endif
274   // assignment
275   virtual TItemField& operator=(TItemField &aItemField);
276   // access to normalized version of content
277   virtual void getAsNormalizedString(string &aString);
278   // access to field contents
279   #ifdef STREAMFIELD_SUPPORT
280   // - set blob loader proxy (ownership is passed to field)
281   void setBlobProxy(TBlobProxy *aBlobProxyP);
282   // - stream interface
283   virtual size_t getStreamSize(void);
284   virtual size_t readStream(void *aBuffer, size_t aMaxBytes);
285   virtual size_t writeStream(void *aBuffer, size_t aNumBytes);
286   virtual bool hasProxy(void) { return fBlobProxyP!=NULL; };
287   // - stream field proxies actually can have dependencies on a local ID
288   virtual void setParentLocalID(cAppCharP aParentLocalID) { if (fBlobProxyP) fBlobProxyP->setParentLocalID(aParentLocalID); };
289   #endif
290   // - as string
291   virtual void setAsString(cAppCharP aString) { DELETEPROXY; if (aString) fString=aString; else fString.erase(); stringWasAssigned(); };
292   virtual void setAsString(const string &aString) { DELETEPROXY; fString=aString; stringWasAssigned(); }; // works even if string contains NULs
293   virtual void setAsString(cAppCharP aString, size_t aLen);
294   virtual void getAsString(string &aString) { PULLFROMPROXY; aString=fString; };
295   virtual void appendToString(string &aString, size_t aMaxLen=0) { PULLFROMPROXY; if (aMaxLen) aString.append(fString,0,aMaxLen); else aString.append(fString); };
296   virtual cAppCharP getCStr(void) { PULLFROMPROXY; return fString.c_str(); } // string can return CStr (used for PalmOS optimization)
297   virtual size_t getStringSize(void); // can cause proxied values to be retrieved, so use with care with BLOBS
298   virtual void unAssign(void) { DELETEPROXY; fString.erase(); TItemField::unAssign(); };
299   // empty test
300   virtual bool isEmpty(void) { return isUnassigned() || getStringSize()==0; }
301   virtual void assignEmpty(void) { DELETEPROXY; fString.erase(); TItemField::assignEmpty(); };
302   // some string operations
303   // - append string
304   virtual void appendString(cAppCharP aString, size_t aMaxChars);
305   // - check if specified field is shortened version of this one
306   virtual bool isShortVers(TItemField &aItemField, sInt32 aOthersMax);
307   // - check if String is contained in value and returns position
308   virtual sInt16 findInString(cAppCharP aString, bool aCaseInsensitive=false);
309   // merge fields
310   virtual bool merge(TItemField &aItemField, const char aSep=0);
311   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem
312   // SYSYNC_NOT_COMPARABLE if not equal and no ordering known
313   virtual sInt16 compareWith(TItemField &aItemField, bool aCaseInsensitive=false);
314   #ifdef STREAMFIELD_SUPPORT
315   void pullFromProxy(void);
316   #endif
317   // debug support
318   #ifdef SYDEBUG
319   virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen);
320   #endif
321 protected:
322   virtual void stringWasAssigned(void) { fAssigned=true; }; // post-process string that was just assigned
323   #ifdef STREAMFIELD_SUPPORT
324   TBlobProxy *fBlobProxyP;
325   #endif
326   string fString;
327 }; // TStringField
328
329
330 // BLOB field. This is a string field but has many direct access functions
331 // disabled, contents should only be read using stream interface,
332 // comparing is not possible
333 class TBlobField: public TStringField
334 {
335   typedef TStringField inherited;
336 public:
337   TBlobField();
338   virtual ~TBlobField();
339   // access to type
340   virtual TItemFieldTypes getType(void) const { return fty_blob; };
341   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_blob ? true : TStringField::isBasedOn(aFieldType); };
342   // changelog support
343   //  Note: uses inherited implementation of TStringField
344   // assignment
345   virtual TItemField& operator=(TItemField &aItemField);
346   // - as string
347   virtual void getAsString(string &aString) { StringObjPrintf(aString,"<BLOB size=%ld>", long(getStringSize())); }; // must be read with stream interface
348   void getBlobAsString(string &aString) { TStringField::getAsString(aString); }; // must use this one to get as string
349   // - as Pointer/Data
350   void getBlobDataPtrSz(void *&aPtr, size_t &aSize) { aPtr=(void *)TStringField::getCStr(); aSize=TStringField::getStringSize(); };
351   void setBlobDataPtrSz(void *aPtr, size_t aSize) { setAsString((cAppCharP)aPtr, aSize); };
352   // - test
353   virtual bool isEmpty(void) { return isUnassigned(); } // do not test for empty string as this would cause BLOB to be read
354   // some string operations
355   // - check if specified field is shortened version of this one
356   virtual bool isShortVers(TItemField & /* aItemField */, sInt32 /* aOthersMax */) { return false; }; // cannot compare
357   // - check if String is contained in value and returns position
358   virtual sInt16 findInString(cAppCharP /* aString */, bool /* aCaseInsensitive */) { return -1; }; // cannot search
359   // merge fields
360   virtual bool merge(TItemField & /* aItemField */, const char /* aSep */=0) { return false; }; // cannot merge
361   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem
362   // SYSYNC_NOT_COMPARABLE if not equal and no ordering known
363   virtual sInt16 compareWith(TItemField & /* aItemField */, bool /* aCaseInsensitive */) { return SYSYNC_NOT_COMPARABLE; }; // cannot compare
364   // make contents and encoding/charset valid
365   void makeContentsValid(void) { PULLFROMPROXY; };
366   // debug support
367   #ifdef SYDEBUG
368   virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen); // show field contents as string for debug output
369   #endif
370   // extra info about BLOB contents
371   TEncodingTypes fHasEncoding;
372   TEncodingTypes fWantsEncoding;
373   TCharSets fCharset;
374 }; // TBlobField
375
376
377 // telephone number string field
378 // compares normalized version of number text (only +*# and digits)
379 class TTelephoneField: public TStringField
380 {
381   typedef TStringField inherited;
382 public:
383   TTelephoneField();
384   virtual ~TTelephoneField();
385   // access to type
386   virtual TItemFieldTypes getType(void) const { return fty_telephone; };
387   virtual TItemFieldTypes getCalcType(void) const { return fty_string; };
388   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_telephone ? true : TStringField::isBasedOn(aFieldType); };
389   // assignment
390   virtual TItemField& operator=(TItemField &aItemField) { return TStringField::operator=(aItemField); };
391   // access to normalized version of content
392   virtual void getAsNormalizedString(string &aString);
393   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem
394   // SYSYNC_NOT_COMPARABLE if not equal and no ordering known
395   virtual sInt16 compareWith(TItemField &aItemField, bool aCaseInsensitive=false);
396 }; // TTelephoneField
397
398
399 // multiline string field
400 // compares without any leading or trailing whitespace, linefeeds, controlchars
401 class TMultilineField: public TStringField
402 {
403   typedef TStringField inherited;
404 public:
405   TMultilineField();
406   virtual ~TMultilineField();
407   // access to type
408   virtual TItemFieldTypes getType(void) const { return fty_multiline; };
409   virtual TItemFieldTypes getCalcType(void) const { return fty_string; };
410   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_multiline ? true : TStringField::isBasedOn(aFieldType); };
411   // assignment
412   virtual TItemField& operator=(TItemField &aItemField) { return TStringField::operator=(aItemField); };
413   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem
414   // SYSYNC_NOT_COMPARABLE if not equal and no ordering known
415   virtual sInt16 compareWith(TItemField &aItemField, bool aCaseInsensitive=false);
416 }; // TMultilineField
417
418
419 // URL field
420 // normalizes URL (appends http:// if no protocol part specified)
421 class TURLField: public TStringField
422 {
423   typedef TStringField inherited;
424 public:
425   TURLField();
426   virtual ~TURLField();
427   // access to type
428   virtual TItemFieldTypes getType(void) const { return fty_url; };
429   virtual TItemFieldTypes getCalcType(void) const { return fty_string; };
430   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_url ? true : TStringField::isBasedOn(aFieldType); };
431   // assignment
432   virtual TItemField& operator=(TItemField &aItemField) { return TStringField::operator=(aItemField); };
433   //%%%virtual void setAsString(cAppCharP aString);
434   virtual void stringWasAssigned(void); // post-process string that was just assigned
435 }; // TURLField
436
437
438 class TTimestampField: public TItemField
439 {
440   typedef TItemField inherited;
441 public:
442   TTimestampField(GZones *aGZonesP);
443   virtual ~TTimestampField();
444   // access to type
445   virtual TItemFieldTypes getType(void) const { return fty_timestamp; };
446   virtual TItemFieldTypes getCalcType(void) const { return fty_integer; };
447   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_timestamp ? true : TItemField::isBasedOn(aFieldType); };
448   // assignment
449   virtual TItemField& operator=(TItemField &aItemField);
450   // changelog support
451   #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
452   virtual uInt16 getDataCRC(uInt16 crc=0);
453   #endif
454   // access to field contents
455   virtual void setAsString(cAppCharP aString);
456   virtual void getAsString(string &aString);
457   virtual fieldinteger_t getAsInteger(void) { return (fieldinteger_t)fTimestamp; };
458   virtual void setAsInteger(fieldinteger_t aInteger) { fTimestamp = (lineartime_t)aInteger; }; // does not touch the timecontext!
459   virtual void unAssign(void) { fTimestamp=noLinearTime; fTimecontext=TCTX_UNKNOWN; TItemField::unAssign(); };
460   // empty test (zero timestamp means empty, unless it is a duration)
461   virtual bool isEmpty(void) { return isUnassigned() || (fTimestamp==noLinearTime && !TCTX_IS_DURATION(fTimecontext)); }
462   virtual void assignEmpty(void) { fTimestamp=noLinearTime; fTimecontext=TCTX_UNKNOWN; TItemField::assignEmpty(); };
463   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem
464   // SYSYNC_NOT_COMPARABLE if not equal and no ordering known
465   virtual sInt16 compareWith(TItemField &aItemField, bool aCaseInsensitive=false);
466   // type specific access and utilities
467   /// @brief add a delta time to the timestamp
468   /// @param aDeltaTime[in] : delta time value in lineartime_t units
469   void addTime(lineartime_t aDeltaTime);
470   /// @brief get time context
471   /// @return time context
472   timecontext_t getTimeContext(void) { return fTimecontext; }
473   /// @brief get time context
474   /// @return minute offset east of UTC, returns 0 for floating timestamps (and UTC, of course)
475   sInt16 getMinuteOffset(void);
476   /// @brief test for floating time (=time not in a specified zone context)
477   /// @return true if context is TCTX_UNKNOWN
478   bool isFloating(void);
479   /// @brief make timestamp floating (i.e. remove time zone info from context)
480   void makeFloating(void);
481   /// @brief test for duration
482   /// @return true if context has TCTX_DURATION rendering flag set
483   bool isDuration(void);
484   /// @brief make timestamp a duration (also implies making it floating)
485   void makeDuration(void);
486   /// @brief get timestamp converted to a specified time context
487   /// @param aTargetContext[in] : requests output context for timestamp.
488   ///        Use TCTX_UNKNOWN to get timestamp as-is.
489   ///        If timestamp is floating, it will always be returned as-is
490   /// @param aActualContext[out] : if not NULL, the actual context of the returned value
491   ///        will be returned here. This might be another
492   //         context than specified with aTargetContext depending on floating/notime status.
493   /// @return timestamp in lineartime
494   lineartime_t getTimestampAs(timecontext_t aTargetContext, timecontext_t *aActualContext=NULL);
495   /// @brief get timestamp as ISO8601 string.
496   /// @param aISOString[out] : timestamp in ISO8601 format
497   /// @param aTargetContext[in] : requests output context for timestamp. Use TCTX_UNKNOWN to show timestamp as-is.
498   /// @param aShowWithZ[in] : if set and timezone is UTC, value will be shown with "Z" appended
499   /// @param aShowWithZone[in] : if set and timestamp is not floating, zone offset will be appended in +-xx:xx form
500   /// @param aExtFormat[in] : if set, ISO8601 extended format is used
501   /// @param aWithFracSecs[in] : if set, fractions of seconds will be shown (millisecond resolution)
502   void getAsISO8601(string &aISOString, timecontext_t aTargetContext, bool aShowWithZ=true, bool aShowWithZone=false, bool aExtFormat=false, bool aWithFracSecs=false);
503   /// @brief set timestamp value and context
504   /// @param aTimestamp[in] : timestamp to set
505   /// @param aTimecontext[in] : context to set
506   void setTimestampAndContext(lineartime_t aTimestamp, timecontext_t aTimecontext) { setTimestamp(aTimestamp); setTimeContext(aTimecontext); };
507   /// @brief set timestamp value without context
508   /// @param aTimestamp[in] : timestamp to set
509   void setTimestamp(lineartime_t aTimestamp) { fTimestamp=aTimestamp; fAssigned=true; };
510   /// @brief set timestamp value and context
511   /// @param aTimecontext[in] : context to set (timestamp will not be touched or converted)
512   virtual void setTimeContext(timecontext_t aTimecontext) { fTimecontext=aTimecontext; fAssigned=true; };
513   /// @brief move timestamp to specified context (i.e. convert the timestamp value from current to
514   ///        specified context). Floating timestamps cannot and will not be moved.
515   /// @param aNewcontext[in] : context to move timestamp to.
516   ///                          timestamp will be converted to represent the same point in time in the new context
517   /// @param aSetUnmovables : if set, non-movable timestamps will be just assigned the new context,
518   //                          that is floating timestamps will be bound to specified context or
519   //                          non-floating timestamps will be made floating if new context is TCTX_UNKNOWN
520   bool moveToContext(timecontext_t aNewcontext, bool aSetUnmovables=false);
521   /// @brief set timestamp from ISO8601 string.
522   /// @return true if successful
523   /// @param aISOString[in] : timestamp in ISO8601 basic or extended format, optionally including Z or +xx:xx zone specifier
524   /// @param aDefaultContext[in] : timezone context to use when ISO8601 does not specify a zone context or when aIgnoreZone is true
525   /// @param aIgnoreZone[in] : if set, timezone specification contained in ISO8601 is ignored. Resulting time context will be aDefaultContext
526   bool setAsISO8601(cAppCharP aISOString, timecontext_t aDefaultContext=TCTX_UNKNOWN, bool aIgnoreZone=false);
527   #ifdef EMAIL_FORMAT_SUPPORT
528   /// @brief get timestamp as RFC(2)822 style date
529   /// @param aRFC822String[out] : timestamp in RFC(2)822 format
530   /// @param aTargetContext[in] : requests output context for timestamp. Use TCTX_UNKNOWN to show timestamp as-is.
531   /// @param aShowWithZone[in] : if set and timestamp is not floating, zone offset will be shown
532   void getAsRFC822date(string &aRFC822String, timecontext_t aTargetContext, bool aShowWithZone=false);
533   /// @brief set timestamp as RFC(2)822 style date
534   /// @return true if successful
535   /// @param aRFC822String[in] : timestamp in RFC(2)822 format
536   /// @param aDefaultContext[in] : timezone context to use when RFC822 date does not specify a time zone
537   /// @param aIgnoreZone[in] : if set, timezone specification contained in input string is ignored. Resulting time context will be aDefaultContext
538   bool setAsRFC822date(cAppCharP aRFC822String, timecontext_t aDefaultContext=TCTX_UNKNOWN, bool aIgnoreZone=false);
539   #endif // EMAIL_FORMAT_SUPPORT
540   // debug support
541   #ifdef SYDEBUG
542   virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen);
543   #endif
544   GZones *getGZones(void) { return fGZonesP; };
545 protected:
546   lineartime_t fTimestamp;    // timestamp in context indicated by fTimecontext
547   timecontext_t fTimecontext; // context/options of timestamp
548   GZones *fGZonesP; // zones
549 }; // TTimestampField
550
551
552 class TDateField: public TTimestampField
553 {
554   typedef TTimestampField inherited;
555 public:
556   TDateField(GZones *aGZonesP);
557   virtual ~TDateField();
558   // assignment
559   virtual TItemField& operator=(TItemField &aItemField) { return TTimestampField::operator=(aItemField); };
560   // access to type
561   virtual TItemFieldTypes getType(void) const { return fty_date; };
562   virtual TItemFieldTypes getCalcType(void) const { return fty_integer; };
563   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_date ? true : TTimestampField::isBasedOn(aFieldType); };
564   // access to field contents
565   virtual void setAsString(cAppCharP aString);
566   virtual void getAsString(string &aString);
567   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem
568   // SYSYNC_NOT_COMPARABLE if not equal and no ordering known
569   virtual sInt16 compareWith(TItemField &aItemField, bool aCaseInsensitive=false);
570   /// @brief set timestamp value and context
571   /// @param aTimecontext[in] : context to set (timestamp will not be touched or converted)
572   virtual void setTimeContext(timecontext_t aTimecontext) { fTimecontext=aTimecontext | TCTX_DATEONLY; fAssigned=true; };
573 }; // TDateField
574
575
576 class TIntegerField: public TItemField
577 {
578   typedef TItemField inherited;
579 public:
580   TIntegerField();
581   virtual ~TIntegerField();
582   // access to type
583   virtual TItemFieldTypes getType(void) const { return fty_integer; };
584   virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_integer ? true : TItemField::isBasedOn(aFieldType); };
585   // assignment
586   virtual TItemField& operator=(TItemField &aItemField);
587   // changelog support
588   #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
589   virtual uInt16 getDataCRC(uInt16 crc=0);
590   #endif
591   // access to field contents
592   // - as string
593   virtual void setAsString(cAppCharP aString);
594   virtual void getAsString(string &aString);
595   virtual void unAssign(void) { fInteger=0; TItemField::unAssign(); };
596   // - as boolean (empty is false, zero value is false, other values are true)
597   virtual bool getAsBoolean(void) { return !(isEmpty() || fInteger==0); };
598   virtual void setAsBoolean(bool aBool) { fAssigned=true; fEmpty=false; if (aBool) fInteger=1; else fInteger=0; };
599   virtual fieldinteger_t getAsInteger(void);
600   virtual void setAsInteger(fieldinteger_t aInteger);
601   // empty test and assignment
602   virtual bool isEmpty(void) { return isUnassigned() || fEmpty; };
603   virtual void assignEmpty(void) { fInteger=0; fEmpty=true; TItemField::assignEmpty(); };
604   // compare: returns 0 if equal, 1 if this > aItem, -1 if this < aItem
605   // SYSYNC_NOT_COMPARABLE if not equal and no ordering known
606   virtual sInt16 compareWith(TItemField &aItemField, bool aCaseInsensitive=false);
607 protected:
608   fieldinteger_t fInteger; // integer value
609   bool fEmpty; // extra empty flag
610 }; // TIntegerField
611
612
613
614 // factory function
615 TItemField *newItemField(const TItemFieldTypes aType, GZones *aGZonesP, bool aAsArray=false);
616
617
618 #ifdef ENGINEINTERFACE_SUPPORT
619
620
621 // special flags coded into value ID
622 #define VALID_FLAG_TZNAME  0x010000
623 #define VALID_FLAG_TZOFFS  0x020000
624 #define VALID_FLAG_ARRSIZ  0x040000
625 #define VALID_FLAG_VALNAME 0x080000
626 #define VALID_FLAG_VALTYPE 0x100000
627 #define VALID_FLAG_NORM    0x200000
628 #define VALID_MASK_FID     0x00FFFF
629
630
631 // key for access to a item using the settings key API
632 class TItemFieldKey :
633   public TSettingsKeyImpl
634 {
635   typedef TSettingsKeyImpl inherited;
636 public:
637   TItemFieldKey(TEngineInterface *aEngineInterfaceP) :
638     inherited(aEngineInterfaceP),
639     fWritten(false)
640   {};
641
642   // get value's ID (e.g. internal index)
643   virtual sInt32 GetValueID(cAppCharP aName);
644
645   bool isWritten(void) { return fWritten; };
646 protected:
647
648   // get value's native type
649   virtual uInt16 GetValueType(sInt32 aID);
650
651   // get value
652   virtual TSyError GetValueInternal(
653     sInt32 aID, sInt32 aArrayIndex,
654     appPointer aBuffer, memSize aBufSize, memSize &aValSize
655   );
656
657   // set value
658   virtual TSyError SetValueInternal(
659     sInt32 aID, sInt32 aArrayIndex,
660     cAppPointer aBuffer, memSize aValSize
661   );
662
663   // flag that will be set on first write access
664   bool fWritten;
665
666   // abstract methods to actually access a TItemField
667   virtual sInt16 getFidFor(cAppCharP aName, stringSize aNameSz) = 0;
668   virtual TItemField *getBaseFieldFromFid(sInt16 aFid) = 0;
669   virtual bool getFieldNameFromFid(sInt16 aFid, string &aFieldName) { return false; /* no name */ };
670
671 private:
672   // utility
673   TItemField *getFieldFromFid(sInt16 aFid, sInt16 aRepOffset, bool aExistingOnly=false);
674
675
676 }; // TItemFieldKey
677
678 #endif // ENGINEINTERFACE_SUPPORT
679
680
681 } // namespace sysync
682
683 #endif  // ItemField_H
684
685 // eof