[657] | 1 | /*
|
---|
| 2 | -----------------------------------------------------------------------------
|
---|
| 3 | This source file is part of OGRE
|
---|
| 4 | (Object-oriented Graphics Rendering Engine)
|
---|
| 5 | For the latest info, see http://www.ogre3d.org/
|
---|
| 6 |
|
---|
| 7 | Copyright (c) 2000-2005 The OGRE Team
|
---|
| 8 | Also see acknowledgements in Readme.html
|
---|
| 9 |
|
---|
| 10 | This program is free software; you can redistribute it and/or modify it under
|
---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software
|
---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later
|
---|
| 13 | version.
|
---|
| 14 |
|
---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT
|
---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
---|
| 18 |
|
---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with
|
---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to
|
---|
| 22 | http://www.gnu.org/copyleft/lesser.txt.
|
---|
| 23 | -----------------------------------------------------------------------------
|
---|
| 24 | */
|
---|
| 25 | #include "OgreStableHeaders.h"
|
---|
| 26 | #include "OgreString.h"
|
---|
| 27 |
|
---|
| 28 | #include "OgreStringVector.h"
|
---|
| 29 |
|
---|
| 30 | namespace Ogre {
|
---|
| 31 |
|
---|
| 32 | //-----------------------------------------------------------------------
|
---|
| 33 | const String StringUtil::BLANK = String("");
|
---|
| 34 | //-----------------------------------------------------------------------
|
---|
| 35 | void StringUtil::trim(String& str, bool left, bool right)
|
---|
| 36 | {
|
---|
| 37 | /*
|
---|
| 38 | size_t lspaces, rspaces, len = length(), i;
|
---|
| 39 |
|
---|
| 40 | lspaces = rspaces = 0;
|
---|
| 41 |
|
---|
| 42 | if( left )
|
---|
| 43 | {
|
---|
| 44 | // Find spaces / tabs on the left
|
---|
| 45 | for( i = 0;
|
---|
| 46 | i < len && ( at(i) == ' ' || at(i) == '\t' || at(i) == '\r');
|
---|
| 47 | ++lspaces, ++i );
|
---|
| 48 | }
|
---|
| 49 |
|
---|
| 50 | if( right && lspaces < len )
|
---|
| 51 | {
|
---|
| 52 | // Find spaces / tabs on the right
|
---|
| 53 | for( i = len - 1;
|
---|
| 54 | i >= 0 && ( at(i) == ' ' || at(i) == '\t' || at(i) == '\r');
|
---|
| 55 | rspaces++, i-- );
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | *this = substr(lspaces, len-lspaces-rspaces);
|
---|
| 59 | */
|
---|
| 60 | static const String delims = " \t\r";
|
---|
| 61 | if(right)
|
---|
| 62 | str.erase(str.find_last_not_of(delims)+1); // trim right
|
---|
| 63 | if(left)
|
---|
| 64 | str.erase(0, str.find_first_not_of(delims)); // trim left
|
---|
| 65 | }
|
---|
| 66 |
|
---|
| 67 | //-----------------------------------------------------------------------
|
---|
| 68 | std::vector<String> StringUtil::split( const String& str, const String& delims, unsigned int maxSplits)
|
---|
| 69 | {
|
---|
| 70 | // static unsigned dl;
|
---|
| 71 | std::vector<String> ret;
|
---|
| 72 | unsigned int numSplits = 0;
|
---|
| 73 |
|
---|
| 74 | // Use STL methods
|
---|
| 75 | size_t start, pos;
|
---|
| 76 | start = 0;
|
---|
| 77 | do
|
---|
| 78 | {
|
---|
| 79 | pos = str.find_first_of(delims, start);
|
---|
| 80 | if (pos == start)
|
---|
| 81 | {
|
---|
| 82 | // Do nothing
|
---|
| 83 | start = pos + 1;
|
---|
| 84 | }
|
---|
| 85 | else if (pos == String::npos || (maxSplits && numSplits == maxSplits))
|
---|
| 86 | {
|
---|
| 87 | // Copy the rest of the string
|
---|
| 88 | ret.push_back( str.substr(start) );
|
---|
| 89 | break;
|
---|
| 90 | }
|
---|
| 91 | else
|
---|
| 92 | {
|
---|
| 93 | // Copy up to delimiter
|
---|
| 94 | ret.push_back( str.substr(start, pos - start) );
|
---|
| 95 | start = pos + 1;
|
---|
| 96 | }
|
---|
| 97 | // parse up to next real data
|
---|
| 98 | start = str.find_first_not_of(delims, start);
|
---|
| 99 | ++numSplits;
|
---|
| 100 |
|
---|
| 101 | } while (pos != String::npos);
|
---|
| 102 |
|
---|
| 103 |
|
---|
| 104 |
|
---|
| 105 | return ret;
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | //-----------------------------------------------------------------------
|
---|
| 109 | void StringUtil::toLowerCase(String& str)
|
---|
| 110 | {
|
---|
| 111 | std::transform(
|
---|
| 112 | str.begin(),
|
---|
| 113 | str.end(),
|
---|
| 114 | str.begin(),
|
---|
| 115 | tolower);
|
---|
| 116 | }
|
---|
| 117 |
|
---|
| 118 | //-----------------------------------------------------------------------
|
---|
| 119 | void StringUtil::toUpperCase(String& str)
|
---|
| 120 | {
|
---|
| 121 | std::transform(
|
---|
| 122 | str.begin(),
|
---|
| 123 | str.end(),
|
---|
| 124 | str.begin(),
|
---|
| 125 | toupper);
|
---|
| 126 | }
|
---|
| 127 | //-----------------------------------------------------------------------
|
---|
| 128 | Real StringUtil::toReal(const String& str)
|
---|
| 129 | {
|
---|
| 130 | return (Real)atof(str.c_str());
|
---|
| 131 | }
|
---|
| 132 | //-----------------------------------------------------------------------
|
---|
| 133 | bool StringUtil::startsWith(const String& str, const String& pattern, bool lowerCase)
|
---|
| 134 | {
|
---|
| 135 | size_t thisLen = str.length();
|
---|
| 136 | size_t patternLen = pattern.length();
|
---|
| 137 | if (thisLen < patternLen || patternLen == 0)
|
---|
| 138 | return false;
|
---|
| 139 |
|
---|
| 140 | String startOfThis = str.substr(0, patternLen);
|
---|
| 141 | if (lowerCase)
|
---|
| 142 | StringUtil::toLowerCase(startOfThis);
|
---|
| 143 |
|
---|
| 144 | return (startOfThis == pattern);
|
---|
| 145 | }
|
---|
| 146 | //-----------------------------------------------------------------------
|
---|
| 147 | bool StringUtil::endsWith(const String& str, const String& pattern, bool lowerCase)
|
---|
| 148 | {
|
---|
| 149 | size_t thisLen = str.length();
|
---|
| 150 | size_t patternLen = pattern.length();
|
---|
| 151 | if (thisLen < patternLen || patternLen == 0)
|
---|
| 152 | return false;
|
---|
| 153 |
|
---|
| 154 | String endOfThis = str.substr(thisLen - patternLen, patternLen);
|
---|
| 155 | if (lowerCase)
|
---|
| 156 | StringUtil::toLowerCase(endOfThis);
|
---|
| 157 |
|
---|
| 158 | return (endOfThis == pattern);
|
---|
| 159 | }
|
---|
| 160 | //-----------------------------------------------------------------------
|
---|
| 161 | String StringUtil::standardisePath(const String& init)
|
---|
| 162 | {
|
---|
| 163 | String path = init;
|
---|
| 164 |
|
---|
| 165 | std::replace( path.begin(), path.end(), '\\', '/' );
|
---|
| 166 | if( path[path.length() - 1] != '/' )
|
---|
| 167 | path += '/';
|
---|
| 168 |
|
---|
| 169 | return path;
|
---|
| 170 | }
|
---|
| 171 | //-----------------------------------------------------------------------
|
---|
| 172 | void StringUtil::splitFilename(const String& qualifiedName,
|
---|
| 173 | String& outBasename, String& outPath)
|
---|
| 174 | {
|
---|
| 175 | String path = qualifiedName;
|
---|
| 176 | // Replace \ with / first
|
---|
| 177 | std::replace( path.begin(), path.end(), '\\', '/' );
|
---|
| 178 | // split based on final /
|
---|
| 179 | size_t i = path.find_last_of('/');
|
---|
| 180 |
|
---|
| 181 | if (i == String::npos)
|
---|
| 182 | {
|
---|
| 183 | outPath = "";
|
---|
| 184 | outBasename = qualifiedName;
|
---|
| 185 | }
|
---|
| 186 | else
|
---|
| 187 | {
|
---|
| 188 | outBasename = path.substr(i+1, path.size() - i - 1);
|
---|
| 189 | outPath = path.substr(0, i+1);
|
---|
| 190 | }
|
---|
| 191 |
|
---|
| 192 | }
|
---|
| 193 | //-----------------------------------------------------------------------
|
---|
| 194 | bool StringUtil::match(const String& str, const String& pattern, bool caseSensitive)
|
---|
| 195 | {
|
---|
| 196 | String tmpStr = str;
|
---|
| 197 | String tmpPattern = pattern;
|
---|
| 198 | if (!caseSensitive)
|
---|
| 199 | {
|
---|
| 200 | StringUtil::toLowerCase(tmpStr);
|
---|
| 201 | StringUtil::toLowerCase(tmpPattern);
|
---|
| 202 | }
|
---|
| 203 |
|
---|
| 204 | String::const_iterator strIt = tmpStr.begin();
|
---|
| 205 | String::const_iterator patIt = tmpPattern.begin();
|
---|
| 206 | String::const_iterator lastWildCardIt = tmpPattern.end();
|
---|
| 207 | while (strIt != tmpStr.end() && patIt != tmpPattern.end())
|
---|
| 208 | {
|
---|
| 209 | if (*patIt == '*')
|
---|
| 210 | {
|
---|
| 211 | lastWildCardIt = patIt;
|
---|
| 212 | // Skip over looking for next character
|
---|
| 213 | ++patIt;
|
---|
| 214 | if (patIt == tmpPattern.end())
|
---|
| 215 | {
|
---|
| 216 | // Skip right to the end since * matches the entire rest of the string
|
---|
| 217 | strIt = tmpStr.end();
|
---|
| 218 | }
|
---|
| 219 | else
|
---|
| 220 | {
|
---|
| 221 | // scan until we find next pattern character
|
---|
| 222 | while(strIt != tmpStr.end() && *strIt != *patIt)
|
---|
| 223 | ++strIt;
|
---|
| 224 | }
|
---|
| 225 | }
|
---|
| 226 | else
|
---|
| 227 | {
|
---|
| 228 | if (*patIt != *strIt)
|
---|
| 229 | {
|
---|
| 230 | if (lastWildCardIt != tmpPattern.end())
|
---|
| 231 | {
|
---|
| 232 | // The last wildcard can match this incorrect sequence
|
---|
| 233 | // rewind pattern to wildcard and keep searching
|
---|
| 234 | patIt = lastWildCardIt;
|
---|
| 235 | lastWildCardIt = tmpPattern.end();
|
---|
| 236 | }
|
---|
| 237 | else
|
---|
| 238 | {
|
---|
| 239 | // no wildwards left
|
---|
| 240 | return false;
|
---|
| 241 | }
|
---|
| 242 | }
|
---|
| 243 | else
|
---|
| 244 | {
|
---|
| 245 | ++patIt;
|
---|
| 246 | ++strIt;
|
---|
| 247 | }
|
---|
| 248 | }
|
---|
| 249 |
|
---|
| 250 | }
|
---|
| 251 | // If we reached the end of both the pattern and the string, we succeeded
|
---|
| 252 | if (patIt == tmpPattern.end() && strIt == tmpStr.end())
|
---|
| 253 | {
|
---|
| 254 | return true;
|
---|
| 255 | }
|
---|
| 256 | else
|
---|
| 257 | {
|
---|
| 258 | return false;
|
---|
| 259 | }
|
---|
| 260 |
|
---|
| 261 | }
|
---|
| 262 |
|
---|
| 263 | }
|
---|