00001
00002
00003
00004
00005 #include <cstdio>
00006 #include <cstring>
00007
00008 #include "typedefs.h"
00009 #include "globals.h"
00010 #include "log.h"
00011 #include "linetoken.h"
00012 #include "inisection.h"
00013 #include "inifile.h"
00014
00015 using namespace miniini_private;
00016
00017 INIFile::INIFile()
00018 :Length(0)
00019 ,Sections(NULL)
00020 {}
00021
00022 bool INIFile::OpenFile(const char * const fname)
00023 {
00024 INISection::InitTempData();
00025
00026 FILE * const file = fopen( fname, "rb" );
00027 if(file == NULL)
00028 {
00029 ERROR("Couldn't open file. Maybe it does not exist? File: %s",
00030 fname);
00031 return false;
00032 }
00033
00034 i seek = fseek(file, 0, SEEK_END);
00035 if(seek != 0)
00036 {
00037 fclose(file);
00038 ERROR("Couldn't reach end of file. File: %s", fname);
00039 return false;
00040 }
00041 const i size = ftell(file);
00042 if(size == -1)
00043 {
00044 fclose(file);
00045 ERROR("Couldn't determine size of file. File: %s", fname);
00046 return false;
00047 }
00048 seek = fseek(file, 0, SEEK_SET);
00049 if(seek!=0)
00050 {
00051 fclose(file);
00052 ERROR("Couldn't reach start of file. File: %s", fname);
00053 return false;
00054 }
00055
00056 c * const buf = new c [size + 1];
00057 const i readnum = fread(buf, size, 1, file);
00058
00059 if(readnum == 0)
00060 {
00061 fclose(file);
00062 delete [] buf;
00063 ERROR("Could open but could not read from file. File might be "
00064 "corrupted or you might not have sufficient rights to "
00065 "read from it. File: %s", fname);
00066 return false;
00067 }
00068
00069 buf[size] = 0;
00070
00071 ui tempsectionscap = 16;
00072
00073 INISection * * tempsections = new INISection * [tempsectionscap];
00074
00075 c * linetoken = strtok(buf, linesep );
00076 while( linetoken!=NULL )
00077 {
00078
00079 const ui linesize = strlen(linetoken);
00080
00081 LineToken linepart = LT_NAME;
00082
00083 c ch;
00084
00085 c * headername = new c[linesize - 1];
00086 ui hnamesize = 0;
00087
00088 for(ui idx = 0; idx < linesize; ++idx)
00089 {
00090 ch = linetoken[idx];
00091
00092 if(ch == comment)
00093 {
00094 if(linepart == LT_HEADER)
00095 {
00096 WARNING("Part of a section header is commented out or there is a stray "
00097 "'[' character. Ignoring. Line: %s File: %s", linetoken, fname);
00098 linepart = LT_NAME;
00099 }
00100 break;
00101 }
00102
00103 if(linepart == LT_NAME)
00104 {
00105
00106 if(ch == ' ' || ch == '\t')
00107 {
00108 continue;
00109 }
00110
00111 if(ch == '[')
00112 {
00113 linepart = LT_HEADER;
00114 continue;
00115 }
00116 }
00117
00118 else if(linepart == LT_HEADER)
00119 {
00120
00121 if(ch == ' ' || ch == '\t')
00122 {
00123 continue;
00124 }
00125 if(ch == ']')
00126 {
00127 break;
00128 }
00129
00130 if(idx == linesize - 1)
00131 {
00132 WARNING("'[' character present in a line but there's no ']'."
00133 "This might be an incomplete header. Ignoring."
00134 "Line: %s File: %s", linetoken, fname);
00135 linepart = LT_NAME;
00136 }
00137
00138 headername[hnamesize] = ch;
00139 ++hnamesize;
00140 }
00141 }
00142
00143 if(linepart == LT_HEADER)
00144 {
00145 if(!hnamesize)
00146 {
00147 WARNING("Header name empty. Ignoring. File: %s Line: %s",
00148 fname, linetoken);
00149 delete [] headername;
00150 linetoken = strtok( NULL, linesep );
00151 continue;
00152 }
00153 headername[hnamesize] = 0;
00154
00155 if(Length + 1 > tempsectionscap)
00156 {
00157 tempsectionscap *= 2;
00158 INISection * * const temptempsections = new INISection * [tempsectionscap];
00159 memcpy(temptempsections, tempsections, Length * sizeof(INISection *));
00160 delete [] tempsections;
00161 tempsections = temptempsections;
00162 }
00163 tempsections[Length] = new INISection();
00164
00165 if(!tempsections[Length]->Init(headername, &linetoken))
00166 {
00167 delete [] headername;
00168 delete tempsections[Length];
00169 continue;
00170 }
00171 delete [] headername;
00172 ++Length;
00173
00174 continue;
00175 }
00176 delete [] headername;
00177 linetoken = strtok( NULL, linesep );
00178 }
00179
00180 delete [] buf;
00181
00182 Sections = new INISection * [Length];
00183 memcpy(Sections, tempsections, Length * sizeof(INISection *));
00184 delete [] tempsections;
00185 fclose( file );
00186 INISection::DestroyTempData();
00187 return true;
00188 }
00189
00190 INIFile::~INIFile()
00191 {
00192 if(!Sections)
00193 {
00194 return;
00195 }
00196 for(ui section = 0; section < Length; ++section)
00197 {
00198 delete Sections[section];
00199 }
00200 delete [] Sections;
00201 }
00202
00203 INISection * INIFile::GetSection(const char * const name) const
00204 {
00205 INISection * const * sect = Sections;
00206 const INISection * const * const sectmax = Sections + Length;
00207 for(; sect < sectmax; ++sect)
00208 {
00209 if(!strcmp(name, (*sect)->Name))
00210 {
00211 return *sect;
00212 }
00213 }
00214 ERROR("Missing requested section. Section: %s", name);
00215 return NULL;
00216 }
00217
00218 INISection * INIFile::operator [] (const char * const name) const
00219 {
00220 return GetSection(name);
00221 }
00222
00223 unsigned INIFile::GetLength() const
00224 {
00225 return static_cast<unsigned>(Length);
00226 }
00227