KiCad PCB EDA Suite
Loading...
Searching...
No Matches
idf_helpers.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) 2014-2017 Cirilo Bernardo
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 <cctype>
22#include <iostream>
23#include <sstream>
24
25#include <io/idf/idf_common.h>
26#include <io/idf/idf_helpers.h>
27
28using namespace std;
29using namespace IDF3;
30
31
32bool IDF3::FetchIDFLine( std::istream& aModel, std::string& aLine, bool& isComment,
33 std::streampos& aFilePos )
34{
35 aLine = "";
36 aFilePos = aModel.tellg();
37
38 if( aModel.fail() )
39 return false;
40
41 std::getline( aModel, aLine );
42
43 isComment = false;
44
45 // A comment begins with a '#' and must be the first character on the line
46 if( aLine[0] == '#' )
47 {
48 // opening '#' is stripped
49 isComment = true;
50 aLine.erase( aLine.begin() );
51 }
52
53 // strip leading and trailing spaces
54 while( !aLine.empty() && isspace( *aLine.begin() ) )
55 aLine.erase( aLine.begin() );
56
57 while( !aLine.empty() && isspace( *aLine.rbegin() ) )
58 aLine.erase( --aLine.end() );
59
60 // a comment line may be empty to improve human readability
61 if( aLine.empty() && !isComment )
62 return false;
63
64 return true;
65}
66
67
68bool IDF3::GetIDFString( const std::string& aLine, std::string& aIDFString, bool& hasQuotes,
69 int& aIndex )
70{
71 // 1. drop all leading spaces
72 // 2. if the first character is '"', read until the next '"',
73 // otherwise read until the next space or EOL.
74
75 std::ostringstream ostr;
76
77 int len = aLine.length();
78 int idx = aIndex;
79
80 if( idx < 0 || idx >= len )
81 return false;
82
83 while( idx < len && isspace( aLine[idx] ) )
84 ++idx;
85
86 if( idx == len )
87 {
88 aIndex = idx;
89 return false;
90 }
91
92 if( aLine[idx] == '"' )
93 {
94 hasQuotes = true;
95 ++idx;
96
97 while( idx < len && aLine[idx] != '"' )
98 ostr << aLine[idx++];
99
100 if( idx == len )
101 {
102 ERROR_IDF << "unterminated quote mark in line:\n";
103 aIndex = idx;
104 return false;
105 }
106
107 ++idx;
108 }
109 else
110 {
111 hasQuotes = false;
112
113 while( idx < len && !isspace( aLine[idx] ) )
114 ostr << aLine[idx++];
115
116 }
117
118 aIDFString = ostr.str();
119 aIndex = idx;
120
121 return true;
122}
123
124
125// perform a comparison between a fixed token string and an input string.
126// the token is assumed to be an upper case IDF token and the input string
127// is data from an IDF file. Since IDF tokens are case-insensitive, we cannot
128// assume anything about the case of the input string.
129bool IDF3::CompareToken( const char* aTokenString, const std::string& aInputString )
130{
131 std::string::size_type i, j;
132 std::string bigToken = aInputString;
133 j = aInputString.length();
134
135 for( i = 0; i < j; ++i )
136 bigToken[i] = std::toupper( bigToken[i] );
137
138 if( !bigToken.compare( aTokenString ) )
139 return true;
140
141 return false;
142}
143
144
145bool IDF3::ParseOwner( const std::string& aToken, IDF3::KEY_OWNER& aOwner )
146{
147 if( CompareToken( "UNOWNED", aToken ) )
148 {
149 aOwner = KEY_OWNER::UNOWNED;
150 return true;
151 }
152 else if( CompareToken( "ECAD", aToken ) )
153 {
154 aOwner = KEY_OWNER::ECAD;
155 return true;
156 }
157 else if( CompareToken( "MCAD", aToken ) )
158 {
159 aOwner = KEY_OWNER::MCAD;
160 return true;
161 }
162
163 ERROR_IDF << "unrecognized IDF OWNER: '" << aToken << "'\n";
164
165 return false;
166}
167
168
169bool IDF3::ParseIDFLayer( const std::string& aToken, IDF3::IDF_LAYER& aLayer )
170{
171 if( CompareToken( "TOP", aToken ) )
172 {
173 aLayer = IDF_LAYER::LYR_TOP;
174 return true;
175 }
176 else if( CompareToken( "BOTTOM", aToken ) )
177 {
178 aLayer = IDF_LAYER::LYR_BOTTOM;
179 return true;
180 }
181 else if( CompareToken( "BOTH", aToken ) )
182 {
183 aLayer = IDF_LAYER::LYR_BOTH;
184 return true;
185 }
186 else if( CompareToken( "INNER", aToken ) )
187 {
188 aLayer = IDF_LAYER::LYR_INNER;
189 return true;
190 }
191 else if( CompareToken( "ALL", aToken ) )
192 {
193 aLayer = IDF_LAYER::LYR_ALL;
194 return true;
195 }
196
197 ERROR_IDF << "unrecognized IDF LAYER: '" << aToken << "'\n";
198
199 aLayer = IDF_LAYER::LYR_INVALID;
200 return false;
201}
202
203
204bool IDF3::WriteLayersText( std::ostream& aBoardFile, IDF3::IDF_LAYER aLayer )
205{
206 switch( aLayer )
207 {
209 aBoardFile << "TOP";
210 break;
211
213 aBoardFile << "BOTTOM";
214 break;
215
217 aBoardFile << "BOTH";
218 break;
219
221 aBoardFile << "INNER";
222 break;
223
225 aBoardFile << "ALL";
226 break;
227
228 default:
229 do
230 {
231 std::ostringstream ostr;
232 ostr << "invalid IDF layer: " << static_cast<int>( aLayer );
233
234 throw( IDF_ERROR( __FILE__, __FUNCTION__, __LINE__, ostr.str() ) );
235 } while( 0 );
236
237 break;
238 }
239
240 return !aBoardFile.fail();
241}
242
243
245{
246 switch( aPlacement )
247 {
249 return "UNPLACED";
250
252 return "PLACED";
253
255 return "MCAD";
256
258 return "ECAD";
259
260 default:
261 break;
262 }
263
264 std::ostringstream ostr;
265 ostr << "[INVALID PLACEMENT VALUE]:" << static_cast<int>( aPlacement );
266
267 return ostr.str();
268}
269
270
272{
273 switch( aLayer )
274 {
276 return "TOP";
277
279 return "BOTTOM";
280
282 return "BOTH";
283
285 return "INNER";
286
288 return "ALL";
289
290 default:
291 break;
292 }
293
294 std::ostringstream ostr;
295 ostr << "[INVALID LAYER VALUE]:" << static_cast<int>( aLayer );
296
297 return ostr.str();
298}
299
300
302{
303 switch( aOwner )
304 {
306 return "UNOWNED";
307
308 case KEY_OWNER::MCAD:
309 return "MCAD";
310
311 case KEY_OWNER::ECAD:
312 return "ECAD";
313
314 default:
315 break;
316 }
317
318 ostringstream ostr;
319 ostr << "UNKNOWN: " << static_cast<int>( aOwner );
320
321 return ostr.str();
322}
#define ERROR_IDF
Definition idf_helpers.h:55
std::string GetPlacementString(IDF3::IDF_PLACEMENT aPlacement)
Return a string representing the given IDF Placement type.
bool ParseIDFLayer(const std::string &aToken, IDF3::IDF_LAYER &aLayer)
Parse an input string for a valid IDF layer specification.
IDF_PLACEMENT
The placement status of a component.
Definition idf_common.h:188
bool GetIDFString(const std::string &aLine, std::string &aIDFString, bool &hasQuotes, int &aIndex)
Parse a line retrieved via FetchIDFLine() and returns the first IDF string found from the starting po...
std::string GetOwnerString(IDF3::KEY_OWNER aOwner)
bool FetchIDFLine(std::istream &aModel, std::string &aLine, bool &isComment, std::streampos &aFilePos)
Retrieve a single line from an IDF file and performs minimal processing.
bool CompareToken(const char *aTokenString, const std::string &aInputString)
Perform a case-insensitive comparison of a token string and an input string.
IDF_LAYER
The various IDF layer classes and groupings.
Definition idf_common.h:137
KEY_OWNER
The type of CAD which has ownership an object.
Definition idf_common.h:85
bool WriteLayersText(std::ostream &aBoardFile, IDF3::IDF_LAYER aLayer)
Write out text corresponding to the given IDF Layer type.
bool ParseOwner(const std::string &aToken, IDF3::KEY_OWNER &aOwner)
Parse the input string for a valid IDF Owner type.
std::string GetLayerString(IDF3::IDF_LAYER aLayer)
Return a string representing the given IDF Layer type.
STL namespace.