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

Revision 1154, 9.9 kB (checked in by ppalmers, 14 years ago)

add expat based parsing of the device cache. add compile-time selection between libxml++ and expat. will allow to get rid of the libxml++ dependency on the long run. scons SERIALIZE_USE_EXPAT=0Only compile testedscons SERIALIZE_USE_EXPAT=0

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