2005/5/9

     
 

ByteBuffer.h

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// 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 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/ByteBuffer.h,v 1.6 2005/04/09 19:26:48 kommer Exp $
#ifndef acdk_lang_ByteBuffer_h
#define acdk_lang_ByteBuffer_h

#include <acdk.h>
#include "Number.h"
#include "Comparable.h"

#include "Exception.h"
#include "ClassCastException.h"
#include "NumberFormatException.h"
#include "../locale/Encoding.h"

namespace acdk {
namespace lang {

ACDK_DECL_INTERFACE(ByteBuffer);

/**
  a ByteBuffer holds a a sequence of bytes
*/
class ACDK_CORE_PUBLIC ByteBuffer
      ACDK_INTERFACEBASE
{
  ACDK_WITH_METAINFO(ByteBuffer)
public:
  virtual int length() = 0;
  /**
    for performance reasons the ByteBuffer implementation should support this method
  */
  foreign virtual byte* begin() { THROW0(UnsupportedOperationException); return 0; }
  /**
    for performance reasons the ByteBuffer implementation should support this method
  */
  foreign virtual byte* end() { THROW0(UnsupportedOperationException); return 0; }
  /**
    begin() and end() are supported
  */
  virtual bool supportNativeIterator() { return false; }
  virtual acdk::lang::Object clone() = 0;
};

/**
  defines the Type of ByteBuffer slice
  @see ByteBuffer
*/
enum SliceType
{
  /**
    changes on slices writes also change original buffer
  */
  ShadowSlice      = 0x0000,
  /**
    if a slice will be change, make a copy/clone of the slice
  */
  CopyOnWriteSlice = 0x0001,
  /** create a copy/clone of the slice */
  ClonedSlice      = 0x0002
};
ACDK_DEF_LIB_ENUM(ACDK_CORE_PUBLIC, SliceType);


ACDK_DECL_INTERFACE(ReadByteBuffer);

/**
  a readable ByteBuffer
*/
class ACDK_CORE_PUBLIC ReadByteBuffer
: implements ByteBuffer
{
  ACDK_WITH_METAINFO(ReadByteBuffer)
public:
  /**
    returns the byte from given position
    May throw RuntimeException or ArrayIndexOutOfBoundsException
  */
  virtual byte get(int idx) = 0;
  /**
    creates a slice of this ByteBuffer
  */
  virtual RReadByteBuffer createReadSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice) = 0;
  
};

ACDK_DECL_INTERFACE(WriteByteBuffer);

/**
  a writeable ByteBuffer
*/
class ACDK_CORE_PUBLIC WriteByteBuffer
: implements ByteBuffer
{
  ACDK_WITH_METAINFO(WriteByteBuffer)
public:
  /**
    set the byte at given position
    May throw RuntimeException or ArrayIndexOutOfBoundsException
  */
  virtual void set(int idx, byte t) = 0;
  /**
    creates a slice of this ByteBuffer
  */
  virtual RWriteByteBuffer createWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice) = 0;
};

ACDK_DECL_INTERFACE(ReadWriteByteBuffer);

/**
  A readable and writeable ByteBuffer 
*/
class ACDK_CORE_PUBLIC ReadWriteByteBuffer
: implements ReadByteBuffer
, implements WriteByteBuffer
{
  ACDK_WITH_METAINFO(ReadWriteByteBuffer)
public:
  /**
    creates a slice of this ByteBuffer
  */
  virtual RReadWriteByteBuffer createReadWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice) = 0;
};

ACDK_DECL_INTERFACE(FlexByteBuffer);

/**
  A FlexBuffer can shrink and grow
  The FlexBuffer may also contains 
  an internal limit
*/
class ACDK_CORE_PUBLIC FlexByteBuffer
: implements ReadWriteByteBuffer
{
  ACDK_WITH_METAINFO(FlexByteBuffer)
public:
  /** 
    append the given byte 
  */
  virtual void append(byte t) = 0;
  /** 
    delete byte at given position and return it 
  */
  virtual byte deleteAt(int idx) = 0;
  /** 
    insert a given byte into given position 
  */
  virtual void insertAt(int idx, byte t) = 0;
  /**
    return -1 if this buffer has no write limit
  */
  virtual int limit() = 0;
  /**
    for performance: ensure capacity
  */
  virtual void ensureCapacity(int cap) = 0;
  /**
    set size of buffer
    if new size > as current size use fill byte to fill new elements
  */
  virtual void resize(int size, byte fill = 0) = 0;
  /**
    alias for the append(byte t) method
  */
  virtual void push(byte t) { append(t); }
  /**
    removes the last byte and return it
  */
  virtual byte pop() { return deleteAt(length() - 1); }

};  


