1 /*
2 * Copyright 2006 Sony Computer Entertainment Inc.
3 *
4 * Licensed under the MIT Open Source License, for details please see license.txt or the website
5 * http://www.opensource.org/licenses/mit-license.php
6 *
7 */
8 #include <cstdarg>
9 #include <algorithm>
10 #include <iterator>
11 #include <dae/daeUtils.h>
12 #include <dae/daeURI.h>
13 
14 #ifdef _WIN32
15 #include <direct.h>  // for getcwd (windows)
16 #else
17 #include <unistd.h>  // for getcwd (linux)
18 #endif
19 
20 #ifndef NO_BOOST
21 #include <boost/filesystem/convenience.hpp>       // THIS WAS NOT COMMENTED.
22 #endif
23 
24 #include <cstdio> // for tmpnam
25 
26 using namespace std;
27 
getSystemType()28 cdom::systemType cdom::getSystemType() {
29 #ifdef WIN32
30 	return Windows;
31 #else
32 	return Posix;
33 #endif
34 }
35 
replace(const string & s,const string & replace,const string & replaceWith)36 string cdom::replace(const string& s, const string& replace, const string& replaceWith) {
37 	if (replace.empty())
38 		return s;
39 
40 	string result;
41 	size_t pos1 = 0, pos2 = s.find(replace);
42 	while (pos2 != string::npos) {
43 		result += s.substr(pos1, pos2-pos1);
44 		result += replaceWith;
45 		pos1 = pos2 + replace.length();
46 		pos2 = s.find(replace, pos1);
47 	}
48 
49 	result += s.substr(pos1, s.length()-pos1);
50 	return result;
51 }
52 
trimWhitespaces(string & str)53 void cdom::trimWhitespaces(string& str) {
54     string whitespaces ( " \t\f\v\n\r" );
55 
56     size_t found = str.find_last_not_of( whitespaces );
57     if ( found != std::string::npos )
58     {
59         str.erase( found + 1 );
60         found = str.find_first_not_of( whitespaces );
61         if ( found != std::string::npos )
62             str.erase( 0, found );
63     }
64     else
65     {
66         // whitespaces only
67         str.clear();
68     }
69 }
70 
tokenize(const string & s,const string & separators,list<string> & tokens,bool separatorsInResult)71 void cdom::tokenize(const string& s,
72                     const string& separators,
73                     /* out */ list<string>& tokens,
74                     bool separatorsInResult) {
75 	size_t currentIndex = 0, nextTokenIndex = 0;
76 	while (currentIndex < s.length() &&
77 	       (nextTokenIndex = s.find_first_of(separators, currentIndex)) != string::npos) {
78 		if ((nextTokenIndex - currentIndex) > 0)
79 			tokens.push_back(s.substr(currentIndex, nextTokenIndex-currentIndex));
80 		if (separatorsInResult)
81 			tokens.push_back(string(1, s[nextTokenIndex]));
82 		currentIndex = nextTokenIndex+1;
83 	}
84 
85 	if (currentIndex < s.length())
86 		tokens.push_back(s.substr(currentIndex, s.length()-currentIndex));
87 }
88 
tokenize(const string & s,const string & separators,bool separatorsInResult)89 list<string> cdom::tokenize(const string& s,
90                             const string& separators,
91                             bool separatorsInResult) {
92 	list<string> result;
93 	tokenize(s, separators, result, separatorsInResult);
94 	return result;
95 }
96 
makeStringArray(const char * s,...)97 vector<string> cdom::makeStringArray(const char* s, ...) {
98 	va_list args;
99 	va_start(args, s);
100 	vector<string> result;
101 	while (s) {
102 		result.push_back(s);
103 		s = va_arg(args, const char*);
104 	}
105 	va_end(args);
106 	return result;
107 }
108 
makeStringList(const char * s,...)109 list<string> cdom::makeStringList(const char* s, ...) {
110 	va_list args;
111 	va_start(args, s);
112 	list<string> result;
113 	while (s) {
114 		result.push_back(s);
115 		s = va_arg(args, const char*);
116 	}
117 	va_end(args);
118 	return result;
119 }
120 
getCurrentDir()121 string cdom::getCurrentDir() {
122 #ifdef __CELLOS_LV2__
123 	// The PS3 has no getcwd call.
124 	// !!!steveT Should we return app_home instead?
125 	return "/";
126 #else
127 	char buffer[1024];
128 #ifdef _WIN32
129 	_getcwd(buffer, 1024);
130 #else
131 	getcwd(buffer, 1024);
132 #endif
133 	return buffer;
134 #endif
135 }
136 
getCurrentDirAsUri()137 string cdom::getCurrentDirAsUri() {
138 	string result = string("file://") + cdom::nativePathToUri(getCurrentDir());
139 	// Make sure the last char is a /
140 	if (!result.empty()  &&  result[result.length()-1] != '/')
141 		result += "/";
142 	return result;
143 }
144 
getFileSeparator()145 char cdom::getFileSeparator() {
146     if (getSystemType() == Windows) {
147         return '\\';
148     }
149     return '/';
150 }
151 #ifndef NO_BOOST
getSystemTmpDir()152 const string& cdom::getSystemTmpDir() {
153 #ifdef WIN32
154     static string tmpDir = string(getenv("TMP")) + getFileSeparator();
155 #elif defined(__linux__) || defined(__linux) || defined(__FreeBSD__)
156     static string tmpDir = "/tmp/";
157 #elif defined __APPLE_CC__
158 static string tmpDir = string(getenv("TMPDIR"));
159 #elif defined __CELLOS_LV2__
160 #error tmp dir for your system unknown
161 #else
162 #error tmp dir for your system unknown
163 #endif
164     return tmpDir;
165 }
166 
getRandomFileName()167 string cdom::getRandomFileName() {
168     std::string randomSegment;
169     // have to createa a buffer in order to make it multi-thread safe
170     std::string tmpbuffer; tmpbuffer.resize(L_tmpnam*2+1);
171     std::string tmp(tmpnam(&tmpbuffer[0]));
172 #ifdef WIN32
173     randomSegment = tmp.substr(tmp.find_last_of('\\')+1);
174 #elif defined(__linux__) || defined(__linux) || defined(__FreeBSD__)
175     randomSegment = tmp.substr(tmp.find_last_of('/')+1);
176 #elif defined __APPLE_CC__
177 	randomSegment = tmp.substr(tmp.find_last_of('/')+1);
178 #elif defined __CELLOS_LV2__
179 #error  usage of tmpnam() for your system unknown
180 #else
181 #error  usage of tmpnam() for your system unknown
182 #endif
183     return randomSegment;
184 }
185 
getSafeTmpDir()186 const string& cdom::getSafeTmpDir() {
187     // there is a race condition here is multiple collada-dom -enabled processes call getSafeTmpDir at the same time.
188     // Therefore, have to check if directory already exists before using it. This still leaves the race
189     // condition, but makes it more difficult to reproduce. A better alternative would be to stop relying on tmpnam!
190     static string tmpDir;
191     do {
192         tmpDir = getSystemTmpDir() + getRandomFileName() + getFileSeparator();
193     } while(boost::filesystem::is_directory(tmpDir));
194     return tmpDir;
195 }
196 #endif //NO_BOOST
197 
strcasecmp(const char * str1,const char * str2)198 int cdom::strcasecmp(const char* str1, const char* str2) {
199 #ifdef _MSC_VER
200 	return _stricmp(str1, str2);
201 #else
202 	return ::strcasecmp(str1, str2);
203 #endif
204 }
205 
tolower(const string & s)206 string cdom::tolower(const string& s) {
207 	string result;
208 	transform(s.begin(), s.end(), back_inserter(result), ::tolower);
209 	return result;
210 }
211