Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/indexedDB/Key.h
Line
Count
Source (jump to first uncovered line)
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
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
  Key()
47
  {
48
    Unset();
49
  }
50
51
  explicit
52
  Key(const nsACString& aBuffer)
53
    : 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
  operator==(const Key& aOther) const
72
  {
73
    Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
74
75
    return mBuffer.Equals(aOther.mBuffer);
76
  }
77
78
  bool
79
  operator!=(const Key& aOther) const
80
0
  {
81
0
    Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
82
0
83
0
    return !mBuffer.Equals(aOther.mBuffer);
84
0
  }
85
86
  bool
87
  operator<(const Key& aOther) const
88
0
  {
89
0
    Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
90
0
91
0
    return Compare(mBuffer, aOther.mBuffer) < 0;
92
0
  }
93
94
  bool
95
  operator>(const Key& aOther) const
96
0
  {
97
0
    Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
98
0
99
0
    return Compare(mBuffer, aOther.mBuffer) > 0;
100
0
  }
101
102
  bool
103
  operator<=(const Key& aOther) const
104
0
  {
105
0
    Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
106
0
107
0
    return Compare(mBuffer, aOther.mBuffer) <= 0;
108
0
  }
109
110
  bool
111
  operator>=(const Key& aOther) const
112
0
  {
113
0
    Assert(!mBuffer.IsVoid() && !aOther.mBuffer.IsVoid());
114
0
115
0
    return Compare(mBuffer, aOther.mBuffer) >= 0;
116
0
  }
117
118
  void
119
  Unset()
120
  {
121
    mBuffer.SetIsVoid(true);
122
  }
123
124
  bool
125
  IsUnset() const
126
0
  {
127
0
    return mBuffer.IsVoid();
128
0
  }
129
130
  bool
131
  IsFloat() const
132
0
  {
133
0
    return !IsUnset() && *BufferStart() == eFloat;
134
0
  }
135
136
  bool
137
  IsDate() const
138
0
  {
139
0
    return !IsUnset() && *BufferStart() == eDate;
140
0
  }
141
142
  bool
143
  IsString() const
144
0
  {
145
0
    return !IsUnset() && *BufferStart() == eString;
146
0
  }
147
148
  bool
149
  IsBinary() const
150
0
  {
151
0
    return !IsUnset() && *BufferStart() == eBinary;
152
0
  }
153
154
  bool
155
  IsArray() const
156
  {
157
    return !IsUnset() && *BufferStart() >= eArray;
158
  }
159
160
  double
161
  ToFloat() const
162
0
  {
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
0
  }
169
170
  double
171
  ToDateMsec() const
172
0
  {
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
0
  }
179
180
  void
181
  ToString(nsString& aString) const
182
0
  {
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
  SetFromString(const nsAString& aString)
191
0
  {
192
0
    mBuffer.Truncate();
193
0
    EncodeString(aString, 0);
194
0
    TrimBuffer();
195
0
  }
196
197
  void
198
  SetFromInteger(int64_t aInt)
199
0
  {
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
  nsresult
218
  ToLocaleBasedKey(Key& aTarget, const nsCString& aLocale) const;
219
220
  void
221
  FinishArray()
222
0
  {
223
0
    TrimBuffer();
224
0
  }
225
226
  const nsCString&
227
  GetBuffer() const
228
0
  {
229
0
    return mBuffer;
230
0
  }
231
232
  nsresult
233
  BindToStatement(mozIStorageStatement* aStatement,
234
                  const nsACString& aParamName) const;
235
236
  nsresult
237
  SetFromStatement(mozIStorageStatement* aStatement, uint32_t aIndex);
238
239
  nsresult
240
  SetFromValueArray(mozIStorageValueArray* aValues, uint32_t aIndex);
241
242
  static int16_t
243
  CompareKeys(const Key& aFirst, const Key& aSecond)
244
0
  {
245
0
    int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
246
0
247
0
    if (result < 0) {
248
0
      return -1;
249
0
    }
250
0
251
0
    if (result > 0) {
252
0
      return 1;
253
0
    }
254
0
255
0
    return 0;
256
0
  }
257
258
private:
259
  const unsigned char*
260
  BufferStart() const
261
0
  {
262
0
    return reinterpret_cast<const unsigned char*>(mBuffer.BeginReading());
263
0
  }
264
265
  const unsigned char*
266
  BufferEnd() const
267
0
  {
268
0
    return reinterpret_cast<const unsigned char*>(mBuffer.EndReading());
269
0
  }
270
271
  // Encoding helper. Trims trailing zeros off of mBuffer as a post-processing
272
  // step.
273
  void
274
  TrimBuffer()
275
0
  {
276
0
    const char* end = mBuffer.EndReading() - 1;
277
0
    while (!*end) {
278
0
      --end;
279
0
    }
280
0
281
0
    mBuffer.Truncate(end + 1 - mBuffer.BeginReading());
282
0
  }
283
284
  // Encoding functions. These append the encoded value to the end of mBuffer
285
  nsresult
286
  EncodeJSVal(JSContext* aCx, JS::Handle<JS::Value> aVal, uint8_t aTypeOffset);
287
288
  nsresult
289
  EncodeString(const nsAString& aString, uint8_t aTypeOffset);
290
291
  template <typename T>
292
  nsresult
293
  EncodeString(const T* aStart, const T* aEnd, uint8_t aTypeOffset);
294
295
  template <typename T>
296
  nsresult
297
  EncodeAsString(const T* aStart, const T* aEnd, uint8_t aType);
298
299
  nsresult
300
  EncodeLocaleString(const nsDependentString& aString, uint8_t aTypeOffset,
301
                     const nsCString& aLocale);
302
303
  void
304
  EncodeNumber(double aFloat, uint8_t aType);
305
306
  nsresult
307
  EncodeBinary(JSObject* aObject, bool aIsViewObject, uint8_t aTypeOffset);
308
309
  // Decoding functions. aPos points into mBuffer and is adjusted to point
310
  // past the consumed value.
311
  static nsresult
312
  DecodeJSVal(const unsigned char*& aPos,
313
              const unsigned char* aEnd,
314
              JSContext* aCx,
315
              JS::MutableHandle<JS::Value> aVal);
316
317
  static void
318
  DecodeString(const unsigned char*& aPos,
319
               const unsigned char* aEnd,
320
               nsString& aString);
321
322
  static double
323
  DecodeNumber(const unsigned char*& aPos, const unsigned char* aEnd);
324
325
  static JSObject*
326
  DecodeBinary(const unsigned char*& aPos,
327
               const unsigned char* aEnd,
328
               JSContext* aCx);
329
330
  nsresult
331
  EncodeJSValInternal(JSContext* aCx,
332
                      JS::Handle<JS::Value> aVal,
333
                      uint8_t aTypeOffset,
334
                      uint16_t aRecursionDepth);
335
336
  static nsresult
337
  DecodeJSValInternal(const unsigned char*& aPos,
338
                      const unsigned char* aEnd,
339
                      JSContext* aCx,
340
                      uint8_t aTypeOffset,
341
                      JS::MutableHandle<JS::Value> aVal,
342
                      uint16_t aRecursionDepth);
343
344
  template <typename T>
345
  nsresult
346
  SetFromSource(T* aSource, uint32_t aIndex);
347
348
  void
349
  Assert(bool aCondition) const
350
#ifdef DEBUG
351
  ;
352
#else
353
  { }
354
#endif
355
};
356
357
} // namespace indexedDB
358
} // namespace dom
359
} // namespace mozilla
360
361
#endif // mozilla_dom_indexeddb_key_h__