Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / indexedDB / Key.h
blob4ab780c225edef49532f24dd5dbda9eed51343f6
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=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/. */
7 #ifndef mozilla_dom_indexeddb_key_h__
8 #define mozilla_dom_indexeddb_key_h__
10 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
12 #include "mozIStorageStatement.h"
14 #include "js/Value.h"
16 namespace IPC {
17 template <typename T> struct ParamTraits;
18 } // namespace IPC
20 BEGIN_INDEXEDDB_NAMESPACE
22 class Key
24 friend struct IPC::ParamTraits<Key>;
26 public:
27 Key()
29 Unset();
32 Key& operator=(const nsAString& aString)
34 SetFromString(aString);
35 return *this;
38 Key& operator=(int64_t aInt)
40 SetFromInteger(aInt);
41 return *this;
44 bool operator==(const Key& aOther) const
46 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
47 "Don't compare unset keys!");
49 return mBuffer.Equals(aOther.mBuffer);
52 bool operator!=(const Key& aOther) const
54 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
55 "Don't compare unset keys!");
57 return !mBuffer.Equals(aOther.mBuffer);
60 bool operator<(const Key& aOther) const
62 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
63 "Don't compare unset keys!");
65 return Compare(mBuffer, aOther.mBuffer) < 0;
68 bool operator>(const Key& aOther) const
70 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
71 "Don't compare unset keys!");
73 return Compare(mBuffer, aOther.mBuffer) > 0;
76 bool operator<=(const Key& aOther) const
78 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
79 "Don't compare unset keys!");
81 return Compare(mBuffer, aOther.mBuffer) <= 0;
84 bool operator>=(const Key& aOther) const
86 NS_ASSERTION(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid(),
87 "Don't compare unset keys!");
89 return Compare(mBuffer, aOther.mBuffer) >= 0;
92 void
93 Unset()
95 mBuffer.SetIsVoid(true);
98 bool IsUnset() const
100 return mBuffer.IsVoid();
103 bool IsFloat() const
105 return !IsUnset() && mBuffer.First() == eFloat;
108 bool IsDate() const
110 return !IsUnset() && mBuffer.First() == eDate;
113 bool IsString() const
115 return !IsUnset() && mBuffer.First() == eString;
118 bool IsArray() const
120 return !IsUnset() && mBuffer.First() >= eArray;
123 double ToFloat() const
125 NS_ASSERTION(IsFloat(), "Why'd you call this?");
126 const unsigned char* pos = BufferStart();
127 double res = DecodeNumber(pos, BufferEnd());
128 NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
129 return res;
132 double ToDateMsec() const
134 NS_ASSERTION(IsDate(), "Why'd you call this?");
135 const unsigned char* pos = BufferStart();
136 double res = DecodeNumber(pos, BufferEnd());
137 NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
138 return res;
141 void ToString(nsString& aString) const
143 NS_ASSERTION(IsString(), "Why'd you call this?");
144 const unsigned char* pos = BufferStart();
145 DecodeString(pos, BufferEnd(), aString);
146 NS_ASSERTION(pos >= BufferEnd(), "Should consume whole buffer");
149 void SetFromString(const nsAString& aString)
151 mBuffer.Truncate();
152 EncodeString(aString, 0);
153 TrimBuffer();
156 void SetFromInteger(int64_t aInt)
158 mBuffer.Truncate();
159 EncodeNumber(double(aInt), eFloat);
160 TrimBuffer();
163 nsresult SetFromJSVal(JSContext* aCx,
164 JS::Handle<JS::Value> aVal)
166 mBuffer.Truncate();
168 if (aVal.isNull() || aVal.isUndefined()) {
169 Unset();
170 return NS_OK;
173 nsresult rv = EncodeJSVal(aCx, aVal, 0);
174 if (NS_FAILED(rv)) {
175 Unset();
176 return rv;
178 TrimBuffer();
180 return NS_OK;
183 nsresult ToJSVal(JSContext* aCx,
184 JS::MutableHandle<JS::Value> aVal) const
186 if (IsUnset()) {
187 aVal.setUndefined();
188 return NS_OK;
191 const unsigned char* pos = BufferStart();
192 nsresult rv = DecodeJSVal(pos, BufferEnd(), aCx, 0, aVal);
193 NS_ENSURE_SUCCESS(rv, rv);
195 NS_ASSERTION(pos >= BufferEnd(),
196 "Didn't consume whole buffer");
198 return NS_OK;
201 nsresult ToJSVal(JSContext* aCx,
202 JS::Heap<JS::Value>& aVal) const
204 JS::Rooted<JS::Value> value(aCx);
205 nsresult rv = ToJSVal(aCx, &value);
206 if (NS_SUCCEEDED(rv)) {
207 aVal = value;
209 return rv;
212 nsresult AppendItem(JSContext* aCx,
213 bool aFirstOfArray,
214 JS::Handle<JS::Value> aVal)
216 nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
217 if (NS_FAILED(rv)) {
218 Unset();
219 return rv;
222 return NS_OK;
225 void FinishArray()
227 TrimBuffer();
230 const nsCString& GetBuffer() const
232 return mBuffer;
235 nsresult BindToStatement(mozIStorageStatement* aStatement,
236 const nsACString& aParamName) const
238 nsresult rv = aStatement->BindBlobByName(aParamName,
239 reinterpret_cast<const uint8_t*>(mBuffer.get()), mBuffer.Length());
241 return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
244 nsresult SetFromStatement(mozIStorageStatement* aStatement,
245 uint32_t aIndex)
247 uint8_t* data;
248 uint32_t dataLength = 0;
250 nsresult rv = aStatement->GetBlob(aIndex, &dataLength, &data);
251 NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
253 mBuffer.Adopt(
254 reinterpret_cast<char*>(const_cast<uint8_t*>(data)), dataLength);
256 return NS_OK;
259 static
260 int16_t CompareKeys(Key& aFirst, Key& aSecond)
262 int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
264 if (result < 0) {
265 return -1;
268 if (result > 0) {
269 return 1;
272 return 0;
275 private:
276 const unsigned char* BufferStart() const
278 return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading());
281 const unsigned char* BufferEnd() const
283 return reinterpret_cast<const unsigned char*>(mBuffer.EndReading());
286 enum {
287 eTerminator = 0,
288 eFloat = 1,
289 eDate = 2,
290 eString = 3,
291 eArray = 4,
292 eMaxType = eArray
295 // Encoding helper. Trims trailing zeros off of mBuffer as a post-processing
296 // step.
297 void TrimBuffer()
299 const char* end = mBuffer.EndReading() - 1;
300 while (!*end) {
301 --end;
304 mBuffer.Truncate(end + 1 - mBuffer.BeginReading());
307 // Encoding functions. These append the encoded value to the end of mBuffer
308 inline nsresult EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal,
309 uint8_t aTypeOffset)
311 return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
313 void EncodeString(const nsAString& aString, uint8_t aTypeOffset);
314 void EncodeNumber(double aFloat, uint8_t aType);
316 // Decoding functions. aPos points into mBuffer and is adjusted to point
317 // past the consumed value.
318 static inline nsresult DecodeJSVal(const unsigned char*& aPos,
319 const unsigned char* aEnd, JSContext* aCx,
320 uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal)
322 return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
325 static void DecodeString(const unsigned char*& aPos,
326 const unsigned char* aEnd,
327 nsString& aString);
328 static double DecodeNumber(const unsigned char*& aPos,
329 const unsigned char* aEnd);
331 nsCString mBuffer;
333 private:
334 nsresult EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
335 uint8_t aTypeOffset, uint16_t aRecursionDepth);
337 static nsresult DecodeJSValInternal(const unsigned char*& aPos,
338 const unsigned char* aEnd,
339 JSContext* aCx, uint8_t aTypeOffset,
340 JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth);
343 END_INDEXEDDB_NAMESPACE
345 #endif /* mozilla_dom_indexeddb_key_h__ */