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-2020 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 <cassert>
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  PTREE* list = &aTree->push_back( PTREE::value_type( key, PTREE() ) )->second;
64 
65  if( tok != DSN_RIGHT )
66  {
67  while( ( tok = aLexer->NextTok() ) != DSN_RIGHT )
68  {
69  if( tok == DSN_EOF )
70  aLexer->Unexpected( DSN_EOF );
71 
72  Scan( list, aLexer );
73  }
74  }
75 }
76 
77 
78 inline void scanAtom( PTREE* aTree, const DSNLEXER* aLexer )
79 {
80  const char* key = aLexer->CurText();
81 
82  aTree->push_back( PTREE::value_type( key, PTREE() ) );
83 }
84 
85 
86 void Scan( PTREE* aTree, DSNLEXER* aLexer )
87 {
88  int tok = aLexer->CurTok();
89 
90  // conditionally read first token.
91  if( tok == DSN_NONE )
92  tok = aLexer->NextTok();
93 
94  if( tok == DSN_EOF )
95  {
96  aLexer->Unexpected( DSN_EOF );
97  }
98 
99  if( tok == DSN_LEFT )
100  {
101  scanList( aTree, aLexer );
102  }
103  else
104  {
105  scanAtom( aTree, aLexer );
106  }
107 }
108 
109 
110 //-----<Format>------------------------------------------------------------------
111 
112 inline bool isAtom( const CPTREE& aTree )
113 {
114  return aTree.size() == 0 && aTree.data().size() == 0;
115 }
116 
117 
118 inline bool isLast( const CPTREE& aTree, CITER it )
119 {
120  CITER next = it;
121  ++next;
122  return next == aTree.end();
123 }
124 
125 
126 inline CITER next( CITER it )
127 {
128  CITER n = it;
129  return ++n;
130 }
131 
132 
133 static void formatNode( OUTPUTFORMATTER* out, int aNestLevel, int aCtl,
134  const std::string& aKey, const CPTREE& aTree );
135 
136 
137 static void formatList( OUTPUTFORMATTER* out, int aNestLevel, int aCtl, const CPTREE& aTree )
138 {
139  for( CITER it = aTree.begin(); it != aTree.end(); ++it )
140  {
141  // Processing a tree which was read in with xml_parser?
142  if( it->first == "<xmlattr>" )
143  {
144  formatList( out, aNestLevel, aCtl | CTL_IN_ATTRS, it->second );
145  continue;
146  }
147 
148  int ctl = 0;
149 
150  if( isLast( aTree, it ) ) // is "it" the last one?
151  {
152  //if( !( aCtl & CTL_IN_ATTRS ) )
153  ctl = CTL_OMIT_NL;
154  }
155  else if( isAtom( next( it )->second ) )
156  {
157  /* if( !( aCtl & CTL_IN_ATTRS ) ) */
158  ctl = CTL_OMIT_NL;
159  }
160 
161  formatNode( out, aNestLevel+1, ctl, it->first, it->second );
162  }
163 }
164 
165 
166 static void formatNode( OUTPUTFORMATTER* out, int aNestLevel, int aCtl,
167  const std::string& aKey, const CPTREE& aTree )
168 
169 {
170  if( !isAtom( aTree ) ) // is a list, not an atom
171  {
172  int ctl = CTL_OMIT_NL;
173 
174  // aTree is list and its first child is a list
175  if( aTree.size() && !isAtom( aTree.begin()->second ) && !aTree.data().size() )
176  ctl = 0;
177 
178  out->Print( aNestLevel, "(%s%s", out->Quotes( aKey ).c_str(), ctl & CTL_OMIT_NL ? "" : "\n" );
179 
180  if( aTree.data().size() ) // sexpr format does not use data()
181  {
182  out->Print( 0, " %s%s",
183  out->Quotes( aTree.data() ).c_str(),
184  aTree.size() ? "\n" : ""
185  );
186  }
187 
188  formatList( out, aNestLevel, aCtl, aTree );
189 
190  out->Print( 0, ")%s", aCtl & CTL_OMIT_NL ? "" : "\n" );
191  }
192 
193  else // is an atom, not a list
194  {
195  out->Print( 0, " %s", out->Quotes( aKey ).c_str() );
196  }
197 }
198 
199 
200 void Format( OUTPUTFORMATTER* out, int aNestLevel, int aCtl, const CPTREE& aTree )
201 {
202  if( aTree.size() == 1 && !aTree.data().size() )
203  {
204  // The topmost node is basically only a container for the document root.
205  // It anchors the paths which traverse the tree deeper.
206  CITER it = aTree.begin();
207  formatNode( out, aNestLevel, aCtl, it->first, it->second );
208  }
209  else
210  {
211  // This is not expected, neither for sexpr nor xml.
212  formatNode( out, aNestLevel, aCtl, "", aTree );
213  }
214 }
215 
CITER next(CITER it)
Definition: ptree.cpp:126
void Scan(PTREE *aTree, DSNLEXER *aLexer)
Function Scan fills an empty PTREE with information from a KiCad s-expresion stream.
Definition: ptree.cpp:86
static void formatNode(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const std::string &aKey, const CPTREE &aTree)
Definition: ptree.cpp:166
PTREE::iterator ITER
Definition: ptree.cpp:36
PTREE::const_iterator CITER
Definition: ptree.cpp:35
static void formatList(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Definition: ptree.cpp:137
OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a convenient ...
Definition: richio.h:328
bool isLast(const CPTREE &aTree, CITER it)
Definition: ptree.cpp:118
const char * CurText() const
Function CurText returns a pointer to the current token's text.
Definition: dsnlexer.h:489
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
void scanAtom(PTREE *aTree, const DSNLEXER *aLexer)
Definition: ptree.cpp:78
boost::property_tree::ptree PTREE
Definition: ptree.h:54
#define CTL_IN_ATTRS
Definition: ptree.cpp:45
bool isAtom(const CPTREE &aTree)
Definition: ptree.cpp:112
const PTREE CPTREE
Definition: ptree.h:55
int CurTok() const
Function CurTok returns whatever NextTok() returned the last time it was called.
Definition: dsnlexer.h:321
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
virtual std::string Quotes(const std::string &aWrapee)
Function Quotes checks aWrapee input string for a need to be quoted (e.g.
Definition: richio.cpp:437
#define CTL_OMIT_NL
Definition: ptree.cpp:44
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:508
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:408
void Unexpected(int aTok) const
Function Unexpected throws an IO_ERROR exception with an input file specific error message.
Definition: dsnlexer.cpp:337
DSNLEXER implements a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:80