root/trunk/libffado/src/libutil/serialize_libxml.cpp

Revision 1254, 10.0 kB (checked in by ppalmers, 14 years ago)

split config.h into config/version/debug_config to allow for faster compilation (splits dependencies)

Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "version.h" // FOR CACHE_VERSION
25
26 #include "serialize.h"
27
28 #include <cstring>
29 #include <cstdlib>
30
31 using namespace std;
32
33 IMPL_DEBUG_MODULE( Util::XMLSerialize,   XMLSerialize,   DEBUG_LEVEL_NORMAL );
34 IMPL_DEBUG_MODULE( Util::XMLDeserialize, XMLDeserialize, DEBUG_LEVEL_NORMAL );
35
36 Util::XMLSerialize::XMLSerialize( std::string fileName )
37     : IOSerialize()
38     , m_filepath( fileName )
39     , m_verboseLevel( DEBUG_LEVEL_NORMAL )
40 {
41     setDebugLevel( DEBUG_LEVEL_NORMAL );
42     try {
43         m_doc.create_root_node( "ffado_cache" );
44         writeVersion();
45     } catch ( const exception& ex ) {
46         cout << "Exception caught: " << ex.what();
47     }
48 }
49
50 Util::XMLSerialize::XMLSerialize( std::string fileName, int verboseLevel )
51     : IOSerialize()
52     , m_filepath( fileName )
53     , m_verboseLevel( verboseLevel )
54 {
55     setDebugLevel(verboseLevel);
56     try {
57         m_doc.create_root_node( "ffado_cache" );
58         writeVersion();
59     } catch ( const exception& ex ) {
60         cout << "Exception caught: " << ex.what();
61     }
62 }
63
64 Util::XMLSerialize::~XMLSerialize()
65 {
66     try {
67         m_doc.write_to_file_formatted( m_filepath );
68     } catch ( const exception& ex ) {
69         cout << "Exception caugth: " << ex.what();
70     }
71
72 }
73
74 void
75 Util::XMLSerialize::writeVersion()
76 {
77     xmlpp::Node* pNode = m_doc.get_root_node();
78     xmlpp::Element* pElem = pNode->add_child( "CacheVersion" );
79     char* valstr;
80     asprintf( &valstr, "%s", CACHE_VERSION );
81     pElem->set_child_text( valstr );
82     free( valstr );
83 }
84
85 bool
86 Util::XMLSerialize::write( std::string strMemberName,
87                            long long value )
88
89 {
90     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "write %s = %d\n",
91                  strMemberName.c_str(), value );
92
93     vector<string> tokens;
94     tokenize( strMemberName, tokens, "/" );
95
96     if ( tokens.size() == 0 ) {
97         debugWarning( "token size is 0\n" );
98         return false;
99     }
100
101     xmlpp::Node* pNode = m_doc.get_root_node();
102     pNode = getNodePath( pNode, tokens );
103
104     // element to be added
105     xmlpp::Element* pElem = pNode->add_child( tokens[tokens.size() - 1] );
106     char* valstr;
107     asprintf( &valstr, "%lld", value );
108     pElem->set_child_text( valstr );
109     free( valstr );
110
111     return true;
112 }
113
114 bool
115 Util::XMLSerialize::write( std::string strMemberName,
116                            std::string str)
117 {
118     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "write %s = %s\n",
119                  strMemberName.c_str(), str.c_str() );
120
121     vector<string> tokens;
122     tokenize( strMemberName, tokens, "/" );
123
124     if ( tokens.size() == 0 ) {
125         debugWarning( "token size is 0\n" );
126         return false;
127     }
128
129     xmlpp::Node* pNode = m_doc.get_root_node();
130     pNode = getNodePath( pNode, tokens );
131
132     // element to be added
133     xmlpp::Element* pElem = pNode->add_child( tokens[tokens.size() - 1] );
134     pElem->set_child_text( str );
135
136     return true;
137 }
138
139 xmlpp::Node*
140 Util::XMLSerialize::getNodePath( xmlpp::Node* pRootNode,
141                                  std::vector<string>& tokens )
142 {
143     // returns the correct node on which the new element has to be added.
144     // if the path does not exist, it will be created.
145
146     if ( tokens.size() == 1 ) {
147         return pRootNode;
148     }
149
150     unsigned int iTokenIdx = 0;
151     xmlpp::Node* pCurNode = pRootNode;
152     for (bool bFound = false;
153          ( iTokenIdx < tokens.size() - 1 );
154          bFound = false, iTokenIdx++ )
155     {
156         xmlpp::Node::NodeList nodeList = pCurNode->get_children();
157         for ( xmlpp::Node::NodeList::iterator it = nodeList.begin();
158               it != nodeList.end();
159               ++it )
160         {
161             if ( ( *it )->get_name() == tokens[iTokenIdx] ) {
162                 pCurNode = *it;
163                 bFound = true;
164                 break;
165             }
166         }
167         if ( !bFound ) {
168             break;
169         }
170     }
171
172     for ( unsigned int i = iTokenIdx; i < tokens.size() - 1; i++, iTokenIdx++ ) {
173         pCurNode = pCurNode->add_child( tokens[iTokenIdx] );
174     }
175     return pCurNode;
176
177 }
178
179 /***********************************/
180
181 Util::XMLDeserialize::XMLDeserialize( std::string fileName )
182     : IODeserialize()
183     , m_filepath( fileName )
184     , m_verboseLevel( DEBUG_LEVEL_NORMAL )
185 {
186     setDebugLevel(DEBUG_LEVEL_NORMAL);
187     try {
188         m_parser.set_substitute_entities(); //We just want the text to
189                                             //be resolved/unescaped
190                                             //automatically.
191         m_parser.parse_file( m_filepath );
192     } catch ( const exception& ex ) {
193         cout << "Exception caught: " << ex.what();
194     }
195 }
196
197 Util::XMLDeserialize::XMLDeserialize( std::string fileName, int verboseLevel )
198     : IODeserialize()
199     , m_filepath( fileName )
200     , m_verboseLevel( verboseLevel )
201 {
202     setDebugLevel(verboseLevel);
203     try {
204         m_parser.set_substitute_entities(); //We just want the text to
205                                             //be resolved/unescaped
206                                             //automatically.
207         m_parser.parse_file( m_filepath );
208     } catch ( const exception& ex ) {
209         cout << "Exception caught: " << ex.what();
210     }
211 }
212
213 Util::XMLDeserialize::~XMLDeserialize()
214 {
215 }
216
217 bool
218 Util::XMLDeserialize::isValid()
219 {
220     return checkVersion();
221 }
222
223 bool
224 Util::XMLDeserialize::checkVersion()
225 {
226     std::string savedVersion;
227     if (read( "CacheVersion", savedVersion )) {
228         Glib::ustring expectedVersion = CACHE_VERSION;
229         debugOutput( DEBUG_LEVEL_NORMAL, "Cache version: %s, expected: %s.\n", savedVersion.c_str(), expectedVersion.c_str() );
230         if (expectedVersion == savedVersion) {
231             debugOutput( DEBUG_LEVEL_VERBOSE, "Cache version OK.\n" );
232             return true;
233         } else {
234             debugOutput( DEBUG_LEVEL_VERBOSE, "Cache version not OK.\n" );
235             return false;
236         }
237     } else return false;
238 }
239
240 bool
241 Util::XMLDeserialize::read( std::string strMemberName,
242                             long long& value )
243
244 {
245     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "lookup %s\n", strMemberName.c_str() );
246
247     xmlpp::Document *pDoc=m_parser.get_document();
248     if(!pDoc) {
249         debugWarning( "no document found\n" );
250         return false;
251     }
252     xmlpp::Node* pNode = pDoc->get_root_node();
253
254     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "pNode = %s\n", pNode->get_name().c_str() );
255
256     xmlpp::NodeSet nodeSet = pNode->find( strMemberName );
257     for ( xmlpp::NodeSet::iterator it = nodeSet.begin();
258           it != nodeSet.end();
259           ++it )
260     {
261         const xmlpp::Element* pElement =
262             dynamic_cast< const xmlpp::Element* >( *it );
263         if ( pElement && pElement->has_child_text() ) {
264             char* tail;
265             value = strtoll( pElement->get_child_text()->get_content().c_str(),
266                              &tail, 0 );
267             debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "found %s = %d\n",
268                          strMemberName.c_str(), value );
269             return true;
270         }
271         debugWarning( "no such a node %s\n", strMemberName.c_str() );
272         return false;
273     }
274
275     debugWarning( "no such a node %s\n", strMemberName.c_str() );
276     return false;
277 }
278
279 bool
280 Util::XMLDeserialize::read( std::string strMemberName,
281                             std::string& str )
282 {
283     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "lookup %s\n", strMemberName.c_str() );
284
285     xmlpp::Document *pDoc=m_parser.get_document();
286     if(!pDoc) {
287         debugWarning( "no document found\n" );
288         return false;
289     }
290     xmlpp::Node* pNode = pDoc->get_root_node();
291
292     xmlpp::NodeSet nodeSet = pNode->find( strMemberName );
293     for ( xmlpp::NodeSet::iterator it = nodeSet.begin();
294           it != nodeSet.end();
295           ++it )
296     {
297         const xmlpp::Element* pElement = dynamic_cast< const xmlpp::Element* >( *it );
298         if ( pElement ) {
299             if ( pElement->has_child_text() ) {
300                 str = pElement->get_child_text()->get_content();
301             } else {
302                 str = "";
303             }
304             debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "found %s = %s\n",
305                          strMemberName.c_str(), str.c_str() );
306             return true;
307         }
308         debugWarning( "no such a node %s\n", strMemberName.c_str() );
309         return false;
310     }
311
312     debugWarning( "no such a node %s\n", strMemberName.c_str() );
313     return false;
314 }
315
316 bool
317 Util::XMLDeserialize::isExisting( std::string strMemberName )
318 {
319     xmlpp::Document *pDoc=m_parser.get_document();
320     if(!pDoc) {
321         return false;
322     }
323     xmlpp::Node* pNode = pDoc->get_root_node();
324     xmlpp::NodeSet nodeSet = pNode->find( strMemberName );
325     return nodeSet.size() > 0;
326 }
327
328 void
329 tokenize(const string& str,
330          vector<string>& tokens,
331          const string& delimiters)
332 {
333     // Skip delimiters at beginning.
334     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
335     // Find first "non-delimiter".
336     string::size_type pos     = str.find_first_of(delimiters, lastPos);
337
338     while (string::npos != pos || string::npos != lastPos)
339     {
340         // Found a token, add it to the vector.
341         tokens.push_back(str.substr(lastPos, pos - lastPos));
342         // Skip delimiters.  Note the "not_of"
343         lastPos = str.find_first_not_of(delimiters, pos);
344         // Find next "non-delimiter"
345         pos = str.find_first_of(delimiters, lastPos);
346     }
347 }
Note: See TracBrowser for help on using the browser.