initial
[prop.git] / lib-src / persist / postream.cc
blobee745a7b4ff7865dd29153847fadd85033f0eccd
1 //////////////////////////////////////////////////////////////////////////////
2 // NOTICE:
3 //
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
9 // your programs.
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
16 // code.
18 // This software is still under development and we welcome(read crave for)
19 // any suggestions and help from the users.
21 // Allen Leung
22 // 1994
23 //////////////////////////////////////////////////////////////////////////////
25 #define PSTREAM_IMPLEMENTATION
26 #include <stdlib.h>
27 #include <string.h>
28 #include <iostream.h>
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)
38 : markers(n),
39 object_types(PObjectType::number_of_types())
42 PObjectLog::~PObjectLog() {}
44 typedef PObjectLog::PObjectInfo PObjectInfo;
46 //////////////////////////////////////////////////////////////////////////////
47 // Class Postream
48 //////////////////////////////////////////////////////////////////////////////
49 Postream:: Postream(ostream& out)
50 : _out(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);
65 obj.persist_write(s);
66 return 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;
78 } else {
79 Ix m = s._object_log->markers.lookup(P_WRAP_ADDR(obj));
80 if (m) {
81 // (b) Object already serialized
82 // Send object marker
83 s << s._object_log->markers.value(m).marker;
84 } else {
85 // (c) Object is new.
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);
100 return s;
103 //////////////////////////////////////////////////////////////////////////////
104 // Output operators
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));
114 return s;
116 #endif
117 Postream& operator << (Postream& s, P_int16 n)
118 { P_local_to_canonic(n);
119 s._out.write((char*)&n,sizeof(n));
120 return s;
122 Postream& operator << (Postream& s, P_uint16 n)
123 { P_local_to_canonic(n);
124 s._out.write((char*)&n,sizeof(n));
125 return s;
127 Postream& operator << (Postream& s, int n)
128 { P_local_to_canonic(n);
129 s._out.write((char*)&n,sizeof(n));
130 return s;
132 Postream& operator << (Postream& s, unsigned int n)
133 { P_local_to_canonic(n);
134 s._out.write((char*)&n,sizeof(n));
135 return s;
137 Postream& operator << (Postream& s, P_int32 n)
138 { P_local_to_canonic(n);
139 s._out.write((char*)&n,sizeof(n));
140 return s;
142 Postream& operator << (Postream& s, P_uint32 n)
143 { P_local_to_canonic(n);
144 s._out.write((char*)&n,sizeof(n));
145 return s;
147 Postream& operator << (Postream& s, P_real32 n)
148 { P_local_to_canonic(n);
149 s._out.write((char*)&n,sizeof(n));
150 return s;
152 Postream& operator << (Postream& s, P_real64 n)
153 { P_local_to_canonic(n);
154 s._out.write((char*)&n,sizeof(n));
155 return s;
158 Postream& operator << (Postream& s, const P_char * str)
159 { if (str == 0) {
160 P_int32 length = -1;
161 s << length;
162 } else {
163 P_int32 length = strlen(str);
164 s << length;
165 s._out.write (str, length);
167 return s;
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)
177 { if (buf == 0) {
178 P_int32 length = -1;
179 *this << length;
180 } else {
181 P_int32 length = len >= 0 ? len : strlen(buf);
182 *this << length;
183 _out.write (buf, length);
185 return *this;
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;
199 f << id;
200 Bool found = f._object_log->object_types[id];
201 if (found)
202 { f << P_OBJECT_ID_TAG;
203 // cerr << "[Writing " << *this << "]\n";
204 } else
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";