Clone
ixen <ixen@copyhandler.com>
committed
on 04 Dec 16
Removed unnecessary includes. Sorted member initialization in constructors. (CH-318)
ch-1.40 + 2 more
ext/libicpf/src/libicpf/cfg_xml.cpp (+62 -5)
1 1 #include "cfg_xml.h"
2 2 #include <expat.h>
3 3 #include "exception.h"
4 4 #include <string>
5 5 #include <map>
6 6 #include <assert.h>
7 7
8 8 BEGIN_ICPF_NAMESPACE
9 9
10 10 /// Buffer size for reading xml data from a file
11 11 #define XML_BUFFER      65536
12 12
  13 // definition of line ending - system dependent
  14 #if defined(_WIN32) || defined(_WIN64)
  15         #define ENDL _t("\r\n")
  16 #else
  17         #define ENDL _t("\n")
  18 #endif
  19
13 20 // forward declaration
14 21 class xml_node;
15 22
16 23 /// Xml node storage
17 24 typedef std::map<tstring_t, xml_node> xml_storage;
18 25 /// String storage (key(s)=>value(s))
19 26 typedef std::multimap<tstring_t, tstring_t> attr_storage;
20 27
21 28 /** Class manages a single xml node.
22 29  */
23 30 class xml_node
24 31 {
25 32 public:
26 33 /** \name Construction/destruction */
27 34 /**@{*/
28 35         /// Standard constructor
29 36         xml_node() : m_mNodes(), m_mAttr(), m_pParentNode(NULL) { };
30 37         /// Constructor defining the parent node
31 38         xml_node(xml_node* pParentNode)  : m_mNodes(), m_mAttr(), m_pParentNode(pParentNode) { };
32 39 /**@}*/
 
178 185         // free parser
179 186         XML_ParserFree(parser);
180 187
181 188         // close the file
182 189         fclose(pFile);
183 190 }
184 191
185 192 /** Saves the internal xml nodes to the specified xml file.
186 193  *
187 194  * \param[in] pszPath - path to the file the data should be written to
188 195  *
189 196  * \note Function overwrites the contents of a file
190 197  */
191 198 void xml_cfg::save(const tchar_t* pszPath)
192 199 {
193 200         // read the data from file in 64kB portions and feed it to the expat xml parser
194 201         FILE* pFile=_tfopen(pszPath, _t("wb"));
195 202         if (pFile == NULL)
196 203                 THROW(icpf::exception::format(_t("Cannot open the file ") TSTRFMT _t(" for writing."), pszPath), 0, errno, 0);
197 204
  205         // put BOM into the file
  206 #if defined(_UNICODE) && (defined(_WIN32) || defined(_WIN64))
  207         // utf-16le
  208         uint_t uiBOM=0x0000feff;
  209         uint_t uiCount=2;
  210 #else
  211         // utf-8
  212         uint_t uiBOM=0x00bfbbef;
  213         uint_t uiCount=3;
  214 #endif
  215
  216         try
  217         {
  218                 // write bom, check if it succeeded
  219                 if (fwrite(&uiBOM, 1, uiCount, pFile) != uiCount)
  220                         THROW(_t("Cannot write the BOM to the file '") TSTRFMT _t("'"), 0, errno, 0);
  221
198 222                 // and write
199 223                 save_node(pFile, m_pMainNode);
  224         }
  225         catch(...)
  226         {
  227                 fclose(pFile);
  228                 throw;
  229         }
200 230
201 231         // close the file
202 232         fclose(pFile);
203 233 }
204 234
205 235 void xml_cfg::save_node(FILE* pFile, ptr_t pNodePtr)
206 236 {
207 237         xml_node* pNode=(xml_node*)pNodePtr;
208 238
209 239         // attributes first
210 240         for (attr_storage::iterator it=pNode->m_mAttr.begin();it != pNode->m_mAttr.end();it++)
211 241         {
212                   _ftprintf(pFile, _t("<") TSTRFMT _t(" value=\"") TSTRFMT _t("\"/>\n"), (*it).first, (*it).second.c_str());
  242                 const tchar_t pszFmt[]=_t("<") TSTRFMT _t(" value=\"") TSTRFMT _t("\"/>") ENDL;
  243
  244                 int_t iSize=_sctprintf(pszFmt, (*it).first.c_str(), (*it).second.c_str());
  245
  246                 if (_ftprintf(pFile, pszFmt, (*it).first.c_str(), (*it).second.c_str()) < 0)
  247                         THROW(_t("Cannot write requested data to the file"), 0, errno, 0);
213 248         }
214 249
215 250         // sub-nodes
216 251         for (xml_storage::iterator it=pNode->m_mNodes.begin();it != pNode->m_mNodes.end();it++)
217 252         {
218 253                 // tag opening
219                   _ftprintf(pFile, _t("<") TSTRFMT _t(">\n"), (*it).first);
  254                 if (_ftprintf(pFile, _t("<") TSTRFMT _t(">") ENDL, (*it).first.c_str()) < 0)
  255                         THROW(_t("Cannot write requested data to the file"), 0, errno, 0);
220 256
221 257                 save_node(pFile, &(*it).second);
222 258
223                   _ftprintf(pFile, _t("</") TSTRFMT _t(">\n"), (*it).first);
  259                 if (_ftprintf(pFile, _t("</") TSTRFMT _t(">") ENDL, (*it).first.c_str()) < 0)
  260                         THROW(_t("Cannot write requested data to the file"), 0, errno, 0);
224 261         }
225 262 }
226 263
  264 void xml_cfg::fprintf_utf8(FILE* pFile, const tchar_t* pszFmt, ...)
  265 {
  266         va_list va;
  267         va_start(va, pszFmt);
  268
  269         // get count of characters in the string
  270         int_t iCount=_vsctprintf(pszFmt, va);
  271         tchar_t* pszFormatted=new tchar_t[iCount+1];
  272
  273         // make a formatted string
  274         va_start(va, pszFmt);
  275         _vsntprintf(pszFormatted, iCount, pszFmt, va);
  276
  277
  278         delete [] pszFormatted;
  279
  280         va_end(va);
  281
  282 }
  283
227 284 /** Function starts a search operation. Given the name of the property
228 285  *  to be searched for (ie. "ch/program/startup"), funtion searches for
229 286  *  it and returns a handle that can be used by subsequent calls to the
230 287  *  find_next(). Free the handle using find_close() after finish.
231 288  *
232 289  * \param[in] pszName - name of the property to search for (in the form of
233 290  *                                              "ch/program/startup" for xml such as this:
234 291  *
235 292  *                                              <ch>
236 293  *                                                      <program>
237 294  *                                                              <startup value="1"/>
238 295  *                                                      </program>
239 296  *                                              </ch>
240 297  * \return Handle to the search (NULL if not found).
241 298  */
242 299 ptr_t xml_cfg::find(const tchar_t* pszName)
243 300 {
244 301         return find(m_pMainNode, pszName);
245 302 }
246 303