diff options
Diffstat (limited to 'kopete/protocols/jabber/jingle/libjingle/talk/xmllite/qname.cpp')
-rw-r--r-- | kopete/protocols/jabber/jingle/libjingle/talk/xmllite/qname.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/qname.cpp b/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/qname.cpp new file mode 100644 index 00000000..e20b57e3 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/qname.cpp @@ -0,0 +1,167 @@ +/* + * libjingle + * Copyright 2004--2005, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string> +#include "talk/base/common.h" +#include "talk/xmllite/xmlelement.h" +#include "talk/xmllite/qname.h" +#include "talk/xmllite/xmlconstants.h" + +//#define new TRACK_NEW + +namespace buzz { + +static int TQName_Hash(const std::string & ns, const char * local) { + int result = ns.size() * 101; + while (*local) { + result *= 19; + result += *local; + local += 1; + } + return result; +} + +static const int bits = 9; +static TQName::Data * get_qname_table() { + static TQName::Data qname_table[1 << bits]; + return qname_table; +} + +static TQName::Data * +AllocateOrFind(const std::string & ns, const char * local) { + int index = TQName_Hash(ns, local); + int increment = index >> (bits - 1) | 1; + TQName::Data * qname_table = get_qname_table(); + for (;;) { + index &= ((1 << bits) - 1); + if (!qname_table[index].Occupied()) { + return new TQName::Data(ns, local); + } + if (qname_table[index].localPart_ == local && + qname_table[index].namespace_ == ns) { + qname_table[index].AddRef(); + return qname_table + index; + } + index += increment; + } +} + +static TQName::Data * +Add(const std::string & ns, const char * local) { + int index = TQName_Hash(ns, local); + int increment = index >> (bits - 1) | 1; + TQName::Data * qname_table = get_qname_table(); + for (;;) { + index &= ((1 << bits) - 1); + if (!qname_table[index].Occupied()) { + qname_table[index].namespace_ = ns; + qname_table[index].localPart_ = local; + qname_table[index].AddRef(); // AddRef twice so it's never deleted + qname_table[index].AddRef(); + return qname_table + index; + } + if (qname_table[index].localPart_ == local && + qname_table[index].namespace_ == ns) { + qname_table[index].AddRef(); + return qname_table + index; + } + index += increment; + } +} + +TQName::~TQName() { + data_->Release(); +} + +TQName::TQName() : data_(TQN_EMPTY.data_) { + data_->AddRef(); +} + +TQName::TQName(bool add, const std::string & ns, const char * local) : + data_(add ? Add(ns, local) : AllocateOrFind(ns, local)) {} + +TQName::TQName(bool add, const std::string & ns, const std::string & local) : + data_(add ? Add(ns, local.c_str()) : AllocateOrFind(ns, local.c_str())) {} + +TQName::TQName(const std::string & ns, const char * local) : + data_(AllocateOrFind(ns, local)) {} + +static std::string +TQName_LocalPart(const std::string & name) { + size_t i = name.rfind(':'); + if (i == std::string::npos) + return name; + return name.substr(i + 1); +} + +static std::string +TQName_Namespace(const std::string & name) { + size_t i = name.rfind(':'); + if (i == std::string::npos) + return STR_EMPTY; + return name.substr(0, i); +} + +TQName::TQName(const std::string & mergedOrLocal) : + data_(AllocateOrFind(TQName_Namespace(mergedOrLocal), + TQName_LocalPart(mergedOrLocal).c_str())) {} + +std::string +TQName::Merged() const { + if (data_->namespace_ == STR_EMPTY) + return data_->localPart_; + + std::string result(data_->namespace_); + result.reserve(result.length() + 1 + data_->localPart_.length()); + result += ':'; + result += data_->localPart_; + return result; +} + +bool +TQName::operator==(const TQName & other) const { + return other.data_ == data_ || + data_->localPart_ == other.data_->localPart_ && + data_->namespace_ == other.data_->namespace_; +} + +int +TQName::Compare(const TQName & other) const { + if (data_ == other.data_) + return 0; + + int result = data_->localPart_.compare(other.data_->localPart_); + if (result) + return result; + + return data_->namespace_.compare(other.data_->namespace_); +} + +} + + + |