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