/* [<][>][^][v][top][bottom][index][help] */
// string_table.h -- A shared string table for Gnash.
//
// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
// 2011 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 <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/thread.hpp>
#include <string>
#include <map>
#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(const std::string& val, std::size_t i)
:
value(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<svt,
boost::multi_index::indexed_by<
boost::multi_index::hashed_unique<
boost::multi_index::tag<StringValue>,
boost::multi_index::member<svt, std::string, &svt::value> >,
boost::multi_index::hashed_unique<
boost::multi_index::tag<StringID>,
boost::multi_index::member<svt, std::size_t, &svt::id>
>
> > 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<StringID>::type::iterator r =
_table.get<StringID>().find(to_find);
return (r == _table.get<StringID>().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;
boost::mutex _lock;
std::size_t _highestKey;
std::map<key, key> _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