1 /***************************************************************************
2                              libdatafile
3                           --------------------
4 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Giuseppe "denever" Martino
5     begin                : Sun May 6 2001
6     email                : denever@users.sourceforge.net
7  ***************************************************************************/
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *  This program is distributed in the hope that it will be useful,        *
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
18  *  GNU General Public License for more details.                           *
19  *                                                                         *
20  *  You should have received a copy of the GNU General Public License      *
21  *  along with this program; if not, write to the Free Software            *
22  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,             *
23  *  MA 02110-1301 USA                                                      *
24  *                                                                         *
25  ***************************************************************************/
26 
27 #include "datafile.hh"
28 
29 #include <fstream>
30 #include <sstream>
31 #include <cctype>
32 
33 using namespace std;
34 using namespace libdatafile;
35 
Datafile(const string & name,const access & a=Read)36 Datafile::Datafile(const string& name, const access& a = Read): m_opened(false), m_filename(name), m_access(a)
37 {
38     m_sections.clear();
39     if( (m_access == Read) || (m_access == Update) )
40     	open();
41 }
42 
Datafile(const Datafile & cpy)43 Datafile::Datafile(const Datafile& cpy): m_opened(cpy.m_opened), m_filename(cpy.m_filename), m_access(cpy.m_access)
44 {
45     m_sections = cpy.m_sections;
46 }
47 
~Datafile()48 Datafile::~Datafile()
49 {
50     if((m_access == Write) || (m_access == Update) || (m_access == Create))
51 	save();
52 }
53 
open()54 void Datafile::open()
55 {
56     ifstream stream(m_filename.c_str());
57 
58     string alfa;
59     string section_name;
60     char ch;
61 
62     alfa.clear();
63     section_name.clear();
64 
65     bool comment = false;
66 
67     if(stream.fail())
68 	throw libdatafile::File_not_exist(m_filename.c_str());
69 
70     while(stream.get(ch))
71 	switch(ch)
72 	{
73 	case '[': // New Section
74 	    if(!comment)
75 	    {
76 		section_name.clear();
77 		break;
78 	    }
79 
80 	case ']': // Create Section
81 	    if(!comment)
82 	    {
83 		section_name = alfa;
84 		alfa.clear();
85 		add_section(section_name);
86 		break;
87 	    }
88 
89 	case '#':
90 	    comment = true;
91 	    break;
92 
93 	case '=':
94 	    if(!comment) // Create an option
95 	    {
96 		section(section_name)->add_option(alfa);
97 		string tmpstr;
98 		stream >> tmpstr;
99 
100 		if(isdigit(tmpstr[0]))
101 		{
102 		    istringstream tmps (tmpstr);
103 
104 		    int tmp;
105 		    tmps>>tmp;
106 
107 		    section(section_name)->option(alfa)->set(tmp);
108 		}
109 		else
110 		    section(section_name)->option(alfa)->set(tmpstr);
111 
112 		alfa.clear();
113 	    }
114 
115 	case '\n':
116 		comment = false;
117 		alfa.clear();
118 		break;
119 
120 	default:
121 		if(!comment)
122 		    if(!isspace(ch))
123 			alfa += ch;
124 	}
125 }
126 
save()127 void Datafile::save()
128 {
129     ofstream out(m_filename.c_str());
130 
131     out.clear();
132 
133     for(sec_it i=begin(); i!=end(); i++)
134     {
135 	out<<endl<<"["<<i->name()<<"]"<<endl;
136 	for(opt_it j=i->begin(); j!=i->end(); j++)
137 	{
138 	    out<<j->name()<<" = ";
139 
140 	    if(j->get() != 9999)
141 		out<<j->get()<<endl;
142 	    else
143 		out<<j->getstr()<<endl;
144 	}
145     }
146 
147     out.close();
148 }
149 
section(const string & name)150 sec_it Datafile::section(const string& name)
151 {
152     if(m_sections.empty())
153 	throw libdatafile::File_not_opened(m_filename.c_str());
154 
155     for(sec_it i=m_sections.begin(); i!=m_sections.end(); i++)
156 	if(i->name() == name)
157 	    return i;
158 
159     throw libdatafile::Section_not_found(name.c_str());
160 }
161 
add_section(const string & name)162 void Datafile::add_section(const string& name)
163 {
164     Section tmp(name);
165     m_sections.push_back(tmp);
166 }
167 
remove_section(const string & name)168 void Datafile::remove_section(const string& name)
169 {
170     if(m_sections.empty())
171 	throw libdatafile::File_not_opened(m_filename.c_str());
172 
173     for(sec_it i=begin(); i!=end(); i++)
174 	if(i->name() == name)
175 	    m_sections.erase(i);
176 
177     throw libdatafile::Section_not_found(name.c_str());
178 }
179 
begin()180 sec_it Datafile::begin()
181 {
182     return m_sections.begin();
183 }
184 
end()185 sec_it Datafile::end()
186 {
187     return m_sections.end();
188 }
189