summaryrefslogtreecommitdiff
path: root/lout/object.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lout/object.cc')
-rw-r--r--lout/object.cc395
1 files changed, 395 insertions, 0 deletions
diff --git a/lout/object.cc b/lout/object.cc
new file mode 100644
index 0000000..933e7aa
--- /dev/null
+++ b/lout/object.cc
@@ -0,0 +1,395 @@
+/*
+ * RTFL (originally part of dillo)
+ *
+ * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * 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; with the following exception:
+ *
+ * The copyright holders of RTFL give you permission to link this file
+ * statically or dynamically against all versions of the graphviz
+ * library, which are published by AT&T Corp. under one of the following
+ * licenses:
+ *
+ * - Common Public License version 1.0 as published by International
+ * Business Machines Corporation (IBM), or
+ * - Eclipse Public License version 1.0 as published by the Eclipse
+ * Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+#include "object.hh"
+#include <stdio.h>
+#include <stdint.h>
+#include <config.h>
+
+namespace lout {
+
+namespace object {
+
+// ------------
+// Object
+// ------------
+
+/**
+ * \brief The destructor is defined as virtual (but not abstract), so that
+ * destruction of Object's works properly.
+ */
+Object::~Object()
+{
+}
+
+/**
+ * \brief Returns, whether two objects are equal.
+ *
+ * The caller should ensure, that this and the object have the same class;
+ * this makes casting of "other" safe. Typically, an implementation should
+ * check this == other first, the caller can assume a fast implementation.
+ */
+bool Object::equals(Object *other)
+{
+ misc::assertNotReached ();
+ return false;
+}
+
+/**
+ * \brief Return a hash value for the object.
+ */
+int Object::hashValue()
+{
+ fprintf (stderr, "Object::hashValue() should be implemented.\n");
+ return 0;
+}
+
+/**
+ * \brief Return an exact copy of the object.
+ */
+Object *Object::clone()
+{
+ misc::assertNotReached ();
+ return NULL;
+}
+
+/**
+ * \brief Use object::Object::intoStringBuffer to return a textual
+ * representation of the object.
+ *
+ * The caller does not have to free the memory, object::Object is responsible
+ * for this.
+ */
+const char *Object::toString()
+{
+ /** \todo garbage! */
+ misc::StringBuffer sb;
+ intoStringBuffer(&sb);
+ char *s = strdup(sb.getChars());
+ return s;
+}
+
+/**
+ * \brief Store a textual representation of the object in a misc::StringBuffer.
+ *
+ * This is used by object::Object::toString.
+ */
+void Object::intoStringBuffer(misc::StringBuffer *sb)
+{
+ sb->append("<not further specified object ");
+ sb->appendPointer(this);
+ sb->append(">");
+}
+
+/**
+ * \brief Return the number of bytes, this object totally uses.
+ */
+size_t Object::sizeOf()
+{
+ fprintf (stderr, "Object::sizeOf() should be implemented.\n");
+ return sizeof(Object*);
+}
+
+// ----------------
+// Comparator
+// ----------------
+
+Comparator *Comparator::compareFunComparator = NULL;
+
+/**
+ * \brief This static method may be used as compare function for
+ * qsort(3) and bsearch(3), for an array of Object* (Object*[] or
+ * Object**).
+ *
+ * "compareFunComparator" should be set before.
+ *
+ * \todo Not reentrant. Consider switching to reentrant variants
+ * (qsort_r), and compare function with an additional argument.
+ */
+int Comparator::compareFun(const void *p1, const void *p2)
+{
+ return compareFunComparator->compare (*(Object**)p1, *(Object**)p2);
+}
+
+// ------------------------
+// StandardComparator
+// ------------------------
+
+int StandardComparator::compare(Object *o1, Object *o2)
+{
+ if (o1 && o2)
+ return ((Comparable*)o1)->compareTo ((Comparable*)o2);
+ else if (o1)
+ return 1;
+ else if (o2)
+ return -1;
+ else
+ return 0;
+}
+
+StandardComparator standardComparator;
+
+// -------------
+// Pointer
+// -------------
+
+bool Pointer::equals(Object *other)
+{
+ return value == ((Pointer*)other)->value;
+}
+
+int Pointer::hashValue()
+{
+/* For some unknown reason, this doesn't compile on some 64bit platforms:
+ *
+ * if (sizeof (int) == sizeof (void*))
+ * return (int)value;
+ * else
+ * return ((int*)&value)[0] ^ ((int*)&value)[1];
+ */
+#if SIZEOF_VOID_P == 4
+ // Assuming that sizeof(void*) == sizeof(int); on 32 bit systems.
+ return (int)value;
+#else
+ // Assuming that sizeof(void*) == 2 * sizeof(int); on 64 bit
+ // systems (int is still 32 bit).
+ // Combine both parts of the pointer value *itself*, not what it
+ // points to, by first referencing it (operator "&"), then
+ // dereferencing it again (operator "[]").
+ return ((intptr_t)value >> 32) ^ ((intptr_t)value);
+#endif
+}
+
+void Pointer::intoStringBuffer(misc::StringBuffer *sb)
+{
+ char buf[64];
+ snprintf(buf, sizeof(buf), "%p", value);
+ sb->append(buf);
+}
+
+// -------------
+// Integer
+// -------------
+
+bool Integer::equals(Object *other)
+{
+ return value == ((Integer*)other)->value;
+}
+
+int Integer::hashValue()
+{
+ return (int)value;
+}
+
+void Integer::intoStringBuffer(misc::StringBuffer *sb)
+{
+ char buf[64];
+ sprintf(buf, "%d", value);
+ sb->append(buf);
+}
+
+int Integer::compareTo(Comparable *other)
+{
+ return value - ((Integer*)other)->value;
+}
+
+// -------------
+// Boolean
+// -------------
+
+bool Boolean::equals(Object *other)
+{
+ bool value2 = ((Boolean*)other)->value;
+ // TODO Does "==" work?
+ return (value && value2) || (!value && value2);
+}
+
+int Boolean::hashValue()
+{
+ return value ? 1 : 0;
+}
+
+void Boolean::intoStringBuffer(misc::StringBuffer *sb)
+{
+ sb->append(value ? "true" : "false");
+}
+
+int Boolean::compareTo(Comparable *other)
+{
+ return (value ? 1 : 0) - (((Boolean*)other)->value ? 1 : 0);
+}
+
+// -----------------
+// ConstString
+// -----------------
+
+bool ConstString::equals(Object *other)
+{
+ ConstString *otherString = (ConstString*)other;
+ return
+ this == other ||
+ (str == NULL && otherString->str == NULL) ||
+ (str != NULL && otherString->str != NULL &&
+ strcmp(str, otherString->str) == 0);
+}
+
+int ConstString::hashValue()
+{
+ return hashValue(str);
+}
+
+
+int ConstString::compareTo(Comparable *other)
+{
+ String *otherString = (String*)other;
+ if (str && otherString->str)
+ return strcmp(str, otherString->str);
+ else if (str)
+ return 1;
+ else if (otherString->str)
+ return -1;
+ else
+ return 0;
+}
+
+
+int ConstString::hashValue(const char *str)
+{
+ if (str) {
+ int h = 0;
+ for (int i = 0; str[i]; i++)
+ h = (h * 256 + str[i]);
+ return h;
+ } else
+ return 0;
+}
+
+void ConstString::intoStringBuffer(misc::StringBuffer *sb)
+{
+ sb->append(str);
+}
+
+// ------------
+// String
+// ------------
+
+String::String (const char *str): ConstString (str ? strdup(str) : NULL)
+{
+}
+
+String::~String ()
+{
+ if (str)
+ free((char *)str);
+}
+
+// ------------
+// Pair
+// ------------
+
+PairBase::PairBase(Object *first, Object *second)
+{
+ this->first = first;
+ this->second = second;
+}
+
+PairBase::~PairBase()
+{
+ if (first)
+ delete first;
+ if (second)
+ delete second;
+}
+
+bool PairBase::equals(Object *other)
+{
+ PairBase *otherPair = (PairBase*)other;
+
+ return
+ // Identical?
+ this == other || (
+ (// Both first parts are NULL, ...
+ (first == NULL && otherPair->first == NULL) ||
+ // ... or both first parts are not NULL and equal
+ (first != NULL && otherPair->first != NULL
+ && first->equals (otherPair->first))) &&
+ // Same with second part.
+ ((second == NULL && otherPair->second == NULL) ||
+ (second != NULL && otherPair->second != NULL
+ && second->equals (otherPair->second))));
+}
+
+int PairBase::hashValue()
+{
+ int value = 0;
+
+ if (first)
+ value ^= first->hashValue();
+ if (second)
+ value ^= second->hashValue();
+
+ return value;
+}
+
+void PairBase::intoStringBuffer(misc::StringBuffer *sb)
+{
+ sb->append("<pair: ");
+
+ if (first)
+ first->intoStringBuffer(sb);
+ else
+ sb->append("(nil)");
+
+ sb->append(",");
+
+ if (second)
+ second->intoStringBuffer(sb);
+ else
+ sb->append("(nil)");
+
+ sb->append(">");
+}
+
+size_t PairBase::sizeOf()
+{
+ size_t size = 0;
+
+ if (first)
+ size += first->sizeOf();
+ if (second)
+ size += second->sizeOf();
+
+ return size;
+}
+
+} // namespace object
+
+} // namespace lout