Home | History | Annotate | Download | only in platform
      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