Form state: Make a new class handling HashMap<FormElementKey, Deque<>>
https://bugs.webkit.org/show_bug.cgi?id=91480

Reviewed by Hajime Morita.

This is a preparation of Bug 91209, "Form state restore: Need to
identify a from by its content."

Make a new class which is responsible to handle "HashMap<FormElementKey,
Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits>."
Also, move the FormElementKey class declaration and related structs from
FormController.h to FormController.cpp because FormElementKey is used
only in FormController.cpp.

No new tests. Just a refactoring.

* html/FormController.cpp:
(WebCore::FormElementKey): Moeved from FormController.h.
(WebCore::FormElementKey::FormElementKey):
Moved from the bottom of FormController.cpp
(WebCore::FormElementKey::~FormElementKey): ditto.
(WebCore::FormElementKey::operator=): ditto.
(WebCore::FormElementKey::ref): ditto.
(WebCore::FormElementKey::deref): ditto.
(WebCore::operator==): Moved from FormController.h
(FormElementKeyHash): ditto.
(WebCore::FormElementKeyHash::equal): ditto.
(WebCore::FormElementKeyHash::hash):
Moved from the bottom of FormController.cpp
(WebCore::FormElementKeyHashTraits::constructDeletedValue):
Moved from FormController.h
(WebCore::FormElementKeyHashTraits::isDeletedValue): ditto.

(WebCore::SavedFormState): Added.
(WebCore::SavedFormState::isEmpty):
(WebCore::SavedFormState::SavedFormState): Added. The constructor.
(WebCore::SavedFormState::create): Added. A factory function.
(WebCore::SavedFormState::appendControlState):
Moved some code from FormController::setStateForNewFormElements.
(WebCore::SavedFormState::takeControlState):
Moved some code from FormController::takeStateForFormElement.

(WebCore::FormController::setStateForNewFormElements):
- Creates SavedFormState if needed.
- Uses SavedFormState::appendControlState.
(WebCore::FormController::takeStateForFormElement):
Uses SavedFormState.
* html/FormController.h:
(FormController):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@122917 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/html/FormController.cpp b/Source/WebCore/html/FormController.cpp
index c30845b..46241be 100644
--- a/Source/WebCore/html/FormController.cpp
+++ b/Source/WebCore/html/FormController.cpp
@@ -77,6 +77,154 @@
 
 // ----------------------------------------------------------------------------
 
