1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is JavaScript structured data serialization.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * the Mozilla Foundation.
19 : * Portions created by the Initial Developer are Copyright (C) 2010
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Jason Orendorff <jorendorff@mozilla.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef jsclone_h___
40 : #define jsclone_h___
41 :
42 : #include "jsapi.h"
43 : #include "jscntxt.h"
44 :
45 : #include "js/HashTable.h"
46 : #include "js/Vector.h"
47 :
48 : namespace js {
49 :
50 : bool
51 : WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nbytesp,
52 : const JSStructuredCloneCallbacks *cb, void *cbClosure);
53 :
54 : bool
55 : ReadStructuredClone(JSContext *cx, const uint64_t *data, size_t nbytes, Value *vp,
56 : const JSStructuredCloneCallbacks *cb, void *cbClosure);
57 :
58 1891 : struct SCOutput {
59 : public:
60 : explicit SCOutput(JSContext *cx);
61 :
62 11835 : JSContext *context() const { return cx; }
63 :
64 : bool write(uint64_t u);
65 : bool writePair(uint32_t tag, uint32_t data);
66 : bool writeDouble(double d);
67 : bool writeBytes(const void *p, size_t nbytes);
68 : bool writeChars(const jschar *p, size_t nchars);
69 :
70 : template <class T>
71 : bool writeArray(const T *p, size_t nbytes);
72 :
73 : bool extractBuffer(uint64_t **datap, size_t *sizep);
74 :
75 16 : uint64_t count() { return buf.length(); }
76 :
77 : private:
78 : JSContext *cx;
79 : js::Vector<uint64_t> buf;
80 : };
81 :
82 : struct SCInput {
83 : public:
84 : SCInput(JSContext *cx, const uint64_t *data, size_t nbytes);
85 :
86 7171 : JSContext *context() const { return cx; }
87 :
88 : bool read(uint64_t *p);
89 : bool readPair(uint32_t *tagp, uint32_t *datap);
90 : bool readDouble(double *p);
91 : bool readBytes(void *p, size_t nbytes);
92 : bool readChars(jschar *p, size_t nchars);
93 :
94 : template <class T>
95 : bool readArray(T *p, size_t nelems);
96 :
97 : private:
98 : bool eof();
99 :
100 : void staticAssertions() {
101 : JS_STATIC_ASSERT(sizeof(jschar) == 2);
102 : JS_STATIC_ASSERT(sizeof(uint32_t) == 4);
103 : JS_STATIC_ASSERT(sizeof(double) == 8);
104 : }
105 :
106 : JSContext *cx;
107 : const uint64_t *point;
108 : const uint64_t *end;
109 : };
110 :
111 : }
112 :
113 756 : struct JSStructuredCloneReader {
114 : public:
115 756 : explicit JSStructuredCloneReader(js::SCInput &in, const JSStructuredCloneCallbacks *cb,
116 : void *cbClosure)
117 : : in(in), objs(in.context()), allObjs(in.context()),
118 756 : callbacks(cb), closure(cbClosure) { }
119 :
120 0 : js::SCInput &input() { return in; }
121 : bool read(js::Value *vp);
122 :
123 : private:
124 5659 : JSContext *context() { return in.context(); }
125 :
126 : bool checkDouble(double d);
127 : JSString *readString(uint32_t nchars);
128 : bool readTypedArray(uint32_t tag, uint32_t nelems, js::Value *vp);
129 : bool readArrayBuffer(uint32_t nbytes, js::Value *vp);
130 : bool readId(jsid *idp);
131 : bool startRead(js::Value *vp);
132 :
133 : js::SCInput ∈
134 :
135 : // Stack of objects with properties remaining to be read.
136 : js::AutoValueVector objs;
137 :
138 : // Stack of all objects read during this deserialization
139 : js::AutoValueVector allObjs;
140 :
141 : // The user defined callbacks that will be used for cloning.
142 : const JSStructuredCloneCallbacks *callbacks;
143 :
144 : // Any value passed to JS_ReadStructuredClone.
145 : void *closure;
146 : };
147 :
148 1891 : struct JSStructuredCloneWriter {
149 : public:
150 1891 : explicit JSStructuredCloneWriter(js::SCOutput &out, const JSStructuredCloneCallbacks *cb,
151 : void *cbClosure)
152 : : out(out), objs(out.context()), counts(out.context()), ids(out.context()),
153 1891 : memory(out.context()), callbacks(cb), closure(cbClosure) { }
154 :
155 1891 : bool init() { return memory.init(); }
156 :
157 : bool write(const js::Value &v);
158 :
159 32 : js::SCOutput &output() { return out; }
160 :
161 : private:
162 4271 : JSContext *context() { return out.context(); }
163 :
164 : bool writeString(uint32_t tag, JSString *str);
165 : bool writeId(jsid id);
166 : bool writeArrayBuffer(JSObject *obj);
167 : bool writeTypedArray(JSObject *obj);
168 : bool startObject(JSObject *obj);
169 : bool startWrite(const js::Value &v);
170 :
171 : inline void checkStack();
172 :
173 : js::SCOutput &out;
174 :
175 : // Vector of objects with properties remaining to be written.
176 : js::AutoValueVector objs;
177 :
178 : // counts[i] is the number of properties of objs[i] remaining to be written.
179 : // counts.length() == objs.length() and sum(counts) == ids.length().
180 : js::Vector<size_t> counts;
181 :
182 : // Ids of properties remaining to be written.
183 : js::AutoIdVector ids;
184 :
185 : // The "memory" list described in the HTML5 internal structured cloning algorithm.
186 : // memory is a superset of objs; items are never removed from Memory
187 : // until a serialization operation is finished
188 : typedef js::HashMap<JSObject *, uint32_t> CloneMemory;
189 : CloneMemory memory;
190 :
191 : // The user defined callbacks that will be used for cloning.
192 : const JSStructuredCloneCallbacks *callbacks;
193 :
194 : // Any value passed to JS_WriteStructuredClone.
195 : void *closure;
196 : };
197 :
198 : #endif /* jsclone_h___ */
|