4 * Author: Lukas Zeller (luz@plan44.ch)
7 * Abstract class, holds a single field value
8 * TStringField, TIntegerField, TTelephoneField, TTimeStampField etc.
9 * Implementations of field types
11 * Copyright (c) 2001-2011 by Synthesis AG + plan44.ch
13 * 2001-08-08 : luz : created
21 #include "sysync_globs.h"
22 #include "sysync_utils.h"
24 #include "engineinterface.h"
28 #ifdef ARRAYFIELD_SUPPORT
34 extern cAppCharP const ItemFieldTypeNames[numFieldTypes];
36 extern const TPropDataTypes devInfPropTypes[numFieldTypes];
40 typedef sInt64 fieldinteger_t;
41 #define StrToFieldinteger(s,i) StrToLongLong(s,i)
43 typedef sInt32 fieldinteger_t;
44 #define StrToFieldinteger(s,i) StrToLong(s,i)
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)
51 // basically abstract class, but can be used to represent EMPTY and ASSIGNED values
56 virtual ~TItemField();
57 #ifdef ARRAYFIELD_SUPPORT
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
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(); }
71 #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
72 virtual uInt16 getDataCRC(uInt16 crc=0) { return crc; }; // base class is always empty
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()); };
91 virtual bool hasProxy(void) { return false; }; // normal fields don't have a proxy
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(); };
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; };
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; };
128 virtual TItemField& operator=(TItemField &aItemField);
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);
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; };
145 virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen); // show field contents as string for debug output
150 #ifdef STREAMFIELD_SUPPORT
156 typedef TItemField *TItemFieldP;
160 #ifdef ARRAYFIELD_SUPPORT
162 typedef std::vector<TItemField *> TFieldArray;
164 // array field, contains a list of fields of TItemFields
165 class TArrayField : public TItemField
167 typedef TItemField inherited;
169 TArrayField(TItemFieldTypes aLeafFieldType, GZones *aGZonesP);
170 virtual ~TArrayField();
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
176 #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
177 virtual uInt16 getDataCRC(uInt16 crc=0);
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
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; };
192 virtual void assignEmpty(void) { unAssign(); fAssigned = true; }; // assigning emptyness must make isAssigned true!
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);
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);
206 virtual size_t StringObjFieldAppend(string &s, uInt16); // show field contents as string for debug output
209 // type of contained leaf fields
210 TItemFieldTypes fLeafFieldType;
211 // first field, is instantiated with array to allow type comparisons
212 TItemField *fFirstField;
215 // actual field vector
221 #ifndef STREAMFIELD_SUPPORT
222 #define PULLFROMPROXY
224 #define PROXYINSTALLED false
226 #define PULLFROMPROXY pullFromProxy()
227 #define DELETEPROXY setBlobProxy(NULL)
228 #define PROXYINSTALLED (fBlobProxyP!=NULL)
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
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 */ };
248 void link(void) { fUsage++; };
249 static void unlink(TBlobProxy *&aProxyP) { if (aProxyP) { if (--(aProxyP->fUsage) == 0) delete aProxyP; aProxyP=NULL; } };
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
262 typedef TItemField inherited;
263 friend class TBlobProxy;
266 virtual ~TStringField();
268 virtual TItemFieldTypes getType(void) const { return fty_string; };
269 virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_string ? true : TItemField::isBasedOn(aFieldType); };
271 #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
272 virtual uInt16 getDataCRC(uInt16 crc=0);
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); };
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(); };
300 virtual bool isEmpty(void) { return isUnassigned() || getStringSize()==0; }
301 virtual void assignEmpty(void) { DELETEPROXY; fString.erase(); TItemField::assignEmpty(); };
302 // some string operations
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);
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);
319 virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen);
322 virtual void stringWasAssigned(void) { fAssigned=true; }; // post-process string that was just assigned
323 #ifdef STREAMFIELD_SUPPORT
324 TBlobProxy *fBlobProxyP;
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
335 typedef TStringField inherited;
338 virtual ~TBlobField();
340 virtual TItemFieldTypes getType(void) const { return fty_blob; };
341 virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_blob ? true : TStringField::isBasedOn(aFieldType); };
343 // Note: uses inherited implementation of TStringField
345 virtual TItemField& operator=(TItemField &aItemField);
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
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); };
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
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; };
368 virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen); // show field contents as string for debug output
370 // extra info about BLOB contents
371 TEncodingTypes fHasEncoding;
372 TEncodingTypes fWantsEncoding;
377 // telephone number string field
378 // compares normalized version of number text (only +*# and digits)
379 class TTelephoneField: public TStringField
381 typedef TStringField inherited;
384 virtual ~TTelephoneField();
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); };
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
399 // multiline string field
400 // compares without any leading or trailing whitespace, linefeeds, controlchars
401 class TMultilineField: public TStringField
403 typedef TStringField inherited;
406 virtual ~TMultilineField();
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); };
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
420 // normalizes URL (appends http:// if no protocol part specified)
421 class TURLField: public TStringField
423 typedef TStringField inherited;
426 virtual ~TURLField();
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); };
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
438 class TTimestampField: public TItemField
440 typedef TItemField inherited;
442 TTimestampField(GZones *aGZonesP);
443 virtual ~TTimestampField();
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); };
449 virtual TItemField& operator=(TItemField &aItemField);
451 #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
452 virtual uInt16 getDataCRC(uInt16 crc=0);
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
542 virtual size_t StringObjFieldAppend(string &s, uInt16 aMaxStrLen);
544 GZones *getGZones(void) { return fGZonesP; };
546 lineartime_t fTimestamp; // timestamp in context indicated by fTimecontext
547 timecontext_t fTimecontext; // context/options of timestamp
548 GZones *fGZonesP; // zones
549 }; // TTimestampField
552 class TDateField: public TTimestampField
554 typedef TTimestampField inherited;
556 TDateField(GZones *aGZonesP);
557 virtual ~TDateField();
559 virtual TItemField& operator=(TItemField &aItemField) { return TTimestampField::operator=(aItemField); };
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; };
576 class TIntegerField: public TItemField
578 typedef TItemField inherited;
581 virtual ~TIntegerField();
583 virtual TItemFieldTypes getType(void) const { return fty_integer; };
584 virtual bool isBasedOn(TItemFieldTypes aFieldType) const { return aFieldType==fty_integer ? true : TItemField::isBasedOn(aFieldType); };
586 virtual TItemField& operator=(TItemField &aItemField);
588 #if defined(CHECKSUM_CHANGELOG) && !defined(RECORDHASH_FROM_DBAPI)
589 virtual uInt16 getDataCRC(uInt16 crc=0);
591 // access to field contents
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);
608 fieldinteger_t fInteger; // integer value
609 bool fEmpty; // extra empty flag
615 TItemField *newItemField(const TItemFieldTypes aType, GZones *aGZonesP, bool aAsArray=false);
618 #ifdef ENGINEINTERFACE_SUPPORT
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
631 // key for access to a item using the settings key API
632 class TItemFieldKey :
633 public TSettingsKeyImpl
635 typedef TSettingsKeyImpl inherited;
637 TItemFieldKey(TEngineInterface *aEngineInterfaceP) :
638 inherited(aEngineInterfaceP),
642 // get value's ID (e.g. internal index)
643 virtual sInt32 GetValueID(cAppCharP aName);
645 bool isWritten(void) { return fWritten; };
648 // get value's native type
649 virtual uInt16 GetValueType(sInt32 aID);
652 virtual TSyError GetValueInternal(
653 sInt32 aID, sInt32 aArrayIndex,
654 appPointer aBuffer, memSize aBufSize, memSize &aValSize
658 virtual TSyError SetValueInternal(
659 sInt32 aID, sInt32 aArrayIndex,
660 cAppPointer aBuffer, memSize aValSize
663 // flag that will be set on first write access
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 */ };
673 TItemField *getFieldFromFid(sInt16 aFid, sInt16 aRepOffset, bool aExistingOnly=false);
678 #endif // ENGINEINTERFACE_SUPPORT
681 } // namespace sysync
683 #endif // ItemField_H