1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MIDIPortMap_h 6 #define MIDIPortMap_h 7 8 #include "bindings/core/v8/ExceptionState.h" 9 #include "bindings/core/v8/ScriptState.h" 10 #include "bindings/core/v8/ScriptValue.h" 11 #include "bindings/core/v8/V8Binding.h" 12 #include "core/dom/Iterator.h" 13 #include "platform/heap/Handle.h" 14 #include "wtf/HashMap.h" 15 #include "wtf/text/StringHash.h" 16 #include "wtf/text/WTFString.h" 17 18 namespace blink { 19 20 template <typename T> 21 class MIDIPortMap : public GarbageCollected<MIDIPortMap<T> > { 22 public: 23 explicit MIDIPortMap(const HeapHashMap<String, Member<T> >& entries) : m_entries(entries) { } 24 25 // IDL attributes / methods 26 size_t size() const { return m_entries.size(); } 27 Iterator* keys(); 28 Iterator* entries(); 29 Iterator* values(); 30 T* get(const String& key) const; 31 bool has(const String& key) const { return m_entries.contains(key); } 32 Iterator* iterator(ScriptState*, ExceptionState&) { return entries(); } 33 34 virtual void trace(Visitor* visitor) 35 { 36 visitor->trace(m_entries); 37 } 38 39 private: 40 typedef HeapHashMap<String, Member<T> > MapType; 41 typedef typename HeapHashMap<String, Member<T> >::const_iterator IteratorType; 42 struct KeySelector { 43 static const String& select(ScriptState*, IteratorType i) { return i->key; } 44 }; 45 struct ValueSelector { 46 static T* select(ScriptState*, IteratorType i) { return i->value; } 47 }; 48 struct EntrySelector { 49 static Vector<ScriptValue> select(ScriptState* scriptState, IteratorType i) 50 { 51 Vector<ScriptValue> entry; 52 entry.append(ScriptValue(scriptState, v8String(scriptState->isolate(), i->key))); 53 entry.append(ScriptValue(scriptState, V8ValueTraits<T*>::toV8Value(i->value, scriptState->context()->Global(), scriptState->isolate()))); 54 return entry; 55 } 56 }; 57 58 // Note: This template class relies on the fact that m_map.m_entries will 59 // never be modified once it is created. 60 template <typename Selector> 61 class MapIterator : public Iterator { 62 public: 63 MapIterator(MIDIPortMap<T>* map, IteratorType iterator, IteratorType end) 64 : m_map(map) 65 , m_iterator(iterator) 66 , m_end(end) 67 { 68 } 69 70 virtual ScriptValue next(ScriptState* scriptState, ExceptionState&) OVERRIDE 71 { 72 if (m_iterator == m_end) 73 return ScriptValue(scriptState, v8DoneIteratorResult(scriptState->isolate())); 74 ScriptValue result(scriptState, v8IteratorResult(scriptState, Selector::select(scriptState, m_iterator))); 75 ++m_iterator; 76 return result; 77 } 78 79 virtual ScriptValue next(ScriptState* scriptState, ScriptValue, ExceptionState& exceptionState) OVERRIDE 80 { 81 return next(scriptState, exceptionState); 82 } 83 84 virtual void trace(Visitor* visitor) OVERRIDE 85 { 86 visitor->trace(m_map); 87 Iterator::trace(visitor); 88 } 89 90 private: 91 // m_map is stored just for keeping it alive. It needs to be kept 92 // alive while JavaScript holds the iterator to it. 93 const Member<const MIDIPortMap<T> > m_map; 94 IteratorType m_iterator; 95 const IteratorType m_end; 96 }; 97 98 const MapType m_entries; 99 }; 100 101 template <typename T> 102 Iterator* MIDIPortMap<T>::keys() 103 { 104 return new MapIterator<KeySelector>(this, m_entries.begin(), m_entries.end()); 105 } 106 107 template <typename T> 108 Iterator* MIDIPortMap<T>::entries() 109 { 110 return new MapIterator<EntrySelector>(this, m_entries.begin(), m_entries.end()); 111 } 112 113 template <typename T> 114 Iterator* MIDIPortMap<T>::values() 115 { 116 return new MapIterator<ValueSelector>(this, m_entries.begin(), m_entries.end()); 117 } 118 119 template <typename T> 120 T* MIDIPortMap<T>::get(const String& key) const 121 { 122 return has(key) ? m_entries.get(key) : 0; 123 } 124 125 } // namespace blink 126 127 #endif 128