/* guile-xapian --- Guile bindings for Xapian
 * Copyright © 2020 Arun Isaac <arunisaac@systemreboot.net>
 * Copyright © 2021 Bob131 <bob@bob131.so>
 *
 * This file is part of guile-xapian.
 *
 * guile-xapian 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.
 *
 * guile-xapian 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 guile-xapian.  If not, see
 * <https://www.gnu.org/licenses/>.
 */

%module wrap
%{
%}

%scheme
%{
;; Try loading the shared library by absolute path. If that fails, try
;; searching for it using LD_LIBRARY_PATH and other mechanisms. We do this
;; so that guile-xapian finds libguilexapian both before and after installation.
(catch #t
  (lambda ()
    (load-extension "@libdir@/libguilexapian" "SWIG_init"))
  (lambda _
    (load-extension "libguilexapian" "SWIG_init")))
%}

%{
  #include <string>

  // We introduce a dummy typedef for std::string without declaring it
  // to SWIG so we can establish a new SWIG typemap applying only to
  // certain redeclarations of existing C++ functions taking or
  // returning strings.
  typedef std::string SWIG_bytevector;

  static inline void typemap_in_SWIG_bytevector (SWIG_bytevector& out, SCM in) {
    out.assign ((char*) SCM_BYTEVECTOR_CONTENTS (in),
                SCM_BYTEVECTOR_LENGTH (in));
  }

  static inline SCM typemap_out_SWIG_bytevector (const SWIG_bytevector& in) {
    SCM result = scm_c_make_bytevector (in.size ());
    memcpy (SCM_BYTEVECTOR_CONTENTS (result), in.data (), in.size ());
    return result;
  }
%}

%typemap(in) SWIG_bytevector {
  if (scm_is_bytevector ($input)) {
    $1 = std::string ();
    typemap_in_SWIG_bytevector ($1, $input);
  } else {
    %argument_fail (SWIG_TypeError, "$type", $symname, $argnum);
  }
}

%typemap(in) SWIG_bytevector&, SWIG_bytevector* {
  if (scm_is_bytevector ($input)) {
    $1 = new std::string ();
    typemap_in_SWIG_bytevector (*$1, $input);
  } else {
    %argument_fail (SWIG_TypeError, "$type", $symname, $argnum);
  }
}

%typemap(out) SWIG_bytevector {
  $result = typemap_out_SWIG_bytevector ($1);
}

%typemap(out) SWIG_bytevector&, SWIG_bytevector* {
  $result = typemap_out_SWIG_bytevector (*$1);
}

%typecheck(SWIG_TYPECHECK_SWIGOBJECT)
  SWIG_bytevector, SWIG_bytevector&, SWIG_bytevector*
{
  $1 = scm_is_bytevector ($input);
}

%include xapian-head.i
%include xapian-headers.i

%extend Xapian::ValueIterator {
  SWIG_bytevector get_value_bytes () {
    return **$self;
  }
}

%extend Xapian::Document {
  SWIG_bytevector get_value_bytes (Xapian::valueno valueno) {
    return $self->get_value (valueno);
  }

  void add_value_bytes (Xapian::valueno valueno, const SWIG_bytevector& bytes) {
    $self->add_value (valueno, bytes);
  }

  SWIG_bytevector get_data_bytes () {
    return $self->get_data ();
  }

  void set_data_bytes (const SWIG_bytevector& bytes) {
    $self->set_data (bytes);
  }
}

%extend Xapian::Database {
  SWIG_bytevector get_metadata_bytes (const std::string& key) {
    return $self->get_metadata (key);
  }
}

%extend Xapian::WritableDatabase {
  void set_metadata_bytes (const std::string& key,
                           const SWIG_bytevector& bytes)
  {
    $self->set_metadata (key, bytes);
  }
}

%extend Xapian::Query {
  Query (op op_, Xapian::valueno slot, const SWIG_bytevector& range_limit) {
    return new Xapian::Query (op_, slot, range_limit);
  }

  Query (op op_, Xapian::valueno slot,
         const SWIG_bytevector& range_lower, const SWIG_bytevector& range_upper)
  {
    return new Xapian::Query (op_, slot, range_lower, range_upper);
  }
}