1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_CODING_H_
6#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_CODING_H_
7
8#include <string>
9#include <utility>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/logging.h"
14#include "base/memory/ref_counted.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/strings/string16.h"
17#include "base/strings/string_piece.h"
18#include "content/common/indexed_db/indexed_db_key.h"
19#include "content/common/indexed_db/indexed_db_key_path.h"
20
21namespace content {
22
23CONTENT_EXPORT extern const unsigned char kMinimumIndexId;
24
25CONTENT_EXPORT std::string MaxIDBKey();
26CONTENT_EXPORT std::string MinIDBKey();
27
28// DatabaseId, BlobKey
29typedef std::pair<int64_t, int64_t> BlobJournalEntryType;
30typedef std::vector<BlobJournalEntryType> BlobJournalType;
31
32CONTENT_EXPORT void EncodeByte(unsigned char value, std::string* into);
33CONTENT_EXPORT void EncodeBool(bool value, std::string* into);
34CONTENT_EXPORT void EncodeInt(int64 value, std::string* into);
35CONTENT_EXPORT void EncodeVarInt(int64 value, std::string* into);
36CONTENT_EXPORT void EncodeString(const base::string16& value,
37                                 std::string* into);
38CONTENT_EXPORT void EncodeStringWithLength(const base::string16& value,
39                                           std::string* into);
40CONTENT_EXPORT void EncodeBinary(const std::string& value, std::string* into);
41CONTENT_EXPORT void EncodeDouble(double value, std::string* into);
42CONTENT_EXPORT void EncodeIDBKey(const IndexedDBKey& value, std::string* into);
43CONTENT_EXPORT void EncodeIDBKeyPath(const IndexedDBKeyPath& value,
44                                     std::string* into);
45CONTENT_EXPORT void EncodeBlobJournal(const BlobJournalType& journal,
46                                      std::string* into);
47
48CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeByte(base::StringPiece* slice,
49                                                  unsigned char* value);
50CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBool(base::StringPiece* slice,
51                                                  bool* value);
52CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeInt(base::StringPiece* slice,
53                                                 int64* value);
54CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeVarInt(base::StringPiece* slice,
55                                                    int64* value);
56CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeString(base::StringPiece* slice,
57                                                    base::string16* value);
58CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeStringWithLength(
59    base::StringPiece* slice,
60    base::string16* value);
61CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBinary(base::StringPiece* slice,
62                                                    std::string* value);
63CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeDouble(base::StringPiece* slice,
64                                                    double* value);
65CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKey(
66    base::StringPiece* slice,
67    scoped_ptr<IndexedDBKey>* value);
68CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKeyPath(
69    base::StringPiece* slice,
70    IndexedDBKeyPath* value);
71CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBlobJournal(
72    base::StringPiece* slice,
73    BlobJournalType* journal);
74
75CONTENT_EXPORT int CompareEncodedStringsWithLength(base::StringPiece* slice1,
76                                                   base::StringPiece* slice2,
77                                                   bool* ok);
78
79CONTENT_EXPORT WARN_UNUSED_RESULT bool ExtractEncodedIDBKey(
80    base::StringPiece* slice,
81    std::string* result);
82
83CONTENT_EXPORT int CompareEncodedIDBKeys(base::StringPiece* slice1,
84                                         base::StringPiece* slice2,
85                                         bool* ok);
86
87CONTENT_EXPORT int Compare(const base::StringPiece& a,
88                           const base::StringPiece& b,
89                           bool index_keys);
90
91class KeyPrefix {
92 public:
93  // These are serialized to disk; any new items must be appended, and none can
94  // be deleted.
95  enum Type {
96    GLOBAL_METADATA,
97    DATABASE_METADATA,
98    OBJECT_STORE_DATA,
99    EXISTS_ENTRY,
100    INDEX_DATA,
101    INVALID_TYPE,
102    BLOB_ENTRY
103  };
104
105  static const size_t kMaxDatabaseIdSizeBits = 3;
106  static const size_t kMaxObjectStoreIdSizeBits = 3;
107  static const size_t kMaxIndexIdSizeBits = 2;
108
109  static const size_t kMaxDatabaseIdSizeBytes =
110      1ULL << kMaxDatabaseIdSizeBits;  // 8
111  static const size_t kMaxObjectStoreIdSizeBytes =
112      1ULL << kMaxObjectStoreIdSizeBits;                                   // 8
113  static const size_t kMaxIndexIdSizeBytes = 1ULL << kMaxIndexIdSizeBits;  // 4
114
115  static const size_t kMaxDatabaseIdBits =
116      kMaxDatabaseIdSizeBytes * 8 - 1;  // 63
117  static const size_t kMaxObjectStoreIdBits =
118      kMaxObjectStoreIdSizeBytes * 8 - 1;                              // 63
119  static const size_t kMaxIndexIdBits = kMaxIndexIdSizeBytes * 8 - 1;  // 31
120
121  static const int64 kMaxDatabaseId =
122      (1ULL << kMaxDatabaseIdBits) - 1;  // max signed int64
123  static const int64 kMaxObjectStoreId =
124      (1ULL << kMaxObjectStoreIdBits) - 1;  // max signed int64
125  static const int64 kMaxIndexId =
126      (1ULL << kMaxIndexIdBits) - 1;  // max signed int32
127
128  static const int64 kInvalidId = -1;
129
130  KeyPrefix();
131  explicit KeyPrefix(int64 database_id);
132  KeyPrefix(int64 database_id, int64 object_store_id);
133  KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id);
134  static KeyPrefix CreateWithSpecialIndex(int64 database_id,
135                                          int64 object_store_id,
136                                          int64 index_id);
137
138  static bool Decode(base::StringPiece* slice, KeyPrefix* result);
139  std::string Encode() const;
140  static std::string EncodeEmpty();
141  int Compare(const KeyPrefix& other) const;
142
143  CONTENT_EXPORT static bool IsValidDatabaseId(int64 database_id);
144  static bool IsValidObjectStoreId(int64 index_id);
145  static bool IsValidIndexId(int64 index_id);
146  static bool ValidIds(int64 database_id,
147                       int64 object_store_id,
148                       int64 index_id) {
149    return IsValidDatabaseId(database_id) &&
150           IsValidObjectStoreId(object_store_id) && IsValidIndexId(index_id);
151  }
152  static bool ValidIds(int64 database_id, int64 object_store_id) {
153    return IsValidDatabaseId(database_id) &&
154           IsValidObjectStoreId(object_store_id);
155  }
156
157  Type type() const;
158
159  int64 database_id_;
160  int64 object_store_id_;
161  int64 index_id_;
162
163 private:
164  // Special constructor for CreateWithSpecialIndex()
165  KeyPrefix(enum Type,
166            int64 database_id,
167            int64 object_store_id,
168            int64 index_id);
169
170  static std::string EncodeInternal(int64 database_id,
171                                    int64 object_store_id,
172                                    int64 index_id);
173};
174
175class SchemaVersionKey {
176 public:
177  CONTENT_EXPORT static std::string Encode();
178};
179
180class MaxDatabaseIdKey {
181 public:
182  CONTENT_EXPORT static std::string Encode();
183};
184
185class DataVersionKey {
186 public:
187  static std::string Encode();
188};
189
190class BlobJournalKey {
191 public:
192  static std::string Encode();
193};
194
195class LiveBlobJournalKey {
196 public:
197  static std::string Encode();
198};
199
200class DatabaseFreeListKey {
201 public:
202  DatabaseFreeListKey();
203  static bool Decode(base::StringPiece* slice, DatabaseFreeListKey* result);
204  CONTENT_EXPORT static std::string Encode(int64 database_id);
205  static CONTENT_EXPORT std::string EncodeMaxKey();
206  int64 DatabaseId() const;
207  int Compare(const DatabaseFreeListKey& other) const;
208
209 private:
210  int64 database_id_;
211};
212
213class DatabaseNameKey {
214 public:
215  static bool Decode(base::StringPiece* slice, DatabaseNameKey* result);
216  CONTENT_EXPORT static std::string Encode(const std::string& origin_identifier,
217                                           const base::string16& database_name);
218  static std::string EncodeMinKeyForOrigin(
219      const std::string& origin_identifier);
220  static std::string EncodeStopKeyForOrigin(
221      const std::string& origin_identifier);
222  base::string16 origin() const { return origin_; }
223  base::string16 database_name() const { return database_name_; }
224  int Compare(const DatabaseNameKey& other);
225
226 private:
227  base::string16 origin_;  // TODO(jsbell): Store encoded strings, or just
228                           // pointers.
229  base::string16 database_name_;
230};
231
232class DatabaseMetaDataKey {
233 public:
234  enum MetaDataType {
235    ORIGIN_NAME = 0,
236    DATABASE_NAME = 1,
237    USER_VERSION = 2,
238    MAX_OBJECT_STORE_ID = 3,
239    USER_INT_VERSION = 4,
240    BLOB_KEY_GENERATOR_CURRENT_NUMBER = 5,
241    MAX_SIMPLE_METADATA_TYPE = 6
242  };
243
244  CONTENT_EXPORT static const int64 kAllBlobsKey;
245  static const int64 kBlobKeyGeneratorInitialNumber;
246  // All keys <= 0 are invalid.  This one's just a convenient example.
247  static const int64 kInvalidBlobKey;
248
249  static bool IsValidBlobKey(int64 blobKey);
250  CONTENT_EXPORT static std::string Encode(int64 database_id,
251                                           MetaDataType type);
252};
253
254class ObjectStoreMetaDataKey {
255 public:
256  enum MetaDataType {
257    NAME = 0,
258    KEY_PATH = 1,
259    AUTO_INCREMENT = 2,
260    EVICTABLE = 3,
261    LAST_VERSION = 4,
262    MAX_INDEX_ID = 5,
263    HAS_KEY_PATH = 6,
264    KEY_GENERATOR_CURRENT_NUMBER = 7
265  };
266
267  ObjectStoreMetaDataKey();
268  static bool Decode(base::StringPiece* slice, ObjectStoreMetaDataKey* result);
269  CONTENT_EXPORT static std::string Encode(int64 database_id,
270                                           int64 object_store_id,
271                                           unsigned char meta_data_type);
272  CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id);
273  CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id,
274                                                 int64 object_store_id);
275  int64 ObjectStoreId() const;
276  unsigned char MetaDataType() const;
277  int Compare(const ObjectStoreMetaDataKey& other);
278
279 private:
280  int64 object_store_id_;
281  unsigned char meta_data_type_;
282};
283
284class IndexMetaDataKey {
285 public:
286  enum MetaDataType {
287    NAME = 0,
288    UNIQUE = 1,
289    KEY_PATH = 2,
290    MULTI_ENTRY = 3
291  };
292
293  IndexMetaDataKey();
294  static bool Decode(base::StringPiece* slice, IndexMetaDataKey* result);
295  CONTENT_EXPORT static std::string Encode(int64 database_id,
296                                           int64 object_store_id,
297                                           int64 index_id,
298                                           unsigned char meta_data_type);
299  CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id,
300                                                 int64 object_store_id);
301  CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id,
302                                                 int64 object_store_id,
303                                                 int64 index_id);
304  int Compare(const IndexMetaDataKey& other);
305  int64 IndexId() const;
306  unsigned char meta_data_type() const { return meta_data_type_; }
307
308 private:
309  int64 object_store_id_;
310  int64 index_id_;
311  unsigned char meta_data_type_;
312};
313
314class ObjectStoreFreeListKey {
315 public:
316  ObjectStoreFreeListKey();
317  static bool Decode(base::StringPiece* slice, ObjectStoreFreeListKey* result);
318  CONTENT_EXPORT static std::string Encode(int64 database_id,
319                                           int64 object_store_id);
320  CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id);
321  int64 ObjectStoreId() const;
322  int Compare(const ObjectStoreFreeListKey& other);
323
324 private:
325  int64 object_store_id_;
326};
327
328class IndexFreeListKey {
329 public:
330  IndexFreeListKey();
331  static bool Decode(base::StringPiece* slice, IndexFreeListKey* result);
332  CONTENT_EXPORT static std::string Encode(int64 database_id,
333                                           int64 object_store_id,
334                                           int64 index_id);
335  CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id,
336                                                 int64 object_store_id);
337  int Compare(const IndexFreeListKey& other);
338  int64 ObjectStoreId() const;
339  int64 IndexId() const;
340
341 private:
342  int64 object_store_id_;
343  int64 index_id_;
344};
345
346class ObjectStoreNamesKey {
347 public:
348  // TODO(jsbell): We never use this to look up object store ids,
349  // because a mapping is kept in the IndexedDBDatabase. Can the
350  // mapping become unreliable?  Can we remove this?
351  static bool Decode(base::StringPiece* slice, ObjectStoreNamesKey* result);
352  CONTENT_EXPORT static std::string Encode(
353      int64 database_id,
354      const base::string16& object_store_name);
355  int Compare(const ObjectStoreNamesKey& other);
356  base::string16 object_store_name() const { return object_store_name_; }
357
358 private:
359  // TODO(jsbell): Store the encoded string, or just pointers to it.
360  base::string16 object_store_name_;
361};
362
363class IndexNamesKey {
364 public:
365  IndexNamesKey();
366  // TODO(jsbell): We never use this to look up index ids, because a mapping
367  // is kept at a higher level.
368  static bool Decode(base::StringPiece* slice, IndexNamesKey* result);
369  CONTENT_EXPORT static std::string Encode(int64 database_id,
370                                           int64 object_store_id,
371                                           const base::string16& index_name);
372  int Compare(const IndexNamesKey& other);
373  base::string16 index_name() const { return index_name_; }
374
375 private:
376  int64 object_store_id_;
377  base::string16 index_name_;
378};
379
380class ObjectStoreDataKey {
381 public:
382  static const int64 kSpecialIndexNumber;
383
384  ObjectStoreDataKey();
385  ~ObjectStoreDataKey();
386
387  static bool Decode(base::StringPiece* slice, ObjectStoreDataKey* result);
388  CONTENT_EXPORT static std::string Encode(int64 database_id,
389                                           int64 object_store_id,
390                                           const std::string encoded_user_key);
391  static std::string Encode(int64 database_id,
392                            int64 object_store_id,
393                            const IndexedDBKey& user_key);
394  scoped_ptr<IndexedDBKey> user_key() const;
395 private:
396  std::string encoded_user_key_;
397};
398
399class ExistsEntryKey {
400 public:
401  ExistsEntryKey();
402  ~ExistsEntryKey();
403
404  static bool Decode(base::StringPiece* slice, ExistsEntryKey* result);
405  CONTENT_EXPORT static std::string Encode(int64 database_id,
406                                           int64 object_store_id,
407                                           const std::string& encoded_key);
408  static std::string Encode(int64 database_id,
409                            int64 object_store_id,
410                            const IndexedDBKey& user_key);
411  scoped_ptr<IndexedDBKey> user_key() const;
412
413 private:
414  static const int64 kSpecialIndexNumber;
415
416  std::string encoded_user_key_;
417  DISALLOW_COPY_AND_ASSIGN(ExistsEntryKey);
418};
419
420class BlobEntryKey {
421 public:
422  BlobEntryKey() : database_id_(0), object_store_id_(0) {}
423  static bool Decode(base::StringPiece* slice, BlobEntryKey* result);
424  static bool FromObjectStoreDataKey(base::StringPiece* slice,
425                                     BlobEntryKey* result);
426  static std::string ReencodeToObjectStoreDataKey(base::StringPiece* slice);
427  static std::string EncodeMinKeyForObjectStore(int64 database_id,
428                                                int64 object_store_id);
429  static std::string EncodeStopKeyForObjectStore(int64 database_id,
430                                                 int64 object_store_id);
431  static std::string Encode(int64 database_id,
432                            int64 object_store_id,
433                            const IndexedDBKey& user_key);
434  std::string Encode() const;
435  int64 database_id() const { return database_id_; }
436  int64 object_store_id() const { return object_store_id_; }
437
438 private:
439  static const int64 kSpecialIndexNumber;
440
441  static std::string Encode(int64 database_id,
442                            int64 object_store_id,
443                            const std::string& encoded_user_key);
444  int64 database_id_;
445  int64 object_store_id_;
446  // This is the user's ObjectStoreDataKey, not the BlobEntryKey itself.
447  std::string encoded_user_key_;
448};
449
450class IndexDataKey {
451 public:
452  IndexDataKey();
453  ~IndexDataKey();
454  static bool Decode(base::StringPiece* slice, IndexDataKey* result);
455  CONTENT_EXPORT static std::string Encode(
456      int64 database_id,
457      int64 object_store_id,
458      int64 index_id,
459      const std::string& encoded_user_key,
460      const std::string& encoded_primary_key,
461      int64 sequence_number);
462  static std::string Encode(int64 database_id,
463                            int64 object_store_id,
464                            int64 index_id,
465                            const IndexedDBKey& user_key);
466  static std::string Encode(int64 database_id,
467                            int64 object_store_id,
468                            int64 index_id,
469                            const IndexedDBKey& user_key,
470                            const IndexedDBKey& user_primary_key);
471  static std::string EncodeMinKey(int64 database_id,
472                                  int64 object_store_id,
473                                  int64 index_id);
474  CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id,
475                                                 int64 object_store_id,
476                                                 int64 index_id);
477  int64 DatabaseId() const;
478  int64 ObjectStoreId() const;
479  int64 IndexId() const;
480  scoped_ptr<IndexedDBKey> user_key() const;
481  scoped_ptr<IndexedDBKey> primary_key() const;
482
483 private:
484  int64 database_id_;
485  int64 object_store_id_;
486  int64 index_id_;
487  std::string encoded_user_key_;
488  std::string encoded_primary_key_;
489  int64 sequence_number_;
490
491  DISALLOW_COPY_AND_ASSIGN(IndexDataKey);
492};
493
494}  // namespace content
495
496#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_CODING_H_
497