1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is Mozilla Communicator client code.
15 : *
16 : * The Initial Developer of the Original Code is
17 : * Netscape Communications Corporation.
18 : * Portions created by the Initial Developer are Copyright (C) 1998
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either of the GNU General Public License Version 2 or later (the "GPL"),
25 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 : * in which case the provisions of the GPL or the LGPL are applicable instead
27 : * of those above. If you wish to allow use of your version of this file only
28 : * under the terms of either the GPL or the LGPL, and not to allow others to
29 : * use your version of this file under the terms of the MPL, indicate your
30 : * decision by deleting the provisions above and replace them with the notice
31 : * and other provisions required by the GPL or the LGPL. If you do not delete
32 : * the provisions above, a recipient may use your version of this file under
33 : * the terms of any one of the MPL, the GPL or the LGPL.
34 : *
35 : * ***** END LICENSE BLOCK ***** */
36 :
37 : /*
38 : * A class which represents a fragment of text (eg inside a text
39 : * node); if only codepoints below 256 are used, the text is stored as
40 : * a char*; otherwise the text is stored as a PRUnichar*
41 : */
42 :
43 : #ifndef nsTextFragment_h___
44 : #define nsTextFragment_h___
45 :
46 : #include "mozilla/Attributes.h"
47 :
48 : #include "nsString.h"
49 : #include "nsReadableUtils.h"
50 : #include "nsTraceRefcnt.h"
51 :
52 : class nsString;
53 : class nsCString;
54 :
55 : // XXX should this normalize the code to keep a \u0000 at the end?
56 :
57 : // XXX nsTextFragmentPool?
58 :
59 : // XXX these need I18N spankage
60 : #define XP_IS_SPACE(_ch) \
61 : (((_ch) == ' ') || ((_ch) == '\t') || ((_ch) == '\n') || ((_ch) == '\r'))
62 :
63 : #define XP_IS_UPPERCASE(_ch) \
64 : (((_ch) >= 'A') && ((_ch) <= 'Z'))
65 :
66 : #define XP_IS_LOWERCASE(_ch) \
67 : (((_ch) >= 'a') && ((_ch) <= 'z'))
68 :
69 : #define XP_TO_LOWER(_ch) ((_ch) | 32)
70 :
71 : #define XP_TO_UPPER(_ch) ((_ch) & ~32)
72 :
73 : #define XP_IS_SPACE_W XP_IS_SPACE
74 :
75 : /**
76 : * A fragment of text. If mIs2b is 1 then the m2b pointer is valid
77 : * otherwise the m1b pointer is valid. If m1b is used then each byte
78 : * of data represents a single ucs2 character with the high byte being
79 : * zero.
80 : *
81 : * This class does not have a virtual destructor therefore it is not
82 : * meant to be subclassed.
83 : */
84 : class nsTextFragment MOZ_FINAL {
85 : public:
86 : static nsresult Init();
87 : static void Shutdown();
88 :
89 : /**
90 : * Default constructor. Initialize the fragment to be empty.
91 : */
92 74985 : nsTextFragment()
93 74985 : : m1b(nsnull), mAllBits(0)
94 : {
95 74985 : MOZ_COUNT_CTOR(nsTextFragment);
96 : NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!");
97 74985 : }
98 :
99 : ~nsTextFragment();
100 :
101 : /**
102 : * Change the contents of this fragment to be a copy of the
103 : * the argument fragment.
104 : */
105 : nsTextFragment& operator=(const nsTextFragment& aOther);
106 :
107 : /**
108 : * Return true if this fragment is represented by PRUnichar data
109 : */
110 2719 : bool Is2b() const
111 : {
112 2719 : return mState.mIs2b;
113 : }
114 :
115 : /**
116 : * Return true if this fragment contains Bidi text
117 : * For performance reasons this flag is only set if explicitely requested (by
118 : * setting the aUpdateBidi argument on SetTo or Append to true).
119 : */
120 73463 : bool IsBidi() const
121 : {
122 73463 : return mState.mIsBidi;
123 : }
124 :
125 : /**
126 : * Get a pointer to constant PRUnichar data.
127 : */
128 5 : const PRUnichar *Get2b() const
129 : {
130 5 : NS_ASSERTION(Is2b(), "not 2b text");
131 5 : return m2b;
132 : }
133 :
134 : /**
135 : * Get a pointer to constant char data.
136 : */
137 1350 : const char *Get1b() const
138 : {
139 1350 : NS_ASSERTION(!Is2b(), "not 1b text");
140 1350 : return (const char *)m1b;
141 : }
142 :
143 : /**
144 : * Get the length of the fragment. The length is the number of logical
145 : * characters, not the number of bytes to store the characters.
146 : */
147 150506 : PRUint32 GetLength() const
148 : {
149 150506 : return mState.mLength;
150 : }
151 :
152 74428 : bool CanGrowBy(size_t n) const
153 : {
154 74428 : return n < (1 << 29) && mState.mLength + n < (1 << 29);
155 : }
156 :
157 : /**
158 : * Change the contents of this fragment to be a copy of the given
159 : * buffer. If aUpdateBidi is true, contents of the fragment will be scanned,
160 : * and mState.mIsBidi will be turned on if it includes any Bidi characters.
161 : */
162 : void SetTo(const PRUnichar* aBuffer, PRInt32 aLength, bool aUpdateBidi);
163 :
164 : /**
165 : * Append aData to the end of this fragment. If aUpdateBidi is true, contents
166 : * of the fragment will be scanned, and mState.mIsBidi will be turned on if
167 : * it includes any Bidi characters.
168 : */
169 : void Append(const PRUnichar* aBuffer, PRUint32 aLength, bool aUpdateBidi);
170 :
171 : /**
172 : * Append the contents of this string fragment to aString
173 : */
174 8445 : void AppendTo(nsAString& aString) const {
175 8445 : if (mState.mIs2b) {
176 3 : aString.Append(m2b, mState.mLength);
177 : } else {
178 8442 : AppendASCIItoUTF16(Substring(m1b, mState.mLength), aString);
179 : }
180 8445 : }
181 :
182 : /**
183 : * Append a substring of the contents of this string fragment to aString.
184 : * @param aOffset where to start the substring in this text fragment
185 : * @param aLength the length of the substring
186 : */
187 0 : void AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const {
188 0 : if (mState.mIs2b) {
189 0 : aString.Append(m2b + aOffset, aLength);
190 : } else {
191 0 : AppendASCIItoUTF16(Substring(m1b + aOffset, aLength), aString);
192 : }
193 0 : }
194 :
195 : /**
196 : * Make a copy of the fragments contents starting at offset for
197 : * count characters. The offset and count will be adjusted to
198 : * lie within the fragments data. The fragments data is converted if
199 : * necessary.
200 : */
201 : void CopyTo(PRUnichar *aDest, PRInt32 aOffset, PRInt32 aCount);
202 :
203 : /**
204 : * Return the character in the text-fragment at the given
205 : * index. This always returns a PRUnichar.
206 : */
207 0 : PRUnichar CharAt(PRInt32 aIndex) const
208 : {
209 0 : NS_ASSERTION(PRUint32(aIndex) < mState.mLength, "bad index");
210 0 : return mState.mIs2b ? m2b[aIndex] : static_cast<unsigned char>(m1b[aIndex]);
211 : }
212 :
213 : struct FragmentBits {
214 : // PRUint32 to ensure that the values are unsigned, because we
215 : // want 0/1, not 0/-1!
216 : // Making these bool causes Windows to not actually pack them,
217 : // which causes crashes because we assume this structure is no more than
218 : // 32 bits!
219 : PRUint32 mInHeap : 1;
220 : PRUint32 mIs2b : 1;
221 : PRUint32 mIsBidi : 1;
222 : PRUint32 mLength : 29;
223 : };
224 :
225 : size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
226 :
227 : private:
228 : void ReleaseText();
229 :
230 : /**
231 : * Scan the contents of the fragment and turn on mState.mIsBidi if it
232 : * includes any Bidi characters.
233 : */
234 : void UpdateBidiFlag(const PRUnichar* aBuffer, PRUint32 aLength);
235 :
236 : union {
237 : PRUnichar *m2b;
238 : const char *m1b; // This is const since it can point to shared data
239 : };
240 :
241 : union {
242 : PRUint32 mAllBits;
243 : FragmentBits mState;
244 : };
245 : };
246 :
247 : #endif /* nsTextFragment_h___ */
248 :
|