// string_table.h -- A shared string table for Gnash. // // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 // Free Software Foundation, Inc // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef GNASH_STRING_TABLE_H #define GNASH_STRING_TABLE_H // Thread Status: SAFE, except for group functions. // The group functions may have strange behavior when trying to automatically // lowercase the additions. #include #include #include #include #include #include #include #include "dsodefs.h" namespace gnash { // So many strings are duplicated (such as standard property names) // that a string table could give significant memory savings. /// A general use string table. class DSOEXPORT string_table { public: /// A little helper for indexing. struct svt { svt(std::string val, std::size_t i) : value(std::move(val)), id(i) {} std::string value; std::size_t id; }; /// A tag to identify the key index. struct StringID {}; /// A tag to identify the string index. struct StringValue {}; /// The container for indexing the strings // /// This contains two indices with no duplicate values: /// 1. An index of unique, case-sensitive strings. /// 2. An index of unique numeric keys. typedef boost::multi_index_container, boost::multi_index::member >, boost::multi_index::hashed_unique< boost::multi_index::tag, boost::multi_index::member > > > table; typedef std::size_t key; /// Find a key for a string. // /// By default a key will be created for a string that isn't present. // /// @param to_find The string to be found. /// @param insert_unfound If this is set to false, a search is /// performed, but no update. /// @return A key which can be used in value or 0 if the /// string is not yet in the table and /// insert_unfound was false. key find(const std::string& to_find, bool insert_unfound = true); /// Find a string by its key. // /// @param key The key of the string to return. /// @return The string which matches key or "" if an invalid key is /// given. const std::string& value(key to_find) const { if (_table.empty() || !to_find) return _empty; table::index::type::iterator r = _table.get().find(to_find); return (r == _table.get().end()) ? _empty : r->value; } /// Insert a string with auto-assigned id. // /// @return The assigned key key insert(const std::string& to_insert); /// Insert a group of strings with their ids preset. // /// @param pList An array of svt objects, these should be fully /// constructed, including their ids. If any id is /// duplicated, the insertion will fail. /// @param size Number of elements in the svt objects array void insert_group(const svt* pList, std::size_t size); /// Insert a string when you will handle the locking yourself. // /// @param to_insert The string to insert /// @return The assigned key key already_locked_insert(const std::string& to_insert); /// Construct the empty string_table string_table() : _highestKey(0), _highestKnownLowercase(0) {} /// Return a caseless equivalent of the passed key. // /// @param a The key to find a caseless equivalent for. The key /// may be its own caseless equivalent, in which case the /// same key will be returned. key noCase(key a) const; /// Set the highest key value known to correspond to a lowercase name // void setHighestKnownLowercase(std::size_t k); private: table _table; static const std::string _empty; std::mutex _lock; std::size_t _highestKey; std::map _caseTable; key _highestKnownLowercase; }; /// Check whether two keys are equivalent // /// This function provides a simple way to check for equivalence either in /// a case sensitive or case-insensitive way. It is mainly for convenience, to /// reduce conditionals in the code. // /// If the comparison is case-sensitive, the keys are equivalent if they are /// equal. // /// @param st The string table to use /// @param a One key to check /// @param b The other key to check /// @param caseless Whether to compare in a case-insensitive way. /// @return True if the keys are equivalent. DSOEXPORT bool equal(string_table& st, string_table::key a, string_table::key b, bool caseless); } #endif