Index: ext/libicpf/src/libicpf/cfg.cpp =================================================================== diff -u -N -r86310fdf8a767b700985ebd1b255004d9eb85fb7 -r6e13958c3d83047ec29e5a703d8982025eb22304 --- ext/libicpf/src/libicpf/cfg.cpp (.../cfg.cpp) (revision 86310fdf8a767b700985ebd1b255004d9eb85fb7) +++ ext/libicpf/src/libicpf/cfg.cpp (.../cfg.cpp) (revision 6e13958c3d83047ec29e5a703d8982025eb22304) @@ -138,9 +138,9 @@ { switch(eCfgType) { - case eXml: - m_pCfgBase = new xml_cfg; - break; + //case eXml: + // m_pCfgBase = new xml_cfg; + // break; case eIni: m_pCfgBase = new ini_cfg; break; @@ -322,10 +322,11 @@ ptr_t hFind=NULL; if( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - const tchar_t* psz=NULL; - while( (psz=m_pCfgBase->find_next(hFind)) != NULL) + PROPINFO pi; + while(m_pCfgBase->find_next(hFind, pi)) { - prop.set_value(psz, property::action_add); + assert(!pi.bGroup); + prop.set_value(pi.pszValue, property::action_add); } m_pCfgBase->find_close(hFind); @@ -366,10 +367,11 @@ ptr_t hFind=NULL; if( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - const tchar_t* psz=NULL; - while( (psz=m_pCfgBase->find_next(hFind)) != NULL) + PROPINFO pi; + while(m_pCfgBase->find_next(hFind, pi)) { - prop.set_value(psz, property::action_add); + assert(!pi.bGroup); + prop.set_value(pi.pszValue, property::action_add); } m_pCfgBase->find_close(hFind); @@ -407,10 +409,11 @@ ptr_t hFind=NULL; if( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - const tchar_t* psz=NULL; - while( (psz=m_pCfgBase->find_next(hFind)) != NULL) + PROPINFO pi; + while(m_pCfgBase->find_next(hFind, pi)) { - prop.set_value(psz, property::action_add); + assert(!pi.bGroup); + prop.set_value(pi.pszValue, property::action_add); } m_pCfgBase->find_close(hFind); @@ -448,10 +451,11 @@ ptr_t hFind=NULL; if( (hFind=m_pCfgBase->find(pszName)) != NULL ) { - const tchar_t* psz=NULL; - while( (psz=m_pCfgBase->find_next(hFind)) != NULL) + PROPINFO pi; + while(m_pCfgBase->find_next(hFind, pi)) { - prop.set_value(psz, property::action_add); + assert(!pi.bGroup); + prop.set_value(pi.pszValue, property::action_add); } m_pCfgBase->find_close(hFind); @@ -484,6 +488,11 @@ const tchar_t* config::get_value(uint_t uiProp, tchar_t* pszBuffer, size_t stMaxSize, size_t stIndex) { m_lock.lock(); + if(uiProp >= m_pvProps->size()) + { + m_lock.unlock(); + THROW(_t("Index out of range"), 0, 0, 0); + } const tchar_t* psz=m_pvProps->at(uiProp).get_value(pszBuffer, stMaxSize, stIndex); m_lock.unlock(); @@ -500,6 +509,11 @@ ll_t config::get_signed_num(uint_t uiProp, size_t stIndex) { m_lock.lock(); + if(uiProp >= m_pvProps->size()) + { + m_lock.unlock(); + THROW(_t("Index out of range"), 0, 0, 0); + } ll_t ll=m_pvProps->at(uiProp).get_signed_num(stIndex); m_lock.unlock(); return ll; @@ -515,6 +529,11 @@ ull_t config::get_unsigned_num(uint_t uiProp, size_t stIndex) { m_lock.lock(); + if(uiProp >= m_pvProps->size()) + { + m_lock.unlock(); + THROW(_t("Index out of range"), 0, 0, 0); + } ull_t ull=m_pvProps->at(uiProp).get_unsigned_num(stIndex); m_lock.unlock(); return ull; @@ -530,6 +549,11 @@ bool config::get_bool(uint_t uiProp, size_t stIndex) { m_lock.lock(); + if(uiProp >= m_pvProps->size()) + { + m_lock.unlock(); + THROW(_t("Index out of range"), 0, 0, 0); + } bool b=m_pvProps->at(uiProp).get_bool(stIndex); m_lock.unlock(); return b; @@ -545,8 +569,14 @@ const tchar_t* config::get_string(uint_t uiProp, size_t stIndex) { m_lock.lock(); + if(uiProp >= m_pvProps->size()) + { + m_lock.unlock(); + THROW(_t("Index out of range"), 0, 0, 0); + } const tchar_t* psz=m_pvProps->at(uiProp).get_string(stIndex); m_lock.unlock(); + return psz; } @@ -563,6 +593,11 @@ return NULL; m_lock.lock(); + if(uiProp >= m_pvProps->size()) + { + m_lock.unlock(); + THROW(_t("Index out of range"), 0, 0, 0); + } const tchar_t* psz=m_pvProps->at(uiProp).get_string(stIndex); size_t stLen = _tcslen(psz); if(stLen >= stBufferSize) @@ -574,6 +609,24 @@ return pszBuffer; } +bool config::enum_properties(const tchar_t* pszName, PFNCFGENUMCALLBACK pfn, ptr_t pParam) +{ + ptr_t pFind = m_pCfgBase->find(pszName); + if(pFind) + { + PROPINFO pi; + while(m_pCfgBase->find_next(pFind, pi)) + { + (*pfn)(pi.bGroup, pi.pszName, pi.pszValue, pParam); + } + + m_pCfgBase->find_close(pFind); + return true; + } + else + return false; +} + /** Function sets the property value from string. * * \param[in] uiProp - property id to set the value for @@ -682,7 +735,6 @@ m_lock.lock(); ptr_t hFind=NULL; - const tchar_t* psz=NULL; for (std::vector::iterator it=m_pvProps->begin();it != m_pvProps->end();it++) { // is this an array property ? @@ -692,9 +744,11 @@ // and fill with value(s) if( (hFind=m_pCfgBase->find((*it).get_name())) != NULL) { - while( (psz=m_pCfgBase->find_next(hFind)) != NULL) + PROPINFO pi; + while(m_pCfgBase->find_next(hFind, pi)) { - (*it).set_value(psz, property::action_add); + assert(!pi.bGroup); + (*it).set_value(pi.pszValue, property::action_add); } } Index: ext/libicpf/src/libicpf/cfg.h =================================================================== diff -u -N -r86310fdf8a767b700985ebd1b255004d9eb85fb7 -r6e13958c3d83047ec29e5a703d8982025eb22304 --- ext/libicpf/src/libicpf/cfg.h (.../cfg.h) (revision 86310fdf8a767b700985ebd1b255004d9eb85fb7) +++ ext/libicpf/src/libicpf/cfg.h (.../cfg.h) (revision 6e13958c3d83047ec29e5a703d8982025eb22304) @@ -33,6 +33,8 @@ /// Callback function definition typedef void(*PFNPROPERTYCHANGED)(uint_t, ptr_t); +/// Enumeration callback +typedef void(*PFNCFGENUMCALLBACK)(bool, const tchar_t*, const tchar_t*, ptr_t); /** \brief Property group handling class * @@ -142,6 +144,9 @@ /// Retrieves the copy of the string const tchar_t* get_string(uint_t uiProp, tchar_t* pszBuffer, size_t stBufferSize, size_t stIndex=0); + /// Enumerates attributes (and groups) + bool enum_properties(const tchar_t* pszName, PFNCFGENUMCALLBACK pfn, ptr_t pParam); + // setting property data /// Sets the value from the string void set_value(uint_t uiProp, const tchar_t* pszVal, property::actions a=property::action_replace, size_t tIndex=0, property_tracker* pTracker=NULL); Index: ext/libicpf/src/libicpf/cfg_ini.cpp =================================================================== diff -u -N -r86310fdf8a767b700985ebd1b255004d9eb85fb7 -r6e13958c3d83047ec29e5a703d8982025eb22304 --- ext/libicpf/src/libicpf/cfg_ini.cpp (.../cfg_ini.cpp) (revision 86310fdf8a767b700985ebd1b255004d9eb85fb7) +++ ext/libicpf/src/libicpf/cfg_ini.cpp (.../cfg_ini.cpp) (revision 6e13958c3d83047ec29e5a703d8982025eb22304) @@ -32,8 +32,14 @@ */ struct INIFINDHANDLE { - attr_storage::iterator it; ///< Iterator of currently retrieved string - attr_storage::iterator itEnd; ///< Iterator of a last string matching the criteria + attr_storage::iterator itAttr; ///< Iterator of currently retrieved string + attr_storage::iterator itAttrEnd; ///< Iterator of a last string matching the criteria + + ini_storage::iterator itSection; ///< Section iterator + ini_storage::iterator itSectionEnd; ///< End of section enumeration + + bool bOnlyAttributes; ///< Enumeration type - true = only attributes (does not use section iterators), false = sections + all attributes inside + bool bSection; ///< Is section to be enumerated first ? }; /// Macro for faster access to the xml storage @@ -54,7 +60,7 @@ delete m_pMainNode; } -/** Function reads the contents of the xml file, parses it using expat parser +/** Function reads the contents of the xml file, parses itAttr using expat parser * and then creates xml nodes in memory that could be read using find functions. * * \param[in] pszPath - path to the file to be read @@ -117,7 +123,7 @@ try { - // write bom, check if it succeeded + // write bom, check if itAttr succeeded // if(fwrite(&uiBOM, 1, uiCount, pFile) != uiCount) // THROW(_t("Cannot write the BOM to the file '") TSTRFMT _t("'"), 0, errno, 0); @@ -151,7 +157,7 @@ /** Function starts a search operation. Given the name of the property * to be searched for(ie. "ch/program/startup"), funtion searches for -* it and returns a handle that can be used by subsequent calls to the +* itAttr and returns a handle that can be used by subsequent calls to the * find_next(). Free the handle using find_close() after finish. * * \param[in] pszName - name of the property to search for(in the form of @@ -160,31 +166,46 @@ */ ptr_t ini_cfg::find(const tchar_t* pszName) { - // parse the path - tstring_t strSection; - tstring_t strAttr; - if(!parse_property_name(pszName, strSection, strAttr)) - return NULL; - - ini_storage::iterator iterSection = m_pMainNode->find(strSection); - if(iterSection == m_pMainNode->end()) - return NULL; - - std::pair pairRange; - if(strAttr == _t("*")) + if(pszName == NULL || pszName[0] == _t('*')) { - pairRange.first = (*iterSection).second.begin(); - pairRange.second = (*iterSection).second.end(); + INIFINDHANDLE* pHandle = new INIFINDHANDLE; + pHandle->bOnlyAttributes = false; + pHandle->bSection = true; + pHandle->itSection = m_pMainNode->begin(); + pHandle->itSectionEnd = m_pMainNode->end(); + + return pHandle; } else - pairRange = (*iterSection).second.equal_range(strAttr); - if(pairRange.first != (*iterSection).second.end()) { - INIFINDHANDLE* pHandle = new INIFINDHANDLE; - pHandle->it = pairRange.first; - pHandle->itEnd = pairRange.second; + // parse the path + tstring_t strSection; + tstring_t strAttr; + if(!parse_property_name(pszName, strSection, strAttr)) + return NULL; - return pHandle; + ini_storage::iterator iterSection = m_pMainNode->find(strSection); + if(iterSection == m_pMainNode->end()) + return NULL; + + std::pair pairRange; + if(strAttr == _t("*")) + { + pairRange.first = (*iterSection).second.begin(); + pairRange.second = (*iterSection).second.end(); + } + else + pairRange = (*iterSection).second.equal_range(strAttr); + if(pairRange.first != (*iterSection).second.end()) + { + INIFINDHANDLE* pHandle = new INIFINDHANDLE; + pHandle->bSection = false; + pHandle->bOnlyAttributes = true; + pHandle->itAttr = pairRange.first; + pHandle->itAttrEnd = pairRange.second; + + return pHandle; + } } return NULL; @@ -196,13 +217,64 @@ * \param[in] pFindHandle - handle to the search (as returned from find()) * \return Pointer to a next string found, NULL if none. */ -const tchar_t* ini_cfg::find_next(ptr_t pFindHandle) +bool ini_cfg::find_next(ptr_t pFindHandle, PROPINFO& pi) { + assert(pFindHandle); + if(!pFindHandle) + return NULL; INIFINDHANDLE* pfh=(INIFINDHANDLE*)pFindHandle; - if(pfh->it != pfh->itEnd) - return (*pfh->it++).second.c_str(); + + if(pfh->bOnlyAttributes) + { + if(pfh->itAttr != pfh->itAttrEnd) + { + pi.pszName = (*pfh->itAttr).first.c_str(); + pi.pszValue = (*pfh->itAttr).second.c_str(); + pi.bGroup = false; + pfh->itAttr++; + return true; + } + else + return false; + } else - return NULL; + { + if(pfh->bSection) + { + if(pfh->itSection == pfh->itSectionEnd) + return false; + pfh->bSection = false; + pfh->itAttr = (*pfh->itSection).second.begin(); + pfh->itAttrEnd = (*pfh->itSection).second.end(); + + // section name + pi.bGroup = true; + pi.pszName = (*pfh->itSection++).first.c_str(); + pi.pszValue = NULL; + return true; + } + else + { + if(pfh->itAttr != pfh->itAttrEnd) + { + pi.bGroup = false; + pi.pszName = (*pfh->itAttr).first.c_str(); + pi.pszValue = (*pfh->itAttr).second.c_str(); + + pfh->itAttr++; + if(pfh->itAttr == pfh->itAttrEnd) + pfh->bSection = true; + return true; + + } + else + { + // should not happen + assert(false); + return false; + } + } + } } /** Closes the find handle. Index: ext/libicpf/src/libicpf/cfg_ini.h =================================================================== diff -u -N -r86310fdf8a767b700985ebd1b255004d9eb85fb7 -r6e13958c3d83047ec29e5a703d8982025eb22304 --- ext/libicpf/src/libicpf/cfg_ini.h (.../cfg_ini.h) (revision 86310fdf8a767b700985ebd1b255004d9eb85fb7) +++ ext/libicpf/src/libicpf/cfg_ini.h (.../cfg_ini.h) (revision 6e13958c3d83047ec29e5a703d8982025eb22304) @@ -34,7 +34,7 @@ /// Searches for a specified key (given all the path to a specific string) virtual ptr_t find(const tchar_t* pszName); /// Searches for the next string - virtual const tchar_t* find_next(ptr_t pFindHandle); + virtual bool find_next(ptr_t pFindHandle, PROPINFO& pi); /// Closes the search operation virtual void find_close(ptr_t pFindHandle); Index: ext/libicpf/src/libicpf/config_base.h =================================================================== diff -u -N -r86310fdf8a767b700985ebd1b255004d9eb85fb7 -r6e13958c3d83047ec29e5a703d8982025eb22304 --- ext/libicpf/src/libicpf/config_base.h (.../config_base.h) (revision 86310fdf8a767b700985ebd1b255004d9eb85fb7) +++ ext/libicpf/src/libicpf/config_base.h (.../config_base.h) (revision 6e13958c3d83047ec29e5a703d8982025eb22304) @@ -6,11 +6,18 @@ BEGIN_ICPF_NAMESPACE +struct LIBICPF_API PROPINFO +{ + const tchar_t* pszName; ///< Property name + const tchar_t* pszValue; ///< String value of the property (only for attribute-level property) + bool bGroup; ///< Group-level property (true) or attribute (false) +}; + /** Base config class. Manages the data that can be directly * read or written to the storage medium (xml file, ini file, * registry, ...). */ -class config_base +class LIBICPF_API config_base { public: /// Actions used when setting value @@ -34,7 +41,7 @@ /// Searches for a specified key (given all the path to a specific string) virtual ptr_t find(const tchar_t* pszName) = 0; /// Searches for the next string - virtual const tchar_t* find_next(ptr_t pFindHandle) = 0; + virtual bool find_next(ptr_t pFindHandle, PROPINFO& pi) = 0; /// Closes the search operation virtual void find_close(ptr_t pFindHandle) = 0;