KiCad PCB EDA Suite
Loading...
Searching...
No Matches
xnode.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <fmt/format.h>
22
23#include "xnode.h"
24
25#include <richio.h>
26#include <string_utils.h>
28
29
30XATTR::XATTR( const wxString& aName, const VALUE_TYPE& aValue ) :
31 wxXmlAttribute( aName, wxEmptyString ),
32 m_originalValue( aValue )
33{
34 std::visit( [&]<typename T0>( T0&& arg )
35 {
36 using T = std::decay_t<T0>;
37
38 if constexpr( std::is_same_v<T, int> )
39 {
40 wxXmlAttribute::SetValue( wxString::Format( "%d", arg ) );
41 }
42 else if constexpr( std::is_same_v<T, double> )
43 {
44 std::string buf;
45
46 if( arg != 0.0 && std::fabs( arg ) <= 0.0001 )
47 {
48 buf = fmt::format( "{:.16f}", arg );
49
50 // remove trailing zeros (and the decimal marker if needed)
51 while( !buf.empty() && buf[buf.size() - 1] == '0' )
52 {
53 buf.pop_back();
54 }
55
56 // if the value was really small
57 // we may have just stripped all the zeros after the decimal
58 if( buf[buf.size() - 1] == '.' )
59 {
60 buf.pop_back();
61 }
62 }
63 else
64 {
65 buf = fmt::format( "{:.10g}", arg );
66 }
67
68 wxXmlAttribute::SetValue( buf );
69 }
70 else if constexpr( std::is_same_v<T, wxString> )
71 {
72 wxXmlAttribute::SetValue( arg );
73 }
74 else
75 {
76 static_assert( sizeof( T ) == 0, "Missing type handling in XNODE::FormatContents" );
77 }
78 }, aValue );
79}
80
81
82void XNODE::AddBool( const wxString& aKey, bool aValue )
83{
84 AddAttribute( aKey, aValue ? wxT( "yes" ) : wxT( "no" ) );
85}
86
87
88void XNODE::AddAttribute( const wxString& aName, const wxString& aValue )
89{
90 XATTR* attr = new XATTR( aName, aValue );
91 wxXmlNode::AddAttribute( attr );
92}
93
94
95void XNODE::AddAttribute( const wxString& aName, int aValue )
96{
97 XATTR* attr = new XATTR( aName, aValue );
98 wxXmlNode::AddAttribute( attr );
99}
100
101
102void XNODE::AddAttribute( const wxString& aName, double aValue )
103{
104 XATTR* attr = new XATTR( aName, aValue );
105 wxXmlNode::AddAttribute( attr );
106}
107
108
110{
111 switch( GetType() )
112 {
113 case wxXML_ELEMENT_NODE:
114 out->Print( "(%s", TO_UTF8( GetName() ) );
115 FormatContents( out );
116
117 if( GetNext() )
118 out->Print( 0, ")\n" );
119 else
120 out->Print( 0, ")" );
121
122 break;
123
124 default:
125 FormatContents( out );
126 }
127}
128
129
131{
132 // output attributes first if they exist
133 for( wxXmlAttribute* attr = GetAttributes(); attr; attr = attr->GetNext() )
134 {
135 bool quote = true;
136
137 if( auto xa = dynamic_cast<XATTR*>( attr ) )
138 {
139 XATTR::VALUE_TYPE value = xa->GetValue();
140
141 std::visit( [&quote]<typename T0>( T0&& )
142 {
143 using T = std::decay_t<T0>;
144
145 if constexpr( std::is_same_v<T, int> || std::is_same_v<T, double> )
146 {
147 quote = false;
148 }
149 }, value );
150 }
151
152 out->Print( 0, " (%s %s)",
153 TO_UTF8( attr->GetName() ),
154 quote ? out->Quotew( attr->GetValue() ).c_str() : TO_UTF8( attr->GetValue() ) );
155 }
156
157 // we only expect to have used one of two types here:
158 switch( GetType() )
159 {
160 case wxXML_ELEMENT_NODE:
161 for( XNODE* child = GetChildren(); child; child = child->GetNext() )
162 {
163 if( child->GetType() != wxXML_TEXT_NODE )
164 {
165 if( child == GetChildren() )
166 out->Print( 0, "\n" );
167
168 child->Format( out );
169 }
170 else
171 {
172 child->Format( out );
173 }
174 }
175
176 break;
177
178 case wxXML_TEXT_NODE:
179 out->Print( 0, " %s", out->Quotew( GetContent() ).c_str() );
180 break;
181
182 default:
183 ; // not supported
184 }
185}
186
187
188wxString XNODE::Format() const
189{
190 STRING_FORMATTER formatter;
191 Format( &formatter );
193 return formatter.GetString();
194}
195
196// EOF
An interface used to output 8 bit text in a convenient way.
Definition richio.h:291
std::string Quotew(const wxString &aWrapee) const
Definition richio.cpp:507
int PRINTF_FUNC_N Print(int nestLevel, const char *fmt,...)
Format and write text to the output stream.
Definition richio.cpp:422
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:418
std::string & MutableString()
Definition richio.h:446
const std::string & GetString()
Definition richio.h:441
An extension of wxXmlAttribute that stores a variant type rather than just a string.
Definition xnode.h:46
std::variant< wxString, int, double > VALUE_TYPE
Definition xnode.h:48
VALUE_TYPE m_originalValue
Definition xnode.h:60
XATTR()
Definition xnode.h:50
wxString Format() const
Definition xnode.cpp:188
XNODE * GetChildren() const
Definition xnode.h:97
XNODE * GetNext() const
Definition xnode.h:102
XNODE()
Definition xnode.h:69
void FormatContents(OUTPUTFORMATTER *out) const
Write the contents of object as UTF8 out to an OUTPUTFORMATTER as an S-expression.
Definition xnode.cpp:130
void AddAttribute(const wxString &aName, const wxString &aValue) override
Definition xnode.cpp:88
void AddBool(const wxString &aKey, bool aValue)
Definition xnode.cpp:82
void Prettify(std::string &aSource, FORMAT_MODE aMode)
Pretty-prints s-expression text according to KiCad format rules.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.