Малая механизация: 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
Re: Малая механизация: C++, slices
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 05.06.06 03:49
Оценка: 26 (1)
Здравствуйте, c-smile, Вы писали:

CS>Вот slices в стиле D arrays.


Можно использовать iterator_range? Например
boost::sub_range,
boost::iterator_range.

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


...
CS> template <typename T >
CS> struct slice
CS> {
...
CS>    slice(): start(0), length(0) {}
CS>    slice(const T* start_, size_t length_) { start = start_; length = length_; }


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

    // Добавим еще один полезный конструктор. Его можно сделать explicit, по желанию.
    template<std::size_t Size>
    slice(const T (&X)[Size]): start(X), length(Size) {}
...
CS> };
  
// убираем макрос и делаем ему достойную замену:
// #define MAKE_SLICE( T, D ) slice<T>(D, sizeof(D) / sizeof(D[0]))
template<class T, std::size_t Size>
slice<T> make_slice(const T (&X)[Size]) { return slice<T>(X); }


...


// инициализация по новому и по разному:
CS>  //slice<int> s1 = MAKE_SLICE( int, v1 );
CS>  //slice<int> s2 = MAKE_SLICE( int, v2 );
CS>  //slice<int> s3 = MAKE_SLICE( int, v3 );
CS>  //slice<int> s4 = MAKE_SLICE( int, v4 );
CS>  //slice<int> s5 = MAKE_SLICE( int, v5 );
  slice<int> s1(v1); // MAKE_SLICE( int, v1 );
  slice<int> s2 = slice<int>(v2); // MAKE_SLICE( int, v2 );
  slice<int> s3 = make_slice(v3); // MAKE_SLICE( int, v3 );
  slice<int> s4 = v4; // MAKE_SLICE( int, v4 );
  slice<int> s5 = make_slice(v5); // MAKE_SLICE( int, v5 );

  slice<char> c7 = "Hello world!"; // и даже так :-)


...
getboost.codeplex.com
citylizard.codeplex.com
Re[2]: Малая механизация: C++, slices
От: c-smile Канада http://terrainformatica.com
Дата: 07.06.06 06:30
Оценка: 1 (1)
Здравствуйте, sergey_shandar, Вы писали:

_>Здравствуйте, c-smile, Вы писали:


CS>>Вот slices в стиле D arrays.


_>Можно использовать iterator_range? Например

_>boost::sub_range,
_>boost::iterator_range.

...

_> template<std::size_t Size>

_> slice(const T (&X)[Size]): start(X), length(Size) {}[/b]


не пойдет на. eVC4 и VC6

Но все равно спасибо.
Re: Малая механизация: C++, slices
От: _FRED_ Черногория
Дата: 07.06.06 11:00
Оценка:
Здравствуйте, c-smile, Вы писали:
CS> template <typename T >
CS> struct slice
CS> {
…
CS>    slice(): start(0), length(0) {}

       // А почему этот конструктор не такой, как все остальные (в смысле инициализации полей класса)?
       // Так же из-за совместимости с какими-то компиляторами?
CS>    slice(const T* start_, size_t length_) { start = start_; length = length_; }

CS>    slice(const slice& src): start(src.start), length(src.length) {}
CS>    slice(const T* start_, const T* end_): start(start_), length( max(end_-start_,0)) {}
…
... << RSDN@Home 1.2.0 alpha rev. 652>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Малая механизация: C++, slices
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 11.06.06 17:16
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, sergey_shandar, Вы писали:


_>>Здравствуйте, c-smile, Вы писали:


CS>>>Вот slices в стиле D arrays.


_>>Можно использовать iterator_range? Например

_>>boost::sub_range,
_>>boost::iterator_range.

CS>...

Все таки, что по поводу boost::range и подобных? Я не утверждаю что нужно использовать boost::range. Но, инетересно было бы сравнить.

_>> template<std::size_t Size>

_>> slice(const T (&X)[Size]): start(X), length(Size) {}[/b]

CS>не пойдет на. eVC4 и VC6

Жаль. На Digital Mars C тоже не пошло. Ну ниче. Для кривых компиляторов можно попробовать так:
template<std::size_t Size, class T>
slice<T> make_slice(const T *X) { return slice<T>(X, Size); }
#define MAKE_SLICE(D) make_slice<sizeof(D) / sizeof(*D)>(D)
getboost.codeplex.com
citylizard.codeplex.com
Re: Малая механизация: C++, slices
От: vdimas Россия  
Дата: 14.06.06 14:13
Оценка:
Здравствуйте, c-smile, Вы писали:

boost::tokenizer пробовал?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.