//----------------------------------------------------------------- void IniFile::load(const std::string filename) { _sections.clear(); if (filename.empty()) { return; } FILE* file = fopen(filename.c_str(), "rb"); if (!file) { return; } static ArrayPtr<char> s_Buffer; static int s_BufferSize = 0; if (s_BufferSize == 0) { // one-time initialization try { s_Buffer.reset(new char[1024]); s_BufferSize = 1024; } catch (const std::bad_alloc&) { return; } } int num_keys_read = 0; std::string section; std::string key; std::string value; char* ptr; int avail; int state = 'A'; int input; int chr; fetch: // fill buffer with data from the stream int num_fetched = fread(s_Buffer.get(), 1, s_BufferSize, file); if (num_fetched == 0) { goto finish; } else { avail = num_fetched; ptr = s_Buffer.get(); } parse: // parse the data in the buffer chr = *ptr; if (chr == '\n' || chr == '\r') { input = 'n'; } else if (chr == '[') { input = 'l'; } else if (chr == ']') { input = 'r'; } else if (chr == '=') { input = 'z'; } else if (chr == ' ') { input = 's'; } else if (chr > 31 && chr < 127) { input = 'g'; } else { input = 'u'; } switch (state) { case 'A': switch (input) { case 'n': case 's': break; case 'l': state = 'B'; break; case 'r': case 'z': case 'g': case 'u': state = 'C'; break; } break; case 'B': switch (input) { case 'n': state = 'A'; break; case 'g': state = 'D'; section = chr; break; case 's': break; case 'l': case 'r': case 'z': case 'u': state = 'C'; break; } break; case 'C': switch (input) { case 'n': state = 'A'; break; case 'l': case 'r': case 'z': case 's': case 'g': case 'u': break; } break; case 'D': switch (input) { case 'n': state = 'A'; break; case 's': case 'g': section += chr; break; case 'r': state = 'E'; break; case 'l': case 'z': case 'u': state = 'C'; break; } break; case 'E': switch (input) { case 'n': state = 'F'; break; case 'l': case 'r': case 'z': case 's': case 'g': case 'u': break; } break; case 'F': switch (input) { case 'n': case 's': break; case 'g': state = 'G'; key = chr; break; case 'l': state = 'B'; break; case 'r': case 'z': case 'u': state = 'H'; break; } break; case 'G': switch (input) { case 'n': state = 'F'; break; case 's': case 'g': key += chr; break; case 'z': state = 'I'; break; case 'l': case 'r': case 'u': state = 'H'; break; } break; case 'H': switch (input) { case 'n': state = 'F'; break; case 'l': case 'r': case 'z': case 's': case 'g': case 'u': break; } break; case 'I': switch (input) { case 'n': state = 'F'; break; case 's': break; case 'l': case 'r': case 'g': state = 'J'; value = chr; break; case 'z': case 'u': state = 'H'; break; } break; case 'J': switch (input) { case 'n': state = 'F'; _sections[strip_whitespace(section)]._keys[strip_whitespace(key)] = strip_whitespace(value); num_keys_read++; break; case 'l': case 'r': case 's': case 'g': value += chr; break; case 'z': case 'u': state = 'H'; _sections[strip_whitespace(section)]._keys[strip_whitespace(key)] = strip_whitespace(value); num_keys_read++; break; } break; } --avail; ++ptr; if (avail > 0) { goto parse; } else { goto fetch; } finish: if (state == 'J') { // we still have a valid key-value pair _sections[strip_whitespace(section)]._keys[strip_whitespace(key)] = strip_whitespace(value); num_keys_read++; } return; }