00001 #include <string.h>
00002 #include <stdlib.h>
00003
00004 #include "Common/File.h"
00005 #include "Common/Error.h"
00006
00007 #include "Common/Ini.h"
00008
00009 #define MAX_BUFSIZE 1024
00010
00011
00012 KIni::KIni( KFile& File )
00013 {
00014 m_pFile = new KFile();
00015 *m_pFile = File;
00016 m_bMustCloseFile = false;
00017 m_bHasChanged = false;
00018 LoadCache();
00019 }
00020
00021
00022 KIni::KIni( char* pFileName )
00023 {
00024 m_pFile = new KFile();
00025 if( !m_pFile->Open( pFileName, KFM_READWRITE ) )
00026 if( !m_pFile->Open( pFileName, KFM_READ ) )
00027 if( !m_pFile->Create( pFileName ) )
00028 KError::Error( NULL, "KIni::KIni(...) Cannot open file : [%s]", pFileName );
00029
00030 m_bMustCloseFile = true;
00031 m_bHasChanged = false;
00032 LoadCache();
00033 }
00034
00035
00036 KIni::~KIni()
00037 {
00038 if( m_bHasChanged && ( m_pFile->GetMode() == KFM_READWRITE ) )
00039 SaveCache();
00040
00041 if( m_bMustCloseFile )
00042 m_pFile->Close();
00043
00044 Deletep( m_pFile );
00045
00046 KIniSection* pSection;
00047 for( pSection = m_SectionsList.GetFirst(); pSection ; pSection = m_SectionsList.GetNext( pSection ) )
00048 delete pSection;
00049 m_SectionsList.Clear();
00050 }
00051
00052
00053 void KIni::LoadCache()
00054 {
00055 KStr sBuffer;
00056 char pSectionName[MAX_BUFSIZE];
00057 char pKeyName[MAX_BUFSIZE];
00058
00059 m_pFile->Rewind();
00060
00061 if( !m_pFile->ReadText( sBuffer ) )
00062 return;
00063
00064 while( !m_pFile->IsEOF() )
00065 {
00066 strcpy( pSectionName, sBuffer.GetpString() );
00067
00068
00069 if( strlen( pSectionName ) && pSectionName[0] == '[' && !(pSectionName[0] == '/' && pSectionName[1] == '/' ) )
00070 {
00071
00072 pSectionName[strlen( pSectionName ) - 1] = '\0';
00073 KIniSection* pSection = new KIniSection( &pSectionName[1] );
00074 m_SectionsList.Add( pSection );
00075
00076
00077
00078
00079
00080 do
00081 {
00082
00083 if( !m_pFile->ReadText( sBuffer ) )
00084 return;
00085
00086 strcpy( pKeyName, sBuffer.GetpString() );
00087
00088 if( strlen( pKeyName ) && pKeyName[0] != '[' && !( pKeyName[0] == '/' && pKeyName[1] == '/' ) )
00089 {
00090 s32 Pos;
00091 char* pPos;
00092 if( pPos = strstr( pKeyName, "=" ) )
00093 {
00094
00095 Pos = (s32)(pPos - pKeyName + 1);
00096 pKeyName[Pos - 1] = '\0';
00097
00098
00099 if( FindKey( &pSectionName[1], pKeyName, false ) )
00100 {
00101 KError::Error( NULL, "KIni::LoadCache(...) : Duplicate key found, ignoring... %s [%s] %s=%s", m_pFile->GetsFileName().GetpString(), &pSectionName[1], pKeyName, &pKeyName[Pos] );
00102 continue;
00103 }
00104
00105 KIniKey* pKey = new KIniKey( pKeyName, &pKeyName[Pos] );
00106 pSection->AddpKey( pKey );
00107
00108
00109
00110
00111 }
00112 }
00113 }while( !m_pFile->IsEOF() && ( pKeyName[0] != '[' ) );
00114 }
00115 else
00116 {
00117 if( !m_pFile->ReadText( sBuffer ) )
00118 return;
00119 }
00120 }
00121 }
00122
00123
00124 void KIni::SaveCache()
00125 {
00126 KIniSection* pIniSection;
00127 KIniKey* pIniKey;
00128 KStr sBuffer;
00129
00130 m_pFile->Reset();
00131
00132 for( pIniSection = m_SectionsList.GetFirst(); pIniSection ; pIniSection = m_SectionsList.GetNext( pIniSection ) )
00133 {
00134 sBuffer = "[";
00135 sBuffer += pIniSection->m_pSection;
00136 sBuffer += "]\r\n";
00137 m_pFile->WriteText( sBuffer );
00138
00139 for( pIniKey = pIniSection->GetpFirstKey(); pIniKey ; pIniKey = pIniSection->GetpNextKey( pIniKey ) )
00140 {
00141 sBuffer = pIniKey->m_pKey;
00142 sBuffer += "=";
00143 sBuffer += pIniKey->m_pValue ? pIniKey->m_pValue : "";
00144 sBuffer += "\r\n";
00145 m_pFile->WriteText( sBuffer );
00146 }
00147 sBuffer = "\r\n";
00148 m_pFile->WriteText( sBuffer );
00149 }
00150 }
00151
00152
00153 char* KIni::FindKey( char* pSection, char* pKey, bool bShowError )
00154 {
00155
00156 KIniSection* pIniSection;
00157 for( pIniSection = m_SectionsList.GetFirst(); pIniSection ; pIniSection = m_SectionsList.GetNext( pIniSection ) )
00158 {
00159 if( stricmp( pIniSection->m_pSection, pSection ) == 0 )
00160 {
00161
00162 KIniKey* pIniKey;
00163 for( pIniKey = pIniSection->GetpFirstKey(); pIniKey ; pIniKey = pIniSection->GetpNextKey( pIniKey ) )
00164 {
00165 if( stricmp( pIniKey->m_pKey, pKey ) == 0 )
00166 {
00167
00168 return pIniKey->m_pValue;
00169 }
00170 }
00171 if( bShowError )
00172 KError::Warning( NULL, "INI : [%s] %s not found", pSection, pKey );
00173
00174 return NULL;
00175 }
00176 }
00177
00178 if( bShowError )
00179 KError::Warning( NULL, "INI : [%s] %s not found", pSection, pKey );
00180
00181 return NULL;
00182 }
00183
00184
00185 void KIni::SetKey( char* pSection, char* pKey, char* pString )
00186 {
00187 KIniSection* pIniSection;
00188 KIniKey* pIniKey;
00189
00190 m_bHasChanged = true;
00191
00192
00193 for( pIniSection = m_SectionsList.GetFirst(); pIniSection ; pIniSection = m_SectionsList.GetNext( pIniSection ) )
00194 {
00195 if( stricmp( pIniSection->m_pSection, pSection ) == 0 )
00196 {
00197
00198 for( pIniKey = pIniSection->GetpFirstKey(); pIniKey ; pIniKey = pIniSection->GetpNextKey( pIniKey ) )
00199 {
00200 if( stricmp( pIniKey->m_pKey, pKey ) == 0 )
00201 {
00202
00203 Freep( pIniKey->m_pValue );
00204 pIniKey->m_pValue = strdup( pString );
00205 return;
00206 }
00207 }
00208 pIniKey = new KIniKey( pKey, pString );
00209 pIniSection->AddpKey( pIniKey );
00210 return;
00211 }
00212 }
00213
00214 pIniSection = new KIniSection( pSection );
00215 m_SectionsList.Add( pIniSection );
00216 pIniKey = new KIniKey( pKey, pString );
00217 pIniSection->AddpKey( pIniKey );
00218 }
00219
00220 s32 KIni::ReadInt( char* pSection, char* pKey, s32 DefaultValue )
00221 {
00222 char* pBuffer;
00223
00224 pBuffer = FindKey( pSection, pKey );
00225 if( !pBuffer )
00226 {
00227 WriteInt( pSection, pKey, DefaultValue );
00228 return DefaultValue;
00229 }
00230
00231 return atoi( pBuffer );
00232 }
00233
00234
00235 float KIni::ReadFloat( char* pSection, char* pKey, float DefaultValue )
00236 {
00237 char* pBuffer;
00238
00239 pBuffer = FindKey( pSection, pKey );
00240 if( !pBuffer )
00241 {
00242 WriteFloat( pSection, pKey, DefaultValue );
00243 return DefaultValue;
00244 }
00245
00246 return (float)atof( pBuffer );
00247 }
00248
00249
00250 const char* KIni::ReadString( char* pSection, char* pKey, char* DefaultString )
00251 {
00252 char* pBuffer;
00253
00254 pBuffer = FindKey( pSection, pKey );
00255 if( !pBuffer )
00256 {
00257 WriteString( pSection, pKey, DefaultString );
00258 return DefaultString;
00259 }
00260
00261 return pBuffer;
00262 }
00263
00264
00265 void KIni::WriteString( char* pSection, char* pKey, char* pString )
00266 {
00267 SetKey( pSection, pKey, pString );
00268 }
00269
00270
00271 void KIni::WriteInt( char* pSection, char* pKey, s32 Value )
00272 {
00273 char pBuffer[MAX_BUFSIZE];
00274
00275 sprintf( pBuffer, "%i", Value );
00276 SetKey( pSection, pKey, pBuffer );
00277 }
00278
00279
00280 void KIni::WriteFloat( char* pSection, char* pKey, float Value )
00281 {
00282 char pBuffer[MAX_BUFSIZE];
00283
00284 sprintf( pBuffer, "%f", Value );
00285 SetKey( pSection, pKey, pBuffer );
00286 }