1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "stdafx.h"
17 
18 #include <map>
19 
20 #include "capi/error.h"
21 #include "capi/csequence.h"
22 #include "capi/user_item_sequence.h"
23 #include "diagnostics/xquery_diagnostics.h"
24 #include <zorba/item_sequence.h>
25 #include "diagnostics/assert.h"
26 
27 using namespace zorba;
28 
29 #define ZIS_TRY CAPI_TRY(UserItemSequence,setter)
30 #define ZIS_CATCH CAPI_CATCH
31 
32 // pointer-to-members are eeeevil
33 typedef Item (ItemFactory::*ItemFactoryMemFn)(const String& aString);
34 #define CALL_ITEMFACTORY_FN(object,ptrToMember) ((object).*(ptrToMember))
35 
36 namespace zorbac {
37 
38   namespace FactoryCreators {
39 
40     // Maps XQC_ItemTypes to from-string item create method
41     static std::map<XQC_ItemType, ItemFactoryMemFn> methods;
42 
43     class CreatorInitializer {
44       public:
CreatorInitializer()45         CreatorInitializer()
46         {
47           methods[XQC_ANY_URI_TYPE] = &ItemFactory::createAnyURI;
48           methods[XQC_DATE_TYPE] = &ItemFactory::createDate;
49           methods[XQC_DATE_TIME_TYPE] = &ItemFactory::createDateTime;
50           methods[XQC_DECIMAL_TYPE] = &ItemFactory::createDecimal;
51           methods[XQC_DOUBLE_TYPE] = &ItemFactory::createDouble;
52           methods[XQC_DURATION_TYPE] = &ItemFactory::createDuration;
53           methods[XQC_FLOAT_TYPE] = &ItemFactory::createFloat;
54           methods[XQC_G_DAY_TYPE] = &ItemFactory::createGDay;
55           methods[XQC_G_MONTH_TYPE] = &ItemFactory::createGMonth;
56           methods[XQC_G_MONTH_DAY_TYPE] = &ItemFactory::createGMonthDay;
57           methods[XQC_G_YEAR_TYPE] = &ItemFactory::createGYear;
58           methods[XQC_G_YEAR_MONTH_TYPE] = &ItemFactory::createGYearMonth;
59           methods[XQC_STRING_TYPE] = &ItemFactory::createString;
60           methods[XQC_TIME_TYPE] = &ItemFactory::createTime;
61         }
62     };
63 
64     // Instance exists only to initialize methods
65     static CreatorInitializer initer;
66   } /* namespace FactoryCreators */
67 
UserItemSequence(XQC_Sequence ** args,unsigned int argc,external_function_init init_fn,external_function_next next_fn,external_function_free free_fn,void * sequence_data,ItemFactory * factory,XQC_ErrorHandler * handler)68   UserItemSequence::UserItemSequence
69   (XQC_Sequence** args, unsigned int argc,
70     external_function_init init_fn, external_function_next next_fn,
71     external_function_free free_fn, void* sequence_data, ItemFactory* factory,
72     XQC_ErrorHandler* handler)
73     : theArgs(args),
74       theArgc(argc),
75       theInitFunction(init_fn),
76       theNextFunction(next_fn),
77       theFreeFunction(free_fn),
78       theSequenceData(sequence_data),
79       theFactory(factory),
80       theErrorHandler(handler)
81   {
82     memset(&theItemSetter, 0, sizeof(Zorba_ItemSetter));
83     theItemSetter.set_string      = UserItemSequence::set_string;
84     theItemSetter.set_integer     = UserItemSequence::set_integer;
85     theItemSetter.set_double      = UserItemSequence::set_double;
86     theItemSetter.set_typed_value = UserItemSequence::set_typed_value;
87 
88   }
89 
~UserItemSequence()90   UserItemSequence::~UserItemSequence()
91   {
92     if (theFreeFunction) {
93       theFreeFunction(theUserData, theSequenceData);
94     }
95     for (unsigned int i = 0; i < theArgc; i++) {
96       theArgs[i]->free(theArgs[i]);
97     }
98     delete[] theArgs;
99   }
100 
101   UserItemSequence*
get(Zorba_ItemSetter * setter)102   UserItemSequence::get(Zorba_ItemSetter* setter)
103   {
104     return (UserItemSequence*)
105       (((char*)setter) - CLASS_OFFSET(UserItemSequence, theItemSetter));
106   }
107 
getIterator()108   Iterator_t UserItemSequence::getIterator()
109   {
110     return new InternalIterator(this);
111   }
112 
InternalIterator(UserItemSequence * item_sequence)113   UserItemSequence::InternalIterator::InternalIterator(UserItemSequence  *item_sequence) : theItemSequence(item_sequence)
114   {
115     is_open = false;
116   }
117 
open()118   void UserItemSequence::InternalIterator::open()
119   {
120     is_open = true;
121     if (theItemSequence->theInitFunction) {
122       theItemSequence->theInitFunction(&theItemSequence->theUserData, theItemSequence->theSequenceData);
123     }
124   }
125 
close()126   void UserItemSequence::InternalIterator::close()
127   {
128     is_open = false;
129   }
130 
isOpen() const131   bool UserItemSequence::InternalIterator::isOpen() const
132   {
133     return is_open;
134   }
135 
136   bool
next(Item & i)137   UserItemSequence::InternalIterator::next(Item& i)
138   {
139     ZORBA_ASSERT(is_open);
140     XQC_Error lRes = theItemSequence->theNextFunction(
141                                   theItemSequence->theArgs,
142                                   theItemSequence->theArgc,
143                                   &theItemSequence->theItemSetter,
144                                   theItemSequence->theUserData,
145                                   theItemSequence->theSequenceData);
146     if (lRes == XQC_END_OF_SEQUENCE)
147       return false;
148     if (lRes != XQC_NO_ERROR)
149       throw ZORBA_EXCEPTION( zerr::ZXQP0003_INTERNAL_ERROR );
150 
151     // theItem will have been set by the user calling back to one
152     // of the Zorba_ItemSetter methods.
153     i = theItemSequence->theItem;
154     assert (!i.isNull());
155 
156     return true;
157   }
158 
159   // Zorba_ItemSetter methods
160 
161   XQC_Error
set_string(Zorba_ItemSetter * setter,const char * value)162   UserItemSequence::set_string(Zorba_ItemSetter* setter, const char* value)
163   {
164     ZIS_TRY {
165       me->theItem = me->theFactory->createString(value);
166     }
167     ZIS_CATCH;
168   }
169 
170   XQC_Error
set_integer(Zorba_ItemSetter * setter,int value)171   UserItemSequence::set_integer(Zorba_ItemSetter* setter, int value)
172   {
173     ZIS_TRY {
174       me->theItem = me->theFactory->createInt(value);
175     }
176     ZIS_CATCH;
177   }
178 
179   XQC_Error
set_double(Zorba_ItemSetter * setter,double value)180   UserItemSequence::set_double(Zorba_ItemSetter* setter, double value)
181   {
182     ZIS_TRY {
183       me->theItem = me->theFactory->createDouble(value);
184     }
185     ZIS_CATCH;
186   }
187 
188   XQC_Error
set_typed_value(Zorba_ItemSetter * setter,XQC_ItemType type,const char * value)189   UserItemSequence::set_typed_value(Zorba_ItemSetter* setter, XQC_ItemType type,
190     const char* value)
191   {
192     ZIS_TRY {
193       switch (type) {
194         case XQC_ANY_URI_TYPE:
195         case XQC_DATE_TYPE:
196         case XQC_DATE_TIME_TYPE:
197         case XQC_DECIMAL_TYPE:
198         case XQC_DOUBLE_TYPE:
199         case XQC_DURATION_TYPE:
200         case XQC_FLOAT_TYPE:
201         case XQC_G_DAY_TYPE:
202         case XQC_G_MONTH_TYPE:
203         case XQC_G_MONTH_DAY_TYPE:
204         case XQC_G_YEAR_TYPE:
205         case XQC_G_YEAR_MONTH_TYPE:
206         case XQC_STRING_TYPE:
207         case XQC_TIME_TYPE: {
208           zorba::String lValue(value);
209           me->theItem = CALL_ITEMFACTORY_FN
210             (*(me->theFactory), FactoryCreators::methods[type])
211             (lValue);
212           break;
213         }
214 
215         default:
216           return XQC_NOT_IMPLEMENTED;
217       }
218     }
219     ZIS_CATCH;
220   }
221 } /* namespace zorbac */
222 /* vim:set et sw=2 ts=2: */
223