
/***************************************************************************
 *   Copyright (C) 2017 by Pierre-Henri WUILLEMIN and Christophe GONZALES   *
 *   {prenom.nom}_at_lip6.fr                                               *
 *                                                                         *
 *   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.             *
 ***************************************************************************/


/*-------------------------------------------------------------------------
Compiler Generator Coco/R,
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
extended by M. Loeberbauer & A. Woess, Univ. of Linz
ported to C++ by Csaba Balazs, University of Szeged
with improvements by Pat Terry, Rhodes University

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, 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.

As an exception, it is allowed to write an extension of Coco/R that is
used as a plugin in non-free software.

If not otherwise stated, any source code generated by Coco/R (other than
Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
#include <agrum/agrum.h>
#include <agrum/core/cocoR/common.h>

#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace gum {

  wchar_t* coco_string_create(const wchar_t* value) {
    return coco_string_create(value, 0);
  }

  wchar_t* coco_string_create(const wchar_t* value, int startIndex) {
    std::size_t valueLen = 0;
    std::size_t len = 0;

    if (value) {
      valueLen = wcslen(value);
      len = valueLen - startIndex;
    }

    return coco_string_create(value, startIndex, (int)len);
  }

  wchar_t* coco_string_create(const wchar_t* value, int startIndex, int length) {
    int      len = 0;
    wchar_t* data;

    if (value) { len = length; }

    data = new wchar_t[len + 1];
    wcsncpy(data, &(value[startIndex]), len);
    data[len] = 0;

    return data;
  }

  wchar_t* coco_string_create_upper(const wchar_t* data) {
    if (!data) { return nullptr; }

    std::size_t dataLen = 0;

    if (data) { dataLen = wcslen(data); }

    wchar_t* newData = new wchar_t[dataLen + 1];

    for (int i = 0; i <= int(dataLen); i++) {
      if ((L'a' <= data[i]) && (data[i] <= L'z')) {
        newData[i] = data[i] + (L'A' - L'a');
      } else {
        newData[i] = data[i];
      }
    }

    newData[dataLen] = L'\0';
    return newData;
  }

  wchar_t* coco_string_create_lower(const wchar_t* data) {
    if (!data) { return nullptr; }

    std::size_t dataLen = wcslen(data);
    return coco_string_create_lower(data, 0, int(dataLen));
  }

  wchar_t*
     coco_string_create_lower(const wchar_t* data, int startIndex, int dataLen) {
    if (!data) { return nullptr; }

    wchar_t* newData = new wchar_t[dataLen + 1];

    for (int i = 0; i <= dataLen; i++) {
      wchar_t ch = data[startIndex + i];

      if ((L'A' <= ch) && (ch <= L'Z')) {
        newData[i] = ch - (L'A' - L'a');
      } else {
        newData[i] = ch;
      }
    }

    newData[dataLen] = L'\0';
    return newData;
  }

  wchar_t* coco_string_create_append(const wchar_t* data1, const wchar_t* data2) {
    wchar_t*    data;
    std::size_t data1Len = 0;
    std::size_t data2Len = 0;

    if (data1) { data1Len = wcslen(data1); }

    if (data2) { data2Len = wcslen(data2); }

    data = new wchar_t[data1Len + data2Len + 1];

    if (data1) { wcscpy(data, data1); }

    if (data2) { wcscpy(data + data1Len, data2); }

    data[data1Len + data2Len] = 0;

    return data;
  }

  wchar_t* coco_string_create_append(const wchar_t* target,
                                     const wchar_t  appendix) {
    int      targetLen = coco_string_length(target);
    wchar_t* data = new wchar_t[targetLen + 2];
    wcsncpy(data, target, targetLen);
    data[targetLen] = appendix;
    data[targetLen + 1] = 0;
    return data;
  }

  void coco_string_delete(wchar_t*& data) {
    delete[] data;
    data = nullptr;
  }

  int coco_string_length(const wchar_t* data) {
    if (data) { return (int)wcslen(data); }

    return 0;
  }

  bool coco_string_endswith(const wchar_t* data, const wchar_t* end) {
    std::size_t dataLen = wcslen(data);
    std::size_t endLen = wcslen(end);
    return (endLen <= dataLen) && (wcscmp(data + dataLen - endLen, end) == 0);
  }

  int coco_string_indexof(const wchar_t* data, const wchar_t value) {
    const wchar_t* chr = wcschr(data, value);

    if (chr) { return (int)(chr - data); }

    return -1;
  }

  int coco_string_lastindexof(const wchar_t* data, const wchar_t value) {
    const wchar_t* chr = wcsrchr(data, value);

    if (chr) { return (int)(chr - data); }

    return -1;
  }

  void coco_string_merge(wchar_t*& target, const wchar_t* appendix) {
    if (!appendix) { return; }

    wchar_t* data = coco_string_create_append(target, appendix);
    delete[] target;
    target = data;
  }

  bool coco_string_equal(const wchar_t* data1, const wchar_t* data2) {
    return wcscmp(data1, data2) == 0;
  }

  int coco_string_compareto(const wchar_t* data1, const wchar_t* data2) {
    return wcscmp(data1, data2);
  }

  unsigned int coco_string_hash(const wchar_t* data) {
    unsigned int h = 0;

    if (!data) { return 0; }

    while (*data != 0) {
      h = (h * 7) ^ *data;
      ++data;
    }

    return h;
  }

  // string handling, ascii character
  wchar_t* coco_string_create(const char* value) {
    std::size_t len = 0;

    if (value) { len = strlen(value); }

    wchar_t* data = new wchar_t[len + 1];

    for (std::size_t i = 0; i < len; ++i) {
      data[i] = (wchar_t)value[i];
    }

    data[len] = 0;
    return data;
  }

  char* coco_string_create_char(const wchar_t* value) {
    int   len = coco_string_length(value);
    char* res = new char[len + 1];

    for (int i = 0; i < len; ++i) {
      res[i] = (char)value[i];
    }

    res[len] = 0;
    return res;
  }

  void coco_string_delete(char*& data) {
    delete[] data;
    data = nullptr;
  }

}   // namespace gum

#endif   // DOXYGEN_SHOULD_SKIP_THIS
