summaryrefslogtreecommitdiff
path: root/src/string_bytes.h
blob: 79520d24705ac0ddda336cd6197c8f6d8b093b79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#ifndef SRC_STRING_BYTES_H_
#define SRC_STRING_BYTES_H_

// Decodes a v8::Local<v8::String> or Buffer to a raw char*

#include "v8.h"
#include "node.h"
#include "env.h"
#include "env-inl.h"

namespace node {

class StringBytes {
 public:
  class InlineDecoder {
   public:
    InlineDecoder() : out_(nullptr) {
    }

    ~InlineDecoder() {
      if (out_ != out_st_)
        delete[] out_;
      out_ = nullptr;
    }

    inline bool Decode(Environment* env,
                       v8::Local<v8::String> string,
                       v8::Local<v8::Value> encoding,
                       enum encoding _default) {
      enum encoding enc = ParseEncoding(env->isolate(), encoding, _default);
      if (!StringBytes::IsValidString(env->isolate(), string, enc)) {
        env->ThrowTypeError("Bad input string");
        return false;
      }

      size_t buflen = StringBytes::StorageSize(env->isolate(), string, enc);
      if (buflen > sizeof(out_st_))
        out_ = new char[buflen];
      else
        out_ = out_st_;
      size_ = StringBytes::Write(env->isolate(),
                                 out_,
                                 buflen,
                                 string,
                                 enc);
      return true;
    }

    inline const char* out() const { return out_; }
    inline size_t size() const { return size_; }

   private:
    static const int kStorageSize = 1024;

    char out_st_[kStorageSize];
    char* out_;
    size_t size_;
  };

  // Does the string match the encoding? Quick but non-exhaustive.
  // Example: a HEX string must have a length that's a multiple of two.
  // FIXME(bnoordhuis) IsMaybeValidString()? Naming things is hard...
  static bool IsValidString(v8::Isolate* isolate,
                            v8::Local<v8::String> string,
                            enum encoding enc);

  // Fast, but can be 2 bytes oversized for Base64, and
  // as much as triple UTF-8 strings <= 65536 chars in length
  static size_t StorageSize(v8::Isolate* isolate,
                            v8::Local<v8::Value> val,
                            enum encoding enc);

  // Precise byte count, but slightly slower for Base64 and
  // very much slower for UTF-8
  static size_t Size(v8::Isolate* isolate,
                     v8::Local<v8::Value> val,
                     enum encoding enc);

  // If the string is external then assign external properties to data and len,
  // then return true. If not return false.
  static bool GetExternalParts(v8::Isolate* isolate,
                               v8::Local<v8::Value> val,
                               const char** data,
                               size_t* len);

  // Write the bytes from the string or buffer into the char*
  // returns the number of bytes written, which will always be
  // <= buflen.  Use StorageSize/Size first to know how much
  // memory to allocate.
  static size_t Write(v8::Isolate* isolate,
                      char* buf,
                      size_t buflen,
                      v8::Local<v8::Value> val,
                      enum encoding enc,
                      int* chars_written = nullptr);

  // Take the bytes in the src, and turn it into a Buffer or String.
  // Don't call with encoding=UCS2.
  static v8::Local<v8::Value> Encode(v8::Isolate* isolate,
                                     const char* buf,
                                     size_t buflen,
                                     enum encoding encoding);

  // The input buffer should be in host endianness.
  static v8::Local<v8::Value> Encode(v8::Isolate* isolate,
                                     const uint16_t* buf,
                                     size_t buflen);

  // Deprecated legacy interface

  NODE_DEPRECATED("Use IsValidString(isolate, ...)",
                  static inline bool IsValidString(
      v8::Local<v8::String> string,
      enum encoding enc) {
    return IsValidString(v8::Isolate::GetCurrent(), string, enc);
  })

  NODE_DEPRECATED("Use StorageSize(isolate, ...)",
                  static inline size_t StorageSize(v8::Local<v8::Value> val,
                                                  enum encoding enc) {
    return StorageSize(v8::Isolate::GetCurrent(), val, enc);
  })

  NODE_DEPRECATED("Use Size(isolate, ...)",
                  static inline size_t Size(v8::Local<v8::Value> val,
                                            enum encoding enc) {
    return Size(v8::Isolate::GetCurrent(), val, enc);
  })

  NODE_DEPRECATED("Use GetExternalParts(isolate, ...)",
                  static inline bool GetExternalParts(v8::Local<v8::Value> val,
                                                      const char** data,
                                                      size_t* len) {
    return GetExternalParts(v8::Isolate::GetCurrent(), val, data, len);
  })

  NODE_DEPRECATED("Use Write(isolate, ...)",
                  static inline size_t Write(char* buf,
                                             size_t buflen,
                                             v8::Local<v8::Value> val,
                                             enum encoding enc,
                                             int* chars_written = nullptr) {
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    return Write(isolate, buf, buflen, val, enc, chars_written);
  })

  NODE_DEPRECATED("Use Encode(isolate, ...)",
                  static inline v8::Local<v8::Value> Encode(
      const char* buf,
      size_t buflen,
      enum encoding encoding) {
    return Encode(v8::Isolate::GetCurrent(), buf, buflen, encoding);
  })

 private:
  static size_t WriteUCS2(char* buf,
                          size_t buflen,
                          size_t nbytes,
                          const char* data,
                          v8::Local<v8::String> str,
                          int flags,
                          size_t* chars_written);
};

}  // namespace node

#endif  // SRC_STRING_BYTES_H_