1 // stringutils.h
2 
3 
4 /**
5  *    Copyright (C) 2018-present MongoDB, Inc.
6  *
7  *    This program is free software: you can redistribute it and/or modify
8  *    it under the terms of the Server Side Public License, version 1,
9  *    as published by MongoDB, Inc.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    Server Side Public License for more details.
15  *
16  *    You should have received a copy of the Server Side Public License
17  *    along with this program. If not, see
18  *    <http://www.mongodb.com/licensing/server-side-public-license>.
19  *
20  *    As a special exception, the copyright holders give permission to link the
21  *    code of portions of this program with the OpenSSL library under certain
22  *    conditions as described in each individual source file and distribute
23  *    linked combinations including the program with the OpenSSL library. You
24  *    must comply with the Server Side Public License in all respects for
25  *    all of the code used other than as permitted herein. If you modify file(s)
26  *    with this exception, you may extend this exception to your version of the
27  *    file(s), but you are not obligated to do so. If you do not wish to do so,
28  *    delete this exception statement from your version. If you delete this
29  *    exception statement from all source files in the program, then also delete
30  *    it in the license file.
31  */
32 
33 #pragma once
34 
35 #include <ctype.h>
36 
37 #include <boost/optional.hpp>
38 #include <memory>
39 #include <string>
40 #include <vector>
41 
42 #include "mongo/base/string_data.h"
43 
44 namespace mongo {
45 
46 // see also mongoutils/str.h - perhaps move these there?
47 // see also text.h
48 
49 void splitStringDelim(const std::string& str, std::vector<std::string>* res, char delim);
50 
51 void joinStringDelim(const std::vector<std::string>& strs, std::string* res, char delim);
52 
tolowerString(StringData input)53 inline std::string tolowerString(StringData input) {
54     std::string::size_type sz = input.size();
55 
56     std::unique_ptr<char[]> line(new char[sz + 1]);
57     char* copy = line.get();
58 
59     for (std::string::size_type i = 0; i < sz; i++) {
60         char c = input[i];
61         copy[i] = (char)tolower((int)c);
62     }
63     copy[sz] = 0;
64     return copy;
65 }
66 
toAsciiLowerCase(StringData input)67 inline std::string toAsciiLowerCase(StringData input) {
68     size_t sz = input.size();
69     std::unique_ptr<char[]> line(new char[sz + 1]);
70     char* res = line.get();
71     for (size_t i = 0; i < sz; i++) {
72         char c = input[i];
73         if (c >= 'A' && c <= 'Z') {
74             res[i] = c + 32;
75         } else {
76             res[i] = c;
77         }
78     }
79     res[sz] = 0;
80     return res;
81 }
82 
83 /** Functor for combining lexical and numeric comparisons. */
84 class LexNumCmp {
85 public:
86     /** @param lexOnly - compare all characters lexically, including digits. */
87     LexNumCmp(bool lexOnly);
88     /**
89      * Non numeric characters are compared lexicographically; numeric substrings
90      * are compared numerically; dots separate ordered comparable subunits.
91      * For convenience, character 255 is greater than anything else.
92      * @param lexOnly - compare all characters lexically, including digits.
93      */
94     static int cmp(StringData s1, StringData s2, bool lexOnly);
95     int cmp(StringData s1, StringData s2) const;
96     bool operator()(StringData s1, StringData s2) const;
97 
98 private:
99     bool _lexOnly;
100 };
101 
102 // TODO: Sane-ify core std::string functionality
103 // For now, this needs to be near the LexNumCmp or else
104 int versionCmp(const StringData rhs, const StringData lhs);
105 
106 /**
107  * A method to escape whitespace and control characters in strings. For example, the string "\t"
108  * goes to "\\t". If `escape_slash` is true, then "/" goes to "\\/".
109  */
110 std::string escape(StringData s, bool escape_slash = false);
111 
112 /**
113  * Converts 'integer' from a base-10 string to a size_t value or returns boost::none if 'integer'
114  * is not a valid base-10 string. A valid string is not allowed to have anything but decimal
115  * numerals, not even a +/- prefix or leading/trailing whitespace.
116  */
117 boost::optional<size_t> parseUnsignedBase10Integer(StringData integer);
118 
119 }  // namespace mongo
120