parse_double.cpp 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #include "parse_double.h"
  2. #include <util/string/ascii.h>
  3. #include <util/string/cast.h>
  4. namespace NYql {
  5. namespace {
  6. template <typename T>
  7. bool GenericTryFloatFromString(TStringBuf buf, T& value) {
  8. value = 0;
  9. if (!buf.size()) {
  10. return false;
  11. }
  12. if (TryFromString(buf.data(), buf.size(), value)) {
  13. return true;
  14. }
  15. const char* ptr = buf.data();
  16. ui32 size = buf.size();
  17. char sign = '+';
  18. if (*ptr == '+' || *ptr == '-') {
  19. sign = *ptr;
  20. ++ptr;
  21. --size;
  22. }
  23. if (size != 3) {
  24. return false;
  25. }
  26. // NaN or Inf (ignoring case)
  27. if (AsciiToUpper(ptr[0]) == 'N' && AsciiToUpper(ptr[1]) == 'A' && AsciiToUpper(ptr[2]) == 'N') {
  28. value = std::numeric_limits<T>::quiet_NaN();
  29. } else if (AsciiToUpper(ptr[0]) == 'I' && AsciiToUpper(ptr[1]) == 'N' && AsciiToUpper(ptr[2]) == 'F') {
  30. value = std::numeric_limits<T>::infinity();
  31. } else {
  32. return false;
  33. }
  34. if (sign == '-') {
  35. value = -value;
  36. }
  37. return true;
  38. }
  39. }
  40. float FloatFromString(TStringBuf buf) {
  41. float result = 0;
  42. if (!TryFloatFromString(buf, result)) {
  43. throw yexception() << "unable to parse float from '" << buf << "'";
  44. }
  45. return result;
  46. }
  47. double DoubleFromString(TStringBuf buf) {
  48. double result = 0;
  49. if (!TryDoubleFromString(buf, result)) {
  50. throw yexception() << "unable to parse double from '" << buf << "'";
  51. }
  52. return result;
  53. }
  54. bool TryFloatFromString(TStringBuf buf, float& value) {
  55. return GenericTryFloatFromString(buf, value);
  56. }
  57. bool TryDoubleFromString(TStringBuf buf, double& value) {
  58. return GenericTryFloatFromString(buf, value);
  59. }
  60. }