blob: 87840bf50cc0a1bce41d69cbf6a0a97ed3c486b3 [file] [log] [blame]
/*
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NB_STRING_INTERNER_H_
#define NB_STRING_INTERNER_H_
#include <set>
#include <string>
#include <vector>
#include "starboard/configuration.h"
#include "starboard/mutex.h"
#include "starboard/types.h"
namespace nb {
// Takes a String and "interns" it, so that there is only one copy. Care is
// taken to prevent memory allocation whenever possible. Intern() will only
// allocate memory if the element is not found, otherwise it's expected to be
// memory allocation free.
//
// A common use case is to never call Clear() or destroy the StringIntern,
// since that will invalidate all std::string* that have been returned.
//
// Example:
// StringInterner str_interner;
// std::string a = "A";
// std::string a_copy = "A";
//
// EXPECT_EQ(str_interner.Intern(a),
// str_interner.Intern(a_copy));
//
class StringInterner {
public:
StringInterner();
~StringInterner(); // All outstanding const std::string* are invalidated.
// Returns an equivalent string to the input. If the input is missing from
// the data store then a copy-by-value is made.
const std::string& Intern(const std::string& str);
const std::string& Intern(const char* c_string);
// Returns the string object if it exists, otherwise NULL.
const std::string* Get(const std::string& str) const;
const std::string* Get(const char* c_string) const;
size_t Size() const;
private:
const std::string& Intern_Locked(const std::string& str);
const std::string* Get_Locked(const std::string& str) const;
std::set<std::string> string_set_;
mutable starboard::Mutex mutex_;
mutable std::string scratch_;
SB_DISALLOW_COPY_AND_ASSIGN(StringInterner);
};
class ConcurrentStringInterner {
public:
explicit ConcurrentStringInterner(size_t table_size = 32);
~ConcurrentStringInterner(); // All outstanding const std::string* are invalidated.
// Returns an equivalent string to the input. If the input is missing from
// the data store then a copy-by-value is made.
const std::string& Intern(const std::string& str);
const std::string& Intern(const char* c_string);
// Returns the string object if it exists, otherwise NULL.
const std::string* Get(const std::string& str) const;
const std::string* Get(const char* c_string) const;
size_t Size() const;
private:
void Construct(size_t table_size);
StringInterner& GetBucket(const char* string, size_t n);
const StringInterner& GetBucket(const char* string, size_t n) const;
std::vector<StringInterner*> string_interner_table_;
SB_DISALLOW_COPY_AND_ASSIGN(ConcurrentStringInterner);
};
} // namespace nb
#endif // NB_STRING_INTERNER_H_