mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
225 lines
7.0 KiB
C++
225 lines
7.0 KiB
C++
// Filename: string_utils.cxx
|
|
// Created by: drose (18Jan99)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "string_utils.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
// Case-insensitive string comparison, from Stroustrup's C++ third edition.
|
|
// Works like strcmp().
|
|
int
|
|
cmp_nocase(const string &s, const string &s2) {
|
|
string::const_iterator p = s.begin();
|
|
string::const_iterator p2 = s2.begin();
|
|
|
|
while (p != s.end() && p2 != s2.end()) {
|
|
if (toupper(*p) != toupper(*p2)) {
|
|
return (toupper(*p) < toupper(*p2)) ? -1 : 1;
|
|
}
|
|
++p;
|
|
++p2;
|
|
}
|
|
|
|
return (s2.size() == s.size()) ? 0 :
|
|
(s.size() < s2.size()) ? -1 : 1; // size is unsigned
|
|
}
|
|
|
|
INLINE int
|
|
toupper_uh(int ch) {
|
|
return (ch == '_') ? '-' : toupper(ch);
|
|
}
|
|
|
|
|
|
int
|
|
cmp_nocase_uh(const string &s, const string &s2) {
|
|
string::const_iterator p = s.begin();
|
|
string::const_iterator p2 = s2.begin();
|
|
|
|
while (p != s.end() && p2 != s2.end()) {
|
|
if (toupper_uh(*p) != toupper_uh(*p2)) {
|
|
return (toupper_uh(*p) < toupper_uh(*p2)) ? -1 : 1;
|
|
}
|
|
++p;
|
|
++p2;
|
|
}
|
|
|
|
return (s2.size() == s.size()) ? 0 :
|
|
(s.size() < s2.size()) ? -1 : 1; // size is unsigned
|
|
}
|
|
|
|
|
|
|
|
string
|
|
downcase(const string &s) {
|
|
string result;
|
|
string::const_iterator p;
|
|
for (p = s.begin(); p != s.end(); ++p) {
|
|
result += tolower(*p);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: extract_words
|
|
// Description: Divides the string into a number of words according
|
|
// to whitespace. The words vector should be cleared by
|
|
// the user before calling; otherwise, the list of words
|
|
// in the string will be appended to the end of whatever
|
|
// was there before.
|
|
//
|
|
// The return value is the number of words extracted.
|
|
////////////////////////////////////////////////////////////////////
|
|
int
|
|
extract_words(const string &str, vector_string &words) {
|
|
int num_words = 0;
|
|
|
|
size_t pos = 0;
|
|
while (pos < str.length() && isspace(str[pos])) {
|
|
pos++;
|
|
}
|
|
while (pos < str.length()) {
|
|
size_t word_start = pos;
|
|
while (pos < str.length() && !isspace(str[pos])) {
|
|
pos++;
|
|
}
|
|
words.push_back(str.substr(word_start, pos - word_start));
|
|
num_words++;
|
|
|
|
while (pos < str.length() && isspace(str[pos])) {
|
|
pos++;
|
|
}
|
|
}
|
|
|
|
return num_words;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: tokenize
|
|
// Description: Chops the source string up into pieces delimited by
|
|
// any of the characters specified in delimiters.
|
|
// Repeated delimiter characters represent zero-length
|
|
// tokens.
|
|
//
|
|
// It is the user's responsibility to ensure the output
|
|
// vector is cleared before calling this function; the
|
|
// results will simply be appended to the end of the
|
|
// vector.
|
|
////////////////////////////////////////////////////////////////////
|
|
void
|
|
tokenize(const string &str, vector_string &words, const string &delimiters) {
|
|
size_t p = 0;
|
|
while (p < str.length()) {
|
|
size_t q = str.find_first_of(delimiters, p);
|
|
if (q == string::npos) {
|
|
words.push_back(str.substr(p));
|
|
return;
|
|
}
|
|
words.push_back(str.substr(p, q - p));
|
|
p = q + 1;
|
|
}
|
|
words.push_back(string());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: trim_left
|
|
// Description: Returns a new string representing the contents of the
|
|
// given string with the leading whitespace removed.
|
|
////////////////////////////////////////////////////////////////////
|
|
string
|
|
trim_left(const string &str) {
|
|
size_t begin = 0;
|
|
while (begin < str.size() && isspace(str[begin])) {
|
|
begin++;
|
|
}
|
|
|
|
return str.substr(begin);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: trim_right
|
|
// Description: Returns a new string representing the contents of the
|
|
// given string with the trailing whitespace removed.
|
|
////////////////////////////////////////////////////////////////////
|
|
string
|
|
trim_right(const string &str) {
|
|
size_t begin = 0;
|
|
size_t end = str.size();
|
|
while (end > begin && isspace(str[end - 1])) {
|
|
end--;
|
|
}
|
|
|
|
return str.substr(begin, end - begin);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: string_to_int
|
|
// Description: A string-interface wrapper around the C library
|
|
// strtol(). This parses the ASCII representation of an
|
|
// integer, and then sets tail to everything that
|
|
// follows the first valid integer read. If, on exit,
|
|
// str == tail, there was no valid integer in the
|
|
// source string; if !tail.empty(), there was garbage
|
|
// after the integer.
|
|
//
|
|
// It is legal if str and tail refer to the same string.
|
|
////////////////////////////////////////////////////////////////////
|
|
int
|
|
string_to_int(const string &str, string &tail) {
|
|
const char *nptr = str.c_str();
|
|
char *endptr;
|
|
int result = strtol(nptr, &endptr, 10);
|
|
tail = endptr;
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: string_to_int
|
|
// Description: Another flavor of string_to_int(), this one returns
|
|
// true if the string is a perfectly valid integer (and
|
|
// sets result to that value), or false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool
|
|
string_to_int(const string &str, int &result) {
|
|
string tail;
|
|
result = string_to_int(str, tail);
|
|
return tail.empty();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: string_to_double
|
|
// Description: A string-interface wrapper around the C library
|
|
// strtol(). This parses the ASCII representation of an
|
|
// floating-point number, and then sets tail to
|
|
// everything that follows the first valid integer read.
|
|
// If, on exit, str == tail, there was no valid integer
|
|
// in the source string; if !tail.empty(), there was
|
|
// garbage after the number.
|
|
//
|
|
// It is legal if str and tail refer to the same string.
|
|
////////////////////////////////////////////////////////////////////
|
|
double
|
|
string_to_double(const string &str, string &tail) {
|
|
const char *nptr = str.c_str();
|
|
char *endptr;
|
|
double result = strtod(nptr, &endptr);
|
|
tail = endptr;
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: string_to_double
|
|
// Description: Another flavor of string_to_double(), this one
|
|
// returns true if the string is a perfectly valid
|
|
// number (and sets result to that value), or false
|
|
// otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool
|
|
string_to_double(const string &str, double &result) {
|
|
string tail;
|
|
result = string_to_double(str, tail);
|
|
return tail.empty();
|
|
}
|