//========================================================================
//
// Array.cc
//
// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================

//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2013, 2017 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================

#include <config.h>

#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif

#include <stdlib.h>
#include <stddef.h>
#include <cassert>
#include "goo/gmem.h"
#include "Object.h"
#include "Array.h"

#ifdef MULTITHREADED
#  define arrayLocker()   MutexLocker locker(&mutex)
#else
#  define arrayLocker()
#endif
//------------------------------------------------------------------------
// Array
//------------------------------------------------------------------------

Array::Array(XRef *xrefA) {
  xref = xrefA;
  elems = nullptr;
  size = length = 0;
  ref = 1;
#ifdef MULTITHREADED
  gInitMutex(&mutex);
#endif
}

Array::~Array() {
  int i;

  for (i = 0; i < length; ++i)
    elems[i].free();
  gfree(elems);
#ifdef MULTITHREADED
  gDestroyMutex(&mutex);
#endif
}

Object Array::copy(XRef *xrefA) const {
  arrayLocker();
  Array *a = new Array(xrefA);
  for (int i = 0; i < length; ++i) {
    a->add(elems[i].copy());
  }
  return Object(a);
}

int Array::incRef() {
  arrayLocker();
  ++ref;
  return ref;
}

int Array::decRef() {
  arrayLocker();
  --ref;
  return ref;
}

void Array::add(Object &&elem) {
  arrayLocker();
  if (length == size) {
    if (length == 0) {
      size = 8;
    } else {
      size *= 2;
    }
    elems = (Object *)greallocn(elems, size, sizeof(Object));
  }
  elems[length].initNullAfterMalloc();
  elems[length] = std::move(elem);
  ++length;
}

void Array::remove(int i) {
  arrayLocker();
  if (i < 0 || i >= length) {
    assert(i >= 0 && i < length);
    return;
  }
  --length;
  memmove( static_cast<void*>(elems + i), elems + i + 1, sizeof(elems[0]) * (length - i) );
}

Object Array::get(int i, int recursion) const {
  if (i < 0 || i >= length) {
    return Object(objNull);
  }
  return elems[i].fetch(xref, recursion);
}

Object Array::getNF(int i) const {
  if (i < 0 || i >= length) {
    return Object(objNull);
  }
  return elems[i].copy();
}

GBool Array::getString(int i, GooString *string) const
{
  Object obj = getNF(i);
  if (obj.isString()) {
    string->clear();
    string->append(obj.getString());
    return gTrue;
  } else {
    return gFalse;
  }
}
