MongoDB C++ Driver  legacy-1.1.2
namespace_string-inl.h
1 // namespacestring-inl.h
2 
3 
4 /* Copyright 2014 MongoDB Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "mongo/util/debug_util.h"
20 
21 namespace mongo {
22 
23 inline StringData NamespaceString::db() const {
24  return _dotIndex == std::string::npos ? StringData() : StringData(_ns.c_str(), _dotIndex);
25 }
26 
27 inline StringData NamespaceString::coll() const {
28  return _dotIndex == std::string::npos ? StringData() : StringData(_ns.c_str() + _dotIndex + 1,
29  _ns.size() - 1 - _dotIndex);
30 }
31 
32 inline bool NamespaceString::normal(const StringData& ns) {
33  if (ns.find('$') == std::string::npos)
34  return true;
35  return oplog(ns);
36 }
37 
38 inline bool NamespaceString::oplog(const StringData& ns) {
39  return ns.startsWith("local.oplog.");
40 }
41 
42 inline bool NamespaceString::special(const StringData& ns) {
43  return !normal(ns) || ns.substr(ns.find('.')).startsWith(".system.");
44 }
45 
46 inline bool NamespaceString::validDBName(const StringData& db) {
47  if (db.size() == 0 || db.size() > 64)
48  return false;
49 
50  for (StringData::const_iterator iter = db.begin(), end = db.end(); iter != end; ++iter) {
51  switch (*iter) {
52  case '\0':
53  case '/':
54  case '\\':
55  case '.':
56  case ' ':
57  case '"':
58  return false;
59 #ifdef _WIN32
60  // We prohibit all FAT32-disallowed characters on Windows
61  case '*':
62  case '<':
63  case '>':
64  case ':':
65  case '|':
66  case '?':
67  return false;
68 #endif
69  default:
70  continue;
71  }
72  }
73  return true;
74 }
75 
77  size_t idx = ns.find('.');
78  if (idx == std::string::npos)
79  return false;
80 
81  return validCollectionName(ns.substr(idx + 1)) || oplog(ns);
82 }
83 
85  if (coll.empty())
86  return false;
87 
88  if (coll[0] == '.')
89  return false;
90 
91  for (StringData::const_iterator iter = coll.begin(), end = coll.end(); iter != end; ++iter) {
92  switch (*iter) {
93  case '\0':
94  case '$':
95  return false;
96  default:
97  continue;
98  }
99  }
100 
101  return true;
102 }
103 
104 inline NamespaceString::NamespaceString() : _ns(), _dotIndex(0) {}
106  _ns = nsIn.toString(); // copy to our buffer
107  _dotIndex = _ns.find('.');
108 }
109 
110 inline NamespaceString::NamespaceString(const StringData& dbName, const StringData& collectionName)
111  : _ns(dbName.size() + collectionName.size() + 1, '\0') {
112  uassert(17235,
113  "'.' is an invalid character in a database name",
114  dbName.find('.') == std::string::npos);
115  uassert(17246,
116  "Collection names cannot start with '.'",
117  collectionName.empty() || collectionName[0] != '.');
118  std::string::iterator it = std::copy(dbName.begin(), dbName.end(), _ns.begin());
119  *it = '.';
120  ++it;
121  it = std::copy(collectionName.begin(), collectionName.end(), it);
122  _dotIndex = dbName.size();
123  dassert(it == _ns.end());
124  dassert(_ns[_dotIndex] == '.');
125  uassert(17295,
126  "namespaces cannot have embedded null characters",
127  _ns.find('\0') == std::string::npos);
128 }
129 
130 inline int nsDBHash(const std::string& ns) {
131  int hash = 7;
132  for (size_t i = 0; i < ns.size(); i++) {
133  if (ns[i] == '.')
134  break;
135  hash += 11 * (ns[i]);
136  hash *= 3;
137  }
138  return hash;
139 }
140 
141 inline bool nsDBEquals(const std::string& a, const std::string& b) {
142  for (size_t i = 0; i < a.size(); i++) {
143  if (a[i] == '.') {
144  // b has to either be done or a '.'
145 
146  if (b.size() == i)
147  return true;
148 
149  if (b[i] == '.')
150  return true;
151 
152  return false;
153  }
154 
155  // a is another character
156  if (b.size() == i)
157  return false;
158 
159  if (b[i] != a[i])
160  return false;
161  }
162 
163  // a is done
164  // make sure b is done
165  if (b.size() == a.size() || b[a.size()] == '.')
166  return true;
167 
168  return false;
169 }
170 
171 /* future : this doesn't need to be an inline. */
172 inline std::string NamespaceString::getSisterNS(const StringData& local) const {
173  verify(local.size() && local[0] != '.');
174  return db().toString() + "." + local.toString();
175 }
176 
177 inline std::string NamespaceString::getSystemIndexesCollection() const {
178  return db().toString() + ".system.indexes";
179 }
180 
181 inline std::string NamespaceString::getCommandNS() const {
182  return db().toString() + ".$cmd";
183 }
184 }
static bool validCollectionComponent(const StringData &ns)
Takes a fully qualified namespace (ie dbname.collectionName), and returns true if the collection name...
Definition: namespace_string-inl.h:76
static bool oplog(const StringData &ns)
Definition: namespace_string-inl.h:38
A StringData object wraps a 'const string&' or a 'const char*' without copying its contents...
Definition: string_data.h:43
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20
static bool normal(const StringData &ns)
Definition: namespace_string-inl.h:32
static bool validDBName(const StringData &dbin)
samples: good foo bar foo-bar bad: foo bar foo.bar foo"bar
Definition: namespace_string-inl.h:46
NamespaceString()
Constructs an empty NamespaceString.
Definition: namespace_string-inl.h:104
static bool validCollectionName(const StringData &coll)
Takes a collection name and returns true if it is a valid collection name.
Definition: namespace_string-inl.h:84
std::string getSisterNS(const StringData &local) const
( foo.bar ).getSisterNS( "blah" ) == foo.blah
Definition: namespace_string-inl.h:172
int nsDBHash(const std::string &ns)
NamespaceDBHash and NamespaceDBEquals allow you to do something like unordered_map and use the full namespace for the string but comparisons are done only on the db piece.
Definition: namespace_string-inl.h:130
bool startsWith(const StringData &prefix) const
Returns true if 'prefix' is a substring of this instance, anchored at position 0. ...
Definition: string_data-inl.h:109