// namespacestring-inl.h /** * Copyright (C) 2013 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ namespace mongo { inline StringData NamespaceString::db() const { return _dotIndex == std::string::npos ? StringData() : StringData( _ns.c_str(), _dotIndex ); } inline StringData NamespaceString::coll() const { return _dotIndex == std::string::npos ? StringData() : StringData( _ns.c_str() + _dotIndex + 1, _ns.size() - 1 - _dotIndex ); } inline bool NamespaceString::normal(const StringData& ns) { if ( ns.find( '$' ) == std::string::npos ) return true; return oplog(ns); } inline bool NamespaceString::oplog(const StringData& ns) { return ns == "local.oplog.rs" || ns == "local.oplog.$main"; } inline bool NamespaceString::special(const StringData& ns) { return !normal(ns) || ns.substr(ns.find('.')).startsWith(".system."); } inline bool NamespaceString::validDBName( const StringData& db ) { if ( db.size() == 0 || db.size() > 64 ) return false; for (StringData::const_iterator iter = db.begin(), end = db.end(); iter != end; ++iter) { switch (*iter) { case '\0': case '/': case '\\': case '.': case ' ': case '"': return false; #ifdef _WIN32 // We prohibit all FAT32-disallowed characters on Windows case '*': case '<': case '>': case ':': case '|': case '?': return false; #endif default: continue; } } return true; } inline bool NamespaceString::validCollectionComponent(const StringData& ns){ size_t idx = ns.find( '.' ); if ( idx == std::string::npos ) return false; return validCollectionName(ns.substr(idx + 1)) || oplog(ns); } inline bool NamespaceString::validCollectionName(const StringData& coll){ if (coll.empty()) return false; for (StringData::const_iterator iter = coll.begin(), end = coll.end(); iter != end; ++iter) { switch (*iter) { case '\0': case '$': return false; default: continue; } } return true; } inline NamespaceString::NamespaceString() : _ns(), _dotIndex(0) {} inline NamespaceString::NamespaceString( const StringData& nsIn ) { _ns = nsIn.toString(); // copy to our buffer _dotIndex = _ns.find( '.' ); } inline NamespaceString::NamespaceString( const StringData& dbName, const StringData& collectionName ) : _ns(dbName.size() + collectionName.size() + 1, '\0') { uassert(17235, "'.' is an invalid character in a database name", dbName.find('.') == std::string::npos); uassert(17246, "Collection names cannot start with '.'", collectionName.empty() || collectionName[0] != '.'); std::string::iterator it = std::copy(dbName.begin(), dbName.end(), _ns.begin()); *it = '.'; ++it; it = std::copy(collectionName.begin(), collectionName.end(), it); _dotIndex = dbName.size(); dassert(it == _ns.end()); dassert(_ns[_dotIndex] == '.'); uassert(17295, "namespaces cannot have embedded null characters", _ns.find('\0') == std::string::npos); } inline int nsDBHash( const std::string& ns ) { int hash = 7; for ( size_t i = 0; i < ns.size(); i++ ) { if ( ns[i] == '.' ) break; hash += 11 * ( ns[i] ); hash *= 3; } return hash; } inline bool nsDBEquals( const std::string& a, const std::string& b ) { for ( size_t i = 0; i < a.size(); i++ ) { if ( a[i] == '.' ) { // b has to either be done or a '.' if ( b.size() == i ) return true; if ( b[i] == '.' ) return true; return false; } // a is another character if ( b.size() == i ) return false; if ( b[i] != a[i] ) return false; } // a is done // make sure b is done if ( b.size() == a.size() || b[a.size()] == '.' ) return true; return false; } /* future : this doesn't need to be an inline. */ inline std::string NamespaceString::getSisterNS( const StringData& local ) const { verify( local.size() && local[0] != '.' ); return db().toString() + "." + local.toString(); } inline std::string NamespaceString::getSystemIndexesCollection() const { return db().toString() + ".system.indexes"; } inline std::string NamespaceString::getCommandNS() const { return db().toString() + ".$cmd"; } }