00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "FUtils/FUDateTime.h"
00010 #include <limits>
00011
00012
00013
00014
00015
00016
00017 #define SPACE builder.append((CH) ' ')
00018 #define VAL(x) builder.append(x)
00019
00020
00021 template<class CH>
00022 FCOLLADA_EXPORT bool FUStringConversion::ToBoolean(const CH* value)
00023 {
00024 return value != NULL && *value != 0 && *value != '0' && *value != 'f' && *value != 'F';
00025 }
00026
00027
00028 template <class CH>
00029 FCOLLADA_EXPORT int32 FUStringConversion::ToInt32(const CH** value)
00030 {
00031 if (!*value) return 0;
00032
00033
00034 const CH* s = *value;
00035 CH c;
00036 while ((c = *s) != 0 && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) { ++s; }
00037
00038 int32 val = 0;
00039 int32 sign = 1;
00040 if (*s == '-') { ++s; sign = -1; }
00041
00042 while ((c = *s) != 0)
00043 {
00044 if (c >= '0' && c <= '9') val = val * 10 + c - '0';
00045 else break;
00046 ++s;
00047 }
00048 val *= sign;
00049 while ((c = *s) != '\0' && (c != ' ' && c != '\t' && c != '\n')) s++;
00050 while ((c = *s) != '\0' && (c == ' ' || c == '\t' || c == '\n')) s++;
00051 *value = s;
00052 return val;
00053 }
00054
00055
00056 template<class CH>
00057 FCOLLADA_EXPORT float FUStringConversion::ToFloat(const CH** value)
00058 {
00059 const CH* s = *value;
00060 if (s == NULL || *s == 0) return 0.0f;
00061
00062
00063 CH c;
00064 while ((c = *s) != 0 && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) { ++s; }
00065
00066
00067 double val = 0.0;
00068 float sign = 1.0;
00069 if (*s == '-') { ++s; sign = -1.0; }
00070 float decimals = 0.0;
00071 int32 exponent = 0;
00072 bool infinity = false;
00073 bool nonValidFound = false;
00074 while ((c = *s) != 0 && !nonValidFound)
00075 {
00076 switch (c)
00077 {
00078 case '.': decimals = 1; break;
00079 case '0': val *= 10.0; decimals *= 10.0; break;
00080 case '1': val = val * 10.0 + 1.0; decimals *= 10.0; break;
00081 case '2': val = val * 10.0 + 2.0; decimals *= 10.0; break;
00082 case '3': val = val * 10.0 + 3.0; decimals *= 10.0; break;
00083 case '4': val = val * 10.0 + 4.0; decimals *= 10.0; break;
00084 case '5': val = val * 10.0 + 5.0; decimals *= 10.0; break;
00085 case '6': val = val * 10.0 + 6.0; decimals *= 10.0; break;
00086 case '7': val = val * 10.0 + 7.0; decimals *= 10.0; break;
00087 case '8': val = val * 10.0 + 8.0; decimals *= 10.0; break;
00088 case '9': val = val * 10.0 + 9.0; decimals *= 10.0; break;
00089 case 'e':
00090 case 'E': ++s; exponent = ToInt32(&s); s -= 2; nonValidFound = true; break;
00091 case 'I': infinity = true;
00092 default: nonValidFound = true; --s; break;
00093 }
00094 ++s;
00095 }
00096
00097 float out = 0.0f;
00098 if (infinity)
00099 {
00100 infinity = false;
00101 c = *(s++);
00102 if (c != 'I') infinity = false;
00103 else
00104 {
00105 c = *(s++);
00106 if (c != 'N') infinity = false;
00107 else
00108 {
00109 c = *(s++);
00110 if (c != 'F') infinity = false;
00111 else out = std::numeric_limits<float>::infinity() * ((float) sign);
00112 }
00113 }
00114 }
00115 if (!infinity)
00116 {
00117
00118 if (decimals == 0.0) decimals = 1.0;
00119 out = (float) (val * sign / decimals);
00120 if (exponent != 0) out *= powf(10.0f, (float) exponent);
00121 }
00122
00123
00124 while ((c = *s) != 0 && c != ' ' && c != '\t' && c != '\r' && c != '\n') { ++s; }
00125 while ((c = *s) != 0 && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) { ++s; }
00126
00127 *value = s;
00128 return out;
00129 }
00130
00131
00132 template<class CH>
00133 FCOLLADA_EXPORT uint32 FUStringConversion::ToUInt32(const CH** value)
00134 {
00135 if (value == NULL || *value == NULL || **value == 0) return 0;
00136
00137
00138 const CH* s = *value;
00139 CH c;
00140 while ((c = *s) != 0 && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) { ++s; }
00141
00142 uint32 val = 0;
00143 while ((c = *s) != 0)
00144 {
00145 if (c >= '0' && c <= '9') val = val * 10 + c - '0';
00146 else break;
00147 ++s;
00148 }
00149
00150 while ((c = *s) != '\0' && (c != ' ' && c != '\t' && c != '\n')) s++;
00151 while ((c = *s) != '\0' && (c == ' ' || c == '\t' || c == '\n')) s++;
00152 *value = s;
00153 return val;
00154 }
00155
00156 template<class CH>
00157 FCOLLADA_EXPORT uint32 FUStringConversion::HexToUInt32(const CH** value, uint32 count)
00158 {
00159 if (value == NULL || *value == NULL || **value == 0) return 0;
00160
00161 const CH* s = *value;
00162 CH c;
00163
00164
00165 if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) s += 2;
00166
00167 uint32 val = 0;
00168 for (uint32 i = 0; i < count && (c = *s) != 0; ++i)
00169 {
00170 if (c >= '0' && c <= '9') val = val * 16 + c - '0';
00171 else if (c >= 'A' && c <= 'F') val = val * 16 + c + 10 - 'A';
00172 else if (c >= 'a' && c <= 'f') val = val * 16 + c + 10 - 'a';
00173 else break;
00174 ++s;
00175 }
00176
00177 *value = s;
00178 return val;
00179 }
00180
00181 template<class CH>
00182 FCOLLADA_EXPORT void FUStringConversion::ToMatrix(const CH** s, FMMatrix44& mx)
00183 {
00184 if (s != NULL && *s != NULL && **s != 0)
00185 {
00186
00187 mx[0][0] = ToFloat(s); mx[1][0] = ToFloat(s); mx[2][0] = ToFloat(s); mx[3][0] = ToFloat(s);
00188 mx[0][1] = ToFloat(s); mx[1][1] = ToFloat(s); mx[2][1] = ToFloat(s); mx[3][1] = ToFloat(s);
00189 mx[0][2] = ToFloat(s); mx[1][2] = ToFloat(s); mx[2][2] = ToFloat(s); mx[3][2] = ToFloat(s);
00190 mx[0][3] = ToFloat(s); mx[1][3] = ToFloat(s); mx[2][3] = ToFloat(s); mx[3][3] = ToFloat(s);
00191 }
00192 }
00193
00194 template<class CH>
00195 FCOLLADA_EXPORT void FUStringConversion::ToDateTime(const CH* value, FUDateTime& dateTime)
00196 {
00197
00198 size_t length;
00199 const CH* c = value;
00200 for (length = 0; *c != 0; ++length) ++c;
00201
00202 if (length == 20)
00203 {
00204 dateTime.SetYear(ToUInt32(value)); value += 5;
00205 dateTime.SetMonth(ToUInt32(value)); value += 3;
00206 dateTime.SetDay(ToUInt32(value)); value += 3;
00207 dateTime.SetHour(ToUInt32(value)); value += 3;
00208 dateTime.SetMinutes(ToUInt32(value)); value += 3;
00209 dateTime.SetSeconds(ToUInt32(value));
00210 }
00211 }
00212
00213
00214 template<class CH>
00215 FCOLLADA_EXPORT FMVector2 FUStringConversion::ToVector2(const CH** value)
00216 {
00217 FMVector2 p;
00218 if (value != NULL && *value != NULL && **value != 0)
00219 {
00220 p.x = ToFloat(value);
00221 p.y = ToFloat(value);
00222 }
00223 return p;
00224 }
00225
00226 template<class CH>
00227 FCOLLADA_EXPORT FMVector3 FUStringConversion::ToVector3(const CH** value)
00228 {
00229 FMVector3 p;
00230 if (value != NULL && *value != NULL && **value != 0)
00231 {
00232 p.x = ToFloat(value);
00233 p.y = ToFloat(value);
00234 p.z = ToFloat(value);
00235 }
00236 return p;
00237 }
00238
00239 template<class CH>
00240 FCOLLADA_EXPORT FMVector4 FUStringConversion::ToVector4(const CH** value)
00241 {
00242 FMVector4 p;
00243 if (value != NULL && *value != NULL && **value != 0)
00244 {
00245 p.x = ToFloat(value);
00246 p.y = ToFloat(value);
00247 p.z = ToFloat(value);
00248
00249
00250 p.w = (*value != NULL && **value != 0) ? ToFloat(value) : 1.0f;
00251 }
00252 return p;
00253 }
00254
00255
00256 template <class CH>
00257 FCOLLADA_EXPORT void FUStringConversion::ToString(FUStringBuilderT<CH>& builder, const FMMatrix44& m)
00258 {
00259 VAL(m[0][0]); SPACE; VAL(m[1][0]); SPACE; VAL(m[2][0]); SPACE; VAL(m[3][0]); SPACE;
00260 VAL(m[0][1]); SPACE; VAL(m[1][1]); SPACE; VAL(m[2][1]); SPACE; VAL(m[3][1]); SPACE;
00261 VAL(m[0][2]); SPACE; VAL(m[1][2]); SPACE; VAL(m[2][2]); SPACE; VAL(m[3][2]); SPACE;
00262 VAL(m[0][3]); SPACE; VAL(m[1][3]); SPACE; VAL(m[2][3]); SPACE; VAL(m[3][3]);
00263 }
00264
00265 template <class CH>
00266 FCOLLADA_EXPORT void FUStringConversion::ToString(FUStringBuilderT<CH>& builder, const FMVector2& p)
00267 {
00268 VAL(p.u); SPACE; VAL(p.v);
00269 }
00270
00271 template <class CH>
00272 FCOLLADA_EXPORT void FUStringConversion::ToString(FUStringBuilderT<CH>& builder, const FMVector3& p)
00273 {
00274 VAL(p.x); SPACE; VAL(p.y); SPACE; VAL(p.z);
00275 }
00276
00277 template <class CH>
00278 FCOLLADA_EXPORT void FUStringConversion::ToString(FUStringBuilderT<CH>& builder, const FMVector4& p)
00279 {
00280 VAL(p.x); SPACE; VAL(p.y); SPACE; VAL(p.z); SPACE; VAL(p.w);
00281 }
00282
00283 template <class CH>
00284 FCOLLADA_EXPORT size_t FUStringConversion::CountValues(const CH* sz)
00285 {
00286 size_t count = 0;
00287 if (sz != NULL && *sz > 0)
00288 {
00289 while (*sz != 0)
00290 {
00291
00292 while (*sz != 0 && (*sz == ' ' || *sz == '\t' || *sz == '\r' || *sz == '\n')) ++sz;
00293 if (*sz == 0) break;
00294
00295
00296 ++count;
00297 while (*sz != 0 && *sz != ' ' && *sz != '\t' && *sz != '\r' && *sz != '\n') ++sz;
00298 }
00299 }
00300 return count;
00301 }
00302
00303 #ifdef HAS_VECTORTYPES
00304
00305 template<class CH>
00306 FCOLLADA_EXPORT void FUStringConversion::ToBooleanList(const CH* value, BooleanList& array)
00307 {
00308 const CH* s = value;
00309 CH c = *s;
00310 array.clear();
00311
00312
00313 while ((c = *s) != 0 && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) { ++s; }
00314
00315 while (*s != 0)
00316 {
00317
00318 array.push_back(ToBoolean(s));
00319
00320
00321 while ((c = *s) != 0 && c != ' ' && c != '\t' && c != '\r' && c != '\n') { ++s; }
00322
00323
00324 while ((c = *s) != 0 && (c == ' ' || c == '\t' || c == '\r' || c == '\n')) { ++s; }
00325 }
00326 }
00327
00328
00329 template<class CH>
00330 FCOLLADA_EXPORT void FUStringConversion::ToInt32List(const CH* value, Int32List& array)
00331 {
00332 size_t length = 0;
00333 if (value != NULL && *value != 0)
00334 {
00335
00336 size_t oldLength = array.size();
00337 for (; length < oldLength && *value != 0; ++length) array[length] = ToInt32(&value);
00338
00339
00340 size_t count = CountValues(value);
00341 if (count > 0) array.reserve(oldLength + count);
00342 while (*value != 0) { array.push_back(ToInt32(&value)); ++length; }
00343 }
00344 if (length != array.size()) array.resize(length);
00345 }
00346
00347
00348 template<class CH>
00349 FCOLLADA_EXPORT void FUStringConversion::ToUInt32List(const CH* value, UInt32List& array)
00350 {
00351 size_t length = 0;
00352 if (value != NULL && *value != 0)
00353 {
00354
00355 size_t oldLength = array.size();
00356 for (; length < oldLength && *value != 0; ++length) array[length] = ToUInt32(&value);
00357
00358
00359 size_t count = CountValues(value);
00360 if (count > 0) array.reserve(oldLength + count);
00361 while (*value != 0) { array.push_back(ToUInt32(&value)); ++length; }
00362 }
00363 if (length != array.size()) array.resize(length);
00364 }
00365
00366
00367 template<class CH>
00368 FCOLLADA_EXPORT void FUStringConversion::ToFloatList(const CH* value, FloatList& array)
00369 {
00370 size_t length = 0;
00371 if (value != NULL && *value != 0)
00372 {
00373
00374 size_t oldLength = array.size();
00375 for (; length < oldLength && *value != 0; ++length) array[length] = ToFloat(&value);
00376
00377
00378 size_t count = CountValues(value);
00379 if (count > 0) array.reserve(oldLength + count);
00380 while (*value != 0) { array.push_back(ToFloat(&value)); ++length; }
00381 }
00382 if (length != array.size()) array.resize(length);
00383 }
00384
00385
00386 template<class CH>
00387 FCOLLADA_EXPORT void FUStringConversion::ToInterleavedFloatList(const CH* value, fm::pvector<FloatList>& arrays)
00388 {
00389 size_t stride = arrays.size();
00390 size_t validCount = 0;
00391 if (value != NULL && *value != 0 && stride > 0)
00392 {
00393 size_t length = arrays[0]->size();
00394 for (size_t count = 0; count < length && *value != 0; ++count, ++validCount)
00395 {
00396 for (size_t i = 0; i < stride && *value != 0; ++i)
00397 {
00398 FloatList* array = arrays[i];
00399 if (array != NULL) array->at(count) = ToFloat(&value);
00400 else ToFloat(&value);
00401 }
00402 }
00403
00404 if (*value != 0)
00405 {
00406
00407 size_t additional = (CountValues(value) + stride - 1) / stride;
00408 for (size_t i = 0; i < stride && *value != 0; ++i)
00409 {
00410 FloatList* array = arrays[i];
00411 if (array != NULL) array->reserve(array->size() + additional);
00412 }
00413
00414
00415 while (*value != 0)
00416 {
00417 size_t i = 0;
00418 for (; i < stride && *value != 0; ++i)
00419 {
00420 FloatList* array = arrays[i];
00421 if (array != NULL) array->push_back(ToFloat(&value));
00422 else ToFloat(&value);
00423 }
00424 if (i == stride) ++validCount;
00425 }
00426 }
00427 }
00428
00429 for (size_t i = 0; i < stride; ++i)
00430 {
00431 if (arrays[i] != NULL) arrays[i]->resize(validCount);
00432 }
00433 }
00434
00435 template <class CH>
00436 FCOLLADA_EXPORT void FUStringConversion::ToInterleavedUInt32List(const CH* value, fm::pvector<UInt32List>& arrays)
00437 {
00438 size_t stride = arrays.size();
00439 size_t validCount = 0;
00440 if (value != NULL && *value != 0 && stride > 0)
00441 {
00442 size_t length = arrays[0]->size();
00443 for (size_t count = 0; count < length && *value != 0; ++count, ++validCount)
00444 {
00445 for (size_t i = 0; i < stride && *value != 0; ++i)
00446 {
00447 UInt32List* array = arrays[i];
00448 if (array != NULL) array->at(count) = ToUInt32(&value);
00449 else ToUInt32(&value);
00450 }
00451 }
00452
00453 if (*value != 0)
00454 {
00455
00456 size_t additional = (CountValues(value) + stride - 1) / stride;
00457 for (size_t i = 0; i < stride && *value != 0; ++i)
00458 {
00459 UInt32List* array = arrays[i];
00460 if (array != NULL) array->reserve(array->size() + additional);
00461 }
00462
00463
00464 while (*value != 0)
00465 {
00466 size_t i = 0;
00467 for (; i < stride && *value != 0; ++i)
00468 {
00469 UInt32List* array = arrays[i];
00470 if (array != NULL) array->push_back(ToUInt32(&value));
00471 else ToUInt32(&value);
00472 }
00473 if (i == stride) ++validCount;
00474 }
00475 }
00476 }
00477
00478 for (size_t i = 0; i < stride; ++i)
00479 {
00480 if (arrays[i] != NULL) arrays[i]->resize(validCount);
00481 }
00482 }
00483
00484
00485 template<class CH>
00486 FCOLLADA_EXPORT void FUStringConversion::ToMatrixList(const CH* value, FMMatrix44List& array)
00487 {
00488 size_t count = 0;
00489 if (value != NULL && *value != 0)
00490 {
00491 size_t length = array.size();
00492 for (; count < length && *value != 0; ++count)
00493 {
00494 ToMatrix(&value, array[count]);
00495 }
00496
00497 while (*value != 0)
00498 {
00499 FMMatrix44List::iterator it = array.insert(array.end(), FMMatrix44::Identity);
00500 ToMatrix(&value, *it);
00501 ++count;
00502 }
00503 }
00504 array.resize(count);
00505 }
00506
00507 template<class CH>
00508 FCOLLADA_EXPORT void FUStringConversion::ToVector2List(const CH* value, FMVector2List& array)
00509 {
00510 size_t count = 0;
00511 if (value != NULL && *value != 0)
00512 {
00513 size_t length = array.size();
00514 for (; count < length && *value != 0; ++count)
00515 {
00516 array[count] = ToVector2(&value);
00517 }
00518
00519 while (*value != 0) { array.push_back(ToVector2(&value)); ++count; }
00520 }
00521 array.resize(count);
00522 }
00523
00524 template<class CH>
00525 FCOLLADA_EXPORT void FUStringConversion::ToVector3List(const CH* value, FMVector3List& array)
00526 {
00527 size_t count = 0;
00528 if (value != NULL && *value != 0)
00529 {
00530 size_t length = array.size();
00531 for (; count < length && *value != 0; ++count)
00532 {
00533 array[count] = ToVector3(&value);
00534 }
00535
00536 while (*value != 0) { array.push_back(ToVector3(&value)); ++count; }
00537 }
00538 array.resize(count);
00539 }
00540
00541 template<class CH>
00542 FCOLLADA_EXPORT void FUStringConversion::ToVector4List(const CH* value, FMVector4List& array)
00543 {
00544 size_t count = 0;
00545 if (value != NULL && *value != 0)
00546 {
00547 size_t length = array.size();
00548 for (; count < length && *value != 0; ++count)
00549 {
00550 array[count] = ToVector4(&value);
00551 }
00552
00553 while (*value != 0) { array.push_back(ToVector4(&value)); ++count; }
00554 }
00555 array.resize(count);
00556 }
00557
00558 template <class CH>
00559 FCOLLADA_EXPORT void FUStringConversion::ToString(FUStringBuilderT<CH>& builder, const FloatList& values)
00560 {
00561 if (values.empty()) return;
00562 if (!builder.empty()) SPACE;
00563 FloatList::const_iterator itV = values.begin();
00564 builder.append(*itV);
00565 for (++itV; itV != values.end(); ++itV) { SPACE; VAL(*itV); }
00566 }
00567
00568 template <class CH>
00569 FCOLLADA_EXPORT void FUStringConversion::ToString(FUStringBuilderT<CH>& builder, const Int32List& values)
00570 {
00571 if (values.empty()) return;
00572 if (!builder.empty()) SPACE;
00573 Int32List::const_iterator itV = values.begin();
00574 builder.append(*itV);
00575 for (++itV; itV != values.end(); ++itV) { SPACE; VAL(*itV); }
00576 }
00577
00578 template <class CH>
00579 FCOLLADA_EXPORT void FUStringConversion::ToString(FUStringBuilderT<CH>& builder, const uint32* values, size_t count)
00580 {
00581 if (count > 0)
00582 {
00583 if (builder.empty()) { builder.append(*values++); --count; }
00584 while (((intptr_t) count) > 0) { SPACE; VAL(*values++); --count; }
00585 }
00586 }
00587
00588 #endif // HAS_VECTORTYPES
00589
00590 #undef SPACE
00591 #undef VAL