summaryrefslogtreecommitdiffstats
path: root/parser/html/nsHtml5String.h
blob: 54954fe1a2ff00894fcc418f9809c65314d4644d (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* 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 nsHtml5String_h
#define nsHtml5String_h

#include "nsString.h"
#include "nsIAtom.h"

class nsHtml5TreeBuilder;

/**
 * A pass-by-value type that can represent 
 *  * nullptr
 *  * empty string
 *  * Non-empty string as exactly-sized (capacity is length) `nsStringBuffer*`
 *  * Non-empty string as an nsIAtom*
 *
 * Holding or passing this type is as unsafe as holding or passing
 * `nsStringBuffer*`/`nsIAtom*`.
 */
class nsHtml5String final
{
private:

  static const uintptr_t kKindMask = uintptr_t(3);

  static const uintptr_t kPtrMask = ~kKindMask;

  enum Kind : uintptr_t {
    eNull = 0,
    eEmpty = 1,
    eStringBuffer = 2,
    eAtom = 3,
  };

  inline Kind GetKind() const { return (Kind)(mBits & kKindMask); }

  inline nsStringBuffer* AsStringBuffer() const
  {
    MOZ_ASSERT(GetKind() == eStringBuffer);
    return reinterpret_cast<nsStringBuffer*>(mBits & kPtrMask);
  }

  inline nsIAtom* AsAtom() const
  {
    MOZ_ASSERT(GetKind() == eAtom);
    return reinterpret_cast<nsIAtom*>(mBits & kPtrMask);
  }

  inline const char16_t* AsPtr() const
  {
    switch (GetKind()) {
      case eStringBuffer:
        return reinterpret_cast<char16_t*>(AsStringBuffer()->Data());
      case eAtom:
        return AsAtom()->GetUTF16String();
      default:
        return nullptr;
    }
  }

public:
  /**
   * Default constructor.
   */
  inline nsHtml5String()
    : nsHtml5String(nullptr)
  {
  }

  /**
   * Constructor from nullptr.
   */
  inline MOZ_IMPLICIT nsHtml5String(decltype(nullptr))
    : mBits(eNull)
  {
  }

  inline uint32_t Length() const
  {
    switch (GetKind()) {
      case eStringBuffer:
        return (AsStringBuffer()->StorageSize()/sizeof(char16_t) - 1);
      case eAtom:
        return AsAtom()->GetLength();
      default:
        return 0;
    }
  }

  /**
   * False iff the string is logically null
   */
  inline MOZ_IMPLICIT operator bool() const { return mBits; }

  /**
   * Get the underlying nsIAtom* or nullptr if this nsHtml5String
   * does not hold an atom.
   */
  inline nsIAtom* MaybeAsAtom()
  {
    if (GetKind() == eAtom) {
      return AsAtom();
    }
    return nullptr;
  }

  void ToString(nsAString& aString);

  void CopyToBuffer(char16_t* aBuffer) const;

  bool LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const;

  bool EqualsASCII(const char* aLiteral) const;

  bool LowerCaseStartsWithASCII(const char* aLowerCaseLiteral) const;

  bool Equals(nsHtml5String aOther) const;

  nsHtml5String Clone();

  void Release();

  static nsHtml5String FromBuffer(char16_t* aBuffer,
                                  int32_t aLength,
                                  nsHtml5TreeBuilder* aTreeBuilder);

  static nsHtml5String FromLiteral(const char* aLiteral);

  static nsHtml5String FromString(const nsAString& aString);

  static nsHtml5String FromAtom(already_AddRefed<nsIAtom> aAtom);

  static nsHtml5String EmptyString();

private:

  /**
   * Constructor from raw bits.
   */
  explicit nsHtml5String(uintptr_t aBits) : mBits(aBits) {};

  /**
   * Zero if null, one if empty, otherwise tagged pointer
   * to either nsIAtom or nsStringBuffer. The two least-significant
   * bits are tag bits.
   */
  uintptr_t mBits;
};

#endif // nsHtml5String_h