summaryrefslogtreecommitdiffstats
path: root/dom/localstorage/LSValue.h
blob: c1b362a50f917566af5de93a705448b47c773c62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_localstorage_LSValue_h
#define mozilla_dom_localstorage_LSValue_h

#include <cstdint>
#include "ErrorList.h"
#include "SnappyUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Span.h"
#include "nsString.h"
#include "nsStringFwd.h"
#include "nsTStringRepr.h"

class mozIStorageStatement;

namespace IPC {
template <typename>
struct ParamTraits;
}

namespace mozilla::dom {

/**
 * Represents a LocalStorage value. From content's perspective, values (if
 * present) are always DOMStrings. This is also true from a quota-tracking
 * perspective. However, for memory and disk efficiency it's preferable to store
 * the value in alternate compressed or utf-8 encoding representations. The
 * LSValue type exists to support these alternate representations, dynamically
 * decompressing/re-encoding to utf-16 while still tracking value size on a
 * utf-16 basis for quota purposes.
 */
class LSValue final {
  friend struct IPC::ParamTraits<LSValue>;

 public:
  enum class ConversionType : uint8_t {
    NONE = 0u,
    UTF16_UTF8 = 1u,
    NUM_TYPES = 2u
  };

  enum class CompressionType : uint8_t {
    UNCOMPRESSED = 0u,
    SNAPPY = 1u,
    NUM_TYPES = 2u
  };

  nsCString mBuffer;
  uint32_t mUTF16Length;
  ConversionType mConversionType;
  CompressionType mCompressionType;

  explicit LSValue()
      : mUTF16Length(0u),
        mConversionType(ConversionType::NONE),
        mCompressionType(CompressionType::UNCOMPRESSED) {
    SetIsVoid(true);
  }

  bool InitFromString(const nsAString& aBuffer);

  nsresult InitFromStatement(mozIStorageStatement* aStatement, uint32_t aIndex);

  bool IsVoid() const { return mBuffer.IsVoid(); }

  void SetIsVoid(bool aVal) { mBuffer.SetIsVoid(aVal); }

  /**
   * This represents the "physical" length that the parent process uses for
   * the size of value/item computation. This can also be used to see how much
   * memory the value is using at rest or what the cost is for sending the value
   * over IPC.
   */
  uint32_t Length() const { return mBuffer.Length(); }

  /*
   * This represents the "logical" length that content sees and that is also
   * used for quota management purposes.
   */
  uint32_t UTF16Length() const { return mUTF16Length; }

  ConversionType GetConversionType() const { return mConversionType; }

  CompressionType GetCompressionType() const { return mCompressionType; }

  bool Equals(const LSValue& aOther) const {
    return mBuffer == aOther.mBuffer &&
           mBuffer.IsVoid() == aOther.mBuffer.IsVoid() &&
           mUTF16Length == aOther.mUTF16Length &&
           mConversionType == aOther.mConversionType &&
           mCompressionType == aOther.mCompressionType;
  }

  bool operator==(const LSValue& aOther) const { return Equals(aOther); }

  bool operator!=(const LSValue& aOther) const { return !Equals(aOther); }

  constexpr const nsCString& AsCString() const { return mBuffer; }

  class Converter {
    nsString mBuffer;

   public:
    explicit Converter(const LSValue& aValue);
    Converter(Converter&& aOther) = default;
    ~Converter() = default;

    operator const nsString&() const { return mBuffer; }

   private:
    Converter() = delete;
    Converter(const Converter&) = delete;
    Converter& operator=(const Converter&) = delete;
    Converter& operator=(const Converter&&) = delete;
  };

  Converter AsString() const { return Converter{*this}; }
};

const LSValue& VoidLSValue();

/**
 * XXX: This function doesn't have to be public
 * once the support for shadow writes is removed.
 */
bool PutCStringBytesToString(const nsACString& aSrc, nsString& aDest);

}  // namespace mozilla::dom

#endif  // mozilla_dom_localstorage_LSValue_h