]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSString.h
JavaScriptCore-521.tar.gz
[apple/javascriptcore.git] / runtime / JSString.h
1 /*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #ifndef JSString_h
24 #define JSString_h
25
26 #include "CommonIdentifiers.h"
27 #include "CallFrame.h"
28 #include "Identifier.h"
29 #include "JSNumberCell.h"
30 #include "PropertySlot.h"
31
32 namespace JSC {
33
34 class JSString;
35
36 JSString* jsEmptyString(JSGlobalData*);
37 JSString* jsEmptyString(ExecState*);
38 JSString* jsString(JSGlobalData*, const UString&); // returns empty string if passed null string
39 JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
40
41 JSString* jsSingleCharacterString(JSGlobalData*, UChar);
42 JSString* jsSingleCharacterString(ExecState*, UChar);
43 JSString* jsSingleCharacterSubstring(JSGlobalData*, const UString&, unsigned offset);
44 JSString* jsSingleCharacterSubstring(ExecState*, const UString&, unsigned offset);
45 JSString* jsSubstring(JSGlobalData*, const UString&, unsigned offset, unsigned length);
46 JSString* jsSubstring(ExecState*, const UString&, unsigned offset, unsigned length);
47
48 // Non-trivial strings are two or more characters long.
49 // These functions are faster than just calling jsString.
50 JSString* jsNontrivialString(JSGlobalData*, const UString&);
51 JSString* jsNontrivialString(ExecState*, const UString&);
52 JSString* jsNontrivialString(JSGlobalData*, const char*);
53 JSString* jsNontrivialString(ExecState*, const char*);
54
55 // Should be used for strings that are owned by an object that will
56 // likely outlive the JSValue this makes, such as the parse tree or a
57 // DOM object that contains a UString
58 JSString* jsOwnedString(JSGlobalData*, const UString&);
59 JSString* jsOwnedString(ExecState*, const UString&);
60
61 class JSString : public JSCell {
62 friend class JIT;
63 friend class Interpreter;
64
65 public:
66 JSString(JSGlobalData* globalData, const UString& value)
67 : JSCell(globalData->stringStructure.get())
68 , m_value(value)
69 {
70 Heap::heap(this)->reportExtraMemoryCost(value.cost());
71 }
72
73 enum HasOtherOwnerType { HasOtherOwner };
74 JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
75 : JSCell(globalData->stringStructure.get())
76 , m_value(value)
77 {
78 }
79 JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
80 : JSCell(globalData->stringStructure.get())
81 , m_value(value)
82 {
83 }
84
85 const UString& value() const { return m_value; }
86
87 bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
88 bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
89
90 bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
91 JSString* getIndex(JSGlobalData*, unsigned);
92
93 static PassRefPtr<Structure> createStructure(JSValuePtr proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); }
94
95 private:
96 enum VPtrStealingHackType { VPtrStealingHack };
97 JSString(VPtrStealingHackType)
98 : JSCell(0)
99 {
100 }
101
102 virtual JSValuePtr toPrimitive(ExecState*, PreferredPrimitiveType) const;
103 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValuePtr& value);
104 virtual bool toBoolean(ExecState*) const;
105 virtual double toNumber(ExecState*) const;
106 virtual JSObject* toObject(ExecState*) const;
107 virtual UString toString(ExecState*) const;
108
109 virtual JSObject* toThisObject(ExecState*) const;
110 virtual UString toThisString(ExecState*) const;
111 virtual JSString* toThisJSString(ExecState*);
112
113 // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
114 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
115 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
116
117 UString m_value;
118 };
119
120 JSString* asString(JSValuePtr);
121
122 inline JSString* asString(JSValuePtr value)
123 {
124 ASSERT(asCell(value)->isString());
125 return static_cast<JSString*>(asCell(value));
126 }
127
128 inline JSString* jsEmptyString(JSGlobalData* globalData)
129 {
130 return globalData->smallStrings.emptyString(globalData);
131 }
132
133 inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
134 {
135 if (c <= 0xFF)
136 return globalData->smallStrings.singleCharacterString(globalData, c);
137 return new (globalData) JSString(globalData, UString(&c, 1));
138 }
139
140 inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset)
141 {
142 ASSERT(offset < static_cast<unsigned>(s.size()));
143 UChar c = s.data()[offset];
144 if (c <= 0xFF)
145 return globalData->smallStrings.singleCharacterString(globalData, c);
146 return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, 1));
147 }
148
149 inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
150 {
151 ASSERT(s);
152 ASSERT(s[0]);
153 ASSERT(s[1]);
154 return new (globalData) JSString(globalData, s);
155 }
156
157 inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
158 {
159 ASSERT(s.size() > 1);
160 return new (globalData) JSString(globalData, s);
161 }
162
163 inline JSString* JSString::getIndex(JSGlobalData* globalData, unsigned i)
164 {
165 ASSERT(canGetIndex(i));
166 return jsSingleCharacterSubstring(globalData, m_value, i);
167 }
168
169 inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
170 inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
171 inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
172 inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { return jsSingleCharacterSubstring(&exec->globalData(), s, offset); }
173 inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
174 inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); }
175 inline JSString* jsNontrivialString(ExecState* exec, const char* s) { return jsNontrivialString(&exec->globalData(), s); }
176 inline JSString* jsOwnedString(ExecState* exec, const UString& s) { return jsOwnedString(&exec->globalData(), s); }
177
178 ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
179 {
180 if (propertyName == exec->propertyNames().length) {
181 slot.setValue(jsNumber(exec, m_value.size()));
182 return true;
183 }
184
185 bool isStrictUInt32;
186 unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
187 if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {
188 slot.setValue(jsSingleCharacterSubstring(exec, m_value, i));
189 return true;
190 }
191
192 return false;
193 }
194
195 ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
196 {
197 if (propertyName < static_cast<unsigned>(m_value.size())) {
198 slot.setValue(jsSingleCharacterSubstring(exec, m_value, propertyName));
199 return true;
200 }
201
202 return false;
203 }
204
205 // --- JSValue inlines ----------------------------
206
207 inline JSString* JSValuePtr::toThisJSString(ExecState* exec)
208 {
209 return JSImmediate::isImmediate(asValue()) ? jsString(exec, JSImmediate::toString(asValue())) : asCell()->toThisJSString(exec);
210 }
211
212 } // namespace JSC
213
214 #endif // JSString_h