1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller ( mueller (at) kde.org ) 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 6 * Copyright (C) 2006 Andrew Wellington (proton (at) 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 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 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 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 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