2 Copyright (c) 2002-2009 Tampere University.
4 This file is part of TTA-Based Codesign Environment (TCE).
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:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
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.
25 * @file Conversion.icc
27 * Conversion static class contains functions for converting between
28 * different types, e.g. from any (possible) type to a string.
30 * Definitions of conversion template functions.
32 * @author Pekka Jääskeläinen 2003 (pjaaskel-no.spam-cs.tut.fi)
41 #include <xercesc/util/XMLString.hpp>
44 * Converts the parameter to a string.
46 * If source type is string, the first character sequence which does
47 * not contain white spaces is returned.
49 * @param source Object to convert.
50 * @return String representation of source.
54 Conversion::toString(const T& source) {
55 std::string result = "";
56 convert<T, std::string, false>(source, result);
61 * Converts boolean to a string.
63 * @param source Boolean to convert.
64 * @return String representation of source.
68 Conversion::toString(bool source) {
77 * Converts double to a string with custom precision.
79 * @param source Double to convert.
80 * @return String representation of source.
83 Conversion::toString(double source, unsigned precision) {
85 s << std::setprecision(precision) << source;
90 * Converts an XMLCh* to C++ string.
92 * @param ch XMLCh* to be converted.
97 Conversion::XMLChToString(const XMLCh* ch) {
98 char* sz = XMLString::transcode(ch);
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
113 * Converts a C++ string to an XMLCh*.
115 * The created XMLCh* must be deleted after use by calling the
116 * XMLString::release function.
118 * @param theString to be converted.
119 * @return The created XMLCh.
123 Conversion::toXMLCh(const std::string& theString) {
124 return XMLString::transcode(theString.c_str());
128 * Converts from one type to another.
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.
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.
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
143 template <typename SourceType, typename DestType, bool destIsNumeric>
145 Conversion::convert(const SourceType& source, DestType& dest)
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.
153 // stream used in removing the whitespace around the token
154 std::stringstream tempStream;
155 tempStream << source;
157 // remove leading whitespace from the string
158 std::string firstToken = "";
159 tempStream >> firstToken;
161 if (tempStream.fail()) {
162 throw NumberFormatException(
163 __FILE__, __LINE__, "convert()", "empty input");
166 if (!restWhiteSpace(tempStream)) {
167 throw NumberFormatException(
168 __FILE__, __LINE__, "convert()", "garbage at the end");
171 std::stringstream stream;
172 stream << firstToken;
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");
183 DestType destination;
184 stream >> destination;
187 throw NumberFormatException(
188 __FILE__, __LINE__, "convert()", "illegal input format");
191 if (!restWhiteSpace(stream)) {
192 throw NumberFormatException(
193 __FILE__, __LINE__, "convert()", "garbage at the end");
201 * Converts the parameter to an int.
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.
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.
213 template <typename T>
215 Conversion::toInt(const T& source)
220 convert<T, int, true>(source, theInt);
221 } catch (const NumberFormatException& e) {
223 // check whether the source in an integer in hex or in binary format
224 std::stringstream hexStream;
226 std::string binary = toString(source);
228 char first = hexStream.get();
229 char second = hexStream.get();
231 if (first == '0' && second == 'x') {
233 // source is in hex format
235 // need to read into unsigned integer at first if the
236 // hexadecimal contains 8 characters, hence being larger
238 unsigned int theUnsigned = 0;
239 hexStream >> std::hex >> theUnsigned;
240 theInt = static_cast<int>(theUnsigned);
242 if (!restWhiteSpace(hexStream)) {
243 throw NumberFormatException(
244 __FILE__, __LINE__, __func__,
245 "Unable to convert the argument to integer: illegal hex "\
248 } else if (binary.length() > 1 &&
249 binary[binary.length() - 1] == 'b') {
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 " \
259 for (unsigned int i = 0; i < binary.length() - 1; i++) {
261 if (binary[i] == '0') {
263 } else if (binary[i] == '1') {
269 theInt = (theInt << 1) | bin;
272 throw NumberFormatException(
273 __FILE__, __LINE__, __func__,
274 "Unable to convert the argument to integer: " +
275 e.errorMessage() + ".");
284 * Converts the parameter to a long int.
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.
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.
296 template <typename T>
298 Conversion::toLong(const T& source) {
300 SLongWord theLong = 0;
302 convert<T, SLongWord, true>(source, theLong);
303 } catch (const NumberFormatException& e) {
305 // check whether the source in an integer in hex or in binary format
306 std::stringstream hexStream;
308 std::string binary = toString(source);
310 char first = hexStream.get();
311 char second = hexStream.get();
313 if (first == '0' && second == 'x') {
315 // source is in hex format
317 // need to read into unsigned integer at first if the
318 // hexadecimal contains 8 characters, hence being larger
320 ULongWord theUnsigned = 0;
321 hexStream >> std::hex >> theUnsigned;
322 theLong = static_cast<SLongWord>(theUnsigned);
324 if (!restWhiteSpace(hexStream)) {
325 throw NumberFormatException(
326 __FILE__, __LINE__, __func__,
327 "Unable to convert the argument to integer: illegal hex "\
330 } else if (binary.length() > 1 &&
331 binary[binary.length() - 1] == 'b') {
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 " \
341 for (unsigned int i = 0; i < binary.length() - 1; i++) {
343 if (binary[i] == '0') {
345 } else if (binary[i] == '1') {
351 theLong = (theLong << 1) | bin;
354 throw NumberFormatException(
355 __FILE__, __LINE__, __func__,
356 "Unable to convert the argument to integer: " +
357 e.errorMessage() + ".");
366 * Converts a double to an int.
368 * @todo Check for overflow (how?).
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.
376 Conversion::toInt(const double& source)
378 return static_cast<int>(source);
382 * Converts a double to an long.
384 * @todo Check for overflow (how?).
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.
392 Conversion::toLong(const double& source) {
393 return static_cast<SLongWord>(source);
398 * Converts the parameter to an unsigned int.
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.
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.
410 template <typename T>
412 Conversion::toUnsignedInt(const T& source)
415 const std::string procName = "Conversion::toUnsignedInt";
417 unsigned int theUnsignedInt = 0;
419 convert<T, unsigned int, true>(source, theUnsignedInt);
420 } catch (NumberFormatException&) {
422 // check whether the source in an integer in hex or in binary format
423 std::stringstream hexStream;
425 std::string binary = toString(source);
427 char first = hexStream.get();
428 char second = hexStream.get();
430 if (first == '0' && second == 'x') {
432 // source is in hex format
433 hexStream >> std::hex >> theUnsignedInt;
435 if (!restWhiteSpace(hexStream)) {
436 throw NumberFormatException(
437 __FILE__, __LINE__, procName, "garbage at the end");
439 } else if (binary.length() > 1 &&
440 binary[binary.length() - 1] == 'b') {
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");
449 for (unsigned int i = 0; i < binary.length() - 1; i++) {
451 if (binary[i] == '0') {
453 } else if (binary[i] == '1') {
459 theUnsignedInt = (theUnsignedInt << 1) | bin;
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");
477 return theUnsignedInt;
483 * Converts the parameter to an unsigned int.
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.
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.
495 template <typename T>
497 Conversion::toUnsignedLong(const T& source) {
499 ULongWord theUnsignedLong = 0;
501 convert<T, ULongWord, true>(source, theUnsignedLong);
502 } catch (NumberFormatException&) {
504 // check whether the source in an integer in hex or in binary format
505 std::stringstream hexStream;
507 std::string binary = toString(source);
509 char first = hexStream.get();
510 char second = hexStream.get();
512 if (first == '0' && second == 'x') {
514 // source is in hex format
515 hexStream >> std::hex >> theUnsignedLong;
517 if (!restWhiteSpace(hexStream)) {
518 throw NumberFormatException(
519 __FILE__, __LINE__, __func__, "garbage at the end");
521 } else if (binary.length() > 1 &&
522 binary[binary.length() - 1] == 'b') {
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");
531 for (unsigned int i = 0; i < binary.length() - 1; i++) {
533 if (binary[i] == '0') {
535 } else if (binary[i] == '1') {
541 theUnsignedLong = (theUnsignedLong << 1) | bin;
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");
559 return theUnsignedLong;
565 * Converts the parameter to a double.
567 * Allows spaces before and after the number.
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.
574 template <typename T>
576 Conversion::toDouble(const T& source)
579 double theDouble = 0.0;
580 convert<T, double, true>(source, theDouble);
586 * Converts the parameter to a float.
588 * Allows spaces before and after the number.
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.
595 template <typename T>
597 Conversion::toFloat(const T& source)
600 float theFloat = 0.0;
601 convert<T, float, true>(source, theFloat);
607 * Converts an source to the string which is in hexadecimal format.
609 * Hexadecimal format contains lower case characters and includes '0x'
610 * literal at the beginning of the string by default.
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.
617 template <typename T>
619 Conversion::toHexString(T source, std::size_t digits, bool include0x) {
621 std::stringstream str;
622 str << std::setw(digits) << std::setfill('0') << std::right << std::hex
625 std::string result = "";
629 result.insert(0, "0x");