OpenASIP  2.0
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  */
52 template <typename T>
53 std::string
54 Conversion::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 
67 inline std::string
68 Conversion::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  */
82 inline std::string
83 Conversion::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  */
95 inline
96 std::string
97 Conversion::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  */
121 inline
122 XMLCh*
123 Conversion::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  */
143 template <typename SourceType, typename DestType, bool destIsNumeric>
144 void
145 Conversion::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  */
213 template <typename T>
214 int
215 Conversion::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  */
296 template <typename T>
297 SLongWord
298 Conversion::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  */
375 inline int
376 Conversion::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  */
391 inline SLongWord
392 Conversion::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  */
410 template <typename T>
411 unsigned int
412 Conversion::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  */
495 template <typename T>
496 ULongWord
497 Conversion::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  */
574 template <typename T>
575 double
576 Conversion::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  */
595 template <typename T>
596 float
597 Conversion::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  */
617 template <typename T>
618 std::string
619 Conversion::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