/********************************************************************** * * cfgread.cpp -- * Copyright (C) 1999 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #include "cfgread.h" #include // for isspace() int write_ini_line (ofstream &fileout, const text_t &key, const text_t &value) { if (key.empty() || value.empty()) return -1; outconvertclass text_t2ascii; fileout << text_t2ascii << key << "=" << value << "\n"; return 0; } int read_ini_line (ifstream &filein, text_t &key, text_t &value) { if (filein.eof()) return -1; key.clear(); value.clear(); char c; filein.get(c); int foundeq = 0; while (!filein.eof() && c != '\n') { if (!foundeq && c == '=') {foundeq = 1; filein.get(c);} if (foundeq) value.push_back(c); else key.push_back(c); filein.get(c); } if (key.empty()) return 0; // blank line maybe? return 0; } // write out line of values to cfgfile // does nothing fancy - make sure no values contain carriage returns int write_cfg_line (ofstream &fileout, const text_tarray &values) { outconvertclass text_t2ascii; text_tarray::const_iterator here = values.begin(); text_tarray::const_iterator end = values.end(); bool first = true; while (here != end) { if (first) fileout << text_t2ascii << *here; else fileout << text_t2ascii << " \"" << *here << "\""; first = false; ++here; } fileout << "\n"; return 0; } // same, but use a file descriptor this time int write_cfg_line (int fileout, const text_tarray &values) { outconvertclass text_t2ascii; text_tarray::const_iterator here = values.begin(); text_tarray::const_iterator end = values.end(); if (here != end) { char *s=here->getcstr(); write(fileout,s ,here->size()); delete []s; ++here; } while (here != end) { write(fileout, " \"", 2); char *s=here->getcstr(); write(fileout,s ,here->size()); delete []s; write(fileout, "\"", 1); ++here; } write(fileout,"\n",1); return 0; } // returns 0 on success, -1 on failure int read_cfg_line (ifstream &filein, text_tarray &values) { // we split up the line into tokens, pushing each token into the // values array. Quoted phrases are a single token. A "\" at the end // of a line continues onto the next line. values.erase(values.begin(), values.end()); if (!filein.good()) return -1; text_t curvalue; char c1; filein.get(c1); // skip white space while (!filein.eof() && isspace((unsigned char) c1)) { filein.get(c1); } // ignore comments while (!filein.eof() && c1 == '#') { while (!filein.eof() && c1!='\n' && c1!='\r') { filein.get(c1); } // skip white space... while (!filein.eof() && isspace((unsigned char) c1)) { filein.get(c1); } } // deal with all the records on this line (possibly multi-line) while (!filein.eof()) { if (c1=='\n' || c1=='\r') { // shouldn't happen? break; } // get the next token curvalue.clear(); bool inquote=false; char quotemark='"'; char preceding='\0'; // 1-char state to allow \" and \' // see if this is a quoted phrase if (c1=='\'' || c1=='\"') { // starts with a quote inquote=true; quotemark = c1; preceding = c1; // just to initialise filein.get(c1); } // get token or a whole phrase while (!filein.eof()) { if (isspace((unsigned char) c1)) { if (! inquote) { // end of token, not inside quote marks break; } else { // inside quote marks. /* Turn eol into space, in case other parsing bits expect eol to also mean end of parsing... */ c1=' '; } } if (c1 == quotemark && inquote && preceding != '\\') { // end of quoted phrase found inquote=false; filein.get(c1); continue; } // add current char to token/phrase // see if current byte is part of a multibyte char (utf-8 only!) unsigned short int c; // text_t uses 16bit unicode unsigned char uc1=(unsigned)c1; if (uc1 < 0x80) { c=uc1; } else if (uc1 >= 0xc0 && uc1 <= 0xdf) { // 2-byte utf-8 unsigned char c2; // two byte character filein.get((char&)c2); // get takes a signed char c = ((uc1 & 0x1f) << 6) + (c2 & 0x3f); } else if (uc1 >= 0xe0 && uc1 <= 0xef) { // 3-byte character unsigned char c2, c3; filein.get((char&)c2); filein.get((char&)c3); c = ((uc1 & 0xf) << 12) + ((c2 & 0x3f) << 6) + (c3 & 0x3f); } else {c=uc1;} // we don't do group2/plane0 (4,5,6-byte utf-8) curvalue.push_back(c); // 16bit unicode if (inquote) preceding = c1; filein.get(c1); } // we now have a token or a phrase // see if we've reached the end of the line if (c1 == '\n' || c1 == '\r') { if (curvalue != "\\") { // the line DOESN'T continue. End of line. values.push_back(curvalue); break; // end of token/phrase } else { // swallow up the EOL chars while (!filein.eof() && (c1=='\r' || c1=='\n')) filein.get(c1); // the current token "\\" will be cleared below } } else { // no new line seen values.push_back(curvalue); } curvalue.clear(); // remove whitespace (but not newline/CR chars) before next token while (!filein.eof() && (c1==' ' || c1=='\t')) filein.get(c1); } // while(1) return 0; }