Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_dom_indexeddb_key_h__
8 : #define mozilla_dom_indexeddb_key_h__
9 :
10 : #include "js/RootingAPI.h"
11 : #include "nsString.h"
12 :
13 : class mozIStorageStatement;
14 : class mozIStorageValueArray;
15 :
16 : namespace IPC {
17 :
18 : template <typename> struct ParamTraits;
19 :
20 : } // namespace IPC
21 :
22 : namespace mozilla {
23 : namespace dom {
24 : namespace indexedDB {
25 :
26 0 : class Key
27 : {
28 : friend struct IPC::ParamTraits<Key>;
29 :
30 : nsCString mBuffer;
31 :
32 : public:
33 : enum {
34 : eTerminator = 0,
35 : eFloat = 0x10,
36 : eDate = 0x20,
37 : eString = 0x30,
38 : eBinary = 0x40,
39 : eArray = 0x50,
40 : eMaxType = eArray
41 : };
42 :
43 : static const uint8_t kMaxArrayCollapse = uint8_t(3);
44 : static const uint8_t kMaxRecursionDepth = uint8_t(64);
45 :
46 0 : Key()
47 0 : {
48 0 : Unset();
49 0 : }
50 :
51 : explicit
52 0 : Key(const nsACString& aBuffer)
53 0 : : mBuffer(aBuffer)
54 0 : { }
55 :
56 : Key&
57 : operator=(const nsAString& aString)
58 : {
59 : SetFromString(aString);
60 : return *this;
61 : }
62 :
63 : Key&
64 : operator=(int64_t aInt)
65 : {
66 : SetFromInteger(aInt);
67 : return *this;
68 : }
69 :
70 : bool
71 0 : operator==(const Key& aOther) const
72 : {
73 0 : Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
74 :
75 0 : return mBuffer.Equals(aOther.mBuffer);
76 : }
77 :
78 : bool
79 0 : operator!=(const Key& aOther) const
80 : {
81 0 : Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
82 :
83 0 : return !mBuffer.Equals(aOther.mBuffer);
84 : }
85 :
86 : bool
87 0 : operator<(const Key& aOther) const
88 : {
89 0 : Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
90 :
91 0 : return Compare(mBuffer, aOther.mBuffer) < 0;
92 : }
93 :
94 : bool
95 0 : operator>(const Key& aOther) const
96 : {
97 0 : Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
98 :
99 0 : return Compare(mBuffer, aOther.mBuffer) > 0;
100 : }
101 :
102 : bool
103 0 : operator<=(const Key& aOther) const
104 : {
105 0 : Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
106 :
107 0 : return Compare(mBuffer, aOther.mBuffer) <= 0;
108 : }
109 :
110 : bool
111 0 : operator>=(const Key& aOther) const
112 : {
113 0 : Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
114 :
115 0 : return Compare(mBuffer, aOther.mBuffer) >= 0;
116 : }
117 :
118 : void
119 0 : Unset()
120 : {
121 0 : mBuffer.SetIsVoid(true);
122 0 : }
123 :
124 : bool
125 0 : IsUnset() const
126 : {
127 0 : return mBuffer.IsVoid();
128 : }
129 :
130 : bool
131 0 : IsFloat() const
132 : {
133 0 : return !IsUnset() && *BufferStart() == eFloat;
134 : }
135 :
136 : bool
137 0 : IsDate() const
138 : {
139 0 : return !IsUnset() && *BufferStart() == eDate;
140 : }
141 :
142 : bool
143 0 : IsString() const
144 : {
145 0 : return !IsUnset() && *BufferStart() == eString;
146 : }
147 :
148 : bool
149 0 : IsBinary() const
150 : {
151 0 : return !IsUnset() && *BufferStart() == eBinary;
152 : }
153 :
154 : bool
155 0 : IsArray() const
156 : {
157 0 : return !IsUnset() && *BufferStart() >= eArray;
158 : }
159 :
160 : double
161 0 : ToFloat() const
162 : {
163 0 : Assert(IsFloat());
164 0 : const unsigned char* pos = BufferStart();
165 0 : double res = DecodeNumber(pos, BufferEnd());
166 0 : Assert(pos >= BufferEnd());
167 0 : return res;
168 : }
169 :
170 : double
171 0 : ToDateMsec() const
172 : {
173 0 : Assert(IsDate());
174 0 : const unsigned char* pos = BufferStart();
175 0 : double res = DecodeNumber(pos, BufferEnd());
176 0 : Assert(pos >= BufferEnd());
177 0 : return res;
178 : }
179 :
180 : void
181 0 : ToString(nsString& aString) const
182 : {
183 0 : Assert(IsString());
184 0 : const unsigned char* pos = BufferStart();
185 0 : DecodeString(pos, BufferEnd(), aString);
186 0 : Assert(pos >= BufferEnd());
187 0 : }
188 :
189 : void
190 0 : SetFromString(const nsAString& aString)
191 : {
192 0 : mBuffer.Truncate();
193 0 : EncodeString(aString, 0);
194 0 : TrimBuffer();
195 0 : }
196 :
197 : void
198 0 : SetFromInteger(int64_t aInt)
199 : {
200 0 : mBuffer.Truncate();
201 0 : EncodeNumber(double(aInt), eFloat);
202 0 : TrimBuffer();
203 0 : }
204 :
205 : nsresult
206 : SetFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal);
207 :
208 : nsresult
209 : ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) const;
210 :
211 : nsresult
212 : ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aVal) const;
213 :
214 : nsresult
215 : AppendItem(JSContext* aCx, bool aFirstOfArray, JS::Handle<JS::Value> aVal);
216 :
217 : #ifdef ENABLE_INTL_API
218 : nsresult
219 : ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const;
220 : #endif
221 :
222 : void
223 0 : FinishArray()
224 : {
225 0 : TrimBuffer();
226 0 : }
227 :
228 : const nsCString&
229 0 : GetBuffer() const
230 : {
231 0 : return mBuffer;
232 : }
233 :
234 : nsresult
235 : BindToStatement(mozIStorageStatement* aStatement,
236 : const nsACString& aParamName) const;
237 :
238 : nsresult
239 : SetFromStatement(mozIStorageStatement* aStatement, uint32_t aIndex);
240 :
241 : nsresult
242 : SetFromValueArray(mozIStorageValueArray* aValues, uint32_t aIndex);
243 :
244 : static int16_t
245 0 : CompareKeys(const Key& aFirst, const Key& aSecond)
246 : {
247 0 : int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
248 :
249 0 : if (result < 0) {
250 0 : return -1;
251 : }
252 :
253 0 : if (result > 0) {
254 0 : return 1;
255 : }
256 :
257 0 : return 0;
258 : }
259 :
260 : private:
261 : const unsigned char*
262 0 : BufferStart() const
263 : {
264 0 : return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading());
265 : }
266 :
267 : const unsigned char*
268 0 : BufferEnd() const
269 : {
270 0 : return reinterpret_cast<const unsigned char*>(mBuffer.EndReading());
271 : }
272 :
273 : // Encoding helper. Trims trailing zeros off of mBuffer as a post-processing
274 : // step.
275 : void
276 0 : TrimBuffer()
277 : {
278 0 : const char* end = mBuffer.EndReading() - 1;
279 0 : while (!*end) {
280 0 : --end;
281 : }
282 :
283 0 : mBuffer.Truncate(end + 1 - mBuffer.BeginReading());
284 0 : }
285 :
286 : // Encoding functions. These append the encoded value to the end of mBuffer
287 : nsresult
288 : EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset);
289 :
290 : void
291 : EncodeString(const nsAString& aString, uint8_t aTypeOffset);
292 :
293 : template <typename T>
294 : void
295 : EncodeString(const T* aStart, const T* aEnd, uint8_t aTypeOffset);
296 :
297 : template <typename T>
298 : void
299 : EncodeAsString(const T* aStart, const T* aEnd, uint8_t aType);
300 :
301 : #ifdef ENABLE_INTL_API
302 : nsresult
303 : EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset,
304 : const nsCString& aLocale);
305 : #endif
306 :
307 : void
308 : EncodeNumber(double aFloat, uint8_t aType);
309 :
310 : void
311 : EncodeBinary(JSObject* aObject, bool aIsViewObject, uint8_t aTypeOffset);
312 :
313 : // Decoding functions. aPos points into mBuffer and is adjusted to point
314 : // past the consumed value.
315 : static nsresult
316 : DecodeJSVal(const unsigned char*& aPos,
317 : const unsigned char* aEnd,
318 : JSContext* aCx,
319 : JS::MutableHandle<JS::Value> aVal);
320 :
321 : static void
322 : DecodeString(const unsigned char*& aPos,
323 : const unsigned char* aEnd,
324 : nsString& aString);
325 :
326 : static double
327 : DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd);
328 :
329 : static JSObject*
330 : DecodeBinary(const unsigned char*& aPos,
331 : const unsigned char* aEnd,
332 : JSContext* aCx);
333 :
334 : nsresult
335 : EncodeJSValInternal(JSContext* aCx,
336 : JS::Handle<JS::Value> aVal,
337 : uint8_t aTypeOffset,
338 : uint16_t aRecursionDepth);
339 :
340 : static nsresult
341 : DecodeJSValInternal(const unsigned char*& aPos,
342 : const unsigned char* aEnd,
343 : JSContext* aCx,
344 : uint8_t aTypeOffset,
345 : JS::MutableHandle<JS::Value> aVal,
346 : uint16_t aRecursionDepth);
347 :
348 : template <typename T>
349 : nsresult
350 : SetFromSource(T* aSource, uint32_t aIndex);
351 :
352 : void
353 : Assert(bool aCondition) const
354 : #ifdef DEBUG
355 : ;
356 : #else
357 : { }
358 : #endif
359 : };
360 :
361 : } // namespace indexedDB
362 : } // namespace dom
363 : } // namespace mozilla
364 :
365 : #endif // mozilla_dom_indexeddb_key_h__
|