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 COMPUTER, 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 COMPUTER, 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
32using namespace std;
33
34namespace WTF {
35
36PassRefPtr<CStringBuffer> CStringBuffer::createUninitialized(size_t length)
37{
38    RELEASE_ASSERT(length < (numeric_limits<unsigned>::max() - sizeof(CStringBuffer)));
39
40    // The +1 is for the terminating NUL character.
41    size_t size = sizeof(CStringBuffer) + length + 1;
42    CStringBuffer* stringBuffer = static_cast<CStringBuffer*>(fastMalloc(size));
43    return adoptRef(new (NotNull, stringBuffer) CStringBuffer(length));
44}
45
46CString::CString(const char* str)
47{
48    if (!str)
49        return;
50
51    init(str, strlen(str));
52}
53
54CString::CString(const char* str, size_t length)
55{
56    if (!str) {
57        ASSERT(!length);
58        return;
59    }
60
61    init(str, length);
62}
63
64void CString::init(const char* str, size_t length)
65{
66    ASSERT(str);
67
68    m_buffer = CStringBuffer::createUninitialized(length);
69    memcpy(m_buffer->mutableData(), str, length);
70    m_buffer->mutableData()[length] = '\0';
71}
72
73char* CString::mutableData()
74{
75    copyBufferIfNeeded();
76    if (!m_buffer)
77        return 0;
78    return m_buffer->mutableData();
79}
80
81CString CString::newUninitialized(size_t length, char*& characterBuffer)
82{
83    CString result;
84    result.m_buffer = CStringBuffer::createUninitialized(length);
85    char* bytes = result.m_buffer->mutableData();
86    bytes[length] = '\0';
87    characterBuffer = bytes;
88    return result;
89}
90
91void CString::copyBufferIfNeeded()
92{
93    if (!m_buffer || m_buffer->hasOneRef())
94        return;
95
96    RefPtr<CStringBuffer> buffer = m_buffer.release();
97    size_t length = buffer->length();
98    m_buffer = CStringBuffer::createUninitialized(length);
99    memcpy(m_buffer->mutableData(), buffer->data(), length + 1);
100}
101
102bool CString::isSafeToSendToAnotherThread() const
103{
104    return !m_buffer || m_buffer->hasOneRef();
105}
106
107bool operator==(const CString& a, const CString& b)
108{
109    if (a.isNull() != b.isNull())
110        return false;
111    if (a.length() != b.length())
112        return false;
113    return !memcmp(a.data(), b.data(), a.length());
114}
115
116bool operator==(const CString& a, const char* b)
117{
118    if (a.isNull() != !b)
119        return false;
120    if (!b)
121        return true;
122    return !strcmp(a.data(), b);
123}
124
125} // namespace WTF
126