1/*
2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3 * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
4 * Copyright (C) 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#ifndef JSSVGPODListCustom_h
23#define JSSVGPODListCustom_h
24
25#include "JSSVGContextCache.h"
26#include "JSSVGPODTypeWrapper.h"
27#include "SVGList.h"
28
29namespace WebCore {
30
31namespace JSSVGPODListCustom {
32
33// Helper structure only containing public typedefs, as C++ does not allow templatized typedefs
34template<typename PODType>
35struct JSSVGPODListTraits {
36    typedef SVGPODListItem<PODType> PODListItem;
37    typedef SVGList<RefPtr<PODListItem> > PODList;
38    typedef PODType (*ConversionCallback)(JSC::JSValue);
39};
40
41template<typename JSPODListType, typename PODType>
42static JSC::JSValue finishGetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper,
43                                 PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item)
44{
45    if (ec) {
46        setDOMException(exec, ec);
47        return JSC::jsUndefined();
48    }
49
50    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
51
52    SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper);
53    return toJS(exec, wrapper->globalObject(),
54                JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), listImp->associatedAttributeName()).get(), context);
55}
56
57template<typename JSPODListType, typename PODType>
58static JSC::JSValue finishSetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper,
59                                 PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item)
60{
61    if (ec) {
62        setDOMException(exec, ec);
63        return JSC::jsUndefined();
64    }
65
66    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
67
68    const QualifiedName& attributeName = listImp->associatedAttributeName();
69    JSSVGContextCache::propagateSVGDOMChange(wrapper, attributeName);
70
71    SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper);
72    return toJS(exec, wrapper->globalObject(),
73                JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), attributeName).get(), context);
74}
75
76template<typename JSPODListType, typename PODType>
77static JSC::JSValue finishSetterReadOnlyResult(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper,
78                                               PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item)
79{
80    if (ec) {
81        setDOMException(exec, ec);
82        return JSC::jsUndefined();
83    }
84
85    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
86    JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName());
87    return toJS(exec, wrapper->globalObject(),
88                JSSVGStaticPODTypeWrapper<PODType>::create(*item).get(), 0  /* no context on purpose */);
89}
90
91template<typename JSPODListType, typename PODType>
92static JSC::JSValue clear(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList&,
93                          typename JSSVGPODListTraits<PODType>::ConversionCallback)
94{
95    ExceptionCode ec = 0;
96    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
97    listImp->clear(ec);
98
99    if (ec)
100        setDOMException(exec, ec);
101    else
102        JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName());
103
104    return JSC::jsUndefined();
105}
106
107template<typename JSPODListType, typename PODType>
108static JSC::JSValue initialize(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args,
109                               typename JSSVGPODListTraits<PODType>::ConversionCallback conversion)
110{
111    ExceptionCode ec = 0;
112    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
113    return finishSetter<JSPODListType, PODType>(exec, ec, wrapper,
114                                                listImp->initialize(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec));
115}
116
117template<typename JSPODListType, typename PODType>
118static JSC::JSValue getItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args,
119                            typename JSSVGPODListTraits<PODType>::ConversionCallback)
120{
121    bool indexOk = false;
122    unsigned index = args.at(0).toUInt32(exec, indexOk);
123    if (!indexOk) {
124        setDOMException(exec, TYPE_MISMATCH_ERR);
125        return JSC::jsUndefined();
126    }
127
128    ExceptionCode ec = 0;
129    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
130    return finishGetter<JSPODListType, PODType>(exec, ec, wrapper,
131                                                listImp->getItem(index, ec));
132}
133
134template<typename JSPODListType, typename PODType>
135static JSC::JSValue insertItemBefore(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args,
136                                     typename JSSVGPODListTraits<PODType>::ConversionCallback conversion)
137{
138    bool indexOk = false;
139    unsigned index = args.at(1).toUInt32(exec, indexOk);
140    if (!indexOk) {
141        setDOMException(exec, TYPE_MISMATCH_ERR);
142        return JSC::jsUndefined();
143    }
144
145    ExceptionCode ec = 0;
146    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
147    return finishSetter<JSPODListType, PODType>(exec, ec, wrapper,
148                                                listImp->insertItemBefore(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec));
149}
150
151template<typename JSPODListType, typename PODType>
152static JSC::JSValue replaceItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args,
153                                typename JSSVGPODListTraits<PODType>::ConversionCallback conversion)
154{
155    bool indexOk = false;
156    unsigned index = args.at(1).toUInt32(exec, indexOk);
157    if (!indexOk) {
158        setDOMException(exec, TYPE_MISMATCH_ERR);
159        return JSC::jsUndefined();
160    }
161
162    ExceptionCode ec = 0;
163    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
164    return finishSetter<JSPODListType, PODType>(exec, ec, wrapper,
165                                                listImp->replaceItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec));
166}
167
168template<typename JSPODListType, typename PODType>
169static JSC::JSValue removeItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args,
170                               typename JSSVGPODListTraits<PODType>::ConversionCallback)
171{
172    bool indexOk = false;
173    unsigned index = args.at(0).toUInt32(exec, indexOk);
174    if (!indexOk) {
175        setDOMException(exec, TYPE_MISMATCH_ERR);
176        return JSC::jsUndefined();
177    }
178
179    ExceptionCode ec = 0;
180    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
181    return finishSetterReadOnlyResult<JSPODListType, PODType>(exec, ec, wrapper,
182                                                              listImp->removeItem(index, ec));
183}
184
185template<typename JSPODListType, typename PODType>
186static JSC::JSValue appendItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args,
187                               typename JSSVGPODListTraits<PODType>::ConversionCallback conversion)
188{
189    ExceptionCode ec = 0;
190    typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl();
191    return finishSetter<JSPODListType, PODType>(exec, ec, wrapper,
192                                                listImp->appendItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec));
193}
194
195}
196
197}
198
199#endif
200