The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
swconfig.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * swconfig.cpp - used for saving and retrieval of configuration
4  * information
5  *
6  * $Id: swconfig.cpp 3748 2020-07-02 17:20:40Z scribe $
7  *
8  * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org)
9  * CrossWire Bible Society
10  * P. O. Box 2528
11  * Tempe, AZ 85280-2528
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation version 2.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * General Public License for more details.
21  *
22  */
23 
24 #include <swconfig.h>
25 #include <utilstr.h>
26 #include <filemgr.h>
27 #include <fcntl.h>
28 
29 
31 
32 #if defined(__GNUC__)
33 #pragma GCC diagnostic push
34 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
35 #endif
36 
38 }
39 
40 
41 SWConfig::SWConfig(const char *ifilename) {
42  filename = ifilename;
43  load();
44 }
45 
46 
48 }
49 
50 
51 #if defined(__GNUC__)
52 #pragma GCC diagnostic pop
53 #endif
54 
56 
57  if (!getFileName().size()) return; // assert we have a filename
58 
59  FileDesc *cfile;
60  char *buf, *data;
61  SWBuf line;
62  ConfigEntMap cursect;
63  SWBuf sectname;
64  bool first = true;
65 
66  getSections().erase(getSections().begin(), getSections().end());
67 
69  if (cfile->getFd() > 0) {
70  bool goodLine = FileMgr::getLine(cfile, line);
71 
72  // clean UTF encoding tags at start of file
73  while (goodLine && line.length() &&
74  ((((unsigned char)line[0]) == 0xEF) ||
75  (((unsigned char)line[0]) == 0xBB) ||
76  (((unsigned char)line[0]) == 0xBF))) {
77  line << 1;
78  }
79 
80  while (goodLine) {
81  // ignore commented lines
82  if (!line.startsWith("#")) {
83  buf = new char [ line.length() + 1 ];
84  strcpy(buf, line.c_str());
85  if (*strstrip(buf) == '[') {
86  if (!first)
87  getSections().insert(SectionMap::value_type(sectname, cursect));
88  else first = false;
89 
90  cursect.erase(cursect.begin(), cursect.end());
91 
92  strtok(buf, "]");
93  sectname = buf+1;
94  }
95  else {
96  strtok(buf, "=");
97  if ((*buf) && (*buf != '=')) {
98  if ((data = strtok(NULL, "")))
99  cursect.insert(ConfigEntMap::value_type(buf, strstrip(data)));
100  else cursect.insert(ConfigEntMap::value_type(buf, ""));
101  }
102  }
103  delete [] buf;
104  }
105  goodLine = FileMgr::getLine(cfile, line);
106  }
107  if (!first)
108  getSections().insert(SectionMap::value_type(sectname, cursect));
109 
111  }
112 }
113 
114 
115 void SWConfig::save() const {
116 
117  if (!getFileName().size()) return; // assert we have a filename
118 
119  FileDesc *cfile;
120  SWBuf buf;
121  SectionMap::const_iterator sit;
122  ConfigEntMap::const_iterator entry;
123  SWBuf sectname;
124 
126  if (cfile->getFd() > 0) {
127 
128  for (sit = getSections().begin(); sit != getSections().end(); ++sit) {
129  buf = "\n[";
130  buf += (*sit).first.c_str();
131  buf += "]\n";
132  cfile->write(buf.c_str(), buf.length());
133  for (entry = (*sit).second.begin(); entry != (*sit).second.end(); ++entry) {
134  buf = (*entry).first.c_str();
135  buf += "=";
136  buf += (*entry).second.c_str();
137  buf += "\n";
138  cfile->write(buf.c_str(), buf.length());
139  }
140  }
141  buf = "\n";
142  cfile->write(buf.c_str(), buf.length());
144  }
145 }
146 
147 
148 void SWConfig::augment(const SWConfig &addFrom) {
149 
150  SectionMap::const_iterator section;
151  ConfigEntMap::const_iterator entry, start, end;
152 
153  for (section = addFrom.getSections().begin(); section != addFrom.getSections().end(); ++section) {
154  for (entry = (*section).second.begin(); entry != (*section).second.end(); ++entry) {
155  start = getSections()[section->first].lower_bound(entry->first);
156  end = getSections()[section->first].upper_bound(entry->first);
157  // do we have multiple instances of the same key?
158  if (start != end) {
159  // TODO: what is this?
160  ConfigEntMap::const_iterator x = addFrom.getSections().find(section->first)->second.lower_bound(entry->first);
161  ConfigEntMap::const_iterator y = addFrom.getSections().find(section->first)->second.upper_bound(entry->first);
162  ++x;
163  if (((++start) != end) || (x != y)) {
164  for (--start; start != end; ++start) {
165  if (!strcmp(start->second.c_str(), entry->second.c_str()))
166  break;
167  }
168  if (start == end)
169  getSections()[(*section).first].insert(ConfigEntMap::value_type((*entry).first, (*entry).second));
170  }
171  else getSections()[section->first][entry->first.c_str()] = entry->second.c_str();
172  }
173  else getSections()[section->first][entry->first.c_str()] = entry->second.c_str();
174  }
175  }
176 }
177 
178 
179 #if defined(__GNUC__)
180 #pragma GCC diagnostic push
181 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
182 #endif
183 
184 // TODO: use deprecated public 'Sections' property for now until we remove deprecation
185 // and store in private property
187 
188 // TODO: use deprecated public 'filename' property for now until we remove deprecation
189 // and store in private property
190 
192 
193 #if defined(__GNUC__)
194 #pragma GCC diagnostic pop
195 #endif
196 
198 
#define SWORD_NAMESPACE_START
Definition: defs.h:39
virtual void load()
Definition: swconfig.cpp:55
FileDesc * open(const char *path, int mode, bool tryDowngrade)
Definition: filemgr.cpp:175
Definition: swbuf.h:47
unsigned long length() const
Definition: swbuf.h:197
virtual SectionMap & getSections()
Definition: swconfig.cpp:186
static unsigned int RDONLY
Definition: filemgr.h:75
static unsigned int RDWR
Definition: filemgr.h:76
static unsigned int TRUNC
Definition: filemgr.h:74
SWBuf getFileName() const
Definition: swconfig.cpp:191
int getFd()
Definition: filemgr.h:231
long write(const void *buf, long count)
Definition: filemgr.cpp:153
SWDEPRECATED SectionMap Sections
Definition: swconfig.h:125
void close(FileDesc *file)
Definition: filemgr.cpp:196
return NULL
Definition: regex.c:7953
virtual void augment(const SWConfig &addFrom)
Definition: swconfig.cpp:148
const char * c_str() const
Definition: swbuf.h:158
std::map< SWBuf, ConfigEntMap, std::less< SWBuf > > SectionMap
Definition: swconfig.h:36
SWConfig()
Definition: swconfig.cpp:37
SWDEPRECATED SWBuf filename
Definition: swconfig.h:130
int size
Definition: regex.c:5043
virtual ~SWConfig()
Definition: swconfig.cpp:47
SWORD_NAMESPACE_START typedef multimapwithdefault< SWBuf, SWBuf, std::less< SWBuf > > ConfigEntMap
Definition: swconfig.h:35
static unsigned int CREAT
Definition: filemgr.h:72
char * strstrip(char *istr)
Definition: utilstr.cpp:118
static char getLine(FileDesc *fDesc, SWBuf &line)
Definition: filemgr.cpp:527
#define SWORD_NAMESPACE_END
Definition: defs.h:40
virtual void save() const
Definition: swconfig.cpp:115
static FileMgr * getSystemFileMgr()
Definition: filemgr.cpp:101