/* -------------------------------------------------------------
 * SWIG library containing argc and argv multi-argument typemaps
 * ------------------------------------------------------------- */

%fragment("SWIG_AsArgcArgv", "header", fragment="SWIG_AsCharPtrAndSize") {
SWIGINTERN int
SWIG_AsArgcArgv(PyObject *input, swig_type_info *ppchar_info, size_t *argc, char ***argv, int *owner) {
  void *vptr;
  int res = SWIG_ConvertPtr(input, &vptr, ppchar_info, 0);
  if (SWIG_IsOK(res)) {
    /* seems dangerous, but the user asked for it... */
    size_t i = 0;
    if (argv && *argv) { while ((*argv)[i] != 0) ++i; }
    if (argc) *argc = i;
    if (owner) *owner = 0;
    return SWIG_OK;
  }
  PyErr_Clear();
  int is_list = PyList_Check(input);
  if (!is_list && !PyTuple_Check(input)) return SWIG_TypeError;

  size_t i;
  res = SWIG_OK;
  size_t size = is_list ? PyList_Size(input) : PyTuple_Size(input);
  if (argv != NULL) {
    char **p = %new_array(size + 1, char*);
    if (p == NULL) {
      SWIG_Error(SWIG_MemoryError, "Failed to allocate memory for 'int ARGC, char **ARGV'");
      return SWIG_ERROR;
    }
    *argv = p;
  }

  for (i = 0; i < size; ++i) {
    /* Thread safety: a list could be modified by another thread while this function
       is running, causing its elements to get dereferenced between PyList_GetItem and
       SWIG_AsCharPtrAndSize, resulting in a segfault.
       tuples are immutable, so this is not an issue for them.  */
    PyObject *obj = is_list ? SWIG_PyList_GetItemRef(input, i) : PyTuple_GetItem(input, i);
    if (!obj) {
      /* List was shrunk by another thread. Return early with SWIG_OK. */
      PyErr_Clear();
      break;
    }
    if (argv) {
      char *cptr = 0; size_t sz = 0; int alloc = 0;
      res = SWIG_AsCharPtrAndSize(obj, &cptr, &sz, &alloc);
      if (SWIG_IsOK(res)) {
        if (cptr && sz) {
          if (alloc == SWIG_NEWOBJ) {
            (*argv)[i] = cptr;
          } else {
            char *p = %new_array(sz, char);
            if (p == NULL) {
              SWIG_Error(SWIG_MemoryError, "Failed to allocate string for 'int ARGC, char **ARGV'");
              (*argv)[i] = 0;
              res = SWIG_MemoryError;
            } else {
              memcpy(p, cptr, sz);
              (*argv)[i] = p;
            }
          }
        } else {
          (*argv)[i] = 0;
        }
      }
    } else {
      res = SWIG_AsCharPtrAndSize(obj, 0, 0, 0);
    }
    if (is_list) Py_DECREF(obj);
    if (!SWIG_IsOK(res)) break;
  }
  if (argc) *argc = i;  // Covers early exits from for loop
  if (argv) (*argv)[i] = 0;
  if (owner) *owner = 1;
  return res;
}
}

/*
  This typemap works with either a char **, a python list or a python
  tuple
 */

%typemap(in,noblock=0,fragment="SWIG_AsArgcArgv") (int ARGC, char **ARGV) (int res,char **argv = 0, size_t argc = 0, int owner= 0) {
  res = SWIG_AsArgcArgv($input, $descriptor(char**), &argc, &argv, &owner);
  if (!SWIG_IsOK(res)) {
    $1 = 0; $2 = 0;
    %argument_fail(SWIG_TypeError, "int ARGC, char **ARGV", $symname, $argnum);
  } else {
    $1 = %static_cast(argc,$1_ltype);
    $2 = %static_cast(argv, $2_ltype);
  }
}

%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) {
  int res = SWIG_AsArgcArgv($input, $descriptor(char**), 0, 0, 0);
  $1 = SWIG_IsOK(res);
}

%typemap(freearg,noblock=1) (int ARGC, char **ARGV)  {
  if (owner$argnum) {
    size_t i = argc$argnum;
    while (i) %delete_array(argv$argnum[--i]);
    %delete_array(argv$argnum);
  }
}
