activerecord-ingres-adapter 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/ext/Ingres.h ADDED
@@ -0,0 +1,318 @@
1
+ /*
2
+ ** Copyright (c) 2009 Ingres Corporation
3
+ **
4
+ ** This program is free software; you can redistribute it and/or modify
5
+ ** it under the terms of the GNU General Public License version 2 as
6
+ ** published by the Free Software Foundation.
7
+ **
8
+ ** This program is distributed in the hope that it will be useful,
9
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ ** GNU General Public License for more details.
12
+ **
13
+ ** You should have received a copy of the GNU General Public License along
14
+ ** with this program; if not, write to the Free Software Foundation, Inc.,
15
+ ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+ */
17
+
18
+ /* static char Sccsid[] = "$Id$"; */
19
+
20
+ /*
21
+ ** INGRES.H
22
+ **
23
+ ** History
24
+ ** 08/24/2009 (grant.croker@ingres.com)
25
+ ** Created
26
+ ** 11/09/2009 (grant.croker@ingres.com)
27
+ ** Add the ability to set the date format for Ingres date values
28
+ ** from within Ruby
29
+ ** 03/30/2010 (grant.croker@ingres.com)
30
+ ** Fix #565 - Compilation errors with Redhat ES 5.4 (x86-64)
31
+ ** 04/07/2010 (grant.croker@ingres.com)
32
+ ** Add missing #include for version.h
33
+ */
34
+
35
+ /* #include <version.h> */
36
+
37
+ /* Constants */
38
+ #define RUBY_INGRES_VERSION "1.4.1"
39
+ #define RUBY_INGRES_API IIAPI_VERSION
40
+
41
+ #define RUBY_STRING "STRING"
42
+ #define RUBY_INTEGER "INTEGER"
43
+ #define RUBY_BYTE "BYTE"
44
+ #define RUBY_TEXT "TEXT"
45
+ #define RUBY_VARCHAR "VARCHAR"
46
+ #define RUBY_DATE "DATE"
47
+ #define RUBY_DOUBLE "DOUBLE"
48
+ #define RUBY_TINYINT "TINYINT"
49
+ #define RUBY_LOB "LOB"
50
+ #define RUBY_UNMAPPED "UNMAPPED_DATATYPE"
51
+ #define ERROR_MESSAGE_HEADER "Ingres Diagnostic Messages:\n"
52
+ #define RubyParamOffset(ip, ipc) ((ip - ipc) * (2 + ipc))
53
+
54
+ #define RUBY_NVARCHAR_PARAMETER 'N'
55
+ #define RUBY_NCHAR_PARAMETER 'n'
56
+ #define RUBY_VARCHAR_PARAMETER 'v'
57
+ #define RUBY_DECIMAL_PARAMETER 'D'
58
+ #define RUBY_LONG_BYTE_PARAMETER 'B'
59
+ #define RUBY_LONG_TEXT_PARAMETER 'T'
60
+ #define RUBY_LONG_VARCHAR_PARAMETER 'V'
61
+
62
+ #define RUBY_INTEGER_PARAMETER 'i'
63
+ #define RUBY_BYTE_PARAMETER 'b'
64
+ #define RUBY_CHAR_PARAMETER 'c'
65
+ #define RUBY_DATE_PARAMETER 'd'
66
+ #define RUBY_TEXT_PARAMETER 't'
67
+ #define RUBY_FLOAT_PARAMETER 'f'
68
+
69
+ #define DECIMAL_BUFFER_LEN 16
70
+ #define DECIMAL_PRECISION 31
71
+ #define DECIMAL_SCALE 15
72
+ #define DOUBLE_PRECISION 31
73
+ #define DOUBLE_SCALE 15
74
+ #define MAX_CHAR_SIZE 32000 /* max #bytes Ingres (var)char */
75
+ #define LOB_SEGMENT_SIZE 8192
76
+
77
+ /* Ingres 2.6 is missing a define for IIAPI_CPV_DFRMT_ISO4 */
78
+ #if !defined(IIAPI_CPV_DFRMT_ISO4)
79
+ #define IIAPI_CPV_DFRMT_ISO4 9
80
+ #endif
81
+
82
+ /* Query types */
83
+
84
+ #define INGRES_SQL_SELECT 0
85
+ #define INGRES_SQL_INSERT 1
86
+ #define INGRES_SQL_UPDATE 2
87
+ #define INGRES_SQL_DELETE 3
88
+ #define INGRES_SQL_COMMIT 4
89
+ #define INGRES_SQL_ROLLBACK 5
90
+ #define INGRES_SQL_OPEN 6
91
+ #define INGRES_SQL_CLOSE 7
92
+ #define INGRES_SQL_CONNECT 8
93
+ #define INGRES_SQL_DISCONNECT 9
94
+ #define INGRES_SQL_GETDBEVENT 10
95
+ #define INGRES_SQL_SAVEPOINT 11
96
+ #define INGRES_SQL_AUTOCOMMIT 12
97
+ #define INGRES_SQL_EXECUTE_PROCEDURE 13
98
+ #define INGRES_SQL_CALL 14
99
+ #define INGRES_SQL_COPY 15
100
+ #define INGRES_SQL_CREATE 16
101
+ #define INGRES_SQL_ALTER 17
102
+ #define INGRES_SQL_DROP 18
103
+ #define INGRES_SQL_GRANT 19
104
+ #define INGRES_SQL_REVOKE 20
105
+ #define INGRES_SQL_MODIFY 21
106
+ #define INGRES_SQL_SET 22
107
+ /* Not really an SQL Statement but INGRES_START_TRANSACTION is expected to be handled as one */
108
+ #define INGRES_START_TRANSACTION 23
109
+ #define INGRES_SQL_ROLLBACK_WORK_TO 24
110
+ #define INGRES_SQL_ROLLBACK_TO 25
111
+
112
+ #define INGRES_NO_OF_COMMANDS 26
113
+ static struct
114
+ {
115
+ char *command;
116
+ int code;
117
+ int length ;
118
+ } SQL_COMMANDS [INGRES_NO_OF_COMMANDS] =
119
+ {
120
+ { "SELECT", INGRES_SQL_SELECT, 6 },
121
+ { "INSERT", INGRES_SQL_INSERT, 6 },
122
+ { "UPDATE", INGRES_SQL_UPDATE, 6 },
123
+ { "DELETE", INGRES_SQL_DELETE, 6 },
124
+ { "COMMIT", INGRES_SQL_COMMIT, 6 },
125
+ { "ROLLBACK", INGRES_SQL_ROLLBACK, 8 },
126
+ { "OPEN", INGRES_SQL_OPEN, 4 },
127
+ { "CLOSE", INGRES_SQL_CLOSE, 5 },
128
+ { "CONNECT", INGRES_SQL_CONNECT, 7 },
129
+ { "DISCONNECT", INGRES_SQL_DISCONNECT, 10 },
130
+ { "GET DBEVENT", INGRES_SQL_GETDBEVENT, 11 },
131
+ { "SAVEPOINT", INGRES_SQL_SAVEPOINT, 9 },
132
+ { "SET AUTOCOMMIT", INGRES_SQL_AUTOCOMMIT, 14 },
133
+ { "EXECUTE PROCEDURE", INGRES_SQL_EXECUTE_PROCEDURE, 17 },
134
+ { "CALL", INGRES_SQL_CALL, 4 },
135
+ { "COPY", INGRES_SQL_COPY, 4 },
136
+ { "CREATE", INGRES_SQL_CREATE, 6 },
137
+ { "ALTER", INGRES_SQL_ALTER, 5 },
138
+ { "DROP", INGRES_SQL_DROP, 4 },
139
+ { "GRANT", INGRES_SQL_GRANT, 5 },
140
+ { "REVOKE", INGRES_SQL_REVOKE, 6 },
141
+ { "MODIFY", INGRES_SQL_MODIFY, 6 },
142
+ { "SET", INGRES_SQL_SET, 3 },
143
+ { "START TRANSACTION", INGRES_START_TRANSACTION, 17 },
144
+ { "ROLLBACK WORK TO", INGRES_SQL_ROLLBACK_WORK_TO, 16 },
145
+ { "ROLLBACK TO", INGRES_SQL_ROLLBACK_TO, 11 },
146
+ };
147
+
148
+ #define INGRES_NO_CONN_PARAMS 1
149
+ static struct
150
+ {
151
+ char *paramName;
152
+ II_LONG paramID;
153
+ } CONN_PARAMS [INGRES_NO_CONN_PARAMS] =
154
+ {
155
+ {"date_format", IIAPI_CP_DATE_FORMAT }, /* for SELECT VARCHAR(date_col) */
156
+ };
157
+
158
+ #define INGRES_NO_ENV_PARAMS 1
159
+ static struct
160
+ {
161
+ char *paramName;
162
+ II_LONG paramID;
163
+ } ENV_PARAMS [INGRES_NO_ENV_PARAMS] =
164
+ {
165
+ {"date_format", IIAPI_EP_DATE_FORMAT }, /* for SELECT date_col */
166
+ };
167
+
168
+ /* Cursor Modes */
169
+ #define INGRES_CURSOR_READONLY 0
170
+ #define INGRES_CURSOR_UPDATE 1
171
+
172
+ typedef struct _II_GLOBALS
173
+ {
174
+ II_PTR envHandle;
175
+ int debug;
176
+ int debug_connection;
177
+ int debug_sql;
178
+ int debug_termination;
179
+ int debug_transactions;
180
+ } II_GLOBALS;
181
+
182
+ typedef struct _II_SAVEPOINT_ENTRY
183
+ {
184
+ char *savePtName;
185
+ II_PTR savePtHandle;
186
+ II_PTR nextSavePtEntry;
187
+ } II_SAVEPOINT_ENTRY;
188
+
189
+ typedef struct _II_CONN
190
+ {
191
+ int autocommit;
192
+ II_PTR connHandle;
193
+ II_PTR tranHandle;
194
+ II_PTR stmtHandle;
195
+ II_PTR envHandle;
196
+ II_LONG fieldCount;
197
+ II_LONG lobSegmentSize;
198
+ IIAPI_DESCRIPTOR *descriptor;
199
+ II_CHAR *errorText;
200
+ II_CHAR sqlstate[6];
201
+ II_LONG errorCode;
202
+ int apiLevel;
203
+ int paramCount;
204
+ int allow_persistent;
205
+ int num_persistent;
206
+ char *cursor_id;
207
+ long cursor_mode;
208
+ char *currentDatabase;
209
+ int queryType;
210
+ VALUE keep_me;
211
+ VALUE resultset;
212
+ VALUE r_column_names;
213
+ VALUE r_data_sizes;
214
+ VALUE r_data_types;
215
+ II_LONG columnCount;
216
+ II_PTR savePtList;
217
+ II_SAVEPOINT_ENTRY *lastSavePtEntry;/* Pointer to the last savePtEntry on savePtList */
218
+ } II_CONN;
219
+
220
+ typedef struct _RUBY_IIAPI_DATAVALUE
221
+ {
222
+ IIAPI_DATAVALUE dataValue[1];
223
+ long dv_length;
224
+ } RUBY_IIAPI_DATAVALUE;
225
+
226
+ typedef struct _RUBY_PARAMETER
227
+ {
228
+ VALUE vkey;
229
+ VALUE vtype;
230
+ VALUE vvalue;
231
+ } RUBY_PARAMETER;
232
+
233
+ #define rb_define_singleton_alias(klass,new,old) rb_define_alias(rb_singleton_class(klass),new,old)
234
+
235
+
236
+ /*
237
+ * Function declarations
238
+ */
239
+ VALUE ii_execute (int param_argc, VALUE * param_argv, VALUE param_self);
240
+ VALUE ii_connect (int param_argc, VALUE * param_argv, VALUE param_self);
241
+ static VALUE ing_disconnect (VALUE param_self);
242
+ VALUE ing_connect (VALUE param_self, VALUE param_targetDB);
243
+ static void ii_conn_init(II_CONN *ii_conn);
244
+ VALUE ing_init (int argc, VALUE *argv, VALUE self);
245
+ void ing_api_init ();
246
+ static VALUE rb_ingres_alloc(VALUE klass);
247
+ static void free_ii_conn (II_CONN *ing_conn);
248
+ static void ing_starttransaction();
249
+ static void ing_commit();
250
+ static void ing_rollback();
251
+ VALUE ing_query (char *param_sqlText);
252
+ static int ing_querytype(char *queryText);
253
+ VALUE ing_execute (VALUE argc, VALUE *argv, VALUE self);
254
+ II_PTR executeQuery (II_CONN *ii_conn, char *param_sqlText);
255
+ static void ing_conn_init(II_CONN *ing_conn);
256
+ void ii_api_query_close (II_CONN *ii_conn);
257
+ void ii_api_connect (II_CONN *ii_conn, char *param_targetDB, char *param_username, char *param_password);
258
+ void ii_api_commit (II_CONN *ii_conn);
259
+ static int ii_query_type(char *queryText);
260
+ void ii_api_rollback (II_CONN *ii_conn, II_SAVEPOINT_ENTRY *savePtEntry);
261
+ void ii_api_disconnect( II_CONN *ii_conn);
262
+ void ii_api_savepoint (II_CONN *ii_conn, VALUE savePtName);
263
+ void ii_free_savePtEntries (II_SAVEPOINT_ENTRY *savePtEntry);
264
+
265
+ void ii_api_set_connect_param (II_CONN *ii_conn, II_LONG paramID, VALUE paramValue);
266
+ void ii_api_set_env_param (II_LONG paramID, VALUE paramValue);
267
+
268
+ /* Transaction control */
269
+ VALUE ii_commit (VALUE param_self);
270
+ VALUE ii_rollback (int param_argc, VALUE * param_argv, VALUE param_self);
271
+ VALUE ii_savepoint (VALUE param_self, VALUE param_savepointName);
272
+ VALUE ii_savepoint_name(II_CONN *ii_conn, char *statement);
273
+
274
+ /* Memory Allocation/Deallocation */
275
+ void *ii_allocate (size_t nitems, size_t size);
276
+ void *ii_reallocate (void *oldPtr, size_t nitems, size_t size);
277
+ void ii_free (void **ptr);
278
+
279
+ /* TODO - The following has been taken from the Ingres CL and should be removed/replaced at some point */
280
+ # define NULLCHAR ('\0') /* string terminator */
281
+ # define EOS NULLCHAR
282
+ # define CM_A_DBL1 0x80 /* 1st byte of double byte character */
283
+ # define CM_A_SPACE 0x10 /* SPACE */
284
+ # define cmdblspace(str) (((*(str)&0377) == 0xA1) && ((*((str)+1)&0377) == 0xA1))
285
+
286
+ # if defined(NT_GENERIC)
287
+ FUNC_EXTERN u_i2 *CMgetAttrTab ();
288
+ FUNC_EXTERN char *CMgetCaseTab ();
289
+ # endif
290
+
291
+ # define CMbytecnt(ptr) (1)
292
+ # define CMnext(str) (++(str))
293
+ # define CMdbl1st(str) (FALSE)
294
+
295
+ # if defined(_MSC_VER) || (defined(NT_GENERIC) && defined(IMPORT_DLL_DATA))
296
+ # define CMwhite(str) ((((u_i2 *)CMgetAttrTab())[*(str)&0377] & CM_A_SPACE) != 0)
297
+ # else /* NT_GENERIC && IMPORT_DLL_DATA */
298
+ # define CMwhite(str) ((CM_AttrTab[*(str)&0377] & CM_A_SPACE) != 0)
299
+ # endif /* NT_GENERIC && IMPORT_DLL_DATA */
300
+
301
+ /* available via Ingres Compatibility Layer */
302
+ /* TODO - Remove dependency on the Ingres CL */
303
+ size_t STtrmwhite (register char *string);
304
+
305
+ /* Certain Ruby releases shipped with different Linux distributions do not contain
306
+ * the necessary defines. E.g. RedHat ES 5.4 ships with Ruby 1.8.5.
307
+ */
308
+ #ifdef RUBY_VERSION_CODE
309
+ # if RUBY_VERSION_CODE < 186
310
+ # define RARRAY_LEN(s) (RARRAY(s)->len)
311
+ # define RSTRING_PTR(s) (RSTRING(s)->ptr)
312
+ # define RSTRING_LEN(s) (RSTRING(s)->len)
313
+ # endif /* RUBY_VERSION_CODE < 186 */
314
+ #endif
315
+
316
+ /*
317
+ vim: ts=2 sw=2 expandtab
318
+ */
data/ext/Unicode.c ADDED
@@ -0,0 +1,219 @@
1
+ /*
2
+ ** Copyright (c) 2009 Ingres Corporation
3
+ **
4
+ ** This program is free software; you can redistribute it and/or modify
5
+ ** it under the terms of the GNU General Public License version 2 as
6
+ ** published by the Free Software Foundation.
7
+ **
8
+ ** This program is distributed in the hope that it will be useful,
9
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ ** GNU General Public License for more details.
12
+ **
13
+ ** You should have received a copy of the GNU General Public License along
14
+ ** with this program; if not, write to the Free Software Foundation, Inc.,
15
+ ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+ */
17
+
18
+ /* static char Sccsid[] = "$Id$"; */
19
+
20
+ /*
21
+ ** UNCIODE.C
22
+ **
23
+ ** History
24
+ ** 24-Aug-2009 (Grant.Croker@ingres.com)
25
+ ** Created / Imported from Ingres.c
26
+ */
27
+
28
+ #include "Unicode.h"
29
+
30
+ int utf8_to_utf16 (UTF8 * sourceStart, const UTF8 * sourceEnd, UCS2 * targetStart, const UCS2 * targetEnd, long *reslen)
31
+ {
32
+ int result = FALSE;
33
+ register UTF8 *source = sourceStart;
34
+ register UCS2 *target = targetStart;
35
+ register UCS4 ch;
36
+ register u_i2 extraBytesToWrite;
37
+ const i4 halfShift = 10;
38
+
39
+ const UCS4 halfBase = 0x0010000UL, halfMask = 0x3FFUL,
40
+ kReplacementCharacter = 0x0000FFFDUL,
41
+ kMaximumUCS2 = 0x0000FFFFUL, kMaximumUCS4 = 0x7FFFFFFFUL,
42
+ kSurrogateHighStart = 0xD800UL, kSurrogateHighEnd = 0xDBFFUL,
43
+ kSurrogateLowStart = 0xDC00UL, kSurrogateLowEnd = 0xDFFFUL;
44
+
45
+ UCS4 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL
46
+ };
47
+
48
+ char bytesFromUTF8[256] = {
49
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
56
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
57
+ };
58
+
59
+ while (source < sourceEnd)
60
+ {
61
+ ch = 0;
62
+ extraBytesToWrite = bytesFromUTF8[*source];
63
+ if (source + extraBytesToWrite > sourceEnd)
64
+ {
65
+ *reslen = target - targetStart;
66
+ return TRUE;
67
+ }
68
+
69
+ switch (extraBytesToWrite) /* note: code falls through cases! */
70
+ {
71
+ case 5:
72
+ ch += *source++;
73
+ ch <<= 6;
74
+ case 4:
75
+ ch += *source++;
76
+ ch <<= 6;
77
+ case 3:
78
+ ch += *source++;
79
+ ch <<= 6;
80
+ case 2:
81
+ ch += *source++;
82
+ ch <<= 6;
83
+ case 1:
84
+ ch += *source++;
85
+ ch <<= 6;
86
+ case 0:
87
+ ch += *source++;
88
+ }
89
+ ch -= offsetsFromUTF8[extraBytesToWrite];
90
+
91
+ if (target >= targetEnd)
92
+ {
93
+ *reslen = target - targetStart;
94
+ return result;
95
+ }
96
+
97
+ if (ch <= kMaximumUCS2)
98
+ {
99
+ *target++ = ch;
100
+ }
101
+ else if (ch > kMaximumUCS4)
102
+ {
103
+ *target++ = kReplacementCharacter;
104
+ }
105
+ else
106
+ {
107
+ if (target + 1 >= targetEnd)
108
+ {
109
+ *reslen = target - targetStart;
110
+ return result;
111
+ }
112
+ ch -= halfBase;
113
+ *target++ = (ch >> halfShift) + kSurrogateHighStart;
114
+ *target++ = (ch & halfMask) + kSurrogateLowStart;
115
+ }
116
+ }
117
+ *reslen = target - targetStart;
118
+ return result;
119
+ }
120
+
121
+ int utf16_to_utf8 (UCS2 * sourceStart, const UCS2 * sourceEnd, UTF8 * targetStart, const UTF8 * targetEnd, long *reslen)
122
+ {
123
+ int result = FALSE;
124
+ register UCS2 *source = sourceStart;
125
+ register UTF8 *target = targetStart;
126
+ register UCS4 ch, ch2;
127
+ register u_i2 bytesToWrite;
128
+ register const UCS4 byteMask = 0xBF;
129
+ register const UCS4 byteMark = 0x80;
130
+ const i4 halfShift = 10;
131
+ UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
132
+
133
+ const UCS4 halfBase = 0x0010000UL, halfMask = 0x3FFUL,
134
+ kReplacementCharacter = 0x0000FFFDUL,
135
+ kMaximumUCS2 = 0x0000FFFFUL, kMaximumUCS4 = 0x7FFFFFFFUL,
136
+ kSurrogateHighStart = 0xD800UL, kSurrogateHighEnd = 0xDBFFUL,
137
+ kSurrogateLowStart = 0xDC00UL, kSurrogateLowEnd = 0xDFFFUL;
138
+
139
+
140
+ while (source < sourceEnd)
141
+ {
142
+ bytesToWrite = 0;
143
+ ch = *source++;
144
+ if (ch >= kSurrogateHighStart && ch <= kSurrogateHighEnd && source < sourceEnd)
145
+ {
146
+ ch2 = *source;
147
+ if (ch2 >= kSurrogateLowStart && ch2 <= kSurrogateLowEnd)
148
+ {
149
+ ch = ((ch - kSurrogateHighStart) << halfShift) + (ch2 - kSurrogateLowStart) + halfBase;
150
+ ++source;
151
+ }
152
+ }
153
+ if (ch < 0x80)
154
+ {
155
+ bytesToWrite = 1;
156
+ }
157
+ else if (ch < 0x800)
158
+ {
159
+ bytesToWrite = 2;
160
+ }
161
+ else if (ch < 0x10000)
162
+ {
163
+ bytesToWrite = 3;
164
+ }
165
+ else if (ch < 0x200000)
166
+ {
167
+ bytesToWrite = 4;
168
+ }
169
+ else if (ch < 0x4000000)
170
+ {
171
+ bytesToWrite = 5;
172
+ }
173
+ else if (ch <= kMaximumUCS4)
174
+ {
175
+ bytesToWrite = 6;
176
+ }
177
+ else
178
+ {
179
+ bytesToWrite = 2;
180
+ ch = kReplacementCharacter;
181
+ }
182
+
183
+ target += bytesToWrite;
184
+ if (target > targetEnd)
185
+ {
186
+ target -= bytesToWrite;
187
+ *reslen = target - targetStart;
188
+ return result;
189
+ }
190
+ switch (bytesToWrite) /* note: code falls through cases! */
191
+ {
192
+ case 6:
193
+ *--target = (ch | byteMark) & byteMask;
194
+ ch >>= 6;
195
+ case 5:
196
+ *--target = (ch | byteMark) & byteMask;
197
+ ch >>= 6;
198
+ case 4:
199
+ *--target = (ch | byteMark) & byteMask;
200
+ ch >>= 6;
201
+ case 3:
202
+ *--target = (ch | byteMark) & byteMask;
203
+ ch >>= 6;
204
+ case 2:
205
+ *--target = (ch | byteMark) & byteMask;
206
+ ch >>= 6;
207
+ case 1:
208
+ *--target = ch | firstByteMark[bytesToWrite];
209
+ }
210
+ target += bytesToWrite;
211
+ }
212
+ *reslen = target - targetStart;
213
+ return result;
214
+ }
215
+
216
+
217
+ /*
218
+ vim: ts=2 sw=2 expandtab
219
+ */