Changeset 121145 in webkit


Ignore:
Timestamp:
Jun 25, 2012 2:43:07 AM (12 years ago)
Author:
tkent@chromium.org
Message:

Change the serialization format of form control state to make the code simple
https://bugs.webkit.org/show_bug.cgi?id=89847

Reviewed by Hajime Morita.

Source/WebCore:

We used multiple strings to represent state of single form control. It
made the code complex. We change the serialization format so that one
CSV string represents state.

Examples in the old format:

"0"
"1", "value"
"3", "value1", "value2,value2", "value3"

Examples in the new format:

""
",value"
",value1,value2\,value2,value3"

Test: fast/forms/state-restore-various-values.html

  • html/FormController.cpp:

(WebCore::FormControlState::serialize):
Generate comma-separated string.
',' in a value is serialized as "\,".
We changed the signature because we don't need the out-argument.
(WebCore::FormControlState::deserialize):
Parses the input comma-separated string.
We changed the signature because we don't need multiple input strings.
(formStateSignature):
Bump up the version because of the representation change.
(WebCore::FormController::formElementsState):
The new serialized format occupies just one string for one control.

  • Expected size is now 3n+1.
  • Use FormControlState::serialize().

(WebCore::FormController::setStateForNewFormElements):
The new serialized format occupies just one string for one control.
So we can check the vector size before the iteration.

  • html/FormController.h:

(FormControlState): Change the function signatures.

  • html/shadow/CalendarPickerElement.cpp:

(WebCore::addJavaScriptString): Use StringBuilder::appendEscaped().

Source/WTF:

  • wtf/text/StringBuilder.h:

(WTF::StringBuilder::appendEscaped): Added. This function adds the
escaped form of the input string. e.g. if stiring="foo,bar" escape='\'
special=',', the appended string is foo\,bar.

LayoutTests:

  • fast/forms/state-restore-broken-state-expected.txt:

