/*!
 * \file    OMS_ArrayObject.cpp
 * \author  IvanS
 * \brief   Array object.
 */

/*

    ========== licence begin  GPL
    Copyright (c) 2003-2005 SAP AG

    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.
    ========== licence end



*/

#include "Oms/OMS_ArrayObject.hpp"
#include "hsp77.h"
#include "ggg01.h"

/// Optimal array object sizes.
static const size_t OMS_ARROBJ_OPTSIZES[] = {
  16,   24,   32,   40,   56,   72,   88, 104,
    120,  144,  168,  192,  216,  248,  280, 328, 
    376,  424,  480,  552,  648,  784,  872, 984, 
    1128, 1320, 1592, 2000, 2672, 4024, 8076 };

/*----------------------------------------------------------------------*/

size_t OmsArrayObjectBase::omsGetClassSize(size_t sizeClass)
{
  if (sizeClass >= OMS_ARROBJ_OPTSIZECNT) {
    ThrowInvalidParam(__MY_FILE__, __LINE__);
  }
  return OMS_ARROBJ_OPTSIZES[sizeClass];
}

/*----------------------------------------------------------------------*/

size_t OmsArrayObjectBase::omsGetSizeClass(size_t byteSize)
{
  if (byteSize < 1 || byteSize > OMS_ARROBJ_OPTSIZES[OMS_ARROBJ_OPTSIZECNT-1]) {
    ThrowInvalidParam(__MY_FILE__, __LINE__);
  }
  const size_t *p = OMS_ARROBJ_OPTSIZES;
  // linear search performs for small number of entries (32)
  // better than binary...
  while (*p < byteSize) ++p;
  return p - OMS_ARROBJ_OPTSIZES;
}

/*----------------------------------------------------------------------*/

void OmsArrayObjectBase::omsRegisterArray(OmsHandle &h, int ClsGuid,
  OmsSchemaHandle sh, OmsContainerNo contId, size_t realSize,
  size_t capacity, const char *typname, OmsAbstractObject *regobj)
{
  char buffer[128];
  sp77sprintf(buffer, sizeof(buffer), "OmsArrayObject<%s>[%d]", 
    typname, capacity);

  OmsAbstractObject::omsRegClass(
    h, ClsGuid, buffer,
    realSize, // persistent size
    realSize, // object size
    NULL, // base class 
    regobj, sh, contId, realSize);
}

/*----------------------------------------------------------------------*/

void OmsArrayObjectBase::ThrowInvalidParam(const char *pFile, unsigned int line)
{
  throw DbpError(DbpError::DB_ERROR, e_illegal_object_pos, "Invalid array object index or size", pFile, line);
}

/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/

void OmsArrayObjectIteratorBase::omsDropContainer()
{
  h.omsDropContainer(guid, sh, rcn, OmsArrayObjectBase::omsGetClassSize(rcn >> 20));
}

/*----------------------------------------------------------------------*/

void OmsArrayObjectIteratorBase::omsDeleteAll()
{
  h.omsDeleteAll(guid, sh, rcn);
}

/*----------------------------------------------------------------------*/

void OmsArrayObjectIteratorBase::omsNext()
{
  if (rcn == 0) {
    szclass = 0;
  } else {
    ++szclass;
  }
  while (szclass < OMS_ARROBJ_OPTSIZECNT) {
    // check if exists
    rcn = cno | (szclass << 20);
    if (h.omsIsRegistered(guid, sh, rcn)) {
      break;
    }
    ++szclass;
  }

  if (szclass >= OMS_ARROBJ_OPTSIZECNT) {
    // does not exist
    rcn = 0;
    szclass = 0;
    return;
  }
}

/*----------------------------------------------------------------------*/

OmsObjByClsIterBase OmsArrayObjectIteratorBase::omsAllOids(int maxBufferSize)
{ 
  return OmsAbstractObject::omsAllOids(h, guid, sh, rcn, maxBufferSize);
}

/*----------------------------------------------------------------------*/
