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