BOOL CInifile::line_exist( LPCSTR S, LPCSTR L ) { if (!section_exist(S)) return FALSE; Sect& I = r_section(S); SectCIt A = std::lower_bound(I.Data.begin(),I.Data.end(),L,item_pred); return (A!=I.Data.end() && xr_strcmp(*A->first,L)==0); }
u32 CInifile::line_count(LPCSTR Sname) { Sect& S = r_section(Sname); SectCIt I = S.Data.begin(); u32 C = 0; for (; I!=S.Data.end(); I++) if (*I->first) C++; return C; }
LPCSTR CInifile::r_string(LPCSTR S, LPCSTR L) { Sect& I = r_section(S); SectCIt A = std::lower_bound(I.Data.begin(),I.Data.end(),L,item_pred); if (A!=I.Data.end() && xr_strcmp(*A->first,L)==0) return *A->second; else xrDebug::Fatal(DEBUG_INFO, "Can't find variable %s in [%s]", L, S); return 0; }
void CInifile::remove_line ( LPCSTR S, LPCSTR L ) { R_ASSERT (!m_flags.test(eReadOnly)); if (line_exist(S,L)) { Sect& data = r_section (S); SectIt_ A = std::lower_bound(data.Data.begin(),data.Data.end(),L,item_pred); R_ASSERT(A!=data.Data.end() && xr_strcmp(*A->first,L)==0); data.Data.erase(A); } }
BOOL CInifile::r_line( LPCSTR S, int L, const char** N, const char** V ) { Sect& SS = r_section(S); if (L>=(int)SS.Data.size() || L<0 ) return FALSE; for (SectCIt I=SS.Data.begin(); I!=SS.Data.end(); I++) if (!(L--)) { *N = *I->first; *V = *I->second; return TRUE; } return FALSE; }
//-------------------------------------------------------------------------------------------------------- // Write functions //-------------------------------------------------------------------------------------- void CInifile::w_string( LPCSTR S, LPCSTR L, LPCSTR V, LPCSTR comment) { R_ASSERT (!m_flags.test(eReadOnly)); // section string256 sect; _parse (sect,S); _strlwr (sect); if (!section_exist(sect)) { // create _new_ section Sect *NEW = new Sect(); NEW->Name = sect; RootIt I = std::lower_bound(DATA.begin(),DATA.end(),sect,sect_pred); DATA.insert (I,NEW); } // parse line/value string4096 line; _parse (line,L); string4096 value; _parse (value,V); // duplicate & insert Item I; Sect& data = r_section (sect); I.first = (line[0]?line:0); I.second = (value[0]?value:0); #ifdef DEBUG I.comment = (comment?comment:0); #endif SectIt_ it = std::lower_bound(data.Data.begin(),data.Data.end(),*I.first,item_pred); if (it != data.Data.end()) { // Check for "first" matching if (0==xr_strcmp(*it->first, *I.first)) { BOOL b = m_flags.test(eOverrideNames); R_ASSERT2(b,make_string("name[%s] already exist in section[%s]",line,sect).c_str()); *it = I; } else { data.Data.insert(it,I); } } else { data.Data.insert(it,I); } }
//-------------------------------------------------------------------------------------------------------- // Write functions //-------------------------------------------------------------------------------------- void CInifile::w_string ( LPCSTR S, LPCSTR L, LPCSTR V, LPCSTR comment) { R_ASSERT (!bReadOnly); // section char sect [256]; _parse (sect,S); _strlwr (sect); if (!section_exist(sect)) { // create _new_ section Sect *NEW = xr_new<Sect>(); NEW->Name = sect; RootIt I = std::lower_bound(DATA.begin(),DATA.end(),sect,sect_pred); DATA.insert (I,NEW); } // parse line/value char line [256]; _parse (line,L); char value [256]; _parse (value,V); // duplicate & insert Item I; Sect& data = r_section (sect); I.first = (line[0]?line:0); I.second = (value[0]?value:0); #ifdef DEBUG I.comment = (comment?comment:0); #endif SectIt_ it = std::lower_bound(data.Data.begin(),data.Data.end(),*I.first,item_pred); if (it != data.Data.end()) { // Check for "first" matching if (0==xr_strcmp(*it->first,*I.first)) { *it = I; } else { data.Data.insert(it,I); } } else { data.Data.insert(it,I); } }
//-------------------------------------------------------------------------------------- CInifile::Sect& CInifile::r_section ( const shared_str& S ) { return r_section(*S); }
void CInifile::Load(IReader* F, LPCSTR path) { R_ASSERT(F); Sect *Current = 0; string4096 str; string4096 str2; BOOL bInsideSTR = FALSE; while (!F->eof()) { F->r_string (str,sizeof(str)); _Trim (str); LPSTR comm = strchr(str,';'); LPSTR comm_1 = strchr(str,'/'); if(comm_1 && (*(comm_1+1)=='/') && ((!comm) || (comm && (comm_1<comm) )) ) { comm = comm_1; } #ifdef DEBUG LPSTR comment = 0; #endif if (comm) { //."bla-bla-bla;nah-nah-nah" char quot = '"'; bool in_quot = false; LPCSTR q1 = strchr(str,quot); if(q1 && q1<comm) { LPCSTR q2 = strchr(++q1,quot); if(q2 && q2>comm) in_quot = true; } if(!in_quot) { *comm = 0; #ifdef DEBUG comment = comm+1; #endif } } if (str[0] && (str[0]=='#') && strstr(str,"#include")) //handle includes { string_path inc_name; R_ASSERT (path&&path[0]); if (_GetItem (str,1,inc_name,'"')) { string_path fn,inc_path,folder; strconcat (sizeof(fn),fn,path,inc_name); _splitpath (fn,inc_path,folder, 0, 0 ); strcat (inc_path,folder); IReader* I = FS.r_open(fn); R_ASSERT3(I,"Can't find include file:", inc_name); Load (I,inc_path); FS.r_close (I); } } else if (str[0] && (str[0]=='[')) //new section ? { // insert previous filled section if (Current) { //store previous section RootIt I = std::lower_bound(DATA.begin(),DATA.end(),*Current->Name,sect_pred); if ((I!=DATA.end())&&((*I)->Name==Current->Name)) xrDebug::Fatal(DEBUG_INFO, "Duplicate section '%s' found.", *Current->Name); DATA.insert (I,Current); } Current = new Sect(); Current->Name = 0; // start new section R_ASSERT3(strchr(str,']'),"Bad ini section found: ",str); LPCSTR inherited_names = strstr(str,"]:"); if (0!=inherited_names) { VERIFY2 (m_flags.test(eReadOnly),"Allow for readonly mode only."); inherited_names += 2; int cnt = _GetItemCount(inherited_names); for (int k=0; k<cnt; ++k) { xr_string tmp; _GetItem (inherited_names,k,tmp); Sect& inherited_section = r_section(tmp.c_str()); for (SectIt_ it =inherited_section.Data.begin(); it!=inherited_section.Data.end(); it++) insert_item (Current,*it); } } *strchr(str,']') = 0; Current->Name = strlwr(str+1); } else // name = value { if (Current) { string4096 value_raw; char* name = str; char* t = strchr(name,'='); if (t) { *t = 0; _Trim (name); ++t; strcpy_s (value_raw, sizeof(value_raw), t); bInsideSTR = _parse(str2, value_raw); if(bInsideSTR)//multiline str value { while(bInsideSTR) { strcat_s (value_raw, sizeof(value_raw),"\r\n"); string4096 str_add_raw; F->r_string (str_add_raw, sizeof(str_add_raw)); R_ASSERT2 ( xr_strlen(value_raw) + xr_strlen(str_add_raw) < sizeof(value_raw), make_string( "Incorrect inifile format: section[%s], variable[%s]. Odd number of quotes (\") found, but should be even.", Current->Name.c_str(), name ) ); strcat_s (value_raw, sizeof(value_raw),str_add_raw); bInsideSTR = _parse(str2, value_raw); if(bInsideSTR) { if( is_empty_line_now(F) ) strcat_s (value_raw, sizeof(value_raw),"\r\n"); } } } } else { _Trim (name); str2[0] = 0; } Item I; I.first = (name[0]?name:NULL); I.second = (str2[0]?str2:NULL); #ifdef DEBUG I.comment = m_flags.test(eReadOnly)?0:comment; #endif if (m_flags.test(eReadOnly)) { if (*I.first) insert_item (Current,I); } else { if ( *I.first || *I.second #ifdef DEBUG || *I.comment #endif ) insert_item (Current,I); } } } } if (Current) { RootIt I = std::lower_bound(DATA.begin(),DATA.end(),*Current->Name,sect_pred); if ((I!=DATA.end())&&((*I)->Name==Current->Name)) xrDebug::Fatal(DEBUG_INFO, "Duplicate section '%s' found.", *Current->Name); DATA.insert (I,Current); } }
void CInifile::Load(IReader* F, LPCSTR path) { R_ASSERT(F); Sect *Current = 0; string4096 str; string4096 str2; while (!F->eof()) { F->r_string (str,sizeof(str)); _Trim (str); LPSTR semi = strchr(str,';'); LPSTR semi_1 = strchr(str,'/'); if(semi_1 && (*(semi_1+1)=='/') && ((!semi) || (semi && (semi_1<semi) )) ){ semi = semi_1; } #ifdef DEBUG LPSTR comment = 0; #endif if (semi) { *semi = 0; #ifdef DEBUG comment = semi+1; #endif } if (str[0] && (str[0]=='#') && strstr(str,"#include")){ string64 inc_name; R_ASSERT (path&&path[0]); if (_GetItem (str,1,inc_name,'"')){ string_path fn,inc_path,folder; strconcat (sizeof(fn),fn,path,inc_name); _splitpath (fn,inc_path,folder, 0, 0 ); strcat (inc_path,folder); IReader* I = FS.r_open(fn); R_ASSERT3(I,"Can't find include file:", inc_name); Load (I,inc_path); FS.r_close (I); } }else if (str[0] && (str[0]=='[')){ // insert previous filled section if (Current){ RootIt I = std::lower_bound(DATA.begin(),DATA.end(),*Current->Name,sect_pred); if ((I!=DATA.end())&&((*I)->Name==Current->Name)) Debug.fatal(DEBUG_INFO,"Duplicate section '%s' found.",*Current->Name); DATA.insert (I,Current); } Current = xr_new<Sect>(); Current->Name = 0; // start new section R_ASSERT3(strchr(str,']'),"Bad ini section found: ",str); LPCSTR inherited_names = strstr(str,"]:"); if (0!=inherited_names){ VERIFY2 (bReadOnly,"Allow for readonly mode only."); inherited_names += 2; int cnt = _GetItemCount(inherited_names); for (int k=0; k<cnt; ++k){ xr_string tmp; _GetItem (inherited_names,k,tmp); Sect& inherited_section = r_section(tmp.c_str()); for (SectIt_ it =inherited_section.Data.begin(); it!=inherited_section.Data.end(); it++) insert_item (Current,*it); } } *strchr(str,']') = 0; Current->Name = strlwr(str+1); } else { if (Current){ char* name = str; char* t = strchr(name,'='); if (t) { *t = 0; _Trim (name); _parse (str2,++t); } else { _Trim (name); str2[0] = 0; } Item I; I.first = (name[0]?name:NULL); I.second = (str2[0]?str2:NULL); #ifdef DEBUG I.comment = bReadOnly?0:comment; #endif if (bReadOnly) { if (*I.first) insert_item (Current,I); } else { if ( *I.first || *I.second #ifdef DEBUG || *I.comment #endif ) insert_item (Current,I); } } } } if (Current) { RootIt I = std::lower_bound(DATA.begin(),DATA.end(),*Current->Name,sect_pred); if ((I!=DATA.end())&&((*I)->Name==Current->Name)) Debug.fatal(DEBUG_INFO,"Duplicate section '%s' found.",*Current->Name); DATA.insert (I,Current); } }