/* * Copyright (C) 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef PropertyName_h #define PropertyName_h #include "Identifier.h" #include "PrivateName.h" namespace JSC { template ALWAYS_INLINE uint32_t toUInt32FromCharacters(const CharType* characters, unsigned length) { // An empty string is not a number. if (!length) return UINT_MAX; // Get the first character, turning it into a digit. uint32_t value = characters[0] - '0'; if (value > 9) return UINT_MAX; // Check for leading zeros. If the first characher is 0, then the // length of the string must be one - e.g. "042" is not equal to "42". if (!value && length > 1) return UINT_MAX; while (--length) { // Multiply value by 10, checking for overflow out of 32 bits. if (value > 0xFFFFFFFFU / 10) return UINT_MAX; value *= 10; // Get the next character, turning it into a digit. uint32_t newValue = *(++characters) - '0'; if (newValue > 9) return UINT_MAX; // Add in the old value, checking for overflow out of 32 bits. newValue += value; if (newValue < value) return UINT_MAX; value = newValue; } return value; } ALWAYS_INLINE uint32_t toUInt32FromStringImpl(StringImpl* impl) { if (impl->is8Bit()) return toUInt32FromCharacters(impl->characters8(), impl->length()); return toUInt32FromCharacters(impl->characters16(), impl->length()); } class PropertyName { public: PropertyName(const Identifier& propertyName) : m_impl(propertyName.impl()) { ASSERT(!m_impl || m_impl->isIdentifier()); } PropertyName(const PrivateName& propertyName) : m_impl(propertyName.uid()) { ASSERT(m_impl && m_impl->isEmptyUnique()); } StringImpl* uid() const { ASSERT(!m_impl || (m_impl->isIdentifier() == !m_impl->isEmptyUnique())); return m_impl; } StringImpl* publicName() const { ASSERT(!m_impl || (m_impl->isIdentifier() == !m_impl->isEmptyUnique())); return m_impl->isIdentifier() ? m_impl : 0; } static const uint32_t NotAnIndex = UINT_MAX; uint32_t asIndex() { ASSERT(!m_impl || (m_impl->isIdentifier() == !m_impl->isEmptyUnique())); return m_impl ? toUInt32FromStringImpl(m_impl) : NotAnIndex; } private: StringImpl* m_impl; }; inline bool operator==(PropertyName a, const Identifier& b) { return a.uid() == b.impl(); } inline bool operator==(const Identifier& a, PropertyName b) { return a.impl() == b.uid(); } inline bool operator==(PropertyName a, PropertyName b) { return a.uid() == b.uid(); } inline bool operator!=(PropertyName a, const Identifier& b) { return a.uid() != b.impl(); } inline bool operator!=(const Identifier& a, PropertyName b) { return a.impl() != b.uid(); } inline bool operator!=(PropertyName a, PropertyName b) { return a.uid() != b.uid(); } } #endif