+class FormElementKey {
+public:
+    FormElementKey(AtomicStringImpl* = 0, AtomicStringImpl* = 0, AtomicStringImpl* = 0);
+    ~FormElementKey();
+    FormElementKey(const FormElementKey&);
+    FormElementKey& operator=(const FormElementKey&);
+
+    AtomicStringImpl* name() const { return m_name; }
+    AtomicStringImpl* type() const { return m_type; }
+    AtomicStringImpl* formKey() const { return m_formKey; }
+
+    // Hash table deleted values, which are only constructed and never copied or destroyed.
+    FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
+    bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValue(); }
+
+private:
+    void ref() const;
+    void deref() const;
+
+    static AtomicStringImpl* hashTableDeletedValue() { return reinterpret_cast<AtomicStringImpl*>(-1); }
+
+    AtomicStringImpl* m_name;
+    AtomicStringImpl* m_type;
+    AtomicStringImpl* m_formKey;
+};
+
+FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type, AtomicStringImpl* formKey)
+    : m_name(name)
+    , m_type(type)
+    , m_formKey(formKey)
+{
+    ref();
+}
+
+FormElementKey::~FormElementKey()
+{
+    deref();
+}
+
+FormElementKey::FormElementKey(const FormElementKey& other)
+    : m_name(other.name())
+    , m_type(other.type())
+    , m_formKey(other.formKey())
+{
+    ref();
+}
+
+FormElementKey& FormElementKey::operator=(const FormElementKey& other)
+{
+    other.ref();
+    deref();
+    m_name = other.name();
+    m_type = other.type();
+    m_formKey = other.formKey();
+    return *this;
+}
+
+void FormElementKey::ref() const
+{
+    if (name())
+        name()->ref();
+    if (type())
+        type()->ref();
+    if (formKey())
+        formKey()->ref();
+}
+
+void FormElementKey::deref() const
+{
+    if (name())
+        name()->deref();
+    if (type())
+        type()->deref();
+    if (formKey())
+        formKey()->deref();
+}
+
+inline bool operator==(const FormElementKey& a, const FormElementKey& b)
+{
+    return a.name() == b.name() && a.type() == b.type() && a.formKey() == b.formKey();
+}
+
+struct FormElementKeyHash {
+    static unsigned hash(const FormElementKey&);
+    static bool equal(const FormElementKey& a, const FormElementKey& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+unsigned FormElementKeyHash::hash(const FormElementKey& key)
+{
+    return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
+}
+
+struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
+    static void constructDeletedValue(FormElementKey& slot) { new (NotNull, &slot) FormElementKey(WTF::HashTableDeletedValue); }
+    static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
+};
+
+// ----------------------------------------------------------------------------
+
+class SavedFormState {
+public:
+    static PassOwnPtr<SavedFormState> create();
+    bool isEmpty() const { return m_stateForNewFormElements.isEmpty(); }
+    void appendControlState(const AtomicString& name, const AtomicString& type, const AtomicString& formKey, const FormControlState&);
+    FormControlState takeControlState(const AtomicString& name, const AtomicString& type, const AtomicString& formKey);
+
+private:
+    SavedFormState() { }
+
+    typedef HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
+    FormElementStateMap m_stateForNewFormElements;
+};
+
+PassOwnPtr<SavedFormState> SavedFormState::create()
+{
+    return adoptPtr(new SavedFormState);
+}
+
+void SavedFormState::appendControlState(const AtomicString& name, const AtomicString& type, const AtomicString& formKey, const FormControlState& state)
+{
+    FormElementKey key(name.impl(), type.impl(), formKey.impl());
+    FormElementStateMap::iterator it = m_stateForNewFormElements.find(key);
+    if (it != m_stateForNewFormElements.end())
+        it->second.append(state);
+    else {
+        Deque<FormControlState> stateList;
+        stateList.append(state);
+        m_stateForNewFormElements.set(key, stateList);
+    }
+}
+
+FormControlState SavedFormState::takeControlState(const AtomicString& name, const AtomicString& type, const AtomicString& formKey)
+{
+    if (m_stateForNewFormElements.isEmpty())
+        return FormControlState();
+    FormElementStateMap::iterator it = m_stateForNewFormElements.find(FormElementKey(name.impl(), type.impl(), formKey.impl()));
+    if (it == m_stateForNewFormElements.end())
+        return FormControlState();
+    ASSERT(it->second.size());
+    FormControlState state = it->second.takeFirst();
+    if (!it->second.size())
+        m_stateForNewFormElements.remove(it);
+    return state;
+}
+
+// ----------------------------------------------------------------------------
+
 class FormKeyGenerator {
     WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
     WTF_MAKE_FAST_ALLOCATED;
@@ -190,7 +338,6 @@
 
 void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
 {
-    typedef FormElementStateMap::iterator Iterator;
     m_formElementsWithState.clear();
 
     size_t i = 0;
@@ -204,38 +351,23 @@
         FormControlState state = FormControlState::deserialize(stateVector, i);
         if (type.isEmpty() || type.impl()->find(isNotFormControlTypeCharacter) != notFound || state.isFailure())
             break;
-
-        FormElementKey key(name.impl(), type.impl(), formKey.impl());
-        Iterator it = m_stateForNewFormElements.find(key);
-        if (it != m_stateForNewFormElements.end())
-            it->second.append(state);
-        else {
-            Deque<FormControlState> stateList;
-            stateList.append(state);
-            m_stateForNewFormElements.set(key, stateList);
-        }
+        if (!m_savedFormState)
+            m_savedFormState = SavedFormState::create();
+        m_savedFormState->appendControlState(name, type, formKey, state);
     }
     if (i != stateVector.size())
-        m_stateForNewFormElements.clear();
+        m_savedFormState.clear();
 }
 
 FormControlState FormController::takeStateForFormElement(const HTMLFormControlElementWithState& control)
 {
-    if (m_stateForNewFormElements.isEmpty())
+    if (!m_savedFormState)
         return FormControlState();
     if (!m_formKeyGenerator)
         m_formKeyGenerator = FormKeyGenerator::create();
-    typedef FormElementStateMap::iterator Iterator;
-    Iterator it = m_stateForNewFormElements.find(FormElementKey(control.name().impl(), control.type().impl(), m_formKeyGenerator->formKey(control).impl()));
-    if (it == m_stateForNewFormElements.end())
-        return FormControlState();
-    ASSERT(it->second.size());
-    FormControlState state = it->second.takeFirst();
-    if (!it->second.size()) {
-        m_stateForNewFormElements.remove(it);
-        if (m_stateForNewFormElements.isEmpty())
-            m_formKeyGenerator.clear();
-    }
+    FormControlState state = m_savedFormState->takeControlState(control.name(), control.type(), m_formKeyGenerator->formKey(control));
+    if (m_savedFormState->isEmpty())
+        m_savedFormState.clear();
     return state;
 }
 
@@ -276,61 +408,5 @@
     }
 }
 
-FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type, AtomicStringImpl* formKey)
-    : m_name(name)
-    , m_type(type)
-    , m_formKey(formKey)
-{
-    ref();
-}
-
-FormElementKey::~FormElementKey()
-{
-    deref();
-}
-
-FormElementKey::FormElementKey(const FormElementKey& other)
-    : m_name(other.name())
-    , m_type(other.type())
-    , m_formKey(other.formKey())
-{
-    ref();
-}
-
-FormElementKey& FormElementKey::operator=(const FormElementKey& other)
-{
-    other.ref();
-    deref();
-    m_name = other.name();
-    m_type = other.type();
-    m_formKey = other.formKey();
-    return *this;
-}
-
-void FormElementKey::ref() const
-{
-    if (name())
-        name()->ref();
-    if (type())
-        type()->ref();
-    if (formKey())
-        formKey()->ref();
-}
-
-void FormElementKey::deref() const
-{
-    if (name())
-        name()->deref();
-    if (type())
-        type()->deref();
-    if (formKey())
-        formKey()->deref();
-}
-
-unsigned FormElementKeyHash::hash(const FormElementKey& key)
-{
-    return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
-}
-
 } // namespace WebCore