Index: ext/libicpf/src/cfg.cpp =================================================================== diff -u -N -r771dac1fbb7608aa92942c6cab7c5c8b0cccb791 -r0d9a4d94a98872815d5840d1bcc4d394d455307c --- ext/libicpf/src/cfg.cpp (.../cfg.cpp) (revision 771dac1fbb7608aa92942c6cab7c5c8b0cccb791) +++ ext/libicpf/src/cfg.cpp (.../cfg.cpp) (revision 0d9a4d94a98872815d5840d1bcc4d394d455307c) @@ -126,8 +126,8 @@ #define m_pvProps ((std::vector*)m_hProps) /** Constructs a config object. - * \param[in] bGlobal - specifies if this class should be globally accessible by the get_config() friend - * function. + * \param[in] pCfgBase - pointer to a base handler of the configuration strings + * cound be pointer to xml handler, ini handler or any other */ config::config(config_base* pCfgBase) : m_lock(), @@ -138,1272 +138,511 @@ /** Destructs the config class. */ -/*config::~config() +config::~config() { - try - { - delete m_pvProps; - delete m_pvUnreg; - } - catch(...) - { - } + delete m_pvProps; } -/** Function opens the specified file, reads all the lines sequentially - * and stores discovered property values in the internal structures. - * \param[in] pszFile - path to a .conf file (could have any extension) - * \return -1 on error or 0 if operation finished succesfully - * \note The properties does not have to be registered prior to use this function. +/** Function opens the specified file using the underlying config base + * and converts the values read to a list of properties registered + * earlier. + * + * \param[in] pszPath - path to a file to be read */ -/*int_t config::read(const char_t* pszFile) +void config::read(const char_t* pszPath) { - // NOTE: this function should reset the m_bModified flag - // open the file - FILE* pFile; - if ( (pFile=fopen(pszFile, "r")) == NULL) - return -1; - - char_t szLine[MAX_LINE], *pszData; - - // lock the instance - has to be done here to make sure all settings are - // consistent if reloaded on-the-fly m_lock.lock(); - while(fgets(szLine, MAX_LINE, pFile)) + try { - szLine[MAX_LINE-1]='\0'; // needed when the line is too int_t - pszData=szLine; + // read the data using underlying object + m_pCfgBase->read(pszPath); - // interpret the line - // skip the whitespaces at the beginning - while(is_whitespace(*pszData)) - pszData++; - - // skip the comments and empty lines - if (pszData[0] == '#' || pszData[0] == ';' || pszData[0] == 0) - continue; - - // split the line to the part on the left of '=' and to the right - char_t* pVal=strchr(pszData, '='); - if (pVal != NULL) - { - pVal[0]='\0'; - pVal++; - - // so we have name in the pszData and value pVal - process_line(trim(pszData), trim(pVal)); - } + // and transform it to eatable form using registered properties + load_registered(); } - - m_bModified=false; + catch(...) + { + m_lock.unlock(); + throw; + } m_lock.unlock(); - - m_clbPropertyChanged.exec((ulong_t)-1, NULL); - - fclose(pFile); - - return 0; } -/** Writes all the registered properties into the given file. To avoid - * deleting any comments or unused properties from a file - the function - * read all the file into memory (!) and modifies only the lines that - * contains the requested property key (or adds a new entry at the end). - * After that the file is being overwritten. - * \param[in] pszFile - path to a .conf file to which the properties shoud be written - * \return -1 on error, 0 on success. +/** Writes all the registered properties into the given file using + * the underlying config base to do this. + * + * \param[in] pszPath - path to a file to write the properties to */ -/*int_t config::write(const char_t* pszFile) +void config::write(const char_t* pszPath) { - // if the config was not modified - why bother writing - if (!m_bModified) - return 0; - - // at first - read the current file (whole) - line by line - std::vector vLines; - FILE* pFile=fopen(pszFile, "r"); - if (pFile != NULL) - { - char_t szLine[MAX_LINE]; - while(fgets(szLine, MAX_LINE, pFile)) - { - vLines.push_back((string)trim(szLine)); - } - - fclose(pFile); - } - - // apply the registered properties to the lines - // NOTE: properties in the unreg cannot have changed, so we don't need to bother with them m_lock.lock(); -#ifdef USE_ENCRYPTION - // encrypt everything if needed try { - for (std::vector<_PROP>::iterator it = m_pvProps->begin();it != m_pvProps->end();it++) - { - encrypt_property(&(*it)); - } + // store current properties to the underlying object + store_registered(); + + // and save + m_pCfgBase->save(pszPath); } catch(...) { m_lock.unlock(); throw; } -#endif - bool bFnd=false; - string str; - for (std::vector<_PROP>::iterator it=m_pvProps->begin();it != m_pvProps->end();it++) - { - // process only if the property was modified - // NOTE: if the file has been modified manually then they won't be overwritten - if ((*it).bModified) - { - // check every line that has been read for property match - bFnd=false; - for (std::vector::iterator sit=vLines.begin();sit != vLines.end();sit++) - { - // line matches ? - if ((*sit).cmpn((*it).pszName, strlen((*it).pszName)) == 0) - { - // replace the line with a new value - prepare_line(&(*it), &(*sit)); - bFnd=true; - break; // break the inner 'for' - } - } - - // if the line was not found - add the line at the end - if (!bFnd) - { - prepare_line(&(*it), &str); - vLines.push_back(str); - } - - // mark as written, although it is a lie ;) - (*it).bModified=false; - } - } - m_bModified=false; m_lock.unlock(); - - // save the new copy of file - // NOTE: at this point the props are all marked as non-modified - if the write fails then all the data are lost - if ( (pFile=fopen(pszFile, "w")) == NULL) - return -1; - - for (std::vector::iterator vit=vLines.begin();vit != vLines.end();vit++) - { - if (fprintf(pFile, STRFMT "\n", (const char_t*)(*vit)) < 0) - return -1; - } - - fclose(pFile); - - return 0; } /** Function returns a property type for a given property id. - * \note The function returns only the type, and not the rest of the property flags. - * \param[in] ulProp - property id to get info about. - * \return The property type. + * + * \param[in] uiProp - property id to get info about + * \return The property type along with its flags. */ -/*int_t config::get_proptype(ulong_t ulProp) +uint_t config::get_type(uint_t uiProp) { m_lock.lock(); + uint_t uiRet=m_pvProps->at(uiProp).get_type(); + m_lock.unlock(); - int_t iRet=m_pvProps->at(ulProp).iType & PTM_TYPE; + return uiRet; +} +/** Retrieves the count of values in the specified property. + * + * \param[in] uiProp - property id to retrieve information about + * \return Count of values. + */ +size_t config::get_value_count(uint_t uiProp) +{ + m_lock.lock(); + size_t stRet=m_pvProps->at(uiProp).get_count(); m_lock.unlock(); - return iRet; + + return stRet; } -/** Function registers property with int_t value, specified range and flags. Also - * checks if the property has already been registered if PF_CHECK flag has been specified (if it - * is, then the existing identifier is returned and nothing is changed). - * \param[in] pszName - name of the property (key in key = value) - * \param[in] iDef - default value for the property - * \param[in] iLo - the lesser value of value's allowable range - * \param[in] iHi - the higher value of value's allowable range - * \param[in] iFlags - additional flags that should be associated with property - * \return Property ID of the newly registered property. +/** Removes an array value at a given index. + * + * \param[in] uiProp - property id to have the value removed + * \param[in] stIndex - index of the value to remove */ -/*ulong_t config::register_int(const char_t* pszName, int_t iDef, int_t iLo, int_t iHi, int_t iFlags) +void config::remove_array_value(uint_t uiProp, size_t stIndex) { - // check if there is already registered value with the given name m_lock.lock(); - ulong_t ulRes; - if (iFlags & PF_CHECK && (ulRes=is_registered(pszName)) != (ulong_t)-1) - { - m_lock.unlock(); - return ulRes; - } - else - { - _PROP property; - - // check if the property is in the unreg container - if ( (ulRes = is_unreg(pszName)) == (ulong_t)-1 ) - { - // property not found in the unreg - means that this is quite new stuff - property.bModified=true; - property.pszName=new char_t[strlen(pszName)+1]; - strcpy(property.pszName, pszName); - property.val.i.iVal=iDef; // will be overwritten when reading file - } - else - { - // get the entry - property=m_pvUnreg->at(ulRes); - m_pvUnreg->erase(m_pvUnreg->begin()+ulRes); - - // set the value from a string - int_t iVal=atol(property.val.pszVal); - delete [] property.val.pszVal; - property.val.i.iVal=iVal; - } - - // common part - property.iType=PT_INT | iFlags; - property.val.i.iLo=iLo; - property.val.i.iHi=iHi; - - // add to the list - m_pvProps->push_back(property); - m_bModified=true; - ulRes=(ulong_t)(m_pvProps->size()-1); - m_lock.unlock(); - - return ulRes; - } + m_pvProps->at(uiProp).remove(stIndex); + m_lock.unlock(); } -/** Function registers property with uint_t value, specified range and flags. Also - * checks if the property is registered if PF_CHECK flag has been specified (if it - * is, then the existing identifier is returned and nothing is changed. - * \param[in] pszName - name of the property (key in key = value) - * \param[in] uiDef - default value for the property - * \param[in] uiLo - the lesser value of value's allowable range - * \param[in] uiHi - the higher value of value's allowable range - * \param[in] iFlags - additional flags that should be associated with property - * \return Property ID of the newly registered property. +/** Clears the list of values in the given property. + * + * \param[in] uiProp - property id to have the values cleared */ -/*ulong_t config::register_uint(const char_t* pszName, uint_t uiDef, uint_t uiLo, uint_t uiHi, int_t iFlags) +void config::clear_array_values(uint_t uiProp) { - // check if there is already registered value with the given name m_lock.lock(); - ulong_t ulRes; - if (iFlags & PF_CHECK && (ulRes=is_registered(pszName)) != (ulong_t)-1) - { - m_lock.unlock(); - return ulRes; - } - else - { - _PROP property; - - if ( (ulRes = is_unreg(pszName)) == (ulong_t)-1 ) - { - property.pszName=new char_t[strlen(pszName)+1]; - strcpy(property.pszName, pszName); - property.val.ui.uiVal=uiDef; // will be overwritten when reading file - property.bModified=true; - } - else - { - // get the entry - property=m_pvUnreg->at(ulRes); - m_pvUnreg->erase(m_pvUnreg->begin()+ulRes); - - uint_t uiVal=strtoul(property.val.pszVal, NULL, 10); - delete [] property.val.pszVal; - property.val.ui.uiVal=uiVal; - } + m_pvProps->at(uiProp).clear_array(); + m_lock.unlock(); +} - // common part - property.iType=PT_UINT | iFlags; - property.val.ui.uiLo=uiLo; - property.val.ui.uiHi=uiHi; - - // add to the list - m_pvProps->push_back(property); - m_bModified=true; - ulRes=(ulong_t)(m_pvProps->size()-1); - m_lock.unlock(); - - return ulRes; - } +/** Retrieves the count of registered properties contained in this config. + * + * \return Count of properties. + */ +size_t config::count() +{ + return m_pvProps->size(); } -/** Function registers property with longlong_t value, specified range and flags. Also - * checks if the property is registered if PF_CHECK flag has been specified (if it - * is, then the existing identifier is returned and nothing is changed. - * \param[in] pszName - name of the property (key in key = value) +/** Function registers the signed number property. If the underlying base object + * contains a string with a specified key - the value is being translated to + * the value of this property. + * + * \param[in] pszName - name of the property * \param[in] llDef - default value for the property - * \param[in] llLo - the lesser value of value's allowable range - * \param[in] llHi - the higher value of value's allowable range - * \param[in] iFlags - additional flags that should be associated with property + * \param[in] llLo - the lower bound of the allowable value range + * \param[in] llHi - the higher bound of the allowable value range + * \param[in] uiFlags - additional flags that should be associated with property * \return Property ID of the newly registered property. */ -/*ulong_t config::register_longlong(const char_t* pszName, longlong_t llDef, longlong_t llLo, longlong_t llHi, int_t iFlags) +uint_t config::register_signed_num(const tchar_t* pszName, ll_t llDef, ll_t llLo, ll_t llHi, uint_t uiFlags) { - // check if there is already registered value with the given name + // prepare the property to insert + property prop(pszName, property::type_signed_num | (uiFlags & property::mask_flags)); + prop.set_signed_range(llLo, llHi); + + // and operate inside the internals m_lock.lock(); - ulong_t ulRes; - if (iFlags & PF_CHECK && (ulRes=is_registered(pszName)) != (ulong_t)-1) + + // get the value for the property name + ptr_t hFind=NULL; + if ( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - m_lock.unlock(); - return ulRes; - } - else - { - _PROP property; - - if ( (ulRes = is_unreg(pszName)) == (ulong_t)-1 ) + const tchar_t* psz=NULL; + while( (psz=m_pCfgBase->find_next(hFind)) != NULL) { - property.pszName=new char_t[strlen(pszName)+1]; - strcpy(property.pszName, pszName); - property.val.ll.llVal=llDef; // will be overwritten when reading file - property.bModified=true; + prop.set_value(psz, property::action_add); } - else - { - // get the entry - property=m_pvUnreg->at(ulRes); - m_pvUnreg->erase(m_pvUnreg->begin()+ulRes); - ll_t llVal; -#ifdef _WIN32 - llVal=_atoi64(property.val.pszVal); -#else - llVal=atoll(property.val.pszVal); -#endif - delete [] property.val.pszVal; - property.val.ll.llVal=llVal; - } + m_pCfgBase->find_close(hFind); + } + else if (!(uiFlags & property::flag_array)) + prop.set_signed_num(llDef); - // common - property.iType=PT_LONGLONG | iFlags; - property.val.ll.llLo=llLo; - property.val.ll.llHi=llHi; + // add to the vector + m_pvProps->push_back(prop); + uint_t uiProp=(uint_t)(m_pvProps->size()-1); - // add to the list - m_pvProps->push_back(property); - m_bModified=true; - ulRes=(ulong_t)(m_pvProps->size()-1); - m_lock.unlock(); - - return ulRes; - } + m_lock.unlock(); + + return uiProp; } -/** Function registers property with ulonglong_t value, specified range and flags. Also - * checks if the property is registered if PF_CHECK flag has been specified (if it - * is, then the existing identifier is returned and nothing is changed. - * \param[in] pszName - name of the property (key in key = value) +/** Function registers the unsigned number property. If the underlying base object + * contains a string with a specified key - the value is being translated to + * the value of this property. + * + * \param[in] pszName - name of the property * \param[in] ullDef - default value for the property - * \param[in] ullLo - the lesser value of value's allowable range - * \param[in] ullHi - the higher value of value's allowable range - * \param[in] iFlags - additional flags that should be associated with property + * \param[in] ullLo - the lower bound of the allowable value range + * \param[in] ullHi - the higher bound of the allowable value range + * \param[in] uiFlags - additional flags that should be associated with property * \return Property ID of the newly registered property. */ -/*ulong_t config::register_ulonglong(const char_t* pszName, ulonglong_t ullDef, ulonglong_t ullLo, ulonglong_t ullHi, int_t iFlags) +uint_t config::register_unsigned_num(const tchar_t* pszName, ull_t ullDef, ull_t ullLo, ull_t ullHi, uint_t uiFlags) { - // check if there is already registered value with the given name + // prepare the property to insert + property prop(pszName, property::type_unsigned_num | (uiFlags & property::mask_flags)); + prop.set_unsigned_range(ullLo, ullHi); + + // and operate inside the internals m_lock.lock(); - ulong_t ulRes; - if (iFlags & PF_CHECK && (ulRes=is_registered(pszName)) != (ulong_t)-1) + + // get the value for the property name + ptr_t hFind=NULL; + if ( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - m_lock.unlock(); - return ulRes; - } - else - { - _PROP property; - - if ( (ulRes = is_unreg(pszName)) == (ulong_t)-1 ) + const tchar_t* psz=NULL; + while( (psz=m_pCfgBase->find_next(hFind)) != NULL) { - property.pszName=new char_t[strlen(pszName)+1]; - strcpy(property.pszName, pszName); - property.val.ull.ullVal=ullDef; // will be overwritten when reading file - property.bModified=true; + prop.set_value(psz, property::action_add); } - else - { - property=m_pvUnreg->at(ulRes); - m_pvUnreg->erase(m_pvUnreg->begin()+ulRes); - ull_t ullVal; -#ifdef _WIN32 - ullVal=(ulonglong_t)_atoi64(property.val.pszVal); -#else - ullVal=(ulonglong_t)atoll(property.val.pszVal); -#endif - delete [] property.val.pszVal; - property.val.ull.ullVal=ullVal; - } + m_pCfgBase->find_close(hFind); + } + else if (!(uiFlags & property::flag_array)) + prop.set_unsigned_num(ullDef); - // common - property.iType=PT_ULONGLONG | iFlags; - property.val.ull.ullLo=ullLo; - property.val.ull.ullHi=ullHi; + // add to the vector + m_pvProps->push_back(prop); + uint_t uiProp=(uint_t)(m_pvProps->size()-1); - // add to the list - m_pvProps->push_back(property); - m_bModified=true; - ulRes=(ulong_t)(m_pvProps->size()-1); - m_lock.unlock(); - - return ulRes; - } + m_lock.unlock(); + + return uiProp; } -/** Function registers property with bool value and flags. Also - * checks if the property is registered if PF_CHECK flag has been specified (if it - * is, then the existing identifier is returned and nothing is changed. - * \param[in] pszName - name of the property (key in key = value) +/** Function registers the boolean property. If the underlying base object + * contains a string with a specified key - the value is being translated to + * the value of this property. + * + * \param[in] pszName - name of the property * \param[in] bDef - default value for the property - * \param[in] iFlags - additional flags that should be associated with property + * \param[in] uiFlags - additional flags that should be associated with property * \return Property ID of the newly registered property. */ -/*ulong_t config::register_bool(const char_t* pszName, bool bDef, int_t iFlags) +uint_t config::register_bool(const tchar_t* pszName, bool bDef, uint_t uiFlags) { - // check if there is already registered value with the given name + // prepare the property to insert + property prop(pszName, property::type_bool | (uiFlags & property::mask_flags)); + + // and operate inside the internals m_lock.lock(); - ulong_t ulRes; - if (iFlags & PF_CHECK && (ulRes=is_registered(pszName)) != (ulong_t)-1) + + // get the value for the property name + ptr_t hFind=NULL; + if ( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - m_lock.unlock(); - return ulRes; - } - else - { - _PROP property; - - if ( (ulRes = is_unreg(pszName)) == (ulong_t)-1 ) + const tchar_t* psz=NULL; + while( (psz=m_pCfgBase->find_next(hFind)) != NULL) { - property.pszName=new char_t[strlen(pszName)+1]; - strcpy(property.pszName, pszName); - property.val.bVal=bDef; // current - property.bModified=true; + prop.set_value(psz, property::action_add); } - else - { - property=m_pvUnreg->at(ulRes); - m_pvUnreg->erase(m_pvUnreg->begin()+ulRes); - - bool bVal; - if (strcmp(property.val.pszVal, "yes") == 0) - bVal=true; - else if (strcmp(property.val.pszVal, "no") == 0) - bVal=false; - else - bVal=atoi(property.val.pszVal) != 0; - delete [] property.val.pszVal; - property.val.bVal=bVal; - } + m_pCfgBase->find_close(hFind); + } + else if (!(uiFlags & property::flag_array)) + prop.set_bool(bDef); - // common - property.iType=PT_BOOL | iFlags; + // add to the vector + m_pvProps->push_back(prop); + uint_t uiProp=(uint_t)(m_pvProps->size()-1); - // add to the list - m_pvProps->push_back(property); - m_bModified=true; - ulRes=(ulong_t)(m_pvProps->size()-1); - m_lock.unlock(); - - return ulRes; - } + m_lock.unlock(); + + return uiProp; } -/** Function registers property with string value and flags. Also - * checks if the property is registered if PF_CHECK flag has been specified (if it - * is, then the existing identifier is returned and nothing is changed. - * If the property is marked as encrypted, then the default value is being treated as - * unencrypted (and the appropriate flag is being set). - * \param[in] pszName - name of the property (key in key = value) +/** Function registers the string property. If the underlying base object + * contains a string with a specified key - the value is being translated to + * the value of this property. + * + * \param[in] pszName - name of the property * \param[in] pszDef - default value for the property - * \param[in] iFlags - additional flags that should be associated with property + * \param[in] uiFlags - additional flags that should be associated with property * \return Property ID of the newly registered property. */ -/*ulong_t config::register_string(const char_t* pszName, const char_t* pszDef, int_t iFlags) +uint_t config::register_string(const tchar_t* pszName, const tchar_t* pszDef, uint_t uiFlags) { - // check if there is already registered value with the given name + // prepare the property to insert + property prop(pszName, property::type_string | (uiFlags & property::mask_flags)); + + // and operate inside the internals m_lock.lock(); - ulong_t ulRes; - if (iFlags & PF_CHECK && (ulRes=is_registered(pszName)) != (ulong_t)-1) + + // get the value for the property name + ptr_t hFind=NULL; + if ( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - m_lock.unlock(); - return ulRes; - } - else - { - _PROP property; - - if ( (ulRes = is_unreg(pszName)) == (ulong_t)-1 ) + const tchar_t* psz=NULL; + while( (psz=m_pCfgBase->find_next(hFind)) != NULL) { - property.iType=PT_STRING | iFlags; -#ifdef USE_ENCRYPTION - if (iFlags & PF_ENCRYPTED) - property.iType |= PF_DECODED; -#endif - property.pszName=new char_t[strlen(pszName)+1]; - strcpy(property.pszName, pszName); - - property.val.pszVal=new char_t[strlen(pszDef)+1]; - strcpy(property.val.pszVal, pszDef); - property.bModified=true; + prop.set_value(psz, property::action_add); } - else - { - property=m_pvUnreg->at(ulRes); - m_pvUnreg->erase(m_pvUnreg->begin()+ulRes); - property.iType = PT_STRING | iFlags; - } - - // add to the list - m_pvProps->push_back(property); - m_bModified=true; - ulRes=(ulong_t)(m_pvProps->size()-1); - m_lock.unlock(); - return ulRes; + m_pCfgBase->find_close(hFind); } -} + else if (!(uiFlags & property::flag_array)) + prop.set_string(pszDef); -/** Functions retrieves the int_t value associated with a given property ID. Can be called - * from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \return The property value. - */ -/*int_t config::get_int(ulong_t ulProp) -{ - m_lock.lock(); + // add to the vector + m_pvProps->push_back(prop); + uint_t uiProp=(uint_t)(m_pvProps->size()-1); - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_INT); - - int_t iRet=m_pvProps->at(ulProp).val.i.iVal; m_lock.unlock(); - return iRet; + + return uiProp; } -/** Functions retrieves the uint_t value associated with a given property ID. Can be called - * from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \return The property value. +/** Function retrieves the value as string. + * + * \param[in] uiProp - property to retrieve the value of + * \param[out] pszBuffer - pointer to a buffer to receive the string (unused + * if retrieving a string value) + * \param[in] stMaxSize - size of the buffer + * \param[in] stIndex - index of the value to retrieve (meaningful only for + * array-based properties) + * \return Pointer to the string. + * + * \note Always use the returned value instead of the buffer contents. Returned + * value may point to some other memory location instead of pszBuffer. */ -/*uint_t config::get_uint(ulong_t ulProp) +const tchar_t* config::get_value(uint_t uiProp, tchar_t* pszBuffer, size_t stMaxSize, size_t stIndex) { m_lock.lock(); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_UINT); - - uint_t ulRet=m_pvProps->at(ulProp).val.ui.uiVal; + const tchar_t* psz=m_pvProps->at(uiProp).get_value(pszBuffer, stMaxSize, stIndex); m_lock.unlock(); - return ulRet; -} -/** Functions retrieves the longlong_t value associated with a given property ID. Can be called - * from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \return The property value. - */ -/*longlong_t config::get_longlong(ulong_t ulProp) -{ - m_lock.lock(); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_LONGLONG); - - longlong_t llRet=m_pvProps->at(ulProp).val.ll.llVal; - m_lock.unlock(); - return llRet; + return psz; } -/** Functions retrieves the ulonglong_t value associated with a given property ID. Can be called - * from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \return The property value. +/** Function retrieves the signed number value. + * + * \param[in] uiProp - property to retrieve the value of + * \param[in] stIndex - index of the value to retrieve (meaningful only for + * array-based properties) + * \return Property value. */ -/*ulonglong_t config::get_ulonglong(ulong_t ulProp) +ll_t config::get_signed_num(uint_t uiProp, size_t stIndex) { m_lock.lock(); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_ULONGLONG); - - ulonglong_t ullRet=m_pvProps->at(ulProp).val.ull.ullVal; + ll_t ll=m_pvProps->at(uiProp).get_signed_num(stIndex); m_lock.unlock(); - return ullRet; + return ll; } -/** Functions retrieves the bool value associated with a given property ID. Can be called - * from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \return The property value. +/** Function retrieves the unsigned number value. + * + * \param[in] uiProp - property to retrieve the value of + * \param[in] stIndex - index of the value to retrieve (meaningful only for + * array-based properties) + * \return Property value. */ -/*bool config::get_bool(ulong_t ulProp) +ull_t config::get_unsigned_num(uint_t uiProp, size_t stIndex) { m_lock.lock(); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_BOOL); - - bool bRet=m_pvProps->at(ulProp).val.bVal; + ull_t ull=m_pvProps->at(uiProp).get_unsigned_num(stIndex); m_lock.unlock(); - return bRet; + return ull; } -/** Functions retrieves the string value associated with a given property ID. Can be called - * from any thread. The string contained in the internal structure is copied to the buffer - * specified by user. Max count of chars that can be copied is specified by the buffer length. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \param[out] psz - buffer for the string - * \param[in] tMaxLen - length of the buffer +/** Function retrieves the bool value. + * + * \param[in] uiProp - property to retrieve the value of + * \param[in] stIndex - index of the value to retrieve (meaningful only for + * array-based properties) + * \return Property value. */ -/*void config::get_string(ulong_t ulProp, char_t* psz, size_t tMaxLen) +bool config::get_bool(uint_t uiProp, size_t stIndex) { m_lock.lock(); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_STRING); - - _PROP& property=m_pvProps->at(ulProp); - -#ifdef USE_ENCRYPTION - // if the property is encrypted and not decoded yet - decode it - try - { - decrypt_property(&property); - } - catch(...) - { - m_lock.unlock(); - throw; - } -#endif - - char_t* pszSrc=property.val.pszVal; - strncpy(psz, pszSrc, tMaxLen); - psz[tMaxLen-1]='\0'; - + bool b=m_pvProps->at(uiProp).get_bool(stIndex); m_lock.unlock(); + return b; } -/** Functions retrieves the int_t value associated with a given property ID. Can be called - * from any thread. Function returns a pointer to a string contained in the internal structures - * so it is definitely faster than the other get_string function, but is much nore dangerous. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \return The pointer to a string contained in the internal structure. +/** Function retrieves the string value. + * + * \param[in] uiProp - property to retrieve the value of + * \param[in] stIndex - index of the value to retrieve (meaningful only for + * array-based properties) + * \return Property value. */ -/*char_t* config::get_string(ulong_t ulProp) +const tchar_t* config::get_string(uint_t uiProp, size_t stIndex) { m_lock.lock(); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_STRING); - - _PROP& property=m_pvProps->at(ulProp); - -#ifdef USE_ENCRYPTION - // if the property is encrypted and not decoded yet - decode it - try - { - decrypt_property(&property); - } - catch(...) - { - m_lock.unlock(); - throw; - } -#endif - - char_t* psz=property.val.pszVal; - char_t* pszNew=new char_t[strlen(psz)+1]; - strcpy(pszNew, psz); - + const tchar_t* psz=m_pvProps->at(uiProp).get_string(stIndex); m_lock.unlock(); - - return pszNew; + return psz; } -/** Function sets the int_t value for a property with specified ID. Can be - * called from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \param[in] lVal - the new value of property to set +/** Function sets the property value from string. + * + * \param[in] uiProp - property id to set the value for + * \param[in] pszVal - string with property value + * \param[in] a - action to take if the property is array based + * \param[in] tIndex - index of a value to set at (for action action_setat) + * \param[out] pTracker - property tracker that collects the property ID's */ -/*void config::set_int(ulong_t ulProp, int_t iVal, property_tracker* pGroup) +void config::set_value(uint_t uiProp, const tchar_t* pszVal, property::actions a, size_t tIndex, property_tracker* pTracker) { m_lock.lock(); - - // get the data - _PROP& property=m_pvProps->at(ulProp); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_INT); - - int_t iOldVal=property.val.i.iVal; - - // check the range - if (iVal < property.val.i.iLo) - property.val.i.iVal=property.val.i.iLo; - else if (iVal > property.val.i.iHi) - property.val.i.iVal=property.val.i.iHi; - else - property.val.i.iVal=iVal; - - bool bMod=(property.val.i.iVal != iOldVal); - if (bMod) - { - property.bModified=true; - m_bModified=true; - } + m_pvProps->at(uiProp).set_value(pszVal, a, tIndex); + if (pTracker) + pTracker->add(uiProp); m_lock.unlock(); - - if (bMod) - { - if (pGroup) - pGroup->add(ulProp); - else - { - property_tracker* pg=begin_group((ulong_t)-1); - pg->add(ulProp); - end_group(pg); - } - } } -/** Function sets the uint_t value for a property with specified ID. Can be - * called from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \param[in] uiVal - the new value of property to set +/** Function sets the signed number property value. + * + * \param[in] uiProp - property id to set the value for + * \param[in] llVal - property value to set + * \param[in] a - action to take if the property is array based + * \param[in] tIndex - index of a value to set at (for action action_setat) + * \param[out] pTracker - property tracker that collects the property ID's */ -/*void config::set_uint(ulong_t ulProp, uint_t uiVal, property_tracker* pGroup) +void config::set_signed_num(uint_t uiProp, ll_t llVal, property::actions a, size_t tIndex, property_tracker* pTracker) { m_lock.lock(); - - // get the data - _PROP& property=m_pvProps->at(ulProp); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_UINT); - - uint_t uiOldVal=property.val.ui.uiVal; - - // check the range - if (uiVal < property.val.ui.uiLo) - property.val.ui.uiVal=property.val.ui.uiLo; - else if (uiVal > property.val.ui.uiHi) - property.val.ui.uiVal=property.val.ui.uiHi; - else - property.val.ui.uiVal=uiVal; - - bool bMod=(property.val.ui.uiVal != uiOldVal); - - if (bMod) - { - property.bModified=true; - m_bModified=true; - } + m_pvProps->at(uiProp).set_signed_num(llVal, a, tIndex); + if (pTracker) + pTracker->add(uiProp); m_lock.unlock(); - - if (bMod) - { - if (pGroup) - pGroup->add(ulProp); - else - { - property_tracker* pg=begin_group((ulong_t)-1); - pg->add(ulProp); - end_group(pg); - } - } } -/** Function sets the longlong_t value for a property with specified ID. Can be - * called from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \param[in] llVal - the new value of property to set +/** Function sets the unsigned number property value. + * + * \param[in] uiProp - property id to set the value for + * \param[in] llVal - property value to set + * \param[in] a - action to take if the property is array based + * \param[in] tIndex - index of a value to set at (for action action_setat) + * \param[out] pTracker - property tracker that collects the property ID's */ -/*void config::set_longlong(ulong_t ulProp, longlong_t llVal, property_tracker* pGroup) +void config::set_unsigned_num(uint_t uiProp, ull_t ullVal, property::actions a, size_t tIndex, property_tracker* pTracker) { m_lock.lock(); - - // get the data - _PROP& property=m_pvProps->at(ulProp); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_LONGLONG); - - ll_t llOldVal=property.val.ll.llVal; - - // check the range - if (llVal < property.val.ll.llLo) - property.val.ll.llVal=property.val.ll.llLo; - else if (llVal > property.val.ll.llHi) - property.val.ll.llVal=property.val.ll.llHi; - else - property.val.ll.llVal=llVal; - - bool bMod=(property.val.ll.llVal != llOldVal); - - if (bMod) - { - property.bModified=true; - m_bModified=true; - } + m_pvProps->at(uiProp).set_unsigned_num(ullVal, a, tIndex); + if (pTracker) + pTracker->add(uiProp); m_lock.unlock(); - - if (bMod) - { - if (pGroup) - pGroup->add(ulProp); - else - { - property_tracker* pg=begin_group((ulong_t)-1); - pg->add(ulProp); - end_group(pg); - } - } } -/** Function sets the ulonglong_t value for a property with specified ID. Can be - * called from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \param[in] ullVal - the new value of property to set +/** Function sets the bool property value. + * + * \param[in] uiProp - property id to set the value for + * \param[in] llVal - property value to set + * \param[in] a - action to take if the property is array based + * \param[in] tIndex - index of a value to set at (for action action_setat) + * \param[out] pTracker - property tracker that collects the property ID's */ -/*void config::set_ulonglong(ulong_t ulProp, ulonglong_t ullVal, property_tracker* pGroup) +void config::set_bool(uint_t uiProp, bool bVal, property::actions a, size_t tIndex, property_tracker* pTracker) { m_lock.lock(); - - // get the data - _PROP& property=m_pvProps->at(ulProp); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_ULONGLONG); - - ull_t ullOldVal=property.val.ull.ullVal; - - // check the range - if (ullVal < property.val.ull.ullLo) - property.val.ull.ullVal=property.val.ull.ullLo; - else if (ullVal > property.val.ull.ullHi) - property.val.ull.ullVal=property.val.ull.ullHi; - else - property.val.ull.ullVal=ullVal; - - bool bMod=(property.val.ull.ullVal != ullOldVal); - - if (bMod) - { - property.bModified=true; - m_bModified=true; - } + m_pvProps->at(uiProp).set_bool(bVal, a, tIndex); + if (pTracker) + pTracker->add(uiProp); m_lock.unlock(); - - if (bMod) - { - if (pGroup) - pGroup->add(ulProp); - else - { - property_tracker* pg=begin_group((ulong_t)-1); - pg->add(ulProp); - end_group(pg); - } - } } -/** Function sets the bool value for a property with specified ID. Can be - * called from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \param[in] bVal - the new value of property to set +/** Function sets the string property value. + * + * \param[in] uiProp - property id to set the value for + * \param[in] llVal - property value to set + * \param[in] a - action to take if the property is array based + * \param[in] tIndex - index of a value to set at (for action action_setat) + * \param[out] pTracker - property tracker that collects the property ID's */ -/*void config::set_bool(ulong_t ulProp, bool bVal, property_tracker* pGroup) +void config::set_string(uint_t uiProp, const tchar_t* pszVal, property::actions a, size_t tIndex, property_tracker* pTracker) { m_lock.lock(); - - // get the data - _PROP& property=m_pvProps->at(ulProp); - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_BOOL); - - bool bMod=(property.val.bVal != bVal); - if (bMod) - { - property.val.bVal=bVal; - - property.bModified=true; - m_bModified=true; - } + m_pvProps->at(uiProp).set_string(pszVal, a, tIndex); + if (pTracker) + pTracker->add(uiProp); m_lock.unlock(); - - if (bMod) - { - if (pGroup) - pGroup->add(ulProp); - else - { - property_tracker* pg=begin_group((ulong_t)-1); - pg->add(ulProp); - end_group(pg); - } - } } -/** Function sets the string value for a property with specified ID. Can be - * called from any thread. - * \param[in] ulProp - property identifier returned by one of the register_* functions - * \param[in] pszVal - the new value of property to set +/** Function reads the values for the registered properties from the underlying + * base config object. */ -/*void config::set_string(ulong_t ulProp, const char_t* pszVal, property_tracker* pGroup) +void config::load_registered() { m_lock.lock(); - _PROP& property=m_pvProps->at(ulProp); - - assert((m_pvProps->at(ulProp).iType & PTM_TYPE) == PT_STRING); - - delete [] property.val.pszVal; - property.val.pszVal=new char_t[strlen(pszVal)+1]; - strcpy(property.val.pszVal, pszVal); - - property.bModified=true; - m_bModified=true; - -#ifdef USE_ENCRYPTION - // make sure the property is marked decoded - if (property.iType & PF_ENCRYPTED) - property.iType |= PF_DECODED; -#endif - - m_lock.unlock(); - - if (pGroup) - pGroup->add(ulProp); - else + ptr_t hFind=NULL; + const tchar_t* psz=NULL; + for (std::vector::iterator it=m_pvProps->begin();it != m_pvProps->end();it++) { - property_tracker* pg=begin_group((ulong_t)-1); - pg->add(ulProp); - end_group(pg); - } -} + // is this an array property ? + if ((*it).is_array()) + (*it).clear_array(); -#ifdef USE_ENCRYPTION - -/** The function starts a new property group. Used to group notifications about the property changes (usually - * sent by using set_* functions. The notification informations are being passed to the callback object only - * after the end_group() was called. - * \param[in] ulID - group id - * \return A pointer to a new property group. Must be released using end_group(). - */ -/*property_tracker* config::begin_group(ulong_t ulID) const -{ - return new property_tracker(ulID); -} - -/** Ends a property group started with a begin_group(). Releases the allocated pointer and sends a group property - * change information to the callback. - * \param[in] pGroup - pointer to the property group allocated with begin_group() - */ -/*void config::end_group(property_tracker* pGroup) -{ - assert(pGroup); - if (pGroup->count() > 0) - m_clbPropertyChanged.exec(pGroup->get_groupid(), (ptr_t)pGroup); - delete pGroup; -} - -/** This function sets a password to be used with the encrypted properties. If this is the first password to be used - * then it is being set only. But if there was another password set previously, then any property encoded with the - * previous password will be decrypted using an old password before setting a new one. - * \param[in] pszPass - a new password to be set. - */ -/*void config::set_password(const char_t* pszPass) -{ - m_lock.lock(); - - if (!m_strPassword.is_empty()) - { - // decrypt everything (if not already) using old password (if exists) - try + // and fill with value(s) + if ( (hFind=m_pCfgBase->find((*it).get_name())) != NULL) { - for (std::vector<_PROP>::iterator it=m_pvProps->begin();it != m_pvProps->end();it++) + while( (psz=m_pCfgBase->find_next(hFind)) != NULL) { - decrypt_property(&(*it)); + (*it).set_value(psz, property::action_add); } } - catch(...) - { - m_lock.unlock(); - throw; - } + + m_pCfgBase->find_close(hFind); } - // set a new pass - char_t szPass[64+1]; - str2key256(pszPass, szPass); - - m_strPassword=(const char_t*)szPass; - m_lock.unlock(); } -/** Internal function that encrypts a one specified property structure. Does make a check regarding - * the correctness of the property. If it does not met the criteria, then function does nothing. - * \param[in/out] property - address of the structure describing the property. +/** Function stores the values of a registered properties to the underlying + * base config object. */ -/*void config::encrypt_property(_PROP* property) const +void config::store_registered() { - printf("Encrypting...\n"); + m_lock.lock(); - if ((property->iType & (PT_STRING | PF_ENCRYPTED | PF_DECODED)) == (PT_STRING | PF_ENCRYPTED | PF_DECODED)) + tchar_t szBuffer[128]; + for (std::vector::iterator it=m_pvProps->begin();it != m_pvProps->end();it++) { - printf("Real encrypt...\n"); - ulong_t ulLen=(ulong_t)(((strlen(property->val.pszVal)+1)*sizeof(char_t)+16)*2); - char_t *pszOut=new char_t[ulLen]; - try - { - strcrypt_aes256(property->val.pszVal, (const char_t*)m_strPassword, pszOut); - } - catch(...) - { - delete [] pszOut; - throw; - } + // clear the current attributes for the property + m_pCfgBase->clear((*it).get_name()); - delete [] property->val.pszVal; - property->val.pszVal=pszOut; - - property->iType &= ~PF_DECODED; - } -} - -/** Internal function that decrypts a one specified property structure. Does make a check regarding - * the correctness of the property. If it does not met the criteria, then function does nothing. - * \param[in/out] property - address of the structure describing the property. - */ -/*void config::decrypt_property(_PROP* property) const -{ - if ((property->iType & (PT_STRING | PF_ENCRYPTED | PF_DECODED)) == (PT_STRING | PF_ENCRYPTED)) - { - ulong_t ulLen=(ulong_t)(strlen(property->val.pszVal)/2); - char_t *pszOut=new char_t[ulLen]; - try + // and fill with value(s) + size_t tCount=(*it).get_count(); + for (size_t t=0;t != tCount;t++) { - strdecrypt_aes256(property->val.pszVal, (const char_t*)m_strPassword, pszOut); + m_pCfgBase->set_value((*it).get_name(), (*it).get_value(szBuffer, 128, t));; } - catch(...) - { - delete [] pszOut; - throw; - } - - delete [] property->val.pszVal; - property->val.pszVal=pszOut; - - property->iType |= PF_DECODED; } -} -#endif - -/** Function trims whitespaces at the beginning and at the end of a string. - * The data in the string is modified, so any whitespace char_t at the end of a string - * is replaced with '\\0', and the function returns a pointer to the first character - * in the string that is not a whitespace. - * \param[in,out] pszString - string to process - * \return Pointer to the first non-whitespace character in a string. - */ -/*char_t* config::trim(char_t* pszString) const -{ - char_t *pszData=pszString; - - // skip the whitespaces at the beginning - while(is_whitespace(*pszData)) - pszData++; - - // the end - size_t iLen=strlen(pszData); - if (iLen != 0) - { - iLen--; - while (iLen > 0 && is_whitespace(*(pszData+iLen))) - pszData[iLen--]='\0'; - } - return pszData; + m_lock.unlock(); } -/** Processes the two strings given (a key = value) - checks if there is any - * registered property with a given name, and if there is - the given value - * is applied to the property in the format specified by that property. - * \param[in] pszName - name of the property to find - * \param[in] pszValue - value of the property; the string is processed using - * the property type found - */ -/*void config::process_line(const char_t* pszName, const char_t* pszValue) -{ - // check if the property name is registered - for (std::vector<_PROP>::iterator it=m_pvProps->begin();it != m_pvProps->end();it++) - { - if (strcmp((*it).pszName, pszName) == 0) - { - // this function is called from read() which reads the standard stuff from a .conf file - (*it).bModified=false; - - // this is it - type of property - switch (it->iType & PTM_TYPE) - { - case PT_INT: - { - it->val.i.iVal=atol(pszValue); - break; - } - case PT_UINT: - { - it->val.ui.uiVal=strtoul(pszValue, NULL, 10); - break; - } - case PT_LONGLONG: - { -#ifdef _WIN32 - it->val.ll.llVal=_atoi64(pszValue); -#else - it->val.ll.llVal=atoll(pszValue); -#endif - break; - } - case PT_ULONGLONG: - { -#ifdef _WIN32 - it->val.ull.ullVal=(ulonglong_t)_atoi64(pszValue); -#else - it->val.ull.ullVal=(ulonglong_t)atoll(pszValue); -#endif - break; - } - case PT_BOOL: - { - if (strcmp(pszValue, "yes") == 0) - it->val.bVal=true; - else if (strcmp(pszValue, "no") == 0) - it->val.bVal=false; - else - it->val.bVal=atoi(pszValue) != 0; - break; - } - case PT_STRING: - { - // delete the old value and add the new one - delete [] it->val.pszVal; - it->val.pszVal=new char_t[strlen(pszValue)+1]; - strcpy(it->val.pszVal, pszValue); - - // update the encryption ststus -#ifdef USE_ENCRYPTION - (*it).iType &= ~PF_DECODED; -#endif - - break; - } - default: - break; - } - - // we need not more processing - return; - } - } - - // if the property wasn't found - add to the unreg as string property - _PROP property; - property.iType=PT_STRING; - property.pszName=new char_t[strlen(pszName)+1]; - strcpy(property.pszName, pszName); - property.bModified=false; - property.val.pszVal=new char_t[strlen(pszValue)+1]; - strcpy(property.val.pszVal, pszValue); - - m_pvUnreg->push_back(property); -} - -/** Prepares the string with the property value to be written to a file. - * There is no sane limitation of the string length (but one should be careful - * because such a limitation is integrated with read-related functions. - * \param[in] property - pointer to the internal structure with property description - * \param[out] pres - pointer to a string object that will receive the line of text - */ -/*void config::prepare_line(const _PROP* property, string* pres) const -{ - assert(property && pres); - - char_t szLine[MAX_LINE]; - switch(property->iType & PTM_TYPE) - { - case PT_INT: - { - snprintf(szLine, MAX_LINE, STRFMT " = " LFMT, property->pszName, property->val.i.iVal); - break; - } - case PT_UINT: - { - snprintf(szLine, MAX_LINE, STRFMT " = " ULFMT, property->pszName, property->val.ui.uiVal); - break; - } - case PT_LONGLONG: - { - snprintf(szLine, MAX_LINE, STRFMT " = " LLFMT, property->pszName, property->val.ll.llVal); - break; - } - case PT_ULONGLONG: - { - snprintf(szLine, MAX_LINE, STRFMT " = " ULLFMT, property->pszName, property->val.ull.ullVal); - break; - } - case PT_BOOL: - { - snprintf(szLine, MAX_LINE, STRFMT " = " ULFMT, property->pszName, (uint_t)property->val.bVal); - break; - } - case PT_STRING: - { - snprintf(szLine, MAX_LINE, STRFMT " = " STRFMT, property->pszName, property->val.pszVal); - break; - } - default: - break; - } - - szLine[MAX_LINE-1]='\0'; -// printf(szLine); - *pres=szLine; -} - -/** Searches for a property with a given name and returns a property - * ID if found. - * \param[in] pszName - property name to search for - * \return The property ID if property has been found, or -1 if not. - */ -/*ulong_t config::is_registered(const char_t* pszName) -{ - // enum through all of the existing nodes - for (std::vector<_PROP>::iterator it=m_pvProps->begin();it != m_pvProps->end();it++) - { - if (strcmp(pszName, (*it).pszName) == 0) - return (ulong_t)(it-m_pvProps->begin()); - } - - return (ulong_t)-1; // no property found -} - -/** Searches for an unregistered property contained in the unreg container. Returns an - * index in the container unreg (if the entry have been found) or -1 (if not). - * \param[in] pszName - name of the property to search for - * \return Property index if found, -1 if not. - */ -/*ulong_t config::is_unreg(const char_t* pszName) -{ - // enum through all of the existing nodes - for (std::vector<_PROP>::iterator it=m_pvUnreg->begin();it != m_pvUnreg->end();it++) - { - if (strcmp(pszName, (*it).pszName) == 0) - return (ulong_t)(it-m_pvUnreg->begin()); - } - - return (ulong_t)-1; // no property found -}*/ - END_ICPF_NAMESPACE Index: ext/libicpf/src/cfg.h =================================================================== diff -u -N -r771dac1fbb7608aa92942c6cab7c5c8b0cccb791 -r0d9a4d94a98872815d5840d1bcc4d394d455307c --- ext/libicpf/src/cfg.h (.../cfg.h) (revision 771dac1fbb7608aa92942c6cab7c5c8b0cccb791) +++ ext/libicpf/src/cfg.h (.../cfg.h) (revision 0d9a4d94a98872815d5840d1bcc4d394d455307c) @@ -77,12 +77,12 @@ /** \name Construction/destruction */ /**@{*/ config(config_base* pCfgBase); ///< Standard constructor - ~config(); ///< Standard destructor + ~config(); ///< Standard destructor /**@}*/ /** \name Reading and writing to the external medium */ /**@{*/ - void read(const tchar_t *pszPath); ///< Reads the file with properties + void read(const tchar_t *pszPath); ///< Reads the properties from the source file void write(const tchar_t* pszPath); ///< Saves the properties to the file /**@}*/ @@ -121,15 +121,15 @@ /** \name Getting and setting values */ /**@{*/ /// Gets the value of string-type property - const tchar_t* get_value(uint_t uiProp, tchar_t* pszBuffer, size_t stMaxSize, size_t stIndex=0) const; + const tchar_t* get_value(uint_t uiProp, tchar_t* pszBuffer, size_t stMaxSize, size_t stIndex=0); /// Gets the value of longlong_t-type property - ll_t get_signed_num(uint_t uiProp, size_t stIndex=0) const; + ll_t get_signed_num(uint_t uiProp, size_t stIndex=0); /// Gets the value of ulonglong_t-type property - ull_t get_unsigned_num(uint_t uiProp, size_t stIndex=0) const; + ull_t get_unsigned_num(uint_t uiProp, size_t stIndex=0); /// Gets the value of bool-type property - bool get_bool(uint_t uiProp, size_t stIndex=0) const; + bool get_bool(uint_t uiProp, size_t stIndex=0); /// Gets the value of string-type property - const tchar_t* get_string(uint_t uiProp, size_t stIndex=0) const; + const tchar_t* get_string(uint_t uiProp, size_t stIndex=0); // setting property data /// Sets the value from the string @@ -145,6 +145,10 @@ /**@}*/ protected: + void load_registered(); ///< Loads the registered property values from the underlying config base + void store_registered(); ///< Stores the registered property values to the underlying config base + +protected: mutex m_lock; ///< Lock for the multi-threaded access to the properties ptr_t m_hProps; ///< Handle to the registered property storage config_base* m_pCfgBase; ///< Underlying base for this class Index: ext/libicpf/src/cfg_xml.cpp =================================================================== diff -u -N -r3e7ccb6efc5089399a7801082d923aeb41f53d2e -r0d9a4d94a98872815d5840d1bcc4d394d455307c --- ext/libicpf/src/cfg_xml.cpp (.../cfg_xml.cpp) (revision 3e7ccb6efc5089399a7801082d923aeb41f53d2e) +++ ext/libicpf/src/cfg_xml.cpp (.../cfg_xml.cpp) (revision 0d9a4d94a98872815d5840d1bcc4d394d455307c) @@ -3,6 +3,7 @@ #include "exception.h" #include #include +#include BEGIN_ICPF_NAMESPACE @@ -279,22 +280,22 @@ * * \param[in] pszName - key name for which the string should be set at * \param[in] pszValue - value to set - * \param[in] bAdd - true if the string should be added to the previous, false if replaced. + * \param[in] a - action to take while setting */ -void xml_cfg::set_value(const tchar_t* pszName, const tchar_t* pszValue, bool bAdd) +void xml_cfg::set_value(const tchar_t* pszName, const tchar_t* pszValue, actions a) { // traverse the current tag tree - set_value(m_pStorage, pszName, pszValue, bAdd); + set_value(m_pStorage, pszName, pszValue, a); } /** Sets the specified value in the given key name - recursive helper function. * * \param[in] pNodePtr - pointer to the xml node to process * \param[in] pszName - key name for which the string should be set at * \param[in] pszValue - value to set - * \param[in] bAdd - true if the string should be added to the previous, false if replaced. + * \param[in] a - action to take while setting */ -void xml_cfg::set_value(ptr_t pNodePtr, const tchar_t* pszName, const tchar_t* pszValue, bool bAdd) +void xml_cfg::set_value(ptr_t pNodePtr, const tchar_t* pszName, const tchar_t* pszValue, actions a) { xml_node* pNode=(xml_node*)pNodePtr; @@ -303,33 +304,62 @@ { xml_storage::iterator it=pNode->m_mNodes.find(tstring(pszName, pszSign-pszName)); if (it != pNode->m_mNodes.end()) - set_value(&(*it).second, pszSign+1, pszValue, bAdd); + set_value(&(*it).second, pszSign+1, pszValue, a); else { std::pair pr=pNode->m_mNodes.insert(xml_storage::value_type(tstring(pszName, pszSign-pszName), xml_node(pNode))); - set_value(&(*pr.first).second, pszSign+1, pszValue, bAdd); + set_value(&(*pr.first).second, pszSign+1, pszValue, a); } } else { - // now it's the key going - if (pszValue == NULL) + // clear if we're replacing + switch(a) { - if (bAdd) - pNode->m_mAttr.erase(tstring(pszName)); // remove the key from map - else - pNode->m_mAttr.clear(); // clear the entire map - } - else - { - // clear if we're replacing - if (!bAdd) - pNode->m_mAttr.clear(); - - // and add + case config_base::action_replace: + pNode->m_mAttr.clear(); + case config_base::action_add: pNode->m_mAttr.insert(attr_storage::value_type(tstring(pszName), tstring(pszValue))); + break; + default: + assert(false); } } } +/** Clear values for a given property name. + * + * \param[in] pszName - name of the property to clear the values for + */ +void xml_cfg::clear(const tchar_t* pszName) +{ + clear(m_pStorage, pszName); +} + +/** Recursive clear function - searches recursively for a proper node + * and finally clears the string map. + * + * \param[in] pNodePtr - pointer to a node to be processed + * \param[in] pszName - name of the property to search for in the given node + */ +void xml_cfg::clear(ptr_t pNodePtr, const tchar_t* pszName) +{ + xml_node* pNode=(xml_node*)pNodePtr; + + // parse the name + tchar_t* pSign=_tcschr(pszName, _t('/')); + if (pSign) + { + // locate the xml_node associated with the name + xml_storage::iterator it=pNode->m_mNodes.find(tstring(pszName, pSign-pszName)); + if (it != pNode->m_mNodes.end()) + clear(&(*it).second, pSign+1); + } + else + { + std::pair pr=pNode->m_mAttr.equal_range(tstring(pszName)); + pNode->m_mAttr.erase(pr.first, pr.second); + } +} + END_ICPF_NAMESPACE Index: ext/libicpf/src/cfg_xml.h =================================================================== diff -u -N -r3e7ccb6efc5089399a7801082d923aeb41f53d2e -r0d9a4d94a98872815d5840d1bcc4d394d455307c --- ext/libicpf/src/cfg_xml.h (.../cfg_xml.h) (revision 3e7ccb6efc5089399a7801082d923aeb41f53d2e) +++ ext/libicpf/src/cfg_xml.h (.../cfg_xml.h) (revision 0d9a4d94a98872815d5840d1bcc4d394d455307c) @@ -38,15 +38,19 @@ /// Closes the search operation virtual void find_close(ptr_t pFindHandle); - /// Sets a value for a given key (either adds to or replaces the previous value) - virtual void set_value(const tchar_t* pszName, const tchar_t* pszValue, bool bAdd); + /// Sets a value for a given key + virtual void set_value(const tchar_t* pszName, const tchar_t* pszValue, actions a=actions::action_add); + /// Clear values for a given property name + virtual void clear(const tchar_t* pszName); /**@}*/ private: /// Find helper - recursively searches for a specific key node ptr_t find(ptr_t pNodePtr, const tchar_t* pszName); /// Set value helper - searches for a specific node and sets the value - void set_value(ptr_t pNodePtr, const tchar_t* pszName, const tchar_t* pszValue, bool bAdd); + void set_value(ptr_t pNodePtr, const tchar_t* pszName, const tchar_t* pszValue, actions a=actions::action_add); + /// Clear helper - clears the appropriate attribures + void clear(ptr_t pNodePtr, const tchar_t* pszName); protected: ptr_t m_hStorage; ///< Handle to the internal xml storage Index: ext/libicpf/src/config_base.h =================================================================== diff -u -N -r771dac1fbb7608aa92942c6cab7c5c8b0cccb791 -r0d9a4d94a98872815d5840d1bcc4d394d455307c --- ext/libicpf/src/config_base.h (.../config_base.h) (revision 771dac1fbb7608aa92942c6cab7c5c8b0cccb791) +++ ext/libicpf/src/config_base.h (.../config_base.h) (revision 0d9a4d94a98872815d5840d1bcc4d394d455307c) @@ -13,6 +13,14 @@ class config_base { public: + /// Actions used when setting value + enum actions + { + action_add, + action_replace + }; + +public: /** \name File operations */ /**@{*/ /// Reads the xml document from the specified file @@ -30,8 +38,10 @@ /// Closes the search operation virtual void find_close(ptr_t pFindHandle) = 0; - /// Sets a value for a given key (either adds to or replaces the previous value) - virtual void set_value(const tchar_t* pszName, const tchar_t* pszValue, bool bAdd) = 0; + /// Sets a value for a given key + virtual void set_value(const tchar_t* pszName, const tchar_t* pszValue, actions a=actions::action_add) = 0; + /// Clear values for a given property name + virtual void clear(const tchar_t* pszName) = 0; /**@}*/ }; Index: ext/libicpf/src/config_property.h =================================================================== diff -u -N -r771dac1fbb7608aa92942c6cab7c5c8b0cccb791 -r0d9a4d94a98872815d5840d1bcc4d394d455307c --- ext/libicpf/src/config_property.h (.../config_property.h) (revision 771dac1fbb7608aa92942c6cab7c5c8b0cccb791) +++ ext/libicpf/src/config_property.h (.../config_property.h) (revision 0d9a4d94a98872815d5840d1bcc4d394d455307c) @@ -66,6 +66,8 @@ void init(const tchar_t* pszName, uint_t uiType, bool bClear=true); /// Retrieves a property type (with flags) uint_t get_type() const { return m_uiPropType; }; + /// Checks if the property is array-based + bool is_array() const { return (m_uiPropType & prop_flags::flag_array) != false; }; /// Sets a property name void set_name(const tchar_t* pszName) { m_pszName=copy_string(pszName); };