[DEV] continue reviewing strings

This commit is contained in:
Edouard DUPIN 2017-08-25 22:45:09 +02:00
parent 7ac3ef06c4
commit 40a9aaba66
6 changed files with 429 additions and 191 deletions

305
etk/Number.cpp Normal file
View File

@ -0,0 +1,305 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license MPL v2.0 (see license file)
*/
#include <etk/Number.hpp>
etk::Number::Number() :
m_negative(false),
m_unit(0),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(int8_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(int16_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(int32_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(int64_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(uint8_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(uint16_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(uint32_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(uint64_t _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(float _value) :
m_negative(false),
m_unit(0),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
m_unit(_value);
_value -= int64_t(_value);
_value *= 10.0;
for (size_t iii=0; iii<64; ++iii) {
if (_value == 0.0) {
return;
}
uint64_t val = _value;
_value = (_value - val) * 10.0;
m_lessZero *= 10;
m_lessZero += val;
m_numberLessZero++;
}
}
etk::Number::Number(double _value) :
m_negative(false),
m_unit(0),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
m_unit(_value);
_value -= int64_t(_value);
_value *= 10.0;
for (size_t iii=0; iii<64; ++iii) {
if (_value == 0.0) {
return;
}
uint64_t val = _value;
_value = (_value - val) * 10.0;
m_lessZero *= 10;
m_lessZero += val;
m_numberLessZero++;
}
}
etk::Number::Number(long double _value) :
m_negative(false),
m_unit(0),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
m_unit(_value);
_value -= int64_t(_value);
_value *= 10.0;
for (size_t iii=0; iii<64; ++iii) {
if (_value == 0.0) {
return;
}
uint64_t val = _value;
_value = (_value - val) * 10.0;
m_lessZero *= 10;
m_lessZero += val;
m_numberLessZero++;
}
}
etk::Number::Number(bool _value) :
m_negative(false),
m_unit(_value),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
}
etk::Number::Number(const etk::UString& _value) :
m_negative(false),
m_unit(0),
m_lessZero(0),
m_numberLessZero(0),
m_exponent(0) {
parse(_value);
}
void etk::Number::clear() {
m_negative = false;
m_unit = 0;
m_lessZero = 0;
m_exponent = 0;
}
bool etk::Number::isDigit(char32_t _value, enum etk::Number::type _type) {
if (_type == type::numberBinary) {
if ( _value == '0'
|| _value == '1') {
return false;
}
return false;
} else if (_type == type::numberHexadecimal) {
if ( _value >= 'A'
&& _value <= 'F') {
return true;
}
if ( _value >= 'a'
&& _value <= 'f') {
return true;
}
}
if ( _value >= '0'
&& _value <= '9') {
return true;
}
return false;
}
bool etk::Number::parse(const etk::UString& _value) {
enum type section = type::numberDecimal;
for (size_t iii=0; iii<_value.size(); ++iii) {
if ( iii == 0
&& _value[iii] == '+') {
// noting to do ==> already positive value
continue;
}
if ( iii == 0
&& _value[iii] == '-') {
m_negative = true;
continue;
}
if ( iii == 1
&& _value[0] == '0'
&& ( _value[1] == 'x'
|| _value[1] == 'X')) {
section = type::numberHexadecimal;
continue;
}
if ( iii == 1
&& _value[0] == '0'
&& ( _value[1] == 'b'
|| _value[1] == 'B')) {
section = type::numberBinary;
continue;
}
if (_value[iii] == '.') {
if (section == type::numberDecimal) {
section = type::numberLessZero;
continue;
}
TK_ERROR("Can not parse the Number '" << _value << "':" << iii << " '.' can not parse");
return false;
}
if (_value[iii] == 'e') {
if ( section == type::numberDecimal
|| section == type::numberLessZero) {
section = type::numberExponent;
continue;
}
TK_ERROR("Can not parse the Number '" << _value << "':" << iii << " 'e' ==> can not parse ...");
return false;
}
if (isDigit(_value[iii], section) == true) {
// TODO: Check too big number
if (section == type::numberDecimal) {
m_unit = (m_unit*10) + (_value[iii]-'0');
} else if (section == type::numberBinary) {
m_unit = (m_unit<<1) + (_value[iii]-'0');
} else if (section == type::numberHexadecimal) {
if (_value[iii] <= 'F') {
m_unit = (m_unit*16) + (_value[iii]-'A' + 10);
} else if (_value[iii] <= 'f') {
m_unit = (m_unit*16) + (_value[iii]-'a' + 10);
} else {
m_unit = (m_unit*16) + (_value[iii]-'0');
}
} else if (section == type::numberLessZero) {
m_lessZero = (m_lessZero*10) + (_value[iii]-'0');
m_numberLessZero++;
} else {
m_exponent = (m_exponent*10) + (_value[iii]-'0');
}
} else {
return false;
}
}
return false;
}
long double etk::Number::getDouble() {
long double out = 0;
out = m_lessZero;
out *= pow(10,-m_numberLessZero);
out += m_unit;
out *= pow(10,m_exponent);
if (m_negative == true) {
out *= -1.0;
}
return -1;
}
uint64_t etk::Number::getU64() {
uint64_t out = 0;
if (m_exponent != 0) {
// Auto manage exponent
long double tmp = getDouble();
if (tmp <= 0.0) {
return 0;
}
return uint64_t(tmp);
}
out += m_unit;
if (m_negative == true) {
return 0;
}
return out;
}
int64_t etk::Number::getI64() {
int64_t out = 0;
if (m_exponent != 0) {
// Auto manage exponent
long double tmp = getDouble();
if (tmp <= 0.0) {
return 0;
}
return int64_t(tmp);
}
out += m_unit;
if (m_negative == true) {
out *= -1.0;
}
return out;
}

67
etk/Number.hpp Normal file
View File

@ -0,0 +1,67 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/String.hpp>
#include <etk/UString.hpp>
namespace etk {
struct Number {
protected:
bool m_negative;
uint64_t m_unit;
uint64_t m_lessZero;
uint64_t m_numberLessZero;
uint32_t m_exponent;
public:
enum class type {
numberDecimal,
numberBinary,
numberHexadecimal,
numberLessZero,
numberExponent,
};
Number();
Number(int8_t _value);
Number(int16_t _value);
Number(int32_t _value);
Number(int64_t _value);
Number(uint8_t _value);
Number(uint16_t _value);
Number(uint32_t _value);
Number(uint64_t _value);
Number(float _value);
Number(double _value);
Number(long double _value);
Number(bool _value);
Number(const etk::UString& _value);
void clear();
bool isDigit(char32_t _value, enum type _type);
// Format:
// 51651
// -455465
// +54654
// 51651.545
// -455465.4845
// +54654.485424
// 51651e12
// -455465e12
// +54654e12
// 51651.545e12
// -455465.4845e12
// +54654.485424e12
// 0x123456789ABCDEF
// 0b10101110101010
bool parse(const etk::UString& _value);
long double getDouble();
uint64_t getU64();
int64_t getI64();
};
}

View File

@ -1,6 +1,7 @@
#include <etk/UString.hpp>
#include <etk/Number.hpp>
etk::UString::UString():
m_data() {
@ -456,182 +457,70 @@ bool etk::UString::startWith(const etk::UString& _val, bool _caseSensitive) cons
return true;
}
struct Number {
public:
bool m_negative;
uint64_t m_unit;
uint64_t m_lessZero;
uint32_t m_exponent;
Number() :
m_negative(false),
m_unit(0),
m_lessZero(0),
m_exponent(0) {
}
void clear() {
m_negative = false;
m_unit = 0;
m_lessZero = 0;
m_exponent = 0;
}
bool isDigit(char32_t _value) {
if (_value < '0') {
return false;
}
if (_value > '9') {
return false;
}
return true;
}
// Format:
// 51651
// -455465
// +54654
// 51651.545
// -455465.4845
// +54654.485424
// 51651e12
// -455465e12
// +54654e12
// 51651.545e12
// -455465.4845e12
// +54654.485424e12
// 0x123456789ABCDEF
bool parse(const etk::UString& _value) {
int8_t section = 0;
for (size_t iii=0; iii<_value.size(); ++iii) {
if ( iii == 0
&& _value[iii] == "+") {
// noting to do ==> already positive value
continue;
}
if ( iii == 0
&& _value[iii] == "-") {
m_negative = true;
continue;
}
if (_value[iii] == ".") {
if (section == 0) {
section = 1;
continue;
}
TK_ERROR("Can not parse the Number '" << _value << "':" << iii << " '.' can not parse");
return false;
}
if (_value[iii] == "e") {
if ( section == 0
|| section == 1) {
section = 2;
continue;
}
TK_ERROR("Can not parse the Number '" << _value << "':" << iii << " 'e' ==> can not parse ...");
return false;
}
if (isDigit(_value[iii]) == true) {
// TODO: Check too big number
if (section == 0) {
m_unit = m_unit*10 + (_value[iii]-'0');
} else if (section == 0) {
m_lessZero = m_lessZero*10 + (_value[iii]-'0');
} else {
m_exponent = m_exponent*10 + (_value[iii]-'0');
}
}
}
return false;
}
};
template <>
long double etk::UString::to<long double>() const {
long double ret = 0;
sscanf(c_str(), "%Lf", &ret);
return ret;
etk::Number value(*this);
return value.getDouble();
}
template <>
double etk::UString::to<double>() const {
double ret = 0;
sscanf(c_str(), "%lf", &ret);
return ret;
etk::Number value(*this);
return value.getDouble();
}
template <>
float etk::UString::to<float>() const {
float ret = 0;
sscanf(c_str(), "%f", &ret);
return ret;
etk::Number value(*this);
return value.getDouble();
}
template <>
int8_t etk::UString::to<int8_t>() const {
int ret = 0;
sscanf(c_str(), "%d", &ret);
return ret;
etk::Number value(*this);
return value.getI64();
}
template <>
int16_t etk::UString::to<int16_t>() const {
int ret = 0;
sscanf(c_str(), "%d", &ret);
return ret;
etk::Number value(*this);
return value.getI64();
}
template <>
int32_t etk::UString::to<int32_t>() const {
int ret = 0;
sscanf(c_str(), "%d", &ret);
return ret;
etk::Number value(*this);
return value.getI64();
}
template <>
int64_t etk::UString::to<int64_t>() const {
int64_t ret = 0;
#if ( defined(__TARGET_OS__Android) \
|| defined(__TARGET_OS__Windows) \
|| defined(__TARGET_OS__MacOs) \
|| defined(__TARGET_OS__IOs))
sscanf(c_str(), "%lld", &ret);
#else
sscanf(c_str(), "%ld", &ret);
#endif
return ret;
etk::Number value(*this);
return value.getI64();
}
template <>
uint8_t etk::UString::to<uint8_t>() const {
int ret = 0;
sscanf(c_str(), "%d", &ret);
return ret;
etk::Number value(*this);
return value.getU64();
}
template <>
uint16_t etk::UString::to<uint16_t>() const {
int ret = 0;
sscanf(c_str(), "%d", &ret);
return ret;
etk::Number value(*this);
return value.getU64();
}
template <>
uint32_t etk::UString::to<uint32_t>() const {
int ret = 0;
sscanf(c_str(), "%d", &ret);
return ret;
etk::Number value(*this);
return value.getU64();
}
template <>
uint64_t etk::UString::to<uint64_t>() const {
uint64_t ret = 0;
#if ( defined(__TARGET_OS__Android) \
|| defined(__TARGET_OS__Windows) \
|| defined(__TARGET_OS__MacOs) \
|| defined(__TARGET_OS__IOs))
sscanf(c_str(), "%llu", &ret);
#else
sscanf(c_str(), "%lu", &ret);
#endif
return ret;
etk::Number value(*this);
return value.getU64();
}
template <>
@ -740,84 +629,57 @@ namespace etk {
}
template<>
etk::UString etk::toString(const bool& _val) {
if (_val == true) {
return "true";
}
return "false";
etk::UString etk::toUString(const bool& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const int8_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%d", _val);
return tmpVal;
etk::UString etk::toUString(const int8_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const int16_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%d", _val);
return tmpVal;
etk::UString etk::toUString(const int16_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const int32_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%d", _val);
return tmpVal;
etk::UString etk::toUString(const int32_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const int64_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%lld", _val);
return tmpVal;
etk::UString etk::toUString(const int64_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const uint8_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%u", _val);
return tmpVal;
etk::UString etk::toUString(const uint8_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const uint16_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%u", _val);
return tmpVal;
etk::UString etk::toUString(const uint16_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const uint32_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%u", _val);
return tmpVal;
etk::UString etk::toUString(const uint32_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const uint64_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%llu", _val);
return tmpVal;
etk::UString etk::toUString(const uint64_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const size_t& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%zu", _val);
return tmpVal;
etk::UString etk::toUString(const size_t& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const float& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%f", _val);
return tmpVal;
etk::UString etk::toUString(const float& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const double& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%f", _val);
return tmpVal;
etk::UString etk::toUString(const double& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
template<>
etk::UString etk::toString(const long double& _val) {
char32_t tmpVal[256];
sprintf(tmpVal, "%Lf", _val);
return tmpVal;
etk::UString etk::toUString(const long double& _val) {
return utf8::convertUnicode(etk::toString(_val));
}
size_t etk::UString::find(char32_t _value, size_t _pos) const {
@ -932,10 +794,10 @@ etk::UString etk::UString::getLine(int32_t _pos) const {
if (startPos == etk::UString::npos) {
startPos = 0;
} else if (startPos >= size() ) {
return "";
return U"";
}
if (stopPos == etk::UString::npos) {
return "";
return U"";
} else if (stopPos >= size() ) {
stopPos = size();
}

View File

@ -7,6 +7,7 @@
#include <etk/math/Vector3D.hpp>
#include <etk/types.hpp>
#include <etk/String.hpp>
#include <etk/UString.hpp>
#pragma once
@ -71,7 +72,7 @@ namespace etk {
*/
Vector2D(const etk::String& _str);
#if __CPP_VERSION__ >= 2011
Vector2D(const std::u32string& _str);
Vector2D(const etk::UString& _str);
#endif
/**
* @brief Operator= Asign the current object with an other object
@ -552,7 +553,7 @@ namespace etk {
* @brief String caster of the object.
* @return the Object cated in string (x.x,y.y)
*/
operator std::u32string() const;
operator etk::UString() const;
#endif
};
//! @not_in_doc

View File

@ -6,6 +6,8 @@
#include <etk/types.hpp>
#include <etk/debug.hpp>
#include <etk/UString.hpp>
#include <etk/String.hpp>
#pragma once

View File

@ -9,6 +9,7 @@
#pragma once
#include <etk/String.hpp>
#include <etk/UString.hpp>
namespace etk {
/**