Home | History | Annotate | Download | only in cpp
      1 /**
      2  * Contents of this file are snippets from node.cc
      3  * see http://www.nodejs.org/
      4  *
      5  * Node's license follows:
      6  *
      7  * Copyright 2009, 2010 Ryan Lienhart Dahl. All rights reserved.
      8  * Permission is hereby granted, free of charge, to any person obtaining a copy
      9  * of this software and associated documentation files (the "Software"), to
     10  * deal in the Software without restriction, including without limitation the
     11  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     12  * sell copies of the Software, and to permit persons to whom the Software is
     13  * furnished to do so, subject to the following conditions:
     14  */
     15 #include <v8.h>
     16 #include <string.h>
     17 
     18 #include "logging.h"
     19 #include "node_object_wrap.h"
     20 
     21 #include "node_util.h"
     22 
     23 enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v, enum encoding _default) {
     24   v8::HandleScope scope;
     25 
     26   if (!encoding_v->IsString()) return _default;
     27 
     28   v8::String::Utf8Value encoding(encoding_v->ToString());
     29 
     30   if (strcasecmp(*encoding, "utf8") == 0) {
     31     return UTF8;
     32   } else if (strcasecmp(*encoding, "utf-8") == 0) {
     33     return UTF8;
     34   } else if (strcasecmp(*encoding, "ascii") == 0) {
     35     return ASCII;
     36   } else if (strcasecmp(*encoding, "binary") == 0) {
     37     return BINARY;
     38   } else if (strcasecmp(*encoding, "raw") == 0) {
     39     fprintf(stderr, "'raw' (array of integers) has been removed. "
     40                     "Use 'binary'.\n");
     41     return BINARY;
     42   } else if (strcasecmp(*encoding, "raws") == 0) {
     43     fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
     44                     "Please update your code.\n");
     45     return BINARY;
     46   } else {
     47     return _default;
     48   }
     49 }
     50 
     51 v8::Local<v8::Value> Encode(const void *buf, size_t len, enum encoding encoding) {
     52   v8::HandleScope scope;
     53 
     54   if (!len) return scope.Close(v8::String::Empty());
     55 
     56   if (encoding == BINARY) {
     57     const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
     58     uint16_t * twobytebuf = new uint16_t[len];
     59     for (size_t i = 0; i < len; i++) {
     60       // XXX is the following line platform independent?
     61       twobytebuf[i] = cbuf[i];
     62     }
     63     v8::Local<v8::String> chunk = v8::String::New(twobytebuf, len);
     64     delete [] twobytebuf; // TODO use ExternalTwoBytev8::String?
     65     return scope.Close(chunk);
     66   }
     67 
     68   // utf8 or ascii encoding
     69   v8::Local<v8::String> chunk = v8::String::New((const char*)buf, len);
     70   return scope.Close(chunk);
     71 }
     72 
     73 // Returns -1 if the handle was not valid for decoding
     74 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
     75   v8::HandleScope scope;
     76 
     77   if (val->IsArray()) {
     78     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
     79                     "Use 'binary'.\n");
     80     assert(0);
     81     return -1;
     82   }
     83 
     84   v8::Local<v8::String> str = val->ToString();
     85 
     86   if (encoding == UTF8) return str->Utf8Length();
     87 
     88   return str->Length();
     89 }
     90 
     91 #ifndef MIN
     92 # define MIN(a, b) ((a) < (b) ? (a) : (b))
     93 #endif
     94 
     95 // Returns number of bytes written.
     96 ssize_t DecodeWrite(char *buf,
     97                     size_t buflen,
     98                     v8::Handle<v8::Value> val,
     99                     enum encoding encoding) {
    100   v8::HandleScope scope;
    101 
    102   // XXX
    103   // A lot of improvement can be made here. See:
    104   // http://code.google.com/p/v8/issues/detail?id=270
    105   // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
    106   // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
    107 
    108   if (val->IsArray()) {
    109     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
    110                     "Use 'binary'.\n");
    111     assert(0);
    112     return -1;
    113   }
    114 
    115   v8::Local<v8::String> str = val->ToString();
    116 
    117   if (encoding == UTF8) {
    118     str->WriteUtf8(buf, buflen, NULL, v8::String::HINT_MANY_WRITES_EXPECTED);
    119     return buflen;
    120   }
    121 
    122   if (encoding == ASCII) {
    123     str->WriteAscii(buf, 0, buflen, v8::String::HINT_MANY_WRITES_EXPECTED);
    124     return buflen;
    125   }
    126 
    127   // THIS IS AWFUL!!! FIXME
    128 
    129   assert(encoding == BINARY);
    130 
    131   uint16_t * twobytebuf = new uint16_t[buflen];
    132 
    133   str->Write(twobytebuf, 0, buflen, v8::String::HINT_MANY_WRITES_EXPECTED);
    134 
    135   for (size_t i = 0; i < buflen; i++) {
    136     unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
    137     assert(b[1] == 0);
    138     buf[i] = b[0];
    139   }
    140 
    141   delete [] twobytebuf;
    142 
    143   return buflen;
    144 }
    145