2008-07-02 Geoffrey Garen <ggaren@apple.com>
[WebKit-https.git] / JavaScriptCore / kjs / JSString.h
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public License
18  *  along with this library; see the file COPYING.LIB.  If not, write to
19  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #ifndef JSString_h
25 #define JSString_h
26
27 #include "CommonIdentifiers.h"
28 #include "JSCell.h"
29 #include "PropertySlot.h"
30 #include "identifier.h"
31 #include "ustring.h"
32
33 namespace KJS {
34
35   class JSString : public JSCell {
36   public:
37     JSString(const UString& value) : m_value(value) { Heap::heap(this)->reportExtraMemoryCost(value.cost()); }
38     enum HasOtherOwnerType { HasOtherOwner };
39     JSString(const UString& value, HasOtherOwnerType) : m_value(value) { }
40
41     const UString& value() const { return m_value; }
42
43     bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
44     bool getStringPropertySlot(unsigned propertyName, PropertySlot&);
45
46     bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
47     JSValue* getIndex(ExecState* exec, unsigned i)
48     {
49         ASSERT(canGetIndex(i));
50         return new (exec) JSString(m_value.substr(i, 1));
51     }
52
53   private:
54     virtual JSType type() const { return StringType; }
55
56     virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
57     virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
58     virtual bool toBoolean(ExecState*) const;
59     virtual double toNumber(ExecState*) const;
60     virtual JSObject* toObject(ExecState*) const;
61     virtual UString toString(ExecState*) const;
62
63     virtual JSObject* toThisObject(ExecState*) const;
64     virtual UString toThisString(ExecState*) const;
65     virtual JSString* toThisJSString(ExecState*);
66
67     // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
68     virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
69     virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
70
71     static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
72     static JSValue* indexGetter(ExecState*, const Identifier&, const PropertySlot&);
73     static JSValue* indexNumericPropertyGetter(ExecState*, unsigned, const PropertySlot&);
74
75     UString m_value;
76   };
77
78   JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
79   JSString* jsString(ExecState*, const char* = ""); // returns empty string if passed 0
80
81   // Should be used for strings that are owned by an object that will
82   // likely outlive the JSValue this makes, such as the parse tree or a
83   // DOM object that contains a UString
84   JSString* jsOwnedString(ExecState*, const UString&); 
85
86 ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
87 {
88     if (propertyName == exec->propertyNames().length) {
89         slot.setCustom(this, lengthGetter);
90         return true;
91     }
92
93     bool isStrictUInt32;
94     unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
95     if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {
96         slot.setCustomIndex(this, i, indexGetter);
97         return true;
98     }
99
100     return false;
101 }
102     
103 ALWAYS_INLINE bool JSString::getStringPropertySlot(unsigned propertyName, PropertySlot& slot)
104 {
105     if (propertyName < static_cast<unsigned>(m_value.size())) {
106         slot.setCustomNumeric(this, indexNumericPropertyGetter);
107         return true;
108     }
109
110     return false;
111 }
112
113 // --- JSValue inlines ----------------------------
114
115 inline JSString* JSValue::toThisJSString(ExecState* exec)
116 {
117     return JSImmediate::isImmediate(this) ? jsString(exec, JSImmediate::toString(this)) : asCell()->toThisJSString(exec);
118 }
119
120 } // namespace KJS
121
122 #endif // JSString_h