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