// **********************************************************************
//
// Copyright (c) 2002
// IONA Technologies, Inc.
// Waltham, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_TEMPLATE_I_H
#define OB_TEMPLATE_I_H

#include <OB/Template.h>

namespace OB
{

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

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

template<class T>
FixVar<T>&
FixVar<T>::operator=(const T& t)
{
    if(&t != ptr_)
    {
        T* oldPtr = ptr_;
        ptr_ = new T(t);
        delete oldPtr;
    }
    return *this;
}

template<class T>
FixVar<T>&
FixVar<T>::operator=(const FixVar<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>
VarVar<T>&
VarVar<T>::operator=(T* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, NCASelfAssign);
    delete ptr_;
    ptr_ = p;
    return *this;
}

template<class T>
VarVar<T>&
VarVar<T>::operator=(const VarVar<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>
SeqVar<T>&
SeqVar<T>::operator=(T* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, NCASelfAssign);
    delete ptr_;
    ptr_ = p;
    return *this;
}

template<class T>
SeqVar<T>&
SeqVar<T>::operator=(const SeqVar<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>
FixArrayVar<T_slice, T, n>::
FixArrayVar(const FixArrayVar<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>
FixArrayVar<T_slice, T, n>&
FixArrayVar<T_slice, T, n>::operator=(T_slice* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, NCASelfAssign);
    delete [] (T*) ptr_;
    ptr_ = p;
    return *this;
}

template<class T_slice, class T, CORBA::ULong n>
FixArrayVar<T_slice, T, n>&
FixArrayVar<T_slice, T, n>::
operator=(const FixArrayVar<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>
VarArrayVar<T_slice, T, n>::
VarArrayVar(const VarArrayVar<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>
VarArrayVar<T_slice, T, n>&
VarArrayVar<T_slice, T, n>::operator=(T_slice* p)
{
    assert_nca(ptr_ == 0 || p != ptr_, NCASelfAssign);
    delete [] (T*) ptr_;
    ptr_ = p;
    return *this;
}

template<class T_slice, class T, CORBA::ULong n>
VarArrayVar<T_slice, T, n>&
VarArrayVar<T_slice, T, n>::
operator=(const VarArrayVar<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, class U>
T*
FixSeq<T, U>::allocbuf(CORBA::ULong n)
{
    try
    {
	return new T[n];
    }
    catch(...)
    {
	return 0;
    }
}

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

template<class T, class U>
FixSeq<T, U>::FixSeq(CORBA::ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
    {
	data_ = allocbuf(max_);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }
    else
	data_ = 0;
}

template<class T, class U>
FixSeq<T, U>::FixSeq(CORBA::ULong m, CORBA::ULong l, T* d, CORBA::Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = d;
}

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

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

	if(max_ > 0)
	{
	    data_ = allocbuf(max_);
	    if(data_ == 0)
		OB::ThrowNoMemoryException();

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

template<class T, class U>
void
FixSeq<T, U>::length(CORBA::ULong newLen)
{
    if(newLen > max_)
    {
	T* old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	if(data_ == 0)
	{
	    if(rel_)
		freebuf(old);
	    OB::ThrowNoMemoryException();
	}

	if(len_)
	    memcpy(data_, old, len_ * sizeof(T));
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T, class U>
void
FixSeq<T, U>::replace(CORBA::ULong max, CORBA::ULong len, T* data,
		      CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
    
    max_ = max;
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = data;
}

template<class T, class U>
T*
FixSeq<T, U>::get_buffer(CORBA::Boolean orphan)
{
    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    max_ = 0;
    len_ = 0;
    rel_ = true;
    data_ = 0;

    return rc;
}

//
// Template for fixed-length general bounded sequence type
//
template<class T, CORBA::ULong max, class U>
T*
BndFixSeq<T, max, U>::allocbuf(CORBA::ULong n)
{
    assert_nca(n == max, NCASeqBound);
    try
    {
	return new T[n];
    }
    catch(...)
    {
	return 0;
    }
}

template<class T, CORBA::ULong max, class U>
BndFixSeq<T, max, U>::BndFixSeq()
    : len_(0), rel_(true), data_(0)
{
}

template<class T, CORBA::ULong max, class U>
BndFixSeq<T, max, U>::BndFixSeq(CORBA::ULong l, T* d, CORBA::Boolean r)
    : len_(l), rel_(r)
{
    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = d;
}

template<class T, CORBA::ULong max, class U>
BndFixSeq<T, max, U>::BndFixSeq(const BndFixSeq<T, max, U>& r)
    : len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T, CORBA::ULong max, class U>
BndFixSeq<T, max, U>&
BndFixSeq<T, max, U>::operator=(const BndFixSeq<T, max, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);

	len_ = r.len_;
	rel_ = true;

	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();

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

template<class T, CORBA::ULong max, class U>
void
BndFixSeq<T, max, U>::length(CORBA::ULong newLen)
{
    assert_nca(newLen <= max, NCASeqLenGrMax);

    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    len_ = newLen;
}

template<class T, CORBA::ULong max, class U>
void
BndFixSeq<T, max, U>::replace(CORBA::ULong len, T* data,
			      CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);

    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = data;
}

template<class T, CORBA::ULong max, class U>
T*
BndFixSeq<T, max, U>::get_buffer(CORBA::Boolean orphan)
{
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    len_ = 0;
    rel_ = true;
    data_ = allocbuf(max);

    return rc;
}

//
// Template for variable-length general unbounded sequence type
//
template<class T, class U>
T*
VarSeq<T, U>::allocbuf(CORBA::ULong n)
{
    try
    {
	return new T[n];
    }
    catch(...)
    {
	return 0;
    }
}

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

template<class T, class U>
VarSeq<T, U>::VarSeq(CORBA::ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
    {
	data_ = allocbuf(max_);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }
    else
	data_ = 0;
}

template<class T, class U>
VarSeq<T, U>::VarSeq(CORBA::ULong m, CORBA::ULong l, T* d, CORBA::Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = d;
}

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

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

	if(max_ > 0)
	{
	    data_ = allocbuf(max_);
	    if(data_ == 0)
		OB::ThrowNoMemoryException();
	}
	else
	    data_ = 0;

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

template<class T, class U>
void
VarSeq<T, U>::length(CORBA::ULong newLen)
{
    if(newLen < len_ && rel_)
    {
 	for(CORBA::ULong i = newLen ; i < len_ ; i++)
 	    data_[i] = T();
    }
    else if(newLen > max_)
    {
	T* old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	if(data_ == 0)
	{
	    if(rel_)
		freebuf(old);
	    OB::ThrowNoMemoryException();
	}

	for(CORBA::ULong i = 0 ; i < len_ ; i++)
	    data_[i] = old[i];
	
	if(rel_)
	    freebuf(old);
	    
	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T, class U>
void
VarSeq<T, U>::replace(CORBA::ULong max, CORBA::ULong len, T* data,
		      CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
    
    max_ = max;
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = data;
}

template<class T, class U>
T*
VarSeq<T, U>::get_buffer(CORBA::Boolean orphan)
{
    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    max_ = 0;
    len_ = 0;
    rel_ = true;
    data_ = 0;

    return rc;
}

//
// Template for variable-length general bounded sequence type
//
template<class T, CORBA::ULong max, class U>
T*
BndVarSeq<T, max, U>::allocbuf(CORBA::ULong n)
{
    assert_nca(n == max, NCASeqBound);
    try
    {
	return new T[n];
    }
    catch(...)
    {
	return 0;
    }
}

template<class T, CORBA::ULong max, class U>
BndVarSeq<T, max, U>::BndVarSeq()
    : len_(0), rel_(true), data_(0)
{
}

template<class T, CORBA::ULong max, class U>
BndVarSeq<T, max, U>::BndVarSeq(CORBA::ULong l, T* d, CORBA::Boolean r)
    : len_(l), rel_(r)
{
    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = d;
}

template<class T, CORBA::ULong max, class U>
BndVarSeq<T, max, U>::BndVarSeq(const BndVarSeq<T, max, U>& r)
    : len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T, CORBA::ULong max, class U>
BndVarSeq<T, max, U>&
BndVarSeq<T, max, U>::operator=(const BndVarSeq<T, max, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);

	len_ = r.len_;
	rel_ = true;

	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();

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

template<class T, CORBA::ULong max, class U>
void
BndVarSeq<T, max, U>::length(CORBA::ULong newLen)
{
    assert_nca(newLen <= max, NCASeqLenGrMax);

    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    if(newLen < len_ && rel_)
    {
 	for(CORBA::ULong i = newLen ; i < len_ ; i++)
 	    data_[i] = T();
    }
    
    len_ = newLen;
}

template<class T, CORBA::ULong max, class U>
void
BndVarSeq<T, max, U>::replace(CORBA::ULong len, T* data,
			      CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
   
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = data;
}

template<class T, CORBA::ULong max, class U>
T*
BndVarSeq<T, max, U>::get_buffer(CORBA::Boolean orphan)
{
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    len_ = 0;
    rel_ = true;
    data_ = allocbuf(max);

    return rc;
}

//
// Template for fixed-length array unbounded sequence type
//
template<class T_arr, class T, CORBA::ULong n, class U>
T_arr*
FixArraySeq<T_arr, T, n, U>::allocbuf(CORBA::ULong nn)
{
    return (T_arr*) Alloc(sizeof(T_arr), nn);
}

template<class T_arr, class T, CORBA::ULong n, class U>
void
FixArraySeq<T_arr, T, n, U>::freebuf(T_arr* p)
{
    if(p)
	Free(p);
}

template<class T_arr, class T, CORBA::ULong n, class U>
FixArraySeq<T_arr, T, n, U>::FixArraySeq()
    : max_(0), len_(0), rel_(true), data_(0)
{
}

template<class T_arr, class T, CORBA::ULong n, class U>
FixArraySeq<T_arr, T, n, U>::FixArraySeq(CORBA::ULong m)
    : max_(m), len_(0), rel_(true) 
{
    if(max_ > 0)
    {
	data_ = allocbuf(max_);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }
    else
	data_ = 0;
}

template<class T_arr, class T, CORBA::ULong n, class U>
FixArraySeq<T_arr, T, n, U>::
FixArraySeq(CORBA::ULong m, CORBA::ULong l, T_arr* d, CORBA::Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = d;
}

template<class T_arr, class T, CORBA::ULong n, class U>
FixArraySeq<T_arr, T, n, U>::
FixArraySeq(const FixArraySeq<T_arr, T, n, U>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_arr, class T, CORBA::ULong n, class U>
FixArraySeq<T_arr, T, n, U>&
FixArraySeq<T_arr, T, n, U>::operator=(const FixArraySeq<T_arr, T, n, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	max_ = r.max_;
	len_ = r.len_;
	rel_ = true;

	if(max_ > 0)
	{
	    data_ = allocbuf(max_);
	    if(data_ == 0)
		OB::ThrowNoMemoryException();
	}
	else
	    data_ = 0;

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

template<class T_arr, class T, CORBA::ULong n, class U>
void
FixArraySeq<T_arr, T, n, U>::length(CORBA::ULong newLen)
{
    if(newLen > max_)
    {
	T_arr* old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	if(data_ == 0)
	{
	    if(rel_)
		freebuf(old);
	    OB::ThrowNoMemoryException();
	}

        memcpy(data_, old, len_ * sizeof(T_arr));

	if(rel_)
	    freebuf(old);

	rel_ = true;
    }
    
    len_ = newLen;
}

template<class T_arr, class T, CORBA::ULong n, class U>
void
FixArraySeq<T_arr, T, n, U>::replace(CORBA::ULong max, CORBA::ULong len,
				       T_arr* data, CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
    
    max_ = max;
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = data;
}

template<class T_arr, class T, CORBA::ULong n, class U>
T_arr*
FixArraySeq<T_arr, T, n, U>::get_buffer(CORBA::Boolean orphan)
{
    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T_arr* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    max_ = 0;
    len_ = 0;
    rel_ = true;
    data_ = 0;

    return rc;
}

//
// Template for fixed-length array bounded sequence type
//
template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
T_arr*
BndFixArraySeq<T_arr, T, n, max, U>::allocbuf(CORBA::ULong nn)
{
    assert_nca(nn == max, NCASeqBound);

    return (T_arr*) Alloc(sizeof(T_arr), nn);
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
void
BndFixArraySeq<T_arr, T, n, max, U>::freebuf(T_arr* p)
{
    if(p)
        Free(p);
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndFixArraySeq<T_arr, T, n, max, U>::BndFixArraySeq()
    : len_(0), rel_(true), data_(0)
{
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndFixArraySeq<T_arr, T, n, max, U>::BndFixArraySeq(CORBA::ULong l,
                                                    T_arr* d,
                                                    CORBA::Boolean r)
    : len_(l), rel_(r)
{
    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = d;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndFixArraySeq<T_arr, T, n, max, U>::
BndFixArraySeq(const BndFixArraySeq<T_arr, T, n, max, U>& r)
    : len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndFixArraySeq<T_arr, T, n, max, U>&
BndFixArraySeq<T_arr, T, n, max, U>::
operator=(const BndFixArraySeq<T_arr, T, n, max, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();

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

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
void
BndFixArraySeq<T_arr, T, n, max, U>::length(CORBA::ULong newLen)
{
    assert_nca(newLen <= max, NCASeqLenGrMax);
    
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    len_ = newLen;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
void
BndFixArraySeq<T_arr, T, n, max, U>::replace(CORBA::ULong len,
					     T_arr* data,
					     CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
   
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = data;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
T_arr*
BndFixArraySeq<T_arr, T, n, max, U>::get_buffer(CORBA::Boolean orphan)
{
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T_arr* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    len_ = 0;
    rel_ = true;
    data_ = allocbuf(max);

    return rc;
}

//
// Template for variable-length array unbounded sequence type
//
template<class T_arr, class T, CORBA::ULong n, class U>
T_arr*
VarArraySeq<T_arr, T, n, U>::allocbuf(CORBA::ULong nn)
{
    return new T_arr[nn];
}

template<class T_arr, class T, CORBA::ULong n, class U>
void
VarArraySeq<T_arr, T, n, U>::freebuf(T_arr* p)
{
    if(p)
        delete [] p;
}

template<class T_arr, class T, CORBA::ULong n, class U>
VarArraySeq<T_arr, T, n, U>::VarArraySeq()
    : max_(0), len_(0), rel_(true), data_(0)
{
}

template<class T_arr, class T, CORBA::ULong n, class U>
VarArraySeq<T_arr, T, n, U>::VarArraySeq(CORBA::ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
    {
	data_ = allocbuf(max_);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }
    else
	data_ = 0;
}

template<class T_arr, class T, CORBA::ULong n, class U>
VarArraySeq<T_arr, T, n, U>::VarArraySeq(CORBA::ULong m, CORBA::ULong l,
					 T_arr* d, CORBA::Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = d;
}

template<class T_arr, class T, CORBA::ULong n, class U>
VarArraySeq<T_arr, T, n, U>::
VarArraySeq(const VarArraySeq<T_arr, T, n, U>& r)
    : max_(0), len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_arr, class T, CORBA::ULong n, class U>
VarArraySeq<T_arr, T, n, U>&
VarArraySeq<T_arr, T, n, U>::
operator=(const VarArraySeq<T_arr, T, n, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	max_ = r.max_;
	len_ = r.len_;
	rel_ = true;

	if(max_ > 0)
	{
	    data_ = allocbuf(max_);
	    if(data_ == 0)
		OB::ThrowNoMemoryException();
	}
	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_arr, class T, CORBA::ULong n, class U>
void
VarArraySeq<T_arr, T, n, U>::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_arr* old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	if(data_ == 0)
	{
	    if(rel_)
		freebuf(old);
	    OB::ThrowNoMemoryException();
	}
	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_arr, class T, CORBA::ULong n, class U>
void
VarArraySeq<T_arr, T, n, U>::replace(CORBA::ULong max, CORBA::ULong len,
				     T_arr* data, CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
    
    max_ = max;
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = data;
}

template<class T_arr, class T, CORBA::ULong n, class U>
T_arr*
VarArraySeq<T_arr, T, n, U>::get_buffer(CORBA::Boolean orphan)
{
    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T_arr* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    max_ = 0;
    len_ = 0;
    rel_ = true;
    data_ = 0;

    return rc;
}

//
// Template for variable-length array bounded sequence type
//
template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
T_arr*
BndVarArraySeq<T_arr, T, n, max, U>::allocbuf(CORBA::ULong nn)
{
    assert_nca(nn == max, NCASeqBound);

    return new T_arr[nn];
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
void
BndVarArraySeq<T_arr, T, n, max, U>::freebuf(T_arr* p)
{
    if(p)
        delete [] p;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndVarArraySeq<T_arr, T, n, max, U>::BndVarArraySeq()
    : len_(0), rel_(true), data_(0)
{
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndVarArraySeq<T_arr, T, n, max, U>::
BndVarArraySeq(CORBA::ULong l, T_arr* d, CORBA::Boolean r)
    : len_(l), rel_(r)
{
    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = d;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndVarArraySeq<T_arr, T, n, max, U>::
BndVarArraySeq(const BndVarArraySeq<T_arr, T, n, max, U>& r)
    : len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
BndVarArraySeq<T_arr, T, n, max, U>&
BndVarArraySeq<T_arr, T, n, max, U>::
operator=(const BndVarArraySeq<T_arr, T, n, max, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);

	len_ = r.len_;
	rel_ = true;

	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();

	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_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
void
BndVarArraySeq<T_arr, T, n, max, U>::length(CORBA::ULong newLen)
{
    assert_nca(newLen <= max, NCASeqLenGrMax);

    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    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();
	}
    }
    
    len_ = newLen;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
void
BndVarArraySeq<T_arr, T, n, max, U>::replace(CORBA::ULong len,
					     T_arr* data,
					     CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
   
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = data;
}

template<class T_arr, class T, CORBA::ULong n, CORBA::ULong max, class U>
T_arr*
BndVarArraySeq<T_arr, T, n, max, U>::get_buffer(CORBA::Boolean orphan)
{
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T_arr* rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    len_ = 0;
    rel_ = true;
    data_ = allocbuf(max);

    return rc;
}

//
// Template for unbounded object reference sequence type
//
template<class T, class U>
T**
ObjSeq<T, U>::allocbuf(CORBA::ULong n)
{
    T** p = (T**) Alloc(sizeof(T*), n);
    if(p)
    {
	for(CORBA::ULong i = 0 ; i < n ; i++)
	    p[i] = 0;
    }
    return p;
}

template<class T, class U>
void
ObjSeq<T, U>::freebuf(T** p)
{
    if(p)
    {
	CORBA::ULong n = Allocated(p);
	
	for(CORBA::ULong i = 0 ; i < n ; i++)
	    OBRelease(p[i]);

	Free(p);
    }
}

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

template<class T, class U>
ObjSeq<T, U>::ObjSeq(CORBA::ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
    {
	data_ = allocbuf(max_);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }
    else
	data_ = 0;
}

template<class T, class U>
ObjSeq<T, U>::ObjSeq(CORBA::ULong m, CORBA::ULong l, T** d, CORBA::Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = d;
}

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

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

	if(max_ > 0)
	{
	    data_ = allocbuf(max_);
	    if(data_ == 0)
		OB::ThrowNoMemoryException();
	}
	else
	    data_ = 0;

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

    return *this;
}

template<class T, class U>
void
ObjSeq<T, U>::length(CORBA::ULong newLen)
{
    if(newLen < len_ && rel_)
    {
	for(CORBA::ULong i = newLen ; i < len_ ; i++)
	{
	    T* old = data_[i];
	    data_[i] = 0;
	    OBRelease(old);
	}
    }
    else if(newLen > max_)
    {
	T** old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	if(data_ == 0)
	{
	    if(rel_)
		freebuf(old);
	    OB::ThrowNoMemoryException();
	}
	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, class U>
void
ObjSeq<T, U>::replace(CORBA::ULong max, CORBA::ULong len, T** data,
		      CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
    
    max_ = max;
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = data;
}

template<class T, class U>
T**
ObjSeq<T, U>::get_buffer(CORBA::Boolean orphan)
{
    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T** rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    max_ = 0;
    len_ = 0;
    rel_ = true;
    data_ = 0;

    return rc;
}

//
// Template for unbounded object reference sequence type
//
template<class T, CORBA::ULong max, class U>
T**
BndObjSeq<T, max, U>::allocbuf(CORBA::ULong n)
{
    assert_nca(n == max, NCASeqBound);
    
    T** p = (T**) Alloc(sizeof(T*), n);
    if(p)
    {
	for(CORBA::ULong i = 0 ; i < n ; i++)
	    p[i] = 0;
    }
    return p;
}

template<class T, CORBA::ULong max, class U>
void
BndObjSeq<T, max, U>::freebuf(T** p)
{
    if(p)
    {
	CORBA::ULong n = Allocated(p);
	
	for(CORBA::ULong i = 0 ; i < n ; i++)
	    OBRelease(p[i]);

	Free(p);
    }
}

template<class T, CORBA::ULong max, class U>
BndObjSeq<T, max, U>::BndObjSeq()
    : len_(0), rel_(true), data_(0)
{
}

template<class T, CORBA::ULong max, class U>
BndObjSeq<T, max, U>
::BndObjSeq(CORBA::ULong l, T** d, CORBA::Boolean r)
    : len_(l), rel_(r)
{
    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = d;
}

template<class T, CORBA::ULong max, class U>
BndObjSeq<T, max, U>
::BndObjSeq(const BndObjSeq<T, max, U>& r)
    : len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<class T, CORBA::ULong max, class U>
BndObjSeq<T, max, U>&
BndObjSeq<T, max, U>::
operator=(const BndObjSeq<T, max, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);

	len_ = r.len_;
	rel_ = true;

	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();

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

    return *this;
}

template<class T, CORBA::ULong max, class U>
void
BndObjSeq<T, max, U>::length(CORBA::ULong newLen)
{
    assert_nca(newLen <= max, NCASeqLenGrMax);

    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    if(newLen < len_ && rel_)
    {
	for(CORBA::ULong i = newLen ; i < len_ ; i++)
	{
	    T* old = data_[i];
	    data_[i] = 0;
	    OBRelease(old);
	}
    }
    
    len_ = newLen;
}

template<class T, CORBA::ULong max, class U>
void
BndObjSeq<T, max, U>::replace(CORBA::ULong len, T** data,
			      CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
   
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = data;
}

template<class T, CORBA::ULong max, class U>
T**
BndObjSeq<T, max, U>::get_buffer(CORBA::Boolean orphan)
{
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    T** rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    len_ = 0;
    rel_ = true;
    data_ = allocbuf(max);

    return rc;
}

//
// Template for unbounded string sequence type
//
template<class U>
StrSeq<U>::StrSeq()
    : max_(0), len_(0), rel_(true), data_(0)
{
}

template<class U>
StrSeq<U>::StrSeq(CORBA::ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
    {
	data_ = allocbuf(max_);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }
    else
	data_ = 0;

}

template<class U>
StrSeq<U>::StrSeq(CORBA::ULong m, CORBA::ULong l, char** d, CORBA::Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = d;
}

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

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

	if(max_ > 0)
	{
	    data_ = allocbuf(max_);
	    if(data_ == 0)
		OB::ThrowNoMemoryException();
	}
	else
	    data_ = 0;

	for(CORBA::ULong i = 0 ; i < len_ ; i++)
	    data_[i] = CORBA::string_dup(r.data_[i]);
    }

    return *this;
}

template<class U>
void
StrSeq<U>::length(CORBA::ULong newLen)
{
    if(newLen < len_ && rel_)
    {
	for(CORBA::ULong i = newLen ; i < len_ ; i++)
	{
	    CORBA::string_free(data_[i]);
	    data_[i] = OB::EmptyString;
	}
    }
    else if(max_ < newLen)
    {
	char** old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	if(data_ == 0)
	{
	    if(rel_)
		freebuf(old);
	    OB::ThrowNoMemoryException();
	}
	for(CORBA::ULong i = 0 ; i < len_ ; i++)
	{
	    if(rel_)
	    {
		data_[i] = old[i];
		old[i] = OB::EmptyString;
	    }
	    else
		data_[i] = CORBA::string_dup(old[i]);
	}
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
/*
    for(CORBA::ULong i = len_ ; i < newLen ; i++)
	data_[i] = OB::EmtpyString;
*/

    len_ = newLen;
}

template<class U>
void
StrSeq<U>::replace(CORBA::ULong max, CORBA::ULong len, char** data,
		   CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
    
    max_ = max;
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = data;
}

template<class U>
char**
StrSeq<U>::get_buffer(CORBA::Boolean orphan)
{
    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    char** rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    max_ = 0;
    len_ = 0;
    rel_ = true;
    data_ = 0;

    return rc;
}

//
// Template for bounded string sequence type
//
template<CORBA::ULong max, class U>
char**
BndStrSeq<max, U>::allocbuf(CORBA::ULong n)
{
    assert_nca(n == max, NCASeqBound);
    return OB::StrSeqAllocbuf(n); 
}

template<CORBA::ULong max, class U>
BndStrSeq<max, U>::BndStrSeq()
    : len_(0), rel_(true), data_(0)
{
}

template<CORBA::ULong max, class U>
BndStrSeq<max, U>::BndStrSeq(CORBA::ULong l, char** d, CORBA::Boolean r)
    : len_(l), rel_(r)
{
    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = d;
}

template<CORBA::ULong max, class U>
BndStrSeq<max, U>::BndStrSeq(const BndStrSeq<max, U>& r)
    : len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<CORBA::ULong max, class U>
BndStrSeq<max, U>&
BndStrSeq<max, U>::operator=(const BndStrSeq<max, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();

	for(CORBA::ULong i = 0 ; i < len_ ; i++)
	    data_[i] = CORBA::string_dup(r.data_[i]);
    }

    return *this;
}


template<CORBA::ULong max, class U>
void
BndStrSeq<max, U>::length(CORBA::ULong newLen)
{
    assert_nca(newLen <= max, NCASeqLenGrMax);

    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    if(newLen < len_ && rel_)
    {
	for(CORBA::ULong i = newLen ; i < len_ ; i++)
	{
	    CORBA::string_free(data_[i]);
	    data_[i] = OB::EmptyString;
	}
    }
    
/*
    for(CORBA::ULong i = len_ ; i < newLen ; i++)
	data_[i] =  OB::EmptyString;
*/

    len_ = newLen;
}

template<CORBA::ULong max, class U>
void
BndStrSeq<max, U>::replace(CORBA::ULong len, char** data,
			   CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
   
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = data;
}

template<CORBA::ULong max, class U>
char**
BndStrSeq<max, U>::get_buffer(CORBA::Boolean orphan)
{
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    char** rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    len_ = 0;
    rel_ = true;
    data_ = allocbuf(max);

    return rc;
}

//
// Template for unbounded wide string sequence type
//
template<class U>
WStrSeq<U>::WStrSeq()
    : max_(0), len_(0), rel_(true), data_(0)
{
}

template<class U>
WStrSeq<U>::WStrSeq(CORBA::ULong m)
    : max_(m), len_(0), rel_(true)
{
    if(max_ > 0)
    {
	data_ = allocbuf(max_);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }
    else
	data_ = 0;

}

template<class U>
WStrSeq<U>::WStrSeq(CORBA::ULong m, CORBA::ULong l, wchar_t** d,
		     CORBA::Boolean r)
    : max_(m), len_(l), rel_(r)
{
    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = d;
}

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

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

	if(max_ > 0)
	{
	    data_ = allocbuf(max_);
	    if(data_ == 0)
		OB::ThrowNoMemoryException();
	}
	else
	    data_ = 0;

	for(CORBA::ULong i = 0 ; i < len_ ; i++)
	    data_[i] = CORBA::wstring_dup(r.data_[i]);
    }

    return *this;
}

template<class U>
void
WStrSeq<U>::length(CORBA::ULong newLen)
{
    if(newLen < len_ && rel_)
    {
	for(CORBA::ULong i = newLen ; i < len_ ; i++)
	{
	    CORBA::wstring_free(data_[i]);
	    data_[i] = OB::EmptyWString;
	}
    }
    else if(max_ < newLen)
    {
	wchar_t** old = data_;
	
	max_ = newLen > max_ * 2 ? newLen : max_ * 2;
	data_ = allocbuf(max_);
	if(data_ == 0)
	{
	    if(rel_)
		freebuf(old);
	    OB::ThrowNoMemoryException();
	}

	for(CORBA::ULong i = 0 ; i < len_ ; i++)
	{
	    if(rel_)
	    {
		data_[i] = old[i];
		old[i] = OB::EmptyWString;
	    }
	    else
		data_[i] = CORBA::wstring_dup(old[i]);
	}
	
	if(rel_)
	    freebuf(old);
	
	rel_ = true;
    }
    
/*
    for(CORBA::ULong i = len_ ; i < newLen ; i++)
	data_[i] =  OB::EmptyWString;
*/

    len_ = newLen;
}

template<class U>
void
WStrSeq<U>::replace(CORBA::ULong max, CORBA::ULong len, wchar_t** data,
		    CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
    
    max_ = max;
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max_, NCASeqLenGrMax);
    data_ = data;
}

template<class U>
wchar_t**
WStrSeq<U>::get_buffer(CORBA::Boolean orphan)
{
    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    wchar_t** rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    max_ = 0;
    len_ = 0;
    rel_ = true;
    data_ = 0;

    return rc;
}

//
// Template for bounded wide string sequence type
//
template<CORBA::ULong max, class U>
wchar_t**
BndWStrSeq<max, U>::allocbuf(CORBA::ULong n)
{
    assert_nca(n == max, NCASeqBound);
    return OB::WStrSeqAllocbuf(n);
}

template<CORBA::ULong max, class U>
BndWStrSeq<max, U>::BndWStrSeq()
    : len_(0), rel_(true), data_(0)
{
}

template<CORBA::ULong max, class U>
BndWStrSeq<max, U>::BndWStrSeq(CORBA::ULong l, wchar_t** d, CORBA::Boolean r)
    : len_(l), rel_(r)
{
    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = d;
}

template<CORBA::ULong max, class U>
BndWStrSeq<max, U>::BndWStrSeq(const BndWStrSeq<max, U>& r)
    : len_(0), rel_(true), data_(0)
{
    *this = r;
}

template<CORBA::ULong max, class U>
BndWStrSeq<max, U>&
BndWStrSeq<max, U>::operator=(const BndWStrSeq<max, U>& r)
{
    if(this != &r)
    {
	if(rel_)
	    freebuf(data_);
	
	len_ = r.len_;
	rel_ = true;

	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();

	for(CORBA::ULong i = 0 ; i < len_ ; i++)
	    data_[i] = CORBA::wstring_dup(r.data_[i]);
    }

    return *this;
}

template<CORBA::ULong max, class U>
void
BndWStrSeq<max, U>::length(CORBA::ULong newLen)
{
    assert_nca(newLen <= max, NCASeqLenGrMax);

    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    if(newLen < len_ && rel_)
    {
	for(CORBA::ULong i = newLen ; i < len_ ; i++)
	{
	    CORBA::wstring_free(data_[i]);
	    data_[i] = OB::EmptyWString;
	}
    }

/*    
    for(CORBA::ULong i = len_ ; i < newLen ; i++)
	data_[i] =  OB::EmptyWString;
*/

    len_ = newLen;
}

template<CORBA::ULong max, class U>
void
BndWStrSeq<max, U>::replace(CORBA::ULong len, wchar_t** data,
			    CORBA::Boolean release)
{
    if(rel_)
        freebuf(data_);
   
    len_ = len;
    rel_ = release;

    assert_nca(len_ <= max, NCASeqLenGrMax);
    data_ = data;
}

template<CORBA::ULong max, class U>
wchar_t**
BndWStrSeq<max, U>::get_buffer(CORBA::Boolean orphan)
{
    if(!data_)
    {
	data_ = allocbuf(max);
	if(data_ == 0)
	    OB::ThrowNoMemoryException();
    }

    //
    // If we're not orphaning the data then return a pointer to the
    // data.
    //
    if(!orphan)
        return data_;

    //
    // If we're not free to release the data, then this isn't
    // permitted.
    //
    if(!rel_)
        return 0;

    //
    // We return a pointer to our internal buffer. The user is
    // responsible for freeing this.
    //
    wchar_t** rc = data_;

    //
    // The sequence now reverts to it's default form
    //
    len_ = 0;
    rel_ = true;
    data_ = allocbuf(max);

    return rc;
}

} // End of namespace OB

#endif
