mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-12-23 09:18:55 +00:00
Implement s3fs_strtoofft via strtoll
This tightens error checking and aligns s3fs with known good behavior.
This commit is contained in:
parent
e936854493
commit
4adcd4a6c8
@ -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 <cerrno>
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
@ -24,6 +25,7 @@
|
||||
#include <syslog.h>
|
||||
#include <ctime>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
@ -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<off_t>(*str - '0');
|
||||
}else if(is_base_16){
|
||||
if('A' <= *str && *str <= 'F'){
|
||||
result += static_cast<off_t>(*str - 'A' + 0x0a);
|
||||
}else if('a' <= *str && *str <= 'f'){
|
||||
result += static_cast<off_t>(*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;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ static inline int STR2NCMP(const char *str1, const char *str2) { return strncmp(
|
||||
|
||||
template <class T> 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);
|
||||
|
@ -79,7 +79,12 @@ void test_strtoofft()
|
||||
{
|
||||
ASSERT_EQUALS(s3fs_strtoofft("0"), static_cast<off_t>(0L));
|
||||
ASSERT_EQUALS(s3fs_strtoofft("9"), static_cast<off_t>(9L));
|
||||
ASSERT_EQUALS(s3fs_strtoofft("A"), static_cast<off_t>(0L));
|
||||
try{
|
||||
s3fs_strtoofft("A");
|
||||
abort();
|
||||
}catch(std::exception &e){
|
||||
// expected
|
||||
}
|
||||
ASSERT_EQUALS(s3fs_strtoofft("A", /*is_base_16=*/ true), static_cast<off_t>(10L));
|
||||
ASSERT_EQUALS(s3fs_strtoofft("F", /*is_base_16=*/ true), static_cast<off_t>(15L));
|
||||
ASSERT_EQUALS(s3fs_strtoofft("a", /*is_base_16=*/ true), static_cast<off_t>(10L));
|
||||
|
Loading…
Reference in New Issue
Block a user