Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
easydom.h
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 
22 /*
23  * easyDom - easy DOM for expat - written by Alexander Rawass <alexannika@users.sourceforge.net>
24  */
25 
26 #ifndef _EASYDOM_H_
27 #define _EASYDOM_H_
28 #include "config.h"
29 #include <expat.h>
30 #include <string>
31 #include <vector>
32 #include <stack>
33 #include <gnuhash.h>
34 #include <stdlib.h>
35 #include "vsfilesystem.h"
36 //using namespace VSFileSystem;
39 using VSFileSystem::Ok;
45 #include "xml_support.h"
46 
47 using std::string;
48 using std::vector;
49 using std::stack;
50 using std::ostream;
51 
53 
54 extern string parseCalike( char const *filename );
55 
57 {
58 public: easyDomNode();
59 
60  void set( easyDomNode *parent, string name, const XML_Char **atts );
61  void printNode( ostream &out, int recurse_level, int level );
62 
63  void addChild( easyDomNode *child );
64 
65  string Name()
66  {
67  return name;
68  }
69 
70  void set_attribute( string name, string value )
71  {
72  attribute_map[name] = value;
73  }
74 
75  string attr_value( string attr_name );
76  vector< easyDomNode* >subnodes;
77 
78 private:
79  easyDomNode *parent;
80  AttributeList *attributes;
81  vsUMap< string, string >attribute_map;
82 //vector<string> att_name;
83 //vector<string> att_value;
84 
85  string name;
86 };
87 
88 typedef vsUMap< string, int >tagMap;
89 
90 class tagDomNode : public easyDomNode
91 {
92 public:
93  int tag;
94 
95  void Tag( tagMap *tagmap )
96  {
97  tag = (*tagmap)[Name()];
98  if (tag == 0) {
99  //cout << "cannot translate tag " << Name() << endl;
100  }
101  vector< easyDomNode* >::const_iterator siter;
102  for (siter = subnodes.begin(); siter != subnodes.end(); siter++) {
103  tagDomNode *tnode = (tagDomNode*) (*siter);
104  tnode->Tag( tagmap );
105  }
106  }
107 };
108 
109 extern const char *textAttr; //should be a static const inside easyDomFactory...
110 
111 template < class domNodeType >
113 {
114 public: easyDomFactory() {}
115 
116  void getColor( char *name, float color[4] );
117  char * getVariable( char *section, char *name );
118 
119  void c_alike_to_xml( const char *filename );
120 
122  {
124  char *buffer;
126  {
127  buffer = 0;
128  currentindex = 0;
129  }
130  }
131  *xml;
132 
133  domNodeType * LoadXML( const char *filename )
134  {
135  topnode = NULL;
136  //Not really nice but should do its job
137  unsigned int length = strlen( filename );
138  VSFile f;
139  VSError err = FileNotFound;
140  if ( length > 8 && !memcmp( (filename+length-7), "mission", 7 ) )
141  err = f.OpenReadOnly( filename, MissionFile );
142  if (err > Ok) {
143  err = f.OpenReadOnly( filename, UnknownFile );
144  if (err > Ok) {
145  string rootthis = string( "/" )+filename;
146  err = f.OpenReadOnly( rootthis, UnknownFile );
147  }
148  }
149  if (err > Ok) {
150  string prefix = ("../mission/");
151  prefix += filename;
152  err = f.OpenReadOnly( prefix.c_str(), UnknownFile );
153  }
154  if (err > Ok) {
155  string prefix = ("mission/");
156  prefix += filename;
157  err = f.OpenReadOnly( prefix.c_str(), UnknownFile );
158  }
159  if (err > Ok) {
160  string prefix = ("../");
161  prefix += filename;
162  err = f.OpenReadOnly( prefix.c_str(), UnknownFile );
163  }
164  if (err > Ok)
165  //cout << "warning: could not open file: " << filename << endl;
166  //assert(0);
167  return NULL;
168  xml = new easyDomFactoryXML;
169 
170  XML_Parser parser = XML_ParserCreate( NULL );
171  XML_SetUserData( parser, this );
172  XML_SetElementHandler( parser, &easyDomFactory::beginElement, &easyDomFactory::endElement );
173  XML_SetCharacterDataHandler( parser, &easyDomFactory::charHandler );
174 
175  XML_Parse( parser, ( f.ReadFull() ).c_str(), f.Size(), 1 );
176  /*
177  * do {
178  * #ifdef BIDBG
179  * char *buf = (XML_Char*)XML_GetBuffer(parser, chunk_size);
180  * #else
181  * char buf[chunk_size];
182  * #endif
183  * int length;
184  *
185  * length = fread (buf,1, chunk_size,inFile);
186  * //length = inFile.gcount();
187  * #ifdef BIDBG
188  * XML_ParseBuffer(parser, length, feof(inFile));
189  * #else
190  * XML_Parse(parser, buf, length, feof(inFile));
191  * #endif
192  * } while(!feof(inFile));
193  */
194  f.Close();
195  XML_ParserFree( parser );
196  delete xml;
197  return (domNodeType*) topnode;
198  }
199 
200  static void charHandler( void *userData, const XML_Char *s, int len )
201  {
202  easyDomFactoryXML *xml = ( (easyDomFactory< domNodeType >*)userData )->xml;
203  if (!xml->buffer)
204  xml->buffer = (char*) malloc( sizeof (char)*(len+1) );
205  else
206  xml->buffer = (char*) realloc( xml->buffer, sizeof (char)*(len+1+xml->currentindex) );
207  strncpy( xml->buffer+xml->currentindex, s, len );
208  xml->currentindex += len;
209  }
210 
211  domNodeType * LoadCalike( const char *filename )
212  {
213  const int chunk_size = 262144;
214 
215  string module_str = parseCalike( filename );
216  if ( module_str.empty() )
217  //cout << "warning: could not open file: " << filename << endl;
218  //assert(0);
219  return NULL;
220  xml = new easyDomFactoryXML;
221 
222  XML_Parser parser = XML_ParserCreate( NULL );
223  XML_SetUserData( parser, this );
224  XML_SetElementHandler( parser, &easyDomFactory::beginElement, &easyDomFactory::endElement );
225  XML_SetCharacterDataHandler( parser, &easyDomFactory::charHandler );
226 
227  int index = 0;
228  int string_size = module_str.size();
229  int incr = chunk_size-2;
230  int is_final = false;
231  do {
232  char buf[chunk_size];
233 
234  int max_index = index+incr;
235  int newlen = incr;
236  //printf("max_index=%d,string_size=%d\n",max_index,string_size);
237  if (max_index >= string_size) {
238  newlen = module_str.size()-index;
239  //printf("getting string from %d length %d\n",index,newlen);
240  const char *strbuf = module_str.c_str();
241  memcpy( buf, strbuf+index, sizeof (char)*newlen );
242  } else {
243  //printf("getting string from %d length %d\n",index,incr);
244  const char *strbuf = module_str.c_str();
245  memcpy( buf, strbuf+index, sizeof (char)*incr );
246  newlen = incr;
247  }
248  index += newlen;
249  if (index >= string_size)
250  is_final = true;
251  XML_Parse( parser, buf, newlen, is_final );
252  } while (!is_final);
253  XML_ParserFree( parser );
254  delete xml;
255  return (domNodeType*) topnode;
256  }
257 
258  static void beginElement( void *userData, const XML_Char *name, const XML_Char **atts )
259  {
260  ( (easyDomFactory*) userData )->beginElement( name, atts );
261  }
262  static void endElement( void *userData, const XML_Char *name )
263  {
264  ( (easyDomFactory*) userData )->endElement( name );
265  }
266 
267 //void beginElement(const string &name, const AttributeList &attributes){
269  {
270  if ( !nodestack.size() )
271  return;
272  domNodeType *stacktop = nodestack.top();
273  if (xml->buffer) {
274  xml->buffer[xml->currentindex] = '\0';
275  stacktop->set_attribute( textAttr, ( stacktop->attr_value( textAttr ) )+(xml->buffer) );
276  free( xml->buffer );
277  }
278  xml->buffer = 0;
279  xml->currentindex = 0;
280  }
281 
282  void beginElement( const string &name, const XML_Char **atts )
283  {
284  //AttributeList::const_iterator iter;
285 
286  doTextBuffer();
287  domNodeType *parent;
288  bool hasParent = false;
289  if ( nodestack.empty() ) {
290  parent = NULL;
291  } else {
292  hasParent = true;
293  parent = nodestack.top();
294  }
295  domNodeType *thisnode = new domNodeType();
296  thisnode->set( parent, name, atts );
297  if (!hasParent)
298  topnode = thisnode;
299  else
300  parent->addChild( thisnode );
301  nodestack.push( thisnode );
302  }
303 
304  void endElement( const string &name )
305  {
306  doTextBuffer();
307  domNodeType *stacktop = nodestack.top();
308  if (stacktop->Name() != name) {
309  std::cout<<"error: expected "<<stacktop->Name()<<" , got "<<name<<std::endl;
310  exit( 1 );
311  } else {
312  nodestack.pop();
313  }
314  }
315 
316  stack< domNodeType* >nodestack;
317 
318  domNodeType *topnode;
319 };
320 
321 #endif //_EASYDOM_H_
322