ACDK_DECL_CLASS(SlicedReadByteBuffer);
/**
  holds a slice from another ReadByteBuffer
*/
class ACDK_CORE_PUBLIC SlicedReadByteBuffer
: extends acdk::lang::Object
, implements ReadByteBuffer
{
  ACDK_WITH_METAINFO(SlicedReadByteBuffer)
protected:
  /// original byte buffer
  RReadByteBuffer _parent;
  // offset where the slice starts
  int _start;
  // offset where the slice ends
  int _end;
public:
  /**
    creates a slice from given ReadByteBuffer
    with given (absolut) start and end offsets
  */
  SlicedReadByteBuffer(IN(RReadByteBuffer) buf, int start = 0, int end = -1)
  : _parent(buf)
  , _start(start)
  , _end(end == -1 ? buf->length() - start : end)
  {
    if (end >= length())
      THROW0(IndexOutOfBoundsException);
  }
   virtual acdk::lang::Object clone()
  {
    return new SlicedReadByteBuffer((RReadByteBuffer)_parent->clone(), _start, _end);
  }
  virtual int length() { return _end - _start; }
  virtual byte get(int idx) 
  { 
    if (idx < 0 || idx > length())
      THROW0(IndexOutOfBoundsException);
    return _parent->get(idx + _start); 
  }
  virtual RReadByteBuffer createReadSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);
  foreign virtual byte* begin() { return _parent->begin() + _start; }
  foreign virtual byte* end() { return _parent->begin() + _end; }
  virtual bool supportNativeIterator() { return _parent->supportNativeIterator(); }
};

ACDK_DECL_CLASS(SlicedReadWriteByteBuffer);
/**
  holds a slice from another ReadWriteByteBuffer
*/
class ACDK_CORE_PUBLIC SlicedReadWriteByteBuffer
: extends acdk::lang::Object
, implements ReadWriteByteBuffer
{
  ACDK_WITH_METAINFO(SlicedReadWriteByteBuffer)
protected:
  RReadWriteByteBuffer _parent;
  int _start;
  int _end;
  SliceType _sliceType;
public:

  SlicedReadWriteByteBuffer(IN(RReadWriteByteBuffer) buf, int start, int end, SliceType sliceType)
  : _parent(buf)
  , _start(start)
  , _end(end)
  , _sliceType(sliceType)
  {
  }
  virtual acdk::lang::Object clone()
  {
    return new SlicedReadWriteByteBuffer((RReadWriteByteBuffer)_parent->clone(), _start, _end, ClonedSlice);
  }
  virtual int length() { return _end - _start; }
  virtual byte get(int idx) 
  { 
    if (idx < 0 || idx > length())
      THROW0(IndexOutOfBoundsException);

    return _parent->get(idx + _start); 
  }
  virtual void set(int idx, byte t) 
  { 
    if (idx < 0 || idx > length())
      THROW0(IndexOutOfBoundsException);
    if (_sliceType == CopyOnWriteSlice)
    {
      _parent = (RReadWriteByteBuffer)_parent->clone();
      _sliceType = ClonedSlice;
    }
    _parent->set(idx + _start, t);
  }
  virtual RReadByteBuffer createReadSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);
  virtual RWriteByteBuffer createWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);
  virtual RReadWriteByteBuffer createReadWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);
};

/**
  internal helper implements standard methods
  for ByteBuffer, which implements native begin() and end() methods

*/
template <typename T>
class  SimplePtrItBuffer
{
protected:
  T* _begin;
  T* _end;
public:
  SimplePtrItBuffer()
    : _begin(0)
    , _end(0)
  {
  }
  SimplePtrItBuffer(T* begin, T* end)
    : _begin(begin)
    , _end(end)
  {
  }
  int length() { return _end - _begin; }
  T get(int idx) { return *(_begin + idx); }
  void set(int idx, T t)
  {
    *(_begin + idx) = t;
  }
};

ACDK_DECL_CLASS(ArrayReadByteBuffer);

