diff --git a/src/string_util.cpp b/src/string_util.cpp index 7f55f94..27a9840 100644 --- a/src/string_util.cpp +++ b/src/string_util.cpp @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include #include #include @@ -24,6 +25,7 @@ #include #include +#include #include #include #include @@ -50,45 +52,18 @@ template std::string str(unsigned long long value); static const char hexAlphabet[] = "0123456789ABCDEF"; +// replacement for C++11 std::stoll off_t s3fs_strtoofft(const char* str, bool is_base_16) { - if(!str || '\0' == *str){ - return 0; + errno = 0; + char *temp; + long long result = strtoll(str, &temp, is_base_16 ? 16 : 10); + + if(temp == str || *temp != '\0'){ + throw std::invalid_argument("s3fs_strtoofft"); } - off_t result; - bool chk_space; - bool chk_base16_prefix; - for(result = 0, chk_space = false, chk_base16_prefix = false; '\0' != *str; str++){ - // check head space - if(!chk_space && isspace(*str)){ - continue; - }else if(!chk_space){ - chk_space = true; - } - // check prefix for base 16 - if(!chk_base16_prefix){ - chk_base16_prefix = true; - if('0' == *str && ('x' == str[1] || 'X' == str[1])){ - is_base_16 = true; - str++; - continue; - } - } - // check like isalnum and set data - result *= (is_base_16 ? 16 : 10); - if('0' <= *str && '9' >= *str){ - result += static_cast(*str - '0'); - }else if(is_base_16){ - if('A' <= *str && *str <= 'F'){ - result += static_cast(*str - 'A' + 0x0a); - }else if('a' <= *str && *str <= 'f'){ - result += static_cast(*str - 'a' + 0x0a); - }else{ - return 0; - } - }else{ - return 0; - } + if((result == LLONG_MIN || result == LLONG_MAX) && errno == ERANGE){ + throw std::out_of_range("s3fs_strtoofft"); } return result; } diff --git a/src/string_util.h b/src/string_util.h index 5a7bdb2..9b5e839 100644 --- a/src/string_util.h +++ b/src/string_util.h @@ -35,7 +35,7 @@ static inline int STR2NCMP(const char *str1, const char *str2) { return strncmp( template std::string str(T value); -// Convert string to off_t. Does not signal invalid input. +// Convert string to off_t. Throws std::invalid_argument and std::out_of_range on bad input. off_t s3fs_strtoofft(const char* str, bool is_base_16 = false); std::string trim_left(const std::string &s, const std::string &t = SPACES); diff --git a/src/test_string_util.cpp b/src/test_string_util.cpp index 82bcb0a..9cafc51 100644 --- a/src/test_string_util.cpp +++ b/src/test_string_util.cpp @@ -79,7 +79,12 @@ void test_strtoofft() { ASSERT_EQUALS(s3fs_strtoofft("0"), static_cast(0L)); ASSERT_EQUALS(s3fs_strtoofft("9"), static_cast(9L)); - ASSERT_EQUALS(s3fs_strtoofft("A"), static_cast(0L)); + try{ + s3fs_strtoofft("A"); + abort(); + }catch(std::exception &e){ + // expected + } ASSERT_EQUALS(s3fs_strtoofft("A", /*is_base_16=*/ true), static_cast(10L)); ASSERT_EQUALS(s3fs_strtoofft("F", /*is_base_16=*/ true), static_cast(15L)); ASSERT_EQUALS(s3fs_strtoofft("a", /*is_base_16=*/ true), static_cast(10L));