wasCSharpSQLite – Blame information for rev 2
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.Runtime.InteropServices; |
||
4 | using System.Text; |
||
5 | |||
6 | namespace Community.CsharpSqlite |
||
7 | { |
||
8 | using etByte = System.Boolean; |
||
9 | using i64 = System.Int64; |
||
10 | using u64 = System.UInt64; |
||
11 | using LONGDOUBLE_TYPE = System.Double; |
||
12 | using sqlite_u3264 = System.UInt64; |
||
13 | using va_list = System.Object; |
||
14 | |||
15 | public partial class Sqlite3 |
||
16 | { |
||
17 | /* |
||
18 | ** The "printf" code that follows dates from the 1980's. It is in |
||
19 | ** the public domain. The original comments are included here for |
||
20 | ** completeness. They are very out-of-date but might be useful as |
||
21 | ** an historical reference. Most of the "enhancements" have been backed |
||
22 | ** out so that the functionality is now the same as standard printf(). |
||
23 | ** |
||
24 | ************************************************************************** |
||
25 | ** |
||
26 | ** The following modules is an enhanced replacement for the "printf" subroutines |
||
27 | ** found in the standard C library. The following enhancements are |
||
28 | ** supported: |
||
29 | ** |
||
30 | ** + Additional functions. The standard set of "printf" functions |
||
31 | ** includes printf, fprintf, sprintf, vprintf, vfprintf, and |
||
32 | ** vsprintf. This module adds the following: |
||
33 | ** |
||
34 | ** * snprintf -- Works like sprintf, but has an extra argument |
||
35 | ** which is the size of the buffer written to. |
||
36 | ** |
||
37 | ** * mprintf -- Similar to sprintf. Writes output to memory |
||
38 | ** obtained from malloc. |
||
39 | ** |
||
40 | ** * xprintf -- Calls a function to dispose of output. |
||
41 | ** |
||
42 | ** * nprintf -- No output, but returns the number of characters |
||
43 | ** that would have been output by printf. |
||
44 | ** |
||
45 | ** * A v- version (ex: vsnprintf) of every function is also |
||
46 | ** supplied. |
||
47 | ** |
||
48 | ** + A few extensions to the formatting notation are supported: |
||
49 | ** |
||
50 | ** * The "=" flag (similar to "-") causes the output to be |
||
51 | ** be centered in the appropriately sized field. |
||
52 | ** |
||
53 | ** * The %b field outputs an integer in binary notation. |
||
54 | ** |
||
55 | ** * The %c field now accepts a precision. The character output |
||
56 | ** is repeated by the number of times the precision specifies. |
||
57 | ** |
||
58 | ** * The %' field works like %c, but takes as its character the |
||
59 | ** next character of the format string, instead of the next |
||
60 | ** argument. For example, printf("%.78'-") prints 78 minus |
||
61 | ** signs, the same as printf("%.78c",'-'). |
||
62 | ** |
||
63 | ** + When compiled using GCC on a SPARC, this version of printf is |
||
64 | ** faster than the library printf for SUN OS 4.1. |
||
65 | ** |
||
66 | ** + All functions are fully reentrant. |
||
67 | ** |
||
68 | ************************************************************************* |
||
69 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
70 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
71 | ** |
||
72 | ** SQLITE_SOURCE_ID: 2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e |
||
73 | ** |
||
74 | ************************************************************************* |
||
75 | */ |
||
76 | //#include "sqliteInt.h" |
||
77 | |||
78 | /* |
||
79 | ** Conversion types fall into various categories as defined by the |
||
80 | ** following enumeration. |
||
81 | */ |
||
82 | //#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ |
||
83 | //#define etFLOAT 2 /* Floating point. %f */ |
||
84 | //#define etEXP 3 /* Exponentional notation. %e and %E */ |
||
85 | //#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ |
||
86 | //#define etSIZE 5 /* Return number of characters processed so far. %n */ |
||
87 | //#define etSTRING 6 /* Strings. %s */ |
||
88 | //#define etDYNSTRING 7 /* Dynamically allocated strings. %z */ |
||
89 | //#define etPERCENT 8 /* Percent symbol. %% */ |
||
90 | //#define etCHARX 9 /* Characters. %c */ |
||
91 | ///* The rest are extensions, not normally found in printf() */ |
||
92 | //#define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */ |
||
93 | //#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '', |
||
94 | // NULL pointers replaced by SQL NULL. %Q */ |
||
95 | //#define etTOKEN 12 /* a pointer to a Token structure */ |
||
96 | //#define etSRCLIST 13 /* a pointer to a SrcList */ |
||
97 | //#define etPOINTER 14 /* The %p conversion */ |
||
98 | //#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */ |
||
99 | //#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ |
||
100 | |||
101 | //#define etINVALID 0 /* Any unrecognized conversion type */ |
||
102 | |||
103 | const int etRADIX = 1; /* Integer types. %d, %x, %o, and so forth */ |
||
104 | const int etFLOAT = 2; /* Floating point. %f */ |
||
105 | const int etEXP = 3; /* Exponentional notation. %e and %E */ |
||
106 | const int etGENERIC = 4; /* Floating or exponential, depending on exponent. %g */ |
||
107 | const int etSIZE = 5; /* Return number of characters processed so far. %n */ |
||
108 | const int etSTRING = 6; /* Strings. %s */ |
||
109 | const int etDYNSTRING = 7; /* Dynamically allocated strings. %z */ |
||
110 | const int etPERCENT = 8; /* Percent symbol. %% */ |
||
111 | const int etCHARX = 9; /* Characters. %c */ |
||
112 | /* The rest are extensions, not normally found in printf() */ |
||
113 | const int etSQLESCAPE = 10; /* Strings with '\'' doubled. %q */ |
||
114 | const int etSQLESCAPE2 = 11; /* Strings with '\'' doubled and enclosed in '', |
||
115 | NULL pointers replaced by SQL NULL. %Q */ |
||
116 | const int etTOKEN = 12; /* a pointer to a Token structure */ |
||
117 | const int etSRCLIST = 13; /* a pointer to a SrcList */ |
||
118 | const int etPOINTER = 14; /* The %p conversion */ |
||
119 | const int etSQLESCAPE3 = 15; /* %w . Strings with '\"' doubled */ |
||
120 | const int etORDINAL = 16; /* %r . 1st, 2nd, 3rd, 4th, etc. English only */ |
||
121 | const int etINVALID = 0; /* Any unrecognized conversion type */ |
||
122 | |||
123 | /* |
||
124 | ** An "etByte" is an 8-bit unsigned value. |
||
125 | */ |
||
126 | //typedef unsigned char etByte; |
||
127 | |||
128 | /* |
||
129 | ** Each builtin conversion character (ex: the 'd' in "%d") is described |
||
130 | ** by an instance of the following structure |
||
131 | */ |
||
132 | public class et_info |
||
133 | { /* Information about each format field */ |
||
134 | public char fmttype; /* The format field code letter */ |
||
135 | public byte _base; /* The _base for radix conversion */ |
||
136 | public byte flags; /* One or more of FLAG_ constants below */ |
||
137 | public byte type; /* Conversion paradigm */ |
||
138 | public byte charset; /* Offset into aDigits[] of the digits string */ |
||
139 | public byte prefix; /* Offset into aPrefix[] of the prefix string */ |
||
140 | /* |
||
141 | * Constructor |
||
142 | */ |
||
143 | public et_info( char fmttype, |
||
144 | byte _base, |
||
145 | byte flags, |
||
146 | byte type, |
||
147 | byte charset, |
||
148 | byte prefix |
||
149 | ) |
||
150 | { |
||
151 | this.fmttype = fmttype; |
||
152 | this._base = _base; |
||
153 | this.flags = flags; |
||
154 | this.type = type; |
||
155 | this.charset = charset; |
||
156 | this.prefix = prefix; |
||
157 | } |
||
158 | |||
159 | } |
||
160 | |||
161 | /* |
||
162 | ** Allowed values for et_info.flags |
||
163 | */ |
||
164 | const byte FLAG_SIGNED = 1; /* True if the value to convert is signed */ |
||
165 | const byte FLAG_INTERN = 2; /* True if for internal use only */ |
||
166 | const byte FLAG_STRING = 4; /* Allow infinity precision */ |
||
167 | |||
168 | |||
169 | /* |
||
170 | ** The following table is searched linearly, so it is good to put the |
||
171 | ** most frequently used conversion types first. |
||
172 | */ |
||
173 | static string aDigits = "0123456789ABCDEF0123456789abcdef"; |
||
174 | static string aPrefix = "-x0\000X0"; |
||
175 | static et_info[] fmtinfo = new et_info[] { |
||
176 | new et_info( 'd', 10, 1, etRADIX, 0, 0 ), |
||
177 | new et_info( 's', 0, 4, etSTRING, 0, 0 ), |
||
178 | new et_info( 'g', 0, 1, etGENERIC, 30, 0 ), |
||
179 | new et_info( 'z', 0, 4, etDYNSTRING, 0, 0 ), |
||
180 | new et_info( 'q', 0, 4, etSQLESCAPE, 0, 0 ), |
||
181 | new et_info( 'Q', 0, 4, etSQLESCAPE2, 0, 0 ), |
||
182 | new et_info( 'w', 0, 4, etSQLESCAPE3, 0, 0 ), |
||
183 | new et_info( 'c', 0, 0, etCHARX, 0, 0 ), |
||
184 | new et_info( 'o', 8, 0, etRADIX, 0, 2 ), |
||
185 | new et_info( 'u', 10, 0, etRADIX, 0, 0 ), |
||
186 | new et_info( 'x', 16, 0, etRADIX, 16, 1 ), |
||
187 | new et_info( 'X', 16, 0, etRADIX, 0, 4 ), |
||
188 | #if !SQLITE_OMIT_FLOATING_POINT |
||
189 | new et_info( 'f', 0, 1, etFLOAT, 0, 0 ), |
||
190 | new et_info( 'e', 0, 1, etEXP, 30, 0 ), |
||
191 | new et_info( 'E', 0, 1, etEXP, 14, 0 ), |
||
192 | new et_info( 'G', 0, 1, etGENERIC, 14, 0 ), |
||
193 | #endif |
||
194 | new et_info( 'i', 10, 1, etRADIX, 0, 0 ), |
||
195 | new et_info( 'n', 0, 0, etSIZE, 0, 0 ), |
||
196 | new et_info( '%', 0, 0, etPERCENT, 0, 0 ), |
||
197 | new et_info( 'p', 16, 0, etPOINTER, 0, 1 ), |
||
198 | |||
199 | /* All the rest have the FLAG_INTERN bit set and are thus for internal |
||
200 | ** use only */ |
||
201 | new et_info( 'T', 0, 2, etTOKEN, 0, 0 ), |
||
202 | new et_info( 'S', 0, 2, etSRCLIST, 0, 0 ), |
||
203 | new et_info( 'r', 10, 3, etORDINAL, 0, 0 ), |
||
204 | }; |
||
205 | /* |
||
206 | ** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point |
||
207 | ** conversions will work. |
||
208 | */ |
||
209 | #if !SQLITE_OMIT_FLOATING_POINT |
||
210 | /* |
||
211 | ** "*val" is a double such that 0.1 <= *val < 10.0 |
||
212 | ** Return the ascii code for the leading digit of *val, then |
||
213 | ** multiply "*val" by 10.0 to renormalize. |
||
214 | ** |
||
215 | ** Example: |
||
216 | ** input: *val = 3.14159 |
||
217 | ** output: *val = 1.4159 function return = '3' |
||
218 | ** |
||
219 | ** The counter *cnt is incremented each time. After counter exceeds |
||
220 | ** 16 (the number of significant digits in a 64-bit float) '0' is |
||
221 | ** always returned. |
||
222 | */ |
||
223 | static char et_getdigit( ref LONGDOUBLE_TYPE val, ref int cnt ) |
||
224 | { |
||
225 | int digit; |
||
226 | LONGDOUBLE_TYPE d; |
||
227 | if ( cnt++ >= 16 ) |
||
228 | return '\0'; |
||
229 | digit = (int)val; |
||
230 | d = digit; |
||
231 | //digit += '0'; |
||
232 | val = ( val - d ) * 10.0; |
||
233 | return (char)digit; |
||
234 | } |
||
235 | #endif // * SQLITE_OMIT_FLOATING_POINT */ |
||
236 | |||
237 | /* |
||
238 | ** Append N space characters to the given string buffer. |
||
239 | */ |
||
240 | static void appendSpace( StrAccum pAccum, int N ) |
||
241 | { |
||
242 | //static const char zSpaces[] = " "; |
||
243 | //while( N>=zSpaces.Length-1 ){ |
||
244 | // sqlite3StrAccumAppend(pAccum, zSpaces, zSpaces.Length-1); |
||
245 | // N -= zSpaces.Length-1; |
||
246 | //} |
||
247 | //if( N>0 ){ |
||
248 | // sqlite3StrAccumAppend(pAccum, zSpaces, N); |
||
249 | //} |
||
250 | pAccum.zText.AppendFormat( "{0," + N + "}", string.Empty ); |
||
251 | } |
||
252 | |||
253 | /* |
||
254 | ** On machines with a small stack size, you can redefine the |
||
255 | ** SQLITE_PRINT_BUF_SIZE to be less than 350. |
||
256 | */ |
||
257 | #if !SQLITE_PRINT_BUF_SIZE |
||
258 | # if (SQLITE_SMALL_STACK) |
||
259 | const int SQLITE_PRINT_BUF_SIZE = 50; |
||
260 | # else |
||
261 | const int SQLITE_PRINT_BUF_SIZE = 350; |
||
262 | #endif |
||
263 | #endif |
||
264 | const int etBUFSIZE = SQLITE_PRINT_BUF_SIZE; /* Size of the output buffer */ |
||
265 | |||
266 | /* |
||
267 | ** The root program. All variations call this core. |
||
268 | ** |
||
269 | ** INPUTS: |
||
270 | ** func This is a pointer to a function taking three arguments |
||
271 | ** 1. A pointer to anything. Same as the "arg" parameter. |
||
272 | ** 2. A pointer to the list of characters to be output |
||
273 | ** (Note, this list is NOT null terminated.) |
||
274 | ** 3. An integer number of characters to be output. |
||
275 | ** (Note: This number might be zero.) |
||
276 | ** |
||
277 | ** arg This is the pointer to anything which will be passed as the |
||
278 | ** first argument to "func". Use it for whatever you like. |
||
279 | ** |
||
280 | ** fmt This is the format string, as in the usual print. |
||
281 | ** |
||
282 | ** ap This is a pointer to a list of arguments. Same as in |
||
283 | ** vfprint. |
||
284 | ** |
||
285 | ** OUTPUTS: |
||
286 | ** The return value is the total number of characters sent to |
||
287 | ** the function "func". Returns -1 on a error. |
||
288 | ** |
||
289 | ** Note that the order in which automatic variables are declared below |
||
290 | ** seems to make a big difference in determining how fast this beast |
||
291 | ** will run. |
||
292 | */ |
||
293 | static char[] buf = new char[etBUFSIZE]; /* Conversion buffer */ |
||
294 | static void sqlite3VXPrintf( |
||
295 | StrAccum pAccum, /* Accumulate results here */ |
||
296 | int useExtended, /* Allow extended %-conversions */ |
||
297 | string fmt, /* Format string */ |
||
298 | va_list[] ap /* arguments */ |
||
299 | ) |
||
300 | { |
||
301 | int c; /* Next character in the format string */ |
||
302 | int bufpt; /* Pointer to the conversion buffer */ |
||
303 | int precision; /* Precision of the current field */ |
||
304 | int length; /* Length of the field */ |
||
305 | int idx; /* A general purpose loop counter */ |
||
306 | int width; /* Width of the current field */ |
||
307 | etByte flag_leftjustify; /* True if "-" flag is present */ |
||
308 | etByte flag_plussign; /* True if "+" flag is present */ |
||
309 | etByte flag_blanksign; /* True if " " flag is present */ |
||
310 | etByte flag_alternateform; /* True if "#" flag is present */ |
||
311 | etByte flag_altform2; /* True if "!" flag is present */ |
||
312 | etByte flag_zeropad; /* True if field width constant starts with zero */ |
||
313 | etByte flag_long; /* True if "l" flag is present */ |
||
314 | etByte flag_longlong; /* True if the "ll" flag is present */ |
||
315 | etByte done; /* Loop termination flag */ |
||
316 | i64 longvalue; |
||
317 | LONGDOUBLE_TYPE realvalue; /* Value for real types */ |
||
318 | et_info infop; /* Pointer to the appropriate info structure */ |
||
319 | char[] buf = new char[etBUFSIZE]; /* Conversion buffer */ |
||
320 | char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ |
||
321 | byte xtype = 0; /* Conversion paradigm */ |
||
322 | // Not used in C# -- string zExtra; /* Extra memory used for etTCLESCAPE conversions */ |
||
323 | #if !SQLITE_OMIT_FLOATING_POINT |
||
324 | int exp, e2; /* exponent of real numbers */ |
||
325 | double rounder; /* Used for rounding floating point values */ |
||
326 | etByte flag_dp; /* True if decimal point should be shown */ |
||
327 | etByte flag_rtz; /* True if trailing zeros should be removed */ |
||
328 | etByte flag_exp; /* True to force display of the exponent */ |
||
329 | int nsd; /* Number of significant digits returned */ |
||
330 | #endif |
||
331 | length = 0; |
||
332 | bufpt = 0; |
||
333 | int _fmt = 0; // Work around string pointer |
||
334 | fmt += '\0'; |
||
335 | |||
336 | for ( ; _fmt <= fmt.Length && ( c = fmt[_fmt] ) != 0; ++_fmt ) |
||
337 | { |
||
338 | if ( c != '%' ) |
||
339 | { |
||
340 | int amt; |
||
341 | bufpt = _fmt; |
||
342 | amt = 1; |
||
343 | while ( _fmt < fmt.Length && ( c = ( fmt[++_fmt] ) ) != '%' && c != 0 ) |
||
344 | amt++; |
||
345 | sqlite3StrAccumAppend( pAccum, fmt.Substring( bufpt, amt ), amt ); |
||
346 | if ( c == 0 ) |
||
347 | break; |
||
348 | } |
||
349 | if ( _fmt < fmt.Length && ( c = ( fmt[++_fmt] ) ) == 0 ) |
||
350 | { |
||
351 | sqlite3StrAccumAppend( pAccum, "%", 1 ); |
||
352 | break; |
||
353 | } |
||
354 | /* Find out what flags are present */ |
||
355 | flag_leftjustify = flag_plussign = flag_blanksign = |
||
356 | flag_alternateform = flag_altform2 = flag_zeropad = false; |
||
357 | done = false; |
||
358 | do |
||
359 | { |
||
360 | switch ( c ) |
||
361 | { |
||
362 | case '-': |
||
363 | flag_leftjustify = true; |
||
364 | break; |
||
365 | case '+': |
||
366 | flag_plussign = true; |
||
367 | break; |
||
368 | case ' ': |
||
369 | flag_blanksign = true; |
||
370 | break; |
||
371 | case '#': |
||
372 | flag_alternateform = true; |
||
373 | break; |
||
374 | case '!': |
||
375 | flag_altform2 = true; |
||
376 | break; |
||
377 | case '0': |
||
378 | flag_zeropad = true; |
||
379 | break; |
||
380 | default: |
||
381 | done = true; |
||
382 | break; |
||
383 | } |
||
384 | } while ( !done && _fmt < fmt.Length - 1 && ( c = ( fmt[++_fmt] ) ) != 0 ); |
||
385 | /* Get the field width */ |
||
386 | width = 0; |
||
387 | if ( c == '*' ) |
||
388 | { |
||
389 | width = va_arg( ap, (Int32)0 ); |
||
390 | if ( width < 0 ) |
||
391 | { |
||
392 | flag_leftjustify = true; |
||
393 | width = -width; |
||
394 | } |
||
395 | c = fmt[++_fmt]; |
||
396 | } |
||
397 | else |
||
398 | { |
||
399 | while ( c >= '0' && c <= '9' ) |
||
400 | { |
||
401 | width = width * 10 + c - '0'; |
||
402 | c = fmt[++_fmt]; |
||
403 | } |
||
404 | } |
||
405 | if ( width > etBUFSIZE - 10 ) |
||
406 | { |
||
407 | width = etBUFSIZE - 12; |
||
408 | } |
||
409 | /* Get the precision */ |
||
410 | if ( c == '.' ) |
||
411 | { |
||
412 | precision = 0; |
||
413 | c = fmt[++_fmt]; |
||
414 | if ( c == '*' ) |
||
415 | { |
||
416 | precision = va_arg( ap, (Int32)0 ); |
||
417 | if ( precision < 0 ) |
||
418 | precision = -precision; |
||
419 | c = fmt[++_fmt]; |
||
420 | } |
||
421 | else |
||
422 | { |
||
423 | while ( c >= '0' && c <= '9' ) |
||
424 | { |
||
425 | precision = precision * 10 + c - '0'; |
||
426 | c = fmt[++_fmt]; |
||
427 | } |
||
428 | } |
||
429 | } |
||
430 | else |
||
431 | { |
||
432 | precision = -1; |
||
433 | } |
||
434 | /* Get the conversion type modifier */ |
||
435 | if ( c == 'l' ) |
||
436 | { |
||
437 | flag_long = true; |
||
438 | c = fmt[++_fmt]; |
||
439 | if ( c == 'l' ) |
||
440 | { |
||
441 | flag_longlong = true; |
||
442 | c = fmt[++_fmt]; |
||
443 | } |
||
444 | else |
||
445 | { |
||
446 | flag_longlong = false; |
||
447 | } |
||
448 | } |
||
449 | else |
||
450 | { |
||
451 | flag_long = flag_longlong = false; |
||
452 | } |
||
453 | /* Fetch the info entry for the field */ |
||
454 | infop = fmtinfo[0]; |
||
455 | xtype = etINVALID; |
||
456 | for ( idx = 0; idx < ArraySize( fmtinfo ); idx++ ) |
||
457 | { |
||
458 | if ( c == fmtinfo[idx].fmttype ) |
||
459 | { |
||
460 | infop = fmtinfo[idx]; |
||
461 | if ( useExtended != 0 || ( infop.flags & FLAG_INTERN ) == 0 ) |
||
462 | { |
||
463 | xtype = infop.type; |
||
464 | } |
||
465 | else |
||
466 | { |
||
467 | return; |
||
468 | } |
||
469 | break; |
||
470 | } |
||
471 | } |
||
472 | //zExtra = null; |
||
473 | |||
474 | /* Limit the precision to prevent overflowing buf[] during conversion */ |
||
475 | if ( precision > etBUFSIZE - 40 && ( infop.flags & FLAG_STRING ) == 0 ) |
||
476 | { |
||
477 | precision = etBUFSIZE - 40; |
||
478 | } |
||
479 | |||
480 | /* |
||
481 | ** At this point, variables are initialized as follows: |
||
482 | ** |
||
483 | ** flag_alternateform TRUE if a '#' is present. |
||
484 | ** flag_altform2 TRUE if a '!' is present. |
||
485 | ** flag_plussign TRUE if a '+' is present. |
||
486 | ** flag_leftjustify TRUE if a '-' is present or if the |
||
487 | ** field width was negative. |
||
488 | ** flag_zeropad TRUE if the width began with 0. |
||
489 | ** flag_long TRUE if the letter 'l' (ell) prefixed |
||
490 | ** the conversion character. |
||
491 | ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed |
||
492 | ** the conversion character. |
||
493 | ** flag_blanksign TRUE if a ' ' is present. |
||
494 | ** width The specified field width. This is |
||
495 | ** always non-negative. Zero is the default. |
||
496 | ** precision The specified precision. The default |
||
497 | ** is -1. |
||
498 | ** xtype The class of the conversion. |
||
499 | ** infop Pointer to the appropriate info struct. |
||
500 | */ |
||
501 | switch ( xtype ) |
||
502 | { |
||
503 | case etPOINTER: |
||
504 | flag_longlong = true;// char*.Length == sizeof(i64); |
||
505 | flag_long = false;// char*.Length == sizeof(long); |
||
506 | /* Fall through into the next case */ |
||
507 | goto case etRADIX; |
||
508 | case etORDINAL: |
||
509 | case etRADIX: |
||
510 | if ( ( infop.flags & FLAG_SIGNED ) != 0 ) |
||
511 | { |
||
512 | i64 v; |
||
513 | if ( flag_longlong ) |
||
514 | { |
||
515 | v = (Int64)va_arg( ap, (Int64)0 ); |
||
516 | } |
||
517 | else if ( flag_long ) |
||
518 | { |
||
519 | v = (Int64)va_arg( ap, (Int64)0 ); |
||
520 | } |
||
521 | else |
||
522 | { |
||
523 | v = (Int32)va_arg( ap, (Int32)0 ); |
||
524 | } |
||
525 | if ( v < 0 ) |
||
526 | { |
||
527 | if ( v == SMALLEST_INT64 ) |
||
528 | { |
||
529 | longvalue = ( (long)( (u64)1 ) << 63 ); |
||
530 | } |
||
531 | else |
||
532 | { |
||
533 | longvalue = -v; |
||
534 | } |
||
535 | prefix = '-'; |
||
536 | } |
||
537 | else |
||
538 | { |
||
539 | longvalue = v; |
||
540 | if ( flag_plussign ) |
||
541 | prefix = '+'; |
||
542 | else if ( flag_blanksign ) |
||
543 | prefix = ' '; |
||
544 | else |
||
545 | prefix = '\0'; |
||
546 | } |
||
547 | } |
||
548 | else |
||
549 | { |
||
550 | if ( flag_longlong ) |
||
551 | { |
||
552 | longvalue = va_arg( ap, (Int64)0 ); |
||
553 | } |
||
554 | else if ( flag_long ) |
||
555 | { |
||
556 | longvalue = va_arg( ap, (Int64)0 ); |
||
557 | } |
||
558 | else |
||
559 | { |
||
560 | longvalue = va_arg( ap, (Int64)0 ); |
||
561 | } |
||
562 | prefix = '\0'; |
||
563 | } |
||
564 | if ( longvalue == 0 ) |
||
565 | flag_alternateform = false; |
||
566 | if ( flag_zeropad && precision < width - ( ( prefix != '\0' ) ? 1 : 0 ) ) |
||
567 | { |
||
568 | precision = width - ( ( prefix != '\0' ) ? 1 : 0 ); |
||
569 | } |
||
570 | bufpt = buf.Length;//[etBUFSIZE-1]; |
||
571 | char[] _bufOrd = null; |
||
572 | if ( xtype == etORDINAL ) |
||
573 | { |
||
574 | char[] zOrd = "thstndrd".ToCharArray(); |
||
575 | int x = (int)( longvalue % 10 ); |
||
576 | if ( x >= 4 || ( longvalue / 10 ) % 10 == 1 ) |
||
577 | { |
||
578 | x = 0; |
||
579 | } |
||
580 | _bufOrd = new char[2]; |
||
581 | _bufOrd[0] = zOrd[x * 2]; |
||
582 | _bufOrd[1] = zOrd[x * 2 + 1]; |
||
583 | //bufpt -= 2; |
||
584 | } |
||
585 | { |
||
586 | |||
587 | char[] _buf; |
||
588 | switch ( infop._base ) |
||
589 | { |
||
590 | case 16: |
||
591 | _buf = longvalue.ToString( "x" ).ToCharArray(); |
||
592 | break; |
||
593 | case 8: |
||
594 | _buf = Convert.ToString( (long)longvalue, 8 ).ToCharArray(); |
||
595 | break; |
||
596 | default: |
||
597 | { |
||
598 | if ( flag_zeropad ) |
||
599 | _buf = longvalue.ToString( new string( '0', width - ( ( prefix != '\0' ) ? 1 : 0 ) ) ).ToCharArray(); |
||
600 | else |
||
601 | _buf = longvalue.ToString().ToCharArray(); |
||
602 | } |
||
603 | break; |
||
604 | } |
||
605 | bufpt = buf.Length - _buf.Length - ( _bufOrd == null ? 0 : 2 ); |
||
606 | Array.Copy( _buf, 0, buf, bufpt, _buf.Length ); |
||
607 | if ( _bufOrd != null ) |
||
608 | { |
||
609 | buf[buf.Length - 1] = _bufOrd[1]; |
||
610 | buf[buf.Length - 2] = _bufOrd[0]; |
||
611 | } |
||
612 | //char* cset; /* Use registers for speed */ |
||
613 | //int _base; |
||
614 | //cset = aDigits[infop.charset]; |
||
615 | //_base = infop._base; |
||
616 | //do |
||
617 | //{ /* Convert to ascii */ |
||
618 | // *(--bufpt) = cset[longvalue % (ulong)_base]; |
||
619 | // longvalue = longvalue / (ulong)_base; |
||
620 | //} while (longvalue > 0); |
||
621 | } |
||
622 | length = buf.Length - bufpt;//length = (int)(&buf[etBUFSIZE-1]-bufpt); |
||
623 | for ( idx = precision - length; idx > 0; idx-- ) |
||
624 | { |
||
625 | buf[( --bufpt )] = '0'; /* Zero pad */ |
||
626 | } |
||
627 | if ( prefix != '\0' ) |
||
628 | buf[--bufpt] = prefix; /* Add sign */ |
||
629 | if ( flag_alternateform && infop.prefix != 0 ) |
||
630 | { /* Add "0" or "0x" */ |
||
631 | int pre; |
||
632 | char x; |
||
633 | pre = infop.prefix; |
||
634 | for ( ; ( x = aPrefix[pre] ) != 0; pre++ ) |
||
635 | buf[--bufpt] = x; |
||
636 | } |
||
637 | length = buf.Length - bufpt;//length = (int)(&buf[etBUFSIZE-1]-bufpt); |
||
638 | break; |
||
639 | case etFLOAT: |
||
640 | case etEXP: |
||
641 | case etGENERIC: |
||
642 | realvalue = va_arg( ap, (Double)0 ); |
||
643 | #if SQLITE_OMIT_FLOATING_POINT |
||
644 | length = 0; |
||
645 | #else |
||
646 | if ( precision < 0 ) |
||
647 | precision = 6; /* Set default precision */ |
||
648 | if ( precision > etBUFSIZE / 2 - 10 ) |
||
649 | precision = etBUFSIZE / 2 - 10; |
||
650 | if ( realvalue < 0.0 ) |
||
651 | { |
||
652 | realvalue = -realvalue; |
||
653 | prefix = '-'; |
||
654 | } |
||
655 | else |
||
656 | { |
||
657 | if ( flag_plussign ) |
||
658 | prefix = '+'; |
||
659 | else if ( flag_blanksign ) |
||
660 | prefix = ' '; |
||
661 | else |
||
662 | prefix = '\0'; |
||
663 | } |
||
664 | if ( xtype == etGENERIC && precision > 0 ) |
||
665 | precision--; |
||
666 | #if FALSE |
||
667 | /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */ |
||
668 | for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); |
||
669 | #else |
||
670 | /* It makes more sense to use 0.5 */ |
||
671 | for ( idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1 ) |
||
672 | { |
||
673 | } |
||
674 | #endif |
||
675 | if ( xtype == etFLOAT ) |
||
676 | realvalue += rounder; |
||
677 | /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ |
||
678 | exp = 0; |
||
679 | #if WINDOWS_MOBILE |
||
680 | //alxwest: Tryparse doesn't exist on Windows Moble and what will Tryparsing a double do? |
||
681 | if ( Double.IsNaN( realvalue )) |
||
682 | #else |
||
683 | if ( Double.IsNaN( realvalue ) || !( Double.TryParse( Convert.ToString( realvalue ), out d ) ) )//if( sqlite3IsNaN((double)realvalue) ) |
||
684 | #endif |
||
685 | { |
||
686 | buf[0] = 'N'; |
||
687 | buf[1] = 'a'; |
||
688 | buf[2] = 'N';// "NaN" |
||
689 | length = 3; |
||
690 | break; |
||
691 | } |
||
692 | if ( realvalue > 0.0 ) |
||
693 | { |
||
694 | while ( realvalue >= 1e32 && exp <= 350 ) |
||
695 | { |
||
696 | realvalue *= 1e-32; |
||
697 | exp += 32; |
||
698 | } |
||
699 | while ( realvalue >= 1e8 && exp <= 350 ) |
||
700 | { |
||
701 | realvalue *= 1e-8; |
||
702 | exp += 8; |
||
703 | } |
||
704 | while ( realvalue >= 10.0 && exp <= 350 ) |
||
705 | { |
||
706 | realvalue *= 0.1; |
||
707 | exp++; |
||
708 | } |
||
709 | while ( realvalue < 1e-8 ) |
||
710 | { |
||
711 | realvalue *= 1e8; |
||
712 | exp -= 8; |
||
713 | } |
||
714 | while ( realvalue < 1.0 ) |
||
715 | { |
||
716 | realvalue *= 10.0; |
||
717 | exp--; |
||
718 | } |
||
719 | if ( exp > 350 ) |
||
720 | { |
||
721 | if ( prefix == '-' ) |
||
722 | { |
||
723 | buf[0] = '-'; |
||
724 | buf[1] = 'I'; |
||
725 | buf[2] = 'n'; |
||
726 | buf[3] = 'f';// "-Inf" |
||
727 | bufpt = 4; |
||
728 | } |
||
729 | else if ( prefix == '+' ) |
||
730 | { |
||
731 | buf[0] = '+'; |
||
732 | buf[1] = 'I'; |
||
733 | buf[2] = 'n'; |
||
734 | buf[3] = 'f';// "+Inf" |
||
735 | bufpt = 4; |
||
736 | } |
||
737 | else |
||
738 | { |
||
739 | buf[0] = 'I'; |
||
740 | buf[1] = 'n'; |
||
741 | buf[2] = 'f';// "Inf" |
||
742 | bufpt = 3; |
||
743 | } |
||
744 | length = sqlite3Strlen30( bufpt );// sqlite3Strlen30(bufpt); |
||
745 | bufpt = 0; |
||
746 | break; |
||
747 | } |
||
748 | } |
||
749 | bufpt = 0; |
||
750 | /* |
||
751 | ** If the field type is etGENERIC, then convert to either etEXP |
||
752 | ** or etFLOAT, as appropriate. |
||
753 | */ |
||
754 | flag_exp = xtype == etEXP; |
||
755 | if ( xtype != etFLOAT ) |
||
756 | { |
||
757 | realvalue += rounder; |
||
758 | if ( realvalue >= 10.0 ) |
||
759 | { |
||
760 | realvalue *= 0.1; |
||
761 | exp++; |
||
762 | } |
||
763 | } |
||
764 | if ( xtype == etGENERIC ) |
||
765 | { |
||
766 | flag_rtz = !flag_alternateform; |
||
767 | if ( exp < -4 || exp > precision ) |
||
768 | { |
||
769 | xtype = etEXP; |
||
770 | } |
||
771 | else |
||
772 | { |
||
773 | precision = precision - exp; |
||
774 | xtype = etFLOAT; |
||
775 | } |
||
776 | } |
||
777 | else |
||
778 | { |
||
779 | flag_rtz = false; |
||
780 | } |
||
781 | if ( xtype == etEXP ) |
||
782 | { |
||
783 | e2 = 0; |
||
784 | } |
||
785 | else |
||
786 | { |
||
787 | e2 = exp; |
||
788 | } |
||
789 | nsd = 0; |
||
790 | flag_dp = ( precision > 0 ? true : false ) | flag_alternateform | flag_altform2; |
||
791 | /* The sign in front of the number */ |
||
792 | if ( prefix != '\0' ) |
||
793 | { |
||
794 | buf[bufpt++] = prefix; |
||
795 | } |
||
796 | /* Digits prior to the decimal point */ |
||
797 | if ( e2 < 0 ) |
||
798 | { |
||
799 | buf[bufpt++] = '0'; |
||
800 | } |
||
801 | else |
||
802 | { |
||
803 | for ( ; e2 >= 0; e2-- ) |
||
804 | { |
||
805 | buf[bufpt++] = (char)( et_getdigit( ref realvalue, ref nsd ) + '0' ); // *(bufpt++) = et_getdigit(ref realvalue, ref nsd); |
||
806 | } |
||
807 | |||
808 | } |
||
809 | /* The decimal point */ |
||
810 | if ( flag_dp ) |
||
811 | { |
||
812 | buf[bufpt++] = '.'; |
||
813 | } |
||
814 | /* "0" digits after the decimal point but before the first |
||
815 | ** significant digit of the number */ |
||
816 | for ( e2++; e2 < 0; precision--, e2++ ) |
||
817 | { |
||
818 | Debug.Assert( precision > 0 ); |
||
819 | buf[bufpt++] = '0'; |
||
820 | } |
||
821 | /* Significant digits after the decimal point */ |
||
822 | while ( ( precision-- ) > 0 ) |
||
823 | { |
||
824 | buf[bufpt++] = (char)( et_getdigit( ref realvalue, ref nsd ) + '0' ); // *(bufpt++) = et_getdigit(&realvalue, nsd); |
||
825 | } |
||
826 | /* Remove trailing zeros and the "." if no digits follow the "." */ |
||
827 | if ( flag_rtz && flag_dp ) |
||
828 | { |
||
829 | while ( buf[bufpt - 1] == '0' ) |
||
830 | buf[--bufpt] = '\0'; |
||
831 | Debug.Assert( bufpt > 0 ); |
||
832 | if ( buf[bufpt - 1] == '.' ) |
||
833 | { |
||
834 | if ( flag_altform2 ) |
||
835 | { |
||
836 | buf[( bufpt++ )] = '0'; |
||
837 | } |
||
838 | else |
||
839 | { |
||
840 | buf[( --bufpt )] = '0'; |
||
841 | } |
||
842 | } |
||
843 | } |
||
844 | /* Add the "eNNN" suffix */ |
||
845 | if ( flag_exp || xtype == etEXP ) |
||
846 | { |
||
847 | buf[bufpt++] = aDigits[infop.charset]; |
||
848 | if ( exp < 0 ) |
||
849 | { |
||
850 | buf[bufpt++] = '-'; |
||
851 | exp = -exp; |
||
852 | } |
||
853 | else |
||
854 | { |
||
855 | buf[bufpt++] = '+'; |
||
856 | } |
||
857 | if ( exp >= 100 ) |
||
858 | { |
||
859 | buf[bufpt++] = (char)( exp / 100 + '0' ); /* 100's digit */ |
||
860 | exp %= 100; |
||
861 | } |
||
862 | buf[bufpt++] = (char)( exp / 10 + '0' ); /* 10's digit */ |
||
863 | buf[bufpt++] = (char)( exp % 10 + '0' ); /* 1's digit */ |
||
864 | } |
||
865 | //bufpt = 0; |
||
866 | |||
867 | /* The converted number is in buf[] and zero terminated. Output it. |
||
868 | ** Note that the number is in the usual order, not reversed as with |
||
869 | ** integer conversions. */ |
||
870 | length = bufpt;//length = (int)(bufpt-buf); |
||
871 | bufpt = 0; |
||
872 | |||
873 | /* Special case: Add leading zeros if the flag_zeropad flag is |
||
874 | ** set and we are not left justified */ |
||
875 | if ( flag_zeropad && !flag_leftjustify && length < width ) |
||
876 | { |
||
877 | int i; |
||
878 | int nPad = width - length; |
||
879 | for ( i = width; i >= nPad; i-- ) |
||
880 | { |
||
881 | buf[bufpt + i] = buf[bufpt + i - nPad]; |
||
882 | } |
||
883 | i = ( prefix != '\0' ? 1 : 0 ); |
||
884 | while ( nPad-- != 0 ) |
||
885 | buf[( bufpt++ ) + i] = '0'; |
||
886 | length = width; |
||
887 | bufpt = 0; |
||
888 | } |
||
889 | #endif //* !defined(SQLITE_OMIT_FLOATING_POINT) */ |
||
890 | break; |
||
891 | case etSIZE: |
||
892 | ap[0] = pAccum.nChar; // *(va_arg(ap,int)) = pAccum.nChar; |
||
893 | length = width = 0; |
||
894 | break; |
||
895 | case etPERCENT: |
||
896 | buf[0] = '%'; |
||
897 | bufpt = 0; |
||
898 | length = 1; |
||
899 | break; |
||
900 | case etCHARX: |
||
901 | c = va_arg( ap, (Char) 0); |
||
902 | buf[0] = (char)c; |
||
903 | if ( precision >= 0 ) |
||
904 | { |
||
905 | for ( idx = 1; idx < precision; idx++ ) |
||
906 | buf[idx] = (char)c; |
||
907 | length = precision; |
||
908 | } |
||
909 | else |
||
910 | { |
||
911 | length = 1; |
||
912 | } |
||
913 | bufpt = 0; |
||
914 | break; |
||
915 | case etSTRING: |
||
916 | case etDYNSTRING: |
||
917 | bufpt = 0;// |
||
918 | string bufStr = (string)va_arg( ap, "string" ); |
||
919 | if ( bufStr.Length > buf.Length ) |
||
920 | buf = new char[bufStr.Length]; |
||
921 | bufStr.ToCharArray().CopyTo( buf, 0 ); |
||
922 | bufpt = bufStr.Length; |
||
923 | if ( bufpt == 0 ) |
||
924 | { |
||
925 | buf[0] = '\0'; |
||
926 | } |
||
927 | else if ( xtype == etDYNSTRING ) |
||
928 | { |
||
929 | // zExtra = bufpt; |
||
930 | } |
||
931 | if ( precision >= 0 ) |
||
932 | { |
||
933 | for ( length = 0; length < precision && length < bufStr.Length && buf[length] != 0; length++ ) |
||
934 | { |
||
935 | } |
||
936 | //length += precision; |
||
937 | } |
||
938 | else |
||
939 | { |
||
940 | length = sqlite3Strlen30( bufpt ); |
||
941 | } |
||
942 | bufpt = 0; |
||
943 | break; |
||
944 | case etSQLESCAPE: |
||
945 | case etSQLESCAPE2: |
||
946 | case etSQLESCAPE3: |
||
947 | { |
||
948 | int i; |
||
949 | int j; |
||
950 | int k; |
||
951 | int n; |
||
952 | bool needQuote; |
||
953 | char ch; |
||
954 | char q = ( ( xtype == etSQLESCAPE3 ) ? '"' : '\'' ); /* Quote character */ |
||
955 | string escarg = (string)va_arg( ap, "char*" ) + '\0'; |
||
956 | bool isnull = ( escarg.Length == 0 || escarg == "NULL\0" ); |
||
957 | if ( isnull ) |
||
958 | escarg = ( xtype == etSQLESCAPE2 ) ? "NULL\0" : "(NULL)\0"; |
||
959 | k = precision; |
||
960 | for ( i = n = 0; k != 0 && ( ch = escarg[i] ) != 0; i++, k-- ) |
||
961 | { |
||
962 | if ( ch == q ) |
||
963 | n++; |
||
964 | } |
||
965 | needQuote = !isnull && ( xtype == etSQLESCAPE2 ); |
||
966 | n += i + 1 + ( needQuote ? 2 : 0 ); |
||
967 | if ( n > etBUFSIZE ) |
||
968 | { |
||
969 | buf = new char[n];//bufpt = zExtra = sqlite3Malloc(n); |
||
970 | //if ( bufpt == 0 ) |
||
971 | //{ |
||
972 | // pAccum->mallocFailed = 1; |
||
973 | // return; |
||
974 | //} |
||
975 | bufpt = 0; //Start of Buffer |
||
976 | } |
||
977 | else |
||
978 | { |
||
979 | //bufpt = buf; |
||
980 | bufpt = 0; //Start of Buffer |
||
981 | } |
||
982 | j = 0; |
||
983 | if ( needQuote ) |
||
984 | buf[bufpt + j++] = q; |
||
985 | k = i; |
||
986 | for ( i = 0; i < k; i++ ) |
||
987 | { |
||
988 | buf[bufpt + j++] = ch = escarg[i]; |
||
989 | if ( ch == q ) |
||
990 | buf[bufpt + j++] = ch; |
||
991 | } |
||
992 | if ( needQuote ) |
||
993 | buf[bufpt + j++] = q; |
||
994 | buf[bufpt + j] = '\0'; |
||
995 | length = j; |
||
996 | /* The precision in %q and %Q means how many input characters to |
||
997 | ** consume, not the length of the output... |
||
998 | ** if( precision>=0 && precision<length ) length = precision; */ |
||
999 | break; |
||
1000 | } |
||
1001 | case etTOKEN: |
||
1002 | { |
||
1003 | Token pToken; |
||
1004 | if ( ap[vaNEXT] is String ) |
||
1005 | { |
||
1006 | pToken = new Token(); |
||
1007 | pToken.z = va_arg( ap, ( String ) null); |
||
1008 | pToken.n = pToken.z.Length; |
||
1009 | } |
||
1010 | else |
||
1011 | pToken = va_arg( ap, (Token) null ); |
||
1012 | if ( pToken != null ) |
||
1013 | { |
||
1014 | sqlite3StrAccumAppend( pAccum, pToken.z.ToString(), (int)pToken.n ); |
||
1015 | } |
||
1016 | length = width = 0; |
||
1017 | break; |
||
1018 | } |
||
1019 | case etSRCLIST: |
||
1020 | { |
||
1021 | SrcList pSrc = va_arg( ap, ( SrcList )null ); |
||
1022 | int k = va_arg( ap, ( Int32 ) 0 ); |
||
1023 | SrcList_item pItem = pSrc.a[k]; |
||
1024 | Debug.Assert( k >= 0 && k < pSrc.nSrc ); |
||
1025 | if ( pItem.zDatabase != null ) |
||
1026 | { |
||
1027 | sqlite3StrAccumAppend( pAccum, pItem.zDatabase, -1 ); |
||
1028 | sqlite3StrAccumAppend( pAccum, ".", 1 ); |
||
1029 | } |
||
1030 | sqlite3StrAccumAppend( pAccum, pItem.zName, -1 ); |
||
1031 | length = width = 0; |
||
1032 | break; |
||
1033 | } |
||
1034 | default: |
||
1035 | { |
||
1036 | Debug.Assert( xtype == etINVALID ); |
||
1037 | return; |
||
1038 | } |
||
1039 | }/* End switch over the format type */ |
||
1040 | /* |
||
1041 | ** The text of the conversion is pointed to by "bufpt" and is |
||
1042 | ** "length" characters long. The field width is "width". Do |
||
1043 | ** the output. |
||
1044 | */ |
||
1045 | if ( !flag_leftjustify ) |
||
1046 | { |
||
1047 | int nspace; |
||
1048 | nspace = width - length;// -2; |
||
1049 | if ( nspace > 0 ) |
||
1050 | { |
||
1051 | appendSpace( pAccum, nspace ); |
||
1052 | } |
||
1053 | } |
||
1054 | if ( length > 0 ) |
||
1055 | { |
||
1056 | sqlite3StrAccumAppend( pAccum, new string( buf, bufpt, length ), length ); |
||
1057 | } |
||
1058 | if ( flag_leftjustify ) |
||
1059 | { |
||
1060 | int nspace; |
||
1061 | nspace = width - length; |
||
1062 | if ( nspace > 0 ) |
||
1063 | { |
||
1064 | appendSpace( pAccum, nspace ); |
||
1065 | } |
||
1066 | } |
||
1067 | //if( zExtra ){ |
||
1068 | // sqlite3DbFree(db,ref zExtra); |
||
1069 | //} |
||
1070 | }/* End for loop over the format string */ |
||
1071 | } /* End of function */ |
||
1072 | |||
1073 | /* |
||
1074 | ** Append N bytes of text from z to the StrAccum object. |
||
1075 | */ |
||
1076 | |||
1077 | static void sqlite3StrAccumAppend( StrAccum p, string z, int N ) |
||
1078 | { |
||
1079 | Debug.Assert( z != null || N == 0 ); |
||
1080 | if ( p.tooBig )//|| p.mallocFailed != 0 ) |
||
1081 | { |
||
1082 | testcase( p.tooBig ); |
||
1083 | //testcase( p.mallocFailed ); |
||
1084 | return; |
||
1085 | } |
||
1086 | if ( N < 0 ) |
||
1087 | { |
||
1088 | N = sqlite3Strlen30( z ); |
||
1089 | } |
||
1090 | if ( N == 0 || NEVER( z == null ) ) |
||
1091 | { |
||
1092 | return; |
||
1093 | } |
||
1094 | //if( p->nChar+N >= p->nAlloc ){ |
||
1095 | // string zNew; |
||
1096 | // if( null==p->useMalloc ){ |
||
1097 | // p->tooBig = 1; |
||
1098 | // N = p->nAlloc - p->nChar - 1; |
||
1099 | // if( N<=0 ){ |
||
1100 | // return; |
||
1101 | // } |
||
1102 | // }else{ |
||
1103 | // string zOld = (p->zText==p->zBase ? 0 : p->zText); |
||
1104 | // i64 szNew = p->nChar; |
||
1105 | // szNew += N + 1; |
||
1106 | // if( szNew > p->mxAlloc ){ |
||
1107 | // sqlite3StrAccumReset(p); |
||
1108 | // p->tooBig = 1; |
||
1109 | // return; |
||
1110 | // }else{ |
||
1111 | // p->nAlloc = (int)szNew; |
||
1112 | // } |
||
1113 | // if( p->useMalloc==1 ){ |
||
1114 | // zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); |
||
1115 | // }else{ |
||
1116 | // zNew = sqlite3_realloc(zOld, p->nAlloc); |
||
1117 | // } |
||
1118 | // if( zNew ){ |
||
1119 | // if( zOld==0 ) memcpy(zNew, p->zText, p->nChar); |
||
1120 | // p->zText = zNew; |
||
1121 | // }else{ |
||
1122 | // p->mallocFailed = 1; |
||
1123 | // sqlite3StrAccumReset(p); |
||
1124 | // return; |
||
1125 | // } |
||
1126 | // } |
||
1127 | //} |
||
1128 | //memcpy(&p->zText[p->nChar], z, N); |
||
1129 | p.zText.Append( z.Substring( 0, N <= z.Length ? N : z.Length ) ); |
||
1130 | //p.nChar += N; |
||
1131 | } |
||
1132 | |||
1133 | /* |
||
1134 | ** Finish off a string by making sure it is zero-terminated. |
||
1135 | ** Return a pointer to the resulting string. Return a NULL |
||
1136 | ** pointer if any kind of error was encountered. |
||
1137 | */ |
||
1138 | static string sqlite3StrAccumFinish( StrAccum p ) |
||
1139 | { |
||
1140 | //if ( p->zText ) |
||
1141 | //{ |
||
1142 | // p->zText[p->nChar] = 0; |
||
1143 | // if ( p->useMalloc && p->zText == p->zBase ) |
||
1144 | // { |
||
1145 | // if ( p->useMalloc == 1 ) |
||
1146 | // { |
||
1147 | // p->zText = sqlite3DbMallocRaw( p->db, p->nChar + 1 ); |
||
1148 | // } |
||
1149 | // else |
||
1150 | // { |
||
1151 | // p->zText = sqlite3_malloc( p->nChar + 1 ); |
||
1152 | // } |
||
1153 | // if ( p->zText ) |
||
1154 | // { |
||
1155 | // memcpy( p->zText, p->zBase, p->nChar + 1 ); |
||
1156 | // } |
||
1157 | // else |
||
1158 | // { |
||
1159 | // p->mallocFailed = 1; |
||
1160 | // } |
||
1161 | // } |
||
1162 | //} |
||
1163 | return p.zText.ToString(); |
||
1164 | } |
||
1165 | |||
1166 | /* |
||
1167 | ** Reset an StrAccum string. Reclaim all malloced memory. |
||
1168 | */ |
||
1169 | static void sqlite3StrAccumReset( StrAccum p ) |
||
1170 | { |
||
1171 | //if ( p.zText.ToString() != p.zBase.ToString() ) |
||
1172 | //{ |
||
1173 | // if ( p.useMalloc == 1 ) |
||
1174 | // { |
||
1175 | // sqlite3DbFree( p.db, ref p.zText ); |
||
1176 | // } |
||
1177 | // else |
||
1178 | // { |
||
1179 | // sqlite3_free( ref p.zText ); |
||
1180 | // } |
||
1181 | //} |
||
1182 | p.zText.Length = 0; |
||
1183 | } |
||
1184 | |||
1185 | /* |
||
1186 | ** Initialize a string accumulator |
||
1187 | */ |
||
1188 | static void sqlite3StrAccumInit( StrAccum p, StringBuilder zBase, int n, int mx ) |
||
1189 | { |
||
1190 | //p.zBase.Length = 0; |
||
1191 | //if ( p.zBase.Capacity < n ) |
||
1192 | // p.zBase.Capacity = n; |
||
1193 | p.zText.Length = 0; |
||
1194 | if ( p.zText.Capacity < n ) |
||
1195 | p.zText.Capacity = n; |
||
1196 | p.db = null; |
||
1197 | //p.nChar = 0; |
||
1198 | //p.nAlloc = n; |
||
1199 | p.mxAlloc = mx; |
||
1200 | //p.useMalloc = 1; |
||
1201 | //p.tooBig = 0; |
||
1202 | //p.mallocFailed = 0; |
||
1203 | } |
||
1204 | /* |
||
1205 | ** Print into memory obtained from sqliteMalloc(). Use the internal |
||
1206 | ** %-conversion extensions. |
||
1207 | */ |
||
1208 | static StrAccum acc = new StrAccum( SQLITE_PRINT_BUF_SIZE ); |
||
1209 | static string sqlite3VMPrintf( sqlite3 db, string zFormat, params va_list[] ap ) |
||
1210 | { |
||
1211 | if ( zFormat == null ) |
||
1212 | return null; |
||
1213 | if ( ap.Length == 0 ) |
||
1214 | return zFormat; |
||
1215 | //string z; |
||
1216 | Debug.Assert( db != null ); |
||
1217 | sqlite3StrAccumInit( acc, null, SQLITE_PRINT_BUF_SIZE, |
||
1218 | db.aLimit[SQLITE_LIMIT_LENGTH] ); |
||
1219 | acc.db = db; |
||
1220 | acc.zText.Length = 0; |
||
1221 | sqlite3VXPrintf( acc, 1, zFormat, ap ); |
||
1222 | // if ( acc.mallocFailed != 0 ) |
||
1223 | // { |
||
1224 | ////// db.mallocFailed = 1; |
||
1225 | // } |
||
1226 | return sqlite3StrAccumFinish( acc ); |
||
1227 | } |
||
1228 | |||
1229 | /* |
||
1230 | ** Print into memory obtained from sqliteMalloc(). Use the internal |
||
1231 | ** %-conversion extensions. |
||
1232 | */ |
||
1233 | static string sqlite3MPrintf( sqlite3 db, string zFormat, params va_list[] ap ) |
||
1234 | { |
||
1235 | string z; |
||
1236 | //va_list ap; |
||
1237 | lock ( lock_va_list ) |
||
1238 | { |
||
1239 | va_start( ap, zFormat ); |
||
1240 | z = sqlite3VMPrintf( db, zFormat, ap ); |
||
1241 | va_end( ref ap ); |
||
1242 | } |
||
1243 | return z; |
||
1244 | } |
||
1245 | |||
1246 | /* |
||
1247 | ** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting |
||
1248 | ** the string and before returnning. This routine is intended to be used |
||
1249 | ** to modify an existing string. For example: |
||
1250 | ** |
||
1251 | ** x = sqlite3MPrintf(db, x, "prefix %s suffix", x); |
||
1252 | ** |
||
1253 | */ |
||
1254 | static string sqlite3MAppendf( sqlite3 db, string zStr, string zFormat, params va_list[] ap ) |
||
1255 | { |
||
1256 | string z; |
||
1257 | //va_list ap; |
||
1258 | lock ( lock_va_list ) |
||
1259 | { |
||
1260 | va_start( ap, zFormat ); |
||
1261 | z = sqlite3VMPrintf( db, zFormat, ap ); |
||
1262 | va_end( ref ap ); |
||
1263 | sqlite3DbFree( db, ref zStr ); |
||
1264 | } |
||
1265 | return z; |
||
1266 | } |
||
1267 | |||
1268 | /* |
||
1269 | ** Print into memory obtained from sqlite3Malloc(). Omit the internal |
||
1270 | ** %-conversion extensions. |
||
1271 | */ |
||
1272 | static string sqlite3_vmprintf( string zFormat, params va_list[] ap ) |
||
1273 | { |
||
1274 | //StrAccum acc = new StrAccum( SQLITE_PRINT_BUF_SIZE ); |
||
1275 | #if !SQLITE_OMIT_AUTOINIT |
||
1276 | if ( sqlite3_initialize() != 0 ) |
||
1277 | return string.Empty; |
||
1278 | #endif |
||
1279 | sqlite3StrAccumInit( acc, null, SQLITE_PRINT_BUF_SIZE, SQLITE_PRINT_BUF_SIZE );//zBase).Length; |
||
1280 | //acc.useMalloc = 2; |
||
1281 | sqlite3VXPrintf( acc, 0, zFormat, ap ); |
||
1282 | return sqlite3StrAccumFinish( acc ); |
||
1283 | } |
||
1284 | |||
1285 | /* |
||
1286 | ** Print into memory obtained from sqlite3Malloc()(). Omit the internal |
||
1287 | ** %-conversion extensions. |
||
1288 | */ |
||
1289 | static public string sqlite3_mprintf( string zFormat, params va_list[] ap ) |
||
1290 | { //, ...){ |
||
1291 | string z; |
||
1292 | #if !SQLITE_OMIT_AUTOINIT |
||
1293 | if ( sqlite3_initialize() != 0 ) |
||
1294 | return string.Empty; |
||
1295 | #endif |
||
1296 | //va_list ap; |
||
1297 | lock ( lock_va_list ) |
||
1298 | { |
||
1299 | va_start( ap, zFormat ); |
||
1300 | z = sqlite3_vmprintf( zFormat, ap ); |
||
1301 | va_end( ref ap ); |
||
1302 | } |
||
1303 | return z; |
||
1304 | } |
||
1305 | |||
1306 | /* |
||
1307 | ** sqlite3_snprintf() works like snprintf() except that it ignores the |
||
1308 | ** current locale settings. This is important for SQLite because we |
||
1309 | ** are not able to use a "," as the decimal point in place of "." as |
||
1310 | ** specified by some locales. |
||
1311 | ** |
||
1312 | ** Oops: The first two arguments of sqlite3_snprintf() are backwards |
||
1313 | ** from the snprintf() standard. Unfortunately, it is too late to change |
||
1314 | ** this without breaking compatibility, so we just have to live with the |
||
1315 | ** mistake. |
||
1316 | ** |
||
1317 | ** sqlite3_vsnprintf() is the varargs version. |
||
1318 | */ |
||
1319 | static public void sqlite3_vsnprintf( int n, StringBuilder zBuf, string zFormat, params va_list[] ap ) |
||
1320 | { |
||
1321 | //StrAccum acc = new StrAccum( SQLITE_PRINT_BUF_SIZE ); |
||
1322 | if ( n <= 0 ) |
||
1323 | return; |
||
1324 | sqlite3StrAccumInit( acc, null, n, 0 ); |
||
1325 | //acc.useMalloc = 0; |
||
1326 | sqlite3VXPrintf( acc, 0, zFormat, ap ); |
||
1327 | zBuf.Length = 0; |
||
1328 | if ( n > 1 && n <= acc.zText.Length ) |
||
1329 | acc.zText.Length = n - 1; |
||
1330 | zBuf.Append( sqlite3StrAccumFinish( acc ) ); |
||
1331 | return; |
||
1332 | } |
||
1333 | |||
1334 | static public void sqlite3_snprintf( int n, StringBuilder zBuf, string zFormat, params va_list[] ap ) |
||
1335 | { |
||
1336 | //string z; |
||
1337 | //va_list ap; |
||
1338 | lock ( lock_va_list ) |
||
1339 | {//StrAccum acc = new StrAccum( SQLITE_PRINT_BUF_SIZE ); |
||
1340 | zBuf.EnsureCapacity( SQLITE_PRINT_BUF_SIZE ); |
||
1341 | va_start( ap, zFormat ); |
||
1342 | sqlite3_vsnprintf( n, zBuf, zFormat, ap ); |
||
1343 | va_end( ref ap ); |
||
1344 | } |
||
1345 | return; |
||
1346 | } |
||
1347 | |||
1348 | //static public string sqlite3_snprintf( int n, ref string zBuf, string zFormat, params va_list[] ap ) |
||
1349 | //{ |
||
1350 | // string z; |
||
1351 | // //va_list ap; |
||
1352 | // StrAccum acc = new StrAccum( SQLITE_PRINT_BUF_SIZE ); |
||
1353 | |||
1354 | // if ( n <= 0 ) |
||
1355 | // { |
||
1356 | // return zBuf; |
||
1357 | // } |
||
1358 | // sqlite3StrAccumInit( acc, null, n, 0 ); |
||
1359 | // //acc.useMalloc = 0; |
||
1360 | // va_start( ap, zFormat ); |
||
1361 | // sqlite3VXPrintf( acc, 0, zFormat, ap ); |
||
1362 | // va_end( ap ); |
||
1363 | // z = sqlite3StrAccumFinish( acc ); |
||
1364 | // return ( zBuf = z ); |
||
1365 | //} |
||
1366 | |||
1367 | /* |
||
1368 | ** This is the routine that actually formats the sqlite3_log() message. |
||
1369 | ** We house it in a separate routine from sqlite3_log() to avoid using |
||
1370 | ** stack space on small-stack systems when logging is disabled. |
||
1371 | ** |
||
1372 | ** sqlite3_log() must render into a static buffer. It cannot dynamically |
||
1373 | ** allocate memory because it might be called while the memory allocator |
||
1374 | ** mutex is held. |
||
1375 | */ |
||
1376 | static void renderLogMsg( int iErrCode, string zFormat, params object[] ap ) |
||
1377 | { |
||
1378 | //StrAccum acc; /* String accumulator */ |
||
1379 | //char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
||
1380 | |||
1381 | sqlite3StrAccumInit( acc, null, SQLITE_PRINT_BUF_SIZE * 3, 0 ); |
||
1382 | //acc.useMalloc = 0; |
||
1383 | sqlite3VXPrintf( acc, 0, zFormat, ap ); |
||
1384 | sqlite3GlobalConfig.xLog( sqlite3GlobalConfig.pLogArg, iErrCode, |
||
1385 | sqlite3StrAccumFinish( acc ) ); |
||
1386 | } |
||
1387 | |||
1388 | /* |
||
1389 | ** Format and write a message to the log if logging is enabled. |
||
1390 | */ |
||
1391 | static void sqlite3_log( int iErrCode, string zFormat, params va_list[] ap ) |
||
1392 | { |
||
1393 | if ( sqlite3GlobalConfig.xLog != null ) |
||
1394 | { |
||
1395 | //va_list ap; /* Vararg list */ |
||
1396 | lock ( lock_va_list ) |
||
1397 | { |
||
1398 | va_start( ap, zFormat ); |
||
1399 | renderLogMsg( iErrCode, zFormat, ap ); |
||
1400 | va_end( ref ap ); |
||
1401 | } |
||
1402 | } |
||
1403 | } |
||
1404 | |||
1405 | #if SQLITE_DEBUG || DEBUG || TRACE |
||
1406 | /* |
||
1407 | ** A version of printf() that understands %lld. Used for debugging. |
||
1408 | ** The printf() built into some versions of windows does not understand %lld |
||
1409 | ** and segfaults if you give it a long long int. |
||
1410 | */ |
||
1411 | static void sqlite3DebugPrintf( string zFormat, params va_list[] ap ) |
||
1412 | { |
||
1413 | //va_list ap; |
||
1414 | lock ( lock_va_list ) |
||
1415 | { |
||
1416 | //StrAccum acc = new StrAccum( SQLITE_PRINT_BUF_SIZE ); |
||
1417 | sqlite3StrAccumInit( acc, null, SQLITE_PRINT_BUF_SIZE, 0 ); |
||
1418 | //acc.useMalloc = 0; |
||
1419 | va_start( ap, zFormat ); |
||
1420 | sqlite3VXPrintf( acc, 0, zFormat, ap ); |
||
1421 | va_end( ref ap ); |
||
1422 | } |
||
1423 | Console.Write( sqlite3StrAccumFinish( acc ) ); |
||
1424 | //fflush(stdout); |
||
1425 | } |
||
1426 | #endif |
||
1427 | #if !SQLITE_OMIT_TRACE |
||
1428 | /* |
||
1429 | ** variable-argument wrapper around sqlite3VXPrintf(). |
||
1430 | */ |
||
1431 | static void sqlite3XPrintf( StrAccum p, string zFormat, params object[] ap ) |
||
1432 | { |
||
1433 | //va_list ap; |
||
1434 | lock ( lock_va_list ) |
||
1435 | { |
||
1436 | va_start( ap, zFormat ); |
||
1437 | sqlite3VXPrintf( p, 1, zFormat, ap ); |
||
1438 | va_end( ref ap ); |
||
1439 | } |
||
1440 | } |
||
1441 | #endif |
||
1442 | |||
1443 | } |
||
1444 | } |