/**
  wrapps a a byteArray as ByteBuffer
*/
class ACDK_CORE_PUBLIC ArrayReadByteBuffer
: extends acdk::lang::Object
, implements ReadByteBuffer
, foreign public SimplePtrItBuffer<byte>
{
  ACDK_WITH_METAINFO(ArrayReadByteBuffer)
protected:
  typedef SimplePtrItBuffer<byte> PtrBufferType;
  RbyteArray _ba;
public:
  /**
    creates a ReadByteBuffer from a byteArray with given absolut
    start and end offsets
  */
  ArrayReadByteBuffer(IN(RbyteArray) ba, int start = 0, int end = -1)
  : _ba(ba)
  {
    _begin = ba->begin() + start;
    if (end == -1)
      end = ba->length() - start;
    _end = _begin + end;
  }
  acdk::lang::Object clone() { return new ArrayReadByteBuffer((RbyteArray)_ba->clone(), startOffset(), endOffset()); }
  int length() { return PtrBufferType::length(); }
  byte get(int idx) { return  PtrBufferType::get(idx); }
  
  virtual RReadByteBuffer createReadSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);

  int startOffset() { return _ba->begin() - _begin; }
  int endOffset() { return startOffset() + length(); }
  foreign virtual byte* begin() { return _begin; }
  foreign virtual byte* end() { return _end; }
  virtual bool supportNativeIterator() { return true; }

  //void set(int idx, byte v) { PtrBufferType::set(idx, v); }
};

ACDK_DECL_CLASS(ArrayReadWriteByteBuffer);
/**
  wrapps a a byteArray as ByteBuffer
*/
class ACDK_CORE_PUBLIC ArrayReadWriteByteBuffer
: extends ArrayReadByteBuffer
, implements ReadWriteByteBuffer
{
  ACDK_WITH_METAINFO(ArrayReadWriteByteBuffer)
public:
  /**
    creates a ReadWriteByteBuffer from a byteArray with given absolut
    start and end offsets
  */
  ArrayReadWriteByteBuffer(IN(RbyteArray) ba, int start = 0, int end = -1)
  : ArrayReadByteBuffer(ba, start, end)
  {
  }
  acdk::lang::Object clone() { return new ArrayReadWriteByteBuffer((RbyteArray)_ba->clone(), startOffset(), endOffset()); }
  void set(int idx, byte v) { PtrBufferType::set(idx, v); }
  virtual RWriteByteBuffer createWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);
  virtual RReadWriteByteBuffer createReadWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);
};


ACDK_DECL_CLASS(CoreByteBuffer);
/**
  CoreByteBuffer is a standard implementation 
  for a FlexByteBuffer
*/
class ACDK_CORE_PUBLIC CoreByteBuffer
: extends acdk::lang::Object
, implements FlexByteBuffer
, implements ReadWriteByteBuffer
{
  ACDK_WITH_METAINFO(CoreByteBuffer)
protected:
  typedef sys::core_vector<byte> VectorType;
  VectorType _array;
public:
  /**
    create a buffer on given size
    element values are undefined
  */
  CoreByteBuffer(int size)
    : _array(size)
  {
  }
  /**
    create a byte buffer on given size and with initial capicity
    the elements are initialized with fillWith byte
  */
  CoreByteBuffer(int size, int initCap, byte fillWith = 0)
    : _array(size, initCap, fillWith)
  {
  }
  /// @internal
  foreign CoreByteBuffer(const VectorType& array)
    : _array(array)
  {
  }
  /// @internal
  foreign CoreByteBuffer(const VectorType& array, int start, int end = -1);
  acdk::lang::Object clone() { return new CoreByteBuffer(_array); }

  foreign virtual byte* begin() { return _array.begin(); }
  foreign virtual byte* end() { return _array.end(); }
  virtual bool supportNativeIterator() { return true; }
  virtual int length() { return _array.size(); }
  byte get(int idx) { return _array[idx]; }
  void set(int idx, byte b) { _array[idx] = b; }
  virtual RReadByteBuffer createReadSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice)
  {
    if (sliceType == ClonedSlice)
      return new CoreByteBuffer(_array, start, end);
    return new SlicedReadByteBuffer(const_cast<CoreByteBuffer*>(this), start, end);
  }
  virtual RWriteByteBuffer createWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice)
  {
    if (sliceType == ClonedSlice)
      return new CoreByteBuffer(_array, start, end);
    return new SlicedReadWriteByteBuffer(const_cast<CoreByteBuffer*>(this), start, end, sliceType);
  }
  virtual RReadWriteByteBuffer createReadWriteSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice)
  {
    if (start == 0 && (end == -1 || end == length()) && sliceType == ShadowSlice)
      return (ReadWriteByteBuffer*)this;
    if (sliceType == ClonedSlice)
      return new CoreByteBuffer(_array, start, end);
    return new SlicedReadWriteByteBuffer(const_cast<CoreByteBuffer*>(this), start, end, sliceType);
  }
  virtual void append(byte t) { _array.push_back(t); }
  virtual byte deleteAt(int idx) { byte t = _array[idx]; _array.erase(_array.begin() + idx); return t; }
  virtual void insertAt(int idx, byte t) { _array.insert(idx, t); }
  virtual int limit() { return -1; }
  virtual void resize(int size, byte fill = 0)  { _array.resize(size, fill); }
  virtual void ensureCapacity(int cap) { _array.ensureCapacity(cap); }
  virtual void push(byte t) { _array.push_back(t); }
  virtual byte pop() { byte t = _array.back(); _array.pop_back(); return t; }
};

