blob: c8f90ae12bc1ee5eb1a6915be8ce9ac4b4f39ed3 [file] [log] [blame]
José Fonseca299a1b32012-01-26 20:32:59 +00001/**************************************************************************
2 *
3 * Copyright 2012 Jose Fonseca
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 **************************************************************************/
25
26/*
27 * Python pickle writer
28 */
29
30#ifndef _PICKLE_HPP_
31#define _PICKLE_HPP_
32
33#include <assert.h>
34#include <stddef.h>
35
36#include <ostream>
37#include <string>
38
39
40class PickleWriter
41{
42private:
43 std::ostream &os;
44
45 /*
46 * Python pickle opcodes. See pickle.py and pickletools.py from Python
47 * standard library for details.
48 */
49 enum Opcode {
50 MARK = '(',
51 STOP = '.',
52 POP = '0',
53 POP_MARK = '1',
54 DUP = '2',
55 FLOAT = 'F',
56 INT = 'I',
57 BININT = 'J',
58 BININT1 = 'K',
59 LONG = 'L',
60 BININT2 = 'M',
61 NONE = 'N',
62 PERSID = 'P',
63 BINPERSID = 'Q',
64 REDUCE = 'R',
65 STRING = 'S',
66 BINSTRING = 'T',
67 SHORT_BINSTRING = 'U',
68 UNICODE = 'V',
69 BINUNICODE = 'X',
70 APPEND = 'a',
71 BUILD = 'b',
72 GLOBAL = 'c',
73 DICT = 'd',
74 EMPTY_DICT = '}',
75 APPENDS = 'e',
76 GET = 'g',
77 BINGET = 'h',
78 INST = 'i',
79 LONG_BINGET = 'j',
80 LIST = 'l',
81 EMPTY_LIST = ']',
82 OBJ = 'o',
83 PUT = 'p',
84 BINPUT = 'q',
85 LONG_BINPUT = 'r',
86 SETITEM = 's',
87 TUPLE = 't',
88 EMPTY_TUPLE = ')',
89 SETITEMS = 'u',
90 BINFLOAT = 'G',
91
92 PROTO = 0x80,
93 NEWOBJ = 0x81,
94 EXT1 = 0x82,
95 EXT2 = 0x83,
96 EXT4 = 0x84,
97 TUPLE1 = 0x85,
98 TUPLE2 = 0x86,
99 TUPLE3 = 0x87,
100 NEWTRUE = 0x88,
101 NEWFALSE = 0x89,
102 LONG1 = 0x8a,
103 LONG4 = 0x8b,
104 };
105
106public:
107 PickleWriter(std::ostream &_os) :
108 os(_os)
109 {
110 os.put(PROTO);
111 os.put(2);
112 }
113
114 ~PickleWriter() {
115 os.put(STOP);
116 }
117
118 inline void beginDict() {
119 os.put(EMPTY_DICT);
120 os.put(BINPUT);
121 os.put(1);
122 }
123
124 inline void endDict() {
125 }
126
127 inline void beginItem() {
128 }
129
130 inline void beginItem(const char * name) {
131 writeString(name);
132 }
133
134 inline void beginItem(const std::string &name) {
135 beginItem(name.c_str());
136 }
137
138 inline void endItem(void) {
139 os.put(SETITEM);
140 }
141
142 inline void beginList() {
143 os.put(EMPTY_LIST);
144 os.put(BINPUT);
145 os.put(1);
146 os.put(MARK);
147 }
148
149 inline void endList(void) {
150 os.put(APPENDS);
151 }
152
153 inline void beginTuple() {
154 os.put(MARK);
155 }
156
157 inline void endTuple(void) {
158 os.put(TUPLE);
159 }
160
161 inline void putInt(int i) {
162 os.put( i & 0xff);
163 os.put((i >> 8) & 0xff);
164 os.put((i >> 16) & 0xff);
165 os.put((i >> 24) & 0xff);
166 }
167
168 inline void writeString(const char *s, size_t length) {
169 if (!s) {
170 writeNone();
171 return;
172 }
173
174 if (length < 256) {
175 os.put(SHORT_BINSTRING);
176 os.put(length);
177 } else {
178 os.put(BINSTRING);
179 putInt(length);
180 }
181 os.write(s, length);
182
183 os.put(BINPUT);
184 os.put(1);
185 }
186
187 inline void writeString(const char *s) {
188 if (!s) {
189 writeNone();
190 return;
191 }
192
193 writeString(s, strlen(s));
194 }
195
196 inline void writeString(const std::string &s) {
197 writeString(s.c_str(), s.size());
198 }
199
200 inline void writeNone(void) {
201 os.put(NONE);
202 }
203
204 inline void writeBool(bool b) {
205 os.put(b ? NEWTRUE : NEWFALSE);
206 }
207
208 inline void writeInt(long i) {
209 // TODO: binary
210 os.put(INT);
211 os << i << '\n';
212 }
213
214 inline void writeFloat(float f) {
215 // TODO: binary
216 os.put(FLOAT);
217 os << f << '\n';
218 }
219};
220
221#endif /* _Pickle_HPP_ */