2012-10-30 03:52:39 +00:00
# include "cmPrefix.h"
# include "cmGlobal.h"
# include "cmRpt.h"
# include "cmErr.h"
# include "cmCtx.h"
# include "cmMem.h"
# include "cmMallocDebug.h"
# include "cmLinkedHeap.h"
# include "cmFileSys.h"
# include "cmText.h"
# include "cmJson.h"
# include "cmPrefs.h"
cmPrH_t cmPrNullHandle = cmSTATIC_NULL_HANDLE ;
typedef struct cmPrCb_str
{
cmPrefsOnChangeFunc_t cbFunc ;
void * cbDataPtr ;
struct cmPrCb_str * linkPtr ;
} cmPrCb_t ;
// Link record used by cmPrNode_t to form the
// path labels for each pref. node.
typedef struct cmPrPath_str
{
const cmChar_t * label ;
struct cmPrPath_str * parentPtr ;
} cmPrPath_t ;
// Every pair in the prefs JSON tree is given a unique id.
// The 'path' chain forms a path of pair labels which names the variable.
typedef struct cmPrNode_str
{
unsigned id ; // unique id assigned to this pref node
cmJsonNode_t * nodePtr ; // pointer to the JSON value for this pref node
cmPrPath_t * pathPtr ; // pointer to the path label chain for this node
struct cmPrNode_str * linkPtr ; // link used to form the pref. node chain
} cmPrNode_t ;
typedef struct
{
cmErr_t err ; //
cmJsonH_t jsH ; // json tree
cmLHeapH_t lhH ; // linked heap handle
cmChar_t * fn ; // default filename
bool dirtyFl ; //
cmPrCb_t * cbChainPtr ; // callback record linked list
cmPrNode_t * idChainPtr ; //
unsigned id ; // next JSON node id
cmChar_t * pathBuf ;
2013-03-27 19:12:26 +00:00
cmChar_t * pathPrefixStr ;
2012-10-30 03:52:39 +00:00
} cmPr_t ;
cmPr_t * _cmPrefsHandleToPtr ( cmPrH_t h )
{
assert ( h . h ! = NULL ) ;
return ( cmPr_t * ) h . h ;
}
cmPrNode_t * _cmPrefsIdToNodePtr ( cmPr_t * p , unsigned id , bool reportErrFl )
{
if ( id = = cmInvalidId )
{
cmErrMsg ( & p - > err , kInvalidIdPrRC , " No preference variables can use the id:%i. " , id ) ;
return NULL ;
}
cmPrNode_t * np = p - > idChainPtr ;
for ( ; np ! = NULL ; np = np - > linkPtr )
if ( np - > id = = id )
return np ;
if ( reportErrFl )
cmErrMsg ( & p - > err , kVarNotFoundPrRC , " The preference variable associated with id:%i does not exist. " , id ) ;
return NULL ;
}
unsigned _cmPrefsCalcNextAvailId ( cmPr_t * p )
{
while ( _cmPrefsIdToNodePtr ( p , p - > id , false ) ! = NULL )
+ + p - > id ;
return p - > id ;
}
cmPrNode_t * _cmPrefsCreateNode ( cmPr_t * p , const cmJsonNode_t * jsPairNodePtr , cmPrPath_t * parentPathPtr )
{
assert ( jsPairNodePtr - > typeId = = kPairTId ) ;
cmPrNode_t * np = cmLHeapAllocZ ( p - > lhH , sizeof ( cmPrNode_t ) ) ;
np - > id = cmInvalidId ;
np - > pathPtr = cmLHeapAllocZ ( p - > lhH , sizeof ( cmPrPath_t ) ) ;
np - > pathPtr - > label = jsPairNodePtr - > u . childPtr - > u . stringVal ;
np - > pathPtr - > parentPtr = parentPathPtr ;
np - > nodePtr = jsPairNodePtr - > u . childPtr - > siblingPtr ;
np - > linkPtr = p - > idChainPtr ;
p - > idChainPtr = np ;
// object and pair nodes cannot be returned as pref values - so do not give them id's
if ( cmJsonIsObject ( np - > nodePtr ) = = false & & cmJsonIsPair ( np - > nodePtr ) = = false )
np - > id = _cmPrefsCalcNextAvailId ( p ) ;
return np ;
}
void _cmPrefsBuildIdList ( cmPr_t * p , const cmJsonNode_t * jsnPtr , cmPrPath_t * parentPathPtr )
{
assert ( jsnPtr ! = NULL ) ;
if ( jsnPtr - > typeId = = kPairTId )
{
cmPrNode_t * np = _cmPrefsCreateNode ( p , jsnPtr , parentPathPtr ) ;
_cmPrefsBuildIdList ( p , jsnPtr - > u . childPtr - > siblingPtr , np - > pathPtr ) ;
}
else
if ( cmJsonChildCount ( jsnPtr ) )
{
const cmJsonNode_t * np = jsnPtr - > u . childPtr ;
for ( ; np ! = NULL ; np = np - > siblingPtr )
_cmPrefsBuildIdList ( p , np , parentPathPtr ) ;
}
}
void _cmPrefsInstallCallback ( cmPr_t * p , cmPrefsOnChangeFunc_t cbFunc , void * cbDataPtr )
{
cmPrCb_t * nrp = cmLHeapAllocZ ( p - > lhH , sizeof ( cmPrCb_t ) ) ;
nrp - > cbFunc = cbFunc ;
nrp - > cbDataPtr = cbDataPtr ;
cmPrCb_t * cp = p - > cbChainPtr ;
// if the cb chain is empty ...
if ( cp = = NULL )
p - > cbChainPtr = nrp ; // ... make the new cb the first on the chain
else
{
// ... otherwise add the new cb to the end of the cb chain
while ( cp - > linkPtr ! = NULL )
cp = cp - > linkPtr ;
cp - > linkPtr = nrp ;
}
}
cmPrRC_t _cmPrefsFinalize ( cmPr_t * p )
{
cmPrRC_t rc = kOkPrRC ;
if ( cmLHeapIsValid ( p - > lhH ) )
cmLHeapDestroy ( & p - > lhH ) ;
if ( cmJsonIsValid ( p - > jsH ) )
if ( cmJsonFinalize ( & p - > jsH ) ! = kOkJsRC )
rc = cmErrMsg ( & p - > err , kJsonFailPrRC , " JSON finalization failed. " ) ;
cmMemPtrFree ( & p - > pathBuf ) ;
cmMemFree ( p ) ;
return rc ;
}
// Convert 'pathString' to a sequence of zero terminated sub-strings.
// The character string returned from this function must be released with a
// call to cmMemFree()
2013-03-27 19:12:26 +00:00
cmChar_t * _cmPrefsCreatePathStr ( cmPr_t * p , const cmChar_t * pathString , int * cnt )
2012-10-30 03:52:39 +00:00
{
assert ( pathString ! = NULL ) ;
2013-03-27 19:12:26 +00:00
cmChar_t * pathStr ;
2012-10-30 03:52:39 +00:00
// duplicate the path string
2013-03-27 19:12:26 +00:00
if ( p - > pathPrefixStr = = NULL )
pathStr = cmMemAllocStr ( pathString ) ;
else
pathStr = cmTsPrintfP ( NULL , " %s/%s " , p - > pathPrefixStr , pathString ) ;
2012-10-30 03:52:39 +00:00
int i = 0 ;
int n = 1 ;
for ( i = 0 ; pathStr [ i ] ; + + i )
if ( pathStr [ i ] = = ' / ' )
{
pathStr [ i ] = 0 ;
+ + n ;
}
* cnt = n ;
return pathStr ;
}
unsigned _cmPrefsId ( cmPr_t * p , const cmChar_t * pathStr , bool reportErrFl )
{
int n = 1 ;
int i ;
unsigned retId = cmInvalidId ;
2013-03-27 19:12:26 +00:00
cmChar_t * path = _cmPrefsCreatePathStr ( p , pathStr , & n ) ;
2012-10-30 03:52:39 +00:00
const cmChar_t * pathArray [ n ] ;
const cmChar_t * cp = path ;
// store path parts in reverse order - because this
// is the way the node sees the path
for ( i = n - 1 ; i > = 0 ; - - i )
{
pathArray [ i ] = cp ;
cp + = strlen ( cp ) + 1 ;
}
const cmPrNode_t * np = p - > idChainPtr ;
// go down the id chain
for ( ; retId = = cmInvalidId & & np ! = NULL ; np = np - > linkPtr )
{
unsigned i = 0 ;
const cmPrPath_t * pp = np - > pathPtr ;
// go down the path chain from leaf to root
while ( strcmp ( pp - > label , pathArray [ i ] ) = = 0 )
{
+ + i ;
pp = pp - > parentPtr ;
// if the match is complete
if ( i = = n & & pp = = NULL )
{
retId = np - > id ;
break ;
}
}
}
if ( retId = = cmInvalidId & & reportErrFl )
cmErrMsg ( & p - > err , kVarNotFoundPrRC , " The preference variable '%s' was not found. " , pathStr ) ;
cmMemFree ( path ) ;
return retId ;
}
cmPrNode_t * _cmPrefsPathToNodePtr ( cmPr_t * p , const cmChar_t * pathStr , bool reportErrFl )
{
unsigned id ;
if ( ( id = _cmPrefsId ( p , pathStr , reportErrFl ) ) = = cmInvalidId )
return NULL ;
return _cmPrefsIdToNodePtr ( p , id , reportErrFl ) ;
}
2013-03-27 19:12:26 +00:00
cmPrRC_t cmPrefsInit ( cmCtx_t * ctx , cmPrH_t * prefsH , const cmChar_t * fnName , const cmChar_t * fnExt , cmPrefsOnChangeFunc_t cbFunc , void * cbDataPtr , const cmChar_t * pathPrefixStr )
2012-12-04 01:16:41 +00:00
{
cmPrRC_t rc = kOkPrRC ;
const cmChar_t * prefsDir = cmFsPrefsDir ( ) ;
const cmChar_t * prefsFn = NULL ;
if ( fnName = = NULL )
fnName = cmFsAppName ( ) ;
if ( fnExt = = NULL )
fnExt = " .js " ;
// if the prefs directory does not exist then create it
if ( cmFsIsDir ( prefsDir ) = = false )
{
if ( cmFsMkDir ( prefsDir ) ! = kOkFsRC )
{
rc = cmErrMsg ( & ctx - > err , kFileSysFailPrRC , " The preference directory '%s' could not be created. " , prefsDir ) ;
goto errLabel ;
}
}
// create the preference file name
if ( ( prefsFn = cmFsMakeFn ( prefsDir , fnName , fnExt , NULL ) ) = = NULL )
{
rc = cmErrMsg ( & ctx - > err , kFileSysFailPrRC , " The preference file name could not be formed. " ) ;
goto errLabel ;
}
// initialize the preference manager
2013-03-27 19:12:26 +00:00
rc = cmPrefsInitialize ( ctx , prefsH , prefsFn , cbFunc , cbDataPtr , pathPrefixStr ) ;
2012-12-04 01:16:41 +00:00
errLabel :
return rc ;
}
2013-03-27 19:12:26 +00:00
cmPrRC_t cmPrefsInitialize ( cmCtx_t * ctx , cmPrH_t * hp , const cmChar_t * fn , cmPrefsOnChangeFunc_t cbFunc , void * cbDataPtr , const cmChar_t * pathPrefixStr )
2012-10-30 03:52:39 +00:00
{
cmPrRC_t rc = kOkPrRC ;
if ( ( rc = cmPrefsFinalize ( hp ) ) ! = kOkPrRC )
return rc ;
cmPr_t * p = cmMemAllocZ ( cmPr_t , 1 ) ;
cmErrSetup ( & p - > err , & ctx - > rpt , " Preferences " ) ;
// initialize a linked heap
if ( cmLHeapIsValid ( p - > lhH = cmLHeapCreate ( 1024 , ctx ) ) = = false )
{
rc = cmErrMsg ( & p - > err , kLHeapFailPrRC , " Linked heap initialization failed. " ) ;
goto errLabel ;
}
// if the preference file exists
if ( cmFsIsFile ( fn ) )
{
// initialize the JSON tree from the preferences file
if ( cmJsonInitializeFromFile ( & p - > jsH , fn , ctx ) ! = kOkJsRC )
{
rc = cmErrMsg ( & p - > err , kJsonFailPrRC , " Preferences initialization failed on JSON initialization. " ) ;
goto errLabel ;
}
// build the id list
_cmPrefsBuildIdList ( p , cmJsonRoot ( p - > jsH ) , NULL ) ;
}
else // otherwise create an empty JSON tree
{
if ( cmJsonInitialize ( & p - > jsH , ctx ) ! = kOkJsRC )
{
rc = cmErrMsg ( & p - > err , kJsonFailPrRC , " An empty JSON tree could not be created. " ) ;
goto errLabel ;
}
2012-11-01 01:01:51 +00:00
if ( cmJsonCreateObject ( p - > jsH , NULL ) = = NULL )
2012-10-30 03:52:39 +00:00
{
rc = cmErrMsg ( & p - > err , kJsonFailPrRC , " The JSON root object could not be created. " ) ;
goto errLabel ;
}
}
// install the callback function
if ( cbFunc ! = NULL )
_cmPrefsInstallCallback ( p , cbFunc , cbDataPtr ) ;
2013-03-27 19:12:26 +00:00
p - > fn = cmLhAllocStr ( p - > lhH , fn ) ;
p - > id = kMaxVarPrId ;
2012-10-30 03:52:39 +00:00
2013-03-27 19:12:26 +00:00
if ( pathPrefixStr ! = NULL & & strlen ( pathPrefixStr ) > 0 )
p - > pathPrefixStr = cmLhAllocStr ( p - > lhH , pathPrefixStr ) ;
2012-11-02 06:21:17 +00:00
2012-10-30 03:52:39 +00:00
hp - > h = p ;
errLabel :
if ( rc ! = kOkPrRC )
{
_cmPrefsFinalize ( p ) ;
hp - > h = NULL ;
}
return rc ;
}
cmPrRC_t cmPrefsFinalize ( cmPrH_t * hp )
{
cmPrRC_t rc = kOkPrRC ;
if ( hp = = NULL | | hp - > h = = NULL )
return kOkPrRC ;
if ( ( rc = _cmPrefsFinalize ( _cmPrefsHandleToPtr ( * hp ) ) ) = = kOkPrRC )
return rc ;
hp - > h = NULL ;
return rc ;
}
bool cmPrefsIsValid ( cmPrH_t h )
{ return h . h ! = NULL ; }
2012-11-01 01:01:51 +00:00
const cmChar_t * cmPrefsFileName ( cmPrH_t h )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return p - > fn ;
}
2012-10-30 03:52:39 +00:00
cmPrRC_t cmPrefsRC ( cmPrH_t h )
{ return cmErrLastRC ( & _cmPrefsHandleToPtr ( h ) - > err ) ; }
cmPrRC_t cmPrefsSetRC ( cmPrH_t h , cmPrRC_t rc )
{ return cmErrSetRC ( & _cmPrefsHandleToPtr ( h ) - > err , rc ) ; }
cmPrRC_t cmPrefsInstallCallback ( cmPrH_t h , cmPrefsOnChangeFunc_t cbFunc , void * cbDataPtr )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
_cmPrefsInstallCallback ( p , cbFunc , cbDataPtr ) ;
return kOkPrRC ;
}
cmPrRC_t cmPrefsRemoveCallback ( cmPrH_t h , cmPrefsOnChangeFunc_t cbFunc )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
cmPrCb_t * cc = p - > cbChainPtr ;
cmPrCb_t * pc = NULL ;
while ( cc = = NULL )
{
if ( cc - > cbFunc = = cbFunc )
{
if ( pc = = NULL )
p - > cbChainPtr = cc - > linkPtr ;
else
pc - > linkPtr = cc - > linkPtr ;
break ;
}
pc = cc ;
cc = cc - > linkPtr ;
}
if ( cc = = NULL )
return cmErrMsg ( & p - > err , kCbNotFoundPrRC , " The callback function %p could not be found. " , cbFunc ) ;
return kOkPrRC ;
}
2013-03-27 19:12:26 +00:00
unsigned cmPrefsId ( cmPrH_t h , const cmChar_t * pathStr , bool reportErrFl )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return _cmPrefsId ( p , pathStr , reportErrFl ) ;
}
2012-10-30 03:52:39 +00:00
unsigned cmPrefsEleCount ( cmPrH_t h , unsigned id )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
cmPrNode_t * np = _cmPrefsIdToNodePtr ( p , id , true ) ;
if ( np = = NULL )
return - 1 ;
if ( cmJsonIsArray ( np - > nodePtr ) )
return cmJsonChildCount ( np - > nodePtr ) ;
return 1 ;
}
void _cmPrefsFormPath ( cmPr_t * p , const cmPrNode_t * np )
{
cmPrPath_t * pp = np - > pathPtr ;
int n = 0 ;
for ( ; pp ! = NULL ; pp = pp - > parentPtr )
+ + n ;
const char * pathArray [ n ] ;
unsigned i = n - 1 ;
for ( pp = np - > pathPtr ; pp ! = NULL ; pp = pp - > parentPtr , - - i )
pathArray [ i ] = pp - > label ;
cmMemPtrFree ( & p - > pathBuf ) ;
for ( i = 0 ; i < n ; + + i )
{
if ( i > 0 )
p - > pathBuf = cmTextAppendSS ( p - > pathBuf , " / " ) ;
p - > pathBuf = cmTextAppendSS ( p - > pathBuf , pathArray [ i ] ) ;
}
}
2013-03-29 06:20:58 +00:00
cmPrRC_t _cmPrefsValue ( cmPr_t * p , const cmPrNode_t * np , const cmJsonNode_t * jnp , bool * bvp , unsigned * uvp , int * ivp , double * rvp , const cmChar_t * * svp , unsigned retEleCnt )
2012-10-30 03:52:39 +00:00
{
cmJsRC_t jsRC = kOkJsRC ;
const char * typeLabel = NULL ;
// verify that adequate return space was provided
if ( retEleCnt < 1 )
{
_cmPrefsFormPath ( p , np ) ;
return cmErrMsg ( & p - > err , kBufTooSmallPrRC , " No return space was provided for the preference variable '%s' (id:%i) . " ,p->pathBuf,np->id) ;
}
if ( bvp ! = NULL )
{
jsRC = cmJsonBoolValue ( jnp , bvp ) ;
typeLabel = " bool " ;
}
else
2013-03-29 06:20:58 +00:00
if ( uvp ! = NULL )
2012-10-30 03:52:39 +00:00
{
2013-03-29 06:20:58 +00:00
jsRC = cmJsonUIntValue ( jnp , uvp ) ;
typeLabel = " uint " ;
2012-10-30 03:52:39 +00:00
}
else
2013-03-29 06:20:58 +00:00
if ( ivp ! = NULL )
2012-10-30 03:52:39 +00:00
{
2013-03-29 06:20:58 +00:00
jsRC = cmJsonIntValue ( jnp , ivp ) ;
typeLabel = " int " ;
2012-10-30 03:52:39 +00:00
}
else
2013-03-29 06:20:58 +00:00
if ( rvp ! = NULL )
2012-10-30 03:52:39 +00:00
{
2013-03-29 06:20:58 +00:00
jsRC = cmJsonRealValue ( jnp , rvp ) ;
typeLabel = " real " ;
2012-10-30 03:52:39 +00:00
}
else
2013-03-29 06:20:58 +00:00
if ( svp ! = NULL )
{
jsRC = cmJsonStringValue ( jnp , svp ) ;
typeLabel = " string " ;
}
else
{
assert ( 0 ) ;
}
2012-10-30 03:52:39 +00:00
if ( jsRC ! = kOkJsRC )
{
_cmPrefsFormPath ( p , np ) ;
return cmErrMsg ( & p - > err , kCvtErrPrRC , " The perferences variable '%s' (id:%i) could not be converted to type ' % s ' . " ,p->pathBuf,np->id,typeLabel) ;
}
return kOkPrRC ;
}
2013-03-29 06:20:58 +00:00
// if eleCntPtr is null then assume the value is a scalar
cmPrRC_t _cmPrefsGetValue ( cmPrH_t h , unsigned id , bool * bvp , unsigned * uvp , int * ivp , double * rvp , const cmChar_t * * svp , unsigned * eleCntPtr , unsigned eleIdx )
2012-10-30 03:52:39 +00:00
{
cmPrRC_t rc = kOkPrRC ;
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
cmPrNode_t * np = NULL ;
2013-03-29 06:20:58 +00:00
unsigned eleCnt = 1 ;
if ( eleCntPtr ! = NULL )
eleCnt = * eleCntPtr ;
2012-10-30 03:52:39 +00:00
// if no return buffer was given - do nothing
2013-03-29 06:20:58 +00:00
if ( eleCnt = = 0 )
2012-10-30 03:52:39 +00:00
return kOkPrRC ;
// locate the pref node from 'id'
if ( ( np = _cmPrefsIdToNodePtr ( p , id , true ) ) = = NULL )
{
rc = cmErrMsg ( & p - > err , kVarNotFoundPrRC , " No preference variable was found for id:%i. " , id ) ;
goto errLabel ;
}
// if the requested pref. var is a scalar
if ( cmJsonIsArray ( np - > nodePtr ) = = false )
{
2013-03-29 06:20:58 +00:00
if ( ( rc = _cmPrefsValue ( p , np , np - > nodePtr , bvp , uvp , ivp , rvp , svp , eleCnt ) ) = = kOkPrRC )
{
if ( eleCntPtr ! = NULL )
* eleCntPtr = 1 ;
}
2012-10-30 03:52:39 +00:00
}
else // the request pref. var. is an array
{
unsigned i = 0 ;
unsigned n = cmJsonChildCount ( np - > nodePtr ) ;
// if the entire array was requestedd
if ( eleIdx = = cmInvalidIdx )
{
// if the return buffer is too small to hold all of the values.
2013-03-29 06:20:58 +00:00
if ( eleCnt < n )
2012-10-30 03:52:39 +00:00
{
2013-03-29 06:20:58 +00:00
if ( eleCntPtr ! = NULL )
* eleCntPtr = 0 ;
2012-10-30 03:52:39 +00:00
_cmPrefsFormPath ( p , np ) ;
rc = cmErrMsg ( & p - > err , kBufTooSmallPrRC , " The return array for the preference variable '%s' (id:%i) is too small to hold '%i elements " , p - > pathBuf , np - > id , n ) ;
goto errLabel ;
}
// read each element
for ( i = 0 ; i < n ; + + i )
{
const cmJsonNode_t * cnp = cmJsonArrayElement ( np - > nodePtr , i ) ;
2013-03-29 06:20:58 +00:00
if ( ( rc = _cmPrefsValue ( p , np , cnp , bvp = = NULL ? NULL : bvp + i , uvp = = NULL ? NULL : uvp + i , ivp = = NULL ? NULL : ivp + i , rvp = = NULL ? NULL : rvp + i , svp = = NULL ? NULL : svp + i , 1 ) ) ! = kOkPrRC )
2012-10-30 03:52:39 +00:00
goto errLabel ;
}
2013-03-29 06:20:58 +00:00
if ( eleCntPtr ! = NULL )
* eleCntPtr = n ;
2012-10-30 03:52:39 +00:00
}
else // a single ele of the array was requested
{
// validate the index
if ( eleIdx > = n )
{
_cmPrefsFormPath ( p , np ) ;
rc = cmErrMsg ( & p - > err , kInvalidIndexPrRC , " The index %i is invalid for the variable '%s' of length %i. " , eleIdx , p - > pathBuf , n ) ;
goto errLabel ;
}
// get the json element at array index 'eleIdx'
const cmJsonNode_t * cnp = cmJsonArrayElement ( np - > nodePtr , eleIdx ) ;
assert ( cnp ! = NULL ) ;
// read the element from the array
2013-03-29 06:20:58 +00:00
if ( ( rc = _cmPrefsValue ( p , np , cnp , bvp , uvp , ivp , rvp , svp , eleCnt ) ) = = kOkPrRC )
{
if ( eleCntPtr ! = NULL )
* eleCntPtr = 1 ;
}
2012-10-30 03:52:39 +00:00
}
}
errLabel :
if ( rc ! = kOkPrRC )
2013-03-29 06:20:58 +00:00
{
if ( eleCntPtr ! = NULL )
* eleCntPtr = 0 ;
}
2012-10-30 03:52:39 +00:00
return rc ;
}
cmPrRC_t cmPrefsGetBool ( cmPrH_t h , unsigned id , bool * vp , unsigned * eleCntPtr )
2013-03-29 06:20:58 +00:00
{ return _cmPrefsGetValue ( h , id , vp , NULL , NULL , NULL , NULL , eleCntPtr , cmInvalidIdx ) ; }
cmPrRC_t cmPrefsGetUInt ( cmPrH_t h , unsigned id , unsigned * vp , unsigned * eleCntPtr )
{ return _cmPrefsGetValue ( h , id , NULL , vp , NULL , NULL , NULL , eleCntPtr , cmInvalidIdx ) ; }
2012-10-30 03:52:39 +00:00
cmPrRC_t cmPrefsGetInt ( cmPrH_t h , unsigned id , int * vp , unsigned * eleCntPtr )
2013-03-29 06:20:58 +00:00
{ return _cmPrefsGetValue ( h , id , NULL , NULL , vp , NULL , NULL , eleCntPtr , cmInvalidIdx ) ; }
2012-10-30 03:52:39 +00:00
cmPrRC_t cmPrefsGetReal ( cmPrH_t h , unsigned id , double * vp , unsigned * eleCntPtr )
2013-03-29 06:20:58 +00:00
{ return _cmPrefsGetValue ( h , id , NULL , NULL , NULL , vp , NULL , eleCntPtr , cmInvalidIdx ) ; }
2012-10-30 03:52:39 +00:00
cmPrRC_t cmPrefsGetString ( cmPrH_t h , unsigned id , const cmChar_t * * vp , unsigned * eleCntPtr )
2013-03-29 06:20:58 +00:00
{ return _cmPrefsGetValue ( h , id , NULL , NULL , NULL , NULL , vp , eleCntPtr , cmInvalidIdx ) ; }
2012-10-30 03:52:39 +00:00
bool cmPrefsBool ( cmPrH_t h , unsigned id )
{
bool v = false ;
unsigned n = 1 ;
cmPrefsGetBool ( h , id , & v , & n ) ;
return v ;
}
unsigned cmPrefsUInt ( cmPrH_t h , unsigned id )
{
int v = 0 ;
unsigned n = 1 ;
cmPrefsGetInt ( h , id , & v , & n ) ;
return ( unsigned ) v ;
}
int cmPrefsInt ( cmPrH_t h , unsigned id )
{
int v = 0 ;
unsigned n = 1 ;
cmPrefsGetInt ( h , id , & v , & n ) ;
return v ;
}
float cmPrefsFloat ( cmPrH_t h , unsigned id )
{
double v = 0 ;
unsigned n = 1 ;
cmPrefsGetReal ( h , id , & v , & n ) ;
return ( float ) v ;
}
double cmPrefsReal ( cmPrH_t h , unsigned id )
{
double v = 0 ;
unsigned n = 1 ;
cmPrefsGetReal ( h , id , & v , & n ) ;
return v ;
}
const cmChar_t * cmPrefsString ( cmPrH_t h , unsigned id )
{
const cmChar_t * v = NULL ;
unsigned n = 1 ;
if ( cmPrefsGetString ( h , id , & v , & n ) = = kOkPrRC )
return v = = NULL ? " " : v ;
return " " ;
}
bool cmPrefsBoolDef ( cmPrH_t h , const cmChar_t * pathStr , bool dfltVal )
{
unsigned id ;
if ( cmPrefsIsValid ( h ) = = false | | ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return dfltVal ;
return cmPrefsBool ( h , id ) ;
}
unsigned cmPrefsUIntDef ( cmPrH_t h , const cmChar_t * pathStr , unsigned dfltVal )
{
unsigned id ;
if ( cmPrefsIsValid ( h ) = = false | | ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return dfltVal ;
return cmPrefsUInt ( h , id ) ;
}
int cmPrefsIntDef ( cmPrH_t h , const cmChar_t * pathStr , int dfltVal )
{
unsigned id ;
if ( cmPrefsIsValid ( h ) = = false | | ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return dfltVal ;
return cmPrefsInt ( h , id ) ;
}
float cmPrefsFloatDef ( cmPrH_t h , const cmChar_t * pathStr , float dfltVal )
{
unsigned id ;
if ( cmPrefsIsValid ( h ) = = false | | ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return dfltVal ;
return cmPrefsFloat ( h , id ) ;
}
double cmPrefsRealDef ( cmPrH_t h , const cmChar_t * pathStr , double dfltVal )
{
unsigned id ;
if ( cmPrefsIsValid ( h ) = = false | | ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return dfltVal ;
return cmPrefsReal ( h , id ) ;
}
const cmChar_t * cmPrefsStringDef ( cmPrH_t h , const cmChar_t * pathStr , const cmChar_t * dfltVal )
{
unsigned id ;
if ( cmPrefsIsValid ( h ) = = false | | ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return dfltVal ;
const cmChar_t * v = cmPrefsString ( h , id ) ;
return v = = NULL | | strlen ( v ) = = 0 ? dfltVal : v ;
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsBoolRc ( cmPrH_t h , const cmChar_t * pathStr , bool * retValPtr )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
unsigned n = 1 ;
return cmPrefsGetBool ( h , id , retValPtr , & n ) ;
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsUIntRc ( cmPrH_t h , const cmChar_t * pathStr , unsigned * retValPtr )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
int v ;
cmPrRC_t rc ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
if ( ( rc = cmPrefsGetInt ( h , id , & v , & n ) ) = = kOkPrRC )
* retValPtr = v ;
return rc ;
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsIntRc ( cmPrH_t h , const cmChar_t * pathStr , int * retValPtr )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
unsigned n = 1 ;
return cmPrefsGetInt ( h , id , retValPtr , & n ) ;
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsFloatRc ( cmPrH_t h , const cmChar_t * pathStr , float * retValPtr )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
double v ;
cmPrRC_t rc ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
if ( ( rc = cmPrefsGetReal ( h , id , & v , & n ) ) = = kOkPrRC )
* retValPtr = v ;
return rc ;
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsRealRc ( cmPrH_t h , const cmChar_t * pathStr , double * retValPtr )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
unsigned n = 1 ;
return cmPrefsGetReal ( h , id , retValPtr , & n ) ;
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsStringRc ( cmPrH_t h , const cmChar_t * pathStr , const cmChar_t * * retValPtr )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
unsigned n = 1 ;
return cmPrefsGetString ( h , id , retValPtr , & n ) ;
}
unsigned cmPrefsArrayElementCount ( cmPrH_t h , unsigned id )
{
cmPrNode_t * np ;
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
// locate the pref node from 'id'
if ( ( np = _cmPrefsIdToNodePtr ( p , id , true ) ) = = NULL )
{
cmErrMsg ( & p - > err , kVarNotFoundPrRC , " No preference variable was found for id:%i. " , id ) ;
return cmInvalidCnt ;
}
// if the requested pref. var is a scalar
if ( cmJsonIsArray ( np - > nodePtr ) )
return cmJsonChildCount ( np - > nodePtr ) ;
return 0 ;
}
bool cmPrefsBoolEle ( cmPrH_t h , unsigned id , unsigned idx )
{
bool v = false ; ;
unsigned n = 1 ;
2013-03-29 06:20:58 +00:00
_cmPrefsGetValue ( h , id , & v , NULL , NULL , NULL , NULL , & n , idx ) ;
2012-10-30 03:52:39 +00:00
return v ;
}
unsigned cmPrefsUIntEle ( cmPrH_t h , unsigned id , unsigned idx )
{
2013-03-29 06:20:58 +00:00
unsigned v = 0 ;
2012-10-30 03:52:39 +00:00
unsigned n = 1 ;
2013-03-29 06:20:58 +00:00
_cmPrefsGetValue ( h , id , NULL , & v , NULL , NULL , NULL , & n , idx ) ;
return v ;
2012-10-30 03:52:39 +00:00
}
int cmPrefsIntEle ( cmPrH_t h , unsigned id , unsigned idx )
{
int v = 0 ;
unsigned n = 1 ;
2013-03-29 06:20:58 +00:00
_cmPrefsGetValue ( h , id , NULL , NULL , & v , NULL , NULL , & n , idx ) ;
2012-10-30 03:52:39 +00:00
return v ;
}
float cmPrefsFloatEle ( cmPrH_t h , unsigned id , unsigned idx )
{
double v = 0 ;
unsigned n = 1 ;
2013-03-29 06:20:58 +00:00
_cmPrefsGetValue ( h , id , NULL , NULL , NULL , & v , NULL , & n , idx ) ;
2012-10-30 03:52:39 +00:00
return ( float ) v ;
}
double cmPrefsRealEle ( cmPrH_t h , unsigned id , unsigned idx )
{
double v = 0 ;
unsigned n = 1 ;
2013-03-29 06:20:58 +00:00
_cmPrefsGetValue ( h , id , NULL , NULL , NULL , & v , NULL , & n , idx ) ;
2012-10-30 03:52:39 +00:00
return v ;
}
const cmChar_t * cmPrefsStringEle ( cmPrH_t h , unsigned id , unsigned idx )
{
const cmChar_t * v = " " ;
unsigned n = 1 ;
2013-03-29 06:20:58 +00:00
if ( _cmPrefsGetValue ( h , id , NULL , NULL , NULL , NULL , & v , & n , idx ) = = kOkPrRC )
2012-10-30 03:52:39 +00:00
return v ;
return " " ;
}
cmPrRC_t _cmPrefsSetValue ( cmPr_t * p , cmPrNode_t * np , cmJsonNode_t * jnp , const bool * bvp , const int * ivp , const double * rvp , const cmChar_t * * svp , bool * deltaFlPtr )
{
cmJsRC_t jsRC = kOkJsRC ;
//const cmChar_t* typeLabel;
if ( bvp ! = NULL )
{
bool v ;
if ( ( jsRC = cmJsonBoolValue ( jnp , & v ) ) = = kOkJsRC )
if ( ( * deltaFlPtr = ( v ! = * bvp ) ) )
jsRC = cmJsonSetBool ( p - > jsH , jnp , * bvp ) ;
//typeLabel = "bool";
}
else
if ( ivp ! = NULL )
{
int v ;
if ( ( jsRC = cmJsonIntValue ( jnp , & v ) ) = = kOkJsRC )
if ( ( * deltaFlPtr = ( v ! = * ivp ) ) )
jsRC = cmJsonSetInt ( p - > jsH , jnp , * ivp ) ;
//typeLabel = "int";
}
else
if ( rvp ! = NULL )
{
double v ;
if ( ( jsRC = cmJsonRealValue ( jnp , & v ) ) = = kOkJsRC )
if ( ( * deltaFlPtr = ( v ! = * rvp ) ) )
jsRC = cmJsonSetReal ( p - > jsH , jnp , * rvp ) ;
//typeLabel = "real";
}
else
if ( svp ! = NULL )
{
const cmChar_t * v ;
if ( ( jsRC = cmJsonStringValue ( jnp , & v ) ) = = kOkJsRC )
{
const cmChar_t * s0 = v = = NULL ? " " : v ;
const cmChar_t * s1 = * svp = = NULL ? " " : * svp ;
if ( ( * deltaFlPtr = ( strcmp ( s0 , s1 ) ! = 0 ) ) )
jsRC = cmJsonSetString ( p - > jsH , jnp , s1 ) ;
}
//typeLabel = "string";
}
else
{
assert ( 0 ) ;
}
if ( jsRC ! = kOkJsRC )
{
_cmPrefsFormPath ( p , np ) ;
return cmErrMsg ( & p - > err , kCvtErrPrRC , " The perferences variable '%s' (id:%i) could not be set . " ,p->pathBuf,np->id) ;
}
return kOkPrRC ;
}
void _cmPrefsCallback ( cmPr_t * p , unsigned id )
{
// notify any listeners that a node has changed values
cmPrCb_t * cbNodePtr = p - > cbChainPtr ;
for ( ; cbNodePtr ! = NULL ; cbNodePtr = cbNodePtr - > linkPtr )
{
cmPrH_t h ;
h . h = p ;
cbNodePtr - > cbFunc ( h , cbNodePtr - > cbDataPtr , id ) ;
}
}
cmPrRC_t _cmPrefsSetValues2 ( cmPr_t * p , cmPrNode_t * np , const bool * bvp , const int * ivp , const double * rvp , const cmChar_t * * svp , const unsigned * eleCntPtr )
{
cmPrRC_t rc = kOkPrRC ;
bool deltaFl = false ; // set to true if the value of the pref. var. identified by 'id' actually changes.
// a scalar has been passed in and the existing json node is also a scalar
if ( cmJsonIsArray ( np - > nodePtr ) = = false & & * eleCntPtr = = 1 )
{
rc = _cmPrefsSetValue ( p , np , np - > nodePtr , bvp , ivp , rvp , svp , & deltaFl ) ;
goto errLabel ;
}
// the pref. variable is an array
if ( cmJsonIsArray ( np - > nodePtr ) )
{
unsigned i ;
unsigned curArrCnt = cmJsonChildCount ( np - > nodePtr ) ;
unsigned n = cmMin ( * eleCntPtr , curArrCnt ) ;
for ( i = 0 ; i < n ; + + i )
{
cmJsonNode_t * jnp = cmJsonArrayElement ( np - > nodePtr , i ) ;
bool dfl = false ;
if ( ( rc = _cmPrefsSetValue ( p , np , jnp , bvp = = NULL ? NULL : bvp + i , ivp = = NULL ? NULL : ivp + i , rvp = = NULL ? NULL : rvp + i , svp = = NULL ? NULL : svp + i , & dfl ) ) ! = kOkPrRC )
return rc ;
if ( dfl )
deltaFl = true ;
}
// if elements should be removed
if ( curArrCnt > * eleCntPtr )
{
deltaFl = true ; // ele's are being removed so the variable value is changing
for ( i = * eleCntPtr ; i < curArrCnt ; + + i )
{
cmJsonNode_t * jnp = cmJsonArrayElement ( np - > nodePtr , * eleCntPtr ) ;
assert ( jnp ! = NULL ) ;
cmJsonRemoveNode ( p - > jsH , jnp , true ) ;
}
}
// if elements should be added
if ( * eleCntPtr > curArrCnt )
{
unsigned typeId = cmInvalidId ;
cmJsonNode_t * jnp = NULL ;
cmJsonNode_t * snp = curArrCnt = = 0 ? NULL : cmJsonArrayElement ( np - > nodePtr , curArrCnt - 1 ) ;
assert ( snp - > ownerPtr = = np - > nodePtr & & snp - > siblingPtr = = NULL ) ;
deltaFl = true ; // ele's are being added so the variable value is changing
if ( ivp ! = NULL )
typeId = kIntTId ;
else
if ( rvp ! = NULL )
typeId = kRealTId ;
else
if ( svp ! = NULL )
typeId = kStringTId ;
// for each new array element
for ( ; i < * eleCntPtr ; + + i )
{
if ( bvp ! = NULL )
typeId = bvp [ i ] ;
// create the new array element node - the new node is automatically added to the end of the array
if ( cmJsonCreate ( p - > jsH , np - > nodePtr , typeId , svp = = NULL ? NULL : svp [ i ] , ivp = = NULL ? 0 : ivp [ i ] , rvp = = NULL ? 0 : rvp [ i ] , & jnp ) ! = kOkJsRC )
{
_cmPrefsFormPath ( p , np ) ;
return cmErrMsg ( & p - > err , kJsonFailPrRC , " Unable to create a value node for '%s' (id=%i) . " ,p->pathBuf,np->id) ;
}
}
}
errLabel :
if ( ( rc = = kOkPrRC ) & & deltaFl )
{
_cmPrefsCallback ( p , np - > id ) ;
// update the global delta flag
p - > dirtyFl = true ;
}
return rc ;
}
_cmPrefsFormPath ( p , np ) ;
return cmErrMsg ( & p - > err , kCvtErrPrRC , " The new preference value could not be converted to the existing preference variable type for '%s' (id=%i) . " ,p->pathBuf,np->id) ;
}
cmPrRC_t _cmPrefsSetValues ( cmPrH_t h , unsigned id , const bool * bvp , const int * ivp , const double * rvp , const cmChar_t * * svp , const unsigned * eleCntPtr )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
cmPrNode_t * np ;
// locate the pref node
if ( ( np = _cmPrefsIdToNodePtr ( p , id , true ) ) = = NULL )
return cmErrMsg ( & p - > err , kVarNotFoundPrRC , " The variable with id=%i was not found. " , id ) ;
return _cmPrefsSetValues2 ( p , np , bvp , ivp , rvp , svp , eleCntPtr ) ;
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsSetBoolArray ( cmPrH_t h , unsigned id , const bool * vp , const unsigned * eleCntPtr )
2012-10-30 03:52:39 +00:00
{ return _cmPrefsSetValues ( h , id , vp , NULL , NULL , NULL , eleCntPtr ) ; }
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsSetIntArray ( cmPrH_t h , unsigned id , const int * vp , const unsigned * eleCntPtr )
2012-10-30 03:52:39 +00:00
{ return _cmPrefsSetValues ( h , id , NULL , vp , NULL , NULL , eleCntPtr ) ; }
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsSetRealArray ( cmPrH_t h , unsigned id , const double * vp , const unsigned * eleCntPtr )
2012-10-30 03:52:39 +00:00
{ return _cmPrefsSetValues ( h , id , NULL , NULL , vp , NULL , eleCntPtr ) ; }
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsSetStringArray ( cmPrH_t h , unsigned id , const cmChar_t * * vp , const unsigned * eleCntPtr )
2012-10-30 03:52:39 +00:00
{ return _cmPrefsSetValues ( h , id , NULL , NULL , NULL , vp , eleCntPtr ) ; }
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsSetBool ( cmPrH_t h , unsigned id , bool val )
{
unsigned n = 1 ;
return cmPrefsSetBoolArray ( h , id , & val , & n ) ;
}
cmPrRC_t cmPrefsSetUInt ( cmPrH_t h , unsigned id , unsigned val )
{
unsigned n = 1 ;
int ival = ( int ) val ;
return cmPrefsSetIntArray ( h , id , & ival , & n ) ;
}
cmPrRC_t cmPrefsSetInt ( cmPrH_t h , unsigned id , int val )
{
unsigned n = 1 ;
return cmPrefsSetIntArray ( h , id , & val , & n ) ;
}
cmPrRC_t cmPrefsSetFloat ( cmPrH_t h , unsigned id , float val )
{
unsigned n = 1 ;
double dval = val ;
return cmPrefsSetRealArray ( h , id , & dval , & n ) ;
}
cmPrRC_t cmPrefsSetReal ( cmPrH_t h , unsigned id , double val )
{
unsigned n = 1 ;
return cmPrefsSetRealArray ( h , id , & val , & n ) ;
}
cmPrRC_t cmPrefsSetString ( cmPrH_t h , unsigned id , const cmChar_t * val )
{
unsigned n = 1 ;
return cmPrefsSetStringArray ( h , id , & val , & n ) ;
}
cmPrRC_t cmPrefsPathSetBool ( cmPrH_t h , const cmChar_t * pathStr , bool val )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
2012-11-01 01:01:51 +00:00
return cmPrefsSetBoolArray ( h , id , & val , & n ) ;
2012-10-30 03:52:39 +00:00
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsPathSetUInt ( cmPrH_t h , const cmChar_t * pathStr , unsigned val )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
int ival = ( int ) val ;
2012-11-01 01:01:51 +00:00
return cmPrefsSetIntArray ( h , id , & ival , & n ) ;
2012-10-30 03:52:39 +00:00
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsPathSetInt ( cmPrH_t h , const cmChar_t * pathStr , int val )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
2012-11-01 01:01:51 +00:00
return cmPrefsSetIntArray ( h , id , & val , & n ) ;
2012-10-30 03:52:39 +00:00
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsPathSetFloat ( cmPrH_t h , const cmChar_t * pathStr , float val )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
double dval = val ;
2012-11-01 01:01:51 +00:00
return cmPrefsSetRealArray ( h , id , & dval , & n ) ;
2012-10-30 03:52:39 +00:00
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsPathSetReal ( cmPrH_t h , const cmChar_t * pathStr , double val )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
2012-11-01 01:01:51 +00:00
return cmPrefsSetRealArray ( h , id , & val , & n ) ;
2012-10-30 03:52:39 +00:00
}
2012-11-01 01:01:51 +00:00
cmPrRC_t cmPrefsPathSetString ( cmPrH_t h , const cmChar_t * pathStr , const cmChar_t * val )
2012-10-30 03:52:39 +00:00
{
unsigned id ;
unsigned n = 1 ;
if ( ( id = cmPrefsId ( h , pathStr , true ) ) = = cmInvalidId )
return kVarNotFoundPrRC ;
2012-11-01 01:01:51 +00:00
return cmPrefsSetStringArray ( h , id , & val , & n ) ;
2012-10-30 03:52:39 +00:00
}
bool _cmPrefsValidateNodeType ( cmJsonNode_t * np , unsigned jsTypeId , unsigned valCnt )
{
// if we are looking for a scalar node then the type must be jsTypeId
if ( valCnt = = 1 )
return np - > typeId = = jsTypeId ;
// if we are looking for an array node then the type must be kArrayTId ...
if ( np - > typeId ! = kArrayTId )
return false ;
unsigned n = cmJsonChildCount ( np ) ;
unsigned i = 0 ;
// ... and all of the array elements must be of type jsTypeId
for ( ; i < n ; + + i )
{
const cmJsonNode_t * cnp = cmJsonArrayElementC ( np , i ) ;
assert ( cnp ! = NULL ) ;
if ( cnp - > typeId ! = jsTypeId )
return false ;
}
return true ;
}
//
cmPrRC_t _cmPrefsCreateJsonNode (
cmPr_t * p ,
unsigned id , // new variable id
const cmChar_t * pathString , // new variable name
unsigned jsTypeId , // type of new variable
const cmChar_t * * strVal , // value of new variable
const double * realVal , //
const int * intVal , //
const bool * boolVal , //
unsigned valCnt , // length of xxxVal[]
bool setFlag ) // true== if same named variable already exists then set the value to xxxVal
{
cmPrRC_t rc = kOkPrRC ;
int pathCnt = 0 ;
2013-03-27 19:12:26 +00:00
cmChar_t * pathStr = _cmPrefsCreatePathStr ( p , pathString , & pathCnt ) ;
2012-10-30 03:52:39 +00:00
const cmChar_t * pathEleStr = pathStr ;
cmJsonNode_t * jsnp = cmJsonRoot ( p - > jsH ) ;
cmJsonNode_t * jsPairNodePtr = NULL ;
cmPrNode_t * pnp = NULL ; // current pref node pointer
bool existsFl = false ; // set if variable already exists
int i ;
assert ( pathCnt > = 1 ) ;
2012-11-02 06:21:17 +00:00
if ( id ! = cmInvalidId & & id > = kMaxVarPrId )
return cmErrMsg ( & p - > err , kNodeCreateFailPrRC , " User supplied id's must be less than 0x%x. " , kMaxVarPrId ) ;
2012-10-30 03:52:39 +00:00
// for each path element
for ( i = 0 ; i < pathCnt ; + + i )
{
cmJsonNode_t * tnp = NULL ;
// find the child pair node of jsnp named 'pathEleStr'.
if ( ( tnp = cmJsonNodeMemberValue ( jsnp , pathEleStr ) ) = = NULL )
break ;
// the located json node must be an object (i<pathCnt-1) or the same type as jsTypeId (i=pathCnt-1)
// This check guarantees that all nodes up to the leaf node are objects and the leaf node matches the created type.
if ( ! ( ( ( i < pathCnt - 1 ) & & cmJsonIsObject ( tnp ) ) | | ( ( i = = pathCnt - 1 ) & & _cmPrefsValidateNodeType ( tnp , jsTypeId , valCnt ) ) ) )
{
rc = cmErrMsg ( & p - > err , kNodeCreateFailPrRC , " Node creation for '%s' failed because an existing node with the same name but different type (%i) was found. " , pathString , tnp - > typeId ) ;
goto errLabel ;
}
// assert that the json nodes we are finding form a tree
assert ( ( tnp - > ownerPtr = = NULL & & jsnp = = NULL ) | | ( tnp - > ownerPtr ! = NULL & & tnp - > ownerPtr - > ownerPtr = = jsnp ) ) ;
jsnp = tnp ;
// find the pref node which refers to the located json node
// (we need to track the pnp->pathPtr)
pnp = p - > idChainPtr ;
for ( ; pnp ! = NULL ; pnp = pnp - > linkPtr )
if ( pnp - > nodePtr = = jsnp )
break ;
assert ( pnp - > pathPtr ! = NULL ) ;
// advance to the next path segment
pathEleStr + = strlen ( pathEleStr ) + 1 ;
}
// if i<pathCnt then json nodes must be created to
// if i==pathCnt then a matching variable already exists
if ( i = = pathCnt )
{
// the reference variable already exists and assignment was requested (setFlag==true).
// but the assignment cannot be made until the 'id' is updated.
existsFl = true ;
}
// we have followed 'pathString' to the last node which already
2012-11-01 01:01:51 +00:00
// exists in the JSON tree - now we must create new JSON nodes to reflect
2012-10-30 03:52:39 +00:00
// the remaining path elements
for ( ; i < pathCnt ; + + i )
{
// if this is the last element in the path - then it is a pair
if ( i = = pathCnt - 1 )
{
// create a scalar value pair node
if ( valCnt = = 1 )
{
const char * sv = strVal = = NULL ? NULL : * strVal ;
double rv = realVal = = NULL ? 0.0 : * realVal ;
int iv = intVal = = NULL ? 0 : * intVal ;
if ( boolVal ! = NULL )
jsTypeId = * boolVal ? kTrueTId : kFalseTId ;
2012-12-04 01:16:41 +00:00
if ( ( jsnp = cmJsonInsertPair ( p - > jsH , jsnp , pathEleStr , jsTypeId , sv , iv , rv ) ) = = NULL )
2012-10-30 03:52:39 +00:00
{
rc = cmErrMsg ( & p - > err , kInvalidIdPrRC , " Preference node create failed for '%s' " , cmStringNullGuard ( pathString ) ) ;
goto errLabel ;
}
}
else // create a vector value pair node
{
switch ( jsTypeId )
{
case kStringTId : jsnp = cmJsonInsertPairStringArray2 ( p - > jsH , jsnp , pathEleStr , valCnt , strVal ) ; break ;
case kRealTId : jsnp = cmJsonInsertPairRealArray2 ( p - > jsH , jsnp , pathEleStr , valCnt , realVal ) ; break ;
case kIntTId : jsnp = cmJsonInsertPairIntArray2 ( p - > jsH , jsnp , pathEleStr , valCnt , intVal ) ; break ;
case kBoolTId : jsnp = cmJsonInsertPairBoolArray2 ( p - > jsH , jsnp , pathEleStr , valCnt , boolVal ) ; break ;
default :
{
rc = cmErrMsg ( & p - > err , kInvalidIdPrRC , " Preference node insert failed on '%s' due to invalid type id '%i'. " , cmStringNullGuard ( pathString ) , jsTypeId ) ;
goto errLabel ;
}
}
}
assert ( jsnp ! = NULL ) ;
jsPairNodePtr = jsnp ;
}
else // this is not the last element in the path - create an object node
{
// create the object associated with this new level
if ( ( jsnp = cmJsonInsertPairObject ( p - > jsH , jsnp , pathEleStr ) ) = = NULL )
{
rc = cmErrMsg ( & p - > err , kJsonFailPrRC , " Preference node create failed because JSON node create failed on '%s'. " , cmStringNullGuard ( pathString ) ) ;
goto errLabel ;
}
jsPairNodePtr = jsnp - > ownerPtr ;
}
2012-11-01 01:01:51 +00:00
unsigned nxtId = p - > id ;
2012-10-30 03:52:39 +00:00
// create a pref node to associate with this new level
2012-11-01 01:01:51 +00:00
if ( ( pnp = _cmPrefsCreateNode ( p , jsPairNodePtr , pnp = = NULL ? NULL : pnp - > pathPtr ) ) = = NULL )
2012-10-30 03:52:39 +00:00
{
rc = cmErrMsg ( & p - > err , kNodeCreateFailPrRC , " Creation failed for the '%s' element of the preference node '%s'. " , cmStringNullGuard ( pathEleStr ) , cmStringNullGuard ( pathString ) ) ;
goto errLabel ;
}
2012-11-01 01:01:51 +00:00
// always leave internal nodes with id=cmInvalidId, leaf node id's will be set below
p - > id = nxtId ;
pnp - > id = cmInvalidId ;
2012-10-30 03:52:39 +00:00
pathEleStr + = strlen ( pathEleStr ) + 1 ;
}
assert ( pnp ! = NULL ) ;
// if an preference variable 'id' was given then set it here
2012-11-01 01:01:51 +00:00
if ( id = = cmInvalidId )
pnp - > id = _cmPrefsCalcNextAvailId ( p ) ;
else
2012-10-30 03:52:39 +00:00
{
2013-03-21 15:18:46 +00:00
if ( existsFl = = false )
if ( _cmPrefsIdToNodePtr ( p , id , false ) ! = NULL )
cmErrWarnMsg ( & p - > err , kDuplicateIdPrRC , " The preference variable id '%i' is used by multiple preference variables including '%s'. " , id , cmStringNullGuard ( pathString ) ) ;
2012-10-30 03:52:39 +00:00
pnp - > id = id ;
}
// if the variable already existed and setFlag==true then update the variable value here
// (note that this cannot occur earlier because the 'id' has not yet been updated
// which might result in the incorrect id being set with the callback function)
if ( existsFl & & setFlag )
if ( ( rc = _cmPrefsSetValues2 ( p , pnp , boolVal , intVal , realVal , strVal , & valCnt ) ) ! = kOkPrRC )
goto errLabel ;
// if a new variable was created then notify the application of the new value
if ( existsFl = = false )
{
assert ( pnp ! = NULL ) ;
_cmPrefsCallback ( p , pnp - > id ) ;
}
errLabel :
cmMemFree ( pathStr ) ;
return rc ;
}
cmPrRC_t cmPrefsCreateBool ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , bool val )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
bool v = val ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kBoolTId , NULL , NULL , NULL , & v , 1 , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateUInt ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , unsigned val )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
int v = val ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kIntTId , NULL , NULL , & v , NULL , 1 , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateInt ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , int val )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
int v = val ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kIntTId , NULL , NULL , & v , NULL , 1 , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateFloat ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , float val )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
double v = val ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kRealTId , NULL , & v , NULL , NULL , 1 , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateReal ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , double val )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
double v = val ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kRealTId , NULL , & v , NULL , NULL , 1 , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateString ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , const cmChar_t * val )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
const cmChar_t * v = val ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kStringTId , & v , NULL , NULL , NULL , 1 , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateBoolArray ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , const bool * val , unsigned eleCnt )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kBoolTId , NULL , NULL , NULL , val , eleCnt , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateUIntArray ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , const unsigned * val , unsigned eleCnt )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kIntTId , NULL , NULL , ( int * ) val , NULL , eleCnt , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateIntArray ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , const int * val , unsigned eleCnt )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kIntTId , NULL , NULL , val , NULL , eleCnt , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateFloatArray ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , const float * val , unsigned eleCnt )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
double * a = cmMemAlloc ( double , eleCnt ) ;
unsigned i ;
for ( i = 0 ; i < eleCnt ; + + i )
a [ i ] = val [ i ] ;
cmPrRC_t rc = _cmPrefsCreateJsonNode ( p , id , pathStr , kRealTId , NULL , a , NULL , NULL , eleCnt , cmIsFlag ( flags , kForceValuePrFl ) ) ;
cmMemFree ( a ) ;
return rc ;
}
cmPrRC_t cmPrefsCreateRealArray ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , const double * val , unsigned eleCnt )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kRealTId , NULL , val , NULL , NULL , eleCnt , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
cmPrRC_t cmPrefsCreateStringArray ( cmPrH_t h , unsigned id , const cmChar_t * pathStr , unsigned flags , const cmChar_t * * val , unsigned eleCnt )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return _cmPrefsCreateJsonNode ( p , id , pathStr , kStringTId , val , NULL , NULL , NULL , eleCnt , cmIsFlag ( flags , kForceValuePrFl ) ) ;
}
bool cmPrefsIsDirty ( cmPrH_t h )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
return p - > dirtyFl ;
}
2013-03-27 19:12:26 +00:00
2012-10-30 03:52:39 +00:00
cmPrRC_t cmPrefsWrite ( cmPrH_t h , const cmChar_t * fn )
{
cmPrRC_t rc = kOkPrRC ;
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
if ( fn = = NULL )
fn = p - > fn ;
2013-03-27 19:12:26 +00:00
if ( cmJsonWrite ( p - > jsH , cmJsonRoot ( p - > jsH ) , fn ) ! = kOkJsRC )
2012-10-30 03:52:39 +00:00
return cmErrMsg ( & p - > err , kWriteFileFailPrRC , " Preference writing failed. " ) ;
p - > dirtyFl = false ;
2013-03-27 19:12:26 +00:00
2012-10-30 03:52:39 +00:00
return rc ;
}
2012-12-04 01:16:41 +00:00
void cmPrefsReport ( cmPrH_t h )
{
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
cmJsonReport ( p - > jsH ) ;
}
2012-10-30 03:52:39 +00:00
//=============================================================================================
// cmPrefsTest()
//
void _cmPrintNode ( const cmPrNode_t * np )
{
const cmPrPath_t * pp = np - > pathPtr ;
const cmJsonNode_t * jnp = np - > nodePtr ;
const cmJsonNode_t * jpp = jnp - > ownerPtr ;
printf ( " id:%i type:0x%x parent:0x%x " , np - > id , jnp - > typeId , jpp = = NULL ? 0 : jpp - > typeId ) ;
while ( pp ! = NULL )
{
printf ( " %s " , pp - > label ) ;
pp = pp - > parentPtr ;
}
printf ( " \n " ) ;
}
void _cmPrintNodes ( const cmPrNode_t * np )
{
if ( np = = NULL )
return ;
_cmPrintNode ( np ) ;
_cmPrintNodes ( np - > linkPtr ) ;
}
/* example preferences file
{
" cfg " :
{
" inAudDevIdx " : 0
" outAudDevIdx " : 0
" syncInputFl " : false
" midiPortBufByteCnt " : 8192
" msgQueueByteCnt " : 64768
" devFramesPerCycle " : 128
" dspFramesPerCycle " : 64
" audioBufCnt " : 3
" srate " : 44100.000000
" chNames " :
{
" left " : 0
" right " : 1
" array " :
[
0 ,
1 ,
2
]
}
}
}
*/
2013-03-27 19:12:26 +00:00
void cmPrefsTest1 ( cmCtx_t * ctx , const char * ifn , const char * ofn )
2012-10-30 03:52:39 +00:00
{
cmPrH_t h = cmPrNullHandle ;
2013-03-27 19:12:26 +00:00
if ( cmPrefsInitialize ( ctx , & h , ifn , NULL , NULL , " pref " ) ! = kOkPrRC )
2012-10-30 03:52:39 +00:00
return ;
cmPr_t * p = _cmPrefsHandleToPtr ( h ) ;
_cmPrintNodes ( p - > idChainPtr ) ;
unsigned id ;
id = cmPrefsId ( h , " cfg/audioBufCnt " , true ) ;
printf ( " id:%i \n " , id ) ;
//id = cmPrefsId(h, "cfg/audioBuf", true );
//printf("id:%i\n",id);
int sr ;
unsigned n = 1 ;
cmPrefsGetInt ( h , cmPrefsId ( h , " cfg/srate " , true ) , & sr , & n ) ;
printf ( " sr:%i %i \n " , sr , n ) ;
cmPrefsGetInt ( h , cmPrefsId ( h , " cfg/chNames/array " , true ) , & sr , & n ) ;
printf ( " sr:%i %i \n " , sr , n ) ;
int arr [ 4 ] ;
n = 4 ;
cmPrefsGetInt ( h , cmPrefsId ( h , " cfg/chNames/array " , true ) , arr , & n ) ;
printf ( " array:%i %i %i n=%i \n " , arr [ 0 ] , arr [ 1 ] , arr [ 2 ] , n ) ;
sr = 44100 ;
n = 1 ;
2012-11-01 01:01:51 +00:00
cmPrefsSetIntArray ( h , cmPrefsId ( h , " cfg/srate " , true ) , & sr , & n ) ;
2012-10-30 03:52:39 +00:00
cmPrefsGetInt ( h , cmPrefsId ( h , " cfg/chNames/array " , true ) , & sr , & n ) ;
printf ( " sr:%i %i \n " , sr , n ) ;
int sarr [ ] = { 10 , 11 , 12 , 13 } ;
n = sizeof ( sarr ) / sizeof ( sarr [ 0 ] ) ;
2012-11-01 01:01:51 +00:00
cmPrefsSetIntArray ( h , cmPrefsId ( h , " cfg/chNames/array " , true ) , sarr , & n ) ;
2012-10-30 03:52:39 +00:00
cmPrefsGetInt ( h , cmPrefsId ( h , " cfg/chNames/array " , true ) , sarr , & n ) ;
printf ( " array:%i %i %i %i n=%i \n " , sarr [ 0 ] , sarr [ 1 ] , sarr [ 2 ] , sarr [ 3 ] , n ) ;
int tarr [ ] = { 20 , 21 } ;
n = sizeof ( tarr ) / sizeof ( tarr [ 0 ] ) ;
2012-11-01 01:01:51 +00:00
cmPrefsSetIntArray ( h , cmPrefsId ( h , " cfg/chNames/array " , true ) , tarr , & n ) ;
2012-10-30 03:52:39 +00:00
cmPrefsGetInt ( h , cmPrefsId ( h , " cfg/chNames/array " , true ) , tarr , & n ) ;
printf ( " array:%i %i n=%i \n " , tarr [ 0 ] , tarr [ 1 ] , n ) ;
cmPrefsCreateBool ( h , cmInvalidId , " cfg/flags/flag0 " , 0 , true ) ;
bool bv = cmPrefsBool ( h , cmPrefsId ( h , " cfg/flags/flag0 " , true ) ) ;
printf ( " bool:%i \n " , bv ) ;
cmPrefsCreateString ( h , cmInvalidId , " cfg/audioBufCnt " , 0 , " hey " ) ;
const cmChar_t * strArray [ ] =
{
" snap " , " crackle " , " pop "
} ;
cmPrefsCreateStringArray ( h , cmInvalidId , " cfg/chNames/strList " , 0 , strArray , 3 ) ;
cmPrefsWrite ( h , ofn ) ;
cmPrefsFinalize ( & h ) ;
}
2013-03-27 19:12:26 +00:00
void cmPrefsTest ( cmCtx_t * ctx , const char * ifn , const char * ofn )
{
cmPrH_t h = cmPrNullHandle ;
if ( cmPrefsInitialize ( ctx , & h , ifn , NULL , NULL , " pref " ) ! = kOkPrRC )
return ;
cmPrefsCreateBool ( h , cmInvalidIdx , " cfg/flag " , 0 , true ) ;
cmPrefsCreateString ( h , cmInvalidIdx , " cfg/string " , 0 , " blah " ) ;
cmPrefsCreateInt ( h , cmInvalidIdx , " cfg/stuff/thing0 " , 0 , 1 ) ;
cmPrefsCreateInt ( h , cmInvalidIdx , " cfg/stuff/thing1 " , 0 , 2 ) ;
const char * strArray [ ] = { " blah " , " bloo " , " blug " } ;
cmPrefsCreateStringArray ( h , cmInvalidId , " cfg/stuff/foo " , 0 , strArray , 3 ) ;
cmPrefsPathSetInt ( h , " cfg/stuff/thing0 " , 10 ) ;
if ( ofn ! = NULL )
cmPrefsWrite ( h , ofn ) ;
cmPrefsFinalize ( & h ) ;
}