ACDK_DECL_CLASS(StringReadByteBuffer);

/**
  This class holds a String, whereas the String::characterClass() must already
  have the correct encoding
*/
class ACDK_CORE_PUBLIC StringReadByteBuffer
: extends acdk::lang::Object
, implements ReadByteBuffer
, foreign public SimplePtrItBuffer<byte>
{ 
  ACDK_WITH_METAINFO(StringReadByteBuffer)
protected:
  RString _str;
  typedef SimplePtrItBuffer<byte> PtrBufferType;
public:
  StringReadByteBuffer(IN(RString) str, int start = 0, int end = -1)
    : _str(str)
  {
    _begin = str->byte_begin() + start;
    if (end == -1)
      end = str->length() - start;
    _end = _begin + end;
  }
  acdk::lang::Object clone() { return new StringReadByteBuffer((RString)_str->clone(), startOffset(), endOffset()); }
  int length() { return PtrBufferType::length(); }
  byte get(int idx) { return  PtrBufferType::get(idx); }
  
  virtual RReadByteBuffer createReadSlice(int start = 0, int end = -1, SliceType sliceType = ShadowSlice);

  int startOffset() { return _str->byte_begin() - _begin; }
  int endOffset() { return startOffset() + length(); }
  foreign virtual byte* begin() { return _begin; }
  foreign virtual byte* end() { return _end; }
  virtual bool supportNativeIterator() { return true; }
  
};

ACDK_DECL_CLASS(Buffers);

/**
  helper methods in connection with ByteBuffers
*/
class ACDK_CORE_PUBLIC Buffers
: extends acdk::lang::Object
{
  ACDK_WITH_METAINFO(Buffers)
public:
  /// internal only
  RString toString() { return Object::toString(); }
  /**
    return a array of hex values
  */
  static RString toString(IN(RByteBuffer) buf);
  /** 
    creates a ReadByteBuffer from given byteArray
  */
  static RReadByteBuffer getReadByteBuffer(IN(RbyteArray) ba);
  /** 
    creates a ReadWriteByteBuffer from given byteArray
  */
  static RReadWriteByteBuffer getReadWriteByteBuffer(IN(RbyteArray) ba, int startIdx = 0, int endIdx = -1);
  /** 
    Converts given ReadByteBuffer to a ReadByteBuffer which supports the native begin() and end() 
    methods. If the given buffer already supports these methods return the given buffer
  */
  static RReadByteBuffer getNativeReadByteBuffer(IN(RReadByteBuffer) buffer);
  /** 
    Converts given WriteByteBuffer to a WriteByteBuffer which supports the native begin() and end() 
    methods. If the given buffer already supports these methods return the given buffer
  */
  static RWriteByteBuffer getNativeWriteByteBuffer(IN(RWriteByteBuffer) buffer);
  /**
    converts the given String to a ReadByteBuffer using the given encoding
  */
  static RReadByteBuffer getReadByteBuffer(IN(RString) str, IN(acdk::locale::REncoding) enc);
  /**
    creates a Reader wrapper from the given ReadByteBuffer
  */
  static acdk::io::RReader getReader(IN(RReadByteBuffer) buffer);
  /**
    creates a Writer wrapper from the given WriteByteBuffer
  */
  static acdk::io::RWriter getWriter(IN(RWriteByteBuffer) buffer);
  /**
    creates a Writer wrapper from the given FlexByteBuffer
  */
  static acdk::io::RWriter getAppendWriter(IN(RFlexByteBuffer) buffer);
  /**
    copy source buffer into target
    stops if source is copied or target is full
    @return count of copied bytes
  */
  static int copyBuffer(IN(RReadByteBuffer) source, IN(RWriteByteBuffer) target);
  /**
    append all bytes from source to buffer
  */
  static void appendBuffer(IN(RReadByteBuffer) source, IN(RFlexByteBuffer) buffer);
};


} // lang
} // acdk


#endif //acdk_lang_ByteBuffer_h