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