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