/*
 *  Copyright (c) 2006-2007 Jan Behrens, FlexiGuided GmbH, Berlin
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 */


/*
 *  File name:    ruby/utf8proc_native.c
 *  Version:      1.1.1
 *  Last changed: 2007-07-22
 *
 *  Description:
 *  Native part of the ruby wrapper for libutf8proc.
 */


#include "../utf8proc.c"
#include "ruby.h"

typedef struct utf8proc_ruby_mapenv_struct {
  int32_t *buffer;
} utf8proc_ruby_mapenv_t;

void utf8proc_ruby_mapenv_free(utf8proc_ruby_mapenv_t *env) {
  free(env->buffer);
  free(env);
}

VALUE utf8proc_ruby_module;
VALUE utf8proc_ruby_options;
VALUE utf8proc_ruby_eUnicodeError;
VALUE utf8proc_ruby_eInvalidUtf8Error;
VALUE utf8proc_ruby_eCodeNotAssignedError;

VALUE utf8proc_ruby_map_error(ssize_t result) {
  VALUE excpt_class;
  switch (result) {
    case UTF8PROC_ERROR_NOMEM:
    excpt_class = rb_eNoMemError; break;
    case UTF8PROC_ERROR_OVERFLOW:
    case UTF8PROC_ERROR_INVALIDOPTS:
    excpt_class = rb_eArgError; break;
    case UTF8PROC_ERROR_INVALIDUTF8:
    excpt_class = utf8proc_ruby_eInvalidUtf8Error; break;
    case UTF8PROC_ERROR_NOTASSIGNED:
    excpt_class = utf8proc_ruby_eCodeNotAssignedError; break;
    default:
    excpt_class = rb_eRuntimeError;
  }
  rb_raise(excpt_class, "%s", utf8proc_errmsg(result));
  return Qnil;
}

VALUE utf8proc_ruby_map(VALUE self, VALUE str_param, VALUE options_param) {
  VALUE str;
  int options;
  VALUE env_obj;
  utf8proc_ruby_mapenv_t *env;
  ssize_t result;
  VALUE retval;
  str = StringValue(str_param);
  options = NUM2INT(options_param) & ~UTF8PROC_NULLTERM;
  env_obj = Data_Make_Struct(rb_cObject, utf8proc_ruby_mapenv_t, NULL,
    utf8proc_ruby_mapenv_free, env);
  result = utf8proc_decompose(RSTRING(str)->ptr, RSTRING(str)->len,
    NULL, 0, options);
  if (result < 0) {
    utf8proc_ruby_map_error(result);
    return Qnil;  // needed to prevent problems with optimization
  }
  env->buffer = ALLOC_N(int32_t, result+1);
  result = utf8proc_decompose(RSTRING(str)->ptr, RSTRING(str)->len,
    env->buffer, result, options);
  if (result < 0) {
    free(env->buffer);
    env->buffer = 0;
    utf8proc_ruby_map_error(result);
    return Qnil;  // needed to prevent problems with optimization
  }
  result = utf8proc_reencode(env->buffer, result, options);
  if (result < 0) {
    free(env->buffer);
    env->buffer = 0;
    utf8proc_ruby_map_error(result);
    return Qnil;  // needed to prevent problems with optimization
  }
  retval = rb_str_new((char *)env->buffer, result);
  free(env->buffer);
  env->buffer = 0;
  return retval;
}

static VALUE utf8proc_ruby_char(VALUE self, VALUE code_param) {
  char buffer[4];
  ssize_t result;
  int uc;
  uc = NUM2INT(code_param);
  if (!utf8proc_codepoint_valid(uc))
    rb_raise(rb_eArgError, "Invalid Unicode code point");
  result = utf8proc_encode_char(uc, buffer);
  return rb_str_new(buffer, result);
}

#define register_utf8proc_option(sym, field) \
  rb_hash_aset(utf8proc_ruby_options, ID2SYM(rb_intern(sym)), INT2FIX(field))

void Init_utf8proc_native() {
  utf8proc_ruby_module = rb_define_module("Utf8Proc");
  rb_define_module_function(utf8proc_ruby_module, "utf8map",
    utf8proc_ruby_map, 2);
  rb_define_module_function(utf8proc_ruby_module, "utf8char",
    utf8proc_ruby_char, 1);
  utf8proc_ruby_eUnicodeError = rb_define_class_under(utf8proc_ruby_module,
    "UnicodeError", rb_eStandardError);
  utf8proc_ruby_eInvalidUtf8Error = rb_define_class_under(
    utf8proc_ruby_module, "InvalidUtf8Error", utf8proc_ruby_eUnicodeError);
  utf8proc_ruby_eCodeNotAssignedError = rb_define_class_under(
    utf8proc_ruby_module, "CodeNotAssignedError",
    utf8proc_ruby_eUnicodeError);
  utf8proc_ruby_options = rb_hash_new();
  register_utf8proc_option("stable",    UTF8PROC_STABLE);
  register_utf8proc_option("compat",    UTF8PROC_COMPAT);
  register_utf8proc_option("compose",   UTF8PROC_COMPOSE);
  register_utf8proc_option("decompose", UTF8PROC_DECOMPOSE);
  register_utf8proc_option("ignore",    UTF8PROC_IGNORE);
  register_utf8proc_option("rejectna",  UTF8PROC_REJECTNA);
  register_utf8proc_option("nlf2ls",    UTF8PROC_NLF2LS);
  register_utf8proc_option("nlf2ps",    UTF8PROC_NLF2PS);
  register_utf8proc_option("nlf2lf",    UTF8PROC_NLF2LF);
  register_utf8proc_option("stripcc",   UTF8PROC_STRIPCC);
  register_utf8proc_option("casefold",  UTF8PROC_CASEFOLD);
  register_utf8proc_option("charbound", UTF8PROC_CHARBOUND);
  register_utf8proc_option("lump",      UTF8PROC_LUMP);
  register_utf8proc_option("stripmark", UTF8PROC_STRIPMARK);
  OBJ_FREEZE(utf8proc_ruby_options);
  rb_define_const(utf8proc_ruby_module, "Options", utf8proc_ruby_options);
}

