KiCad PCB EDA Suite
ptree.cpp
Go to the documentation of this file.
1 
2 /*
3  * This program source code file is part of KiCad, a free EDA CAD application.
4  *
5  * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2013 KiCad Developers, see CHANGELOG.TXT for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 // Something in either <boost/property_tree/ptree.hpp> causes a bunch of compiler
27 // errors in <wx/msw/winundef.h> version 2.9 on MinGW.
28 #include <macros.h>
29 
30 #include <boost/property_tree/ptree.hpp>
31 
32 #include <assert.h>
33 #include <ptree.h>
34 
35 typedef PTREE::const_iterator CITER;
36 typedef PTREE::iterator ITER;
37 
38 #if defined(DEBUG)
39  #define D(x) x
40 #else
41  #define D(x)
42 #endif
43 
44 #define CTL_OMIT_NL (1<<0)
45 #define CTL_IN_ATTRS (1<<1)
46 
47 
48 //-----<Scan>------------------------------------------------------------------
49 
55 inline void scanList( PTREE* aTree, DSNLEXER* aLexer )
56 {
57  assert( aLexer->CurTok() == DSN_LEFT );
58 
59  int tok = aLexer->NextTok();
60 
61  const char* key = aLexer->CurText();
62 
63  //D(printf( "%s: '%s'\n", __func__, key );)
64 
65  PTREE* list = &aTree->push_back( PTREE::value_type( key, PTREE() ) )->second;
66 
67  if( tok != DSN_RIGHT )
68  {
69  while( ( tok = aLexer->NextTok() ) != DSN_RIGHT )
70  {
71  if( tok == DSN_EOF )
72  aLexer->Unexpected( DSN_EOF );
73 
74  Scan( list, aLexer );
75  }
76  }
77 }
78 
79 
80 inline void scanAtom( PTREE* aTree, DSNLEXER* aLexer )
81 {
82  const char* key = aLexer->CurText();
83 
84  //D(printf( "%s: '%s'\n", __func__, key );)
85 
86  aTree->push_back( PTREE::value_type( key, PTREE() ) );
87 }
88 
89 
90 void Scan( PTREE* aTree, DSNLEXER* aLexer ) throw( IO_ERROR )
91 {
92  int tok = aLexer->CurTok();
93 
94  // conditionally read first token.
95  if( tok == DSN_NONE )
96  tok = aLexer->NextTok();
97 
98  if( tok == DSN_EOF )
99  {
100  aLexer->Unexpected( DSN_EOF );
101  }
102 
103  if( tok == DSN_LEFT )
104  {
105  scanList( aTree, aLexer );
106  }
107  else
108  {
109  scanAtom( aTree, aLexer );
110  }
111 }
112 
113 
114 //-----<Format>------------------------------------------------------------------
115 
116 inline bool isAtom( CPTREE& aTree )
117 {
118  return aTree.size()==0 && aTree.data().size()==0;
119 }
120 
121 
122 inline bool isLast( CPTREE& aTree, CITER it )
123 {
124  CITER next = it;
125  ++next;
126  return next == aTree.end();
127 }
128 
129 
130 inline CITER next( CITER it )
131 {
132  CITER n = it;
133  return ++n;
134 }
135 
136 
137 static void formatNode( OUTPUTFORMATTER* out, int aNestLevel, int aCtl,
138  const std::string& aKey, CPTREE& aTree ) throw( IO_ERROR );
139 
140 
141 static void formatList( OUTPUTFORMATTER* out, int aNestLevel, int aCtl, CPTREE& aTree )
142  throw( IO_ERROR )
143 {
144  for( CITER it = aTree.begin(); it != aTree.end(); ++it )
145  {
146  // Processing a tree which was read in with xml_parser?
147  if( it->first == "<xmlattr>" )
148  {
149  formatList( out, aNestLevel, aCtl | CTL_IN_ATTRS, it->second );
150  continue;
151  }
152 
153  int ctl = 0;
154 
155  if( isLast( aTree, it ) ) // is "it" the last one?
156  {
157  //if( !( aCtl & CTL_IN_ATTRS ) )
158  ctl = CTL_OMIT_NL;
159  }
160  else if( isAtom( next( it )->second ) )
161  {
162  /* if( !( aCtl & CTL_IN_ATTRS ) ) */
163  ctl = CTL_OMIT_NL;
164  }
165 
166  formatNode( out, aNestLevel+1, ctl, it->first, it->second );
167  }
168 }
169 
170 
171 static void formatNode( OUTPUTFORMATTER* out, int aNestLevel, int aCtl,
172  const std::string& aKey, CPTREE& aTree )
173  throw( IO_ERROR )
174 {
175  if( !isAtom( aTree ) ) // is a list, not an atom
176  {
177  int ctl = CTL_OMIT_NL;
178 
179  // aTree is list and its first child is a list
180  if( aTree.size() && !isAtom( aTree.begin()->second ) && !aTree.data().size() )
181  ctl = 0;
182 
183  out->Print( aNestLevel, "(%s%s", out->Quotes( aKey ).c_str(), ctl & CTL_OMIT_NL ? "" : "\n" );
184 
185  if( aTree.data().size() ) // sexpr format does not use data()
186  {
187  out->Print( 0, " %s%s",
188  out->Quotes( aTree.data() ).c_str(),
189  aTree.size() ? "\n" : ""
190  );
191  }
192 
193  formatList( out, aNestLevel, aCtl, aTree );
194 
195  out->Print( 0, ")%s", aCtl & CTL_OMIT_NL ? "" : "\n" );
196  }
197 
198  else // is an atom, not a list
199  {
200  out->Print( 0, " %s", out->Quotes( aKey ).c_str() );
201  }
202 }
203 
204 
205 void Format( OUTPUTFORMATTER* out, int aNestLevel, int aCtl, CPTREE& aTree ) throw( IO_ERROR )
206 {
207  if( aTree.size() == 1 && !aTree.data().size() )
208  {
209  // The topmost node is basically only a container for the document root.
210  // It anchors the paths which traverse the tree deeper.
211  CITER it = aTree.begin();
212  formatNode( out, aNestLevel, aCtl, it->first, it->second );
213  }
214  else
215  {
216  // This is not expected, neither for sexpr nor xml.
217  formatNode( out, aNestLevel, aCtl, "", aTree );
218  }
219 }
220 
CITER next(CITER it)
Definition: ptree.cpp:130
void Scan(PTREE *aTree, DSNLEXER *aLexer)
Function Scan fills an empty PTREE with information from a KiCad s-expresion stream.
Definition: ptree.cpp:90
const PTREE CPTREE
Definition: eagle_plugin.h:63
bool isLast(CPTREE &aTree, CITER it)
Definition: ptree.cpp:122
PTREE::iterator ITER
Definition: ptree.cpp:36
void Unexpected(int aTok)
Function Unexpected throws an IO_ERROR exception with an input file specific error message...
Definition: dsnlexer.cpp:369
PTREE::const_iterator CITER
Definition: ptree.cpp:35
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
static void formatList(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Definition: ptree.cpp:141
bool isAtom(CPTREE &aTree)
Definition: ptree.cpp:116
This file contains miscellaneous commonly used macros and functions.
void scanList(PTREE *aTree, DSNLEXER *aLexer)
Function scanList reads a sexpr list from the input stream into a new node with key aLexer->CurText()...
Definition: ptree.cpp:55
#define CTL_IN_ATTRS
Definition: ptree.cpp:45
int CurTok()
Function CurTok returns whatever NextTok() returned the last time it was called.
Definition: dsnlexer.h:320
void scanAtom(PTREE *aTree, DSNLEXER *aLexer)
Definition: ptree.cpp:80
static void formatNode(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const std::string &aKey, CPTREE &aTree)
Definition: ptree.cpp:171
PTREE::const_iterator CITER
#define CTL_OMIT_NL
Definition: ptree.cpp:44
boost::property_tree::ptree PTREE
Definition: eagle_plugin.h:62
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
int NextTok()
Function NextTok returns the next token found in the input file or DSN_EOF when reaching the end of f...
Definition: dsnlexer.cpp:540
const char * CurText()
Function CurText returns a pointer to the current token's text.
Definition: dsnlexer.h:479
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
Class DSNLEXER implements a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:79