Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/pub_iter_imp into 
lp:zorba.

Commit message:
Added count() & skip() to public Iterator API.

Requested reviews:
  Paul J. Lucas (paul-lucas)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/pub_iter_imp/+merge/201708

Added count() & skip() to public Iterator API.
-- 
https://code.launchpad.net/~zorba-coders/zorba/pub_iter_imp/+merge/201708
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'NOTICE.txt'
--- NOTICE.txt	2014-01-10 02:36:58 +0000
+++ NOTICE.txt	2014-01-15 03:04:02 +0000
@@ -482,7 +482,8 @@
 Copyright: 2000 D. J. Bernstein
 Website: http://cr.yp.to/ftpparse.html
 
-      Commercial use is fine, if you let me know what programs you're using this in.
+      Commercial use is fine, if you let me know what programs you're
+      using this in.
     
 
 External libraries used by this project:

=== modified file 'include/zorba/function.h'
--- include/zorba/function.h	2013-08-23 11:15:04 +0000
+++ include/zorba/function.h	2014-01-15 03:04:02 +0000
@@ -4,7 +4,7 @@
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
@@ -30,10 +30,10 @@
 
 /**************************************************************************//**
   The Function class represents a function that is callable from XQuery code,
-  and it gives access to the various properties that are specified in the 
+  and it gives access to the various properties that are specified in the
   declaration of the function within a Prolog.
 
-  Instances of Function are returned by the StaticContext::findFunctions() 
+  Instances of Function are returned by the StaticContext::findFunctions()
   method. To be mopre precise, StaticContext::findFunctions() returns smart
   pointers to Function objects. These smart pointers must be destroyed before
   the StaticContext object they were obtained from is destroyed.
@@ -45,31 +45,27 @@
 class ZORBA_DLL_PUBLIC Function : public SmartObject
 {
  public:
-  /** \brief Destructor
-   */
-  virtual ~Function() {}
-
   /**
    * @return True if the function is sequential; false otherwise.
-   */  
+   */
   virtual bool
   isSequential() const = 0;
 
   /**
    * @return True if the function is updating; false otherwise.
-   */  
+   */
   virtual bool
   isUpdating() const = 0;
 
   /**
    * @return True if the function is private; false otherwise.
-   */  
+   */
   virtual bool
   isPrivate() const = 0;
 
   /**
    * @return True if the function is deterministic; false otherwise.
-   */  
+   */
   virtual bool
   isDeterministic() const = 0;
 
@@ -99,7 +95,7 @@
 
   /**
    * @return The arity of the function. If the function is variadic (which is
-   *         possible only for builtin functions), the result of this method 
+   *         possible only for builtin functions), the result of this method
    *         is non-deterministic.
    */
   virtual size_t
@@ -119,7 +115,7 @@
 
   /**
    * @return True if the function implementation is written in XQuery (or
-   *         equivalently, it is a non-external function with a Prolog 
+   *         equivalently, it is a non-external function with a Prolog
    *         declaration); false otherwise
    */
   virtual bool
@@ -138,10 +134,10 @@
   The ExternalFunction class serves as the base of subclasses that represent
   the implementation/body of external functions.
 
-  Instances of ExternalFunction must provide an evaluate method that serves 
-  as the implementation of the function. During its evaluation, an external 
-  function may or may not need to access the static and/or dynamic context of 
-  the invoking XQuery module. If the function implementation does need to 
+  Instances of ExternalFunction must provide an evaluate method that serves
+  as the implementation of the function. During its evaluation, an external
+  function may or may not need to access the static and/or dynamic context of
+  the invoking XQuery module. If the function implementation does need to
   access either context, the function is referred to as "contextual"; otherwise,
   it is "non-contextual".
 *******************************************************************************/
@@ -150,8 +146,7 @@
 public:
   typedef std::vector<ItemSequence*> Arguments_t;
 
