1 //////////////////////////////////////////////////////////////////////////////
4 // ADLib, Prop and their related set of tools and documentation are in the
5 // public domain. The author(s) of this software reserve no copyrights on
6 // the source code and any code generated using the tools. You are encouraged
7 // to use ADLib and Prop to develop software, in both academic and commercial
8 // settings, and are welcomed to incorporate any part of ADLib and Prop into
11 // Although you are under no obligation to do so, we strongly recommend that
12 // you give away all software developed using our tools.
14 // We also ask that credit be given to us when ADLib and/or Prop are used in
15 // your programs, and that this notice be preserved intact in all the source
18 // This software is still under development and we welcome(read crave for)
19 // any suggestions and help from the users.
23 //////////////////////////////////////////////////////////////////////////////
25 #define PSTREAM_IMPLEMENTATION
29 #include <AD/persist/ptype.h> // persistent type id
30 #include <AD/persist/pstream.h> // persistent stream base class
31 #include <AD/persist/pconvert.h> // conversions
32 #include <AD/persist/po_impl.h> // persistent stream implementation
33 #include <AD/hash/lhash2.h> // linear probing hash table
34 #include <AD/strings/quark.h> // atomic strings
35 #include <AD/contain/variset.h> // variable length integer set
37 PObjectLog::PObjectLog(int n
)
39 object_types(PObjectType::number_of_types())
42 PObjectLog::~PObjectLog() {}
44 typedef PObjectLog::PObjectInfo PObjectInfo
;
46 //////////////////////////////////////////////////////////////////////////////
48 //////////////////////////////////////////////////////////////////////////////
49 Postream:: Postream(ostream
& out
)
51 _object_log(new PObjectLog(1025)),
52 _next_marker(P_FIRST_MARKER
)
54 Postream::~Postream() { _object_log
->clean(); delete _object_log
; }
56 void PObjectLog::clean ()
57 { foreach (i
, markers
) { markers
.value(i
).obj
= 0; }
60 //////////////////////////////////////////////////////////////////////////////
61 // Stream output from an object.
62 //////////////////////////////////////////////////////////////////////////////
63 Postream
& operator << (Postream
& s
, const PObject
& obj
)
64 { obj
.persist_type_id().write(s
);
69 //////////////////////////////////////////////////////////////////////////////
70 // Stream output from an object pointer
71 //////////////////////////////////////////////////////////////////////////////
72 Postream
& operator << (Postream
& s
, const PObject
* obj
)
74 if (P_IS_UNBOXED(obj
)) {
75 // (a) Object is unboxed
76 // Send small integer tag
77 s
<< -(P_OBJECT_MARKER
)obj
;
79 Ix m
= s
._object_log
->markers
.lookup(P_WRAP_ADDR(obj
));
81 // (b) Object already serialized
83 s
<< s
._object_log
->markers
.value(m
).marker
;
86 // Add new marker to the log
87 P_OBJECT_MARKER new_marker
= s
._next_marker
--;
89 s
<< P_NEW_OBJECT_TAG
;
90 s
._object_log
->markers
.insert(P_WRAP_ADDR(obj
),
91 PObjectInfo(obj
,new_marker
));
93 // Write out the type of object
94 obj
->persist_type_id().write(s
);
96 // Write out the contents of object
97 obj
->persist_write(s
);
103 //////////////////////////////////////////////////////////////////////////////
105 //////////////////////////////////////////////////////////////////////////////
106 Postream
& operator << (Postream
& s
, P_char c
)
107 { s
._out
<< c
; return s
; }
108 Postream
& operator << (Postream
& s
, P_uchar c
)
109 { s
._out
<< c
; return s
; }
110 #ifdef PROP_BOOL_IS_DEFINED
111 Postream
& operator << (Postream
& s
, bool b
)
112 { char x
= b
? 1 : 0;
113 s
._out
.write(&x
, sizeof(x
));
117 Postream
& operator << (Postream
& s
, P_int16 n
)
118 { P_local_to_canonic(n
);
119 s
._out
.write((char*)&n
,sizeof(n
));
122 Postream
& operator << (Postream
& s
, P_uint16 n
)
123 { P_local_to_canonic(n
);
124 s
._out
.write((char*)&n
,sizeof(n
));
127 Postream
& operator << (Postream
& s
, int n
)
128 { P_local_to_canonic(n
);
129 s
._out
.write((char*)&n
,sizeof(n
));
132 Postream
& operator << (Postream
& s
, unsigned int n
)
133 { P_local_to_canonic(n
);
134 s
._out
.write((char*)&n
,sizeof(n
));
137 Postream
& operator << (Postream
& s
, P_int32 n
)
138 { P_local_to_canonic(n
);
139 s
._out
.write((char*)&n
,sizeof(n
));
142 Postream
& operator << (Postream
& s
, P_uint32 n
)
143 { P_local_to_canonic(n
);
144 s
._out
.write((char*)&n
,sizeof(n
));
147 Postream
& operator << (Postream
& s
, P_real32 n
)
148 { P_local_to_canonic(n
);
149 s
._out
.write((char*)&n
,sizeof(n
));
152 Postream
& operator << (Postream
& s
, P_real64 n
)
153 { P_local_to_canonic(n
);
154 s
._out
.write((char*)&n
,sizeof(n
));
158 Postream
& operator << (Postream
& s
, const P_char
* str
)
163 P_int32 length
= strlen(str
);
165 s
._out
.write (str
, length
);
170 Postream
& operator << (Postream
& s
, const P_uchar
* str
)
171 { return s
<< (const P_char
*)str
; }
173 Postream
& operator << (Postream
& s
, const Quark
& q
)
174 { return s
<< q
.string(); }
176 Postream
& Postream::write (const char buf
[], int len
)
181 P_int32 length
= len
>= 0 ? len
: strlen(buf
);
183 _out
.write (buf
, length
);
188 Postream
& Postream::write (const unsigned char buf
[], int len
)
189 { return write((const char *)buf
, len
);
192 //////////////////////////////////////////////////////////////////////////////
194 // Write a persistent type to a persistent stream
196 //////////////////////////////////////////////////////////////////////////////
197 void PObjectType::write (Postream
& f
) const
198 { P_OBJECT_TYPEID id
= entry
->unique_id
;
200 Bool found
= f
._object_log
->object_types
[id
];
202 { f
<< P_OBJECT_ID_TAG
;
203 // cerr << "[Writing " << *this << "]\n";
205 { f
<< P_OBJECT_NAME_TAG
;
206 f
.write(entry
->type_name
,entry
->type_name_len
);
207 f
._object_log
->object_types
.setUnion(id
);
208 // cerr << "[Writing new " << *this << "]\n";