Mercurial > hg > orthanc-stone
view OrthancStone/Sources/Toolbox/GenericToolbox.h @ 1730:af4a2d08549c
preparing for release
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 02 Dec 2020 12:47:05 +0100 |
parents | 5b8b88e5bfd6 |
children | 9ac2a65d4172 |
line wrap: on
line source
/** * Stone of Orthanc * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2020 Osimis S.A., Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/>. **/ #pragma once #include <Compatibility.h> #include <OrthancException.h> #include <boost/shared_ptr.hpp> #include <string> #include <stdint.h> #include <math.h> #include <memory> namespace OrthancStone { namespace GenericToolbox { /** Fast floating point string validation. No trimming applied, so the input must match regex /^[-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/ The following are allowed as edge cases: "" and "-" */ inline bool LegitDoubleString(const char* text) { const char* p = text; if(*p == '-') p++; size_t period = 0; while(*p != 0) { if (*p >= '0' && *p <= '9') ++p; else if(*p == '.') { if(period > 0) return false; else period++; ++p; } else if (*p == 'e' || *p == 'E') { ++p; if (*p == '-' || *p == '+') ++p; // "e+"/"E+" "e-"/"E-" or "e"/"E" must be followed by a number if (!(*p >= '0' && *p <= '9')) return false; // these must be the last in the string while(*p >= '0' && *p <= '9') ++p; return (*p == 0); } else { return false; } } return true; } /** Fast integer string validation. No trimming applied, so the input must match regex /^-?[0-9]*$/ The following are allowed as edge cases: "" and "-" */ inline bool LegitIntegerString(const char* text) { const char* p = text; if (*p == '-') p++; while (*p != 0) { if (*p >= '0' && *p <= '9') ++p; else return false; } return true; } /* Fast string --> double conversion. Must pass the LegitDoubleString test String to doubles with at most 18 digits */ inline bool StringToDouble(double& r, const char* text) { if(!LegitDoubleString(text)) return false; static const double FRAC_FACTORS[] = { 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001, 0.0000000001, 0.00000000001, 0.000000000001, 0.0000000000001, 0.00000000000001, 0.000000000000001, 0.0000000000000001, 0.00000000000000001, 0.000000000000000001, 0.0000000000000000001 }; const size_t FRAC_FACTORS_LEN = sizeof(FRAC_FACTORS)/sizeof(double); r = 0.0; double neg = 1.0; const char* p = text; if (*p == '-') { neg = -1.0; ++p; } // 12345.67890 while (*p >= '0' && *p <= '9') { r = (r*10.0) + (*p - '0'); // 1 12 123 123 12345 ++p; } if (*p == '.') { double f = 0.0; size_t n = 1; ++p; while (*p >= '0' && *p <= '9' && n < FRAC_FACTORS_LEN) { f += (*p - '0') * FRAC_FACTORS[n]; ++p; ++n; } r += f; } r *= neg; // skip the remaining numbers until we reach not-a-digit (either the // end of the string OR the scientific notation symbol) while ((*p >= '0' && *p <= '9')) ++p; if (*p == 0 ) { return true; } else if ((*p == 'e') || (*p == 'E')) { // process the scientific notation double sign; // no init is safe (read below) ++p; if (*p == '-') { sign = -1.0; // point to first number ++p; } else if (*p == '+') { sign = 1.0; // point to first number ++p; } else if (*p >= '0' && *p <= '9') { sign = 1.0; } else { // only a sign char or a number is allowed return false; } // now p points to the absolute value of the exponent double exp = 0; while (*p >= '0' && *p <= '9') { exp = (exp * 10.0) + static_cast<double>(*p - '0'); // 1 12 123 123 12345 ++p; } // now we have our exponent. put a sign on it. exp *= sign; double scFac = ::pow(10.0, exp); r *= scFac; // only allowed symbol here is EOS return (*p == 0); } else { // not allowed return false; } } inline bool StringToDouble(double& r, const std::string& text) { return StringToDouble(r, text.c_str()); } /** Fast string to integer conversion. Leading zeroes and minus are accepted, but a leading + sign is NOT. Must pass the LegitIntegerString function test. In addition, an empty string (or lone minus sign) yields 0. */ template<typename T> inline bool StringToInteger(T& r, const char* text) { if (!LegitIntegerString(text)) return false; r = 0; T neg = 1; const char* p = text; if (*p == '-') { neg = -1; ++p; } while (*p >= '0' && *p <= '9') { r = (r * 10) + static_cast<T>(*p - '0'); // 1 12 123 123 12345 ++p; } r *= neg; if (*p == 0) return true; else return false; } template<typename T> inline bool StringToInteger(T& r, const std::string& text) { return StringToInteger<T>(r, text.c_str()); } /** if input is "rgb(12,23,255)" --> function fills `red`, `green` and `blue` and returns true else ("everything else") --> function returns false and leaves all values untouched */ bool GetRgbValuesFromString(uint8_t& red, uint8_t& green, uint8_t& blue, const char* text); /** See main overload */ inline bool GetRgbValuesFromString(uint8_t& red, uint8_t& green, uint8_t& blue, const std::string& text) { return GetRgbValuesFromString(red, green, blue, text.c_str()); } /** Same as GetRgbValuesFromString */ bool GetRgbaValuesFromString(uint8_t& red, uint8_t& green, uint8_t& blue, uint8_t& alpha, const char* text); /** Same as GetRgbValuesFromString */ inline bool GetRgbaValuesFromString(uint8_t& red, uint8_t& green, uint8_t& blue, uint8_t& alpha, const std::string& text) { return GetRgbaValuesFromString(red, green, blue, alpha, text.c_str()); } /** This method could have been called StripSpacesAndChangeToLower but we might want to add some UUID validation to the argument */ void NormalizeUuid(std::string& uuid); } }