void blockFromBuffer(KviCString & szBuffer) { indent(szBuffer); szBuffer.prepend("{\n"); szBuffer.stripRightWhiteSpace(); szBuffer.ensureLastCharIs('\n'); szBuffer.append("}\n"); }
bool KviConfigurationFile::load() { // this is really faster than the old version :) // open the file KviFile f(m_szFileName); if(!f.open(QFile::ReadOnly)) return false; KviCString tmp; KviConfigurationFileGroup * p_group = 0; int iLoadBlockSize = LOAD_BLOCK_SIZE; char * buffer = (char *)KviMemory::allocate(iLoadBlockSize * sizeof(char)); int toRead; int readedLen; int remainingLen = 0; char * p = buffer; // start writing to the beginning of the buffer do { // compute the length to read toRead = iLoadBlockSize - remainingLen; if(toRead < 1) { // ops... a string longer than iLoadBlockSize - 1 chars iLoadBlockSize += LOAD_BLOCK_SIZE; int iOffset = p - buffer; buffer = (char *)KviMemory::reallocate(buffer,iLoadBlockSize * sizeof(char)); p = buffer + iOffset; toRead += LOAD_BLOCK_SIZE; } // do read readedLen = f.read(p,toRead); if(readedLen < toRead) { // check for errors if(readedLen <= 0) { if(readedLen < 0) { // error at all f.close(); KviMemory::free(buffer); return true; // nothing more to parse anyway } else { // just a zero byte read if(remainingLen == 0) { // there was nothing in the buffer f.close(); // nothing to parse anyway KviMemory::free(buffer); return true; } // there is something in the buffer but we have readed 0 bytes // this usually means that the last line in the file has no trailing newline // ...we just fake it :) *p = '\n'; readedLen = 1; } } else { // just readed something but less than expected // check if the last readed char is a newline // if it isn't, fake it if(*(p + readedLen - 1) != '\n') { *(p + readedLen) = '\n'; readedLen++; } } } // compute the end pointer char * endp = p + readedLen; p = buffer; // start from beginning of the data buffer at all // begin of the current string char * begin = p; // and loop while(p < endp) { // find a newline if(*p != '\n') { p++; continue; } // newline! *p = 0; // now begin points to the string that terminates in p // skip leading whitespace while((*begin == '\t') || (*begin == ' '))begin++; if(p == begin) { // empty line p++; begin = p; continue; } // now p > begin // check if there are trailing spaces (include CR so CRLF is trimmed too) char * trail = p - 1; p++; while(trail >= begin) { if((*trail == '\r') || (*trail == '\t') || (*trail == ' '))*trail = 0; else break; trail--; } // yeah, have some data in this line :D switch(*begin) { case 0: // empty line break; case '#': // comment: just skip it break; case '[': // group ? begin++; if(*begin && (*begin != ']')) { char * z = begin; #define COMPAT_WITH_OLD_CONFIGS #ifdef COMPAT_WITH_OLD_CONFIGS // run to the end of the string while(*z)z++; // run back to the trailing ']' while((z > begin) && (*z != ']'))z--; // if it is not ther just run back to the end of the string if(*z != ']')while(*z)z++; #else // new configs have it always encoded properly while(*z && (*z != ']'))z++; #endif *z = 0; tmp.hexDecode(begin); tmp.stripRightWhiteSpace(); // no external spaces in group names if(!tmp.isEmpty()) { QString szGroup = m_bLocal8Bit ? QString::fromLocal8Bit(tmp.ptr(),tmp.len()) : QString::fromUtf8(tmp.ptr(),tmp.len()); p_group = m_pDict->find(szGroup); if(!p_group) { p_group = new KviConfigurationFileGroup(17,false); p_group->setAutoDelete(true); m_pDict->insert(szGroup,p_group); } } } break; default: { // real data ? char * z = begin; while(*z && (*z != '='))z++; if(*z && (z != begin)) { *z = 0; tmp.hexDecode(begin); tmp.stripRightWhiteSpace(); // No external spaces at all in keys if(!tmp.isEmpty()) { QString szKey = m_bLocal8Bit ? QString::fromLocal8Bit(tmp.ptr(),tmp.len()) : QString::fromUtf8(tmp.ptr(),tmp.len()); z++; while(*z && ((*z == ' ') || (*z == '\t')))z++; if(*z) { tmp.hexDecode(z); QString * pVal = new QString( m_bLocal8Bit ? QString::fromLocal8Bit(tmp.ptr(),tmp.len()) : QString::fromUtf8(tmp.ptr(),tmp.len()) ); if(!p_group) { // ops...we're missing a group // use the default one p_group = new KviConfigurationFileGroup(17,false); p_group->setAutoDelete(true); m_pDict->insert(KVI_CONFIG_DEFAULT_GROUP,p_group); } p_group->replace(szKey,pVal); } else { // we in fact need this (mercy :D) // otherwise the empty options will be treated as non-existing ones // and will get the defaults (which is bad) QString * pVal = new QString(QString()); p_group->replace(szKey,pVal); } } } } break; } begin = p; } if(begin != endp) { // there is data with no trailing newline in the buffer remainingLen = endp-begin; if(buffer != begin) { KviMemory::move(buffer,begin,remainingLen); p = buffer + remainingLen; } // else p remains where it is } else { p = buffer; } } while(readedLen == toRead); f.close(); KviMemory::free(buffer); return true; }