OpenASIP 2.2
Loading...
Searching...
No Matches
Conversion.icc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file Conversion.icc
26 *
27 * Conversion static class contains functions for converting between
28 * different types, e.g. from any (possible) type to a string.
29 *
30 * Definitions of conversion template functions.
31 *
32 * @author Pekka Jääskeläinen 2003 (pjaaskel-no.spam-cs.tut.fi)
33 *
34 */
35
36#include <sstream>
37#include <cctype>
38#include <iostream>
39#include <iomanip>
40
41#include <xercesc/util/XMLString.hpp>
42
43/**
44 * Converts the parameter to a string.
45 *
46 * If source type is string, the first character sequence which does
47 * not contain white spaces is returned.
48 *
49 * @param source Object to convert.
50 * @return String representation of source.
51 */
52template <typename T>
53std::string
54Conversion::toString(const T& source) {
55 std::string result = "";
56 convert<T, std::string, false>(source, result);
57 return result;
58}
59
60/**
61 * Converts boolean to a string.
62 *
63 * @param source Boolean to convert.
64 * @return String representation of source.
65 */
66
67inline std::string
68Conversion::toString(bool source) {
69 if (source) {
70 return "1";
71 } else {
72 return "0";
73 }
74}
75
76/**
77 * Converts double to a string with custom precision.
78 *
79 * @param source Double to convert.
80 * @return String representation of source.
81 */
82inline std::string
83Conversion::toString(double source, unsigned precision) {
84 std::stringstream s;
85 s << std::setprecision(precision) << source;
86 return s.str();
87}
88
89/**
90 * Converts an XMLCh* to C++ string.
91 *
92 * @param ch XMLCh* to be converted.
93 * @return The string.
94 */
95inline
96std::string
97Conversion::XMLChToString(const XMLCh* ch) {
98 char* sz = XMLString::transcode(ch);
99 std::string ret = sz;
100 // TODO: xercesc version 3.1 wants delete, not delete[].
101 // xercesc version 2.8 wants delete[], not delete.
102 // not sure which was the actual version where this changed.
103#if _XERCES_VERSION < 30000
104 delete[] sz;
105#else
106 delete sz;
107#endif
108 return ret;
109}
110
111
112/**
113 * Converts a C++ string to an XMLCh*.
114 *
115 * The created XMLCh* must be deleted after use by calling the
116 * XMLString::release function.
117 *
118 * @param theString to be converted.
119 * @return The created XMLCh.
120 */
121inline
122XMLCh*
123Conversion::toXMLCh(const std::string& theString) {
124 return XMLString::transcode(theString.c_str());
125}
126
127/**
128 * Converts from one type to another.
129 *
130 * Allows spaces before and after the converted type (in case source is
131 * a string). Makes sure there's no garbage after the converted value.
132 *
133 * In addition, does not allow too large (greater than what the type
134 * can represent) or small (close to zero) values for numeric types.
135 *
136 * @param source Object to convert from.
137 * @param dest Destination object to convert to.
138 * @return Converted value.
139 * @exception NumberFormatException If source cannot be represented as target
140 * type.
141 *
142 */
143template <typename SourceType, typename DestType, bool destIsNumeric>
144void
145Conversion::convert(const SourceType& source, DestType& dest)
146 {
147
148 /// @todo: Figure out if the source type is larger than destination type
149 /// and throw. Conversion double -> float should be an error.
150 /// It could be handled with function template specializing, too bad
151 /// I couldn't get it working.
152
153 // stream used in removing the whitespace around the token
154 std::stringstream tempStream;
155 tempStream << source;
156
157 // remove leading whitespace from the string
158 std::string firstToken = "";
159 tempStream >> firstToken;
160
161 if (tempStream.fail()) {
162 throw NumberFormatException(
163 __FILE__, __LINE__, "convert()", "empty input");
164 }
165
166 if (!restWhiteSpace(tempStream)) {
167 throw NumberFormatException(
168 __FILE__, __LINE__, "convert()", "garbage at the end");
169 }
170
171 std::stringstream stream;
172 stream << firstToken;
173 firstToken = "";
174
175 if (destIsNumeric) {
176 // check that there is digit or negative sign at the beginning
177 if (!isdigit(stream.peek()) && stream.peek() != '-') {
178 throw NumberFormatException(
179 __FILE__, __LINE__, "convert()", "garbage at the beginning");
180 }
181 }
182
183 DestType destination;
184 stream >> destination;
185
186 if (stream.fail()) {
187 throw NumberFormatException(
188 __FILE__, __LINE__, "convert()", "illegal input format");
189 }
190
191 if (!restWhiteSpace(stream)) {
192 throw NumberFormatException(
193 __FILE__, __LINE__, "convert()", "garbage at the end");
194 }
195
196 dest = destination;
197}
198
199
200/**
201 * Converts the parameter to an int.
202 *
203 * Allows spaces before and after the number. Binary and hexadecimal
204 * formats are accepted as well. Binary format is indicated by
205 * extension 'b' and hexadecimal has '0x' in the beginning.
206 *
207 *
208 * @param source Object to convert.
209 * @return Int representation of source.
210 * @exception NumberFormatException If source cannot be represented as
211 * int including overflow.
212 */
213template <typename T>
214int
215Conversion::toInt(const T& source)
216 {
217
218 int theInt = 0;
219 try {
220 convert<T, int, true>(source, theInt);
221 } catch (const NumberFormatException& e) {
222
223 // check whether the source in an integer in hex or in binary format
224 std::stringstream hexStream;
225 hexStream << source;
226 std::string binary = toString(source);
227
228 char first = hexStream.get();
229 char second = hexStream.get();
230
231 if (first == '0' && second == 'x') {
232
233 // source is in hex format
234
235 // need to read into unsigned integer at first if the
236 // hexadecimal contains 8 characters, hence being larger
237 // than integer
238 unsigned int theUnsigned = 0;
239 hexStream >> std::hex >> theUnsigned;
240 theInt = static_cast<int>(theUnsigned);
241
242 if (!restWhiteSpace(hexStream)) {
243 throw NumberFormatException(
244 __FILE__, __LINE__, __func__,
245 "Unable to convert the argument to integer: illegal hex "\
246 "string.");
247 }
248 } else if (binary.length() > 1 &&
249 binary[binary.length() - 1] == 'b') {
250
251 // source is in binary format
252 if (binary.length() - 1 > sizeof(int) * 8) {
253 throw NumberFormatException(
254 __FILE__, __LINE__, __func__,
255 "Unable to convert the argument to integer: too long " \
256 "binary number.");
257 }
258
259 for (unsigned int i = 0; i < binary.length() - 1; i++) {
260 int bin = 2;
261 if (binary[i] == '0') {
262 bin = 0;
263 } else if (binary[i] == '1') {
264 bin = 1;
265 } else {
266 throw;
267 }
268
269 theInt = (theInt << 1) | bin;
270 }
271 } else {
272 throw NumberFormatException(
273 __FILE__, __LINE__, __func__,
274 "Unable to convert the argument to integer: " +
275 e.errorMessage() + ".");
276 }
277
278 }
279
280 return theInt;
281}
282
283/**
284 * Converts the parameter to a long int.
285 *
286 * Allows spaces before and after the number. Binary and hexadecimal
287 * formats are accepted as well. Binary format is indicated by
288 * extension 'b' and hexadecimal has '0x' in the beginning.
289 *
290 *
291 * @param source Object to convert.
292 * @return Int representation of source.
293 * @exception NumberFormatException If source cannot be represented as
294 * int including overflow.
295 */
296template <typename T>
297SLongWord
298Conversion::toLong(const T& source) {
299
300 SLongWord theLong = 0;
301 try {
302 convert<T, SLongWord, true>(source, theLong);
303 } catch (const NumberFormatException& e) {
304
305 // check whether the source in an integer in hex or in binary format
306 std::stringstream hexStream;
307 hexStream << source;
308 std::string binary = toString(source);
309
310 char first = hexStream.get();
311 char second = hexStream.get();
312
313 if (first == '0' && second == 'x') {
314
315 // source is in hex format
316
317 // need to read into unsigned integer at first if the
318 // hexadecimal contains 8 characters, hence being larger
319 // than integer
320 ULongWord theUnsigned = 0;
321 hexStream >> std::hex >> theUnsigned;
322 theLong = static_cast<SLongWord>(theUnsigned);
323
324 if (!restWhiteSpace(hexStream)) {
325 throw NumberFormatException(
326 __FILE__, __LINE__, __func__,
327 "Unable to convert the argument to integer: illegal hex "\
328 "string.");
329 }
330 } else if (binary.length() > 1 &&
331 binary[binary.length() - 1] == 'b') {
332
333 // source is in binary format
334 if (binary.length() - 1 > sizeof(SLongWord) * 8) {
335 throw NumberFormatException(
336 __FILE__, __LINE__, __func__,
337 "Unable to convert the argument to integer: too long " \
338 "binary number.");
339 }
340
341 for (unsigned int i = 0; i < binary.length() - 1; i++) {
342 SLongWord bin = 2;
343 if (binary[i] == '0') {
344 bin = 0;
345 } else if (binary[i] == '1') {
346 bin = 1;
347 } else {
348 throw;
349 }
350
351 theLong = (theLong << 1) | bin;
352 }
353 } else {
354 throw NumberFormatException(
355 __FILE__, __LINE__, __func__,
356 "Unable to convert the argument to integer: " +
357 e.errorMessage() + ".");
358 }
359
360 }
361
362 return theLong;
363}
364
365/**
366 * Converts a double to an int.
367 *
368 * @todo Check for overflow (how?).
369 *
370 * @param source Object to convert.
371 * @return Int representation of source.
372 * @exception NumberFormatException If source cannot be represented as
373 * int including overflow.
374 */
375inline int
376Conversion::toInt(const double& source)
377 {
378 return static_cast<int>(source);
379}
380
381/**
382 * Converts a double to an long.
383 *
384 * @todo Check for overflow (how?).
385 *
386 * @param source Object to convert.
387 * @return Int representation of source.
388 * @exception NumberFormatException If source cannot be represented as
389 * int including overflow.
390 */
391inline SLongWord
392Conversion::toLong(const double& source) {
393 return static_cast<SLongWord>(source);
394}
395
396
397/**
398 * Converts the parameter to an unsigned int.
399 *
400 * Allows spaces before and after the number. Binary and hexadecimal
401 * formats are accepted as well. Binary format is indicated by
402 * extension 'b' and hexadecimal has '0x' in the beginning.
403 *
404 *
405 * @param source Object to convert.
406 * @return Int representation of source.
407 * @exception NumberFormatException If source cannot be represented as
408 * int including overflow.
409 */
410template <typename T>
411unsigned int
412Conversion::toUnsignedInt(const T& source)
413 {
414
415 const std::string procName = "Conversion::toUnsignedInt";
416
417 unsigned int theUnsignedInt = 0;
418 try {
419 convert<T, unsigned int, true>(source, theUnsignedInt);
420 } catch (NumberFormatException&) {
421
422 // check whether the source in an integer in hex or in binary format
423 std::stringstream hexStream;
424 hexStream << source;
425 std::string binary = toString(source);
426
427 char first = hexStream.get();
428 char second = hexStream.get();
429
430 if (first == '0' && second == 'x') {
431
432 // source is in hex format
433 hexStream >> std::hex >> theUnsignedInt;
434
435 if (!restWhiteSpace(hexStream)) {
436 throw NumberFormatException(
437 __FILE__, __LINE__, procName, "garbage at the end");
438 }
439 } else if (binary.length() > 1 &&
440 binary[binary.length() - 1] == 'b') {
441
442 // source is in binary format
443 if (binary.length() - 1 > sizeof(unsigned int) * 8) {
444 throw NumberFormatException(
445 __FILE__, __LINE__, procName,
446 "too long binary to convert");
447 }
448
449 for (unsigned int i = 0; i < binary.length() - 1; i++) {
450 int bin = 2;
451 if (binary[i] == '0') {
452 bin = 0;
453 } else if (binary[i] == '1') {
454 bin = 1;
455 } else {
456 throw;
457 }
458
459 theUnsignedInt = (theUnsignedInt << 1) | bin;
460 }
461 } else {
462 throw;
463 }
464
465 }
466
467 // check if the source is signed
468 std::stringstream tempStream;
469 tempStream << source;
470 std::string firstToken = "";
471 tempStream >> firstToken;
472 if (firstToken[0] == '-') {
473 throw NumberFormatException(
474 __FILE__, __LINE__, procName, "signed input value");
475 }
476
477 return theUnsignedInt;
478}
479
480
481
482/**
483 * Converts the parameter to an unsigned int.
484 *
485 * Allows spaces before and after the number. Binary and hexadecimal
486 * formats are accepted as well. Binary format is indicated by
487 * extension 'b' and hexadecimal has '0x' in the beginning.
488 *
489 *
490 * @param source Object to convert.
491 * @return Int representation of source.
492 * @exception NumberFormatException If source cannot be represented as
493 * int including overflow.
494 */
495template <typename T>
496ULongWord
497Conversion::toUnsignedLong(const T& source) {
498
499 ULongWord theUnsignedLong = 0;
500 try {
501 convert<T, ULongWord, true>(source, theUnsignedLong);
502 } catch (NumberFormatException&) {
503
504 // check whether the source in an integer in hex or in binary format
505 std::stringstream hexStream;
506 hexStream << source;
507 std::string binary = toString(source);
508
509 char first = hexStream.get();
510 char second = hexStream.get();
511
512 if (first == '0' && second == 'x') {
513
514 // source is in hex format
515 hexStream >> std::hex >> theUnsignedLong;
516
517 if (!restWhiteSpace(hexStream)) {
518 throw NumberFormatException(
519 __FILE__, __LINE__, __func__, "garbage at the end");
520 }
521 } else if (binary.length() > 1 &&
522 binary[binary.length() - 1] == 'b') {
523
524 // source is in binary format
525 if (binary.length() - 1 > sizeof(ULongWord) * 8) {
526 throw NumberFormatException(
527 __FILE__, __LINE__, __func__,
528 "too long binary to convert");
529 }
530
531 for (unsigned int i = 0; i < binary.length() - 1; i++) {
532 SLongWord bin = 2;
533 if (binary[i] == '0') {
534 bin = 0;
535 } else if (binary[i] == '1') {
536 bin = 1;
537 } else {
538 throw;
539 }
540
541 theUnsignedLong = (theUnsignedLong << 1) | bin;
542 }
543 } else {
544 throw;
545 }
546
547 }
548
549 // check if the source is signed
550 std::stringstream tempStream;
551 tempStream << source;
552 std::string firstToken = "";
553 tempStream >> firstToken;
554 if (firstToken[0] == '-') {
555 throw NumberFormatException(
556 __FILE__, __LINE__, __func__, "signed input value");
557 }
558
559 return theUnsignedLong;
560}
561
562
563
564/**
565 * Converts the parameter to a double.
566 *
567 * Allows spaces before and after the number.
568 *
569 * @param source Object to convert.
570 * @return Double representation of source.
571 * @exception NumberFormatException If source cannot be represented as
572 * double including overflow.
573 */
574template <typename T>
575double
576Conversion::toDouble(const T& source)
577 {
578
579 double theDouble = 0.0;
580 convert<T, double, true>(source, theDouble);
581
582 return theDouble;
583}
584
585/**
586 * Converts the parameter to a float.
587 *
588 * Allows spaces before and after the number.
589 *
590 * @param source Object to convert.
591 * @return Double representation of source.
592 * @exception NumberFormatException If source cannot be represented as
593 * float including overflow.
594 */
595template <typename T>
596float
597Conversion::toFloat(const T& source)
598 {
599
600 float theFloat = 0.0;
601 convert<T, float, true>(source, theFloat);
602
603 return theFloat;
604}
605
606/**
607 * Converts an source to the string which is in hexadecimal format.
608 *
609 * Hexadecimal format contains lower case characters and includes '0x'
610 * literal at the beginning of the string by default.
611 *
612 * @param source An source to be converted into a hexadecimal string.
613 * @param digits Number of digits to display (default is no leading zeroes).
614 * @param include0x If true prepend '0x'.
615 * @return Returns the binary string.
616 */
617template <typename T>
618std::string
619Conversion::toHexString(T source, std::size_t digits, bool include0x) {
620
621 std::stringstream str;
622 str << std::setw(digits) << std::setfill('0') << std::right << std::hex
623 << source;
624
625 std::string result = "";
626 str >> result;
627
628 if (include0x) {
629 result.insert(0, "0x");
630 }
631
632 return result;
633}
634
635
636
637