// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_TEMPLATE_I_H
#define OB_TEMPLATE_I_H

// ----------------------------------------------------------------------
// T_var templates
// ----------------------------------------------------------------------

//
// T_var template for fixed-length general data types
//
template<class T>
OBFixVar<T>&
OBFixVar<T>::operator=(T* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, OBNCASelfAssign);
    delete ptr_;
    ptr_ = p;
    return *this;
}

template<class T>
OBFixVar<T>&
OBFixVar<T>::operator=(const OBFixVar<T>& r)
{
    T* newPtr;
    
    if(r.ptr_)
	newPtr = new T(*r.ptr_);
    else
	newPtr = 0;

    if(ptr_)
	delete ptr_;
    
    ptr_ = newPtr;
    
    return *this;
}

//
// T_var template for variable-length general data types
//
template<class T>
OBVarVar<T>&
OBVarVar<T>::operator=(T* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, OBNCASelfAssign);
    delete ptr_;
    ptr_ = p;
    return *this;
}

template<class T>
OBVarVar<T>&
OBVarVar<T>::operator=(const OBVarVar<T>& r)
{
    T* newPtr;
    
    if(r.ptr_)
	newPtr = new T(*r.ptr_);
    else
	newPtr = 0;

    if(ptr_)
	delete ptr_;
    
    ptr_ = newPtr;
    
    return *this;
}

//
// T_var template for sequence types
//
template<class T>
OBSeqVar<T>&
OBSeqVar<T>::operator=(T* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, OBNCASelfAssign);
    delete ptr_;
    ptr_ = p;
    return *this;
}

template<class T>
OBSeqVar<T>&
OBSeqVar<T>::operator=(const OBSeqVar<T>& r)
{
    T* newPtr;
    
    if(r.ptr_)
	newPtr = new T(*r.ptr_);
    else
	newPtr = 0;

    if(ptr_)
	delete ptr_;
    
    ptr_ = newPtr;
    
    return *this;
}

//
// T_var template for fixed-length array types
//
template<class T_slice, class T, CORBA_ULong n>
OBFixArrayVar<T_slice, T, n>::
OBFixArrayVar(const OBFixArrayVar<T_slice, T, n>& r)
{
    if(r.ptr_)
    {
	ptr_ = (T_slice*) new T[n];
	memcpy(ptr_, r.ptr_, n * sizeof(T));
    }
    else
	ptr_ = 0;
}

template<class T_slice, class T, CORBA_ULong n>
OBFixArrayVar<T_slice, T, n>&
OBFixArrayVar<T_slice, T, n>::operator=(T_slice* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, OBNCASelfAssign);
    delete [] (T*) ptr_;
    ptr_ = p;
    return *this;
}

template<class T_slice, class T, CORBA_ULong n>
OBFixArrayVar<T_slice, T, n>&
OBFixArrayVar<T_slice, T, n>::
operator=(const OBFixArrayVar<T_slice, T, n>& r)
{
    if(this != &r)
    {
	delete [] (T*) ptr_;

	if(r.ptr_)
	{
	    ptr_ = (T_slice*) new T[n];
	    memcpy(ptr_, r.ptr_, n * sizeof(T));
	}
	else
	    ptr_ = 0;
    }

    return *this;
}

//
// T_var template for variable-length array types
//
template<class T_slice, class T, CORBA_ULong n>
OBVarArrayVar<T_slice, T, n>::
OBVarArrayVar(const OBVarArrayVar<T_slice, T, n>& r)
{
    if(r.ptr_)
    {
	ptr_ = (T_slice*) new T[n];
 	T* to = (T*) ptr_;
 	T* from = (T*) r.ptr_;
  	for(CORBA_ULong i = 0 ; i < n ; i++)
	    to[i] = from[i];
    }
    else
	ptr_ = 0;
}

template<class T_slice, class T, CORBA_ULong n>
OBVarArrayVar<T_slice, T, n>&
OBVarArrayVar<T_slice, T, n>::operator=(T_slice* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, OBNCASelfAssign);
    delete [] (T*) ptr_;
    ptr_ = p;
    return *this;
}

template<class T_slice, class T, CORBA_ULong n>
OBVarArrayVar<T_slice, T, n>&
OBVarArrayVar<T_slice, T, n>::
operator=(const OBVarArrayVar<T_slice, T, n>& r)
{
    if(this != &r)
    {
	delete [] (T*) ptr_;

	if(r.ptr_)
	{
	    ptr_ = (T_slice*) new T[n];
	    T* to = (T*) ptr_;
	    T* from = (T*) r.ptr_;
	    for(CORBA_ULong i = 0 ; i < n ; i++)
		to[i] = from[i];
	}
	else
	    ptr_ = 0;
    }

    return *this;
}

//
// Template for object reference _var types
//

/* Everything defined as inline */

// ----------------------------------------------------------------------
// Sequences
// ----------------------------------------------------------------------

