File indexing completed on 2025-02-21 09:30:08
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #pragma once
0017 #ifndef FAST_A_TO_F_H_INCLUDED
0018 #define FAST_A_TO_F_H_INCLUDED
0019
0020 #ifdef __GNUC__
0021 # pragma GCC system_header
0022 #endif
0023
0024 #include <cmath>
0025 #include <limits>
0026 #include <stdint.h>
0027 #include <assimp/defs.h>
0028
0029 #include "StringComparison.h"
0030 #include <assimp/DefaultLogger.hpp>
0031 #include <assimp/Exceptional.h>
0032 #include <assimp/StringUtils.h>
0033
0034 #ifdef _MSC_VER
0035 # include <stdint.h>
0036 #else
0037 # include <assimp/Compiler/pstdint.h>
0038 #endif
0039
0040 namespace Assimp {
0041
0042 static constexpr size_t NumItems = 16;
0043
0044 constexpr double fast_atof_table[NumItems] = {
0045 0.0,
0046 0.1,
0047 0.01,
0048 0.001,
0049 0.0001,
0050 0.00001,
0051 0.000001,
0052 0.0000001,
0053 0.00000001,
0054 0.000000001,
0055 0.0000000001,
0056 0.00000000001,
0057 0.000000000001,
0058 0.0000000000001,
0059 0.00000000000001,
0060 0.000000000000001
0061 };
0062
0063
0064
0065
0066 inline unsigned int strtoul10( const char* in, const char** out=0) {
0067 unsigned int value = 0;
0068
0069 for ( ;; ) {
0070 if ( *in < '0' || *in > '9' ) {
0071 break;
0072 }
0073
0074 value = ( value * 10 ) + ( *in - '0' );
0075 ++in;
0076 }
0077 if ( out ) {
0078 *out = in;
0079 }
0080 return value;
0081 }
0082
0083
0084
0085
0086 inline unsigned int strtoul8( const char* in, const char** out=0) {
0087 unsigned int value( 0 );
0088 for ( ;; ) {
0089 if ( *in < '0' || *in > '7' ) {
0090 break;
0091 }
0092
0093 value = ( value << 3 ) + ( *in - '0' );
0094 ++in;
0095 }
0096 if ( out ) {
0097 *out = in;
0098 }
0099 return value;
0100 }
0101
0102
0103
0104
0105 inline unsigned int strtoul16( const char* in, const char** out=0) {
0106 unsigned int value( 0 );
0107 for ( ;; ) {
0108 if ( *in >= '0' && *in <= '9' ) {
0109 value = ( value << 4u ) + ( *in - '0' );
0110 } else if (*in >= 'A' && *in <= 'F') {
0111 value = ( value << 4u ) + ( *in - 'A' ) + 10;
0112 } else if (*in >= 'a' && *in <= 'f') {
0113 value = ( value << 4u ) + ( *in - 'a' ) + 10;
0114 } else {
0115 break;
0116 }
0117 ++in;
0118 }
0119 if ( out ) {
0120 *out = in;
0121 }
0122 return value;
0123 }
0124
0125
0126
0127
0128
0129 inline unsigned int HexDigitToDecimal(char in) {
0130 unsigned int out( UINT_MAX );
0131 if ( in >= '0' && in <= '9' ) {
0132 out = in - '0';
0133 } else if ( in >= 'a' && in <= 'f' ) {
0134 out = 10u + in - 'a';
0135 } else if ( in >= 'A' && in <= 'F' ) {
0136 out = 10u + in - 'A';
0137 }
0138
0139
0140 return out;
0141 }
0142
0143
0144
0145
0146 inline uint8_t HexOctetToDecimal(const char* in) {
0147 return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]);
0148 }
0149
0150
0151
0152
0153 inline int strtol10( const char* in, const char** out = 0) {
0154 bool inv = (*in=='-');
0155 if ( inv || *in == '+' ) {
0156 ++in;
0157 }
0158
0159 int value = strtoul10(in,out);
0160 if (inv) {
0161 if (value < INT_MAX && value > INT_MIN) {
0162 value = -value;
0163 } else {
0164 ASSIMP_LOG_WARN( "Converting the string \"", in, "\" into an inverted value resulted in overflow." );
0165 }
0166 }
0167 return value;
0168 }
0169
0170
0171
0172
0173
0174
0175
0176 inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) {
0177 if ('0' == in[0]) {
0178 return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out);
0179 }
0180 return strtoul10(in, out);
0181 }
0182
0183
0184
0185
0186
0187 template<typename ExceptionType = DeadlyImportError>
0188 inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) {
0189 unsigned int cur = 0;
0190 uint64_t value = 0;
0191
0192 if ( *in < '0' || *in > '9' ) {
0193
0194 throw ExceptionType("The string \"", ai_str_toprintable(in, (int)strlen(in)), "\" cannot be converted into a value." );
0195 }
0196
0197 for ( ;; ) {
0198 if ( *in < '0' || *in > '9' ) {
0199 break;
0200 }
0201
0202 const uint64_t new_value = ( value * (uint64_t) 10 ) + ( (uint64_t) ( *in - '0' ) );
0203
0204
0205 if ( new_value < value ) {
0206 ASSIMP_LOG_WARN( "Converting the string \"", in, "\" into a value resulted in overflow." );
0207 return 0;
0208 }
0209
0210 value = new_value;
0211
0212 ++in;
0213 ++cur;
0214
0215 if (max_inout && *max_inout == cur) {
0216 if (out) {
0217 while ( *in >= '0' && *in <= '9' ) {
0218 ++in;
0219 }
0220 *out = in;
0221 }
0222
0223 return value;
0224 }
0225 }
0226 if ( out ) {
0227 *out = in;
0228 }
0229
0230 if ( max_inout ) {
0231 *max_inout = cur;
0232 }
0233
0234 return value;
0235 }
0236
0237
0238
0239
0240 template<typename ExceptionType = DeadlyImportError>
0241 inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) {
0242 bool inv = (*in == '-');
0243 if ( inv || *in == '+' ) {
0244 ++in;
0245 }
0246
0247 int64_t value = strtoul10_64<ExceptionType>(in, out, max_inout);
0248 if (inv) {
0249 value = -value;
0250 }
0251 return value;
0252 }
0253
0254
0255 #define AI_FAST_ATOF_RELAVANT_DECIMALS 15
0256
0257
0258
0259
0260
0261
0262 template<typename Real, typename ExceptionType = DeadlyImportError>
0263 inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) {
0264 Real f = 0;
0265
0266 bool inv = (*c == '-');
0267 if (inv || *c == '+') {
0268 ++c;
0269 }
0270
0271 if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) {
0272 out = std::numeric_limits<Real>::quiet_NaN();
0273 c += 3;
0274 return c;
0275 }
0276
0277 if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) {
0278 out = std::numeric_limits<Real>::infinity();
0279 if (inv) {
0280 out = -out;
0281 }
0282 c += 3;
0283 if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) {
0284 c += 5;
0285 }
0286 return c;
0287 }
0288
0289 if (!(c[0] >= '0' && c[0] <= '9') &&
0290 !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) {
0291
0292 throw ExceptionType("Cannot parse string \"", ai_str_toprintable(c, (int)strlen(c)),
0293 "\" as a real number: does not start with digit "
0294 "or decimal point followed by digit.");
0295 }
0296
0297 if (*c != '.' && (! check_comma || c[0] != ',')) {
0298 f = static_cast<Real>( strtoul10_64<ExceptionType> ( c, &c) );
0299 }
0300
0301 if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') {
0302 ++c;
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS;
0313 double pl = static_cast<double>( strtoul10_64<ExceptionType> ( c, &c, &diff ));
0314
0315 pl *= fast_atof_table[diff];
0316 f += static_cast<Real>( pl );
0317 }
0318
0319 else if (*c == '.') {
0320 ++c;
0321 }
0322
0323
0324
0325 if (*c == 'e' || *c == 'E') {
0326 ++c;
0327 const bool einv = (*c=='-');
0328 if (einv || *c=='+') {
0329 ++c;
0330 }
0331
0332
0333
0334
0335 Real exp = static_cast<Real>( strtoul10_64<ExceptionType>(c, &c) );
0336 if (einv) {
0337 exp = -exp;
0338 }
0339 f *= std::pow(static_cast<Real>(10.0), exp);
0340 }
0341
0342 if (inv) {
0343 f = -f;
0344 }
0345 out = f;
0346 return c;
0347 }
0348
0349
0350
0351 template<typename ExceptionType = DeadlyImportError>
0352 inline ai_real fast_atof(const char* c) {
0353 ai_real ret(0.0);
0354 fast_atoreal_move<ai_real, ExceptionType>(c, ret);
0355
0356 return ret;
0357 }
0358
0359 template<typename ExceptionType = DeadlyImportError>
0360 inline
0361 ai_real fast_atof( const char* c, const char** cout) {
0362 ai_real ret(0.0);
0363 *cout = fast_atoreal_move<ai_real, ExceptionType>(c, ret);
0364
0365 return ret;
0366 }
0367
0368 template<typename ExceptionType = DeadlyImportError>
0369 inline ai_real fast_atof( const char** inout) {
0370 ai_real ret(0.0);
0371 *inout = fast_atoreal_move<ai_real, ExceptionType>(*inout, ret);
0372
0373 return ret;
0374 }
0375
0376 }
0377
0378 #endif