]> Dogcows Code - chaz/yoink/blobdiff - src/stlplus/strings/string_int.cpp
cleanup stlplus files
[chaz/yoink] / src / stlplus / strings / string_int.cpp
index 178cf4c86f37e20b581cfd9de6db0d1d92dad148..ec5e10c93f8811d53830da2b7c9d5dcd39b67d21 100644 (file)
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-//   Author:    Andy Rushton\r
-//   Copyright: (c) Southampton University 1999-2004\r
-//              (c) Andy Rushton           2004-2009\r
-//   License:   BSD License, see ../docs/license.html\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#include "string_int.hpp"\r
-#include <ctype.h>\r
-#include <stdlib.h>\r
-\r
-namespace stlplus\r
-{\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-  // character mappings\r
-\r
-  static char to_char [] = "0123456789abcdefghijklmnopqrstuvwxyz";\r
-  static int from_char [] = \r
-  {\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,\r
-    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\r
-    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\r
-    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\r
-    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\r
-  };\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-  // Conversions to string\r
-  // Local generic routines\r
-\r
-  // signed version of the generic image generation function for all integer types\r
-  template<typename T>\r
-  static std::string simage (T i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    if (radix < 2 || radix > 36)\r
-      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));\r
-    // untangle all the options\r
-    bool hashed = false;\r
-    bool binary = false;\r
-    bool octal = false;\r
-    bool hex = false;\r
-    switch(display)\r
-    {\r
-    case radix_none:\r
-      break;\r
-    case radix_hash_style:\r
-      hashed = radix != 10;\r
-      break;\r
-    case radix_hash_style_all:\r
-      hashed = true;\r
-      break;\r
-    case radix_c_style:\r
-      if (radix == 16)\r
-        hex = true;\r
-      else if (radix == 8)\r
-        octal = true;\r
-      else if (radix == 2)\r
-        binary = true;\r
-      break;\r
-    case radix_c_style_or_hash:\r
-      if (radix == 16)\r
-        hex = true;\r
-      else if (radix == 8)\r
-        octal = true;\r
-      else if (radix == 2)\r
-        binary = true;\r
-      else if (radix != 10)\r
-        hashed = true;\r
-      break;\r
-    default:\r
-      throw std::invalid_argument("invalid radix display value");\r
-    }\r
-    // create constants of the same type as the template parameter to avoid type mismatches\r
-    const T t_zero(0);\r
-    const T t_radix(radix);\r
-    // the C representations for binary, octal and hex use 2's-complement representation\r
-    // all other represenations use sign-magnitude\r
-    std::string result;\r
-    if (hex || octal || binary)\r
-    {\r
-      // bit-pattern representation\r
-      // this is the binary representation optionally shown in octal or hex\r
-      // first generate the binary by masking the bits\r
-      // ensure that it has at least one bit!\r
-      for (T mask(1); ; mask <<= 1)\r
-      {\r
-        result.insert((std::string::size_type)0, 1, i & mask ? '1' : '0');\r
-        if (mask == t_zero) break;\r
-      }\r
-      // the result is now the full width of the type - e.g. int will give a 32-bit result\r
-      // now interpret this as either binary, octal or hex and add the prefix\r
-      if (binary)\r
-      {\r
-        // the result is already binary - but the width may be wrong\r
-        // if this is still smaller than the width field, sign extend\r
-        // otherwise trim down to either the width or the smallest string that preserves the value\r
-        while (result.size() < width)\r
-          result.insert((std::string::size_type)0, 1, result[0]);\r
-        while (result.size() > width)\r
-        {\r
-          // do not trim to less than 2 bits (sign plus 1-bit magnitude)\r
-          if (result.size() <= 2) break;\r
-          // only trim if it doesn't change the sign and therefore the value\r
-          if (result[0] != result[1]) break;\r
-          result.erase(0,1);\r
-        }\r
-        // add the prefix\r
-        result.insert((std::string::size_type)0, "0b");\r
-      }\r
-      else if (octal)\r
-      {\r
-        // the result is currently binary - but before converting get the width right\r
-        // the width is expressed in octal digits so make the binary 3 times this\r
-        // if this is still smaller than the width field, sign extend\r
-        // otherwise trim down to either the width or the smallest string that preserves the value\r
-        // also ensure that the binary is a multiple of 3 bits to make the conversion to octal easier\r
-        while (result.size() < 3*width)\r
-          result.insert((std::string::size_type)0, 1, result[0]);\r
-        while (result.size() > 3*width)\r
-        {\r
-          // do not trim to less than 2 bits (sign plus 1-bit magnitude)\r
-          if (result.size() <= 2) break;\r
-          // only trim if it doesn't change the sign and therefore the value\r
-          if (result[0] != result[1]) break;\r
-          result.erase(0,1);\r
-        }\r
-        while (result.size() % 3 != 0)\r
-          result.insert((std::string::size_type)0, 1, result[0]);\r
-        // now convert to octal\r
-        std::string octal_result;\r
-        for (unsigned i = 0; i < result.size()/3; i++)\r
-        {\r
-          // yuck - ugly or what?\r
-          if (result[i*3] == '0')\r
-          {\r
-            if (result[i*3+1] == '0')\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '0';\r
-              else\r
-                octal_result += '1';\r
-            }\r
-            else\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '2';\r
-              else\r
-                octal_result += '3';\r
-            }\r
-          }\r
-          else\r
-          {\r
-            if (result[i*3+1] == '0')\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '4';\r
-              else\r
-                octal_result += '5';\r
-            }\r
-            else\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '6';\r
-              else\r
-                octal_result += '7';\r
-            }\r
-          }\r
-        }\r
-        result = octal_result;\r
-        // add the prefix\r
-        result.insert((std::string::size_type)0, "0");\r
-      }\r
-      else\r
-      {\r
-        // hex - similar to octal\r
-        while (result.size() < 4*width)\r
-          result.insert((std::string::size_type)0, 1, result[0]);\r
-        while (result.size() > 4*width)\r
-        {\r
-          // do not trim to less than 2 bits (sign plus 1-bit magnitude)\r
-          if (result.size() <= 2) break;\r
-          // only trim if it doesn't change the sign and therefore the value\r
-          if (result[0] != result[1]) break;\r
-          result.erase(0,1);\r
-        }\r
-        while (result.size() % 4 != 0)\r
-          result.insert((std::string::size_type)0, 1, result[0]);\r
-        // now convert to hex\r
-        std::string hex_result;\r
-        for (unsigned i = 0; i < result.size()/4; i++)\r
-        {\r
-          // yuck - ugly or what?\r
-          if (result[i*4] == '0')\r
-          {\r
-            if (result[i*4+1] == '0')\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '0';\r
-                else\r
-                  hex_result += '1';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '2';\r
-                else\r
-                  hex_result += '3';\r
-              }\r
-            }\r
-            else\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '4';\r
-                else\r
-                  hex_result += '5';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '6';\r
-                else\r
-                  hex_result += '7';\r
-              }\r
-            }\r
-          }\r
-          else\r
-          {\r
-            if (result[i*4+1] == '0')\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '8';\r
-                else\r
-                  hex_result += '9';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += 'a';\r
-                else\r
-                  hex_result += 'b';\r
-              }\r
-            }\r
-            else\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += 'c';\r
-                else\r
-                  hex_result += 'd';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += 'e';\r
-                else\r
-                  hex_result += 'f';\r
-              }\r
-            }\r
-          }\r
-        }\r
-        result = hex_result;\r
-        // add the prefix\r
-        result.insert((std::string::size_type)0, "0x");\r
-      }\r
-    }\r
-    else\r
-    {\r
-      // convert to sign-magnitude\r
-      // the representation is:\r
-      // [radix#][sign]magnitude\r
-      bool negative = i < t_zero;\r
-      // create a representation of the magnitude by successive division\r
-      do\r
-      {\r
-        T ch = abs(i % t_radix);\r
-        i /= t_radix;\r
-        result.insert((std::string::size_type)0, 1, to_char[ch]);\r
-      }\r
-      while(i != t_zero || result.size() < width);\r
-      // add the prefixes\r
-      // add a sign only for negative values\r
-      if (negative)\r
-        result.insert((std::string::size_type)0, 1, '-');\r
-      // then prefix everything with the radix if the hashed representation was requested\r
-      if (hashed)\r
-        result.insert((std::string::size_type)0, unsigned_to_string(radix) + "#");\r
-    }\r
-    return result;\r
-  }\r
-\r
-  // unsigned version\r
-  template<typename T>\r
-  static std::string uimage (T i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    if (radix < 2 || radix > 36)\r
-      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));\r
-    // untangle all the options\r
-    bool hashed = false;\r
-    bool binary = false;\r
-    bool octal = false;\r
-    bool hex = false;\r
-    switch(display)\r
-    {\r
-    case radix_none:\r
-      break;\r
-    case radix_hash_style:\r
-      hashed = radix != 10;\r
-      break;\r
-    case radix_hash_style_all:\r
-      hashed = true;\r
-      break;\r
-    case radix_c_style:\r
-      if (radix == 16)\r
-        hex = true;\r
-      else if (radix == 8)\r
-        octal = true;\r
-      else if (radix == 2)\r
-        binary = true;\r
-      break;\r
-    case radix_c_style_or_hash:\r
-      if (radix == 16)\r
-        hex = true;\r
-      else if (radix == 8)\r
-        octal = true;\r
-      else if (radix == 2)\r
-        binary = true;\r
-      else if (radix != 10)\r
-        hashed = true;\r
-      break;\r
-    default:\r
-      throw std::invalid_argument("invalid radix display value");\r
-    }\r
-    // create constants of the same type as the template parameter to avoid type mismatches\r
-    const T t_zero(0);\r
-    const T t_radix(radix);\r
-    // the C representations for binary, octal and hex use 2's-complement representation\r
-    // all other represenations use sign-magnitude\r
-    std::string result;\r
-    if (hex || octal || binary)\r
-    {\r
-      // bit-pattern representation\r
-      // this is the binary representation optionally shown in octal or hex\r
-      // first generate the binary by masking the bits\r
-      // ensure at least one bit\r
-      for (T mask(1); ; mask <<= 1)\r
-      {\r
-        result.insert((std::string::size_type)0, 1, i & mask ? '1' : '0');\r
-        if (mask == t_zero) break;\r
-      }\r
-      // the result is now the full width of the type - e.g. int will give a 32-bit result\r
-      // now interpret this as either binary, octal or hex and add the prefix\r
-      if (binary)\r
-      {\r
-        // the result is already binary - but the width may be wrong\r
-        // if this is still smaller than the width field, zero extend\r
-        // otherwise trim down to either the width or the smallest string that preserves the value\r
-        while (result.size() < width)\r
-          result.insert((std::string::size_type)0, 1, '0');\r
-        while (result.size() > width)\r
-        {\r
-          // do not trim to less than 1 bit (1-bit magnitude)\r
-          if (result.size() <= 1) break;\r
-          // only trim if it doesn't change the sign and therefore the value\r
-          if (result[0] != '0') break;\r
-          result.erase(0,1);\r
-        }\r
-        // add the prefix\r
-        result.insert((std::string::size_type)0, "0b");\r
-      }\r
-      else if (octal)\r
-      {\r
-        // the result is currently binary - but before converting get the width right\r
-        // the width is expressed in octal digits so make the binary 3 times this\r
-        // if this is still smaller than the width field, sign extend\r
-        // otherwise trim down to either the width or the smallest string that preserves the value\r
-        // also ensure that the binary is a multiple of 3 bits to make the conversion to octal easier\r
-        while (result.size() < 3*width)\r
-          result.insert((std::string::size_type)0, 1, '0');\r
-        while (result.size() > 3*width)\r
-        {\r
-          // do not trim to less than 1 bit (1-bit magnitude)\r
-          if (result.size() <= 1) break;\r
-          // only trim if it doesn't change the sign and therefore the value\r
-          if (result[0] != '0') break;\r
-          result.erase(0,1);\r
-        }\r
-        while (result.size() % 3 != 0)\r
-          result.insert((std::string::size_type)0, 1, '0');\r
-        // now convert to octal\r
-        std::string octal_result;\r
-        for (unsigned i = 0; i < result.size()/3; i++)\r
-        {\r
-          // yuck - ugly or what?\r
-          if (result[i*3] == '0')\r
-          {\r
-            if (result[i*3+1] == '0')\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '0';\r
-              else\r
-                octal_result += '1';\r
-            }\r
-            else\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '2';\r
-              else\r
-                octal_result += '3';\r
-            }\r
-          }\r
-          else\r
-          {\r
-            if (result[i*3+1] == '0')\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '4';\r
-              else\r
-                octal_result += '5';\r
-            }\r
-            else\r
-            {\r
-              if (result[i*3+2] == '0')\r
-                octal_result += '6';\r
-              else\r
-                octal_result += '7';\r
-            }\r
-          }\r
-        }\r
-        result = octal_result;\r
-        // add the prefix if the leading digit is not already 0\r
-        if (result.empty() || result[0] != '0') result.insert((std::string::size_type)0, "0");\r
-      }\r
-      else\r
-      {\r
-        // similar to octal\r
-        while (result.size() < 4*width)\r
-          result.insert((std::string::size_type)0, 1, '0');\r
-        while (result.size() > 4*width)\r
-        {\r
-          // do not trim to less than 1 bit (1-bit magnitude)\r
-          if (result.size() <= 1) break;\r
-          // only trim if it doesn't change the sign and therefore the value\r
-          if (result[0] != '0') break;\r
-          result.erase(0,1);\r
-        }\r
-        while (result.size() % 4 != 0)\r
-          result.insert((std::string::size_type)0, 1, '0');\r
-        // now convert to hex\r
-        std::string hex_result;\r
-        for (unsigned i = 0; i < result.size()/4; i++)\r
-        {\r
-          // yuck - ugly or what?\r
-          if (result[i*4] == '0')\r
-          {\r
-            if (result[i*4+1] == '0')\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '0';\r
-                else\r
-                  hex_result += '1';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '2';\r
-                else\r
-                  hex_result += '3';\r
-              }\r
-            }\r
-            else\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '4';\r
-                else\r
-                  hex_result += '5';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '6';\r
-                else\r
-                  hex_result += '7';\r
-              }\r
-            }\r
-          }\r
-          else\r
-          {\r
-            if (result[i*4+1] == '0')\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += '8';\r
-                else\r
-                  hex_result += '9';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += 'a';\r
-                else\r
-                  hex_result += 'b';\r
-              }\r
-            }\r
-            else\r
-            {\r
-              if (result[i*4+2] == '0')\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += 'c';\r
-                else\r
-                  hex_result += 'd';\r
-              }\r
-              else\r
-              {\r
-                if (result[i*4+3] == '0')\r
-                  hex_result += 'e';\r
-                else\r
-                  hex_result += 'f';\r
-              }\r
-            }\r
-          }\r
-        }\r
-        result = hex_result;\r
-        // add the prefix\r
-        result.insert((std::string::size_type)0, "0x");\r
-      }\r
-    }\r
-    else\r
-    {\r
-      // convert to sign-magnitude\r
-      // the representation is:\r
-      // [radix#]magnitude\r
-      // create a representation of the magnitude by successive division\r
-      do\r
-      {\r
-        T ch = i % t_radix;\r
-        i /= t_radix;\r
-        result.insert((std::string::size_type)0, 1, to_char[(int)ch]);\r
-      }\r
-      while(i != t_zero || result.size() < width);\r
-      // prefix everything with the radix if the hashed representation was requested\r
-      if (hashed)\r
-        result.insert((std::string::size_type)0, unsigned_to_string(radix) + "#");\r
-    }\r
-    return result;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-  // exported conversions to string\r
-\r
-  std::string short_to_string(short i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return simage(i, radix, display, width);\r
-  }\r
-\r
-  std::string unsigned_short_to_string(unsigned short i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return uimage(i, radix, display, width);\r
-  }\r
-\r
-  std::string int_to_string(int i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return simage(i, radix, display, width);\r
-  }\r
-\r
-  std::string unsigned_to_string(unsigned i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return uimage(i, radix, display, width);\r
-  }\r
-\r
-  std::string long_to_string(long i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return simage(i, radix, display, width);\r
-  }\r
-\r
-  std::string unsigned_long_to_string(unsigned long i, unsigned radix, radix_display_t display, unsigned width)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return uimage(i, radix, display, width);\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-  // Conversions FROM string\r
-  // local template function\r
-  // Note: this has been copied and modified for the inf class - so any changes here must be made there too\r
-\r
-  // signed version\r
-  template<typename T>\r
-  static T svalue(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    if (radix != 0 && (radix < 2 || radix > 36))\r
-      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));\r
-    std::string::size_type i = 0;\r
-    // the radix passed as a parameter is just the default - it can be\r
-    // overridden by either the C prefix or the hash prefix. Note: a leading zero\r
-    // is the C-style prefix for octal - I only make this override the default\r
-    // when the default prefix is not specified\r
-    // First check for a C-style prefix\r
-    bool c_style = false;\r
-    if (i < str.size() && str[i] == '0')\r
-    {\r
-      // octal, binary or hex\r
-      if (i+1 < str.size() && tolower(str[i+1]) == 'x')\r
-      {\r
-        radix = 16;\r
-        i += 2;\r
-        c_style = true;\r
-      }\r
-      else if (i+1 < str.size() && tolower(str[i+1]) == 'b')\r
-      {\r
-        radix = 2;\r
-        i += 2;\r
-        c_style = true;\r
-      }\r
-      else if (radix == 0)\r
-      {\r
-        radix = 8;\r
-        i += 1;\r
-        c_style = true;\r
-      }\r
-    }\r
-    // now check for a hash-style prefix if a C-style prefix was not found\r
-    if (i == 0)\r
-    {\r
-      // scan for the sequence {digits}#\r
-      bool hash_found = false;\r
-      std::string::size_type j = i;\r
-      for (; j < str.size(); j++)\r
-      {\r
-        if (!isdigit(str[j]))\r
-        {\r
-          if (str[j] == '#')\r
-            hash_found = true;\r
-          break;\r
-        }\r
-      }\r
-      if (hash_found)\r
-      {\r
-        // use the hash prefix to define the radix\r
-        // i points to the start of the radix and j points to the # character\r
-        std::string slice = str.substr(i, j-i);\r
-        radix = string_to_unsigned(slice);\r
-        i = j+1;\r
-      }\r
-    }\r
-    if (radix == 0)\r
-      radix = 10;\r
-    if (radix < 2 || radix > 36)\r
-      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));\r
-    T val(0);\r
-    if (c_style)\r
-    {\r
-      // the C style formats are bit patterns not integer values - these need\r
-      // to be sign-extended to get the right value\r
-      std::string binary;\r
-      if (radix == 2)\r
-      {\r
-        for (std::string::size_type j = i; j < str.size(); j++)\r
-        {\r
-          switch(str[j])\r
-          {\r
-          case '0':\r
-            binary += '0';\r
-            break;\r
-          case '1':\r
-            binary += '1';\r
-            break;\r
-          default:\r
-            throw std::invalid_argument("invalid binary character in string " + str);\r
-            break;\r
-          }\r
-        }\r
-      }\r
-      else if (radix == 8)\r
-      {\r
-        for (std::string::size_type j = i; j < str.size(); j++)\r
-        {\r
-          switch(str[j])\r
-          {\r
-          case '0':\r
-            binary += "000";\r
-            break;\r
-          case '1':\r
-            binary += "001";\r
-            break;\r
-          case '2':\r
-            binary += "010";\r
-            break;\r
-          case '3':\r
-            binary += "011";\r
-            break;\r
-          case '4':\r
-            binary += "100";\r
-            break;\r
-          case '5':\r
-            binary += "101";\r
-            break;\r
-          case '6':\r
-            binary += "110";\r
-            break;\r
-          case '7':\r
-            binary += "111";\r
-            break;\r
-          default:\r
-            throw std::invalid_argument("invalid octal character in string " + str);\r
-            break;\r
-          }\r
-        }\r
-      }\r
-      else\r
-      {\r
-        for (std::string::size_type j = i; j < str.size(); j++)\r
-        {\r
-          switch(tolower(str[j]))\r
-          {\r
-          case '0':\r
-            binary += "0000";\r
-            break;\r
-          case '1':\r
-            binary += "0001";\r
-            break;\r
-          case '2':\r
-            binary += "0010";\r
-            break;\r
-          case '3':\r
-            binary += "0011";\r
-            break;\r
-          case '4':\r
-            binary += "0100";\r
-            break;\r
-          case '5':\r
-            binary += "0101";\r
-            break;\r
-          case '6':\r
-            binary += "0110";\r
-            break;\r
-          case '7':\r
-            binary += "0111";\r
-            break;\r
-          case '8':\r
-            binary += "1000";\r
-            break;\r
-          case '9':\r
-            binary += "1001";\r
-            break;\r
-          case 'a':\r
-            binary += "1010";\r
-            break;\r
-          case 'b':\r
-            binary += "1011";\r
-            break;\r
-          case 'c':\r
-            binary += "1100";\r
-            break;\r
-          case 'd':\r
-            binary += "1101";\r
-            break;\r
-          case 'e':\r
-            binary += "1110";\r
-            break;\r
-          case 'f':\r
-            binary += "1111";\r
-            break;\r
-          default:\r
-            throw std::invalid_argument("invalid hex character in string " + str);\r
-            break;\r
-          }\r
-        }\r
-      }\r
-      // now sign-extend to the right number of bits for the type\r
-      while (binary.size() < sizeof(T)*8)\r
-        binary.insert((std::string::size_type)0, 1, binary.empty() ? '0' : binary[0]);\r
-      // now convert the value\r
-      for (std::string::size_type j = 0; j < binary.size(); j++)\r
-      {\r
-        val *= 2;\r
-        int ch = from_char[(unsigned char)binary[j]] ;\r
-        val += T(ch);\r
-      }\r
-    }\r
-    else\r
-    {\r
-      // now scan for a sign and find whether this is a negative number\r
-      bool negative = false;\r
-      if (i < str.size())\r
-      {\r
-        switch (str[i])\r
-        {\r
-        case '-':\r
-          negative = true;\r
-          i++;\r
-          break;\r
-        case '+':\r
-          i++;\r
-          break;\r
-        }\r
-      }\r
-      for (; i < str.size(); i++)\r
-      {\r
-        val *= T(radix);\r
-        int ch = from_char[(unsigned char)str[i]] ;\r
-        if (ch == -1 || (unsigned)ch >= radix)\r
-          throw std::invalid_argument("invalid character in string " + str);\r
-        val += T(ch);\r
-      }\r
-      if (negative)\r
-        val = -val;\r
-    }\r
-    return val;\r
-  }\r
-\r
-  // unsigned version\r
-  template<typename T>\r
-  static T uvalue(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    if (radix != 0 && (radix < 2 || radix > 36))\r
-      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));\r
-    unsigned i = 0;\r
-    // the radix passed as a parameter is just the default - it can be\r
-    // overridden by either the C prefix or the hash prefix. Note: a leading\r
-    // zero is the C-style prefix for octal - I only make this override the\r
-    // default when the default prefix is not specified\r
-    // First check for a C-style prefix\r
-    bool c_style = false;\r
-    if (i < str.size() && str[i] == '0')\r
-    {\r
-      // binary or hex\r
-      if (i+1 < str.size() && tolower(str[i+1]) == 'x')\r
-      {\r
-        radix = 16;\r
-        i += 2;\r
-        c_style = true;\r
-      }\r
-      else if (i+1 < str.size() && tolower(str[i+1]) == 'b')\r
-      {\r
-        radix = 2;\r
-        i += 2;\r
-        c_style = true;\r
-      }\r
-      else if (radix == 0)\r
-      {\r
-        radix = 8;\r
-        i += 1;\r
-        c_style = true;\r
-      }\r
-    }\r
-    // now check for a hash-style prefix if a C-style prefix was not found\r
-    if (i == 0)\r
-    {\r
-      // scan for the sequence {digits}#\r
-      bool hash_found = false;\r
-      unsigned j = i;\r
-      for (; j < str.size(); j++)\r
-      {\r
-        if (!isdigit(str[j]))\r
-        {\r
-          if (str[j] == '#')\r
-            hash_found = true;\r
-          break;\r
-        }\r
-      }\r
-      if (hash_found)\r
-      {\r
-        // use the hash prefix to define the radix\r
-        // i points to the start of the radix and j points to the # character\r
-        std::string slice = str.substr(i, j-i);\r
-        radix = string_to_unsigned(slice);\r
-        i = j+1;\r
-      }\r
-    }\r
-    if (radix == 0)\r
-      radix = 10;\r
-    if (radix < 2 || radix > 36)\r
-      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));\r
-    T val(0);\r
-    if (c_style)\r
-    {\r
-      // the C style formats are bit patterns not integer values - these need\r
-      // to be sign-extended to get the right value\r
-      std::string binary;\r
-      if (radix == 2)\r
-      {\r
-        for (unsigned j = i; j < str.size(); j++)\r
-        {\r
-          switch(str[j])\r
-          {\r
-          case '0':\r
-            binary += '0';\r
-            break;\r
-          case '1':\r
-            binary += '1';\r
-            break;\r
-          default:\r
-            throw std::invalid_argument("invalid hex character in string " + str);\r
-            break;\r
-          }\r
-        }\r
-      }\r
-      else if (radix == 8)\r
-      {\r
-        for (unsigned j = i; j < str.size(); j++)\r
-        {\r
-          switch(str[j])\r
-          {\r
-          case '0':\r
-            binary += "000";\r
-            break;\r
-          case '1':\r
-            binary += "001";\r
-            break;\r
-          case '2':\r
-            binary += "010";\r
-            break;\r
-          case '3':\r
-            binary += "011";\r
-            break;\r
-          case '4':\r
-            binary += "100";\r
-            break;\r
-          case '5':\r
-            binary += "101";\r
-            break;\r
-          case '6':\r
-            binary += "110";\r
-            break;\r
-          case '7':\r
-            binary += "111";\r
-            break;\r
-          default:\r
-            throw std::invalid_argument("invalid octal character in string " + str);\r
-            break;\r
-          }\r
-        }\r
-      }\r
-      else\r
-      {\r
-        for (unsigned j = i; j < str.size(); j++)\r
-        {\r
-          switch(tolower(str[j]))\r
-          {\r
-          case '0':\r
-            binary += "0000";\r
-            break;\r
-          case '1':\r
-            binary += "0001";\r
-            break;\r
-          case '2':\r
-            binary += "0010";\r
-            break;\r
-          case '3':\r
-            binary += "0011";\r
-            break;\r
-          case '4':\r
-            binary += "0100";\r
-            break;\r
-          case '5':\r
-            binary += "0101";\r
-            break;\r
-          case '6':\r
-            binary += "0110";\r
-            break;\r
-          case '7':\r
-            binary += "0111";\r
-            break;\r
-          case '8':\r
-            binary += "1000";\r
-            break;\r
-          case '9':\r
-            binary += "1001";\r
-            break;\r
-          case 'a':\r
-            binary += "1010";\r
-            break;\r
-          case 'b':\r
-            binary += "1011";\r
-            break;\r
-          case 'c':\r
-            binary += "1100";\r
-            break;\r
-          case 'd':\r
-            binary += "1101";\r
-            break;\r
-          case 'e':\r
-            binary += "1110";\r
-            break;\r
-          case 'f':\r
-            binary += "1111";\r
-            break;\r
-          default:\r
-            throw std::invalid_argument("invalid hex character in string " + str);\r
-            break;\r
-          }\r
-        }\r
-      }\r
-      // now zero-extend to the right number of bits for the type\r
-      while (binary.size() < sizeof(T)*8)\r
-        binary.insert((std::string::size_type)0, 1, '0');\r
-      // now convert the value\r
-      for (unsigned j = 0; j < binary.size(); j++)\r
-      {\r
-        val *= 2;\r
-        int ch = from_char[(unsigned char)binary[j]] ;\r
-        val += T(ch);\r
-      }\r
-    }\r
-    else\r
-    {\r
-      // now scan for a sign and find whether this is a negative number\r
-      if (i < str.size())\r
-      {\r
-        switch (str[i])\r
-        {\r
-        case '-':\r
-          throw std::invalid_argument("invalid sign character in string " + str + " for unsigned value");\r
-          i++;\r
-          break;\r
-        case '+':\r
-          i++;\r
-          break;\r
-        }\r
-      }\r
-      for (; i < str.size(); i++)\r
-      {\r
-        val *= T(radix);\r
-        int ch = from_char[(unsigned char)str[i]] ;\r
-        if (ch == -1 || (unsigned)ch >= radix)\r
-        {\r
-          throw std::invalid_argument("invalid character in string " + str);\r
-        }\r
-        val += T(ch);\r
-      }\r
-    }\r
-    return val;\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-  // exported functions\r
-\r
-  short string_to_short(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return svalue<short>(str, radix);\r
-  }\r
-\r
-  unsigned short string_to_unsigned_short(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return uvalue<unsigned short>(str, radix);\r
-  }\r
-\r
-  int string_to_int(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return svalue<int>(str, radix);\r
-  }\r
-\r
-  unsigned string_to_unsigned(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return uvalue<unsigned>(str, radix);\r
-  }\r
-\r
-  long string_to_long(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return svalue<long>(str, radix);\r
-  }\r
-\r
-  unsigned long string_to_unsigned_long(const std::string& str, unsigned radix)\r
-    throw(std::invalid_argument)\r
-  {\r
-    return uvalue<unsigned long>(str, radix);\r
-  }\r
-\r
-  ////////////////////////////////////////////////////////////////////////////////\r
-\r
-} // end namespace stlplus\r
+////////////////////////////////////////////////////////////////////////////////
+
+//   Author:    Andy Rushton
+//   Copyright: (c) Southampton University 1999-2004
+//              (c) Andy Rushton           2004-2009
+//   License:   BSD License, see ../docs/license.html
+
+////////////////////////////////////////////////////////////////////////////////
+#include "string_int.hpp"
+#include <ctype.h>
+#include <stdlib.h>
+
+namespace stlplus
+{
+
+  ////////////////////////////////////////////////////////////////////////////////
+  // character mappings
+
+  static char to_char [] = "0123456789abcdefghijklmnopqrstuvwxyz";
+  static int from_char [] = 
+  {
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+  };
+
+  ////////////////////////////////////////////////////////////////////////////////
+  // Conversions to string
+  // Local generic routines
+
+  // signed version of the generic image generation function for all integer types
+  template<typename T>
+  static std::string simage (T i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    if (radix < 2 || radix > 36)
+      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));
+    // untangle all the options
+    bool hashed = false;
+    bool binary = false;
+    bool octal = false;
+    bool hex = false;
+    switch(display)
+    {
+    case radix_none:
+      break;
+    case radix_hash_style:
+      hashed = radix != 10;
+      break;
+    case radix_hash_style_all:
+      hashed = true;
+      break;
+    case radix_c_style:
+      if (radix == 16)
+        hex = true;
+      else if (radix == 8)
+        octal = true;
+      else if (radix == 2)
+        binary = true;
+      break;
+    case radix_c_style_or_hash:
+      if (radix == 16)
+        hex = true;
+      else if (radix == 8)
+        octal = true;
+      else if (radix == 2)
+        binary = true;
+      else if (radix != 10)
+        hashed = true;
+      break;
+    default:
+      throw std::invalid_argument("invalid radix display value");
+    }
+    // create constants of the same type as the template parameter to avoid type mismatches
+    const T t_zero(0);
+    const T t_radix(radix);
+    // the C representations for binary, octal and hex use 2's-complement representation
+    // all other represenations use sign-magnitude
+    std::string result;
+    if (hex || octal || binary)
+    {
+      // bit-pattern representation
+      // this is the binary representation optionally shown in octal or hex
+      // first generate the binary by masking the bits
+      // ensure that it has at least one bit!
+      for (T mask(1); ; mask <<= 1)
+      {
+        result.insert((std::string::size_type)0, 1, i & mask ? '1' : '0');
+        if (mask == t_zero) break;
+      }
+      // the result is now the full width of the type - e.g. int will give a 32-bit result
+      // now interpret this as either binary, octal or hex and add the prefix
+      if (binary)
+      {
+        // the result is already binary - but the width may be wrong
+        // if this is still smaller than the width field, sign extend
+        // otherwise trim down to either the width or the smallest string that preserves the value
+        while (result.size() < width)
+          result.insert((std::string::size_type)0, 1, result[0]);
+        while (result.size() > width)
+        {
+          // do not trim to less than 2 bits (sign plus 1-bit magnitude)
+          if (result.size() <= 2) break;
+          // only trim if it doesn't change the sign and therefore the value
+          if (result[0] != result[1]) break;
+          result.erase(0,1);
+        }
+        // add the prefix
+        result.insert((std::string::size_type)0, "0b");
+      }
+      else if (octal)
+      {
+        // the result is currently binary - but before converting get the width right
+        // the width is expressed in octal digits so make the binary 3 times this
+        // if this is still smaller than the width field, sign extend
+        // otherwise trim down to either the width or the smallest string that preserves the value
+        // also ensure that the binary is a multiple of 3 bits to make the conversion to octal easier
+        while (result.size() < 3*width)
+          result.insert((std::string::size_type)0, 1, result[0]);
+        while (result.size() > 3*width)
+        {
+          // do not trim to less than 2 bits (sign plus 1-bit magnitude)
+          if (result.size() <= 2) break;
+          // only trim if it doesn't change the sign and therefore the value
+          if (result[0] != result[1]) break;
+          result.erase(0,1);
+        }
+        while (result.size() % 3 != 0)
+          result.insert((std::string::size_type)0, 1, result[0]);
+        // now convert to octal
+        std::string octal_result;
+        for (unsigned i = 0; i < result.size()/3; i++)
+        {
+          // yuck - ugly or what?
+          if (result[i*3] == '0')
+          {
+            if (result[i*3+1] == '0')
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '0';
+              else
+                octal_result += '1';
+            }
+            else
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '2';
+              else
+                octal_result += '3';
+            }
+          }
+          else
+          {
+            if (result[i*3+1] == '0')
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '4';
+              else
+                octal_result += '5';
+            }
+            else
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '6';
+              else
+                octal_result += '7';
+            }
+          }
+        }
+        result = octal_result;
+        // add the prefix
+        result.insert((std::string::size_type)0, "0");
+      }
+      else
+      {
+        // hex - similar to octal
+        while (result.size() < 4*width)
+          result.insert((std::string::size_type)0, 1, result[0]);
+        while (result.size() > 4*width)
+        {
+          // do not trim to less than 2 bits (sign plus 1-bit magnitude)
+          if (result.size() <= 2) break;
+          // only trim if it doesn't change the sign and therefore the value
+          if (result[0] != result[1]) break;
+          result.erase(0,1);
+        }
+        while (result.size() % 4 != 0)
+          result.insert((std::string::size_type)0, 1, result[0]);
+        // now convert to hex
+        std::string hex_result;
+        for (unsigned i = 0; i < result.size()/4; i++)
+        {
+          // yuck - ugly or what?
+          if (result[i*4] == '0')
+          {
+            if (result[i*4+1] == '0')
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '0';
+                else
+                  hex_result += '1';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '2';
+                else
+                  hex_result += '3';
+              }
+            }
+            else
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '4';
+                else
+                  hex_result += '5';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '6';
+                else
+                  hex_result += '7';
+              }
+            }
+          }
+          else
+          {
+            if (result[i*4+1] == '0')
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '8';
+                else
+                  hex_result += '9';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += 'a';
+                else
+                  hex_result += 'b';
+              }
+            }
+            else
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += 'c';
+                else
+                  hex_result += 'd';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += 'e';
+                else
+                  hex_result += 'f';
+              }
+            }
+          }
+        }
+        result = hex_result;
+        // add the prefix
+        result.insert((std::string::size_type)0, "0x");
+      }
+    }
+    else
+    {
+      // convert to sign-magnitude
+      // the representation is:
+      // [radix#][sign]magnitude
+      bool negative = i < t_zero;
+      // create a representation of the magnitude by successive division
+      do
+      {
+        T ch = abs(i % t_radix);
+        i /= t_radix;
+        result.insert((std::string::size_type)0, 1, to_char[ch]);
+      }
+      while(i != t_zero || result.size() < width);
+      // add the prefixes
+      // add a sign only for negative values
+      if (negative)
+        result.insert((std::string::size_type)0, 1, '-');
+      // then prefix everything with the radix if the hashed representation was requested
+      if (hashed)
+        result.insert((std::string::size_type)0, unsigned_to_string(radix) + "#");
+    }
+    return result;
+  }
+
+  // unsigned version
+  template<typename T>
+  static std::string uimage (T i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    if (radix < 2 || radix > 36)
+      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));
+    // untangle all the options
+    bool hashed = false;
+    bool binary = false;
+    bool octal = false;
+    bool hex = false;
+    switch(display)
+    {
+    case radix_none:
+      break;
+    case radix_hash_style:
+      hashed = radix != 10;
+      break;
+    case radix_hash_style_all:
+      hashed = true;
+      break;
+    case radix_c_style:
+      if (radix == 16)
+        hex = true;
+      else if (radix == 8)
+        octal = true;
+      else if (radix == 2)
+        binary = true;
+      break;
+    case radix_c_style_or_hash:
+      if (radix == 16)
+        hex = true;
+      else if (radix == 8)
+        octal = true;
+      else if (radix == 2)
+        binary = true;
+      else if (radix != 10)
+        hashed = true;
+      break;
+    default:
+      throw std::invalid_argument("invalid radix display value");
+    }
+    // create constants of the same type as the template parameter to avoid type mismatches
+    const T t_zero(0);
+    const T t_radix(radix);
+    // the C representations for binary, octal and hex use 2's-complement representation
+    // all other represenations use sign-magnitude
+    std::string result;
+    if (hex || octal || binary)
+    {
+      // bit-pattern representation
+      // this is the binary representation optionally shown in octal or hex
+      // first generate the binary by masking the bits
+      // ensure at least one bit
+      for (T mask(1); ; mask <<= 1)
+      {
+        result.insert((std::string::size_type)0, 1, i & mask ? '1' : '0');
+        if (mask == t_zero) break;
+      }
+      // the result is now the full width of the type - e.g. int will give a 32-bit result
+      // now interpret this as either binary, octal or hex and add the prefix
+      if (binary)
+      {
+        // the result is already binary - but the width may be wrong
+        // if this is still smaller than the width field, zero extend
+        // otherwise trim down to either the width or the smallest string that preserves the value
+        while (result.size() < width)
+          result.insert((std::string::size_type)0, 1, '0');
+        while (result.size() > width)
+        {
+          // do not trim to less than 1 bit (1-bit magnitude)
+          if (result.size() <= 1) break;
+          // only trim if it doesn't change the sign and therefore the value
+          if (result[0] != '0') break;
+          result.erase(0,1);
+        }
+        // add the prefix
+        result.insert((std::string::size_type)0, "0b");
+      }
+      else if (octal)
+      {
+        // the result is currently binary - but before converting get the width right
+        // the width is expressed in octal digits so make the binary 3 times this
+        // if this is still smaller than the width field, sign extend
+        // otherwise trim down to either the width or the smallest string that preserves the value
+        // also ensure that the binary is a multiple of 3 bits to make the conversion to octal easier
+        while (result.size() < 3*width)
+          result.insert((std::string::size_type)0, 1, '0');
+        while (result.size() > 3*width)
+        {
+          // do not trim to less than 1 bit (1-bit magnitude)
+          if (result.size() <= 1) break;
+          // only trim if it doesn't change the sign and therefore the value
+          if (result[0] != '0') break;
+          result.erase(0,1);
+        }
+        while (result.size() % 3 != 0)
+          result.insert((std::string::size_type)0, 1, '0');
+        // now convert to octal
+        std::string octal_result;
+        for (unsigned i = 0; i < result.size()/3; i++)
+        {
+          // yuck - ugly or what?
+          if (result[i*3] == '0')
+          {
+            if (result[i*3+1] == '0')
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '0';
+              else
+                octal_result += '1';
+            }
+            else
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '2';
+              else
+                octal_result += '3';
+            }
+          }
+          else
+          {
+            if (result[i*3+1] == '0')
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '4';
+              else
+                octal_result += '5';
+            }
+            else
+            {
+              if (result[i*3+2] == '0')
+                octal_result += '6';
+              else
+                octal_result += '7';
+            }
+          }
+        }
+        result = octal_result;
+        // add the prefix if the leading digit is not already 0
+        if (result.empty() || result[0] != '0') result.insert((std::string::size_type)0, "0");
+      }
+      else
+      {
+        // similar to octal
+        while (result.size() < 4*width)
+          result.insert((std::string::size_type)0, 1, '0');
+        while (result.size() > 4*width)
+        {
+          // do not trim to less than 1 bit (1-bit magnitude)
+          if (result.size() <= 1) break;
+          // only trim if it doesn't change the sign and therefore the value
+          if (result[0] != '0') break;
+          result.erase(0,1);
+        }
+        while (result.size() % 4 != 0)
+          result.insert((std::string::size_type)0, 1, '0');
+        // now convert to hex
+        std::string hex_result;
+        for (unsigned i = 0; i < result.size()/4; i++)
+        {
+          // yuck - ugly or what?
+          if (result[i*4] == '0')
+          {
+            if (result[i*4+1] == '0')
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '0';
+                else
+                  hex_result += '1';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '2';
+                else
+                  hex_result += '3';
+              }
+            }
+            else
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '4';
+                else
+                  hex_result += '5';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '6';
+                else
+                  hex_result += '7';
+              }
+            }
+          }
+          else
+          {
+            if (result[i*4+1] == '0')
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += '8';
+                else
+                  hex_result += '9';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += 'a';
+                else
+                  hex_result += 'b';
+              }
+            }
+            else
+            {
+              if (result[i*4+2] == '0')
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += 'c';
+                else
+                  hex_result += 'd';
+              }
+              else
+              {
+                if (result[i*4+3] == '0')
+                  hex_result += 'e';
+                else
+                  hex_result += 'f';
+              }
+            }
+          }
+        }
+        result = hex_result;
+        // add the prefix
+        result.insert((std::string::size_type)0, "0x");
+      }
+    }
+    else
+    {
+      // convert to sign-magnitude
+      // the representation is:
+      // [radix#]magnitude
+      // create a representation of the magnitude by successive division
+      do
+      {
+        T ch = i % t_radix;
+        i /= t_radix;
+        result.insert((std::string::size_type)0, 1, to_char[(int)ch]);
+      }
+      while(i != t_zero || result.size() < width);
+      // prefix everything with the radix if the hashed representation was requested
+      if (hashed)
+        result.insert((std::string::size_type)0, unsigned_to_string(radix) + "#");
+    }
+    return result;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+  // exported conversions to string
+
+  std::string short_to_string(short i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    return simage(i, radix, display, width);
+  }
+
+  std::string unsigned_short_to_string(unsigned short i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    return uimage(i, radix, display, width);
+  }
+
+  std::string int_to_string(int i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    return simage(i, radix, display, width);
+  }
+
+  std::string unsigned_to_string(unsigned i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    return uimage(i, radix, display, width);
+  }
+
+  std::string long_to_string(long i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    return simage(i, radix, display, width);
+  }
+
+  std::string unsigned_long_to_string(unsigned long i, unsigned radix, radix_display_t display, unsigned width)
+    throw(std::invalid_argument)
+  {
+    return uimage(i, radix, display, width);
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+  // Conversions FROM string
+  // local template function
+  // Note: this has been copied and modified for the inf class - so any changes here must be made there too
+
+  // signed version
+  template<typename T>
+  static T svalue(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    if (radix != 0 && (radix < 2 || radix > 36))
+      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));
+    std::string::size_type i = 0;
+    // the radix passed as a parameter is just the default - it can be
+    // overridden by either the C prefix or the hash prefix. Note: a leading zero
+    // is the C-style prefix for octal - I only make this override the default
+    // when the default prefix is not specified
+    // First check for a C-style prefix
+    bool c_style = false;
+    if (i < str.size() && str[i] == '0')
+    {
+      // octal, binary or hex
+      if (i+1 < str.size() && tolower(str[i+1]) == 'x')
+      {
+        radix = 16;
+        i += 2;
+        c_style = true;
+      }
+      else if (i+1 < str.size() && tolower(str[i+1]) == 'b')
+      {
+        radix = 2;
+        i += 2;
+        c_style = true;
+      }
+      else if (radix == 0)
+      {
+        radix = 8;
+        i += 1;
+        c_style = true;
+      }
+    }
+    // now check for a hash-style prefix if a C-style prefix was not found
+    if (i == 0)
+    {
+      // scan for the sequence {digits}#
+      bool hash_found = false;
+      std::string::size_type j = i;
+      for (; j < str.size(); j++)
+      {
+        if (!isdigit(str[j]))
+        {
+          if (str[j] == '#')
+            hash_found = true;
+          break;
+        }
+      }
+      if (hash_found)
+      {
+        // use the hash prefix to define the radix
+        // i points to the start of the radix and j points to the # character
+        std::string slice = str.substr(i, j-i);
+        radix = string_to_unsigned(slice);
+        i = j+1;
+      }
+    }
+    if (radix == 0)
+      radix = 10;
+    if (radix < 2 || radix > 36)
+      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));
+    T val(0);
+    if (c_style)
+    {
+      // the C style formats are bit patterns not integer values - these need
+      // to be sign-extended to get the right value
+      std::string binary;
+      if (radix == 2)
+      {
+        for (std::string::size_type j = i; j < str.size(); j++)
+        {
+          switch(str[j])
+          {
+          case '0':
+            binary += '0';
+            break;
+          case '1':
+            binary += '1';
+            break;
+          default:
+            throw std::invalid_argument("invalid binary character in string " + str);
+            break;
+          }
+        }
+      }
+      else if (radix == 8)
+      {
+        for (std::string::size_type j = i; j < str.size(); j++)
+        {
+          switch(str[j])
+          {
+          case '0':
+            binary += "000";
+            break;
+          case '1':
+            binary += "001";
+            break;
+          case '2':
+            binary += "010";
+            break;
+          case '3':
+            binary += "011";
+            break;
+          case '4':
+            binary += "100";
+            break;
+          case '5':
+            binary += "101";
+            break;
+          case '6':
+            binary += "110";
+            break;
+          case '7':
+            binary += "111";
+            break;
+          default:
+            throw std::invalid_argument("invalid octal character in string " + str);
+            break;
+          }
+        }
+      }
+      else
+      {
+        for (std::string::size_type j = i; j < str.size(); j++)
+        {
+          switch(tolower(str[j]))
+          {
+          case '0':
+            binary += "0000";
+            break;
+          case '1':
+            binary += "0001";
+            break;
+          case '2':
+            binary += "0010";
+            break;
+          case '3':
+            binary += "0011";
+            break;
+          case '4':
+            binary += "0100";
+            break;
+          case '5':
+            binary += "0101";
+            break;
+          case '6':
+            binary += "0110";
+            break;
+          case '7':
+            binary += "0111";
+            break;
+          case '8':
+            binary += "1000";
+            break;
+          case '9':
+            binary += "1001";
+            break;
+          case 'a':
+            binary += "1010";
+            break;
+          case 'b':
+            binary += "1011";
+            break;
+          case 'c':
+            binary += "1100";
+            break;
+          case 'd':
+            binary += "1101";
+            break;
+          case 'e':
+            binary += "1110";
+            break;
+          case 'f':
+            binary += "1111";
+            break;
+          default:
+            throw std::invalid_argument("invalid hex character in string " + str);
+            break;
+          }
+        }
+      }
+      // now sign-extend to the right number of bits for the type
+      while (binary.size() < sizeof(T)*8)
+        binary.insert((std::string::size_type)0, 1, binary.empty() ? '0' : binary[0]);
+      // now convert the value
+      for (std::string::size_type j = 0; j < binary.size(); j++)
+      {
+        val *= 2;
+        int ch = from_char[(unsigned char)binary[j]] ;
+        val += T(ch);
+      }
+    }
+    else
+    {
+      // now scan for a sign and find whether this is a negative number
+      bool negative = false;
+      if (i < str.size())
+      {
+        switch (str[i])
+        {
+        case '-':
+          negative = true;
+          i++;
+          break;
+        case '+':
+          i++;
+          break;
+        }
+      }
+      for (; i < str.size(); i++)
+      {
+        val *= T(radix);
+        int ch = from_char[(unsigned char)str[i]] ;
+        if (ch == -1 || (unsigned)ch >= radix)
+          throw std::invalid_argument("invalid character in string " + str);
+        val += T(ch);
+      }
+      if (negative)
+        val = -val;
+    }
+    return val;
+  }
+
+  // unsigned version
+  template<typename T>
+  static T uvalue(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    if (radix != 0 && (radix < 2 || radix > 36))
+      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));
+    unsigned i = 0;
+    // the radix passed as a parameter is just the default - it can be
+    // overridden by either the C prefix or the hash prefix. Note: a leading
+    // zero is the C-style prefix for octal - I only make this override the
+    // default when the default prefix is not specified
+    // First check for a C-style prefix
+    bool c_style = false;
+    if (i < str.size() && str[i] == '0')
+    {
+      // binary or hex
+      if (i+1 < str.size() && tolower(str[i+1]) == 'x')
+      {
+        radix = 16;
+        i += 2;
+        c_style = true;
+      }
+      else if (i+1 < str.size() && tolower(str[i+1]) == 'b')
+      {
+        radix = 2;
+        i += 2;
+        c_style = true;
+      }
+      else if (radix == 0)
+      {
+        radix = 8;
+        i += 1;
+        c_style = true;
+      }
+    }
+    // now check for a hash-style prefix if a C-style prefix was not found
+    if (i == 0)
+    {
+      // scan for the sequence {digits}#
+      bool hash_found = false;
+      unsigned j = i;
+      for (; j < str.size(); j++)
+      {
+        if (!isdigit(str[j]))
+        {
+          if (str[j] == '#')
+            hash_found = true;
+          break;
+        }
+      }
+      if (hash_found)
+      {
+        // use the hash prefix to define the radix
+        // i points to the start of the radix and j points to the # character
+        std::string slice = str.substr(i, j-i);
+        radix = string_to_unsigned(slice);
+        i = j+1;
+      }
+    }
+    if (radix == 0)
+      radix = 10;
+    if (radix < 2 || radix > 36)
+      throw std::invalid_argument("invalid radix value " + unsigned_to_string(radix));
+    T val(0);
+    if (c_style)
+    {
+      // the C style formats are bit patterns not integer values - these need
+      // to be sign-extended to get the right value
+      std::string binary;
+      if (radix == 2)
+      {
+        for (unsigned j = i; j < str.size(); j++)
+        {
+          switch(str[j])
+          {
+          case '0':
+            binary += '0';
+            break;
+          case '1':
+            binary += '1';
+            break;
+          default:
+            throw std::invalid_argument("invalid hex character in string " + str);
+            break;
+          }
+        }
+      }
+      else if (radix == 8)
+      {
+        for (unsigned j = i; j < str.size(); j++)
+        {
+          switch(str[j])
+          {
+          case '0':
+            binary += "000";
+            break;
+          case '1':
+            binary += "001";
+            break;
+          case '2':
+            binary += "010";
+            break;
+          case '3':
+            binary += "011";
+            break;
+          case '4':
+            binary += "100";
+            break;
+          case '5':
+            binary += "101";
+            break;
+          case '6':
+            binary += "110";
+            break;
+          case '7':
+            binary += "111";
+            break;
+          default:
+            throw std::invalid_argument("invalid octal character in string " + str);
+            break;
+          }
+        }
+      }
+      else
+      {
+        for (unsigned j = i; j < str.size(); j++)
+        {
+          switch(tolower(str[j]))
+          {
+          case '0':
+            binary += "0000";
+            break;
+          case '1':
+            binary += "0001";
+            break;
+          case '2':
+            binary += "0010";
+            break;
+          case '3':
+            binary += "0011";
+            break;
+          case '4':
+            binary += "0100";
+            break;
+          case '5':
+            binary += "0101";
+            break;
+          case '6':
+            binary += "0110";
+            break;
+          case '7':
+            binary += "0111";
+            break;
+          case '8':
+            binary += "1000";
+            break;
+          case '9':
+            binary += "1001";
+            break;
+          case 'a':
+            binary += "1010";
+            break;
+          case 'b':
+            binary += "1011";
+            break;
+          case 'c':
+            binary += "1100";
+            break;
+          case 'd':
+            binary += "1101";
+            break;
+          case 'e':
+            binary += "1110";
+            break;
+          case 'f':
+            binary += "1111";
+            break;
+          default:
+            throw std::invalid_argument("invalid hex character in string " + str);
+            break;
+          }
+        }
+      }
+      // now zero-extend to the right number of bits for the type
+      while (binary.size() < sizeof(T)*8)
+        binary.insert((std::string::size_type)0, 1, '0');
+      // now convert the value
+      for (unsigned j = 0; j < binary.size(); j++)
+      {
+        val *= 2;
+        int ch = from_char[(unsigned char)binary[j]] ;
+        val += T(ch);
+      }
+    }
+    else
+    {
+      // now scan for a sign and find whether this is a negative number
+      if (i < str.size())
+      {
+        switch (str[i])
+        {
+        case '-':
+          throw std::invalid_argument("invalid sign character in string " + str + " for unsigned value");
+          i++;
+          break;
+        case '+':
+          i++;
+          break;
+        }
+      }
+      for (; i < str.size(); i++)
+      {
+        val *= T(radix);
+        int ch = from_char[(unsigned char)str[i]] ;
+        if (ch == -1 || (unsigned)ch >= radix)
+        {
+          throw std::invalid_argument("invalid character in string " + str);
+        }
+        val += T(ch);
+      }
+    }
+    return val;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+  // exported functions
+
+  short string_to_short(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    return svalue<short>(str, radix);
+  }
+
+  unsigned short string_to_unsigned_short(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    return uvalue<unsigned short>(str, radix);
+  }
+
+  int string_to_int(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    return svalue<int>(str, radix);
+  }
+
+  unsigned string_to_unsigned(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    return uvalue<unsigned>(str, radix);
+  }
+
+  long string_to_long(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    return svalue<long>(str, radix);
+  }
+
+  unsigned long string_to_unsigned_long(const std::string& str, unsigned radix)
+    throw(std::invalid_argument)
+  {
+    return uvalue<unsigned long>(str, radix);
+  }
+
+  ////////////////////////////////////////////////////////////////////////////////
+
+} // end namespace stlplus
This page took 0.105784 seconds and 4 git commands to generate.