• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Google Inc. 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
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "config.h"
33 #include "platform/text/LineEnding.h"
34 
35 #include "wtf/text/CString.h"
36 #include "wtf/text/WTFString.h"
37 
38 namespace {
39 
40 class OutputBuffer {
41 public:
42     virtual char* allocate(size_t) = 0;
43     virtual void copy(const CString&) = 0;
~OutputBuffer()44     virtual ~OutputBuffer() { }
45 };
46 
47 class CStringBuffer FINAL : public OutputBuffer {
48 public:
CStringBuffer(CString & buffer)49     CStringBuffer(CString& buffer)
50         : m_buffer(buffer)
51     {
52     }
~CStringBuffer()53     virtual ~CStringBuffer() { }
54 
allocate(size_t size)55     virtual char* allocate(size_t size) OVERRIDE
56     {
57         char* ptr;
58         m_buffer = CString::newUninitialized(size, ptr);
59         return ptr;
60     }
61 
copy(const CString & source)62     virtual void copy(const CString& source) OVERRIDE
63     {
64         m_buffer = source;
65     }
66 
buffer() const67     const CString& buffer() const { return m_buffer; }
68 
69 private:
70     CString m_buffer;
71 };
72 
73 class VectorCharAppendBuffer FINAL : public OutputBuffer {
74 public:
VectorCharAppendBuffer(Vector<char> & buffer)75     VectorCharAppendBuffer(Vector<char>& buffer)
76         : m_buffer(buffer)
77     {
78     }
~VectorCharAppendBuffer()79     virtual ~VectorCharAppendBuffer() { }
80 
allocate(size_t size)81     virtual char* allocate(size_t size) OVERRIDE
82     {
83         size_t oldSize = m_buffer.size();
84         m_buffer.grow(oldSize + size);
85         return m_buffer.data() + oldSize;
86     }
87 
copy(const CString & source)88     virtual void copy(const CString& source) OVERRIDE
89     {
90         m_buffer.append(source.data(), source.length());
91     }
92 
93 private:
94     Vector<char>& m_buffer;
95 };
96 
internalNormalizeLineEndingsToCRLF(const CString & from,OutputBuffer & buffer)97 void internalNormalizeLineEndingsToCRLF(const CString& from, OutputBuffer& buffer)
98 {
99     // Compute the new length.
100     size_t newLen = 0;
101     const char* p = from.data();
102     while (p < from.data() + from.length()) {
103         char c = *p++;
104         if (c == '\r') {
105             // Safe to look ahead because of trailing '\0'.
106             if (*p != '\n') {
107                 // Turn CR into CRLF.
108                 newLen += 2;
109             }
110         } else if (c == '\n') {
111             // Turn LF into CRLF.
112             newLen += 2;
113         } else {
114             // Leave other characters alone.
115             newLen += 1;
116         }
117     }
118     if (newLen < from.length())
119         return;
120 
121     if (newLen == from.length()) {
122         buffer.copy(from);
123         return;
124     }
125 
126     p = from.data();
127     char* q = buffer.allocate(newLen);
128 
129     // Make a copy of the string.
130     while (p < from.data() + from.length()) {
131         char c = *p++;
132         if (c == '\r') {
133             // Safe to look ahead because of trailing '\0'.
134             if (*p != '\n') {
135                 // Turn CR into CRLF.
136                 *q++ = '\r';
137                 *q++ = '\n';
138             }
139         } else if (c == '\n') {
140             // Turn LF into CRLF.
141             *q++ = '\r';
142             *q++ = '\n';
143         } else {
144             // Leave other characters alone.
145             *q++ = c;
146         }
147     }
148 }
149 
150 };
151 
152 namespace WebCore {
153 
154 void normalizeToCROrLF(const CString& from, Vector<char>& result, bool toCR);
155 
156 // Normalize all line-endings to CR or LF.
normalizeToCROrLF(const CString & from,Vector<char> & result,bool toCR)157 void normalizeToCROrLF(const CString& from, Vector<char>& result, bool toCR)
158 {
159     // Compute the new length.
160     size_t newLen = 0;
161     bool needFix = false;
162     const char* p = from.data();
163     char fromEndingChar = toCR ? '\n' : '\r';
164     char toEndingChar = toCR ? '\r' : '\n';
165     while (p < from.data() + from.length()) {
166         char c = *p++;
167         if (c == '\r' && *p == '\n') {
168             // Turn CRLF into CR or LF.
169             p++;
170             needFix = true;
171         } else if (c == fromEndingChar) {
172             // Turn CR/LF into LF/CR.
173             needFix = true;
174         }
175         newLen += 1;
176     }
177 
178     // Grow the result buffer.
179     p = from.data();
180     size_t oldResultSize = result.size();
181     result.grow(oldResultSize + newLen);
182     char* q = result.data() + oldResultSize;
183 
184     // If no need to fix the string, just copy the string over.
185     if (!needFix) {
186         memcpy(q, p, from.length());
187         return;
188     }
189 
190     // Make a copy of the string.
191     while (p < from.data() + from.length()) {
192         char c = *p++;
193         if (c == '\r' && *p == '\n') {
194             // Turn CRLF or CR into CR or LF.
195             p++;
196             *q++ = toEndingChar;
197         } else if (c == fromEndingChar) {
198             // Turn CR/LF into LF/CR.
199             *q++ = toEndingChar;
200         } else {
201             // Leave other characters alone.
202             *q++ = c;
203         }
204     }
205 }
206 
normalizeLineEndingsToCRLF(const CString & from)207 CString normalizeLineEndingsToCRLF(const CString& from)
208 {
209     if (!from.length())
210         return from;
211     CString result;
212     CStringBuffer buffer(result);
213     internalNormalizeLineEndingsToCRLF(from, buffer);
214     return buffer.buffer();
215 }
216 
normalizeLineEndingsToCR(const CString & from,Vector<char> & result)217 void normalizeLineEndingsToCR(const CString& from, Vector<char>& result)
218 {
219     normalizeToCROrLF(from, result, true);
220 }
221 
normalizeLineEndingsToLF(const CString & from,Vector<char> & result)222 void normalizeLineEndingsToLF(const CString& from, Vector<char>& result)
223 {
224     normalizeToCROrLF(from, result, false);
225 }
226 
normalizeLineEndingsToNative(const CString & from,Vector<char> & result)227 void normalizeLineEndingsToNative(const CString& from, Vector<char>& result)
228 {
229 #if OS(WIN)
230     VectorCharAppendBuffer buffer(result);
231     internalNormalizeLineEndingsToCRLF(from, buffer);
232 #else
233     normalizeLineEndingsToLF(from, result);
234 #endif
235 }
236 
237 } // namespace WebCore
238