// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // Date: Mon. Apr. 18 19:52:34 CST 2011 #include #ifndef BUTIL_STRING_SPLITTER_INL_H #define BUTIL_STRING_SPLITTER_INL_H namespace butil { StringSplitter::StringSplitter(const char* str_begin, const char* str_end, const char sep, EmptyFieldAction action) : _head(str_begin) , _str_tail(str_end) , _sep(sep) , _empty_field_action(action) { init(); } StringSplitter::StringSplitter(const char* str, char sep, EmptyFieldAction action) : StringSplitter(str, NULL, sep, action) {} StringSplitter::StringSplitter(const StringPiece& input, char sep, EmptyFieldAction action) : StringSplitter(input.data(), input.data() + input.length(), sep, action) {} void StringSplitter::init() { // Find the starting _head and _tail. if (__builtin_expect(_head != NULL, 1)) { if (_empty_field_action == SKIP_EMPTY_FIELD) { for (; not_end(_head) && *_head == _sep; ++_head) {} } for (_tail = _head; not_end(_tail) && *_tail != _sep; ++_tail) {} } else { _tail = NULL; } } StringSplitter& StringSplitter::operator++() { if (__builtin_expect(_tail != NULL, 1)) { if (not_end(_tail)) { ++_tail; if (_empty_field_action == SKIP_EMPTY_FIELD) { for (; not_end(_tail) && *_tail == _sep; ++_tail) {} } } _head = _tail; for (; not_end(_tail) && *_tail != _sep; ++_tail) {} } return *this; } StringSplitter StringSplitter::operator++(int) { StringSplitter tmp = *this; operator++(); return tmp; } StringSplitter::operator const void*() const { return (_head != NULL && not_end(_head)) ? _head : NULL; } const char* StringSplitter::field() const { return _head; } size_t StringSplitter::length() const { return static_cast(_tail - _head); } StringPiece StringSplitter::field_sp() const { return StringPiece(field(), length()); } bool StringSplitter::not_end(const char* p) const { return (_str_tail == NULL) ? *p : (p != _str_tail); } int StringSplitter::to_int8(int8_t* pv) const { long v = 0; if (to_long(&v) == 0 && v >= -128 && v <= 127) { *pv = (int8_t)v; return 0; } return -1; } int StringSplitter::to_uint8(uint8_t* pv) const { unsigned long v = 0; if (to_ulong(&v) == 0 && v <= 255) { *pv = (uint8_t)v; return 0; } return -1; } int StringSplitter::to_int(int* pv) const { long v = 0; if (to_long(&v) == 0 && v >= INT_MIN && v <= INT_MAX) { *pv = (int)v; return 0; } return -1; } int StringSplitter::to_uint(unsigned int* pv) const { unsigned long v = 0; if (to_ulong(&v) == 0 && v <= UINT_MAX) { *pv = (unsigned int)v; return 0; } return -1; } int StringSplitter::to_long(long* pv) const { char* endptr = NULL; *pv = strtol(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringSplitter::to_ulong(unsigned long* pv) const { char* endptr = NULL; *pv = strtoul(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringSplitter::to_longlong(long long* pv) const { char* endptr = NULL; *pv = strtoll(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringSplitter::to_ulonglong(unsigned long long* pv) const { char* endptr = NULL; *pv = strtoull(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringSplitter::to_float(float* pv) const { char* endptr = NULL; *pv = strtof(field(), &endptr); return (endptr == field() + length()) ? 0 : -1; } int StringSplitter::to_double(double* pv) const { char* endptr = NULL; *pv = strtod(field(), &endptr); return (endptr == field() + length()) ? 0 : -1; } StringMultiSplitter::StringMultiSplitter ( const char* str, const char* seps, EmptyFieldAction action) : _head(str) , _str_tail(NULL) , _seps(seps) , _empty_field_action(action) { init(); } StringMultiSplitter::StringMultiSplitter ( const char* str_begin, const char* str_end, const char* seps, EmptyFieldAction action) : _head(str_begin) , _str_tail(str_end) , _seps(seps) , _empty_field_action(action) { init(); } void StringMultiSplitter::init() { if (__builtin_expect(_head != NULL, 1)) { if (_empty_field_action == SKIP_EMPTY_FIELD) { for (; not_end(_head) && is_sep(*_head); ++_head) {} } for (_tail = _head; not_end(_tail) && !is_sep(*_tail); ++_tail) {} } else { _tail = NULL; } } StringMultiSplitter& StringMultiSplitter::operator++() { if (__builtin_expect(_tail != NULL, 1)) { if (not_end(_tail)) { ++_tail; if (_empty_field_action == SKIP_EMPTY_FIELD) { for (; not_end(_tail) && is_sep(*_tail); ++_tail) {} } } _head = _tail; for (; not_end(_tail) && !is_sep(*_tail); ++_tail) {} } return *this; } StringMultiSplitter StringMultiSplitter::operator++(int) { StringMultiSplitter tmp = *this; operator++(); return tmp; } bool StringMultiSplitter::is_sep(char c) const { for (const char* p = _seps; *p != '\0'; ++p) { if (c == *p) { return true; } } return false; } StringMultiSplitter::operator const void*() const { return (_head != NULL && not_end(_head)) ? _head : NULL; } const char* StringMultiSplitter::field() const { return _head; } size_t StringMultiSplitter::length() const { return static_cast(_tail - _head); } StringPiece StringMultiSplitter::field_sp() const { return StringPiece(field(), length()); } bool StringMultiSplitter::not_end(const char* p) const { return (_str_tail == NULL) ? *p : (p != _str_tail); } int StringMultiSplitter::to_int8(int8_t* pv) const { long v = 0; if (to_long(&v) == 0 && v >= -128 && v <= 127) { *pv = (int8_t)v; return 0; } return -1; } int StringMultiSplitter::to_uint8(uint8_t* pv) const { unsigned long v = 0; if (to_ulong(&v) == 0 && v <= 255) { *pv = (uint8_t)v; return 0; } return -1; } int StringMultiSplitter::to_int(int* pv) const { long v = 0; if (to_long(&v) == 0 && v >= INT_MIN && v <= INT_MAX) { *pv = (int)v; return 0; } return -1; } int StringMultiSplitter::to_uint(unsigned int* pv) const { unsigned long v = 0; if (to_ulong(&v) == 0 && v <= UINT_MAX) { *pv = (unsigned int)v; return 0; } return -1; } int StringMultiSplitter::to_long(long* pv) const { char* endptr = NULL; *pv = strtol(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringMultiSplitter::to_ulong(unsigned long* pv) const { char* endptr = NULL; *pv = strtoul(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringMultiSplitter::to_longlong(long long* pv) const { char* endptr = NULL; *pv = strtoll(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringMultiSplitter::to_ulonglong(unsigned long long* pv) const { char* endptr = NULL; *pv = strtoull(field(), &endptr, 10); return (endptr == field() + length()) ? 0 : -1; } int StringMultiSplitter::to_float(float* pv) const { char* endptr = NULL; *pv = strtof(field(), &endptr); return (endptr == field() + length()) ? 0 : -1; } int StringMultiSplitter::to_double(double* pv) const { char* endptr = NULL; *pv = strtod(field(), &endptr); return (endptr == field() + length()) ? 0 : -1; } void KeyValuePairsSplitter::UpdateDelimiterPosition() { const StringPiece key_value_pair(key_and_value()); _delim_pos = key_value_pair.find(_key_value_delim); if (_delim_pos == StringPiece::npos) { _delim_pos = key_value_pair.length(); } } } // namespace butil #endif // BUTIL_STRING_SPLITTER_INL_H