#include "swppfdtable.h" #include "sopnamsp.h" #include "pexceptions.h" /*! \class SOPHYA::SwPPFDataTable \ingroup HiStats This class can be used to organize data in table (row-column) form. Each column holds homogeneous data (same data type), while different columns can be used for different data types (integer, float, string ...). A PPF stream is used as swap space. Due to limitations in the current implementation of PPF streams, read operations (acces to table data) cannot be performed when a table is being filled. \warning - When creating a table, the output PPF stream (POutPersist) must not be closed (destroyed) before the SwPPFDataTable object is written to the stream. - It is not possible to make a complete (deep) copy of a SwPPFDataTable Copy constructor and equal operator shares the data. - The destructor DOES NOT save the table object itself to the swap stream. The << operator should be used on the output PPF stream being used as swap in order to save the table. \sa SOPHYA::MuTyV \sa SOPHYA::DataTableRow \sa SOPHYA::DataTable \sa SOPHYA::SwSegDataBlock SOPHYA::PPFDataSwapper \code #include "swppfdtable.h" // ... { // ---- Creation of the table // Create the swap stream POutPersist so("myswtable.ppf"); SwPPFDataTable dt(so, 64); // define table columns dt.AddFloatColumn("X0_f"); dt.AddFloatColumn("X1_f"); dt.AddDoubleColumn("X0X0pX1X1_d"); // Fill the table r_8 x[5]; for(int i=0; i<63; i++) { x[0] = (i%9)-4.; x[1] = (i/9)-3.; x[2] = x[0]*x[0]+x[1]*x[1]; dt.AddRow(x); } // Printing table info cout << dt ; // Swap out all data and write the table structure to the PPF stream so << dt ; // .... } { // ---- Accessing information from a previously created table SwPPFDataTable dt; PInPersist si("myswtable.ppf"); si >> dt; // Printing table info cout << dt ; } \endcode */ //! Default constructor with optional specification of block (or segment) size SwPPFDataTable::SwPPFDataTable(sa_size_t segsz) : BaseDataTable(segsz), mSwOut(NULL), mSwIn(NULL) { } /*! Constructor with the specification of the output swap stream - and optional specification of block (or segment) size */ SwPPFDataTable::SwPPFDataTable(POutPersist & os, sa_size_t segsz) : BaseDataTable(segsz) , mSwOut(&os), mSwIn(NULL), mISwapper(os), mLSwapper(os), mFSwapper(os), mDSwapper(os), mYSwapper(os), mZSwapper(os), mSSwapper(os) { } //! Protected constructor for creation from a swap stream SwPPFDataTable::SwPPFDataTable(PInPersist & is, sa_size_t segsz) : BaseDataTable(segsz) , mSwOut(NULL), mSwIn(NULL) { PInPersist* pis = new PInPersist(is.FileName(), false); mSwIn = new St_InSwap; mSwIn->pis = pis; mSwIn->refcnt = 1; mISwapper.SetInStream(*pis); mLSwapper.SetInStream(*pis); mFSwapper.SetInStream(*pis); mDSwapper.SetInStream(*pis); mYSwapper.SetInStream(*pis); mZSwapper.SetInStream(*pis); mSSwapper.SetInStream(*pis); } //! copy constructor - shares the data SwPPFDataTable::SwPPFDataTable(SwPPFDataTable const & a) : BaseDataTable(a.SegmentSize()), mSwOut(NULL), mSwIn(NULL) { Share(a); } //! Destructor - Deletes / closes the input PPF swap stream SwPPFDataTable::~SwPPFDataTable() { if (mSwIn) { mSwIn->refcnt--; if (mSwIn->refcnt == 0) { delete mSwIn->pis; delete mSwIn; mSwIn = NULL; } } } void SwPPFDataTable::Share(SwPPFDataTable const & a) { // Recopie (attention !) brutale des swappers et les streams associes mISwapper = a.mISwapper; mLSwapper = a.mLSwapper; mFSwapper = a.mFSwapper; mDSwapper = a.mDSwapper; mYSwapper = a.mYSwapper; mZSwapper = a.mZSwapper; mSSwapper = a.mSSwapper; mSwOut = a.mSwOut; mSwIn = a.mSwIn; if (mSwIn) mSwIn->refcnt++; // comptage de reference pour le stream input // On recopie la taille de segment mSegSz = a.SegmentSize(); if (a.NVar() == 0) return; // Table sans colonne // On copie la structure de table CopyStructure(a); // // Update nombre d'entree, ... mNEnt = a.mNEnt; mNSeg = a.mNSeg; if (a.mInfo) mInfo = new DVList(*(a.mInfo)); // mis a jour des tableax min-max mMin = a.mMin; mMax = a.mMax; mMinMaxNEnt = a.mMinMaxNEnt; // Et on partage les donnees des colonnes for (size_t kk=0; kk 0) throw ParmError("SwPPFDataTable::AddColumn() Table contains already data "); CheckColName(cnom); sa_size_t ser; sa_size_t idx = NVar(); switch (ft) { case IntegerField : ser = mICols.size(); mICols.push_back(SwSegDataBlock(mISwapper, mSegSz)); mIColIdx.push_back(idx); mIColsP.push_back(NULL); for(sa_size_t kk=0; kk(mLSwapper, mSegSz)); mLColIdx.push_back(idx); mLColsP.push_back(NULL); for(sa_size_t kk=0; kk(mFSwapper, mSegSz)); mFColIdx.push_back(idx); mFColsP.push_back(NULL); for(sa_size_t kk=0; kk( mDSwapper,mSegSz)); mDColIdx.push_back(idx); mDColsP.push_back(NULL); for(sa_size_t kk=0; kk >(mYSwapper, mSegSz)); mYColIdx.push_back(idx); mYColsP.push_back(NULL); for(sa_size_t kk=0; kk >(mZSwapper, mSegSz)); mZColIdx.push_back(idx); mZColsP.push_back(NULL); for(sa_size_t kk=0; kk(mSSwapper, mSegSz)); mSColIdx.push_back(idx); mSColsP.push_back(NULL); for(sa_size_t kk=0; kk mMax[k]) mMax[k] = x; mMinMaxNEnt[k]++; } return BaseDataTable::AddRow(data); } //! Adds a row (or line to the table) with input data as an array of MuTyV /*! The min/max values for each column is updated, in addition to the actions performed by the base class AddRow() */ sa_size_t SwPPFDataTable::AddRow(const MuTyV * data) { // On est oblige de calculer les min-max lors du remplissage // On ne peut pas en effet 'relire' le swap pendant l'ecriture for(sa_size_t k=0; k mMax[k]) mMax[k] = x; mMinMaxNEnt[k]++; } return BaseDataTable::AddRow(data); } //! Adds a row (or line) to the table with input data as DataTableRow object /*! The min/max values for each column is updated, in addition to the actions performed by the base class AddRow() */ sa_size_t SwPPFDataTable::AddRow(DataTableRow const& data) { if ( data.Size() != NCols() ) throw SzMismatchError(" SwPPFDataTable::AddRow() - data.Size() != NCols() "); return AddRow(data.MTVPtr()); }