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