Apply the serialization format change.

  • fast/forms/state-restore-various-values-expected.txt: Added.
  • fast/forms/state-restore-various-values.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r121141 r121145  
     12012-06-25  Kent Tamura  <tkent@chromium.org>
     2
     3        Change the serialization format of form control state to make the code simple
     4        https://bugs.webkit.org/show_bug.cgi?id=89847
     5
     6        Reviewed by Hajime Morita.
     7
     8        * fast/forms/state-restore-broken-state-expected.txt:
     9        Apply the serialization format change.
     10        * fast/forms/state-restore-various-values-expected.txt: Added.
     11        * fast/forms/state-restore-various-values.html: Added.
     12
    1132012-06-24  Kristóf Kosztyó  <kkristof@inf.u-szeged.hu>
    214
  • trunk/LayoutTests/fast/forms/state-restore-broken-state-expected.txt

    r120895 r121145  
    1 CONSOLE MESSAGE: line 5: Generated state: [name1,text,1,modified]
     1CONSOLE MESSAGE: line 5: Generated state: [name1,text,,modified]
    22The value was modified in the first load of state-restore-broken-state-1.html, but it should not be restored because the state-restore-broken-state-2.html breaks the state.
    33
  • trunk/Source/WTF/ChangeLog

    r121140 r121145  
     12012-06-25  Kent Tamura  <tkent@chromium.org>
     2
     3        Change the serialization format of form control state to make the code simple
     4        https://bugs.webkit.org/show_bug.cgi?id=89847
     5
     6        Reviewed by Hajime Morita.
     7
     8        * wtf/text/StringBuilder.h:
     9        (WTF::StringBuilder::appendEscaped): Added. This function adds the
     10        escaped form of the input string. e.g. if stiring="foo,bar" escape='\'
     11        special=',', the appended string is foo\,bar.
     12
    1132012-06-24  Adam Barth  <abarth@webkit.org>
    214
  • trunk/Source/WTF/wtf/text/StringBuilder.h

    r111778 r121145  
    131131    }
    132132
     133    void appendEscaped(const String& string, UChar escape, UChar special)
     134    {
     135        if (string.isEmpty())
     136            return;
     137        unsigned requiredSize = length() + string.length();
     138        if (capacity() < requiredSize)
     139            reserveCapacity(requiredSize);
     140        for (unsigned i = 0; i < string.length(); ++i) {
     141            UChar ch = string[i];
     142            if (ch == escape || ch == special)
     143                append(escape);
     144            append(ch);
     145        }
     146    }
     147
    133148    String toString()
    134149    {
  • trunk/Source/WebCore/ChangeLog

    r121144 r121145  
     12012-06-25  Kent Tamura  <tkent@chromium.org>
     2
     3        Change the serialization format of form control state to make the code simple
     4        https://bugs.webkit.org/show_bug.cgi?id=89847
     5
     6        Reviewed by Hajime Morita.
     7
     8        We used multiple strings to represent state of single form control. It
     9        made the code complex. We change the serialization format so that one
     10        CSV string represents state.
     11
     12        Examples in the old format:
     13            "0"
     14            "1", "value"
     15            "3", "value1", "value2,value2", "value3"
     16
     17        Examples in the new format:
     18            ""
     19            ",value"
     20            ",value1,value2\,value2,value3"
     21
     22        Test: fast/forms/state-restore-various-values.html
     23
     24        * html/FormController.cpp:
     25        (WebCore::FormControlState::serialize):
     26        Generate comma-separated string.
     27        ',' in a value is serialized as "\,".
     28        We changed the signature because we don't need the out-argument.
     29        (WebCore::FormControlState::deserialize):
     30        Parses the input comma-separated string.
     31        We changed the signature because we don't need multiple input strings.
     32        (formStateSignature):
     33        Bump up the version because of the representation change.
     34        (WebCore::FormController::formElementsState):
     35        The new serialized format occupies just one string for one control.
     36        - Expected size is now 3n+1.
     37        - Use FormControlState::serialize().
     38        (WebCore::FormController::setStateForNewFormElements):
     39        The new serialized format occupies just one string for one control.
     40        So we can check the vector size before the iteration.
     41        * html/FormController.h:
     42        (FormControlState): Change the function signatures.
     43
     44        * html/shadow/CalendarPickerElement.cpp:
     45        (WebCore::addJavaScriptString): Use StringBuilder::appendEscaped().
     46
    1472012-06-22  Yury Semikhatsky  <yurys@chromium.org>
    248
  • trunk/Source/WebCore/html/FormController.cpp

    r121128 r121145  
    2323
    2424#include "HTMLFormControlElementWithState.h"
     25#include <wtf/text/StringBuilder.h>
    2526
    2627namespace WebCore {
     
    3132
    3233// Serilized form of FormControlState:
    33 //  (',' means strings around it are separated in stateVector.)
    3434//
    3535// SerializedControlState ::= SkipState | RestoreState
    36 // SkipState ::= '0'
    37 // RestoreState ::= UnsignedNumber, ControlValue+
    38 // UnsignedNumber ::= [0-9]+
    39 // ControlValue ::= arbitrary string
    40 //
    41 // RestoreState has a sequence of ControlValues. The length of the
    42 // sequence is represented by UnsignedNumber.
    43 
    44 void FormControlState::serializeTo(Vector<String>& stateVector) const
     36// SkipState ::= ''
     37// RestoreState ::= (',' EscapedValue )+
     38// EscapedValue ::= ('\\' | '\,' | [^\,])+
     39
     40String FormControlState::serialize() const
    4541{
    4642    ASSERT(!isFailure());
    47     stateVector.append(String::number(m_values.size()));
     43    if (!m_values.size())
     44        return emptyString();
     45
     46    size_t enoughSize = 0;
    4847    for (size_t i = 0; i < m_values.size(); ++i)
    49         stateVector.append(m_values[i].isNull() ? emptyString() : m_values[i]);
    50 }
    51 
    52 FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
    53 {
    54     if (index >= stateVector.size())
     48        enoughSize += 1 + m_values[i].length() * 2;
     49    StringBuilder builder;
     50    builder.reserveCapacity(enoughSize);
     51    for (size_t i = 0; i < m_values.size(); ++i) {
     52        builder.append(',');
     53        builder.appendEscaped(m_values[i], '\\', ',');
     54    }
     55    return builder.toString();
     56}
     57
     58FormControlState FormControlState::deserialize(const String& escaped)
     59{
     60    if (!escaped.length())
     61        return FormControlState();
     62    if (escaped[0] != ',')
    5563        return FormControlState(TypeFailure);
    56     size_t valueSize = stateVector[index++].toUInt();
    57     if (!valueSize)
    58         return FormControlState();
    59     if (index + valueSize > stateVector.size())
    60         return FormControlState(TypeFailure);
     64
     65    size_t valueSize = 1;
     66    for (unsigned i = 1; i < escaped.length(); ++i) {
     67        if (escaped[i] == '\\') {
     68            if (++i >= escaped.length())
     69                return FormControlState(TypeFailure);
     70        } else if (escaped[i] == ',')
     71            valueSize++;
     72    }
     73
    6174    FormControlState state;
    6275    state.m_values.reserveCapacity(valueSize);
    63     for (size_t i = 0; i < valueSize; ++i)
    64         state.append(stateVector[index++]);
     76    StringBuilder builder;
     77    for (unsigned i = 1; i < escaped.length(); ++i) {
     78        if (escaped[i] == '\\') {
     79            if (++i >= escaped.length())
     80                return FormControlState(TypeFailure);
     81            builder.append(escaped[i]);
     82        } else if (escaped[i] == ',') {
     83            state.append(builder.toString());
     84            builder.clear();
     85        } else
     86            builder.append(escaped[i]);
     87    }
     88    state.append(builder.toString());
    6589    return state;
    6690}
     
    82106    // attribute value of a form control. The following string literal should
    83107    // contain some characters which are rarely used for name attribute values.
    84     DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 3 \n\r=&"));
     108    DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% WebKit serialized form state version 4 \n\r=&"));
    85109    return signature;
    86110}
     
    89113{
    90114    Vector<String> stateVector;
    91     stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4 + 1);
     115    stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3 + 1);
    92116    stateVector.append(formStateSignature());
    93117    typedef FormElementListHashSet::const_iterator Iterator;
     
    99123        stateVector.append(elementWithState->name().string());
    100124        stateVector.append(elementWithState->formControlType().string());
    101         elementWithState->saveFormControlState().serializeTo(stateVector);
     125        stateVector.append(elementWithState->saveFormControlState().serialize());
    102126    }
    103127    return stateVector;
     
    114138    m_formElementsWithState.clear();
    115139
    116     size_t i = 0;
    117     if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
     140    if (stateVector.size() < 1 || stateVector[0] != formStateSignature())
    118141        return;
    119 
    120     while (i + 2 < stateVector.size()) {
    121         AtomicString name = stateVector[i++];
    122         AtomicString type = stateVector[i++];
    123         FormControlState state = FormControlState::deserialize(stateVector, i);
     142    if ((stateVector.size() - 1) % 3)
     143        return;
     144
     145    for (size_t i = 1; i < stateVector.size(); i += 3) {
     146        AtomicString name = stateVector[i];
     147        AtomicString type = stateVector[i + 1];
     148        FormControlState state = FormControlState::deserialize(stateVector[i + 2]);
    124149        if (type.isEmpty() || type.impl()->find(isNotFormControlTypeCharacter) != notFound || state.isFailure())
    125150            break;
     
    135160        }
    136161    }
    137     if (i != stateVector.size())
    138         m_stateForNewFormElements.clear();
    139162}
    140163
  • trunk/Source/WebCore/html/FormController.h

    r121004 r121145  
    7979    FormControlState() : m_type(TypeSkip) { }
    8080    explicit FormControlState(const String& value) : m_type(TypeRestore) { m_values.append(value); }
    81     static FormControlState deserialize(const Vector<String>& stateVector, size_t& index);
     81    static FormControlState deserialize(const String&);
    8282    FormControlState(const FormControlState& another) : m_type(another.m_type), m_values(another.m_values) { }
    8383    FormControlState& operator=(const FormControlState&);
     
    8787    const String& operator[](size_t i) const { return m_values[i]; }
    8888    void append(const String&);
    89     void serializeTo(Vector<String>& stateVector) const;
     89    String serialize() const;
    9090
    9191private:
  • trunk/Source/WebCore/html/shadow/CalendarPickerElement.cpp

    r120313 r121145  
    152152    addLiteral("\"", writer);
    153153    StringBuilder builder;
    154     builder.reserveCapacity(str.length());
    155     for (unsigned i = 0; i < str.length(); ++i) {
    156         if (str[i] == '\\' || str[i] == '"')
    157             builder.append('\\');
    158         builder.append(str[i]);
    159     }
     154    builder.appendEscaped(str, '\\', '"');
    160155    addString(builder.toString(), writer);
    161156    addLiteral("\"", writer);
Note: See TracChangeset for help on using the changeset viewer.