Малая механизация: C++, slices
От: c-smile Канада http://terrainformatica.com
Дата: 04.06.06 07:27
Оценка: 7 (2) +1
Вот slices в стиле D arrays.

Плюс там внизу бонус tokens/tokensz:
  slice token;
  tokens toks( "Hello world", ' ');
  while(toks.next(token))
  {
    // делаем чего-нибудь полезное с token
  }


Вот весь код, успехов.

//|
//|
//| Copyright (c) 2001-2006
//| Andrew Fedoniouk - andrew@terrainformatica.com
//|
//| slices, array fragments
//|
//|


#ifndef __tl_slice_h__
#define __tl_slice_h__

//#include "tl_basic.h"

namespace tool
{

 template <typename T >
 struct slice
 {
    const T* start;
    size_t   length;

    slice(): start(0), length(0) {}
    slice(const T* start_, size_t length_) { start = start_; length = length_; }


    slice(const slice& src): start(src.start), length(src.length) {}
    slice(const T* start_, const T* end_): start(start_), length( max(end_-start_,0)) {}

    slice& operator = (const slice& src) { start = src.start; length = src.length; return *this; }

    const T*      end() const { return start + length; } 

    bool operator == ( const slice& r ) const 
    {  
      if( length != r.length )
        return false;
      for( uint i = 0; i < length; ++i )
        if( start[i] != r.start[i] )
          return false;
      return true;
    }

    bool operator != ( const slice& r ) const { return !operator==(r); }
           
    T operator[] ( uint idx ) const 
    {  
      assert( idx < length );
      if(idx < length)
        return start[idx];
      return 0;
    }

    // [idx1..length)
    slice operator() ( uint idx1 ) const 
    {  
      assert( idx1 < length );
      if ( idx1 < length ) 
          return slice( start + idx1, length - idx1 );
      return slice();
    }
    // [idx1..idx2)
    slice operator() ( uint idx1, uint idx2 ) const 
    {  
      assert( idx1 < length );
      assert( idx2 <= length );
      assert( idx1 <= idx2 );
      if ( idx1 < idx2 ) 
          return slice( start + idx1, idx2 - idx1 );
      return slice();
    }

    int index_of( T e ) const
    {  
      for( uint i = 0; i < length; ++i ) if( start[i] == e ) return i;
      return -1;
    }

    int last_index_of( T e ) const
    {  
      for( uint i = length; i > 0 ;) if( start[--i] == e ) return i;
      return -1;
    }

    int index_of( const slice& s ) const
    {  
      if( s.length > length ) return -1;
      if( s.length == 0 ) return -1;
      uint l = length - s.length;
      for( uint i = 0; i < l ; ++i) 
        if( start[i] == *s.start ) 
        {
          const T* p = s.start;
          uint last = i + s.length;
          for( uint j = i + 1; j < last; ++j ) 
            if( *(++p) != start[j]) 
              goto next_i;
          return i;
          next_i: continue;
        }
      return -1;
    }

    int last_index_of( const slice& s ) const
    {  
      if( s.length > length ) return -1;
      if( s.length == 0 ) return -1;
      const T* ps = s.end() - 1;
      for( uint i = length; i > 0 ; ) 
        if( start[--i] == *ps ) 
        {
          const T* p = ps;
          uint j, first = i - s.length + 1; 
          for( j = i; j > first; ) 
            if( *(--p) != start[--j]) 
              goto next_i;
          return j;
          next_i: continue;
        }
      return -1;
    }


 };
  
#define MAKE_SLICE( T, D ) slice<T>(D, sizeof(D) / sizeof(D[0]))

#ifdef _DEBUG

inline void slice_unittest() 
{
  int v1[] = { 0,1,2,3,4,5,6,7,8,9 };
  int v2[] = { 3,4,5 };
  int v3[] = { 0,1,2 };
  int v4[] = { 0,1,2,4 };
  int v5[] = { 1,1,2,3 };

  slice<int> s1 = MAKE_SLICE( int, v1 );
  slice<int> s2 = MAKE_SLICE( int, v2 );
  slice<int> s3 = MAKE_SLICE( int, v3 );
  slice<int> s4 = MAKE_SLICE( int, v4 );
  slice<int> s5 = MAKE_SLICE( int, v5 );

  assert( s1 != s2 );
  assert( s1(3,6) == s2 );
  assert( s1.index_of(3) == 3 );
  assert( s1.index_of(s2) == 3 );
  assert( s1.last_index_of(3) == 3 );
  assert( s1.last_index_of(s2) == 3 );

  assert( s1.index_of(s3) == 0 );
  assert( s1.last_index_of(s3) == 0 );

  assert( s1.index_of(s4) == -1 );
  assert( s1.last_index_of(s4) == -1 );

  assert( s1.index_of(s5) == -1 );
  assert( s1.last_index_of(s5) == -1 );

}

#endif

 template <typename T >
    class tokens
    {
      T   delimeter;
      const T* p;
      const T* start;
      const T* end;
      const T* tok()
      {
        for(;p && *p; ++p)
          if(*p == delimeter) return p++;
        return p;
      }
    public:

      tokens(const T *text, T separator = ' '): delimeter(separator)
      {
        start = p = text;
        end = tok();
      }
      bool next(slice<T>& v) 
      {  
        if(start && *start)
        {
          v.set(start,end-start);
          start = p; 
          end = tok();
          return true;
        }
        return false;
      }
    };

 template <typename T >
    class tokensz
    {
      T   delimeter;
      const T* p;
      const T* tail;
      const T* start;
      const T* end;
      const T* tok()
      {
        for(;p < tail; ++p)
          if(*p == delimeter) return p++;
        return p;
      }
    public:

      tokensz(const T *text, size_t text_length, T separator = ' '): delimeter(separator)
      {
        start = p = text;
        tail = p + text_length;
        end = tok();
      }
      bool next(slice<T>& v) 
      {  
        if(start < tail)
        {
          v.set(start,end-start);
          start = p; 
          end = tok();
          return true;
        }
        return false;
      }
    };

typedef slice<char> chars;
typedef slice<wchar_t> wchars;

}

#endif
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.