Serenity Operating System
at hosted 128 lines 3.8 kB view raw
1/* 2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/FlyString.h> 28#include <AK/HashTable.h> 29#include <AK/String.h> 30#include <AK/StringUtils.h> 31#include <AK/StringView.h> 32 33namespace AK { 34 35struct FlyStringImplTraits : public AK::Traits<StringImpl*> { 36 static unsigned hash(const StringImpl* s) { return s ? s->hash() : 0; } 37 static bool equals(const StringImpl* a, const StringImpl* b) 38 { 39 ASSERT(a); 40 ASSERT(b); 41 if (a == b) 42 return true; 43 if (a->length() != b->length()) 44 return false; 45 return !__builtin_memcmp(a->characters(), b->characters(), a->length()); 46 } 47}; 48 49static HashTable<StringImpl*, FlyStringImplTraits>& fly_impls() 50{ 51 static HashTable<StringImpl*, FlyStringImplTraits>* table; 52 if (!table) 53 table = new HashTable<StringImpl*, FlyStringImplTraits>; 54 return *table; 55} 56 57void FlyString::did_destroy_impl(Badge<StringImpl>, StringImpl& impl) 58{ 59 fly_impls().remove(&impl); 60} 61 62FlyString::FlyString(const String& string) 63{ 64 if (string.is_null()) 65 return; 66 auto it = fly_impls().find(const_cast<StringImpl*>(string.impl())); 67 if (it == fly_impls().end()) { 68 fly_impls().set(const_cast<StringImpl*>(string.impl())); 69 string.impl()->set_fly({}, true); 70 m_impl = string.impl(); 71 } else { 72 ASSERT((*it)->is_fly()); 73 m_impl = *it; 74 } 75} 76 77FlyString::FlyString(const StringView& string) 78 : FlyString(static_cast<String>(string)) 79{ 80} 81 82FlyString::FlyString(const char* string) 83 : FlyString(static_cast<String>(string)) 84{ 85} 86 87int FlyString::to_int(bool& ok) const 88{ 89 return StringUtils::convert_to_int(view(), ok); 90} 91 92bool FlyString::equals_ignoring_case(const StringView& other) const 93{ 94 return StringUtils::equals_ignoring_case(view(), other); 95} 96 97FlyString FlyString::to_lowercase() const 98{ 99 return String(*m_impl).to_lowercase(); 100} 101 102StringView FlyString::view() const 103{ 104 return { characters(), length() }; 105} 106 107bool FlyString::operator==(const String& string) const 108{ 109 if (m_impl == string.impl()) 110 return true; 111 return String(m_impl.ptr()) == string; 112} 113 114bool FlyString::operator==(const StringView& string) const 115{ 116 return String(string) == String(m_impl.ptr()); 117} 118 119bool FlyString::operator==(const char* string) const 120{ 121 if (is_null()) 122 return !string; 123 if (!string) 124 return false; 125 return !__builtin_strcmp(m_impl->characters(), string); 126} 127 128}