summaryrefslogtreecommitdiff
path: root/src/mongo/util/mongoutils/str.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/mongoutils/str.h')
-rw-r--r--src/mongo/util/mongoutils/str.h374
1 files changed, 197 insertions, 177 deletions
diff --git a/src/mongo/util/mongoutils/str.h b/src/mongo/util/mongoutils/str.h
index ed7fe35411f..561bf20008c 100644
--- a/src/mongo/util/mongoutils/str.h
+++ b/src/mongo/util/mongoutils/str.h
@@ -43,189 +43,209 @@
namespace mongoutils {
- namespace str {
-
- /** the idea here is to make one liners easy. e.g.:
-
- return str::stream() << 1 << ' ' << 2;
-
- since the following doesn't work:
-
- (std::stringstream() << 1).str();
- */
- class stream {
- public:
- mongo::StringBuilder ss;
- template<class T>
- stream& operator<<(const T& v) {
- ss << v;
- return *this;
- }
- operator std::string () const { return ss.str(); }
- };
-
- inline bool startsWith(const char *str, const char *prefix) {
- const char *s = str;
- const char *p = prefix;
- while( *p ) {
- if( *p != *s ) return false;
- p++; s++;
- }
- return true;
- }
- inline bool startsWith(const std::string& s, const std::string& p) {
- return startsWith(s.c_str(), p.c_str());
- }
-
- // while these are trivial today use in case we do different wide char things later
- inline bool startsWith(const char *p, char ch) { return *p == ch; }
- inline bool startsWith(const std::string& s, char ch) { return startsWith(s.c_str(), ch); }
-
- inline bool endsWith(const std::string& s, const std::string& p) {
- int l = p.size();
- int x = s.size();
- if( x < l ) return false;
- return strncmp(s.c_str()+x-l, p.c_str(), l) == 0;
- }
- inline bool endsWith(const char *s, char p) {
- size_t len = strlen(s);
- return len && s[len-1] == p;
- }
- inline bool endsWith(const char *p, const char *suffix) {
- size_t a = strlen(p);
- size_t b = strlen(suffix);
- if ( b > a ) return false;
- return strcmp(p + a - b, suffix) == 0;
- }
-
- inline bool equals( const char * a , const char * b ) { return strcmp( a , b ) == 0; }
-
- /** find char x, and return rest of std::string thereafter, or "" if not found */
- inline const char * after(const char *s, char x) {
- const char *p = strchr(s, x);
- return (p != 0) ? p+1 : "";
- }
- inline std::string after(const std::string& s, char x) {
- const char *p = strchr(s.c_str(), x);
- return (p != 0) ? std::string(p+1) : "";
- }
-
- /** find std::string x, and return rest of std::string thereafter, or "" if not found */
- inline const char * after(const char *s, const char *x) {
- const char *p = strstr(s, x);
- return (p != 0) ? p+strlen(x) : "";
- }
- inline std::string after(const std::string& s, const std::string& x) {
- const char *p = strstr(s.c_str(), x.c_str());
- return (p != 0) ? std::string(p+x.size()) : "";
- }
-
- /** @return true if s contains x
- * These should not be used with strings containing NUL bytes
- */
- inline bool contains(const std::string& s, const std::string& x) {
- return strstr(s.c_str(), x.c_str()) != 0;
- }
- inline bool contains(const std::string& s, char x) {
- verify(x != '\0'); // this expects c-strings so don't use when looking for NUL bytes
- return strchr(s.c_str(), x) != 0;
- }
-
- /** @return everything before the character x, else entire std::string */
- inline std::string before(const std::string& s, char x) {
- const char *p = strchr(s.c_str(), x);
- return (p != 0) ? s.substr(0, p-s.c_str()) : s;
- }
-
- /** @return everything before the std::string x, else entire std::string */
- inline std::string before(const std::string& s, const std::string& x) {
- const char *p = strstr(s.c_str(), x.c_str());
- return (p != 0) ? s.substr(0, p-s.c_str()) : s;
- }
-
- /** check if if strings share a common starting prefix
- @return offset of divergence (or length if equal). 0=nothing in common. */
- inline int shareCommonPrefix(const char *p, const char *q) {
- int ofs = 0;
- while( 1 ) {
- if( *p == 0 || *q == 0 )
- break;
- if( *p != *q )
- break;
- p++; q++; ofs++;
- }
- return ofs;
- }
- inline int shareCommonPrefix(const std::string &a, const std::string &b)
- { return shareCommonPrefix(a.c_str(), b.c_str()); }
-
- /** std::string to unsigned. zero if not a number. can end with non-num chars */
- inline unsigned toUnsigned(const std::string& a) {
- unsigned x = 0;
- const char *p = a.c_str();
- while( 1 ) {
- if( !isdigit(*p) )
- break;
- x = x * 10 + (*p - '0');
- p++;
- }
- return x;
- }
-
- /** split a std::string on a specific char. We don't split N times, just once
- on the first occurrence. If char not present entire std::string is in L
- and R is empty.
- @return true if char found
- */
- inline bool splitOn(const std::string &s, char c, std::string& L, std::string& R) {
- const char *start = s.c_str();
- const char *p = strchr(start, c);
- if( p == 0 ) {
- L = s; R.clear();
- return false;
- }
- L = std::string(start, p-start);
- R = std::string(p+1);
- return true;
- }
- /** split scanning reverse direction. Splits ONCE ONLY. */
- inline bool rSplitOn(const std::string &s, char c, std::string& L, std::string& R) {
- const char *start = s.c_str();
- const char *p = strrchr(start, c);
- if( p == 0 ) {
- L = s; R.clear();
- return false;
- }
- L = std::string(start, p-start);
- R = std::string(p+1);
- return true;
- }
-
- /** @return number of occurrences of c in s */
- inline unsigned count( const std::string& s , char c ) {
- unsigned n=0;
- for ( unsigned i=0; i<s.size(); i++ )
- if ( s[i] == c )
- n++;
- return n;
- }
-
- /** trim leading spaces. spaces only, not tabs etc. */
- inline std::string ltrim(const std::string& s) {
- const char *p = s.c_str();
- while( *p == ' ' ) p++;
- return p;
- }
-
- } // namespace str
+namespace str {
+
+/** the idea here is to make one liners easy. e.g.:
+
+ return str::stream() << 1 << ' ' << 2;
+
+ since the following doesn't work:
+
+ (std::stringstream() << 1).str();
+*/
+class stream {
+public:
+ mongo::StringBuilder ss;
+ template <class T>
+ stream& operator<<(const T& v) {
+ ss << v;
+ return *this;
+ }
+ operator std::string() const {
+ return ss.str();
+ }
+};
+
+inline bool startsWith(const char* str, const char* prefix) {
+ const char* s = str;
+ const char* p = prefix;
+ while (*p) {
+ if (*p != *s)
+ return false;
+ p++;
+ s++;
+ }
+ return true;
+}
+inline bool startsWith(const std::string& s, const std::string& p) {
+ return startsWith(s.c_str(), p.c_str());
+}
+
+// while these are trivial today use in case we do different wide char things later
+inline bool startsWith(const char* p, char ch) {
+ return *p == ch;
+}
+inline bool startsWith(const std::string& s, char ch) {
+ return startsWith(s.c_str(), ch);
+}
+
+inline bool endsWith(const std::string& s, const std::string& p) {
+ int l = p.size();
+ int x = s.size();
+ if (x < l)
+ return false;
+ return strncmp(s.c_str() + x - l, p.c_str(), l) == 0;
+}
+inline bool endsWith(const char* s, char p) {
+ size_t len = strlen(s);
+ return len && s[len - 1] == p;
+}
+inline bool endsWith(const char* p, const char* suffix) {
+ size_t a = strlen(p);
+ size_t b = strlen(suffix);
+ if (b > a)
+ return false;
+ return strcmp(p + a - b, suffix) == 0;
+}
+
+inline bool equals(const char* a, const char* b) {
+ return strcmp(a, b) == 0;
+}
+
+/** find char x, and return rest of std::string thereafter, or "" if not found */
+inline const char* after(const char* s, char x) {
+ const char* p = strchr(s, x);
+ return (p != 0) ? p + 1 : "";
+}
+inline std::string after(const std::string& s, char x) {
+ const char* p = strchr(s.c_str(), x);
+ return (p != 0) ? std::string(p + 1) : "";
+}
+
+/** find std::string x, and return rest of std::string thereafter, or "" if not found */
+inline const char* after(const char* s, const char* x) {
+ const char* p = strstr(s, x);
+ return (p != 0) ? p + strlen(x) : "";
+}
+inline std::string after(const std::string& s, const std::string& x) {
+ const char* p = strstr(s.c_str(), x.c_str());
+ return (p != 0) ? std::string(p + x.size()) : "";
+}
+
+/** @return true if s contains x
+ * These should not be used with strings containing NUL bytes
+ */
+inline bool contains(const std::string& s, const std::string& x) {
+ return strstr(s.c_str(), x.c_str()) != 0;
+}
+inline bool contains(const std::string& s, char x) {
+ verify(x != '\0'); // this expects c-strings so don't use when looking for NUL bytes
+ return strchr(s.c_str(), x) != 0;
+}
+
+/** @return everything before the character x, else entire std::string */
+inline std::string before(const std::string& s, char x) {
+ const char* p = strchr(s.c_str(), x);
+ return (p != 0) ? s.substr(0, p - s.c_str()) : s;
+}
+
+/** @return everything before the std::string x, else entire std::string */
+inline std::string before(const std::string& s, const std::string& x) {
+ const char* p = strstr(s.c_str(), x.c_str());
+ return (p != 0) ? s.substr(0, p - s.c_str()) : s;
+}
+
+/** check if if strings share a common starting prefix
+ @return offset of divergence (or length if equal). 0=nothing in common. */
+inline int shareCommonPrefix(const char* p, const char* q) {
+ int ofs = 0;
+ while (1) {
+ if (*p == 0 || *q == 0)
+ break;
+ if (*p != *q)
+ break;
+ p++;
+ q++;
+ ofs++;
+ }
+ return ofs;
+}
+inline int shareCommonPrefix(const std::string& a, const std::string& b) {
+ return shareCommonPrefix(a.c_str(), b.c_str());
+}
+
+/** std::string to unsigned. zero if not a number. can end with non-num chars */
+inline unsigned toUnsigned(const std::string& a) {
+ unsigned x = 0;
+ const char* p = a.c_str();
+ while (1) {
+ if (!isdigit(*p))
+ break;
+ x = x * 10 + (*p - '0');
+ p++;
+ }
+ return x;
+}
+
+/** split a std::string on a specific char. We don't split N times, just once
+ on the first occurrence. If char not present entire std::string is in L
+ and R is empty.
+ @return true if char found
+*/
+inline bool splitOn(const std::string& s, char c, std::string& L, std::string& R) {
+ const char* start = s.c_str();
+ const char* p = strchr(start, c);
+ if (p == 0) {
+ L = s;
+ R.clear();
+ return false;
+ }
+ L = std::string(start, p - start);
+ R = std::string(p + 1);
+ return true;
+}
+/** split scanning reverse direction. Splits ONCE ONLY. */
+inline bool rSplitOn(const std::string& s, char c, std::string& L, std::string& R) {
+ const char* start = s.c_str();
+ const char* p = strrchr(start, c);
+ if (p == 0) {
+ L = s;
+ R.clear();
+ return false;
+ }
+ L = std::string(start, p - start);
+ R = std::string(p + 1);
+ return true;
+}
+
+/** @return number of occurrences of c in s */
+inline unsigned count(const std::string& s, char c) {
+ unsigned n = 0;
+ for (unsigned i = 0; i < s.size(); i++)
+ if (s[i] == c)
+ n++;
+ return n;
+}
+
+/** trim leading spaces. spaces only, not tabs etc. */
+inline std::string ltrim(const std::string& s) {
+ const char* p = s.c_str();
+ while (*p == ' ')
+ p++;
+ return p;
+}
+
+} // namespace str
} // namespace mongoutils
namespace mongo {
- using namespace mongoutils;
+using namespace mongoutils;
#if defined(_WIN32)
- inline int strcasecmp(const char* s1, const char* s2) {return _stricmp(s1, s2);}
+inline int strcasecmp(const char* s1, const char* s2) {
+ return _stricmp(s1, s2);
+}
#endif
} // namespace mongo