/*
 * Copyright (c) 2002-2006 Samit Basu
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef __Data_hpp__
#define __Data_hpp__

#include "Types.hpp"
#include "Dimensions.hpp"
#include <QSharedData>

/**
 * This is a helper class that is used by the Array class to 
 * support the reference counting scheme used by the Array objects.
 * It essentially stores blocks of data along with a count of
 * how many owners of the data block there are (standard reference
 * counting).  The Array class is declared a friend, as all the
 * methods (including the constructors) are private.
 */
class FunctionDef;
class Array;

class Data : public QSharedData {
private:
  /**
   * The Class of the data block.  Useful for determining how the data
   * block must be treated.
   */
  Class m_dataClass;
  /**
   * Sparsity flag - true if we are a sparse array.
   */
  bool m_sparse;
  /**
   * Pointer to the data block.
   */
  void *cp;
  /**
   * The dimensions of the data block.
   */
  Dimensions m_dimensions;
  /**
   * The field names of the array - used only for structure array types.
   */
  rvstring m_fieldNames;
  /**
   * The class name - only used for user-defined classes
   */
  rvstring m_className;

public:
  /**
   * Construct a Data object with the given arguments.
   * the owner count is initialized to 1.
   */
  inline Data(Class aClass, const Dimensions& dims, void *s, 
	      bool sparseflag = false, 
	      rvstring fields = rvstring(), 
	      rvstring classname = rvstring()) : 
    cp(s), m_dimensions(dims), m_dataClass(aClass) {
    m_sparse = sparseflag;
    m_fieldNames = fields;
    m_sparse = sparseflag;
    m_className = classname;
  } 
  inline Data(const Data& copy) :
    m_dataClass(copy.m_dataClass),
    m_dimensions(copy.m_dimensions),
    m_sparse(copy.m_sparse),
    m_fieldNames(copy.m_fieldNames),
    m_className(copy.m_className) {
    cp = copyDataBlock(copy.cp);
  }
  void* copyDataBlock(void *dp);
  void FreeData();
  /**
   * The destructor.  Calls freeDataBlock member function.
   */
  inline ~Data() {
    FreeData();
  }
  /**
   * Change the contents of the Data object.  The data pointer,
   * class and size are given.  The behavior/return value depends
   * on the number of owners:
   *   - If there is only one owner for this Data block, then
   *     freeDataBlock is called to delete the current data, and
   *     the members are simply reassigned to the given arguments.
   *     The return value is the "this" pointer.
   *   - Otherwise, the number of owners for the current block
   *     is decreased by one, and a new Data object is returned
   *     with the given contents.
   */
  inline void putData(Class aClass, const Dimensions& dims, void *s, 
		      bool sparseflag = false, 
		      rvstring fields = rvstring(),
		      rvstring classname = rvstring()) {
    FreeData();
    cp = s;
    m_dataClass = aClass;
    m_dimensions = dims;
    m_fieldNames = fields;
    m_sparse = sparseflag;
    m_className = classname;
  }
  /**
   * Get a read-only pointer to the data.
   */
  inline const void* getData() const {return cp;}
  inline void* getWriteableData() {return cp;}
  inline void setData(void * p) {FreeData(); cp = p;}
  /**
   * Set and Get methods for members
   */
  inline Class dataClass() const {return m_dataClass;}
  inline void setDataClass(Class p) {m_dataClass = p;}
  inline bool sparse() const {return m_sparse;}
  inline void setSparse(bool p) {m_sparse = p;}
  inline const Dimensions& dimensions() const {return m_dimensions;}
  inline void setDimensions(const Dimensions& p) {m_dimensions = p;}
  inline const rvstring& fieldNames() const {return m_fieldNames;}
  inline void setFieldNames(const rvstring& p) {m_fieldNames = p;}
  inline const rvstring& className() const {return m_className;}
  inline void setClassName(const rvstring& p) {m_className = p;}
  /**
   * Return true if this is a user-defined class
   */
  inline bool isUserClass() const {return (!m_className.empty());}
};

#endif


syntax highlighted by Code2HTML, v. 0.9.1