servlib/prophet/Dictionary.cc
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/prophet/Dictionary.cc	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,177 @@
+/*
+ *    Copyright 2007 Baylor University
+ *
+ *    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.
+ */
+
+#include "Dictionary.h"
+
+namespace prophet
+{
+
+// Reserve 0xffff as in-band error report
+const u_int16_t Dictionary::INVALID_SID = 0xffff;
+const std::string Dictionary::NULL_STR;
+
+Dictionary::Dictionary(const std::string& sender, 
+                       const std::string& receiver)
+    : sender_(sender), receiver_(receiver) {}
+
+Dictionary::Dictionary(const Dictionary& d)
+    : sender_(d.sender_), receiver_(d.receiver_),
+      ribd_(d.ribd_), rribd_(d.rribd_) {}
+
+u_int16_t
+Dictionary::find(const std::string& dest_id) const
+{
+    // weed out the oddball
+    if (dest_id == "") return INVALID_SID;
+
+    // answer the easy ones before troubling map::find
+    if (dest_id == sender_) return 0;
+    if (dest_id == receiver_) return 1;
+
+    // OK, now we fall back to the Google
+    ribd::const_iterator i = (ribd::const_iterator) ribd_.find(dest_id);
+    if (i != ribd_.end()) return (*i).second;
+
+    // you fail it!
+    return INVALID_SID;
+}
+
+const std::string&
+Dictionary::find(u_int16_t id) const
+{
+    // answer the easy ones first
+    if (id == 0) return sender_;
+    if (id == 1) return receiver_;
+
+    // fall back to reverse RIBD
+    const_iterator i = (const_iterator) rribd_.find(id);
+    if (i != rribd_.end()) return (*i).second;
+
+    // no dice
+    return NULL_STR;
+}
+
+u_int16_t
+Dictionary::insert(const std::string& dest_id)
+{
+    // weed out the oddball
+    if (dest_id == "") return INVALID_SID;
+
+    // only assign once
+    if (find(dest_id) != INVALID_SID)
+        return INVALID_SID;
+
+    // our dirty little secret:  just increment the internal
+    // SID by skipping the first two (implicit sender & receiver)
+    u_int16_t sid = ribd_.size() + 2;
+
+    // somehow the dictionary filled up!?
+    if (sid == INVALID_SID) return INVALID_SID;
+
+    bool res = assign(dest_id,sid);
+    while (res == false)
+    {
+        res = assign(dest_id,++sid);
+        if (sid == INVALID_SID)
+            // sad times ... ?
+            return INVALID_SID;
+    }
+    return sid;
+}
+
+bool
+Dictionary::assign(const std::string& dest_id, u_int16_t sid)
+{
+    // weed out the oddball
+    if (dest_id == "") return false;
+
+    // these shouldn't get out of sync
+    if (ribd_.size() != rribd_.size()) return false;
+
+    // enforce sender/receiver definitions
+    if (sid == 0)
+    {
+        if (sender_ == "" && dest_id != "")
+        {
+            sender_.assign(dest_id);
+            return true;
+        }
+        return false;
+    }
+    else if (sid == 1)
+    {
+        if (receiver_ == "" && dest_id != "")
+        {
+            receiver_.assign(dest_id);
+            return true;
+        }
+        return false;
+    }
+    else if (sid == INVALID_SID)
+    {
+        // what were you thinking?
+        return false;
+    }
+
+    // attempt to insert into forward lookup
+    bool res = ribd_.insert(ribd::value_type(dest_id,sid)).second;
+    if ( ! res ) return false;
+
+    // move on to reverse lookup
+    res = rribd_.insert(rribd::value_type(sid,dest_id)).second;
+    if ( ! res )
+        ribd_.erase(dest_id);
+
+               // complain if we get out of sync
+    return res && (ribd_.size() == rribd_.size());
+}
+
+size_t
+Dictionary::guess_ribd_size(size_t RASsz) const
+{
+    size_t retval = 0;
+    for (const_iterator i = rribd_.begin(); i != rribd_.end(); i++)
+    {
+        retval += FOUR_BYTE_ALIGN( RASsz + (*i).second.length() );
+    }
+    return retval;
+}
+
+void
+Dictionary::clear()
+{
+    // wipe out everything from the dictionary
+    sender_.assign("");
+    receiver_.assign("");
+    ribd_.clear();
+    rribd_.clear();
+}
+
+void 
+Dictionary::dump(BundleCore* core,const char* file,u_int line) const
+{
+    if (core == NULL) return;
+    core->print_log("dictionary", BundleCore::LOG_DEBUG,
+            "%s(%u): 0 -> %s", file, line, sender_.c_str());
+    core->print_log("dictionary", BundleCore::LOG_DEBUG,
+            "%s(%u): 1 -> %s", file, line, receiver_.c_str());
+    for (const_iterator i = rribd_.begin(); i != rribd_.end(); i++)
+        core->print_log("dictionary", BundleCore::LOG_DEBUG,
+                "%s(%u): %u -> %s", file, line, (*i).first,
+                (*i).second.c_str());
+}
+
+}; // namespace prophet