4 * Authors: Beat Forster
7 * SDK utility functions for
9 * - string alloc/dispose
12 * written in Std C, can be used in C++ as well
14 * Copyright (c) 2004-2011 by Synthesis AG + plan44.ch
19 #include "sync_dbapidef.h"
30 #include "android/log.h"
33 #define MyDB "SDK" /* local debug name */
34 #define Old_SDKversionMask 0xffff00ff /* Old mask for version comparison: Omit OS identifier */
35 #define maxmsglen 1024 /* Maximum string length for callback string */
39 /* This StdC module is independent from namespace "sysync" */
41 /* Get the plug-in's version/subversion number
42 * The plugin will contain a user defined <buildNumber> 0..255
43 * This version number is defined by Synthesis and should not be changed:
44 * The engine contains also a version number, and makes some comparisons.
46 CVersion Plugin_Version( short buildNumber )
51 #define SDK_VERSION_MAJOR 1 /* Release: V1.9.1, change this if you need troubles */
52 #define SDK_VERSION_MINOR 9
53 #define SDK_SUBVERSION 1
55 /* allowed range for the local build number */
56 if (buildNumber< 0) buildNumber= 0;
57 if (buildNumber>255) buildNumber= 255;
59 v= ((SDK_VERSION_MAJOR *P +
60 SDK_VERSION_MINOR)*P +
65 } /* Plugin_Version */
69 /* Check, if <version_feature> is supported in <currentVersion>
70 * NOTE: For the SyncML engine internally everything is supported
71 * This will be reflected with the fact that for 2.1.1.X
72 * the engine's version was always much much higher.
73 * Today the engine's version is equivalent to the SDK version.
75 bool Feature_Supported ( CVersion versionFeature, CVersion currentVersion )
77 CVersion v= currentVersion;
78 if (v<VP_NewBuildNumber) v= v & Old_SDKversionMask; /* avoid OS identifier comparison */
79 return v>=versionFeature;
80 } /* FeatureSupported */
83 /* Check, if <version_feature> is equivalent to <currentVersion>
85 bool Feature_SupportedEq( CVersion versionFeature, CVersion currentVersion )
87 CVersion v= currentVersion;
88 if (v<VP_NewBuildNumber) v= v & Old_SDKversionMask; /* avoid OS identifier comparison */
89 return v==versionFeature;
90 } /* FeatureSupportedEq */
94 /* Get platform identifier */
95 cAppCharP MyPlatform( void )
101 p= "PLATFORM:iPhone"; /* there is ONLY XCode, no need to mention that here */
102 #elif defined __MWERKS__
103 p= "PLATFORM:Mac (CodeWarrior)";
104 #elif defined __GNUC__
105 p= "PLATFORM:Mac (XCode)";
112 p= "PLATFORM:Windows (CodeWarrior)";
113 #elif defined _MSC_VER
114 p= "PLATFORM:Windows (VisualStudio)";
116 p= "PLATFORM:Windows";
121 p= "PLATFORM:Android";
126 /* elif **** for JAVA defined at the Java code ******** */
127 /* p= "PLATFORM:Java" */
129 /* elif **** for .net defined at the C# code ******** */
130 /* p= "PLATFORM:C#" */
133 p= "PLATFORM:unknown";
141 /* -------------------- string allocation/deallocation -------- */
142 /* Allocate local memory for a string */
143 appCharP StrAllocN( cAppCharP s, int n, bool fullSize )
150 if (n>len) n= len; /* never more than the length of <s> */
153 cp= (char*)malloc( n+1 );
155 strncpy( cp, s, n ); /* not yet NUL terminated !! */
162 /* Allocate local memory for a string */
163 appCharP StrAlloc ( cAppCharP s ) {
164 return StrAllocN( s, strlen( s ), true );
168 /* !Dispose a string which has been allocated with 'StrAlloc' */
169 void StrDispose( void* s ) {
170 if (s!=NULL) free( s );
175 /* ------------------ field operations ------------------------- */
176 bool Field( cAppCharP item, cAppCharP key, char** field )
180 char* t= (char*)item;
184 b= strstr( t,key ); if (!b) break; /* <key> available ? */
186 if (!e) e= strstr( b,"\n" ); /* get the end of this field */
188 if (b==item || *(b-1)=='\r'
192 if (*(b-1)==':') { /* correctly separated ? */
193 if (!e) *field= StrAlloc ( b ); /* either the rest */
194 else *field= StrAllocN( b, e-b, false ); /* or till next field */
195 return *field != NULL;
201 t= e+1; /* go to the next field */
209 bool SameField( cAppCharP item, cAppCharP key, cAppCharP field )
212 bool ok= Field( item, key, &vv ); /* get the <key> field */
214 ok= strcmp( field,vv )==0; /* and compare it with <field> */
215 StrDispose ( vv ); /* <vv> is no longer used now */
223 /* ------------------ callback system -------------------------------------- */
224 /* Initialize to safe defaults, useable for Std C as well
225 * NOTE: The current = latest available <callbackVersion> will be taken
227 static bool BadCB( void* aCallbackRef )
229 DB_Callback cb= aCallbackRef;
232 printf( "bad cb==NULL\n" ); return true;
235 if (cb->callbackRef!=cb) {
236 printf( "bad callbackRef %08lX <> %08lX\n",
237 (unsigned long)cb->callbackRef,
238 (unsigned long)cb ); return true;
241 return false; /* false= it's ok */
245 void NBlk( void* aCallbackRef )
248 DB_Callback cb= aCallbackRef;
249 if (!CB_OK( cb,2 )) return;
250 /*if ( BadCB( aCallbackRef )) return;*/
252 for (i=0; i<cb->lCount; i++) printf( " " );
257 static void BeginBlk( void* aCallbackRef, cAppCharP aTag,
259 cAppCharP aAttrText )
261 DB_Callback cb= aCallbackRef;
262 if ( BadCB( aCallbackRef )) return;
264 NBlk( cb ); printf( "<%s> %s %s\n", aTag, aDesc, aAttrText );
270 static void EndBlk( void* aCallbackRef, cAppCharP aTag )
272 DB_Callback cb= aCallbackRef;
273 if (!CB_OK( cb,2 )) return;
274 /*if ( BadCB( aCallbackRef )) return;*/
277 NBlk( cb ); printf( "</%s>\n", aTag );
282 static void EndThread( void* aCallbackRef )
284 DB_Callback cb= aCallbackRef;
285 if (!CB_OK( cb,2 )) return;
286 /*if ( BadCB( aCallbackRef )) return;*/
288 NBlk( cb ); printf( "=EndThread=\n" );
293 /* -------------------------------------------------------------------- */
294 void InitCallback( void* aCB, uInt16 aVersion, void* aRoutine, void* aExoticRoutine )
299 cb->callbackVersion= aVersion;
300 cb->callbackRef = cb; /* the callback pointer is the cb itself here */
303 cb->debugFlags = 0; /* debug disable so far */
304 cb->DB_DebugPuts = aRoutine;
306 if (aExoticRoutine) cb->debugFlags= DBG_PLUGIN_ALL;
307 else cb->debugFlags= DBG_PLUGIN_INT + DBG_PLUGIN_DB;
310 cb->cContext= 0; /* contexts */
316 cb->DB_DebugBlock = BeginBlk; /* level 2 */
317 cb->DB_DebugEndBlock = EndBlk;
318 cb->DB_DebugEndThread= EndThread;
323 cb->DB_DebugExotic = aExoticRoutine; /* level 3 */
326 cb->allow_DLL_legacy= 0; /* false */ /* level 4 */
329 cb->allow_DLL = 0; /* false */ /* level 5 */
332 cb->reserved1= 0; /* level 6 */
339 cb->thisCB = cb; /* level 7 */
344 cb->thisBase = NULL; /* level 8 */
348 cb->ui.SetStringMode = NULL;
349 cb->ui.InitEngineXML = NULL;
350 cb->ui.InitEngineFile = NULL;
351 cb->ui.InitEngineCB = NULL;
353 cb->ui.OpenSession = NULL;
354 cb->ui.OpenSessionKey = NULL;
355 cb->ui.SessionStep = NULL;
356 cb->ui.GetSyncMLBuffer = NULL;
357 cb->ui.RetSyncMLBuffer = NULL;
358 cb->ui.ReadSyncMLBuffer = NULL;
359 cb->ui.WriteSyncMLBuffer= NULL;
360 cb->ui.CloseSession = NULL;
362 cb->ui.OpenKeyByPath = NULL;
363 cb->ui.OpenSubkey = NULL;
364 cb->ui.DeleteSubkey = NULL;
365 cb->ui.GetKeyID = NULL;
366 cb->ui.SetTextMode = NULL;
367 cb->ui.SetTimeMode = NULL;
368 cb->ui.CloseKey = NULL;
370 cb->ui.GetValue = NULL;
371 cb->ui.GetValueByID = NULL;
372 cb->ui.GetValueID = NULL;
373 cb->ui.SetValue = NULL;
374 cb->ui.SetValueByID = NULL;
378 cb->SDK_Interface_size= sizeof(SDK_Interface_Struct); /* level 9 */
380 cb->dt.StartDataRead = NULL; /* tunnel callback functions, for internal use only */
381 cb->dt.ReadNextItem = NULL;
382 cb->dt.ReadItem = NULL;
383 cb->dt.EndDataRead = NULL;
385 cb->dt.StartDataWrite = NULL;
386 cb->dt.InsertItem = NULL;
387 cb->dt.UpdateItem = NULL;
388 cb->dt.MoveItem = NULL;
389 cb->dt.DeleteItem = NULL;
390 cb->dt.EndDataWrite = NULL;
393 if (CB_OK( cb,11 )) {
394 cb->dt.DisposeObj = NULL;
396 cb->dt.ReadNextItemAsKey= NULL;
397 cb->dt.ReadItemAsKey = NULL;
398 cb->dt.InsertItemAsKey = NULL;
399 cb->dt.UpdateItemAsKey = NULL;
405 /* Initialize to safe defaults and "CB_PurePrintf", usable for Std C as well */
406 /* Normal debug output */
407 void InitCallback_Pure ( void* aCB, uInt16 aVersion ) {
408 InitCallback ( aCB, aVersion, CB_PurePrintf, NULL );
409 } /* InitCallback_Pure */
412 /* Initialize to safe defaults and "CB_PurePrintf", usable for Std C as well */
413 /* Normal and exotic debug output */
414 void InitCallback_Exotic( void* aCB, uInt16 aVersion ) {
415 InitCallback ( aCB, aVersion, CB_PurePrintf, CB_PurePrintf );
416 } /* InitCallback_Exotic */
420 /* The <aRoutine> for 'InitCallback', when a simple "printf" is
421 * requested for the callback.
423 * Routine must be defined as
424 * typedef void (*DB_DebugPuts_Func)( void *aCallbackRef, cAppCharP aText );
426 void CB_PurePrintf( void* aCB, cAppCharP aText )
429 if (!CB_OK( cb,2 )) return;
430 /*if ( BadCB( aCB )) return;*/
432 NBlk( cb ); printf( "%s\n", aText );
433 } /* CB_PurePrintf */
437 /* Get the size of the SDK_Interface_Struct to be copied */
438 TSyError SDK_Size( void* aCB, uInt32 *sSize )
440 TSyError err= LOCERR_OK;
441 DB_Callback cb = aCB;
444 /* try to get the SDK_Interface_Struct <sSize> of the calling engine */
445 if (cb->callbackVersion< SDK_Interface_Struct_V8) { err= LOCERR_TOOOLD; break; }
446 if (cb->callbackVersion==SDK_Interface_Struct_V8) *sSize= SDK_Interface_Struct_V8_Size;
447 else *sSize= cb->SDK_Interface_size;
449 /* but it must neither be smaller than version 8 size nor larger than the own size */
450 if (*sSize< SDK_Interface_Struct_V8_Size) { err= LOCERR_TOOOLD; break; }
451 if (*sSize>sizeof(SDK_Interface_Struct)) *sSize= sizeof(SDK_Interface_Struct);
454 /*printf( "sizeof=%d sSize=%d err=%d\n", sizeof(SDK_Interface_Struct), *sSize, err );*/
460 /* ---------- debug output ----------------------------------- */
461 /* prints directly to the screen */
462 static void ConsolePuts( cAppCharP msg )
465 __android_log_write( ANDROID_LOG_DEBUG, "ConsolePuts", msg );
467 printf( "%s\n", msg );
472 #if !defined(SYSYNC_ENGINE) && !defined(UIAPI_LINKED)
473 /* the Synthesis SyncML engine has its own implementation */
474 /* => use this code in SDK only */
475 void ConsoleVPrintf( cAppCharP format, va_list args )
478 char msg[ maxmsglen ];
479 msg[ 0 ]= '\0'; /* start with an empty <msg> */
480 vsnprintf ( msg, maxmsglen,format,args ); /* assemble the message string */
481 ConsolePuts( msg ); /* write the string */
483 } /* ConsoleVPrintf */
485 void ConsolePrintf( cAppCharP text, ... )
488 va_start ( args,text );
489 ConsoleVPrintf( text,args );
491 } /* ConsolePrintf */
495 /* Get the callback version of <aCB> */
496 uInt16 CB_Version( void* aCB )
499 if (cb) return cb->callbackVersion;
504 /* Check, if <aCB> structure is at least <minVersion> */
505 bool CB_OK( void* aCB, uInt16 minVersion ) { return CB_Version( aCB )>=minVersion; }
507 /* Check, if <aCB> structure supports UI callback (cbVersion>=6) */
508 /* static bool CB_UI( void* aCB ) { return CB_OK( aCB,6 ); } */
510 /* Check, if <aCB> structure supports <gContext> (cbVersion>=8) and <gContext> <> 0 */
511 bool CB_gContext ( void* aCB )
514 return CB_OK ( aCB,8 ) && cb->gContext!=0;
518 /* Check, if <aCB> structure supports CA_SubSytem (cbVersion>=10) */
519 bool CB_SubSystem( void* aCB ) { return CB_OK( aCB,10 ); }
522 /* Check, if <aCB> structure is at least <minVersion> and DBG_PLUGIN_DB is set */
523 bool DB_OK( void* aCB, uInt16 minVersion )
525 DB_Callback cb= aCB; /* at least one flag must be set */
526 return CB_OK( aCB,minVersion ) && (DBG_PLUGIN_DB & cb->debugFlags)!=DBG_PLUGIN_NONE;
530 /* Check, if <aCB> structure is at least <minVersion> and one of <debugFlags> is set */
531 bool Callback_OK( void* aCB, uInt16 minVersion, uInt16 debugFlags )
533 DB_Callback cb= aCB; /* at least one flag must be set */
534 return CB_OK( aCB,minVersion ) && (debugFlags & cb->debugFlags)!=DBG_PLUGIN_NONE;
539 /* Normal callback output of <text> */
540 void CallbackPuts( void* aCB, cAppCharP text )
543 if (!Callback_OK( aCB, 1,DBG_PLUGIN_ALL )) return;
545 if (cb->DB_DebugPuts)
546 cb->DB_DebugPuts( cb->callbackRef, text );
551 /* Exotic callback output of <text> */
552 static void CallbackExotic( void* aCB, cAppCharP text )
555 if (!Callback_OK( aCB, 3,DBG_PLUGIN_ALL )) { CallbackPuts( aCB,text ); return; }
557 if (cb->DB_DebugExotic)
558 cb->DB_DebugExotic( cb->callbackRef, text );
559 } /* CallbackExotic */
563 static void CallbackVPrintf( DB_Callback aCB, cAppCharP format, va_list args, uInt16 outputMode )
570 char message[ maxmsglen ];
571 char* ptr= (char*)&message;
574 // need a copy for vasprintf() call
579 message[ 0 ]= '\0'; /* start with an empty <msg> */
580 vsnprintf( message, maxmsglen, format,args ); /* assemble the message string */
583 isMax= strlen(message)==maxmsglen-1;
584 if (isMax && vasprintf( &ptr, format, copy ) != -1) {};
588 switch (outputMode) {
589 case OutputNorm : CallbackPuts ( aCB, ptr ); break;
590 /* case OutputExoticBefore: */
591 /* case OutputExoticAfter : */
592 case OutputExotic : CallbackExotic( aCB, ptr ); break;
594 case OutputExoticBefore:
595 case OutputExoticAfter :
597 case OutputAfter : NBlk ( (void*)aCB );
598 ConsolePuts ( ptr ); break;
602 if (isMax) free( ptr );
605 } /* CallbackVPrintf */
609 void DEBUG_( void* aCB, cAppCharP text, ... )
614 if (Callback_OK( aCB, 1,DBG_PLUGIN_ALL )) {
615 va_start ( args,text );
616 CallbackVPrintf( aCB, text,args, false );
625 void DoDEBUG( void* aCB, uInt16 outputMode, bool withIntro,
627 cAppCharP routine, va_list args,
630 cAppCharP dbIntro= "";
637 if (*routine!='\0') {
638 if (withIntro) { dbIntro= "##### ";
639 if (outputMode==OutputBefore ||
640 outputMode==OutputExoticBefore) dbIntro= ">>>>> ";
641 if (outputMode==OutputAfter ||
642 outputMode==OutputExoticAfter) dbIntro= "<<<<< ";
649 #elif defined SDK_DLL
655 if (*text!='\0') p= ": ";
658 size= strlen(dbIntro) + strlen(id) +
659 strlen(isX) + strlen(routine) +
660 strlen(p) + strlen(text) + 1;
662 s= (char*)malloc( size );
664 sprintf( s, "%s%s%s%s%s%s", dbIntro,id,isX,routine,p,text );
665 CallbackVPrintf( aCB, s,args, outputMode );
673 /* ------------------------------------------------------------------------------------- */
674 void DEBUG_Call( void* aCB, uInt16 debugFlags,
677 cAppCharP text, ... )
682 if (Callback_OK( aCB, 1,debugFlags )) {
683 va_start ( args,text );
684 DoDEBUG( aCB, false,true, ident,routine, args,text );
692 void DEBUG_INT( void* aCB, cAppCharP ident,
694 cAppCharP text, ... )
698 if (Callback_OK( aCB, 1,DBG_PLUGIN_INT )) {
699 va_start ( args,text );
700 DoDEBUG( aCB, false,true, ident,routine, args,text );
708 void DEBUG_DB( void* aCB, cAppCharP ident,
710 cAppCharP text, ... )
714 if (Callback_OK( aCB, 1,DBG_PLUGIN_DB )) {
715 va_start ( args,text );
716 DoDEBUG( aCB, false,true, ident,routine, args,text );
724 /* ------------------------------------------------------------------------------------- */
725 void DEBUG_Exotic_INT( void* aCB, cAppCharP ident,
727 cAppCharP text, ... )
731 if (Callback_OK( aCB, 1,DBG_PLUGIN_INT ) &&
732 Callback_OK( aCB, 1,DBG_PLUGIN_EXOT )) {
733 va_start ( args,text );
734 DoDEBUG( aCB, true,true, ident,routine, args,text );
738 } /* DEBUG_Exotic_INT */
742 void DEBUG_Exotic_DB( void* aCB, cAppCharP ident,
744 cAppCharP text, ... )
748 if (Callback_OK( aCB, 1,DBG_PLUGIN_EXOT )) {
749 va_start ( args,text );
750 DoDEBUG( aCB, true,true, ident,routine, args,text );
754 } /* DEBUG_Exotic_DB */
758 void DEBUG_Exotic_DBW( void* aCB, cAppCharP ident,
760 cAppCharP text, ... )
764 if (Callback_OK( aCB, 1,DBG_PLUGIN_EXOT )) {
765 va_start ( args,text );
766 DoDEBUG( aCB, true,false,ident,routine, args,text );
770 } /* DEBUG_Exotic_DBW */
774 /* ------------------------------------------------------------------------------------- */
775 /* Start of sub block */
776 void DEBUG_Block( void* aCB, cAppCharP aTag,
778 cAppCharP aAttrText )
780 /* callbackVersion >= 2 support for blocks */
783 if (Callback_OK( aCB, 2,DBG_PLUGIN_ALL ) &&
785 cb->DB_DebugBlock( cb->callbackRef, aTag,aDesc,aAttrText );
787 DEBUG_DB( aCB, MyDB, aTag, "%s (%s) BEGIN", aAttrText,aDesc );
793 /* End of sub block */
794 void DEBUG_EndBlock( void* aCB, cAppCharP aTag )
798 if (Callback_OK( aCB, 2,DBG_PLUGIN_ALL ) &&
799 cb->DB_DebugEndBlock)
800 cb->DB_DebugEndBlock( cb->callbackRef, aTag );
802 DEBUG_DB( aCB, MyDB, aTag, "END" );
804 } /* DEBUG_EndBlock */
808 void DEBUG_EndThread( void* aCB )
812 if (Callback_OK( aCB, 2,DBG_PLUGIN_ALL ) &&
813 cb->DB_DebugEndThread)
814 cb->DB_DebugEndThread( cb->callbackRef );
816 DEBUG_DB( aCB, MyDB, "THREAD", "END" );
818 } /* DEBUG_EndThread */