1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller ( mueller@kde.org )
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25 #include "config.h"
26 #include "Length.h"
27
28 #include "PlatformString.h"
29 #include <wtf/ASCIICType.h>
30 #include <wtf/Assertions.h>
31 #include <wtf/OwnArrayPtr.h>
32 #include <wtf/text/StringBuffer.h>
33
34 using namespace WTF;
35
36 namespace WebCore {
37
parseLength(const UChar * data,unsigned length)38 static Length parseLength(const UChar* data, unsigned length)
39 {
40 if (length == 0)
41 return Length(1, Relative);
42
43 unsigned i = 0;
44 while (i < length && isSpaceOrNewline(data[i]))
45 ++i;
46 if (i < length && (data[i] == '+' || data[i] == '-'))
47 ++i;
48 while (i < length && isASCIIDigit(data[i]))
49 ++i;
50 unsigned intLength = i;
51 while (i < length && (isASCIIDigit(data[i]) || data[i] == '.'))
52 ++i;
53 unsigned doubleLength = i;
54
55 // IE quirk: Skip whitespace between the number and the % character (20 % => 20%).
56 while (i < length && isSpaceOrNewline(data[i]))
57 ++i;
58
59 bool ok;
60 UChar next = (i < length) ? data[i] : ' ';
61 if (next == '%') {
62 // IE quirk: accept decimal fractions for percentages.
63 double r = charactersToDouble(data, doubleLength, &ok);
64 if (ok)
65 return Length(r, Percent);
66 return Length(1, Relative);
67 }
68 int r = charactersToIntStrict(data, intLength, &ok);
69 if (next == '*') {
70 if (ok)
71 return Length(r, Relative);
72 return Length(1, Relative);
73 }
74 if (ok)
75 return Length(r, Fixed);
76 return Length(0, Relative);
77 }
78
countCharacter(const UChar * data,unsigned length,UChar character)79 static int countCharacter(const UChar* data, unsigned length, UChar character)
80 {
81 int count = 0;
82 for (int i = 0; i < static_cast<int>(length); ++i)
83 count += data[i] == character;
84 return count;
85 }
86
newCoordsArray(const String & string,int & len)87 PassOwnArrayPtr<Length> newCoordsArray(const String& string, int& len)
88 {
89 unsigned length = string.length();
90 const UChar* data = string.characters();
91 StringBuffer spacified(length);
92 for (unsigned i = 0; i < length; i++) {
93 UChar cc = data[i];
94 if (cc > '9' || (cc < '0' && cc != '-' && cc != '*' && cc != '.'))
95 spacified[i] = ' ';
96 else
97 spacified[i] = cc;
98 }
99 RefPtr<StringImpl> str = StringImpl::adopt(spacified);
100
101 str = str->simplifyWhiteSpace();
102
103 len = countCharacter(str->characters(), str->length(), ' ') + 1;
104 OwnArrayPtr<Length> r = adoptArrayPtr(new Length[len]);
105
106 int i = 0;
107 unsigned pos = 0;
108 size_t pos2;
109
110 while ((pos2 = str->find(' ', pos)) != notFound) {
111 r[i++] = parseLength(str->characters() + pos, pos2 - pos);
112 pos = pos2+1;
113 }
114 r[i] = parseLength(str->characters() + pos, str->length() - pos);
115
116 ASSERT(i == len - 1);
117
118 return r.release();
119 }
120
newLengthArray(const String & string,int & len)121 PassOwnArrayPtr<Length> newLengthArray(const String& string, int& len)
122 {
123 RefPtr<StringImpl> str = string.impl()->simplifyWhiteSpace();
124 if (!str->length()) {
125 len = 1;
126 return nullptr;
127 }
128
129 len = countCharacter(str->characters(), str->length(), ',') + 1;
130 OwnArrayPtr<Length> r = adoptArrayPtr(new Length[len]);
131
132 int i = 0;
133 unsigned pos = 0;
134 size_t pos2;
135
136 while ((pos2 = str->find(',', pos)) != notFound) {
137 r[i++] = parseLength(str->characters() + pos, pos2 - pos);
138 pos = pos2+1;
139 }
140
141 ASSERT(i == len - 1);
142
143 // IE Quirk: If the last comma is the last char skip it and reduce len by one.
144 if (str->length()-pos > 0)
145 r[i] = parseLength(str->characters() + pos, str->length() - pos);
146 else
147 len--;
148
149 return r.release();
150 }
151
152 } // namespace WebCore
153