Added dict object

This commit is contained in:
Michael Hansen
2009-07-24 21:15:51 +00:00
parent 8b0fc18921
commit 1737240a7c
8 changed files with 225 additions and 74 deletions

View File

@@ -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 <cstring>
/* 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<PycObject> obj) const
{
PycRef<PycLong> longObj = obj.cast<PycLong>();
if (m_size != longObj->m_size)
return false;
std::list<int>::const_iterator it1 = m_value.begin();
std::list<int>::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<PycObject> obj) const
{
PycRef<PycFloat> floatObj = obj.cast<PycFloat>();
if (m_value == floatObj->m_value)
return true;
return (strcmp(m_value, floatObj->m_value) == 0);
}

View File

@@ -12,6 +12,9 @@ public:
bool isType(int type) const
{ return (type == TYPE_INT) || PycObject::isType(type); }
bool isEqual(PycRef<PycObject> obj) const
{ return m_value == obj.cast<PycInt>()->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<PycObject> 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<PycObject> 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

View File

@@ -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<PycObject> Pyc_NULL = (PycObject*)0;
PycRef<PycObject> Pyc_None = new PycObject(PycObject::TYPE_NONE);
PycRef<PycObject> Pyc_Ellipsis = new PycObject(PycObject::TYPE_ELLIPSIS);
PycRef<PycObject> Pyc_StopIteration = new PycObject(PycObject::TYPE_STOPITER);
PycRef<PycObject> Pyc_False = new PycObject(PycObject::TYPE_FALSE);
PycRef<PycObject> Pyc_True = new PycObject(PycObject::TYPE_TRUE);
PycObjRef CreateObject(int type)
PycRef<PycObject> 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<PycObject> LoadObject(PycData* stream, PycModule* mod)
{
PycObjRef obj = CreateObject(stream->getByte());
PycRef<PycObject> obj = CreateObject(stream->getByte());
if (obj != Pyc_NULL)
obj->load(stream, mod);
return obj;

120
object.h
View File

@@ -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 _Obj>
class PycRef {
@@ -94,15 +43,70 @@ private:
_Obj* m_obj;
};
typedef PycRef<PycObject> 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<PycObject> 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<PycObject> CreateObject(int type);
PycRef<PycObject> 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<PycObject> Pyc_NULL;
extern PycRef<PycObject> Pyc_None;
extern PycRef<PycObject> Pyc_Ellipsis;
extern PycRef<PycObject> Pyc_StopIteration;
extern PycRef<PycObject> Pyc_False;
extern PycRef<PycObject> Pyc_True;
#endif

View File

@@ -11,6 +11,21 @@ void PycTuple::load(PycData* stream, PycModule* mod)
m_values[i] = LoadObject(stream, mod);
}
bool PycTuple::isEqual(PycRef<PycObject> obj) const
{
PycRef<PycTuple> tupleObj = obj.cast<PycTuple>();
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<m_size; i++)
m_values.push_back(LoadObject(stream, mod));
}
bool PycList::isEqual(PycRef<PycObject> obj) const
{
PycRef<PycList> listObj = obj.cast<PycList>();
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<m_size; i++)
m_values.push_back(LoadObject(stream, mod));
}
bool PycDict::isEqual(PycRef<PycObject> obj) const
{
PycRef<PycDict> dictObj = obj.cast<PycDict>();
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<PycObject> PycDict::get(PycRef<PycObject> 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
}

View File

@@ -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<PycObject> 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<PycObject> 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<PycRef<PycObject> > key_t;
typedef std::list<PycRef<PycObject> > 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<PycObject> obj) const;
void load(class PycData* stream, class PycModule* mod);
int size() const { return m_size; }
PycRef<PycObject> get(PycRef<PycObject> 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

View File

@@ -33,6 +33,14 @@ void PycString::load(PycData* stream, PycModule* mod)
}
}
bool PycString::isEqual(PycRef<PycObject> obj) const
{
PycRef<PycString> strObj = obj.cast<PycString>();
if (m_value == strObj->m_value)
return true;
return (strcmp(m_value, strObj->m_value) == 0);
}
void OutputString(PycRef<PycString> str, QuoteStyle style, FILE* F)
{

View File

@@ -21,6 +21,8 @@ public:
(type == TYPE_STRINGREF) || PycObject::isType(type);
}
bool isEqual(PycRef<PycObject> obj) const;
void load(class PycData* stream, class PycModule* mod);
int length() const { return m_length; }