<commit_before>// XXX: Need to make it use KeyEqual as opposed to ==
// XXX: Need to do error checking on the calls into the filter and make
//      sure things are not going wrong in there
#include "blash.hpp"

namespace bloomhash {
template<class KeyType,
  class  ValueType,
  class  Hash,
  class  KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::insertInChain(size_t idx, const KeyType& key, const ValueType& val) {
      // We will get a low set of false-positives here
      if (filters[idx].Contain(key) == cuckoofilter::Ok) { // it is _in_ the chain so we need to search through and updat the val
        Node* curr = buckets[idx];
        while (curr) {
          if (curr->key == key) {
            curr->val = val;
          }
        }
      } else { // not in the chain so add it at the beginning
        filters[idx].Add(key);
        Node* newStart = new Node();
        newStart->key = key;
        newStart->val = val;
        newStart->next = buckets[idx];
        buckets[idx] = newStart;
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::rehashResize() {
      size_t newSize = size * 2;
      // TODO: try to make this whole thing re-use the pre-existing memory
      // that we have already allocated for @buckets and @filters
      Node* newHash = calloc(sizeof(Node), newSize);
      // Chains are getting moved around so we need to re-do our filters
      cuckoofilter::CuckooFilter<KeyType, numBitsToUse>* newFilters = calloc(sizeof(cuckoofilter::CuckooFilter<KeyType, numBitsToUse>), newSize);

      // Go through our old buckets and filters
      for (int i = 0; i < size; ++i) {
        // Nodes get reused
        Node* chain = buckets[i];
        // Filters on the other hand do not. So free the filter
        delete filters[i];
        // Go through our chain and re-hash them
        while (chain) {
          Node* tmp = chain->next;
          // Evict from chain
          chain->next = nullptr;
          // Get it's new hash
          size_t newHsh = hasher(chain->key) % newSize;
          // If it collides
          if (newHash[newHsh] != nullptr) { // collision
            // Go down that chain and insert it
            // FYI: if it collides, we will already be there, so we don't
            // need to add a new filter.
            chain->next = newHash[newHsh];
            newHash[newHsh] = chain;
          } else {
            // No collision, so we simply add it. Also since we're updating
            // (i.e. re-doing) the filters, we need to create one here
            newHash[newHsh] = chain;
            newFilters[newHash] = cuckoofilter::CuckooFilter<KeyType, numBitsToUse>();
          }
          newFilters[newHash].Add(chain->key);
          chain = tmp;
        }
      }
      // update size now
      size = newSize;

      // free our buckets
      free(buckets);
      // Now point them at the new one
      buckets = newHash;

      // free the filter-array memory
      free(filters);
      // Now point them at the new filters
      filters = newFilters;
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::deleteInChain(size_t idx, const KeyType& key) {
      // This returns cuckoofilter::Ok then there is a very strong
      // probability of it being in the chain so go searching for it. If it
      // returns something else, then it's definitely _not_ in the chain so
      // don't do anything
      if (filters[idx].Contain(key) == cuckoofilter::Ok) {
        // Note: don't delete till we _know_ it's in the chain -- the bloom
        // filter saying it's in the chain doesn't necessariy mean that it
        // actually is in the chain.

        // Grab the head of the chain
        Node* curr = buckets[idx];
        // Grab a prev pointer for eas-of-use
        Node* prev = nullptr;
        while (curr) {
          // Found it
          if (curr->key == key) {
            // So delete it from the filter
            filters[idx].Delete(key);
            // This was at the head of the chain. So simply replace what
            // the bucket points to as the head of the chain
            if (prev == nullptr) {
              buckets[idx] = curr->next;
            } else {
              // else have the pointers skip-over that node
              prev->next = curr->next;
            }
            // don't forget to be good and free the memory!
            delete curr;
            break;
          }
          // haven't found it yet -- keep searching!
          curr = curr->next;
        }
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    // VERY similar to deleteInChain
    bool BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::bucketContains(const KeyType& key) {
      size_t idx = hasher(key) % size;
      // This returns cuckoofilter::Ok then there is a very strong
      // probability of it being in the chain so go searching for it. If it
      // returns something else, then it's definitely _not_ in the chain so
      // simply return false.
      if (filters[idx].Contain(key) == cuckoofilter::Ok) {
        // probabilistic! This gives a high certainting that something with
        // that key is in the bucket but it need not be the case (but this
        // is _highly_ unlikely).
        return true;
      } else {
        return false;
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    // We lazily allocate filters
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::BloomHash() {
      // TODO: make it check to make sure we allocated the memory here
      filters = calloc(sizeof(cuckoofilter::CuckooFilter<KeyType, numBitsToUse>), defaultSize);
      buckets = calloc(sizeof(Node), defaultSize);
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    // REMEMBER: we create filters lazily!
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::BloomHash(BloomHash& other) {
      // State that needs to be copied:
      // * size of buckets -- DONE
      // * each node in the table -- DONE
      // * filters -- How to copy these? -- just create a new one and add -- DONE
      // * size -- DONE
      filters = calloc(sizeof(cuckoofilter::CuckooFilter<KeyType, numBitsToUse>), other.size);
      buckets = calloc(sizeof(Node), other.size);

      size = other.size;

      for (int i = 0; i < size; ++i) {
        // Copy the chain
        if (other.buckets[i] != nullptr) {
          Node* curr = other.buckets[i];

          // Create the filter and add the data in
          cuckoofilter::CuckooFilter<KeyType, numBitsToUse> newFilt;
          newFilt.Add(curr->key);

          // Setup the head
          Node* newNode = new Node(curr->key, curr->val);
          buckets[i] = newNode;
          curr = curr->next;

          while (curr) {
            newFilt.Add(curr->key);
            Node* newNodeNext = new Node(curr->key, curr->val);
            newNode->next = newNodeNext;
            newNode = newNode->next;
          }
        }
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::BloomHash(BloomHash&& other) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>& BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::operator=(BloomHash& other) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>& BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::operator=(BloomHash&& other) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::~BloomHash() {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::insert(const KeyType& key, const ValueType& val) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::erase(const KeyType& key) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    ValueType& BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::find(const KeyType& key) {
      //BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::Iter
      //BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::find(const KeyType& key) {
    }
    }

<commit_msg>Fix line lengths<commit_after>// XXX: Need to make it use KeyEqual as opposed to ==
// XXX: Need to do error checking on the calls into the filter and make
//      sure things are not going wrong in there
#include "blash.hpp"

namespace bloomhash {
template<class KeyType,
  class  ValueType,
  class  Hash,
  class  KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
         ::insertInChain(size_t idx, const KeyType& key, const ValueType& val) {
      // We will get a low set of false-positives here
      if (filters[idx].Contain(key) == cuckoofilter::Ok) { // it is _in_ the chain so we need to search through and updat the val
        Node* curr = buckets[idx];
        while (curr) {
          if (curr->key == key) {
            curr->val = val;
          }
        }
      } else { // not in the chain so add it at the beginning
        filters[idx].Add(key);
        Node* newStart = new Node();
        newStart->key = key;
        newStart->val = val;
        newStart->next = buckets[idx];
        buckets[idx] = newStart;
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
         ::rehashResize() {
      size_t newSize = size * 2;
      // TODO: try to make this whole thing re-use the pre-existing memory
      // that we have already allocated for @buckets and @filters
      Node* newHash = calloc(sizeof(Node), newSize);
      // Chains are getting moved around so we need to re-do our filters
      cuckoofilter::CuckooFilter<KeyType, numBitsToUse>* newFilters = calloc(sizeof(cuckoofilter::CuckooFilter<KeyType, numBitsToUse>), newSize);

      // Go through our old buckets and filters
      for (int i = 0; i < size; ++i) {
        // Nodes get reused
        Node* chain = buckets[i];
        // Filters on the other hand do not. So free the filter
        delete filters[i];
        // Go through our chain and re-hash them
        while (chain) {
          Node* tmp = chain->next;
          // Evict from chain
          chain->next = nullptr;
          // Get it's new hash
          size_t newHsh = hasher(chain->key) % newSize;
          // If it collides
          if (newHash[newHsh] != nullptr) { // collision
            // Go down that chain and insert it
            // FYI: if it collides, we will already be there, so we don't
            // need to add a new filter.
            chain->next = newHash[newHsh];
            newHash[newHsh] = chain;
          } else {
            // No collision, so we simply add it. Also since we're updating
            // (i.e. re-doing) the filters, we need to create one here
            newHash[newHsh] = chain;
            newFilters[newHash] = cuckoofilter::CuckooFilter<KeyType, numBitsToUse>();
          }
          newFilters[newHash].Add(chain->key);
          chain = tmp;
        }
      }
      // update size now
      size = newSize;

      // free our buckets
      free(buckets);
      // Now point them at the new one
      buckets = newHash;

      // free the filter-array memory
      free(filters);
      // Now point them at the new filters
      filters = newFilters;
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
         ::deleteInChain(size_t idx, const KeyType& key) {
      // This returns cuckoofilter::Ok then there is a very strong
      // probability of it being in the chain so go searching for it. If it
      // returns something else, then it's definitely _not_ in the chain so
      // don't do anything
      if (filters[idx].Contain(key) == cuckoofilter::Ok) {
        // Note: don't delete till we _know_ it's in the chain -- the bloom
        // filter saying it's in the chain doesn't necessariy mean that it
        // actually is in the chain.

        // Grab the head of the chain
        Node* curr = buckets[idx];
        // Grab a prev pointer for eas-of-use
        Node* prev = nullptr;
        while (curr) {
          // Found it
          if (curr->key == key) {
            // So delete it from the filter
            filters[idx].Delete(key);
            // This was at the head of the chain. So simply replace what
            // the bucket points to as the head of the chain
            if (prev == nullptr) {
              buckets[idx] = curr->next;
            } else {
              // else have the pointers skip-over that node
              prev->next = curr->next;
            }
            // don't forget to be good and free the memory!
            delete curr;
            break;
          }
          // haven't found it yet -- keep searching!
          curr = curr->next;
        }
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    // VERY similar to deleteInChain
    bool BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
         ::bucketContains(const KeyType& key) {
      size_t idx = hasher(key) % size;
      // This returns cuckoofilter::Ok then there is a very strong
      // probability of it being in the chain so go searching for it. If it
      // returns something else, then it's definitely _not_ in the chain so
      // simply return false.
      if (filters[idx].Contain(key) == cuckoofilter::Ok) {
        // probabilistic! This gives a high certainting that something with
        // that key is in the bucket but it need not be the case (but this
        // is _highly_ unlikely).
        return true;
      } else {
        return false;
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    // We lazily allocate filters
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
    ::BloomHash() {
      // TODO: make it check to make sure we allocated the memory here
      filters = calloc(sizeof(cuckoofilter::CuckooFilter<KeyType, numBitsToUse>), defaultSize);
      buckets = calloc(sizeof(Node), defaultSize);
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    // REMEMBER: we create filters lazily!
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
    ::BloomHash(BloomHash& other) {
      // State that needs to be copied:
      // * size of buckets -- DONE
      // * each node in the table -- DONE
      // * filters -- How to copy these? -- just create a new one and add -- DONE
      // * size -- DONE
      filters = calloc(sizeof(cuckoofilter::CuckooFilter<KeyType, numBitsToUse>), other.size);
      buckets = calloc(sizeof(Node), other.size);

      size = other.size;

      for (int i = 0; i < size; ++i) {
        // Copy the chain
        if (other.buckets[i] != nullptr) {
          Node* curr = other.buckets[i];

          // Create the filter and add the data in
          cuckoofilter::CuckooFilter<KeyType, numBitsToUse> newFilt;
          newFilt.Add(curr->key);

          // Setup the head
          Node* newNode = new Node(curr->key, curr->val);
          buckets[i] = newNode;
          curr = curr->next;

          while (curr) {
            newFilt.Add(curr->key);
            Node* newNodeNext = new Node(curr->key, curr->val);
            newNode->next = newNodeNext;
            newNode = newNode->next;
          }
        }
      }
    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
    ::BloomHash(BloomHash&& other) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>&
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::operator=(BloomHash& other) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>&
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::operator=(BloomHash&& other) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::~BloomHash() {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
         ::insert(const KeyType& key, const ValueType& val) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    void BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
         ::erase(const KeyType& key) {

    }

template<class KeyType,
  class ValueType,
  class Hash,
  class KeyEqual,
  size_t numBitsToUse,
  size_t defaultSize>
    ValueType& BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>
               ::find(const KeyType& key) {
      //BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::Iter
      //BloomHash<KeyType, ValueType, Hash, KeyEqual, numBitsToUse, defaultSize>::find(const KeyType& key) {
    }
    }

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tkspinbutton.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 12:19:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_toolkit.hxx"

#ifndef TOOLKIT_CONTROLS_TKSPINBUTTON_HXX
#include "toolkit/controls/tkspinbutton.hxx"
#endif
#ifndef _TOOLKIT_HELPER_PROPERTY_HXX_
#include "toolkit/helper/property.hxx"
#endif
#ifndef _TOOLKIT_HELPER_UNOPROPERTYARRAYHELPER_HXX_
#include "toolkit/helper/unopropertyarrayhelper.hxx"
#endif
#ifndef _COM_SUN_STAR_AWT_SCROLLBARORIENTATION_HPP_
#include <com/sun/star/awt/ScrollBarOrientation.hpp>
#endif

#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
#include <cppuhelper/typeprovider.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

//........................................................................
namespace toolkit
{
//........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::awt;
    using namespace ::com::sun::star::lang;
    using namespace ::com::sun::star::beans;

    //====================================================================
    //= UnoSpinButtonModel
    //====================================================================
    //--------------------------------------------------------------------
    UnoSpinButtonModel::UnoSpinButtonModel()
    {
        ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
        ImplRegisterProperty( BASEPROPERTY_BORDER );
        ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
        ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
        ImplRegisterProperty( BASEPROPERTY_ENABLED );
        ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
        ImplRegisterProperty( BASEPROPERTY_HELPURL );
        ImplRegisterProperty( BASEPROPERTY_ORIENTATION );
        ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
        ImplRegisterProperty( BASEPROPERTY_REPEAT );
        ImplRegisterProperty( BASEPROPERTY_REPEAT_DELAY );
        ImplRegisterProperty( BASEPROPERTY_SYMBOL_COLOR );
        ImplRegisterProperty( BASEPROPERTY_SPINVALUE );
        ImplRegisterProperty( BASEPROPERTY_SPINVALUE_MIN );
        ImplRegisterProperty( BASEPROPERTY_SPINVALUE_MAX );
        ImplRegisterProperty( BASEPROPERTY_SPININCREMENT );
        ImplRegisterProperty( BASEPROPERTY_TABSTOP );
    }

    //--------------------------------------------------------------------
    ::rtl::OUString UnoSpinButtonModel::getServiceName( ) throw (RuntimeException)
    {
        return ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonModel );
    }

    //--------------------------------------------------------------------
    Any UnoSpinButtonModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
    {
        switch ( nPropId )
        {
        case BASEPROPERTY_DEFAULTCONTROL:
            return makeAny( ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonControl ) );

        case BASEPROPERTY_BORDER:
            return makeAny( (sal_Int16) 0 );

        case BASEPROPERTY_REPEAT:
            return makeAny( (sal_Bool)sal_True );

        default:
            return UnoControlModel::ImplGetDefaultValue( nPropId );
        }
    }

    //--------------------------------------------------------------------
    ::cppu::IPropertyArrayHelper& UnoSpinButtonModel::getInfoHelper()
    {
        static UnoPropertyArrayHelper* pHelper = NULL;
        if ( !pHelper )
        {
            Sequence<sal_Int32> aIDs = ImplGetPropertyIds();
            pHelper = new UnoPropertyArrayHelper( aIDs );
        }
        return *pHelper;
    }

    //--------------------------------------------------------------------
    Reference< XPropertySetInfo > UnoSpinButtonModel::getPropertySetInfo(  ) throw(RuntimeException)
    {
        static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
        return xInfo;
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL UnoSpinButtonModel::getImplementationName(  ) throw(RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.toolkit.UnoSpinButtonModel" ) );
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL UnoSpinButtonModel::getSupportedServiceNames() throw(RuntimeException)
    {
        Sequence< ::rtl::OUString > aServices( UnoControlModel::getSupportedServiceNames() );
        aServices.realloc( aServices.getLength() + 1 );
        aServices[ aServices.getLength() - 1 ] = ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonModel );
        return aServices;
    }

    //====================================================================
    //= UnoSpinButtonControl
    //====================================================================
    //--------------------------------------------------------------------
    UnoSpinButtonControl::UnoSpinButtonControl()
        :maAdjustmentListeners( *this )
    {
    }

    //--------------------------------------------------------------------
    ::rtl::OUString UnoSpinButtonControl::GetComponentServiceName()
    {
        return ::rtl::OUString::createFromAscii( "SpinButton" );
    }

    //--------------------------------------------------------------------
    Any UnoSpinButtonControl::queryAggregation( const Type & rType ) throw(RuntimeException)
    {
        Any aRet = UnoControlBase::queryAggregation( rType );
        if ( !aRet.hasValue() )
            aRet = UnoSpinButtonControl_Base::queryInterface( rType );
        return aRet;
    }

    //--------------------------------------------------------------------
    IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoSpinButtonControl, UnoControlBase, UnoSpinButtonControl_Base )

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::dispose() throw(RuntimeException)
    {
        ::osl::ClearableMutexGuard aGuard( GetMutex() );
        if ( maAdjustmentListeners.getLength() )
        {
            Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
            if ( xSpinnable.is() )
                xSpinnable->removeAdjustmentListener( this );

            EventObject aDisposeEvent;
            aDisposeEvent.Source = *this;

            aGuard.clear();
            maAdjustmentListeners.disposeAndClear( aDisposeEvent );
        }

        UnoControl::dispose();
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL UnoSpinButtonControl::getImplementationName(  ) throw(RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.toolkit.UnoSpinButtonControl" ) );
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL UnoSpinButtonControl::getSupportedServiceNames() throw(RuntimeException)
    {
        Sequence< ::rtl::OUString > aServices( UnoControlBase::getSupportedServiceNames() );
        aServices.realloc( aServices.getLength() + 1 );
        aServices[ aServices.getLength() - 1 ] = ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonControl );
        return aServices;
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer ) throw(RuntimeException)
    {
        UnoControl::createPeer( rxToolkit, rParentPeer );

        Reference < XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            xSpinnable->addAdjustmentListener( this );
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::adjustmentValueChanged( const AdjustmentEvent& rEvent ) throw(RuntimeException)
    {
        switch ( rEvent.Type )
        {
            case AdjustmentType_ADJUST_LINE:
            case AdjustmentType_ADJUST_PAGE:
            case AdjustmentType_ADJUST_ABS:
                ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), makeAny( rEvent.Value ), sal_False );
                break;
            default:
                DBG_ERROR( "UnoSpinButtonControl::adjustmentValueChanged - unknown Type" );
        }

        if ( maAdjustmentListeners.getLength() )
        {
            AdjustmentEvent aEvent( rEvent );
            aEvent.Source = *this;
            maAdjustmentListeners.adjustmentValueChanged( aEvent );
        }
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::addAdjustmentListener( const Reference< XAdjustmentListener > & listener ) throw(RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        maAdjustmentListeners.addInterface( listener );
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::removeAdjustmentListener( const Reference< XAdjustmentListener > & listener ) throw(RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        maAdjustmentListeners.removeInterface( listener );
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setValue( sal_Int32 value ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), makeAny( value ), sal_True );
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setValues( sal_Int32 minValue, sal_Int32 maxValue, sal_Int32 currentValue ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MIN ), makeAny( minValue ), sal_True );
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MAX ), makeAny( maxValue ), sal_True );
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), makeAny( currentValue ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getValue(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nValue = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nValue = xSpinnable->getValue();

        return nValue;
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setMinimum( sal_Int32 minValue ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MIN ), makeAny( minValue ), sal_True );
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setMaximum( sal_Int32 maxValue ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MAX ), makeAny( maxValue ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getMinimum(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nMin = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nMin = xSpinnable->getMinimum();

        return nMin;
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getMaximum(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nMax = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nMax = xSpinnable->getMaximum();

        return nMax;
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setSpinIncrement( sal_Int32 spinIncrement ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPININCREMENT ), makeAny( spinIncrement ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getSpinIncrement(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nIncrement = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nIncrement = xSpinnable->getSpinIncrement();

        return nIncrement;
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setOrientation( sal_Int32 orientation ) throw (NoSupportException, RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ORIENTATION ), makeAny( orientation ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getOrientation(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nOrientation = ScrollBarOrientation::HORIZONTAL;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nOrientation = xSpinnable->getOrientation();

        return nOrientation;
    }

//........................................................................
}  // namespace toolkit
//........................................................................

<commit_msg>INTEGRATION: CWS changefileheader (1.5.210); FILE MERGED 2008/04/01 16:00:59 thb 1.5.210.3: #i85898# Stripping all external header guards 2008/04/01 12:56:51 thb 1.5.210.2: #i85898# Stripping all external header guards 2008/03/28 15:40:17 rt 1.5.210.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: tkspinbutton.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_toolkit.hxx"
#include "toolkit/controls/tkspinbutton.hxx"
#include "toolkit/helper/property.hxx"
#include "toolkit/helper/unopropertyarrayhelper.hxx"
#include <com/sun/star/awt/ScrollBarOrientation.hpp>

#include <cppuhelper/typeprovider.hxx>
#include <tools/debug.hxx>

//........................................................................
namespace toolkit
{
//........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::awt;
    using namespace ::com::sun::star::lang;
    using namespace ::com::sun::star::beans;

    //====================================================================
    //= UnoSpinButtonModel
    //====================================================================
    //--------------------------------------------------------------------
    UnoSpinButtonModel::UnoSpinButtonModel()
    {
        ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
        ImplRegisterProperty( BASEPROPERTY_BORDER );
        ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
        ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
        ImplRegisterProperty( BASEPROPERTY_ENABLED );
        ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
        ImplRegisterProperty( BASEPROPERTY_HELPURL );
        ImplRegisterProperty( BASEPROPERTY_ORIENTATION );
        ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
        ImplRegisterProperty( BASEPROPERTY_REPEAT );
        ImplRegisterProperty( BASEPROPERTY_REPEAT_DELAY );
        ImplRegisterProperty( BASEPROPERTY_SYMBOL_COLOR );
        ImplRegisterProperty( BASEPROPERTY_SPINVALUE );
        ImplRegisterProperty( BASEPROPERTY_SPINVALUE_MIN );
        ImplRegisterProperty( BASEPROPERTY_SPINVALUE_MAX );
        ImplRegisterProperty( BASEPROPERTY_SPININCREMENT );
        ImplRegisterProperty( BASEPROPERTY_TABSTOP );
    }

    //--------------------------------------------------------------------
    ::rtl::OUString UnoSpinButtonModel::getServiceName( ) throw (RuntimeException)
    {
        return ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonModel );
    }

    //--------------------------------------------------------------------
    Any UnoSpinButtonModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
    {
        switch ( nPropId )
        {
        case BASEPROPERTY_DEFAULTCONTROL:
            return makeAny( ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonControl ) );

        case BASEPROPERTY_BORDER:
            return makeAny( (sal_Int16) 0 );

        case BASEPROPERTY_REPEAT:
            return makeAny( (sal_Bool)sal_True );

        default:
            return UnoControlModel::ImplGetDefaultValue( nPropId );
        }
    }

    //--------------------------------------------------------------------
    ::cppu::IPropertyArrayHelper& UnoSpinButtonModel::getInfoHelper()
    {
        static UnoPropertyArrayHelper* pHelper = NULL;
        if ( !pHelper )
        {
            Sequence<sal_Int32> aIDs = ImplGetPropertyIds();
            pHelper = new UnoPropertyArrayHelper( aIDs );
        }
        return *pHelper;
    }

    //--------------------------------------------------------------------
    Reference< XPropertySetInfo > UnoSpinButtonModel::getPropertySetInfo(  ) throw(RuntimeException)
    {
        static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
        return xInfo;
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL UnoSpinButtonModel::getImplementationName(  ) throw(RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.toolkit.UnoSpinButtonModel" ) );
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL UnoSpinButtonModel::getSupportedServiceNames() throw(RuntimeException)
    {
        Sequence< ::rtl::OUString > aServices( UnoControlModel::getSupportedServiceNames() );
        aServices.realloc( aServices.getLength() + 1 );
        aServices[ aServices.getLength() - 1 ] = ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonModel );
        return aServices;
    }

    //====================================================================
    //= UnoSpinButtonControl
    //====================================================================
    //--------------------------------------------------------------------
    UnoSpinButtonControl::UnoSpinButtonControl()
        :maAdjustmentListeners( *this )
    {
    }

    //--------------------------------------------------------------------
    ::rtl::OUString UnoSpinButtonControl::GetComponentServiceName()
    {
        return ::rtl::OUString::createFromAscii( "SpinButton" );
    }

    //--------------------------------------------------------------------
    Any UnoSpinButtonControl::queryAggregation( const Type & rType ) throw(RuntimeException)
    {
        Any aRet = UnoControlBase::queryAggregation( rType );
        if ( !aRet.hasValue() )
            aRet = UnoSpinButtonControl_Base::queryInterface( rType );
        return aRet;
    }

    //--------------------------------------------------------------------
    IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoSpinButtonControl, UnoControlBase, UnoSpinButtonControl_Base )

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::dispose() throw(RuntimeException)
    {
        ::osl::ClearableMutexGuard aGuard( GetMutex() );
        if ( maAdjustmentListeners.getLength() )
        {
            Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
            if ( xSpinnable.is() )
                xSpinnable->removeAdjustmentListener( this );

            EventObject aDisposeEvent;
            aDisposeEvent.Source = *this;

            aGuard.clear();
            maAdjustmentListeners.disposeAndClear( aDisposeEvent );
        }

        UnoControl::dispose();
    }

    //--------------------------------------------------------------------
    ::rtl::OUString SAL_CALL UnoSpinButtonControl::getImplementationName(  ) throw(RuntimeException)
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.toolkit.UnoSpinButtonControl" ) );
    }

    //--------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL UnoSpinButtonControl::getSupportedServiceNames() throw(RuntimeException)
    {
        Sequence< ::rtl::OUString > aServices( UnoControlBase::getSupportedServiceNames() );
        aServices.realloc( aServices.getLength() + 1 );
        aServices[ aServices.getLength() - 1 ] = ::rtl::OUString::createFromAscii( szServiceName_UnoSpinButtonControl );
        return aServices;
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer >  & rParentPeer ) throw(RuntimeException)
    {
        UnoControl::createPeer( rxToolkit, rParentPeer );

        Reference < XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            xSpinnable->addAdjustmentListener( this );
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::adjustmentValueChanged( const AdjustmentEvent& rEvent ) throw(RuntimeException)
    {
        switch ( rEvent.Type )
        {
            case AdjustmentType_ADJUST_LINE:
            case AdjustmentType_ADJUST_PAGE:
            case AdjustmentType_ADJUST_ABS:
                ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), makeAny( rEvent.Value ), sal_False );
                break;
            default:
                DBG_ERROR( "UnoSpinButtonControl::adjustmentValueChanged - unknown Type" );
        }

        if ( maAdjustmentListeners.getLength() )
        {
            AdjustmentEvent aEvent( rEvent );
            aEvent.Source = *this;
            maAdjustmentListeners.adjustmentValueChanged( aEvent );
        }
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::addAdjustmentListener( const Reference< XAdjustmentListener > & listener ) throw(RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        maAdjustmentListeners.addInterface( listener );
    }

    //--------------------------------------------------------------------
    void UnoSpinButtonControl::removeAdjustmentListener( const Reference< XAdjustmentListener > & listener ) throw(RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        maAdjustmentListeners.removeInterface( listener );
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setValue( sal_Int32 value ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), makeAny( value ), sal_True );
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setValues( sal_Int32 minValue, sal_Int32 maxValue, sal_Int32 currentValue ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MIN ), makeAny( minValue ), sal_True );
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MAX ), makeAny( maxValue ), sal_True );
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), makeAny( currentValue ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getValue(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nValue = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nValue = xSpinnable->getValue();

        return nValue;
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setMinimum( sal_Int32 minValue ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MIN ), makeAny( minValue ), sal_True );
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setMaximum( sal_Int32 maxValue ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MAX ), makeAny( maxValue ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getMinimum(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nMin = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nMin = xSpinnable->getMinimum();

        return nMin;
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getMaximum(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nMax = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nMax = xSpinnable->getMaximum();

        return nMax;
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setSpinIncrement( sal_Int32 spinIncrement ) throw (RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPININCREMENT ), makeAny( spinIncrement ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getSpinIncrement(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nIncrement = 0;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nIncrement = xSpinnable->getSpinIncrement();

        return nIncrement;
    }

    //--------------------------------------------------------------------
    void SAL_CALL UnoSpinButtonControl::setOrientation( sal_Int32 orientation ) throw (NoSupportException, RuntimeException)
    {
        ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ORIENTATION ), makeAny( orientation ), sal_True );
    }

    //--------------------------------------------------------------------
    sal_Int32 SAL_CALL UnoSpinButtonControl::getOrientation(  ) throw (RuntimeException)
    {
        ::osl::MutexGuard aGuard( GetMutex() );
        sal_Int32 nOrientation = ScrollBarOrientation::HORIZONTAL;

        Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
        if ( xSpinnable.is() )
            nOrientation = xSpinnable->getOrientation();

        return nOrientation;
    }

//........................................................................
}  // namespace toolkit
//........................................................................

<|endoftext|>


<commit_before>
#ifndef AT_TIMER_HPP
#define AT_TIMER_HPP

#include "atNotifier.h++"

class atTimer : public atNotifier
{
   private:

      static atTimer    *systemTimer;

      double            markTime;
      double            markInterval;

   public:

      atTimer();
      ~atTimer();

      void              mark();
      void              markAtInterval(double intervalTime);
      double            getInterval();
      double            getElapsed();
};

#endif
<commit_msg>Removed the systemTimer static member.  This is a concept left over from the vsTimer.<commit_after>
#ifndef AT_TIMER_HPP
#define AT_TIMER_HPP

#include "atNotifier.h++"

class atTimer : public atNotifier
{
   private:

      double            markTime;
      double            markInterval;

   public:

      atTimer();
      ~atTimer();

      void              mark();
      void              markAtInterval(double intervalTime);
      double            getInterval();
      double            getElapsed();
};

#endif
<|endoftext|>


<commit_before>//MIT License
//Copyright 2017 Patrick Laughrea
#include "base64.hpp"

#include <cassert>
#include <stdexcept>

#include "constants.hpp"
#include "various/stringBuilder.hpp"

using namespace std;
using namespace various;
using namespace webss;

static void readBytes(SmartIterator& it, char bytes[4]);
static void writeBytes(char bytes[4]);

static const char* ERROR_EXPECTED = "expected character";

#define DECODE_ALL_0 '+'
#define DECODE_ALL_1 '-'
#define DECODE_NUMBER '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
#define DECODE_UPPER 'Q': case 'W': case 'F': case 'R': case 'K': case 'Y': case 'J': case 'I': case 'O': case 'P': \
	case 'A': case 'S': case 'D': case 'T': case 'G': case 'H': case 'E': case 'U': case 'L': \
	case 'Z': case 'X': case 'C': case 'V': case 'B': case 'N': case 'M'
#define DECODE_LOWER 'q': case 'w': case 'f': case 'r': case 'k': case 'y': case 'j': case 'i': case 'o': case 'p': \
	case 'a': case 's': case 'd': case 't': case 'g': case 'h': case 'e': case 'u': case 'l': \
	case 'z': case 'x': case 'c': case 'v': case 'b': case 'n': case 'm'
#define DECODE_CHAR_1 '_'
#define DECODE_CHAR_2 '='
#define DECODE_IGNORED ' ': case '\x7f': \
	case '\x00': case '\x01': case '\x02': case '\x03': case '\x04': case '\x05': case '\x06': case '\x07': case '\x08': case '\x09': case '\x0a': case '\x0b': case '\x0c': case '\x0d': case '\x0e': case '\x0f': \
	case '\x10': case '\x11': case '\x12': case '\x13': case '\x14': case '\x15': case '\x16': case '\x17': case '\x18': case '\x19': case '\x1a': case '\x1b': case '\x1c': case '\x1d': case '\x1e': case '\x1f'
#define PutThreeBytes(byte) { sb += byte; sb += byte; sb += byte; }

SmartIterator webss::decodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[4];
		int32_t bytesInt;
	};
decodeStart:
	if (!it)
		throw runtime_error(ERROR_EXPECTED);
	switch (*it)
	{
	case CHAR_END_TUPLE:
		return sb.str();
	case DECODE_ALL_0:
		PutThreeBytes('\0')
		goto decodeEnd;
	case DECODE_ALL_1:
		PutThreeBytes('\xff');
		goto decodeEnd;
	case DECODE_IGNORED:
		goto decodeEnd;
	default:
		break;
	}
	readBytes(it, bytes);
	//the 4 bytes: 00111111|00222222|00333333|00112233
	//will become: 11111111|22222222|33333333|00000000
	bytesInt |= (bytesInt & 0x30) << 26;
	bytesInt |= (bytesInt & 0x0c) << 20;
	bytesInt |= (bytesInt & 0x03) << 14;
	bytes[3] = 0;
	sb += bytes;
decodeEnd:
	++it;
	goto decodeStart;
}

static void readBytes(SmartIterator& it, char bytes[4])
{
	int i = 0;
startSwitch:
	switch (*it)
	{
	case DECODE_IGNORED:
		goto restart;
	case DECODE_NUMBER:
		bytes[i] = *it - '0';
		break;
	case DECODE_UPPER:
		bytes[i] = *it - 'A' + 10;
		break;
	case DECODE_LOWER:
		bytes[i] = *it - 'a' + 36;
		break;
	case DECODE_CHAR_1:
		bytes[i] = 62;
		break;
	case DECODE_CHAR_2:
		bytes[i] = 63;
		break;
	default:
		throw runtime_error("forbidden character in encoded binary");
	}
	if (++i == 4)
		return;
restart:
	if (!++it)
		throw runtime_error(ERROR_EXPECTED);
	goto startSwitch;
}

#define ENCODE_NUMBER 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9
#define ENCODE_UPPER 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: \
	case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: \
	case 30: case 31: case 32: case 33: case 34: case 35
#define ENCODE_LOWER 36: case 37: case 38: case 39: \
	case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: \
	case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: \
	case 60: case 61
#define ENCODE_CHAR_1 62
#define ENCODE_CHAR_2 63

#ifndef BASE64_DISABLE_ENCODE_ALL_ZEROS
#ifndef BASE64_DISABLE_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } }
#endif
#else //BASE64_DISABLE_ENCODE_ALL_ZEROS
#ifdef BASE64_DISABLE_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) ;
#endif
#endif //BASE64_DISABLE_ENCODE_ALL_ZEROS

string webss::encodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[5];
		int32_t bytesInt;
	};
	bytes[4] = 0;
encodeStart:
	if (!it)
		return sb;
	bytesInt = 0;
	bytes[0] = *it;
	if (!++it)
	{
		SpecialCheck(0xff000000, return sb)
		goto encodeBytes;
	}
	bytes[1] = *it;
	if (!++it)
	{
		SpecialCheck(0xffff0000, return sb)
		goto encodeBytes;
	}
	bytes[2] = *it;
	SpecialCheck(0xffffff00, ++it; goto encodeStart)
encodeBytes:
	//the 4 bytes: 11111111|22222222|33333333|00000000
	//will become: 00111111|00222222|00333333|00112233
	bytesInt |= (bytesInt & (0xc0 << 24)) >> 26;
	bytesInt |= (bytesInt & (0xc0 << 16)) >> 20;
	bytesInt |= (bytesInt & (0xc0 << 8)) >> 14;
	writeBytes(bytes);
	sb += bytes;
	++it;
	goto encodeStart;
}

static void writeBytes(char bytes[4])
{
	for (int i = 0; i < 4; ++i)
		switch (bytes[i])
		{
		case ENCODE_NUMBER:
			bytes[i] += '0';
			break;
		case ENCODE_UPPER:
			bytes[i] += 'A' - 10;
			break;
		case ENCODE_LOWER:
			bytes[i] += 'a' - 36;
			break;
		case ENCODE_CHAR_1:
			bytes[i] = DECODE_CHAR_1;
			break;
		case ENCODE_CHAR_2:
			bytes[i] = DECODE_CHAR_2;
			break;
		default:
			assert(false); throw domain_error("");
		}
}<commit_msg>Change Base64 values for encoded all 0s and 1s<commit_after>//MIT License
//Copyright 2017 Patrick Laughrea
#include "base64.hpp"

#include <cassert>
#include <stdexcept>

#include "constants.hpp"
#include "various/stringBuilder.hpp"

using namespace std;
using namespace various;
using namespace webss;

static void readBytes(SmartIterator& it, char bytes[4]);
static void writeBytes(char bytes[4]);

static const char* ERROR_EXPECTED = "expected character";

#define DECODE_ALL_0 '_'
#define DECODE_ALL_1 '+'
#define DECODE_NUMBER '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
#define DECODE_UPPER 'Q': case 'W': case 'F': case 'R': case 'K': case 'Y': case 'J': case 'I': case 'O': case 'P': \
	case 'A': case 'S': case 'D': case 'T': case 'G': case 'H': case 'E': case 'U': case 'L': \
	case 'Z': case 'X': case 'C': case 'V': case 'B': case 'N': case 'M'
#define DECODE_LOWER 'q': case 'w': case 'f': case 'r': case 'k': case 'y': case 'j': case 'i': case 'o': case 'p': \
	case 'a': case 's': case 'd': case 't': case 'g': case 'h': case 'e': case 'u': case 'l': \
	case 'z': case 'x': case 'c': case 'v': case 'b': case 'n': case 'm'
#define DECODE_CHAR_1 '-'
#define DECODE_CHAR_2 '='
#define DECODE_IGNORED ' ': case '\x7f': \
	case '\x00': case '\x01': case '\x02': case '\x03': case '\x04': case '\x05': case '\x06': case '\x07': case '\x08': case '\x09': case '\x0a': case '\x0b': case '\x0c': case '\x0d': case '\x0e': case '\x0f': \
	case '\x10': case '\x11': case '\x12': case '\x13': case '\x14': case '\x15': case '\x16': case '\x17': case '\x18': case '\x19': case '\x1a': case '\x1b': case '\x1c': case '\x1d': case '\x1e': case '\x1f'
#define PutThreeBytes(byte) { sb += byte; sb += byte; sb += byte; }

SmartIterator webss::decodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[4];
		int32_t bytesInt;
	};
decodeStart:
	if (!it)
		throw runtime_error(ERROR_EXPECTED);
	switch (*it)
	{
	case CHAR_END_TUPLE:
		return sb.str();
	case DECODE_ALL_0:
		PutThreeBytes('\0')
		goto decodeEnd;
	case DECODE_ALL_1:
		PutThreeBytes('\xff');
		goto decodeEnd;
	case DECODE_IGNORED:
		goto decodeEnd;
	default:
		break;
	}
	readBytes(it, bytes);
	//the 4 bytes: 00111111|00222222|00333333|00112233
	//will become: 11111111|22222222|33333333|00000000
	bytesInt |= (bytesInt & 0x30) << 26;
	bytesInt |= (bytesInt & 0x0c) << 20;
	bytesInt |= (bytesInt & 0x03) << 14;
	bytes[3] = 0;
	sb += bytes;
decodeEnd:
	++it;
	goto decodeStart;
}

static void readBytes(SmartIterator& it, char bytes[4])
{
	int i = 0;
startSwitch:
	switch (*it)
	{
	case DECODE_IGNORED:
		goto restart;
	case DECODE_NUMBER:
		bytes[i] = *it - '0';
		break;
	case DECODE_UPPER:
		bytes[i] = *it - 'A' + 10;
		break;
	case DECODE_LOWER:
		bytes[i] = *it - 'a' + 36;
		break;
	case DECODE_CHAR_1:
		bytes[i] = 62;
		break;
	case DECODE_CHAR_2:
		bytes[i] = 63;
		break;
	default:
		throw runtime_error("forbidden character in encoded binary");
	}
	if (++i == 4)
		return;
restart:
	if (!++it)
		throw runtime_error(ERROR_EXPECTED);
	goto startSwitch;
}

#define ENCODE_NUMBER 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9
#define ENCODE_UPPER 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: \
	case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: \
	case 30: case 31: case 32: case 33: case 34: case 35
#define ENCODE_LOWER 36: case 37: case 38: case 39: \
	case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: \
	case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: \
	case 60: case 61
#define ENCODE_CHAR_1 62
#define ENCODE_CHAR_2 63

#ifndef BASE64_DISABLE_ENCODE_ALL_ZEROS
#ifndef BASE64_DISABLE_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } }
#endif
#else //BASE64_DISABLE_ENCODE_ALL_ZEROS
#ifdef BASE64_DISABLE_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) ;
#endif
#endif //BASE64_DISABLE_ENCODE_ALL_ZEROS

string webss::encodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[5];
		int32_t bytesInt;
	};
	bytes[4] = 0;
encodeStart:
	if (!it)
		return sb;
	bytesInt = 0;
	bytes[0] = *it;
	if (!++it)
	{
		SpecialCheck(0xff000000, return sb)
		goto encodeBytes;
	}
	bytes[1] = *it;
	if (!++it)
	{
		SpecialCheck(0xffff0000, return sb)
		goto encodeBytes;
	}
	bytes[2] = *it;
	SpecialCheck(0xffffff00, ++it; goto encodeStart)
encodeBytes:
	//the 4 bytes: 11111111|22222222|33333333|00000000
	//will become: 00111111|00222222|00333333|00112233
	bytesInt |= (bytesInt & (0xc0 << 24)) >> 26;
	bytesInt |= (bytesInt & (0xc0 << 16)) >> 20;
	bytesInt |= (bytesInt & (0xc0 << 8)) >> 14;
	writeBytes(bytes);
	sb += bytes;
	++it;
	goto encodeStart;
}

static void writeBytes(char bytes[4])
{
	for (int i = 0; i < 4; ++i)
		switch (bytes[i])
		{
		case ENCODE_NUMBER:
			bytes[i] += '0';
			break;
		case ENCODE_UPPER:
			bytes[i] += 'A' - 10;
			break;
		case ENCODE_LOWER:
			bytes[i] += 'a' - 36;
			break;
		case ENCODE_CHAR_1:
			bytes[i] = DECODE_CHAR_1;
			break;
		case ENCODE_CHAR_2:
			bytes[i] = DECODE_CHAR_2;
			break;
		default:
			assert(false); throw domain_error("");
		}
}<|endoftext|>


<commit_before>#include <cstdio>
#include <asmjit/asmjit.h>
#include <vector>
using namespace asmjit;
using namespace asmjit::x86;

int main(int argc, char *argv[]) {
	std::vector<char> cells(256); // construct 256 cells
	JitRuntime runtime;
	X86Compiler c(&runtime);

	cells.assign(256, 0);

	const char code[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.";

	c.addFunc(kFuncConvHost, FuncBuilder1<void, char*>());

	X86GpVar cells_ptr(c, kVarTypeIntPtr, "cells_ptr");
	c.setArg(0, cells_ptr);
	X86GpVar a(c, kVarTypeInt32, "a");
	//X86GpVar b(c, kVarTypeInt32, "b");

	X86GpVar _putchar(c, kVarTypeIntPtr, "_putchar");
	c.mov(_putchar, intptr_t(&putchar));

	for(char ch : code) {
		switch(ch) {
			case '+':
				c.inc(byte_ptr(cells_ptr));
				break;
			case '<':
				c.sub(cells_ptr, 4);
				break;
			case '>':
				c.add(cells_ptr, 4);
				break;
			case '.': {
				c.mov(a, byte_ptr(cells_ptr));
				X86CallNode *call = c.call(_putchar, kX86FuncConvCDecl, FuncBuilder1<int, int>());
				call->setArg(0, a);
				break;
			}
			case '\0':
				break;
			default:
				printf("error: unknown char '%c'\n", ch);
				return 1;
		}
	}

	c.endFunc();

	void* funcPtr = c.make();
	typedef int (*FuncType)(char *ptr);

	// run JITed code
	FuncType func = asmjit_cast<FuncType>(funcPtr);
	func(cells.data());

	runtime.release((void*)func);

	return 0;
}<commit_msg>implement looping<commit_after>#include <cstdio>
#include <asmjit/asmjit.h>
#include <vector>
#include <stack>
using namespace asmjit;
using namespace asmjit::x86;

int main(int argc, char *argv[]) {
	std::vector<char> cells(1024); // construct 256 cells
	std::stack<std::pair<Label, Label>> block_labels;
	JitRuntime runtime;
	X86Compiler c(&runtime);

	cells.assign(1024, 0);

	const char code[] = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";

	c.addFunc(kFuncConvHost, FuncBuilder1<void, char*>());

	X86GpVar cells_ptr(c, kVarTypeIntPtr, "cells_ptr");
	c.setArg(0, cells_ptr);
	X86GpVar a(c, kVarTypeInt8, "a");
	X86GpVar b(c, kVarTypeInt32, "b");

	X86GpVar _putchar(c, kVarTypeIntPtr, "_putchar");
	c.mov(_putchar, intptr_t(&putchar));

	//Label lbl(c);
	//Label lbl2(c);

	for(char ch : code) {
		switch(ch) {
			case '+':
				c.inc(byte_ptr(cells_ptr));
				break;
			case '-':
				c.dec(byte_ptr(cells_ptr));
				break;
			case '<':
				c.dec(cells_ptr);
				break;
			case '>':
				c.inc(cells_ptr);
				break;
			case '.': {
				c.mov(b, byte_ptr(cells_ptr));
				X86CallNode *call = c.call(_putchar, kX86FuncConvCDecl, FuncBuilder1<int, int>());
				call->setArg(0, b);
				break;
			}
			case '[': {
				// a pair of addresses for (start of loop, end of loop)
				block_labels.emplace(std::make_pair(Label(c), Label(c)));
				auto& label_pair = block_labels.top();

				c.bind(label_pair.first);
				c.mov(a, byte_ptr(cells_ptr));
				c.test(a, a);
				c.jz(label_pair.second);
				break;
			}
			case ']': {
				auto& label_pair = block_labels.top();
				block_labels.pop();
				c.jmp(label_pair.first);
				c.bind(label_pair.second); // back-patch the label to refer to here (after the ])
				break;
			}
			case '\0':
				break;
			default:
				printf("error: unknown char '%c'\n", ch);
				return 1;
		}
	}

	c.endFunc();

	void* funcPtr = c.make();
	typedef int (*FuncType)(char *ptr);

	// run JITed code
	FuncType func = asmjit_cast<FuncType>(funcPtr);
	func(cells.data());

	runtime.release((void*)func);

	return 0;
}<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <string>

#include <unistd.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <netdb.h>
#include <cstdlib>
#include <cstring>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"

#include "constants.h"
#include "network.h"
#include "helper_function.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *>, ps_compare> proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void mapPrint(){
  cout << "proc_loc_dict size: "<<proc_loc_dict.size() << endl;
  cout << "Map Print: ";
  for(map<procedure_signature, list<server_info *>, ps_compare> ::const_iterator it = proc_loc_dict.begin();
   it != proc_loc_dict.end(); it++){

    cout << it->first.name << ", " ;
  }

  cout << endl;
}

void roundRobinPrint(){
  cout << "roundRobin Print: ";
  for(list<server_function_info *> ::const_iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    cout << (*it)->ps->name << endl;
  }
}

void registration_request_handler(RegisterRequestMessage * message, int sock){
  const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  cout << "We are trying to register: " << name << endl;

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    proc_loc_dict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    server_function_info * info = new server_function_info(entry, newKey);
    roundRobinList.push_back(info);

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = proc_loc_dict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->socket == sock){
        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        sameLoc = true;
      }
    }

  	if(!sameLoc){ //same procedure different socket
       server_info * new_msg_loc = new server_info(server_identifier, port, sock);
       hostList.push_back(new_msg_loc);
    }
  }

  mapPrint();
  roundRobinPrint();

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
void location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same and argTypes
    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);
      Segment locSuccessSeg = Segment(locSuccessSeg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      //When we have identified the correct procedure_signature use splice and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      break;
 		}
	}

  if(!exist){
    int reasoncode = -5; // Need actual reasoncode
    LocFailureMessage locFailMsg = LocFailureMessage(reasoncode);
    Segment locFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    locFailSeg.send(sock);
  }
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);

    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);

    location_request_handler(lqm, sock);
  }

	return retval;
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main(){

  vector<int> myConnections;
  vector<int> myToRemove;

  // Creates the welcome socket
  int welcomeSocket = createSocket();
  int status = setUpToListen(welcomeSocket);

  cout << "BINDER_ADDRESS " << getHostAddress() << endl;
  cout << "BINDER_PORT " << getSocketPort(welcomeSocket) << endl;

  fd_set readfds;
  int n;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(welcomeSocket, &readfds);

    n = welcomeSocket;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(welcomeSocket, &readfds)) {
        int connectionSocket = acceptConnection(welcomeSocket);

        if (connectionSocket < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          continue;
        }

        myConnections.push_back(connectionSocket);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;

            cout << "Socket iterator" << endl;

          if (FD_ISSET(tempConnection, &readfds)) {

            cout << "We in here" << endl;

            Segment * segment = 0;
            status = Segment::receive(tempConnection, segment);

            //TODO: More sophisticaled error handling/replies
            // Maybe status should be reasonacode instead
            if (status < 0 && segment->getType() == MSG_TYPE_REGISTER_REQUEST) {
                RegisterFailureMessage regFailMsg = RegisterFailureMessage(status);
                Segment regFailSeg = Segment(regFailMsg.getLength(), MSG_TYPE_REGISTER_FAILURE, &regFailMsg);
                regFailSeg.send(tempConnection);
                return status;
            } else if (status < 0 && segment->getType() == MSG_TYPE_LOC_REQUEST) {
                LocFailureMessage locFailMsg = LocFailureMessage(status);
                Segment regFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
                regFailSeg.send(tempConnection);
                return status;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(tempConnection);
              return status;
            }

            request_handler(segment, tempConnection);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        destroySocket(*it);
      }
      myToRemove.clear();
    }
  }

  // Destroys the welcome socket
  destroySocket(welcomeSocket);
}
<commit_msg>code cleanup<commit_after>#include <iostream>
#include <sstream>
#include <string>

#include <unistd.h>
#include <vector>
#include <algorithm>
#include <list>
#include <map>

#include <cstdlib>
#include <cstring>

#include "segment.h"
#include "message.h"
#include "register_success_message.h"
#include "register_failure_message.h"
#include "register_request_message.h"
#include "loc_success_message.h"
#include "loc_failure_message.h"
#include "loc_request_message.h"
#include "terminate_message.h"

#include "constants.h"
#include "network.h"
#include "helper_function.h"

using namespace std;

//TODO:
//MANAGE CLIENT CONNECTION
//MANAGE SERVER CONNECTION
//DATABASE
//ROUND ROBIN

static map<procedure_signature, list<server_info *>, ps_compare> proc_loc_dict;
static list<server_function_info *> roundRobinList;

/*
TODO:
ADD FUNCTION TO MAP
ADD FUNCTION TO ROUND ROBIN
IF FUNCTION EXISTS IN ROUND ROBIN DELETE OLD REPLACE WITH NEW (where)
*/

void mapPrint(){
  cout << "proc_loc_dict size: "<<proc_loc_dict.size() << endl;
  cout << "Map Print: ";
  for(map<procedure_signature, list<server_info *>, ps_compare> ::const_iterator it = proc_loc_dict.begin();
   it != proc_loc_dict.end(); it++){

    cout << it->first.name << ", " ;
  }

  cout << endl;
}

void roundRobinPrint(){
  cout << "roundRobin Print: ";
  for(list<server_function_info *> ::const_iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){
    cout << (*it)->ps->name << endl;
  }
}

void registration_request_handler(RegisterRequestMessage * message, int sock){
  const char * name = message->getName().c_str();
  int * argTypes = message->getArgTypes();
  string server_identifier = message->getServerIdentifier();
  int port = message->getPort();

  cout << "We are trying to register: " << name << endl;

  procedure_signature key(name, argTypes);

  int status = 0;

  //if 'key' dosnt exist in map, add it to the map and round robin
	if (proc_loc_dict.find(key) == proc_loc_dict.end()) {
    //The purpose of this function is so we can have copy of the argTypes that not the original
    int *memArgTypes = copyArgTypes(argTypes);

    key = procedure_signature(name, memArgTypes);
    proc_loc_dict[key] = list<server_info *>();

    //This is bad we shouldn't need a newKey and we should be able to use the key above
    //due to &* reasones I made a variable newKey for the 'info' object
    procedure_signature * newKey = new procedure_signature(name, memArgTypes);
    server_info * entry = new server_info(server_identifier, port, sock);

    //Adding to roundRobinList
    server_function_info * info = new server_function_info(entry, newKey);
    roundRobinList.push_back(info);

  } else {
    bool sameLoc = false;
    list<server_info *> hostList = proc_loc_dict[key];

    for (list<server_info *>::iterator it = hostList.begin(); it != hostList.end(); it++) {
      if((*it)->socket == sock){
        //If they have the same socket, then must be same server_address/port
        //The same procedure signature already exists on the same location
        //TODO: Move to end of round robin or something, maybe we should keep
        sameLoc = true;
      }
    }

  	if(!sameLoc){ //same procedure different socket
       server_info * new_msg_loc = new server_info(server_identifier, port, sock);
       hostList.push_back(new_msg_loc);
    }
  }

  mapPrint();
  roundRobinPrint();

  RegisterSuccessMessage regSuccessMsg = RegisterSuccessMessage(status);
  Segment regSuccessSeg = Segment(regSuccessMsg.getLength(), MSG_TYPE_REGISTER_SUCCESS, &regSuccessMsg);
  regSuccessSeg.send(sock);

}

/*
TODO:
USE ROUND ROBIN TO ACCESS THE CORRECT SERVER/FUNCTION FOR THE CLIENT
*/
void location_request_handler(LocRequestMessage * message, int sock){

  bool exist = false;
	for (list<server_function_info *>::iterator it = roundRobinList.begin(); it != roundRobinList.end(); it++){

    //If the name are the same and argTypes
    if((*it)->ps->name == message->getName() && compareArr((*it)->ps->argTypes, message->getArgTypes() )){
      exist = true;

      LocSuccessMessage locSuccessMsg = LocSuccessMessage((*it)->si->server_identifier, (*it)->si->port);
      Segment locSuccessSeg = Segment(locSuccessSeg.getLength(), MSG_TYPE_LOC_SUCCESS, &locSuccessMsg);
      locSuccessSeg.send(sock);

      //When we have identified the correct procedure_signature use splice and move that service to the end
      roundRobinList.splice(roundRobinList.end(), roundRobinList, it);
      break;
 		}
	}

  if(!exist){
    int reasoncode = -5; // Need actual reasoncode
    LocFailureMessage locFailMsg = LocFailureMessage(reasoncode);
    Segment locFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
    locFailSeg.send(sock);
  }
}

int request_handler(Segment * segment, int sock){
  int retval = 0;
  if(segment->getType() == MSG_TYPE_REGISTER_REQUEST){ //'LOC_REQUEST'
    Message * cast1 = segment->getMessage();
    RegisterRequestMessage * rrm = dynamic_cast<RegisterRequestMessage*>(cast1);

    registration_request_handler(rrm, sock);

  }else if (segment->getType() == MSG_TYPE_LOC_REQUEST){ //'REGISTER'
    Message * cast2 = segment->getMessage();
    LocRequestMessage * lqm = dynamic_cast<LocRequestMessage*>(cast2);

    location_request_handler(lqm, sock);
  }

	return retval;
}

//TODO:
//Create helper functions that can be used for rpcServer.cc
int main() {
  vector<int> myConnections;
  vector<int> myToRemove;

  // Creates the welcome socket
  int welcomeSocket = createSocket();
  int status = setUpToListen(welcomeSocket);

  cout << "BINDER_ADDRESS " << getHostAddress() << endl;
  cout << "BINDER_PORT " << getSocketPort(welcomeSocket) << endl;

  fd_set readfds;
  int n;

  while(true){
    //CONNECTIONS VECTOR
    FD_ZERO(&readfds);
    FD_SET(welcomeSocket, &readfds);

    n = welcomeSocket;

    for (vector<int>::iterator it = myConnections.begin();it != myConnections.end(); ++it) {
      int connection = *it;
      FD_SET(connection, &readfds);
       if (connection > n){
        n = connection;
      }
    }

    n = n+1;

    status = select(n, &readfds, NULL, NULL, NULL);

    if (status == -1) {
      cerr << "ERROR: select failed." << endl;
    } else {

      if (FD_ISSET(welcomeSocket, &readfds)) {
        int connectionSocket = acceptConnection(welcomeSocket);

        if (connectionSocket < 0) {
          cerr << "ERROR: while accepting connection" << endl;
          continue;
        }

        myConnections.push_back(connectionSocket);

      } else {

        for (vector<int>::iterator it = myConnections.begin(); it != myConnections.end(); ++it) {
          int tempConnection = *it;

            cout << "Socket iterator" << endl;

          if (FD_ISSET(tempConnection, &readfds)) {

            cout << "We in here" << endl;

            Segment * segment = 0;
            status = Segment::receive(tempConnection, segment);

            //TODO: More sophisticaled error handling/replies
            // Maybe status should be reasonacode instead
            if (status < 0 && segment->getType() == MSG_TYPE_REGISTER_REQUEST) {
                RegisterFailureMessage regFailMsg = RegisterFailureMessage(status);
                Segment regFailSeg = Segment(regFailMsg.getLength(), MSG_TYPE_REGISTER_FAILURE, &regFailMsg);
                regFailSeg.send(tempConnection);
                return status;
            } else if (status < 0 && segment->getType() == MSG_TYPE_LOC_REQUEST) {
                LocFailureMessage locFailMsg = LocFailureMessage(status);
                Segment regFailSeg = Segment(locFailMsg.getLength(), MSG_TYPE_LOC_FAILURE, &locFailMsg);
                regFailSeg.send(tempConnection);
                return status;
            }

            if (status == 0) {
              // client has closed the connection
              myToRemove.push_back(tempConnection);
              return status;
            }

            request_handler(segment, tempConnection);
          }
        }
      }

      for (vector<int>::iterator it = myToRemove.begin(); it != myToRemove.end(); ++it) {
        myConnections.erase(remove(myConnections.begin(), myConnections.end(), *it), myConnections.end());
        destroySocket(*it);
      }
      myToRemove.clear();
    }
  }

  // Destroys the welcome socket
  destroySocket(welcomeSocket);
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2015 Neil Babson and Gabe Stauth
   This source file is protected under the MIT License.
   Please see the file LICENSE in the distribution for license terms.
*/

/*
   This file contains the implementation of the boardGame class functions
   which control a 9 x 9 Go board.  The main function provides an interface
   to allow a 2 person game to be played.
*/
#include "board.h"
using namespace std;

const bool DEBUG = true;

int main()
{
   char move[3];
   int color = 0;
   gameBoard board;
   bool passFlag = false;

   do
   {
      board.draw();
      cout << "Enter a move (i.e. g3, p=pass, u=undo, q=quit) : ";
      cin.get(move, 10, '\n');
      if (cin.fail())
	 cin.clear();
      cin.ignore(10, '\n');
      if (move[0] == 'u')
	 board.undo();
      else if (move[0] == 'p')
      {
	 if (passFlag)
	    move[0] = 'q';
	 passFlag = true;
      }
      else if (move[0] != 'q')
      {
         if (!board.move((int)move[0] - 96,(int)move[1] - 48, color))
            cout << "Invalid move\n";
	 else
	    passFlag = false;
      }
      color = (color + 1) % 2;
   }
   while (move[0] != 'q');
   return 0;
}

// Constructor
gameBoard::gameBoard()
{
   for (int i = 1; i < 10; ++i)
      for(int j = 1; j < 10; ++j)
	 pieces[i][j].color = 0;
   for (int i = 0; i < 11; ++i)
   {
      pieces[0][i].color = 3;
      pieces[10][i].color = 3;
      pieces[i][0].color = 3;
      pieces[i][10].color = 3;
   }
   history.push(pieces, koFlag, koMove);
   numString = 0;
   dead[0] = dead[1] = 0;
   koFlag = false;
}

void gameBoard::undo()
{
   history.pop(pieces, koFlag, koMove);
   if (undoFlag)
      history.pop(pieces, koFlag, koMove);
   undoFlag = false;
}

// Returns 0 if the player attempts to make an illegal move.
int gameBoard::move(int x, int y, int &color)
{
    if (x < 1 || x > 9 || y < 1 || y > 9)
       return 0;
    if (pieces[x][y].color)
       return 0;
    if (koFlag)
       if (x == koMove[0] && y == koMove[1])
	  return 0;
       else
	  koFlag = false;
    if (!addGroup(x, y, color + 1))
       return 0;

    pieces[x][y].color = color + 1;
    history.push(pieces, koFlag, koMove);
    undoFlag = true;
    return 1;
}

// Displays a game position.
void gameBoard::draw()
{
   cout << "\033[35;7m";
   cout << "  1 2 3 4 5 6 7 8 9  \n ";
   for (int i = 0; i < 20; ++i)
      cout << (char) 128;
   for (int i = 1; i < 10; ++i)
   {
      cout << endl << (char) (i + 96) << (char) 128;
      for (int j = 1; j < 10; ++j)
      {
	 if (pieces[i][j].color == 0)
	    cout << ". ";
	 else if (pieces[i][j].color == 1)
	    cout << "\033[40m0 ";
	 else
	    cout << "\033[47m0\033[40;7m ";
      }
      cout << (char) 128;
   }
   cout << "\n ";
   for (int i = 0; i < 20; ++i)
      cout << (char) 128;
   cout << endl << endl << "\033[0m";
}

// Reset the visited flags
void gameBoard::resetFlags()
{
   for (int i = 1; i < 10; ++i)
      for (int j = 1; j < 10; ++j)
	 pieces[i][j].visited = false;
}

// Checks the neoghbors of a stone that has been played to find out if any groups have died and if the move is legal.
int gameBoard::addGroup(int x, int y, int color)
{
   pieces[x][y].groupNum = ++numString;
   resetFlags();
   pieces[x][y].visited = true;
   return checkNeighbor(x+1, y, color) + checkNeighbor(x-1, y, color) + checkNeighbor(x, y-1, color) + checkNeighbor(x, y+1, color);
}

// Eliminates a dead group.  The location of the first removed piece is saved in the koMove array.
// If only a single stone is killed the goFlag is set to true, and the location stored in koMove
// is an illegal play.
void gameBoard::killGroup(int groupNum, int color)
{
   int deadStones = 0;

   for (int i = 1; i < 10; ++i)
      for (int j = 1; j < 10; ++j)
	 if (pieces[i][j].groupNum == groupNum)
	 {
	    if (!deadStones)
	    {
	       koMove[0] = i;
	       koMove[1] = j;
	    }
	    ++deadStones;
	    pieces[i][j].color = 0;
	 }

   if (deadStones == 1)
      koFlag = true;
   dead[color - 1] += deadStones;
}

// This function searches until it finds a liberty for a group,
// returning 0 if the group is dead.
int gameBoard::checkLiberties(int x, int y, int color)
{
   int liberties;

   if (pieces[x][y].color == 0 && !pieces[x][y].visited)
      return 1;
   if (pieces[x][y].color != color || pieces[x][y].visited)
   {
      pieces[x][y].visited = true;
      return 0;
   }
   pieces[x][y].visited = true;
   liberties = checkLiberties(x-1, y, color);
   if (!liberties)
      liberties = checkLiberties(x+1, y, color);
   if (!liberties)
      liberties = checkLiberties(x, y-1, color);
   if (!liberties)
      liberties = checkLiberties(x, y+1, color);
   return liberties;
}

// Calls checkLiberties to check whether a move killed any of its adjacent groups
// and then calls numberGroup to assign the same group number to all
// connected stones of the same color.
int gameBoard::checkNeighbor(int x, int y, int color)
{
   if (pieces[x][y].color == 0)
      return 1;
   if (!pieces[x][y].visited && color != pieces[x][y].color && pieces[x][y].color != 3)
   {
      if (!checkLiberties(x, y, pieces[x][y].color))
      {
	 killGroup(pieces[x][y].groupNum, pieces[x][y].color);
	 return 1;
      }
      return 0;
   }
   else if (color == pieces[x][y].color)
      return numberGroup(x, y, color);
   return 0;
}

// Recursive function assigns new group number to all stones of a connected group.
// 0 is returned if the group has no liberties, indicating an illegal move.
int gameBoard::numberGroup(int x, int y, int color)
{
   if (pieces[x][y].color == 0)
      return 1;
   if (pieces[x][y].color == 3 || pieces[x][y].visited)
      return 0;
   if (pieces[x][y].color == color)
   {
      pieces[x][y].visited = true;
      pieces[x][y].groupNum = numString;
      return numberGroup(x-1, y, color) + numberGroup(x+1, y, color) + numberGroup(x, y-1, color) + numberGroup(x, y+1, color);
   }
   return 0;
}

<commit_msg>changed so that illegal move does not switch players<commit_after>/*
   Copyright (c) 2015 Neil Babson and Gabe Stauth
   This source file is protected under the MIT License.
   Please see the file LICENSE in the distribution for license terms.
*/

/*
   This file contains the implementation of the boardGame class functions
   which control a 9 x 9 Go board.  The main function provides an interface
   to allow a 2 person game to be played.
*/
#include "board.h"
using namespace std;

const bool DEBUG = true;

int main()
{
   char move[3];
   int color = 0;
   gameBoard board;
   bool passFlag = false;

   do
   {
      board.draw();
      cout << "Enter a move (i.e. g3, p=pass, u=undo, q=quit) : ";
      cin.get(move, 10, '\n');
      if (cin.fail())
	 cin.clear();
      cin.ignore(10, '\n');
      if (move[0] == 'u')
	 board.undo();
      else if (move[0] == 'p')
      {
	 if (passFlag)
	    move[0] = 'q';
	 passFlag = true;
      }
      else if (move[0] != 'q')
      {
	 if (!board.move((int)move[0] - 96,(int)move[1] - 48, color))
	 {
	    cout << "Invalid move\n";
	    color = (color + 1) % 2;
	 }
	 else
	    passFlag = false;
      }
      color = (color + 1) % 2;
   }
   while (move[0] != 'q');
   return 0;
}

// Constructor
gameBoard::gameBoard()
{
   for (int i = 1; i < 10; ++i)
      for(int j = 1; j < 10; ++j)
	 pieces[i][j].color = 0;
   for (int i = 0; i < 11; ++i)
   {
      pieces[0][i].color = 3;
      pieces[10][i].color = 3;
      pieces[i][0].color = 3;
      pieces[i][10].color = 3;
   }
   history.push(pieces, koFlag, koMove);
   numString = 0;
   dead[0] = dead[1] = 0;
   koFlag = false;
}

void gameBoard::undo()
{
   history.pop(pieces, koFlag, koMove);
   if (undoFlag)
      history.pop(pieces, koFlag, koMove);
   undoFlag = false;
}

// Returns 0 if the player attempts to make an illegal move.
int gameBoard::move(int x, int y, int &color)
{
    if (x < 1 || x > 9 || y < 1 || y > 9)
       return 0;
    if (pieces[x][y].color)
       return 0;
    if (koFlag)
       if (x == koMove[0] && y == koMove[1])
	  return 0;
       else
	  koFlag = false;
    if (!addGroup(x, y, color + 1))
       return 0;

    pieces[x][y].color = color + 1;
    history.push(pieces, koFlag, koMove);
    undoFlag = true;
    return 1;
}

// Displays a game position.
void gameBoard::draw()
{
   cout << "\033[35;7m";
   cout << "  1 2 3 4 5 6 7 8 9  \n ";
   for (int i = 0; i < 20; ++i)
      cout << (char) 128;
   for (int i = 1; i < 10; ++i)
   {
      cout << endl << (char) (i + 96) << (char) 128;
      for (int j = 1; j < 10; ++j)
      {
	 if (pieces[i][j].color == 0)
	    cout << ". ";
	 else if (pieces[i][j].color == 1)
	    cout << "\033[40m0 ";
	 else
	    cout << "\033[47m0\033[40;7m ";
      }
      cout << (char) 128;
   }
   cout << "\n ";
   for (int i = 0; i < 20; ++i)
      cout << (char) 128;
   cout << endl << endl << "\033[0m";
}

// Reset the visited flags
void gameBoard::resetFlags()
{
   for (int i = 1; i < 10; ++i)
      for (int j = 1; j < 10; ++j)
	 pieces[i][j].visited = false;
}

// Checks the neoghbors of a stone that has been played to find out if any groups have died and if the move is legal.
int gameBoard::addGroup(int x, int y, int color)
{
   pieces[x][y].groupNum = ++numString;
   resetFlags();
   pieces[x][y].visited = true;
   return checkNeighbor(x+1, y, color) + checkNeighbor(x-1, y, color) + checkNeighbor(x, y-1, color) + checkNeighbor(x, y+1, color);
}

// Eliminates a dead group.  The location of the first removed piece is saved in the koMove array.
// If only a single stone is killed the goFlag is set to true, and the location stored in koMove
// is an illegal play.
void gameBoard::killGroup(int groupNum, int color)
{
   int deadStones = 0;

   for (int i = 1; i < 10; ++i)
      for (int j = 1; j < 10; ++j)
	 if (pieces[i][j].groupNum == groupNum)
	 {
	    if (!deadStones)
	    {
	       koMove[0] = i;
	       koMove[1] = j;
	    }
	    ++deadStones;
	    pieces[i][j].color = 0;
	 }

   if (deadStones == 1)
      koFlag = true;
   dead[color - 1] += deadStones;
}

// This function searches until it finds a liberty for a group,
// returning 0 if the group is dead.
int gameBoard::checkLiberties(int x, int y, int color)
{
   int liberties;

   if (pieces[x][y].color == 0 && !pieces[x][y].visited)
      return 1;
   if (pieces[x][y].color != color || pieces[x][y].visited)
   {
      pieces[x][y].visited = true;
      return 0;
   }
   pieces[x][y].visited = true;
   liberties = checkLiberties(x-1, y, color);
   if (!liberties)
      liberties = checkLiberties(x+1, y, color);
   if (!liberties)
      liberties = checkLiberties(x, y-1, color);
   if (!liberties)
      liberties = checkLiberties(x, y+1, color);
   return liberties;
}

// Calls checkLiberties to check whether a move killed any of its adjacent groups
// and then calls numberGroup to assign the same group number to all
// connected stones of the same color.
int gameBoard::checkNeighbor(int x, int y, int color)
{
   if (pieces[x][y].color == 0)
      return 1;
   if (!pieces[x][y].visited && color != pieces[x][y].color && pieces[x][y].color != 3)
   {
      if (!checkLiberties(x, y, pieces[x][y].color))
      {
	 killGroup(pieces[x][y].groupNum, pieces[x][y].color);
	 return 1;
      }
      return 0;
   }
   else if (color == pieces[x][y].color)
      return numberGroup(x, y, color);
   return 0;
}

// Recursive function assigns new group number to all stones of a connected group.
// 0 is returned if the group has no liberties, indicating an illegal move.
int gameBoard::numberGroup(int x, int y, int color)
{
   if (pieces[x][y].color == 0)
      return 1;
   if (pieces[x][y].color == 3 || pieces[x][y].visited)
      return 0;
   if (pieces[x][y].color == color)
   {
      pieces[x][y].visited = true;
      pieces[x][y].groupNum = numString;
      return numberGroup(x-1, y, color) + numberGroup(x+1, y, color) + numberGroup(x, y-1, color) + numberGroup(x, y+1, color);
   }
   return 0;
}

<|endoftext|>