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 <[email protected]>
6 * Copyright (C) 2013-2020 KiCad Developers, see AUTHORS.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
35typedef PTREE::const_iterator CITER;
36typedef 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
55inline 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
78inline 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
86void 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
112inline bool isAtom( const CPTREE& aTree )
113{
114 return aTree.size() == 0 && aTree.data().size() == 0;
115}
116
117
118inline bool isLast( const CPTREE& aTree, CITER it )
119{
120 CITER next = it;
121 ++next;
122 return next == aTree.end();
123}
124
125
126inline CITER next( CITER it )
127{
128 CITER n = it;
129 return ++n;
130}
131
132
133static void formatNode( OUTPUTFORMATTER* out, int aNestLevel, int aCtl,
134 const std::string& aKey, const CPTREE& aTree );
135
136
137static 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
166static 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
200void 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
Implement a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:79
const char * CurText() const
Return a pointer to the current token's text.
Definition: dsnlexer.h:398
int NextTok()
Return the next token found in the input file or DSN_EOF when reaching the end of file.
Definition: dsnlexer.cpp:519
int CurTok() const
Return whatever NextTok() returned the last time it was called.
Definition: dsnlexer.h:237
void Unexpected(int aTok) const
Throw an IO_ERROR exception with an input file specific error message.
Definition: dsnlexer.cpp:342
An interface used to output 8 bit text in a convenient way.
Definition: richio.h:310
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition: richio.cpp:431
virtual std::string Quotes(const std::string &aWrapee) const
Check aWrapee input string for a need to be quoted (e.g.
Definition: richio.cpp:460
@ DSN_LEFT
Definition: dsnlexer.h:67
@ DSN_RIGHT
Definition: dsnlexer.h:66
@ DSN_NONE
Definition: dsnlexer.h:59
@ DSN_EOF
Definition: dsnlexer.h:69
This file contains miscellaneous commonly used macros and functions.
PTREE::iterator ITER
Definition: ptree.cpp:36
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
bool isLast(const CPTREE &aTree, CITER it)
Definition: ptree.cpp:118
void scanAtom(PTREE *aTree, const DSNLEXER *aLexer)
Definition: ptree.cpp:78
#define CTL_IN_ATTRS
Definition: ptree.cpp:45
static void formatList(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Definition: ptree.cpp:137
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
bool isAtom(const CPTREE &aTree)
Definition: ptree.cpp:112
PTREE::const_iterator CITER
Definition: ptree.cpp:35
static void formatNode(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const std::string &aKey, const CPTREE &aTree)
Definition: ptree.cpp:166
CITER next(CITER it)
Definition: ptree.cpp:126
void Scan(PTREE *aTree, DSNLEXER *aLexer)
Fill an empty PTREE with information from a KiCad s-expression stream.
Definition: ptree.cpp:86
#define CTL_OMIT_NL
Definition: ptree.cpp:44
const PTREE CPTREE
Definition: ptree.h:53
boost::property_tree::ptree PTREE
Definition: ptree.h:52