1 /* 2 Copyright (c) 2008-2009 NetAllied Systems GmbH 3 4 This file is part of COLLADAStreamWriter. 5 6 Licensed under the MIT Open Source License, 7 for details please see LICENSE file or the website 8 http://www.opensource.org/licenses/mit-license.php 9 */ 10 11 #include "COLLADABUStableHeaders.h" 12 #include "COLLADABUUtils.h" 13 #include "COLLADABUPlatform.h" 14 15 #include <string.h> 16 #include <list> 17 #ifdef _WIN32 18 #include <Windows.h> 19 #endif 20 21 namespace COLLADABU 22 { 23 24 const String Utils::FILE_PROTOCOL = "file:///"; 25 const String Utils::FILE_DELIMITER = "/"; 26 const char Utils::FILE_DELIMITER_CHAR = '/'; 27 28 const String Utils::EMPTY_STRING = String(); 29 30 // defines 31 #define MAX_FILENAME_LEN 512 32 33 // The number of characters at the start of an absolute filename. e.g. in DOS, 34 // absolute filenames start with "X:\" so this value should be 3, in UNIX they start 35 // with "\" so this value should be 1. A slash must set to '\\' for DOS or '/' for UNIX. 36 37 #if defined(COLLADABU_OS_WIN) 38 #define ABSOLUTE_NAME_START 3 39 #define SLASH '\\' 40 #elif defined(COLLADABU_OS_MAC) 41 #define ABSOLUTE_NAME_START 1 // TODO Ist das so? 42 #define SLASH '/' // TODO Ist das so? 43 #else 44 #define ABSOLUTE_NAME_START 1 45 #define SLASH '/' 46 #endif 47 48 49 50 //--------------------------------- checkNCName(const String & ncName)51 String Utils::checkNCName ( const String &ncName ) 52 { 53 String result; 54 result.reserve ( ncName.length() ); 55 56 // check if first character is an alpha character 57 char firstCharacter = ncName[0]; 58 59 if ( isAsciiAlphaChar ( firstCharacter ) ) 60 result.append ( 1, firstCharacter ); 61 else 62 result.append ( 1, '_' ); 63 64 //replace all spaces and colons by underlines 65 for ( size_t i = 1; i<ncName.length(); ++i ) 66 { 67 char character = ncName[i]; 68 69 if ( isIDChar ( character ) ) 70 result.append ( 1, character ); 71 else 72 result.append ( 1, '_' ); 73 } 74 75 return result; 76 } 77 78 //--------------------------------- checkID(const String & id)79 String Utils::checkID ( const String &id ) 80 { 81 return checkNCName ( id ); 82 } 83 84 //--------------------------------- translateToXML(const String & srcString)85 String Utils::translateToXML ( const String &srcString ) 86 { 87 String returnString = ""; 88 89 for ( unsigned int i=0; i<srcString.length(); ++i ) 90 { 91 switch ( srcString[i]) 92 { 93 // case '\r': 94 // returnString += "
"; 95 // break; 96 case '<': 97 returnString += "<"; 98 break; 99 case '>': 100 returnString += ">"; 101 break; 102 case '&': 103 returnString += "&"; 104 break; 105 case '"': 106 returnString += """; 107 break; 108 case '\'': 109 returnString += "'"; 110 break; 111 default : 112 returnString += srcString[i]; 113 } 114 } 115 116 return returnString; 117 } 118 119 120 121 //--------------------------------- replaceDot(const String & text)122 String Utils::replaceDot ( const String &text ) 123 { 124 std::stringstream stream; 125 126 for ( size_t i = 0; i < text.length(); ++i ) 127 { 128 if ( text[i] == '.' ) 129 stream << '_'; 130 else 131 stream << text[i]; 132 } 133 134 return stream.str(); 135 } 136 137 //--------------------------------- stringFindAndReplace(String & source,const String searchString,const String replaceString)138 void Utils::stringFindAndReplace ( String &source, const String searchString, const String replaceString ) 139 { 140 size_t found = source.find ( searchString ); 141 if ( found != String::npos ) 142 { 143 size_t searchStrLength = searchString.length(); 144 size_t replaceStrLength = replaceString.length(); 145 do 146 { 147 source.replace ( found, searchStrLength, replaceString ); 148 found = source.find (searchString, found + replaceStrLength ); 149 } while ( found != String::npos ); 150 } 151 152 } 153 154 //--------------------------------- equals(const String & str1,const String & str2)155 bool Utils::equals ( const String &str1, const String &str2 ) 156 { 157 return ( strcmp ( str1.c_str(), str2.c_str() ) == 0 ); 158 } 159 160 //-------------------------------- equalsIgnoreCase(const String & s1,const String & s2)161 bool Utils::equalsIgnoreCase ( const String& s1, const String& s2 ) 162 { 163 String::const_iterator it1=s1.begin(); 164 String::const_iterator it2=s2.begin(); 165 166 // has the end of at least one of the strings been reached? 167 while ( (it1!=s1.end()) && (it2!=s2.end()) ) 168 { 169 if(::toupper(*it1) != ::toupper(*it2)) //letters differ? 170 // return -1 to indicate 'smaller than', 1 otherwise 171 return false; 172 // proceed to the next character in each string 173 ++it1; 174 ++it2; 175 } 176 size_t size1=s1.size(), size2=s2.size();// cache lengths 177 //return -1,0 or 1 according to strings' lengths 178 if (size1==size2) 179 return true; 180 return false; 181 } 182 183 //-------------------------------- getSystemType()184 Utils::SystemType Utils::getSystemType() 185 { 186 #ifdef COLLADABU_OS_WIN 187 return WINDOWS; 188 #else 189 return POSIX; 190 #endif 191 } 192 193 //-------------------------------- split(const String & text,const String & separators,std::vector<String> & words)194 void Utils::split ( const String& text, const String& separators, std::vector<String>& words ) 195 { 196 size_t n = text.length(); 197 size_t start, stop; 198 199 start = text.find_first_not_of(separators); 200 while (start < n) 201 { 202 stop = text.find_first_of(separators, start); 203 if (stop > n) stop = n; 204 words.push_back(text.substr(start, stop - start)); 205 start = text.find_first_not_of(separators, stop+1); 206 } 207 } 208 209 #ifdef COLLADABU_OS_WIN 210 //-------------------------------- createDirectoryIfNeeded(const WideString & pathString)211 bool Utils::createDirectoryIfNeeded( const WideString &pathString ) 212 { 213 bool pathExists = false; 214 215 216 SystemType type = getSystemType(); 217 if( type != WINDOWS ) 218 return false; 219 220 const wchar_t* currentPath = _wgetcwd( 0, 0); 221 const wchar_t* testPath = pathString.c_str(); 222 223 pathExists = _wchdir( testPath ) == 0; 224 if( !pathExists ) 225 { 226 _wmkdir( testPath ); 227 pathExists = _wchdir( testPath ) == 0; 228 } 229 230 _wchdir( currentPath ); 231 return pathExists; 232 233 } 234 #endif 235 236 //-------------------------------- createDirectoryIfNeeded(const String & pathString)237 bool Utils::createDirectoryIfNeeded( const String &pathString ) 238 { 239 bool pathExists = false; 240 241 #ifdef COLLADABU_OS_WIN 242 SystemType type = getSystemType(); 243 if( type != WINDOWS ) 244 return false; 245 246 const char* currentPath = _getcwd( 0, 0); 247 const char* testPath = pathString.c_str(); 248 249 pathExists = _chdir( testPath ) == 0; 250 if( !pathExists ) 251 { 252 _mkdir( testPath ); 253 pathExists = _chdir( testPath ) == 0; 254 } 255 256 _chdir( currentPath ); 257 258 #else 259 SystemType type = getSystemType(); 260 if( type != POSIX ) 261 return false; 262 263 const char* currentPath = getcwd( 0, 0); 264 const char* testPath = pathString.c_str(); 265 pathExists = chdir( testPath ) == 0; 266 if( !pathExists ) 267 { 268 pathExists = mkdir(testPath, 0755) == false; 269 } 270 chdir( currentPath ); 271 #endif 272 return pathExists; 273 } 274 275 #ifdef COLLADABU_OS_WIN 276 //-------------------------------- createDirectoryRecursive(const WideString & pathString)277 bool Utils::createDirectoryRecursive( const WideString &pathString ) 278 { 279 if (pathString.length() == 0) 280 return false; 281 282 WideString path = pathString; 283 284 if (path[path.length()-1] != '/' && path[path.length()-1] != '\\') 285 path.push_back('\\'); 286 287 std::list<WideString> paths; 288 size_t offset = WideString::npos; 289 while ((offset != 0) && (offset = pathString.find_last_of(L"/\\", offset)) != WideString::npos) 290 { 291 paths.push_front(pathString.substr(0, offset + 1)); 292 if (offset != 0) --offset; 293 } 294 295 bool pathExists = true; 296 const wchar_t* currentPath = _wgetcwd(0, 0); 297 298 for (std::list<WideString>::const_iterator iPath = paths.begin(); iPath != paths.end(); ++iPath) 299 { 300 // if path exists 301 if (_wchdir((*iPath).c_str()) == 0) { 302 _wchdir(currentPath); 303 continue; 304 } 305 306 // path does not exist, try to create it 307 _wmkdir((*iPath).c_str()); 308 309 if (_wchdir((*iPath).c_str()) != 0) 310 { 311 pathExists = false; 312 break; 313 } 314 } 315 316 // Restore current path 317 _wchdir(currentPath); 318 return pathExists; 319 } 320 #endif 321 322 //-------------------------------- createDirectoryRecursive(const String & pathString)323 bool Utils::createDirectoryRecursive( const String &pathString ) 324 { 325 if (pathString.length() == 0) 326 return false; 327 328 String path = pathString; 329 330 if (path[path.length()-1] != '/' && path[path.length()-1] != '\\') 331 path.push_back('\\'); 332 333 std::list<String> paths; 334 size_t offset = String::npos; 335 while ((offset != 0) && (offset = pathString.find_last_of("/\\", offset)) != String::npos) 336 { 337 paths.push_front(pathString.substr(0, offset + 1)); 338 if (offset !=0) --offset; 339 } 340 341 bool pathExists = true; 342 343 SystemType type = getSystemType(); 344 345 #ifdef COLLADABU_OS_WIN 346 if( type != WINDOWS ) 347 return false; 348 349 const char* currentPath = _getcwd(0, 0); 350 351 for (std::list<String>::const_iterator iPath = paths.begin(); iPath != paths.end(); ++iPath) 352 { 353 // if path exists 354 if (_chdir((*iPath).c_str()) == 0) { 355 _chdir(currentPath); 356 continue; 357 } 358 359 // path does not exist, try to create it 360 _mkdir((*iPath).c_str()); 361 362 if (_chdir((*iPath).c_str()) != 0) 363 { 364 pathExists = false; 365 break; 366 } 367 } 368 369 // Restore current path 370 _chdir(currentPath); 371 #else 372 if( type != POSIX ) 373 return false; 374 375 const char* currentPath = getcwd(0, 0); 376 377 for (std::list<String>::const_iterator iPath = paths.begin(); iPath != paths.end(); ++iPath) 378 { 379 // if path exists 380 if (chdir((*iPath).c_str()) == 0) 381 continue; 382 383 // path does not exist, try to create it 384 mkdir((*iPath).c_str(), 0755); 385 386 if (chdir((*iPath).c_str()) != 0) 387 { 388 pathExists = false; 389 break; 390 } 391 } 392 393 // Restore current path 394 chdir(currentPath); 395 #endif 396 return pathExists; 397 } 398 399 #ifdef COLLADABU_OS_WIN 400 //-------------------------------- directoryExists(const WideString & pathString)401 bool Utils::directoryExists( const WideString &pathString ) 402 { 403 bool pathExists = false; 404 405 406 SystemType type = getSystemType(); 407 if( type != WINDOWS ) 408 return false; 409 410 const wchar_t* currentPath = _wgetcwd( 0, 0); 411 const wchar_t* testPath = pathString.c_str(); 412 413 pathExists = _wchdir( testPath ) == 0; 414 _wchdir( currentPath ); 415 return pathExists; 416 417 } 418 #endif 419 420 //-------------------------------- directoryExists(const String & pathString)421 bool Utils::directoryExists( const String &pathString ) 422 { 423 bool pathExists = false; 424 425 #ifdef COLLADABU_OS_WIN 426 SystemType type = getSystemType(); 427 if( type != WINDOWS ) 428 return false; 429 430 const char* currentPath = _getcwd( 0, 0); 431 const char* testPath = pathString.c_str(); 432 433 pathExists = _chdir( testPath ) == 0; 434 _chdir( currentPath ); 435 return pathExists; 436 #else 437 SystemType type = getSystemType(); 438 if( type != POSIX ) 439 return false; 440 441 struct stat st; 442 if(stat(pathString.c_str(),&st) == 0) 443 pathExists = true; 444 445 #endif 446 447 return pathExists; 448 } 449 450 //-------------------------------- copyFile(const String & source,const String & destination)451 bool Utils::copyFile( const String &source, const String &destination ) 452 { 453 bool copystatus = false; 454 455 #ifdef COLLADABU_OS_WIN 456 SystemType type = getSystemType(); 457 if( type != WINDOWS ) 458 return false; 459 460 char command[4097]; 461 sprintf(command,"copy \"%s\" \"%s\"", source.c_str(), destination.c_str() ); 462 size_t length = strlen(command); 463 if( length > 4096) 464 return false; 465 466 int status = system(command); 467 copystatus = (status == 0 ? true : false); 468 #else 469 SystemType type = getSystemType(); 470 if( type != POSIX ) 471 return false; 472 473 char command[4097]; 474 sprintf(command, "/bin/cp \"%s\" \"%s\"", source.c_str(), destination.c_str()); 475 size_t length = strlen(command); 476 if( length > 4096) 477 return false; 478 479 480 int status = system(command); 481 copystatus = (status == 0 ? true : false); 482 #endif 483 484 return copystatus; 485 } 486 487 //-------------------------------- deleteFile(const String & pathString)488 bool Utils::deleteFile(const String &pathString) 489 { 490 SystemType type = getSystemType(); 491 492 #ifdef COLLADABU_OS_WIN 493 if (type != WINDOWS) 494 return false; 495 return DeleteFileA(pathString.c_str()) != FALSE; 496 #else 497 if (type != POSIX) 498 return false; 499 char command[4097]; 500 sprintf(command, "rm -f \"%s\"", pathString.c_str()); 501 int status = system(command); 502 return status == 0; 503 #endif 504 } 505 506 //-------------------------------- fileExistsAndIsReadable(const String & pathString)507 bool Utils::fileExistsAndIsReadable( const String &pathString ) 508 { 509 FILE* f = fopen( pathString.c_str(), "r"); 510 bool readable = (f != 0); 511 if( readable ) 512 fclose(f); 513 return readable; 514 } 515 } 516