From 1737240a7cfd2ccc2322179252775bb44c5274a6 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Fri, 24 Jul 2009 21:15:51 +0000 Subject: [PATCH] Added dict object --- numeric.cpp | 27 ++++++++++-- numeric.h | 11 +++-- object.cpp | 20 +++++---- object.h | 120 ++++++++++++++++++++++++++------------------------- sequence.cpp | 75 ++++++++++++++++++++++++++++++++ sequence.h | 36 ++++++++++++++++ string.cpp | 8 ++++ string.h | 2 + 8 files changed, 225 insertions(+), 74 deletions(-) diff --git a/numeric.cpp b/numeric.cpp index d1ec6bf..c61165a 100644 --- a/numeric.cpp +++ b/numeric.cpp @@ -1,9 +1,7 @@ #include "numeric.h" #include "data.h" #include "module.h" - -PycObjRef Pyc_False = new PycObject(PycObject::TYPE_FALSE); -PycObjRef Pyc_True = new PycObject(PycObject::TYPE_TRUE); +#include /* PycInt */ void PycInt::load(PycData* stream, PycModule*) @@ -21,6 +19,21 @@ void PycLong::load(PycData* stream, PycModule*) m_value.push_back(stream->get16()); } +bool PycLong::isEqual(PycRef obj) const +{ + PycRef longObj = obj.cast(); + if (m_size != longObj->m_size) + return false; + std::list::const_iterator it1 = m_value.begin(); + std::list::const_iterator it2 = longObj->m_value.begin(); + while (it1 != m_value.end()) { + if (*it1 != *it2) + return false; + ++it1, ++it2; + } + return true; +} + /* PycFloat */ void PycFloat::load(PycData* stream, PycModule*) @@ -35,3 +48,11 @@ void PycFloat::load(PycData* stream, PycModule*) m_value = 0; } } + +bool PycFloat::isEqual(PycRef obj) const +{ + PycRef floatObj = obj.cast(); + if (m_value == floatObj->m_value) + return true; + return (strcmp(m_value, floatObj->m_value) == 0); +} diff --git a/numeric.h b/numeric.h index 7d000f6..6ee0da9 100644 --- a/numeric.h +++ b/numeric.h @@ -12,6 +12,9 @@ public: bool isType(int type) const { return (type == TYPE_INT) || PycObject::isType(type); } + bool isEqual(PycRef obj) const + { return m_value == obj.cast()->m_value; } + void load(class PycData* stream, class PycModule* mod); int value() const { return m_value; } @@ -28,6 +31,8 @@ public: bool isType(int type) const { return (type == TYPE_LONG) || PycObject::isType(type); } + bool isEqual(PycRef obj) const; + void load(class PycData* stream, class PycModule* mod); int size() const { return m_size; } @@ -48,6 +53,8 @@ public: bool isType(int type) const { return (type == TYPE_FLOAT) || PycObject::isType(type); } + bool isEqual(PycRef obj) const; + void load(class PycData* stream, class PycModule* mod); const char* value() const { return m_value; } @@ -56,8 +63,4 @@ private: char* m_value; // Floats are stored as strings }; -/* Static Singleton objects */ -extern PycObjRef Pyc_False; -extern PycObjRef Pyc_True; - #endif diff --git a/object.cpp b/object.cpp index 0210063..6e9627a 100644 --- a/object.cpp +++ b/object.cpp @@ -6,12 +6,14 @@ #include "numeric.h" #include "code.h" -PycObjRef Pyc_NULL = (PycObject*)0; -PycObjRef Pyc_None = new PycObject(PycObject::TYPE_NONE); -PycObjRef Pyc_Ellipsis = new PycObject(PycObject::TYPE_ELLIPSIS); -PycObjRef Pyc_StopIteration = new PycObject(PycObject::TYPE_STOPITER); +PycRef Pyc_NULL = (PycObject*)0; +PycRef Pyc_None = new PycObject(PycObject::TYPE_NONE); +PycRef Pyc_Ellipsis = new PycObject(PycObject::TYPE_ELLIPSIS); +PycRef Pyc_StopIteration = new PycObject(PycObject::TYPE_STOPITER); +PycRef Pyc_False = new PycObject(PycObject::TYPE_FALSE); +PycRef Pyc_True = new PycObject(PycObject::TYPE_TRUE); -PycObjRef CreateObject(int type) +PycRef CreateObject(int type) { switch (type) { case PycObject::TYPE_NULL: @@ -50,8 +52,8 @@ PycObjRef CreateObject(int type) return new PycTuple(); case PycObject::TYPE_LIST: return new PycList(); - //case PycObject::TYPE_DICT: - // ... + case PycObject::TYPE_DICT: + return new PycDict(); case PycObject::TYPE_CODE: case PycObject::TYPE_CODE2: return new PycCode(); @@ -67,9 +69,9 @@ PycObjRef CreateObject(int type) } } -PycObjRef LoadObject(PycData* stream, PycModule* mod) +PycRef LoadObject(PycData* stream, PycModule* mod) { - PycObjRef obj = CreateObject(stream->getByte()); + PycRef obj = CreateObject(stream->getByte()); if (obj != Pyc_NULL) obj->load(stream, mod); return obj; diff --git a/object.h b/object.h index f1c9d8d..b403758 100644 --- a/object.h +++ b/object.h @@ -1,57 +1,6 @@ #ifndef _PYC_OBJECT_H #define _PYC_OBJECT_H -/* Please only hold PycObjects inside PycRefs! */ -class PycObject { -public: - enum Type { - // From the Python Marshallers - TYPE_NULL = '0', - TYPE_NONE = 'N', - TYPE_FALSE = 'F', - TYPE_TRUE = 'T', - TYPE_STOPITER = 'S', - TYPE_ELLIPSIS = '.', - TYPE_INT = 'i', - TYPE_INT64 = 'I', - TYPE_FLOAT = 'f', - TYPE_BINARY_FLOAT = 'g', - TYPE_COMPLEX = 'x', - TYPE_BINARY_COMPLEX = 'y', - TYPE_LONG = 'l', - TYPE_STRING = 's', - TYPE_INTERNED = 't', - TYPE_STRINGREF = 'R', - TYPE_TUPLE = '(', - TYPE_LIST = '[', - TYPE_DICT = '{', - TYPE_CODE = 'c', - TYPE_CODE2 = 'C', // Used in Python 1.0 - 1.2 - TYPE_UNICODE = 'u', - TYPE_UNKNOWN = '?', - TYPE_SET = '<', - TYPE_FROZENSET = '>', - }; - - PycObject(int type = TYPE_UNKNOWN) : m_refs(0), m_type(type) { } - virtual ~PycObject() { } - - int type() const { return (this) ? m_type : TYPE_NULL; } - - virtual bool isType(int type) const - { return (this) ? type == m_type : type == TYPE_NULL; } - - virtual void load(class PycData*, class PycModule*) { } - -private: - int m_refs; - int m_type; - -public: - void addRef() { if (this) ++m_refs; } - void delRef() { if (this && --m_refs == 0) delete this; } -}; - template class PycRef { @@ -94,15 +43,70 @@ private: _Obj* m_obj; }; -typedef PycRef PycObjRef; -PycObjRef CreateObject(int type); -PycObjRef LoadObject(class PycData* stream, class PycModule* mod); +/* Please only hold PycObjects inside PycRefs! */ +class PycObject { +public: + enum Type { + // From the Python Marshallers + TYPE_NULL = '0', + TYPE_NONE = 'N', + TYPE_FALSE = 'F', + TYPE_TRUE = 'T', + TYPE_STOPITER = 'S', + TYPE_ELLIPSIS = '.', + TYPE_INT = 'i', + TYPE_INT64 = 'I', + TYPE_FLOAT = 'f', + TYPE_BINARY_FLOAT = 'g', + TYPE_COMPLEX = 'x', + TYPE_BINARY_COMPLEX = 'y', + TYPE_LONG = 'l', + TYPE_STRING = 's', + TYPE_INTERNED = 't', + TYPE_STRINGREF = 'R', + TYPE_TUPLE = '(', + TYPE_LIST = '[', + TYPE_DICT = '{', + TYPE_CODE = 'c', + TYPE_CODE2 = 'C', // Used in Python 1.0 - 1.2 + TYPE_UNICODE = 'u', + TYPE_UNKNOWN = '?', + TYPE_SET = '<', + TYPE_FROZENSET = '>', + }; + + PycObject(int type = TYPE_UNKNOWN) : m_refs(0), m_type(type) { } + virtual ~PycObject() { } + + int type() const { return (this) ? m_type : TYPE_NULL; } + + virtual bool isType(int type) const + { return (this) ? type == m_type : type == TYPE_NULL; } + + virtual bool isEqual(PycRef obj) const + { return (this == (PycObject*)obj); } + + virtual void load(class PycData*, class PycModule*) { } + +private: + int m_refs; + int m_type; + +public: + void addRef() { if (this) ++m_refs; } + void delRef() { if (this && --m_refs == 0) delete this; } +}; + +PycRef CreateObject(int type); +PycRef LoadObject(class PycData* stream, class PycModule* mod); /* Static Singleton objects */ -extern PycObjRef Pyc_NULL; -extern PycObjRef Pyc_None; -extern PycObjRef Pyc_Ellipsis; -extern PycObjRef Pyc_StopIteration; +extern PycRef Pyc_NULL; +extern PycRef Pyc_None; +extern PycRef Pyc_Ellipsis; +extern PycRef Pyc_StopIteration; +extern PycRef Pyc_False; +extern PycRef Pyc_True; #endif diff --git a/sequence.cpp b/sequence.cpp index 9e6a6cc..758bfdc 100644 --- a/sequence.cpp +++ b/sequence.cpp @@ -11,6 +11,21 @@ void PycTuple::load(PycData* stream, PycModule* mod) m_values[i] = LoadObject(stream, mod); } +bool PycTuple::isEqual(PycRef obj) const +{ + PycRef tupleObj = obj.cast(); + if (m_size != tupleObj->m_size) + return false; + value_t::const_iterator it1 = m_values.begin(); + value_t::const_iterator it2 = tupleObj->m_values.begin(); + while (it1 != m_values.end()) { + if (!(*it1)->isEqual(*it2)) + return false; + ++it1, ++it2; + } + return true; +} + /* PycList */ void PycList::load(PycData* stream, PycModule* mod) @@ -19,3 +34,63 @@ void PycList::load(PycData* stream, PycModule* mod) for (int i=0; i obj) const +{ + PycRef listObj = obj.cast(); + if (m_size != listObj->m_size) + return false; + value_t::const_iterator it1 = m_values.begin(); + value_t::const_iterator it2 = listObj->m_values.begin(); + while (it1 != m_values.end()) { + if (!(*it1)->isEqual(*it2)) + return false; + ++it1, ++it2; + } + return true; +} + + +/* PycDict */ +void PycDict::load(PycData* stream, PycModule* mod) +{ + m_size = stream->get32(); + for (int i=0; i obj) const +{ + PycRef dictObj = obj.cast(); + if (m_size != dictObj->m_size) + return false; + + key_t::const_iterator ki1 = m_keys.begin(); + key_t::const_iterator ki2 = dictObj->m_keys.begin(); + while (ki1 != m_keys.end()) { + if (!(*ki1)->isEqual(*ki2)) + return false; + ++ki1, ++ki2; + } + + value_t::const_iterator vi1 = m_values.begin(); + value_t::const_iterator vi2 = dictObj->m_values.begin(); + while (vi1 != m_values.end()) { + if (!(*vi1)->isEqual(*vi2)) + return false; + ++vi1, ++vi2; + } + return true; +} + +PycRef PycDict::get(PycRef key) const +{ + key_t::const_iterator ki = m_keys.begin(); + value_t::const_iterator vi = m_values.begin(); + while (ki != m_keys.end()) { + if ((*ki)->isEqual(key)) + return *vi; + ++ki, ++vi; + } + return Pyc_NULL; // Disassembly shouldn't get non-existant keys +} diff --git a/sequence.h b/sequence.h index d5a22aa..5d1994d 100644 --- a/sequence.h +++ b/sequence.h @@ -12,6 +12,11 @@ public: PycTuple(int type = TYPE_TUPLE) : PycObject(type), m_size(0) { } + bool isType(int type) const + { return (type == TYPE_TUPLE) || PycObject::isType(type); } + + bool isEqual(PycRef obj) const; + void load(class PycData* stream, class PycModule* mod); int size() const { return m_size; } @@ -29,6 +34,11 @@ public: PycList(int type = TYPE_LIST) : PycObject(type), m_size(0) { } + bool isType(int type) const + { return (type == TYPE_LIST) || PycObject::isType(type); } + + bool isEqual(PycRef obj) const; + void load(class PycData* stream, class PycModule* mod); int size() const { return m_size; } @@ -39,4 +49,30 @@ private: value_t m_values; }; +class PycDict : public PycObject { +public: + typedef std::list > key_t; + typedef std::list > value_t; + + PycDict(int type = TYPE_DICT) + : PycObject(type), m_size(0) { } + + bool isType(int type) const + { return (type == TYPE_DICT) || PycObject::isType(type); } + + bool isEqual(PycRef obj) const; + + void load(class PycData* stream, class PycModule* mod); + + int size() const { return m_size; } + PycRef get(PycRef key) const; + key_t keys() const { return m_keys; } + value_t values() const { return m_values; } + +private: + int m_size; + key_t m_keys; + value_t m_values; +}; + #endif diff --git a/string.cpp b/string.cpp index 124028d..f1a212a 100644 --- a/string.cpp +++ b/string.cpp @@ -33,6 +33,14 @@ void PycString::load(PycData* stream, PycModule* mod) } } +bool PycString::isEqual(PycRef obj) const +{ + PycRef strObj = obj.cast(); + if (m_value == strObj->m_value) + return true; + return (strcmp(m_value, strObj->m_value) == 0); +} + void OutputString(PycRef str, QuoteStyle style, FILE* F) { diff --git a/string.h b/string.h index 19869c5..9f9ee3a 100644 --- a/string.h +++ b/string.h @@ -21,6 +21,8 @@ public: (type == TYPE_STRINGREF) || PycObject::isType(type); } + bool isEqual(PycRef obj) const; + void load(class PycData* stream, class PycModule* mod); int length() const { return m_length; }