360 lines
12 KiB
C++
360 lines
12 KiB
C++
/* -*-c++-*- */
|
|
/* osgEarth - Geospatial SDK for OpenSceneGraph
|
|
* Copyright 2020 Pelican Mapping
|
|
* http://osgearth.org
|
|
*
|
|
* osgEarth is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
#ifndef OSGEARTH_STRING_UTILS_H
|
|
#define OSGEARTH_STRING_UTILS_H 1
|
|
|
|
#include <osgEarth/Common>
|
|
#include <osg/Vec3>
|
|
#include <osg/Vec3d>
|
|
#include <osg/Vec4>
|
|
#include <osg/Vec4ub>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <sstream>
|
|
#include <locale>
|
|
#include <iomanip>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <set>
|
|
#include <cctype>
|
|
|
|
namespace osgEarth { namespace Util
|
|
{
|
|
extern OSGEARTH_EXPORT const std::string EMPTY_STRING;
|
|
|
|
using StringVector = std::vector<std::string>;
|
|
using StringSet = std::set<std::string>;
|
|
using StringTable = std::unordered_map<std::string, std::string>;
|
|
|
|
/** Replaces all the instances of "pattern" with "replacement" in "in_out" */
|
|
extern OSGEARTH_EXPORT std::string& replaceIn(
|
|
std::string& in_out,
|
|
const std::string& pattern,
|
|
const std::string& replacement );
|
|
|
|
/** Replaces all the instances of "pattern" with "replacement" in "in_out" (case-insensitive) */
|
|
extern OSGEARTH_EXPORT std::string& ciReplaceIn(
|
|
std::string& in_out,
|
|
const std::string& pattern,
|
|
const std::string& replacement );
|
|
|
|
/**
|
|
* Trims whitespace from the ends of a string.
|
|
*/
|
|
extern OSGEARTH_EXPORT std::string trim( const std::string& in );
|
|
|
|
/**
|
|
* Trims whitespace from the ends of a string; in-place modification on the string to reduce string copies.
|
|
*/
|
|
extern OSGEARTH_EXPORT void trim2( std::string& str );
|
|
|
|
//! Removes leading and trailing whitespace, and replaces all other
|
|
//! whitespace with single spaces
|
|
extern OSGEARTH_EXPORT std::string trimAndCompress(const std::string& in);
|
|
|
|
/**
|
|
* True is "ref" starts with "pattern"
|
|
*/
|
|
extern OSGEARTH_EXPORT bool startsWith(
|
|
const std::string& ref,
|
|
const std::string& pattern,
|
|
bool caseSensitive =true,
|
|
const std::locale& locale =std::locale() );
|
|
|
|
/**
|
|
* True is "ref" ends with "pattern"
|
|
*/
|
|
extern OSGEARTH_EXPORT bool endsWith(
|
|
const std::string& ref,
|
|
const std::string& pattern,
|
|
bool caseSensitive =true,
|
|
const std::locale& locale =std::locale() );
|
|
|
|
/**
|
|
* Case-insensitive compare
|
|
*/
|
|
extern OSGEARTH_EXPORT bool ciEquals(
|
|
const std::string& lhs,
|
|
const std::string& rhs,
|
|
const std::locale& local = std::locale() );
|
|
|
|
/**
|
|
* Case-insensitive STL comparator
|
|
*/
|
|
inline bool ci_char_equals(char c1, char c2) {
|
|
return std::tolower(c1) == std::tolower(c2);
|
|
}
|
|
inline bool ci_equals(const std::string& lhs, const std::string& rhs) {
|
|
return (lhs.size() == rhs.size()) &&
|
|
std::equal(lhs.begin(), lhs.end(), rhs.begin(), ci_char_equals);
|
|
}
|
|
struct ci_string_less {
|
|
bool operator()(const std::string& lhs, const std::string& rhs) const {
|
|
for(size_t i=0; i<std::min(lhs.size(), rhs.size()); ++i) {
|
|
if (std::tolower(lhs[i]) < std::tolower(rhs[i])) return true;
|
|
if (std::tolower(lhs[i]) > std::tolower(rhs[i])) return false;
|
|
}
|
|
return lhs.size() < rhs.size();
|
|
}
|
|
};
|
|
|
|
|
|
extern OSGEARTH_EXPORT std::string joinStrings( const StringVector& input, char delim );
|
|
|
|
/** Returns a lower-case version of the input string. */
|
|
extern OSGEARTH_EXPORT std::string toLower( const std::string& input );
|
|
|
|
/** Parses a color string in the form "255 255 255 255" (r g b a [0..255]) into an OSG color. */
|
|
extern OSGEARTH_EXPORT osg::Vec4ub stringToColor(const std::string& str, osg::Vec4ub default_value);
|
|
|
|
/** Creates a string in the form "255 255 255 255" (r g b a [0..255]) from a color */
|
|
extern OSGEARTH_EXPORT std::string colorToString( const osg::Vec4ub& c );
|
|
|
|
/** Converts a string to a vec3f */
|
|
extern OSGEARTH_EXPORT osg::Vec3f stringToVec3f( const std::string& str, const osg::Vec3f& default_value );
|
|
|
|
/** Converts a vec3f to a string */
|
|
extern OSGEARTH_EXPORT std::string vec3fToString( const osg::Vec3f& v );
|
|
|
|
/** Parses an HTML color ("#rrggbb" or "#rrggbbaa") into an OSG color. */
|
|
extern OSGEARTH_EXPORT osg::Vec4f htmlColorToVec4f( const std::string& html );
|
|
|
|
/** Makes an HTML color ("#rrggbb" or "#rrggbbaa") from an OSG color. */
|
|
extern OSGEARTH_EXPORT std::string vec4fToHtmlColor( const osg::Vec4f& c );
|
|
|
|
/** Makes a valid filename out of a string */
|
|
extern OSGEARTH_EXPORT std::string toLegalFileName( const std::string& input, bool allowSubdir=false, const char* replacementChar=NULL);
|
|
|
|
/** Generates a hashed integer for a string (poor man's MD5) */
|
|
extern OSGEARTH_EXPORT unsigned hashString( const std::string& input );
|
|
|
|
/** Same as hashString but returns a string value. */
|
|
extern OSGEARTH_EXPORT std::string hashToString(const std::string& input);
|
|
|
|
/**
|
|
* Gets the total number of seconds formatted as H:M:S
|
|
*/
|
|
extern OSGEARTH_EXPORT std::string prettyPrintTime( double seconds );
|
|
|
|
/**
|
|
* Gets a pretty printed version of the given size in MB.
|
|
*/
|
|
extern OSGEARTH_EXPORT std::string prettyPrintSize( double mb );
|
|
|
|
//! Extract the "i-th" token from a delimited string
|
|
extern OSGEARTH_EXPORT std::string getToken(const std::string& input, unsigned i, const std::string& delims=",");
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// conversion templates
|
|
|
|
// converts a string to primitive using serialization
|
|
template<typename T> inline T
|
|
as( const std::string& str, const T& default_value )
|
|
{
|
|
T temp = default_value;
|
|
std::istringstream strin( str );
|
|
if ( !strin.eof() ) strin >> temp;
|
|
return temp;
|
|
}
|
|
|
|
// template specialization for integers (to handle hex)
|
|
#define AS_INT_DEC_OR_HEX(TYPE) \
|
|
template<> inline TYPE \
|
|
as< TYPE >(const std::string& str, const TYPE & dv) { \
|
|
TYPE temp = dv; \
|
|
std::istringstream strin( trim(str) ); \
|
|
if ( !strin.eof() ) { \
|
|
if ( str.length() >= 2 && str[0] == '0' && str[1] == 'x' ) { \
|
|
strin.seekg( 2 ); \
|
|
strin >> std::hex >> temp; \
|
|
} \
|
|
else { \
|
|
strin >> temp; \
|
|
} \
|
|
} \
|
|
return temp; \
|
|
}
|
|
|
|
AS_INT_DEC_OR_HEX(int)
|
|
AS_INT_DEC_OR_HEX(unsigned)
|
|
AS_INT_DEC_OR_HEX(short)
|
|
AS_INT_DEC_OR_HEX(unsigned short)
|
|
AS_INT_DEC_OR_HEX(long)
|
|
AS_INT_DEC_OR_HEX(unsigned long)
|
|
|
|
// template specialization for a bool
|
|
template<> inline bool
|
|
as<bool>( const std::string& str, const bool& default_value )
|
|
{
|
|
std::string temp = toLower(str);
|
|
return
|
|
temp == "true" || temp == "yes" || temp == "on" ? true :
|
|
temp == "false" || temp == "no" || temp == "off" ? false :
|
|
default_value;
|
|
}
|
|
|
|
template<> inline osg::Vec3f
|
|
as<osg::Vec3f>( const std::string& str, const osg::Vec3f& default_value )
|
|
{
|
|
return stringToVec3f(str, default_value);
|
|
}
|
|
|
|
// template specialization for string
|
|
template<> inline std::string
|
|
as<std::string>( const std::string& str, const std::string& default_value )
|
|
{
|
|
return str;
|
|
}
|
|
|
|
// snips a substring and parses it.
|
|
template<typename T> inline bool
|
|
as(const std::string& in, unsigned start, unsigned len, T default_value)
|
|
{
|
|
std::string buf;
|
|
std::copy( in.begin()+start, in.begin()+start+len, std::back_inserter(buf) );
|
|
return as<T>(buf, default_value);
|
|
}
|
|
|
|
// converts a primitive to a string
|
|
template<typename T> inline std::string
|
|
toString(const T& value)
|
|
{
|
|
std::stringstream out;
|
|
//out << std::setprecision(20) << std::fixed << value;
|
|
out << std::setprecision(20) << value;
|
|
std::string outStr;
|
|
outStr = out.str();
|
|
return outStr;
|
|
}
|
|
|
|
// template speciallization for a bool to print out "true" or "false"
|
|
template<> inline std::string
|
|
toString<bool>(const bool& value)
|
|
{
|
|
return value ? "true" : "false";
|
|
}
|
|
|
|
template<> inline std::string
|
|
toString<osg::Vec3f>(const osg::Vec3f& value)
|
|
{
|
|
return vec3fToString(value);
|
|
}
|
|
|
|
/**
|
|
* Assembles and returns an inline string using a stream-like << operator.
|
|
* Example:
|
|
* std::string str = Stringify() << "Hello, world " << variable;
|
|
*/
|
|
struct Stringify
|
|
{
|
|
operator std::string () const
|
|
{
|
|
std::string result;
|
|
result = buf.str();
|
|
return result;
|
|
}
|
|
|
|
template<typename T>
|
|
Stringify& operator << (const T& val) { buf << val; return (*this); }
|
|
|
|
Stringify& operator << (const Stringify& val) { buf << (std::string)val; return (*this); }
|
|
|
|
protected:
|
|
std::stringstream buf;
|
|
};
|
|
|
|
template<> inline
|
|
Stringify& Stringify::operator << <bool>(const bool& val) { buf << (val ? "true" : "false"); return (*this); }
|
|
|
|
template<> inline
|
|
Stringify& Stringify::operator << <osg::Vec3f>(const osg::Vec3f& val) {
|
|
buf << val.x() << " " << val.y() << " " << val.z(); return (*this); }
|
|
|
|
template<> inline
|
|
Stringify& Stringify::operator << <osg::Vec3d>(const osg::Vec3d& val ) {
|
|
buf << val.x() << " " << val.y() << " " << val.z(); return (*this); }
|
|
|
|
template<> inline
|
|
Stringify& Stringify::operator << <osg::Vec4f>(const osg::Vec4f& val) {
|
|
buf << val.r() << " " << val.g() << " " << val.b() << " " << val.a(); return (*this); }
|
|
|
|
/**
|
|
* Splits a string up into a vector of strings based on a set of
|
|
* delimiters, quotes, and rules.
|
|
*/
|
|
class OSGEARTH_EXPORT StringTokenizer
|
|
{
|
|
public:
|
|
StringTokenizer(
|
|
const std::string& delims =" \t\r\n",
|
|
const std::string& quotes ="'\"" );
|
|
|
|
StringTokenizer(
|
|
const std::string& input,
|
|
StringVector& output,
|
|
const std::string& delims =" \t\r\n",
|
|
const std::string& quotes ="'\"",
|
|
bool keepEmpties =true,
|
|
bool trimTokens =true);
|
|
|
|
StringTokenizer(
|
|
const std::string& input,
|
|
StringTable& output,
|
|
const std::string& delims = " \t\r\n",
|
|
const std::string& keypairseparators = "=",
|
|
const std::string& quotes = "'\"",
|
|
bool keepEmpties = true,
|
|
bool trimTokens = true);
|
|
|
|
|
|
void tokenize( const std::string& input, StringVector& output ) const;
|
|
|
|
bool& keepEmpties() { return _allowEmpties; }
|
|
|
|
bool& trimTokens() { return _trimTokens; }
|
|
|
|
void addDelim( char delim, bool keepAsToken =false );
|
|
|
|
void addDelims( const std::string& delims, bool keepAsTokens =false );
|
|
|
|
void addQuote( char delim, bool keepInToken =false );
|
|
|
|
void addQuotes( const std::string& delims, bool keepInTokens =false );
|
|
|
|
private:
|
|
using TokenMap = std::map<char,bool>;
|
|
TokenMap _delims;
|
|
TokenMap _quotes;
|
|
bool _allowEmpties;
|
|
bool _trimTokens;
|
|
};
|
|
} }
|
|
|
|
|
|
namespace osgEarth
|
|
{
|
|
namespace Strings = osgEarth::Util;
|
|
}
|
|
|
|
|
|
#endif // OSGEARTH_STRING_UTILS_H
|
|
|