//
// Template for fixed-length general unbounded sequence type
//
template<class T>
OBFixSeq<T>::OBFixSeq()
    : max_(0), len_(0), off_(0), rel_(true), data_(0)
{
}

template<class T>
OBFixSeq<T>::OBFixSeq(CORBA_ULong m)
    : max_(m), len_(0), off_(0), rel_(true)
{
    if(max_ > 0)
	data_ = allocbuf(off_ + max_);
    else
	data_ = 0;
}

template<class T>
OBFixSeq<T>::OBFixSeq(CORBA_ULong m, CORBA_ULong l, T* d, CORBA_Boolean r)
    : max_(m), len_(l), off_(0), rel_(r)
{
    assert_nca(len_ <= max_, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T>
OBFixSeq<T>::OBFixSeq(const OBFixSeq<T>& r)
    : max_(0), len_(0), off_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T>
OBFixSeq<T>&
OBFixSeq<T>::operator=(const OBFixSeq<T>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	max_ = r.max_;
	off_ = r.off_;
	len_ = r.len_;
	rel_ = true;

	if(off_ + max_ > 0)
	{
	    data_ = allocbuf(off_ + max_);

	    if(len_)
		memcpy(data_ + off_, r.data_ + off_, len_ * sizeof(T));
	}
	else
	    data_ = 0;
    }
    
    return *this;
}

template<class T>
void
OBFixSeq<T>::length(CORBA_ULong newLen)
{
    if(newLen > max_)
    {
	if(rel_ && off_ / 2 >= newLen - max_)
	{
	    CORBA_ULong diff = off_ / 2;
	    off_ -= diff;
	    max_ += diff;

	    if(len_)
		memmove(data_ + off_, data_ + off_ + diff, len_ * sizeof(T));
	}
	else
	{
	    T* old = data_;
	    
	    max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	    data_ = allocbuf(off_ + max_);
	    
	    if(len_)
		memcpy(data_ + off_, old + off_, len_ * sizeof(T));
	    
	    if(rel_)
		freebuf(old);
	    
	    rel_ = true;
	}
    }
    
    len_ = newLen;
}

template<class T>
void
OBFixSeq<T>::insert(const T& r)
{
    if(off_ == 0)
    {
	if(rel_ && (max_ - len_) / 2 >= 1)
	{
	    CORBA_ULong diff = (max_ - len_) / 2;
	    off_ += diff;
	    max_ -= diff;

	    if(len_)
		memmove(data_ + off_, data_ + off_ - diff, len_ * sizeof(T));
	}
	else
	{
	    T* old = data_;
	    
	    off_ = max_ > 1 ? max_ : 1;
	    data_ = allocbuf(off_ + max_);
	    
	    if(len_)
		memcpy(data_ + off_, old, len_ * sizeof(T));
	    
	    if(rel_)
		freebuf(old);
	    
	    rel_ = true;
	}
    }
	
    off_--;
    len_++;
    max_++;

    data_[0 + off_] = r;
}

template<class T>
void
OBFixSeq<T>::append(const T& r)
{
    length(len_ + 1);
    data_[len_ - 1 + off_] = r;
}

template<class T>
void
OBFixSeq<T>::remove(CORBA_ULong n)
{
    assert_nca(n < len_, OBNCASeqRange);

    if(!rel_)
    {
	T* old = data_;
	data_ = allocbuf(off_ + max_);

	if(len_)
	    memcpy(data_ + off_, old + off_, len_ * sizeof(T));

	freebuf(old);
	    
	rel_ = true;
    }
    
    if(n >= len_ / 2)
    {
	if(len_ > 1 + n)
	    memmove(data_ + off_ + n, data_ + off_ + n + 1,
		    (len_ - 1 - n) * sizeof(T));
	
	len_--;
    }
    else
    {
	if(n)
	    memmove(data_ + off_ + 1, data_ + off_, n * sizeof(T));

	off_++;
	len_--;
	max_--;
    }
}

template<class T>
void
OBFixSeq<T>::consume(OBFixSeq<T>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    off_ = r.off_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.max_ = 0;
    r.len_ = 0;
    r.off_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for fixed-length general bounded sequence type
//
template<class T, CORBA_ULong max>
OBBndFixSeq<T, max>::OBBndFixSeq()
    : max_(max), len_(0), rel_(true), data_(0)
{
    data_ = allocbuf(max);
}

template<class T, CORBA_ULong max>
OBBndFixSeq<T, max>::OBBndFixSeq(CORBA_ULong l, T* d, CORBA_Boolean r)
    : max_(l), len_(l), rel_(r)
{
    assert_nca(len_ <= max, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T, CORBA_ULong max>
OBBndFixSeq<T, max>::OBBndFixSeq(const OBBndFixSeq<T, max>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T, CORBA_ULong max>
OBBndFixSeq<T, max>&
OBBndFixSeq<T, max>::operator=(const OBBndFixSeq<T, max>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);

	len_ = r.len_;
	rel_ = true;

	max_ = max;
	data_ = allocbuf(max);

	if(len_)
	    memcpy(data_, r.data_, len_ * sizeof(T));
    }
    
    return *this;
}

template<class T, CORBA_ULong max>
void
OBBndFixSeq<T, max>::length(CORBA_ULong newLen)
{
    assert_nca(newLen <= max, OBNCASeqLenGrMax);
    if(newLen > max_)
    {
	T* old = data_;

	max_ = max;
	data_ = allocbuf(max);

	if(len_)
	    memcpy(data_, old, len_ * sizeof(T));

	if(rel_)
	    freebuf(old);

	rel_ = true;
    }

    len_ = newLen;
}

template<class T, CORBA_ULong max>
void
OBBndFixSeq<T, max>::consume(OBBndFixSeq<T, max>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for variable-length general unbounded sequence type
//
template<class T>
OBVarSeq<T>::OBVarSeq()
    : max_(0), len_(0), off_(0), rel_(true), data_(0)
{
}

template<class T>
OBVarSeq<T>::OBVarSeq(CORBA_ULong m)
    : max_(m), len_(0), off_(0), rel_(true)
{
    if(max_ > 0)
	data_ = allocbuf(off_ + max_);
    else
	data_ = 0;
}

template<class T>
OBVarSeq<T>::OBVarSeq(CORBA_ULong m, CORBA_ULong l, T* d, CORBA_Boolean r)
    : max_(m), len_(l), off_(0), rel_(r)
{
    assert_nca(len_ <= max_, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T>
OBVarSeq<T>::OBVarSeq(const OBVarSeq<T>& r)
    : max_(0), len_(0), off_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T>
OBVarSeq<T>&
OBVarSeq<T>::operator=(const OBVarSeq<T>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	max_ = r.max_;
	off_ = r.off_;
	len_ = r.len_;
	rel_ = true;

	if(off_ + max_ > 0)
	    data_ = allocbuf(off_ + max_);
	else
	    data_ = 0;

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    data_[i + off_] = r.data_[i + off_];
    }
    
    return *this;
}

template<class T>
void
OBVarSeq<T>::length(CORBA_ULong newLen)
{
    if(newLen < len_ && rel_)
    {
 	for(CORBA_ULong i = newLen ; i < len_ ; i++)
 	    data_[i + off_] = T();
    }
    else if(newLen > max_)
    {
	if(rel_ && off_ / 2 >= newLen - max_)
	{
	    CORBA_ULong diff = off_ / 2;
	    off_ -= diff;
	    max_ += diff;

	    CORBA_ULong i;

	    for(i = 0 ; i < len_ ; i++)
		data_[i + off_] = data_[i + off_ + diff];

 	    for(i = 0 ; i < diff ; i++)
 		data_[i + off_ + len_] = T();
	}
	else
	{
	    T* old = data_;
	    
	    max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	    data_ = allocbuf(off_ + max_);
	    
	    for(CORBA_ULong i = 0 ; i < len_ ; i++)
		data_[i + off_] = old[i + off_];
	    
	    if(rel_)
		freebuf(old);
	    
	    rel_ = true;
	}
    }
    
    len_ = newLen;
}

template<class T>
void
OBVarSeq<T>::insert(const T& r)
{
    if(off_ == 0)
    {
	if(rel_ && (max_ - len_) / 2 >= 1)
	{
	    CORBA_ULong diff = (max_ - len_) / 2;
	    off_ += diff;
	    max_ -= diff;

	    CORBA_ULong i;

 	    for(i = len_ ; i > 0 ; i--)
		data_[i - 1 + off_] = data_[i - 1 + off_ - diff];

 	    for(i = 0 ; i < diff ; i++)
 		data_[i + off_ - diff] = T();
	}
	else
	{
	    T* old = data_;
	    
	    off_ = max_ > 1 ? max_ : 1;
	    data_ = allocbuf(off_ + max_);
	    
	    for(CORBA_ULong i = 0 ; i < len_ ; i++)
		data_[i + off_] = old[i];
	    
	    if(rel_)
		freebuf(old);
	    
	    rel_ = true;
	}
    }
	
    off_--;
    len_++;
    max_++;

    data_[0 + off_] = r;
}

template<class T>
void
OBVarSeq<T>::append(const T& r)
{
    length(len_ + 1);
    data_[len_ - 1 + off_] = r;
}

template<class T>
void
OBVarSeq<T>::remove(CORBA_ULong n)
{
    assert_nca(n < len_, OBNCASeqRange);

    if(!rel_)
    {
	T* old = data_;
	data_ = allocbuf(off_ + max_);
	    
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    data_[i + off_] = old[i + off_];

	freebuf(old);
	    
	rel_ = true;
    }
    
    if(n >= len_ / 2)
    {
	for(CORBA_ULong i = n ; i < len_ - 1; i++)
	    data_[i + off_] = data_[i + 1 + off_];

 	data_[len_ - 1 + off_] = T();
	
	len_--;
    }
    else
    {
	for(CORBA_ULong i = n ; i > 0 ; i--)
	    data_[i + off_] = data_[i - 1 + off_];
	
 	data_[0 + off_] = T();

	off_++;
	len_--;
	max_--;
    }
}

template<class T>
void
OBVarSeq<T>::consume(OBVarSeq<T>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    off_ = r.off_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.max_ = 0;
    r.len_ = 0;
    r.off_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for variable-length general bounded sequence type
//
template<class T, CORBA_ULong max>
OBBndVarSeq<T, max>::OBBndVarSeq()
    : max_(max), len_(0), rel_(true), data_(0)
{
    data_ = allocbuf(max);
}

template<class T, CORBA_ULong max>
OBBndVarSeq<T, max>::OBBndVarSeq(CORBA_ULong l, T* d, CORBA_Boolean r)
    : max_(l), len_(l), rel_(r)
{
    assert_nca(len_ <= max, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T, CORBA_ULong max>
OBBndVarSeq<T, max>::OBBndVarSeq(const OBBndVarSeq<T, max>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T, CORBA_ULong max>
OBBndVarSeq<T, max>&
OBBndVarSeq<T, max>::operator=(const OBBndVarSeq<T, max>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	max_ = max;
	data_ = allocbuf(max);

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    data_[i] = r.data_[i];
    }
    
    return *this;
}

template<class T, CORBA_ULong max>
void
OBBndVarSeq<T, max>::length(CORBA_ULong newLen)
{
    assert_nca(newLen <= max, OBNCASeqLenGrMax);

    if(newLen < len_ && rel_)
    {
 	for(CORBA_ULong i = newLen ; i < len_ ; i++)
 	    data_[i] = T();
    }
    else if(newLen > max_)
    {
	T* old = data_;

	max_ = max;
	data_ = allocbuf(max);

	for(CORBA_ULong i = 0 ; i < len_; i++)
	    data_[i] = old[i];

	if(rel_)
	    freebuf(old);

	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T, CORBA_ULong max>
void
OBBndVarSeq<T, max>::consume(OBBndVarSeq<T, max>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = max;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for fixed-length array unbounded sequence type
//
template<class T_slice, class T, CORBA_ULong n>
T_slice**
OBFixArraySeq<T_slice, T, n>::allocbuf(CORBA_ULong nn)
{
    T_slice** p = (T_slice**) OBAlloc(sizeof(T_slice*), nn);
    
    for(CORBA_ULong i = 0 ; i < nn ; i++)
	p[i] = (T_slice*) new T[n];

    return p;
}

template<class T_slice, class T, CORBA_ULong n>
void
OBFixArraySeq<T_slice, T, n>::freebuf(T_slice** p)
{
    if(p)
    {
	CORBA_ULong nn = OBAllocated(p);
	
	for(CORBA_ULong i = 0 ; i < nn ; i++)
	    delete [] (T*) p[i];

	OBFree(p);
    }
}

template<class T_slice, class T, CORBA_ULong n>
OBFixArraySeq<T_slice, T, n>::OBFixArraySeq()
    : max_(0), len_(0), rel_(true), data_(0)
{
}

template<class T_slice, class T, CORBA_ULong n>
OBFixArraySeq<T_slice, T, n>::OBFixArraySeq(CORBA_ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
	data_ = allocbuf(max_);
    else
	data_ = 0;
}

template<class T_slice, class T, CORBA_ULong n>
OBFixArraySeq<T_slice, T, n>::
OBFixArraySeq(CORBA_ULong m, CORBA_ULong l, T_slice** d, CORBA_Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T_slice, class T, CORBA_ULong n>
OBFixArraySeq<T_slice, T, n>::
OBFixArraySeq(const OBFixArraySeq<T_slice, T, n>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_slice, class T, CORBA_ULong n>
OBFixArraySeq<T_slice, T, n>&
OBFixArraySeq<T_slice, T, n>::operator=(const OBFixArraySeq<T_slice, T, n>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	max_ = r.max_;
	len_ = r.len_;
	rel_ = true;

	if(max_ > 0)
	    data_ = allocbuf(max_);
	else
	    data_ = 0;

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    memcpy(data_[i], r.data_[i], n * sizeof(T));
    }
    
    return *this;
}

template<class T_slice, class T, CORBA_ULong n>
void
OBFixArraySeq<T_slice, T, n>::length(CORBA_ULong newLen)
{
    if(newLen > max_)
    {
	T_slice** old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    memcpy(data_[i], old[i], n * sizeof(T));
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T_slice, class T, CORBA_ULong n>
void
OBFixArraySeq<T_slice, T, n>::consume(OBFixArraySeq<T_slice, T, n>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.max_ = 0;
    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for fixed-length array bounded sequence type
//
template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
T_slice**
OBBndFixArraySeq<T_slice, T, n, max>::allocbuf(CORBA_ULong nn)
{
    T_slice** p = (T_slice**) OBAlloc(sizeof(T_slice*), nn);
    
    for(CORBA_ULong i = 0 ; i < nn ; i++)
	p[i] = (T_slice*) new T[n];

    return p;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
void
OBBndFixArraySeq<T_slice, T, n, max>::freebuf(T_slice** p)
{
    if(p)
    {
	CORBA_ULong num = OBAllocated(p);
	
	for(CORBA_ULong i = 0 ; i < num ; i++)
	    delete [] (T*) p[i];

	OBFree(p);
    }
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndFixArraySeq<T_slice, T, n, max>::OBBndFixArraySeq()
    : max_(max), len_(0), rel_(true), data_(0)
{
    data_ = allocbuf(max);
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndFixArraySeq<T_slice, T, n, max>::OBBndFixArraySeq(CORBA_ULong l, T_slice** d, CORBA_Boolean r)
    : max_(l), len_(l), rel_(r)
{
    assert_nca(len_ <= max, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndFixArraySeq<T_slice, T, n, max>::OBBndFixArraySeq(const OBBndFixArraySeq<T_slice, T, n, max>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndFixArraySeq<T_slice, T, n, max>&
OBBndFixArraySeq<T_slice, T, n, max>::
operator=(const OBBndFixArraySeq<T_slice, T, n, max>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	max_ = max;
	data_ = allocbuf(max);

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    memcpy(data_[i], r.data_[i], n * sizeof(T));
    }
    
    return *this;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
void
OBBndFixArraySeq<T_slice, T, n, max>::length(CORBA_ULong newLen)
{
    assert_nca(newLen <= max, OBNCASeqLenGrMax);

    if(newLen > max_)
    {
	T_slice** old = data_;

	max_ = max;
	data_ = allocbuf(max_);
	
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    memcpy(data_[i], old[i], n * sizeof(T));
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }

    len_ = newLen;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
void
OBBndFixArraySeq<T_slice, T, n, max>::
consume(OBBndFixArraySeq<T_slice, T, n, max>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for variable-length array unbounded sequence type
//
template<class T_slice, class T, CORBA_ULong n>
T_slice**
OBVarArraySeq<T_slice, T, n>::allocbuf(CORBA_ULong nn)
{
    T_slice** p = (T_slice**) OBAlloc(sizeof(T_slice*), nn);
    
    for(CORBA_ULong i = 0 ; i < nn ; i++)
	p[i] = (T_slice*) new T[n];

    return p;
}

template<class T_slice, class T, CORBA_ULong n>
void
OBVarArraySeq<T_slice, T, n>::freebuf(T_slice** p)
{
    if(p)
    {
	CORBA_ULong nn = OBAllocated(p);
	
	for(CORBA_ULong i = 0 ; i < nn ; i++)
	    delete [] (T*) p[i];

	OBFree(p);
    }
}

template<class T_slice, class T, CORBA_ULong n>
OBVarArraySeq<T_slice, T, n>::OBVarArraySeq()
    : max_(0), len_(0), rel_(true), data_(0)
{
}

template<class T_slice, class T, CORBA_ULong n>
OBVarArraySeq<T_slice, T, n>::OBVarArraySeq(CORBA_ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
	data_ = allocbuf(max_);
    else
	data_ = 0;
}

template<class T_slice, class T, CORBA_ULong n>
OBVarArraySeq<T_slice, T, n>::OBVarArraySeq(CORBA_ULong m, CORBA_ULong l, T_slice** d, CORBA_Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T_slice, class T, CORBA_ULong n>
OBVarArraySeq<T_slice, T, n>::OBVarArraySeq(const OBVarArraySeq<T_slice, T, n>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_slice, class T, CORBA_ULong n>
OBVarArraySeq<T_slice, T, n>&
OBVarArraySeq<T_slice, T, n>::operator=(const OBVarArraySeq<T_slice, T, n>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	max_ = r.max_;
	len_ = r.len_;
	rel_ = true;

	if(max_ > 0)
	    data_ = allocbuf(max_);
	else
	    data_ = 0;

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    T* to = (T*) data_[i];
	    T* from = (T*) r.data_[i];
	    for(CORBA_ULong j = 0 ; j < n ; j++)
		to[j] = from[j];
	}
    }
    
    return *this;
}

template<class T_slice, class T, CORBA_ULong n>
void
OBVarArraySeq<T_slice, T, n>::length(CORBA_ULong newLen)
{
    if(newLen < len_ && rel_)
    {
 	for(CORBA_ULong i = newLen ; i < len_ ; i++)
	{
	    T* p = (T*) data_[i];
	    for(CORBA_ULong j = 0 ; j < n ; j++)
		p[j] = T();
	}
    }
    else if(newLen > max_)
    {
	T_slice** old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    T* to = (T*) data_[i];
	    T* from = (T*) old[i];
	    for(CORBA_ULong j = 0 ; j < n ; j++)
		to[j] = from[j];
	}
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T_slice, class T, CORBA_ULong n>
void
OBVarArraySeq<T_slice, T, n>::consume(OBVarArraySeq<T_slice, T, n>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.max_ = 0;
    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for variable-length array bounded sequence type
//
template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
T_slice**
OBBndVarArraySeq<T_slice, T, n, max>::allocbuf(CORBA_ULong nn)
{
    T_slice** p = (T_slice**) OBAlloc(sizeof(T_slice*), nn);
    
    for(CORBA_ULong i = 0 ; i < nn ; i++)
	p[i] = (T_slice*) new T[n];

    return p;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
void
OBBndVarArraySeq<T_slice, T, n, max>::freebuf(T_slice** p)
{
    if(p)
    {
	CORBA_ULong num = OBAllocated(p);
	
	for(CORBA_ULong i = 0 ; i < num ; i++)
	    delete [] (T*) p[i];

	OBFree(p);
    }
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndVarArraySeq<T_slice, T, n, max>::OBBndVarArraySeq()
    : max_(max), len_(0), rel_(true), data_(0)
{
    data_ = allocbuf(max);
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndVarArraySeq<T_slice, T, n, max>::
OBBndVarArraySeq(CORBA_ULong l, T_slice** d, CORBA_Boolean r)
    : max_(l), len_(l), rel_(r)
{
    assert_nca(len_ <= max, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndVarArraySeq<T_slice, T, n, max>::
OBBndVarArraySeq(const OBBndVarArraySeq<T_slice, T, n, max>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
OBBndVarArraySeq<T_slice, T, n, max>&
OBBndVarArraySeq<T_slice, T, n, max>::
operator=(const OBBndVarArraySeq<T_slice, T, n, max>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	max_ = max;
	data_ = allocbuf(max);

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    T* to = (T*) data_[i];
	    T* from = (T*) r.data_[i];
	    for(CORBA_ULong j = 0 ; j < n ; j++)
		to[j] = from[j];
	}
    }
    
    return *this;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
void
OBBndVarArraySeq<T_slice, T, n, max>::length(CORBA_ULong newLen)
{
    assert_nca(newLen <= max, OBNCASeqLenGrMax);

    if(newLen < len_ && rel_)
    {
 	for(CORBA_ULong i = newLen ; i < len_ ; i++)
	{
	    T* p = (T*) data_[i];
	    for(CORBA_ULong j = 0 ; j < n ; j++)
		p[j] = T();
	}
    }
    else if(newLen > max_)
    {
	T_slice** old = data_;

	max_ = max;
	data_ = allocbuf(max);
	
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    T* to = (T*) data_[i];
	    T* from = (T*) old[i];
	    for(CORBA_ULong j = 0 ; j < n ; j++)
		to[j] = from[j];
	}
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T_slice, class T, CORBA_ULong n, CORBA_ULong max>
void
OBBndVarArraySeq<T_slice, T, n, max>::
consume(OBBndVarArraySeq<T_slice, T, n, max>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for unbounded object reference sequence type
//
template<class T>
T**
OBObjSeq<T>::allocbuf(CORBA_ULong n)
{
    T** p = (T**) OBAlloc(sizeof(T*), n);
    
    for(CORBA_ULong i = 0 ; i < n ; i++)
	p[i] = 0;

    return p;
}

template<class T>
void
OBObjSeq<T>::freebuf(T** p)
{
    if(p)
    {
	CORBA_ULong n = OBAllocated(p);
	
	for(CORBA_ULong i = 0 ; i < n ; i++)
	    OBRelease(p[i]);

	OBFree(p);
    }
}

template<class T>
OBObjSeq<T>::OBObjSeq()
    : max_(0), len_(0), off_(0), rel_(true), data_(0)
{
}

template<class T>
OBObjSeq<T>::OBObjSeq(CORBA_ULong m)
    : max_(m), len_(0), off_(0), rel_(true)
{
    if(off_ + max_ > 0)
	data_ = allocbuf(off_ + max_);
    else
	data_ = 0;
}

template<class T>
OBObjSeq<T>::OBObjSeq(CORBA_ULong m, CORBA_ULong l, T** d, CORBA_Boolean r)
    : max_(m), len_(l), off_(0), rel_(r)
{
    assert_nca(len_ <= max_, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T>
OBObjSeq<T>::OBObjSeq(const OBObjSeq<T>& r)
    : max_(0), len_(0), off_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T>
OBObjSeq<T>&
OBObjSeq<T>::operator=(const OBObjSeq<T>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	max_ = r.max_;
	off_ = r.off_;
	len_ = r.len_;
	rel_ = true;

	if(off_ + max_ > 0)
	    data_ = allocbuf(off_ + max_);
	else
	    data_ = 0;

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    data_[i + off_] = r.data_[i + off_];
	    OBDuplicate(data_[i + off_]);
	}
    }

    return *this;
}

template<class T>
void
OBObjSeq<T>::length(CORBA_ULong newLen)
{
    if(newLen < len_ && rel_)
    {
	for(CORBA_ULong i = newLen ; i < len_ ; i++)
	{
	    OBRelease(data_[i + off_]);
	    data_[i + off_] = 0;
	}
    }
    else if(newLen > max_)
    {
	if(rel_ && off_ / 2 >= newLen - max_)
	{
	    CORBA_ULong diff = off_ / 2;
	    off_ -= diff;
	    max_ += diff;

	    CORBA_ULong i;

	    for(i = 0 ; i < len_ ; i++)
		data_[i + off_] = data_[i + off_ + diff];

	    for(i = 0 ; i < diff ; i++)
		data_[i + off_ + len_] = 0;
	}
	else
	{
	    T** old = data_;
	    
	    max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	    data_ = allocbuf(off_ + max_);
	    
	    for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    {
		if(rel_)
		{
		    data_[i + off_] = old[i + off_];
		    old[i + off_] = 0;
		}
		else
		{
		    data_[i + off_] = old[i + off_];
		    OBDuplicate(data_[i + off_]);
		}
	    }
	    
	    if(rel_)
		freebuf(old);
	    
	    rel_ = true;
	}
    }
    
    len_ = newLen;
}

template<class T>
void
OBObjSeq<T>::insert(T* r)
{
    if(off_ == 0)
    {
	if(rel_ && (max_ - len_) / 2 >= 1)
	{
	    CORBA_ULong diff = (max_ - len_) / 2;
	    off_ += diff;
	    max_ -= diff;

	    CORBA_ULong i;

	    for(i = len_ ; i > 0 ; i--)
		data_[i - 1 + off_] = data_[i - 1 + off_ - diff];

	    for(i = 0 ; i < diff ; i++)
		data_[i + off_ - diff] = 0;
	}
	else
	{
	    T** old = data_;
	    
	    off_ = max_ > 1 ? max_ : 1;
	    data_ = allocbuf(off_ + max_);
	    
	    for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    {
		if(rel_)
		{
		    data_[i + off_] = old[i];
		    old[i] = 0;
		}
		else
		{
		    data_[i + off_] = old[i];
		    OBDuplicate(data_[i + off_]);
		}
	    }
	    
	    if(rel_)
		freebuf(old);
	    
	    rel_ = true;
	}
    }
	
    off_--;
    len_++;
    max_++;

    data_[0 + off_] = r;
}

template<class T>
void
OBObjSeq<T>::insert(const OBObjVar<T>& r)
{
    OBDuplicate(r.in());
    insert(r.in());
}

template<class T>
void
OBObjSeq<T>::insert(const OBObjForSeq<T>& r)
{
    OBDuplicate(r.in());
    insert(r.in());
}

template<class T>
void
OBObjSeq<T>::append(T* r)
{
    length(len_ + 1);
    data_[len_ - 1 + off_] = r;
}

template<class T>
void
OBObjSeq<T>::append(const OBObjVar<T>& r)
{
    OBDuplicate(r.in());
    append(r.in());
}

template<class T>
void
OBObjSeq<T>::append(const OBObjForSeq<T>& r)
{
    OBDuplicate(r.in());
    append(r.in());
}

template<class T>
void
OBObjSeq<T>::remove(CORBA_ULong n)
{
    assert_nca(n < len_, OBNCASeqRange);

    if(!rel_)
    {
	T** old = data_;
	data_ = allocbuf(off_ + max_);
	    
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    data_[i + off_] = old[i + off_];
	    old[i + off_] = 0;
	}

	freebuf(old);
	    
	rel_ = true;
    }

    OBRelease(data_[n + off_]);
    
    if(n >= len_ / 2)
    {
	for(CORBA_ULong i = n ; i < len_ - 1 ; i++)
	    data_[i + off_] = data_[i + 1 + off_];
	
	data_[len_ - 1 + off_] = 0;
	
	len_--;
    }
    else
    {
	for(CORBA_ULong i = n ; i > 0 ; i--)
	    data_[i + off_] = data_[i - 1 + off_];
	
	data_[0 + off_] = 0;
	
	off_++;
	len_--;
	max_--;
    }
}

template<class T>
void
OBObjSeq<T>::consume(OBObjSeq<T>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    off_ = r.off_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.max_ = 0;
    r.len_ = 0;
    r.off_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

//
// Template for bounded object reference sequence type
//
template<class T, CORBA_ULong max>
T**
OBBndObjSeq<T, max>::allocbuf(CORBA_ULong n)
{
    T** p = (T**) OBAlloc(sizeof(T*), n);
    
    for(CORBA_ULong i = 0 ; i < n ; i++)
	p[i] = 0;

    return p;
}

template<class T, CORBA_ULong max>
void
OBBndObjSeq<T, max>::freebuf(T** p)
{
    if(p)
    {
	CORBA_ULong n = OBAllocated(p);
	
	for(CORBA_ULong i = 0 ; i < n ; i++)
	    OBRelease(p[i]);

	OBFree(p);
    }
}

template<class T, CORBA_ULong max>
OBBndObjSeq<T, max>::OBBndObjSeq()
    : max_(max), len_(0), rel_(true)
{
    data_ = allocbuf(max);
}

template<class T, CORBA_ULong max>
OBBndObjSeq<T, max>
::OBBndObjSeq(CORBA_ULong l, T** d, CORBA_Boolean r)
    : max_(l), len_(l), rel_(r)
{
    assert_nca(len_ <= max, OBNCASeqLenGrMax);
    data_ = d;
}

template<class T, CORBA_ULong max>
OBBndObjSeq<T, max>
::OBBndObjSeq(const OBBndObjSeq<T, max>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T, CORBA_ULong max>
OBBndObjSeq<T, max>&
OBBndObjSeq<T, max>::
operator=(const OBBndObjSeq<T, max>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	max_ = max;
	data_ = allocbuf(max);

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    data_[i] = r.data_[i];
	    OBDuplicate(data_[i]);
	}
    }

    return *this;
}

template<class T, CORBA_ULong max>
void
OBBndObjSeq<T, max>::length(CORBA_ULong newLen)
{
    assert_nca(newLen <= max, OBNCASeqLenGrMax);

    if(newLen < len_ && rel_)
    {
	for(CORBA_ULong i = newLen ; i < len_ ; i++)
	{
	    OBRelease(data_[i]);
	    data_[i] = 0;
	}
    }
    else if(newLen > max_)
    {
	T** old = data_;
	   
	max_ = max;
	data_ = allocbuf(max);
	    
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    if(rel_)
	    {
		data_[i] = old[i];
		old[i] = 0;
	    }
	    else
	    {
		data_[i] = old[i];
		OBDuplicate(data_[i]);
	    }
	}
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T, CORBA_ULong max>
void
OBBndObjSeq<T, max>::consume(OBBndObjSeq<T, max>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

/*
 * Unbounded string sequence type is in Sequence.cc
 */

//
// Template for bounded string sequence type
//
template<CORBA_ULong max>
OBBndStrSeq<max>::OBBndStrSeq()
    : max_(max), len_(0), rel_(true)
{
    data_ = allocbuf(max);
}

template<CORBA_ULong max>
OBBndStrSeq<max>::OBBndStrSeq(CORBA_ULong l, char** d, CORBA_Boolean r)
    : max_(l), len_(l), rel_(r)
{
    assert_nca(len_ <= max, OBNCASeqLenGrMax);
    data_ = d;
}

template<CORBA_ULong max>
OBBndStrSeq<max>::OBBndStrSeq(const OBBndStrSeq<max>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<CORBA_ULong max>
OBBndStrSeq<max>&
OBBndStrSeq<max>::operator=(const OBBndStrSeq<max>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	max_ = max;
	data_ = allocbuf(max);

	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	    data_[i] = CORBA_string_dup(r.data_[i]);
    }

    return *this;
}

template<CORBA_ULong max>
void
OBBndStrSeq<max>::length(CORBA_ULong newLen)
{
    assert_nca(newLen <= max, OBNCASeqLenGrMax);

    if(newLen < len_ && rel_)
    {
	for(CORBA_ULong i = newLen ; i < len_ ; i++)
	{
	    CORBA_string_free(data_[i]);
	    data_[i] = 0;
	}
    }
    else if (newLen > max_)
    {
	char** old = data_;

	max_ = max;
	data_ = allocbuf(max);
	
	for(CORBA_ULong i = 0 ; i < len_ ; i++)
	{
	    if(rel_)
	    {
		data_[i] = old[i];
		old[i] = 0;
	    }
	    else
		data_[i] = CORBA_string_dup(old[i]);
	}
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
    len_ = newLen;
}

template<CORBA_ULong max>
void
OBBndStrSeq<max>::consume(OBBndStrSeq<max>& r)
{
    if(data_ && rel_)
	freebuf(data_);

    max_ = r.max_;
    len_ = r.len_;
    rel_ = r.rel_;
    data_ = r.data_;

    r.len_ = 0;
    r.rel_ = true;
    r.data_ = 0;
}

// ----------------------------------------------------------------------
// Constructed type info class (for use with the any type)
// ----------------------------------------------------------------------

//
// This is for all types that use new/delete
//
template<class T>
class OBInfo : public OBConstructedInfo
{
public:

    OBInfo() { };

    virtual void* alloc() const
    { return new T; }

    virtual void free(void* p) const
    { delete (T*)p; }

    virtual void* dup(const void* p) const
    { return new T(*(const T*)p); }

    virtual void marshal(const void* p, CORBA_Octet*& oct) const
    { OBMarshal(*(const T*)p, oct); }

    virtual void marshalCount(const void* p, CORBA_ULong& count) const
    { OBMarshalCount(*(const T*)p, count); }

    virtual void unmarshal(void* p, const CORBA_Octet*& oct, bool swap) const
    { OBUnmarshal(*(T*)p, oct, swap); }
};

#endif
