
/**********************************************************//**
 **
 ** @file index/reflist/reflist.h
 **
 ** Copyright (C) 2010  Xpace, LLC.  All rights reserved
 **
 ** www.xpace.net
 **
 **************************************************************/


#ifndef XPACE_REFLIST_H
#define XPACE_REFLIST_H

#include <vector>

#include "base/types.h"
#include "base/sharedimpl.h"

namespace Xpace
{
  /// A cursor into a list of references - e.g., a search result
  /// A single reference is an array of uint64s

  class XPACE_EXPORT RefListCursor
  {
  public :
    /// @return the number of references in the list
    uint64 getCount
      ()
    const;

    /// @return the current cursor position within the list
    uint64 getPosition
      ()
    const;

    /// move the cursor
    /// @param distance the distance to move
    /// @param relative the starting point; true = move from current position, false = move from start
    /// @return true if move succeeded, false (and do not move) otherwise
    bool move
      (int64 distance = 1,
       bool relative = true); 

    /// @return the first element of the current ref
    uint64 operator*
      ()
      const;
    /// @return a pointer to the array of uint64s that make up the current ref
    const uint64* get
      ()
    const;
    /// @param len - fillin for the number of elements in the current ref
    /// @return a pointer to the array of uint64s that make up the current ref
    const uint64* get
      (uint* len)
    const;

    /// Interface of the functor passed to forEach().  Create an
    /// implemention of forEachRef defining an operator().
    class forEachRef
    {
    public :
      virtual ~forEachRef
        () 
      { 
      }

      /// called for each reference in the list
      /// @param ref a pointer to the array of uint64s that make up the current ref
      /// @param len the number of elements in the current ref
      /// @return true to continue, false to abort
      virtual bool operator()
        (uint64 *const ref,
         uint len)
      = 0;
    };

    /// Enumerate references in the cursor's underlying reference list, starting at
    /// start (relative to the whole list), calling the callThis functor for each one.
    /// The cursor itself is unchanged.
    /// @param call This will be called for each reference in the list
    /// @param start Call callThis beginning at this ref
    /// @return true if all references were iterated, false if iteration was aborted
    bool forEach
      (forEachRef* callThis,
       uint64 start = 0)
      const;

    /// @return true if past last ref
    bool operator!
      ()
    const;

    /// this list OR rhs list
    /// @param rhs the other source list
    void opOr
      (RefListCursor* rhs);

    /// this list AND rhs list
    /// @param rhs the other source list
    void opAnd
      (RefListCursor* rhs);

    /// AND a vector of ref lists
    /// @param list the source lists. NB - any of these may be altered
    /// @return the result, which may be one of the source lists
    static RefListCursor opAnd
      (std::vector<RefListCursor>* list); 

    /// count the refs in this list AND rhs list
    /// @param rhs the other source list
    /// @return the number of refs 
    uint64 countAnd
      (const RefListCursor& rhs)
      const;

    /// invert a ref list
    /// @param end the number of refs in the universe; if 0, get from index
    void opNot
      (uint64 end = 0);       

    /// Does this reference list have this ref?
    /// @param ref look for this ref
    /// @param pos fill-in the position in the list of this ref
    /// @return true if the list has the ref, false if not
    bool hasRef
      (uint64 ref,
       uint64* pos = 0)   
      const;

    /// Does this reference list have this ref?
    /// @param ref look for this ref
    /// @param pos fill-in the position in the list of this ref
    /// @return true if the list has the ref, false if not
    bool hasRef
      (std::vector<uint64>& ref,
       uint64* pos = 0)   
      const;

    /// add a reference to the list
    /// @param ref add this ref
    void addRef
      (uint64 ref);
    /// @param ref add this ref
    void addRef
      (std::vector<uint64>& ref);

    /// remove a reference from the list
    /// @param remove this ref (if it exists)
    void removeRef
      (uint64 ref);
    /// @param remove this ref (if it exists)
    void removeRef
      (std::vector<uint64> ref);

    class Factory;
    DECLARE_IMPL(RefListCursor)
  };

}; // namespace Xpace

#endif