- public:
-  virtual ~ExternalFunction() {}
+  virtual ~ExternalFunction();
 
   /**
    * @return The namespace URI of the function QName
@@ -189,8 +184,6 @@
 class ZORBA_DLL_PUBLIC NonContextualExternalFunction : public ExternalFunction
 {
  public:
-  virtual ~NonContextualExternalFunction() {}
-
   virtual ItemSequence_t
   evaluate(const Arguments_t&) const = 0;
 
@@ -201,7 +194,7 @@
 
 /**************************************************************************//**
   The ContextualExternalFunction class serves as the base of subclasses that
-  represent the implementation of contextual external functions. 
+  represent the implementation of contextual external functions.
 
   For each external function, an application must provide a concrete subclass
   of this class and "store" an instance of the subclass inside an ExternalModule
@@ -211,14 +204,12 @@
 class ZORBA_DLL_PUBLIC ContextualExternalFunction : public ExternalFunction
 {
  public:
-  virtual ~ContextualExternalFunction() {}
-
   virtual ItemSequence_t
   evaluate(
       const Arguments_t&,
       const StaticContext*,
       const DynamicContext*) const = 0;
-  
+
   bool
   isContextual() const { return true; }
 };

=== modified file 'include/zorba/iterator.h'
--- include/zorba/iterator.h	2013-08-01 09:52:25 +0000
+++ include/zorba/iterator.h	2014-01-15 03:04:02 +0000
@@ -34,13 +34,10 @@
 class ZORBA_DLL_PUBLIC Iterator : virtual public SmartObject
 {
  public:
-  /** \brief Destructor
-   */
-  virtual ~Iterator() {}
-
   /** \brief Start iterating.
    *
-   * This function needs to be called before calling next() or close().
+   * This function needs to be called before calling next(), count(), skip() or
+   * close().
    * Its purpose is to create and initialize any resources that may be 
    * needed during the iteration. It should not be called again until
    * after close() has been called.
@@ -73,10 +70,30 @@
   close() = 0;
 
   /**
-   * brief Check whether the iterator is open or not
+   * \brief Check whether the iterator is open or not
    */
   virtual bool
   isOpen() const = 0;
+
+  /**
+   * Counts the number of items this iterator would have returned.
+   *
+   * @throw ZorbaException if an error occurs or the iterator has not been
+   * opened.
+   */
+  virtual int64_t
+  count();
+
+  /**
+   * Skips a number of items.
+   *
+   * @param count The number of items to skip.
+   * @return \c true only if there are more items.
+   * @throw ZorbaException if an error occurs or the iterator has not been
+   * opened.
+   */
+  virtual bool
+  skip(int64_t count);
 };
 
 

=== modified file 'modules/ftp-client/ftp-client.xq.src/ftp_functions.cpp'
--- modules/ftp-client/ftp-client.xq.src/ftp_functions.cpp	2014-01-11 01:27:47 +0000
+++ modules/ftp-client/ftp-client.xq.src/ftp_functions.cpp	2014-01-15 03:04:02 +0000
@@ -612,14 +612,18 @@
 
   // inherited from Iterator
   void close();
+  int64_t count();
   bool isOpen() const;
   bool next( Item& );
   void open();
+  bool skip( int64_t );
 
 private:
   ItemFactory *const factory_;
   istream is_;
   bool open_;
+
+  bool get_line( string* );
 };
 
 list_iterator::list_iterator( curl::streambuf *cbuf, ItemFactory *factory ) :
@@ -633,10 +637,32 @@
   open_ = false;
 }
 
+int64_t list_iterator::count() {
+  int64_t count = 0;
+  string line;
+  while ( get_line( &line ) ) {
+    struct ftpparse ftp_file;
+    if ( ftpparse( &ftp_file, line.data(), line.size() ) )
+      ++count;
+  } // while
+  return count;
+}
+
 Iterator_t list_iterator::getIterator() {
   return this;
 }
 
+bool list_iterator::get_line( string *line ) {
+  while ( getline( is_, *line ) ) {
+    if ( !line->empty() ) {
+      if ( (*line)[ line->size() - 1 ] == '\r' )
+        line->erase( line->size() - 1 );
+      return true;
+    }
+  } // while
+  return false;
+}
+
 bool list_iterator::isOpen() const {
   return open_;
 }
@@ -647,11 +673,7 @@
   static Item const size_key( factory_->createString( "size" ) );
 
   string line;
