1/* 2 * Copyright (C) 2003, 2006, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 27#include "config.h" 28#include "CString.h" 29 30#include <string.h> 31#include <wtf/StringHasher.h> 32 33namespace WTF { 34 35PassRefPtr<CStringBuffer> CStringBuffer::createUninitialized(size_t length) 36{ 37 RELEASE_ASSERT(length < (std::numeric_limits<unsigned>::max() - sizeof(CStringBuffer))); 38 39 // The +1 is for the terminating null character. 40 size_t size = sizeof(CStringBuffer) + length + 1; 41 CStringBuffer* stringBuffer = static_cast<CStringBuffer*>(fastMalloc(size)); 42 return adoptRef(new (NotNull, stringBuffer) CStringBuffer(length)); 43} 44 45CString::CString(const char* str) 46{ 47 if (!str) 48 return; 49 50 init(str, strlen(str)); 51} 52 53CString::CString(const char* str, size_t length) 54{ 55 if (!str) { 56 ASSERT(!length); 57 return; 58 } 59 60 init(str, length); 61} 62 63void CString::init(const char* str, size_t length) 64{ 65 ASSERT(str); 66 67 m_buffer = CStringBuffer::createUninitialized(length); 68 memcpy(m_buffer->mutableData(), str, length); 69 m_buffer->mutableData()[length] = '\0'; 70} 71 72char* CString::mutableData() 73{ 74 copyBufferIfNeeded(); 75 if (!m_buffer) 76 return 0; 77 return m_buffer->mutableData(); 78} 79 80CString CString::newUninitialized(size_t length, char*& characterBuffer) 81{ 82 CString result; 83 result.m_buffer = CStringBuffer::createUninitialized(length); 84 char* bytes = result.m_buffer->mutableData(); 85 bytes[length] = '\0'; 86 characterBuffer = bytes; 87 return result; 88} 89 90void CString::copyBufferIfNeeded() 91{ 92 if (!m_buffer || m_buffer->hasOneRef()) 93 return; 94 95 RefPtr<CStringBuffer> buffer = m_buffer.release(); 96 size_t length = buffer->length(); 97 m_buffer = CStringBuffer::createUninitialized(length); 98 memcpy(m_buffer->mutableData(), buffer->data(), length + 1); 99} 100 101bool CString::isSafeToSendToAnotherThread() const 102{ 103 return !m_buffer || m_buffer->hasOneRef(); 104} 105 106bool operator==(const CString& a, const CString& b) 107{ 108 if (a.isNull() != b.isNull()) 109 return false; 110 if (a.length() != b.length()) 111 return false; 112 return !memcmp(a.data(), b.data(), a.length()); 113} 114 115bool operator==(const CString& a, const char* b) 116{ 117 if (a.isNull() != !b) 118 return false; 119 if (!b) 120 return true; 121 return !strcmp(a.data(), b); 122} 123 124unsigned CString::hash() const 125{ 126 if (isNull()) 127 return 0; 128 StringHasher hasher; 129 for (const char* ptr = data(); *ptr; ++ptr) 130 hasher.addCharacter(*ptr); 131 return hasher.hash(); 132} 133 134bool operator<(const CString& a, const CString& b) 135{ 136 if (a.isNull()) 137 return !b.isNull(); 138 if (b.isNull()) 139 return false; 140 return strcmp(a.data(), b.data()) < 0; 141} 142 143bool CStringHash::equal(const CString& a, const CString& b) 144{ 145 if (a.isHashTableDeletedValue()) 146 return b.isHashTableDeletedValue(); 147 if (b.isHashTableDeletedValue()) 148 return false; 149 return a == b; 150} 151 152} // namespace WTF 153