/********************************************************************************
* *
* G e n e r i c A r r a y *
* *
*********************************************************************************
* Copyright (C) 1997,2024 by Jeroen van der Zijp. All Rights Reserved. *
*********************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* 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 *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see *
********************************************************************************/
#ifndef FXARRAY_H
#define FXARRAY_H
#ifndef FXELEMENT_H
#include "FXElement.h"
#endif
namespace FX {
/// ArrayBase manages a memory buffer
class FXAPI FXArrayBase {
protected:
FXptr ptr;
protected:
FXArrayBase();
FXbool resize(FXival num,FXival sz);
~FXArrayBase();
};
/// Array of some generic type
template
class FXArray : public FXArrayBase {
public:
/// Allocate initially empty array
FXArray(){ }
/// Allocate array of n elements
FXArray(FXival n){ no(n); }
/// Allocate array copied from another
FXArray(const FXArray& src){
if(no(src.no())){ copyElms(data(),src.data(),src.no()); }
}
/// Allocate initialized with n copies of object
FXArray(const EType& src,FXival n){
if(no(n)){ fillElms(data(),src,n); }
}
/// Allocate initialized with array of n objects
FXArray(const EType* src,FXival n){
if(no(n)){ copyElms(data(),src,n); }
}
/// Return number of items
FXival no() const { return *(((FXival*)ptr)-1); }
/// Change number of elements in array to n
FXbool no(FXival n){
FXival m=no();
if((n-m)>0){
if(!resize(n,sizeof(EType))) return false;
constructElms(&at(m),n-m);
}
else if((m-n)>0){
destructElms(&at(n),m-n);
if(!resize(n,sizeof(EType))) return false;
}
return true;
}
/// Assign from another array
FXArray& operator=(const FXArray& src){
if(data()!=src.data() && no(src.no())){ copyElms(data(),src.data(),src.no()); }
return *this;
}
/// Return pointer to array
EType* data(){ return reinterpret_cast(ptr); }
const EType* data() const { return reinterpret_cast(ptr); }
/// Index into array
EType& operator[](FXival i){ return data()[i]; }
const EType& operator[](FXival i) const { return data()[i]; }
/// Index into array
EType& at(FXival i){ return data()[i]; }
const EType& at(FXival i) const { return data()[i]; }
/// First element in array
EType& head(){ return data()[0]; }
const EType& head() const { return data()[0]; }
/// Last element in array
EType& tail(){ return data()[no()-1]; }
const EType& tail() const { return data()[no()-1]; }
/// Adopt array from another one; the other array becomes empty
FXArray& adopt(FXArray& src){
if(ptr!=src.ptr && no(0)){ swap(ptr,src.ptr); }
return *this;
}
/// Assign object p to array
FXbool assign(const EType& src){
if(no(1)){ head()=src; return true; }
return false;
}
/// Assign n copies of object to array
FXbool assign(const EType& src,FXival n){
if(no(n)){ fillElms(data(),src,n); return true; }
return false;
}
/// Assign n objects to list
FXbool assign(const EType* src,FXival n){
if(no(n)){ copyElms(data(),src,n); return true; }
return false;
}
/// Assign n objects to list
FXbool assign(const FXArray& src){
return assign(src.data(),src.no());
}
/// Insert an object
FXbool insert(FXival pos,const EType& src){
if(no(no()+1)){ moveElms(data()+pos+1,data()+pos,no()-pos-1); at(pos)=src; return true; }
return false;
}
/// Insert n copies of object at specified position
FXbool insert(FXival pos,const EType& src,FXival n){
if(no(no()+n)){ moveElms(data()+pos+n,data()+pos,no()-pos-n); fillElms(data()+pos,src,n); return true; }
return false;
}
/// Insert n objects at specified position
FXbool insert(FXival pos,const EType* src,FXival n){
if(no(no()+n)){ moveElms(data()+pos+n,data()+pos,no()-pos-n); copyElms(data()+pos,src,n); return true; }
return false;
}
/// Insert n objects at specified position
FXbool insert(FXival pos,const FXArray& src){
return insert(pos,src.data(),src.no());
}
/// Prepend object
FXbool prepend(const EType& src){
if(no(no()+1)){ moveElms(data()+1,data(),no()-1); head()=src; return true; }
return false;
}
/// Prepend n copies of object
FXbool prepend(const EType& src,FXival n){
if(no(no()+n)){ moveElms(data()+n,data(),no()-n); fillElms(data(),src,n); return true; }
return false;
}
/// Prepend n objects
FXbool prepend(const EType* src,FXival n){
if(no(no()+n)){ moveElms(data()+n,data(),no()-n); copyElms(data(),src,n); return true; }
return false;
}
/// Prepend n objects
FXbool prepend(const FXArray& src){
return prepend(src.data(),src.no());
}
/// Append object
FXbool append(const EType& src){
if(no(no()+1)){ tail()=src; return true; }
return false;
}
/// Append n copies of object
FXbool append(const EType& src,FXival n){
if(no(no()+n)){ fillElms(data()+no()-n,src,n); return true; }
return false;
}
/// Append n objects
FXbool append(const EType* src,FXival n){
if(no(no()+n)){ copyElms(data()+no()-n,src,n); return true; }
return false;
}
/// Append n objects
FXbool append(const FXArray& src){
return append(src.data(),src.no());
}
/// Replace an object by other object
FXbool replace(FXival pos,const EType& src){
at(pos)=src;
return true;
}
/// Replace the m objects at pos with n copies of other object
FXbool replace(FXival pos,FXival m,const EType& src,FXival n){
if(mn){
moveElms(data()+pos+n,data()+pos+m,no()-pos-m);
if(!no(no()-m+n)) return false;
}
fillElms(data()+pos,src,n);
return true;
}
/// Replace m objects at pos by n other objects
FXbool replace(FXival pos,FXival m,const EType* src,FXival n){
if(mn){
moveElms(data()+pos+n,data()+pos+m,no()-pos-m);
if(!no(no()-m+n)) return false;
}
copyElms(data()+pos,src,n);
return true;
}
/// Replace m objects at pos by other objects
FXbool replace(FXival pos,FXival m,const FXArray& src){
return replace(pos,m,src.data(),src.no());
}
/// Remove object at pos
FXbool erase(FXival pos){
moveElms(data()+pos,data()+pos+1,no()-pos-1);
return no(no()-1);
}
/// Remove n objects starting at pos
FXbool erase(FXival pos,FXival n){
moveElms(data()+pos,data()+pos+n,no()-pos-n);
return no(no()-n);
}
/// Push object to end
FXbool push(const EType& src){
if(no(no()+1)){ tail()=src; return true; }
return false;
}
/// Pop object from end
FXbool pop(){
return no(no()-1);
}
/// Remove all objects
FXbool clear(){
return no(0);
}
/// Delete data
~FXArray(){
clear();
}
};
}
#endif