static CharsetMap::RecodeStatus
    CharsetMap__recode
    ( const CharsetMap & obj, Int32 * p0, int p1, int p2, const void * p3, void * p4 )
    {
#ifdef assert
        assert(sizeof(int32_t) == sizeof(Int32));
#endif
        return obj.recode((Int32*)p0, p1, p2, p3, p4);
    }
Handle<Value> CharsetMap_recode_out(const Arguments &args) {
  HandleScope scope;
  
  REQUIRE_ARGS_LENGTH(5);
 
  JsValueConverter<CharsetMap *> converter(args.Holder());
  CharsetMap * csmap = converter.toC();

  int32_t lengths[2]; 
  enum { SOURCE = 0 , DEST = 1 };  // for lengths[]
  int status = CharsetMap::RECODE_OK;

  Local<Value> result = String::Empty();
  
  Local<Object> NodeBuffer = args[0]->ToObject();
  char * buffer            = node::Buffer::Data(NodeBuffer);
  uint32_t offset          = args[1]->Uint32Value();
  lengths[SOURCE]          = args[2]->Int32Value();
  int32_t cs_from          = args[3]->Int32Value();
  Local<Object> statusObj  = args[4]->ToObject();
  
  /* Destination charset */
  int32_t cs_to            = csmap->getUTF16CharsetNumber();

  /* Special case: source string is UTF-8 */
  if(cs_from == csmap->getUTF8CharsetNumber()) {
    result = String::New(buffer + offset, lengths[SOURCE]);
  }

  /* General case */
  else {
    lengths[DEST] = lengths[SOURCE] * 2;  
    char * target = new char[lengths[DEST]];
    status = csmap->recode(lengths, cs_from, cs_to, buffer + offset, target);
    if(status == CharsetMap::RECODE_OK) {
      result = String::New(target, lengths[DEST]);
    }
	delete[] target;
  }

  // statusObj->Set(String::NewSymbol("status"), Integer::New(status));
  return scope.Close(result);
}
Handle<Value> CharsetMap_recode_in(const Arguments &args) {
  HandleScope scope;
  DEBUG_MARKER(UDEB_DEBUG);
  
  REQUIRE_ARGS_LENGTH(5);

  JsValueConverter<CharsetMap *> converter(args.Holder());
  CharsetMap * csmap = converter.toC();
  
  int32_t lengths[2]; 
  enum { SOURCE = 0 , DEST = 1 };  // for lengths[]
  int status = CharsetMap::RECODE_OK;
  int copyLen;
  
  Local<Object> NodeBuffer = args[2]->ToObject();
  Local<String> sourceStr  = args[0]->ToString();
  int32_t cs_to            = args[1]->Int32Value();
  char * buffer            = node::Buffer::Data(NodeBuffer);
  uint32_t offset          = args[3]->Uint32Value();
  lengths[DEST]            = args[4]->Int32Value();

  /* Source string length and charset */
  int32_t cs_from          = csmap->getUTF16CharsetNumber();
  lengths[SOURCE]          = sourceStr->Length();

  /* Special case: if the destination is 2-byte unicode, just copy directly. 
     sourceStr->Write(uint16_t * ...) might face alignment issues, so we use
     memcpy().
  */
  if(cs_to == cs_from) {
    if(lengths[DEST] >= lengths[SOURCE]) {
      copyLen = lengths[SOURCE];
    }
    else {
      copyLen = lengths[DEST];
      status = csmap->RECODE_BUFF_TOO_SMALL;
    }
    DEBUG_PRINT("recodeIn() optimized path UTF16 -> UTF16 using memcpy");
    String::Value source(sourceStr);
    memcpy(buffer + offset, *source, copyLen);
    lengths[DEST] = copyLen;
  }
  
  /* Special case: if the destination is UTF-8, let V8 do the copying. 
     copyLen will receive the length written in characters.
     The return value is the length written in bytes.
  */
  else if(cs_to == csmap->getUTF8CharsetNumber()) {
    lengths[DEST] = sourceStr->WriteUtf8(buffer + offset, lengths[DEST], 
                                         &copyLen, 1);
    if(copyLen < sourceStr->Length()) {
      status = CharsetMap::RECODE_BUFF_TOO_SMALL;
    }                                         
    DEBUG_PRINT("recodeIn() UTF16 -> UTF8 using v8 WriteUtf8(): %s",
                buffer + offset);
  }
  
  /* General case: use CharsetMap::recode() */
  else {
    String::Value source(sourceStr);
    status = csmap->recode(lengths, cs_from, cs_to, *source, buffer + offset);
    DEBUG_PRINT("recodeIn() UTF16 -> X using recode(%c%c%c%c...): %s", 
                (*source)[1], (*source)[3], (*source)[5], (*source)[7],
                buffer + offset);
  }

  /* Build the return value */
  Local<Object> returnVal = Object::New();
  returnVal->Set(String::NewSymbol("status"), Integer::New(status));
  returnVal->Set(String::NewSymbol("lengthIn"), Integer::New(lengths[SOURCE]));
  returnVal->Set(String::NewSymbol("lengthOut"), Integer::New(lengths[DEST]));
  returnVal->Set(String::NewSymbol("charset"), args[1]);
  returnVal->Set(String::NewSymbol("offset"), Integer::New(offset));
  
  return scope.Close(returnVal);
}
 static int
 CharsetMap__getUTF16CharsetNumber
 ( const CharsetMap & obj )
 {
     return obj.getUTF16CharsetNumber();
 }
 static int
 CharsetMap__getCharsetNumber
 ( const CharsetMap & obj, const char * p0 )
 {
     return obj.getCharsetNumber(p0);
 }