text: #include <fstream>
  #include <iostream>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string>
  
  #include <R.h>
  #include <Rdefines.h>
  #include <Rinternals.h>
  
  #include "indigo-renderer.h"
  #include "indigo.h"
  
  #ifndef REXPORT_SYMBOL
  #ifdef _WIN32
  #define REXPORT_SYMBOL __declspec(dllexport)
  #else
  #define REXPORT_SYMBOL
  #endif
  #endif
  
  #ifndef REXPORT
  #ifndef __cplusplus
  #define REXPORT REXPORT_SYMBOL
  #else
  #define REXPORT extern "C" REXPORT_SYMBOL
  #endif
  #endif
  
  static void _setStringToSTRSXP(SEXP* result, const char* str)
  {
      if (str != NULL)
          SET_STRING_ELT(*result, 0, mkChar(str));
      else
          SET_STRING_ELT(*result, 0, NA_STRING);
  }
  
  REXPORT SEXP r_indigoVersion()
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
      _setStringToSTRSXP(&result, indigoVersion());
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoGetLastError()
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
      _setStringToSTRSXP(&result, indigoGetLastError());
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoAllocSessionId()
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
      INTEGER(result)[0] = indigoAllocSessionId();
      UNPROTECT(1);
      return result;
  }
  
  REXPORT void r_indigoSetSessionId(SEXP id)
  {
      indigoSetSessionId(INTEGER(id)[0]);
  }
  
  REXPORT void r_indigoReleaseSessionId(SEXP id)
  {
      indigoReleaseSessionId(INTEGER(id)[0]);
  }
  
  REXPORT void r_indigoFree(SEXP obj_id)
  {
      indigoFree(INTEGER(obj_id)[0]);
  }
  
  REXPORT SEXP r_indigoLoadMolecule(SEXP data)
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
      INTEGER(result)[0] = indigoLoadMoleculeFromString(CHAR(STRING_ELT(data, 0)));
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoLoadQueryMolecule(SEXP data)
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
      INTEGER(result)[0] = indigoLoadQueryMoleculeFromString(CHAR(STRING_ELT(data, 0)));
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoCanonicalSmiles(SEXP mol)
  {
      const char* con_smiles = indigoCanonicalSmiles(INTEGER(mol)[0]);
  
      SEXP result = PROTECT(allocVector(STRSXP, 1));
      _setStringToSTRSXP(&result, con_smiles);
  
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoFingerprint(SEXP mol, SEXP mode)
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
      INTEGER(result)[0] = indigoFingerprint(INTEGER(mol)[0], CHAR(STRING_ELT(mode, 0)));
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoMolecularWeight(SEXP mol)
  {
      SEXP result = PROTECT(allocVector(REALSXP, 1));
      REAL(result)[0] = indigoMolecularWeight(INTEGER(mol)[0]);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoSetOption(SEXP option, SEXP value)
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
      SEXPTYPE val_type = TYPEOF(value);
  
      const char* opt_str = CHAR(STRING_ELT(option, 0));
      int set_result = -1;
  
      printf("val_type=%d\n", val_type);
  
      if (val_type == LGLSXP)
          set_result = indigoSetOptionBool(opt_str, LOGICAL(value)[0]);
      else if (val_type == INTSXP)
          set_result = indigoSetOptionInt(opt_str, INTEGER(value)[0]);
      else if (val_type == REALSXP)
          set_result = indigoSetOptionFloat(opt_str, REAL(value)[0]);
      else if (val_type == STRSXP)
          set_result = indigoSetOption(opt_str, CHAR(STRING_ELT(value, 0)));
  
      INTEGER(result)[0] = set_result;
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoResetOptions()
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
      int set_result = indigoResetOptions();
  
      INTEGER(result)[0] = set_result;
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP r_indigoLayout(SEXP item)
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
  
      INTEGER(result)[0] = indigoLayout(INTEGER(item)[0]);
      UNPROTECT(1);
  
      return result;
  }
  
  REXPORT SEXP r_indigoAromatize(SEXP obj)
  {
      SEXP result = PROTECT(allocVector(INTSXP, 1));
      INTEGER(result)[0] = indigoAromatize(INTEGER(obj)[0]);
      UNPROTECT(1);
      return result;
  }
  
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  
  REXPORT SEXP canonicalSmiles(SEXP data)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
  
      int m = indigoLoadMoleculeFromString(CHAR(STRING_ELT(data, 0)));
      _setStringToSTRSXP(&result, indigoCanonicalSmiles(m));
      indigoFree(m);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP smiles(SEXP data)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
  
      int m = indigoLoadMoleculeFromString(CHAR(STRING_ELT(data, 0)));
      _setStringToSTRSXP(&result, indigoSmiles(m));
      indigoFree(m);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT void setFingerprintParams()
  {
      indigoSetOptionInt("fp-ord-qwords", 25);
      indigoSetOptionInt("fp-sim-qwords", 8);
      indigoSetOptionInt("fp-any-qwords", 15);
      indigoSetOptionInt("fp-tau-qwords", 0);
      indigoSetOptionInt("fp-ext-enabled", 0);
      indigoSetOption("similarity-type", "SIM");
  }
  
  REXPORT SEXP aromatize(SEXP mol)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
  
      int m = indigoLoadMoleculeFromString(CHAR(STRING_ELT(mol, 0)));
      indigoAromatize(m);
      const char* ar_m = indigoCanonicalSmiles(m);
      _setStringToSTRSXP(&result, ar_m);
      indigoFree(m);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP aromatizeQuery(SEXP mol)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
  
      int m = indigoLoadQueryMoleculeFromString(CHAR(STRING_ELT(mol, 0)));
      indigoAromatize(m);
      const char* ar_m = indigoSmiles(m);
      _setStringToSTRSXP(&result, ar_m);
      indigoFree(m);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP checkSub(SEXP query, SEXP target, SEXP mode)
  {
      int q = indigoLoadQueryMoleculeFromString(CHAR(STRING_ELT(query, 0)));
      int t = indigoLoadMoleculeFromString(CHAR(STRING_ELT(target, 0)));
      int matcher = indigoSubstructureMatcher(t, CHAR(STRING_ELT(mode, 0)));
      SEXP smatch;
      PROTECT(smatch = NEW_INTEGER(1));
  
      int match_res = indigoMatch(matcher, q);
  
      INTEGER(smatch)[0] = match_res;
  
      indigoFree(q);
      indigoFree(t);
      indigoFree(matcher);
      indigoFree(match_res);
  
      UNPROTECT(1);
      return smatch;
  }
  
  const char* _makeOnesListStr(int mol, const char* mode)
  {
      if (mol == -1)
          return NULL;
  
      int fp = indigoFingerprint(mol, mode);
      if (fp == -1)
          return NULL;
  
      const char* ones_list = indigoOneBitsList(fp);
  
      indigoFree(fp);
      return ones_list;
  }
  
  REXPORT SEXP fingerprint(SEXP item, SEXP mode)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
      SET_STRING_ELT(result, 0, mkChar(""));
  
      int i = indigoLoadMoleculeFromString(CHAR(STRING_ELT(item, 0)));
  
      const char* ones_list = _makeOnesListStr(i, CHAR(STRING_ELT(mode, 0)));
  
      if (ones_list != NULL)
          SET_STRING_ELT(result, 0, mkChar(ones_list));
  
      indigoFree(i);
      UNPROTECT(1);
  
      return result;
  }
  
  REXPORT SEXP fingerprintQuery(SEXP item, SEXP mode)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
      SET_STRING_ELT(result, 0, mkChar(""));
  
      int i = indigoLoadQueryMoleculeFromString(CHAR(STRING_ELT(item, 0)));
  
      const char* ones_list = _makeOnesListStr(i, CHAR(STRING_ELT(mode, 0)));
  
      if (ones_list != NULL)
          SET_STRING_ELT(result, 0, mkChar(ones_list));
  
      indigoFree(i);
      UNPROTECT(1);
  
      return result;
  }
  
  REXPORT SEXP molecularWeight(SEXP item)
  {
      SEXP result = PROTECT(allocVector(REALSXP, 1));
      int i = indigoLoadMoleculeFromString(CHAR(STRING_ELT(item, 0)));
      REAL(result)[0] = indigoMolecularWeight(i);
      indigoFree(i);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP render(SEXP item)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
  
      char* raw_ptr;
      int size;
  
      indigoSetOption("render-output-format", "svg");
      indigoSetOption("render-background-color", "255, 255, 255");
  
      int mol = indigoLoadMoleculeFromString(CHAR(STRING_ELT(item, 0)));
      indigoLayout(mol);
      int buffer_object = indigoWriteBuffer();
      int render_res = indigoRender(mol, buffer_object);
      const char* svg_str = indigoToString(buffer_object);
  
      SET_STRING_ELT(result, 0, mkChar(svg_str));
      indigoFree(buffer_object);
      indigoFree(mol);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP renderQuery(SEXP item)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
  
      char* raw_ptr;
      int size;
  
      indigoSetOption("render-output-format", "svg");
      indigoSetOption("render-background-color", "255, 255, 255");
  
      int mol = indigoLoadQueryMoleculeFromString(CHAR(STRING_ELT(item, 0)));
      indigoLayout(mol);
      int buffer_object = indigoWriteBuffer();
      int render_res = indigoRender(mol, buffer_object);
      const char* svg_str = indigoToString(buffer_object);
  
      SET_STRING_ELT(result, 0, mkChar(svg_str));
      indigoFree(buffer_object);
      indigoFree(mol);
      UNPROTECT(1);
      return result;
  }
  
  REXPORT SEXP renderHighlightedTarget(SEXP target, SEXP query)
  {
      SEXP result = PROTECT(allocVector(STRSXP, 1));
  
      char* raw_ptr;
      int size;
  
      indigoSetOption("render-output-format", "svg");
      indigoSetOption("render-background-color", "255, 255, 255");
  
      int q = indigoLoadQueryMoleculeFromString(CHAR(STRING_ELT(query, 0)));
      int t = indigoLoadMoleculeFromString(CHAR(STRING_ELT(target, 0)));
      int m = indigoSubstructureMatcher(t, "");
      int res = 0;
      res = indigoMatch(m, q);
  
      int ht = indigoHighlightedTarget(res);
  
      indigoLayout(ht);
      int buffer_object = indigoWriteBuffer();
      int render_res = indigoRender(ht, buffer_object);
      const char* svg_str = indigoToString(buffer_object);
  
      SET_STRING_ELT(result, 0, mkChar(svg_str));
      indigoFree(buffer_object);
      indigoFree(ht);
      UNPROTECT(1);
      return result;
  }
  