// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: IniFile.cpp,v 1.7 2005/08/19 03:18:24 vlg Exp $ //------------------------------------------------------------------------------ // IniFile.cpp //------------------------------------------------------------------------------ // Copyright (C) 2003,2004 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // Date: Sat Sep 6 00:17:52 EDT 2003 //------------------------------------------------------------------------------ #include #include #include using namespace ASSA; IniFile:: IniFile (const string& fname_) : m_fname (fname_), m_section_pttrn ("\\[[a-zA-Z0-9]+.*] *$"), m_tuple_pttrn ("^[ \t]*[a-zA-Z0-9]+.* *= *.*"), m_comment_pttrn ("^#.*$") { trace_with_mask ("IniFile::IniFile", INIFILE); } IniFile:: ~IniFile () { trace_with_mask ("IniFile::~IniFile", INIFILE); m_config.clear (); } int IniFile:: load () { trace_with_mask ("IniFile::load", INIFILE); const int size = 1024; char inbuf [size]; string line; string name; string value; int ret = -1; m_stream.open (m_fname.c_str (), std::ios::in); if (!m_stream) { goto done; } while (m_stream) { m_stream.getline (inbuf, size, '\n'); DL((INIFILE,"Input: \"%s\"\n", inbuf)); if (::strlen (inbuf) == 0 || m_comment_pttrn.match (inbuf) == 0) { continue; } line = inbuf; if (m_section_pttrn.match (inbuf) == 0) { if (trim_section_name (line) < 0) { goto done; } m_config.push_back (sect_type (line, std::list ())); } else if (m_tuple_pttrn.match (inbuf) == 0) { if (Utils::split_pair (line, '=', name, value) < 0) { goto done; } Utils::trim_sides (name); Utils::trim_sides (value); m_config.back ().second.push_back (tuple_type (name, value)); } else { goto done; } } /** From N.M.Josuttis, "The C++ Standard Library", Sec. 13.9 File Access: "Clear eofbit and failbit set due to the end-of-file. Note that after the processing of a file, clear() must be called to clear the state flags that are set at end-of-file. This is required because the stream object is used for multiple files. open() NEVER clears any state flags. Thus, if a stream was not in a good state, after closing and reopening it, you still have to call clear() to get to a good state. This is also the case, if you open a different file." */ ret = 0; done: if (ret < 0) { DL((INIFILE, "Parse error: illegal syntax!\n")); } m_stream.clear (); m_stream.close (); return ret; } int IniFile:: sync (const string& fname_) { trace_with_mask ("IniFile::sync(fname)", INIFILE); ::unlink (fname_.c_str ()); m_stream.open (fname_.c_str (), std::ios::app | std::ios::out); if (!m_stream) { EL((INIFILE,"Failed to open(\"%s\", app|out)\n", fname_.c_str ())); return -1; } const_config_iterator i = m_config.begin (); const_tuple_iterator j; while (i != m_config.end ()) { m_stream << "[" << (*i).first << "]\n"; j = (*i).second.begin (); while (j != (*i).second.end ()) { m_stream << (*j).first << "=" << (*j).second << "\n"; j++; } m_stream << "\n"; i++; } m_stream.clear (); m_stream.close (); return 0; } void IniFile:: dump () const { trace_with_mask ("IniFile::dump", INIFILE); const_config_iterator i = m_config.begin (); const_tuple_iterator j; DL((INIFILE,"============= Start =================\n")); while (i != m_config.end ()) { DL((INIFILE, "[%s]\n", (*i).first.c_str ())); j = (*i).second.begin (); while (j != (*i).second.end ()) { DL((INIFILE, " %s=\%s\n", (*j).first.c_str (), (*j).second.c_str ())); j++; } i++; } DL((INIFILE,"============== End =================\n")); } string IniFile:: get_value (const string& section_, const string& name_) const { const_config_iterator i = m_config.begin (); const_tuple_iterator j; string ret (""); while (i != m_config.end ()) { if ((*i).first == section_) { j = (*i).second.begin (); while (j != (*i).second.end ()) { if ((*j).first == name_) { ret = (*j).second; break; } j++; } } i++; } return ret; } void IniFile:: add_section (const string& section_) { const_config_iterator i = find_section (section_); if (i == m_config.end ()) { m_config.push_back (sect_type (section_, std::list ())); } } IniFile::config_iterator IniFile:: find_section (const string& section_) { config_iterator i = m_config.begin (); while (i != m_config.end ()) { if ((*i).first == section_) { return (i); } i++; } return m_config.end (); } IniFile::const_config_iterator IniFile:: find_section (const string& section_) const { const_config_iterator i = m_config.begin (); while (i != m_config.end ()) { if ((*i).first == section_) { return (i); } i++; } return m_config.end (); } int IniFile:: set_pair (const string& section_, const tuple_type& newkey_) { trace_with_mask ("IniFile::set_pair", INIFILE); config_iterator i = find_section (section_); if (i == sect_end ()) { DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ())); return -1; } tuple_iterator j = (*i).second.begin (); while (j != (*i).second.end ()) { if ((*j).first == newkey_.first) { (*j).second = newkey_.second; return 0; } j++; } (*i).second.push_back (newkey_); return 0; } int IniFile:: drop_section (const string& section_) { trace_with_mask ("IniFile::drop_section", INIFILE); config_iterator i = find_section (section_); if (i == sect_end ()) { DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ())); return -1; } m_config.erase (i); return 0; } int IniFile:: drop_pair (const string& section_, const string& name_) { trace_with_mask ("IniFile::drop_pair", INIFILE); config_iterator i = find_section (section_); if (i == sect_end ()) { DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ())); return -1; } tuple_iterator j = (*i).second.begin (); while (j != (*i).second.end ()) { if ((*j).first == name_) { (*i).second.erase (j); return 0; } j++; } return -1; }