-  while ( getline( is_, line ) ) {
-    if ( line.empty() )
-      continue;
-    if ( line[ line.size() - 1 ] == '\r' )
-      line.erase( line.size() - 1 );
+  while ( get_line( &line ) ) {
     struct ftpparse ftp_file;
     if ( ftpparse( &ftp_file, line.data(), line.size() ) ) {
       vector<pair<Item,Item> > kv;
@@ -709,6 +731,17 @@
   open_ = true;
 }
 
+bool list_iterator::skip( int64_t count ) {
+  string line;
+  bool more_items = true;
+  while ( count > 0 && (more_items = get_line( &line )) ) {
+    struct ftpparse ftp_file;
+    if ( ftpparse( &ftp_file, line.data(), line.size() ) )
+      --count;
+  } // while
+  return more_items;
+}
+
 list_function::list_function( module const *m ) :
   function( m, "list" )
 {

=== modified file 'src/api/CMakeLists.txt'
--- src/api/CMakeLists.txt	2014-01-03 17:31:44 +0000
+++ src/api/CMakeLists.txt	2014-01-15 03:04:02 +0000
@@ -16,8 +16,10 @@
 
 SET(API_SRCS
     base64_util.cpp
+    external_function.cpp
     smart_ptr.cpp
     diagnostic_handler.cpp
+    iterator.cpp
     zorba.cpp
     zorbaimpl.cpp
     xqueryimpl.cpp

=== added file 'src/api/external_function.cpp'
--- src/api/external_function.cpp	1970-01-01 00:00:00 +0000
+++ src/api/external_function.cpp	2014-01-15 03:04:02 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006-2013 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <zorba/function.h>
+
+namespace zorba {
+
+///////////////////////////////////////////////////////////////////////////////
+
+ExternalFunction::~ExternalFunction() {
+  // out-of-line since it's virtual
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== added file 'src/api/iterator.cpp'
--- src/api/iterator.cpp	1970-01-01 00:00:00 +0000
+++ src/api/iterator.cpp	2014-01-15 03:04:02 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2006-2013 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <zorba/item.h>
+#include <zorba/iterator.h>
+
+namespace zorba {
+
+///////////////////////////////////////////////////////////////////////////////
+
+int64_t Iterator::count() {
+  int64_t count = 0;
+  Item item;
+  while ( next( item ) )
+    ++count;
+  return count;
+}
+
+bool Iterator::skip( int64_t count ) {
+  Item item;
+  bool more_items = true;
+  while ( count > 0 && (more_items = next( item )) )
+    --count;
+  return more_items;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/runtime/base/plan_iterator.cpp'
--- src/runtime/base/plan_iterator.cpp	2013-08-05 11:54:06 +0000
+++ src/runtime/base/plan_iterator.cpp	2014-01-15 03:04:02 +0000
@@ -186,7 +186,7 @@
     ++count;
   }
 
-  STACK_PUSH(GENV_ITEMFACTORY->createInteger(result, Integer(count)), state);
+  STACK_PUSH(GENV_ITEMFACTORY->createInteger(result, xs_integer(count)), state);
   STACK_END(state);
 }
 

=== modified file 'src/runtime/core/fncall_iterator.cpp'
--- src/runtime/core/fncall_iterator.cpp	2014-01-10 22:33:46 +0000
+++ src/runtime/core/fncall_iterator.cpp	2014-01-15 03:04:02 +0000
@@ -49,8 +49,9 @@
 #include "util/string_util.h"
 
 #include "store/api/index.h"
+#include "store/api/item_factory.h"
+#include "store/api/iterator_factory.h"
 #include "store/api/store.h"
-#include "store/api/iterator_factory.h"
 #include "store/api/temp_seq.h"
 
 
@@ -859,6 +860,93 @@
   }
 }
 
+bool ExtFunctionCallIterator::count( store::Item_t &result,
+                                     PlanState &planState ) const {
+  ItemSequence_t api_seq;
+
+  ExtFunctionCallIteratorState *state;
+  DEFAULT_STACK_INIT( ExtFunctionCallIteratorState, state, planState );
+
+  try {
+    if ( theFunction->isContextual() ) {
+      ContextualExternalFunction const *const f =
+        dynamic_cast<ContextualExternalFunction const*>( theFunction );
+      ZORBA_ASSERT( f );
+      StaticContextImpl sctx(
+        theModuleSctx,
+        planState.theQuery ?
+          planState.theQuery->getRegisteredDiagnosticHandlerNoSync() :
+          nullptr
+      );
+      DynamicContextImpl dctx(
+        nullptr, planState.theGlobalDynCtx, theModuleSctx
+      );
+      api_seq = f->evaluate( state->m_extArgs, &sctx, &dctx );
+    } else {
+      NonContextualExternalFunction const *const f =
+        dynamic_cast<NonContextualExternalFunction const*>( theFunction );
+      ZORBA_ASSERT( f );
+      api_seq = f->evaluate( state->m_extArgs );
+    }
+    if ( !!api_seq ) {
+      Iterator_t api_iter( api_seq->getIterator() );
+      api_iter->open();
+      int64_t const count = api_iter->count();
+      api_iter->close();
+      GENV_ITEMFACTORY->createInteger( result, xs_integer( count ) );
+    }
+  }
+  catch ( ZorbaException &e ) {
+    set_source( e, loc );
+    throw;
+  }
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool ExtFunctionCallIterator::skip( int64_t count,
+                                    PlanState &planState ) const {
+  ItemSequence_t api_seq;
+  bool more_items;
+
+  ExtFunctionCallIteratorState *state;
+  DEFAULT_STACK_INIT( ExtFunctionCallIteratorState, state, planState );
+
+  try {
+    if ( theFunction->isContextual() ) {
+      ContextualExternalFunction const *const f =
+        dynamic_cast<ContextualExternalFunction const*>( theFunction );
+      ZORBA_ASSERT( f );
+      StaticContextImpl sctx(
+        theModuleSctx,
+        planState.theQuery ?
+          planState.theQuery->getRegisteredDiagnosticHandlerNoSync() :
+          nullptr
+      );
+      DynamicContextImpl dctx(
+        nullptr, planState.theGlobalDynCtx, theModuleSctx
+      );
+      api_seq = f->evaluate( state->m_extArgs, &sctx, &dctx );
+    } else {
+      NonContextualExternalFunction const *const f =
+        dynamic_cast<NonContextualExternalFunction const*>( theFunction );
+      ZORBA_ASSERT( f );
+      api_seq = f->evaluate( state->m_extArgs );
+    }
+    if ( !!api_seq ) {
+      Iterator_t api_iter( api_seq->getIterator() );
+      api_iter->open();
+      more_items = api_iter->skip( count );
+      api_iter->close();
+    }
+  }
+  catch ( ZorbaException &e ) {
+    set_source( e, loc );
+    throw;
+  }
+  STACK_PUSH( more_items, state );
+  STACK_END( state );
+}
 
 bool ExtFunctionCallIterator::nextImpl(
     store::Item_t& result,
@@ -906,17 +994,12 @@
         state->theResultIter = state->theResult->getIterator();
     } // if (!theFunction->isContextual())
   }
-  catch (XQueryException& e)
-  {
-    set_source( e, loc );
-    throw;
-  }
   catch (ZorbaException& e)
   {
     set_source( e, loc );
     throw;
   }
-  catch (std::exception& e)
+  catch (std::exception const& e)
   {
     throw XQUERY_EXCEPTION(
       zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR,

=== modified file 'src/runtime/core/fncall_iterator.h'
--- src/runtime/core/fncall_iterator.h	2013-09-26 09:37:30 +0000
+++ src/runtime/core/fncall_iterator.h	2014-01-15 03:04:02 +0000
@@ -259,6 +259,9 @@
   void openImpl(PlanState& planState, uint32_t& offset);
 
   bool nextImpl(store::Item_t& result, PlanState& planState) const;
+
+  bool count(store::Item_t& result, PlanState& planState) const;
+  bool skip(int64_t count, PlanState &planState) const;
 };
 
 }

-- 
Mailing list: https://launchpad.net/~zorba-coders
Post to     : zorba-coders@lists.launchpad.net
Unsubscribe : https://launchpad.net/~zorba-coders
More help   : https://help.launchpad.net/ListHelp

Reply via email to