]> git.cworth.org Git - apitrace/blob - common/pickle.hpp
c8f90ae12bc1ee5eb1a6915be8ce9ac4b4f39ed3
[apitrace] / common / pickle.hpp
1 /**************************************************************************
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
40 class PickleWriter
41 {
42 private:
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
106 public:
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_ */