File Coverage

xs/XS.xs
Criterion Covered Total %
statement 675 802 84.1
branch 550 1038 52.9
condition n/a
subroutine n/a
pod n/a
total 1225 1840 66.5


line stmt bran cond sub pod time code
1             /* vim: set ts=2 sts=2 sw=2 et tw=75: */
2              
3             /*
4             * Copyright 2009-2016 MongoDB, Inc.
5             *
6             * Licensed under the Apache License, Version 2.0 (the "License");
7             * you may not use this file except in compliance with the License.
8             * You may obtain a copy of the License at
9             *
10             * http://www.apache.org/licenses/LICENSE-2.0
11             *
12             * Unless required by applicable law or agreed to in writing, software
13             * distributed under the License is distributed on an "AS IS" BASIS,
14             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15             * See the License for the specific language governing permissions and
16             * limitations under the License.
17             */
18              
19             #include "bson.h"
20             #include "EXTERN.h"
21             #include "perl.h"
22             #include "XSUB.h"
23             #include "regcomp.h"
24             #include "string.h"
25             #include "limits.h"
26              
27             /* load after other Perl headers */
28             #include "ppport.h"
29              
30             /* adapted from perl.h and must come after it */
31             #if !defined(Strtoll)
32             # ifdef __hpux
33             # define Strtoll __strtoll
34             # endif
35             # ifdef WIN32
36             # define Strtoll _strtoi64
37             # endif
38             # if !defined(Strtoll) && defined(HAS_STRTOLL)
39             # define Strtoll strtoll
40             # endif
41             # if !defined(Strtoll) && defined(HAS_STRTOQ)
42             # define Strtoll strtoq
43             # endif
44             # if !defined(Strtoll)
45             # error strtoll not available
46             # endif
47             #endif
48              
49             /* whether to add an _id field */
50             #define PREP 1
51             #define NO_PREP 0
52              
53             /* define regex macros for Perl 5.8 */
54             #ifndef RX_PRECOMP
55             #define RX_PRECOMP(re) ((re)->precomp)
56             #define RX_PRELEN(re) ((re)->prelen)
57             #endif
58              
59             #define SUBTYPE_BINARY_DEPRECATED 2
60             #define SUBTYPE_BINARY 0
61              
62             /* struct for circular ref checks */
63             typedef struct _stackette {
64             void *ptr;
65             struct _stackette *prev;
66             } stackette;
67              
68             #define EMPTY_STACK 0
69              
70             #define MAX_DEPTH 100
71              
72             /* convenience functions taken from Text::CSV_XS by H.M. Brand */
73             #define _is_reftype(f,x) \
74             (f && ((SvGMAGICAL (f) && mg_get (f)) || 1) && SvROK (f) && SvTYPE (SvRV (f)) == x)
75             #define _is_arrayref(f) _is_reftype (f, SVt_PVAV)
76             #define _is_hashref(f) _is_reftype (f, SVt_PVHV)
77             #define _is_coderef(f) _is_reftype (f, SVt_PVCV)
78              
79             /* shorthand for getting an SV* from a hash and key */
80             #define _hv_fetchs_sv(h,k) \
81             (((svp = hv_fetchs(h, k, FALSE)) && *svp) ? *svp : 0)
82              
83             /* perl call helpers
84             *
85             * For convenience, these functions encapsulate the verbose stack
86             * manipulation code necessary to call perl functions from C.
87             *
88             */
89              
90             static SV * call_method_va(SV *self, const char *method, int num, ...);
91             static SV * call_method_with_pairs_va(SV *self, const char *method, ...);
92             static SV * new_object_from_pairs(const char *klass, ...);
93             static SV * call_method_with_arglist (SV *self, const char *method, va_list args);
94             static SV * call_sv_va (SV *func, int num, ...);
95             static SV * call_pv_va (char *func, int num, ...);
96             static bool call_key_value_iter (SV *func, SV **ret );
97              
98             #define call_perl_reader(s,m) call_method_va(s,m,0)
99              
100             /* BSON encoding
101             *
102             * Public function perl_mongo_sv_to_bsonis the entry point. It calls one
103             * of the container encoding functions, hv_doc_to_bson, or
104             * ixhash_doc_to_bson. Those iterate their contents, encoding them with
105             * sv_to_bson_elem. sv_to_bson_elem delegates to various append_*
106             * functions for particular types.
107             *
108             * Other functions are utility functions used during encoding.
109             */
110              
111             static void perl_mongo_sv_to_bson (bson_t * bson, SV *sv, HV *opts);
112              
113             static void hv_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc);
114             static void ixhash_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc);
115             static void iter_src_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc);
116              
117             #define hv_doc_to_bson(b,d,o,s,u) hv_to_bson((b),(d),(o),(s),(u),0)
118             #define hv_elem_to_bson(b,d,o,s,u) hv_to_bson((b),(d),(o),(s),(u),1)
119             #define ixhash_doc_to_bson(b,d,o,s,u) ixhash_to_bson((b),(d),(o),(s),(u),0)
120             #define ixhash_elem_to_bson(b,d,o,s,u) ixhash_to_bson((b),(d),(o),(s),(u),1)
121             #define iter_doc_to_bson(b,d,o,s,u) iter_src_to_bson((b),(d),(o),(s),(u),0)
122             #define iter_elem_to_bson(b,d,o,s,u) iter_src_to_bson((b),(d),(o),(s),(u),1)
123              
124             static void sv_to_bson_elem (bson_t * bson, const char *key, SV *sv, HV *opts, stackette *stack, int depth);
125              
126             const char * maybe_append_first_key(bson_t *bson, HV *opts, stackette *stack, int depth);
127              
128             static void append_binary(bson_t * bson, const char * key, bson_subtype_t subtype, SV * sv);
129             static void append_regex(bson_t * bson, const char *key, REGEXP *re, SV * sv);
130             static void append_decomposed_regex(bson_t *bson, const char *key, const char *pattern, const char *flags);
131             static void append_fit_int(bson_t * bson, const char *key, SV * sv);
132             static void append_utf8(bson_t * bson, const char *key, SV * sv);
133              
134             static void assert_valid_key(const char* str, STRLEN len);
135             static const char * bson_key(const char * str, HV *opts);
136             static void get_regex_flags(char * flags, SV *sv);
137             static int64_t math_bigint_to_int64(SV *sv, const char *key);
138             static SV* int64_as_SV(int64_t value);
139             static stackette * check_circular_ref(void *ptr, stackette *stack);
140             static SV* bson_parent_type(SV *sv);
141              
142             /* BSON decoding
143             *
144             * Public function _decode_bson is the entry point. It calls
145             * bson_doc_to_hashref, which construct a container and fills it using
146             * bson_elem_to_sv. That may call bson_doc_to_hashref or
147             * bson_doc_to_arrayref to decode sub-containers.
148             *
149             * The bson_oid_to_sv function manually constructs a BSON::OID object to
150             * avoid the overhead of calling its constructor. This optimization is
151             * fragile and might need to be reconsidered.
152             *
153             */
154              
155             static SV * bson_doc_to_hashref(bson_iter_t * iter, HV *opts, int depth, bool top);
156             static SV * bson_doc_to_tiedhash(bson_iter_t * iter, HV *opts, int depth, bool top);
157             static SV * bson_array_to_arrayref(bson_iter_t * iter, HV *opts, int depth);
158             static SV * bson_elem_to_sv(const bson_iter_t * iter, const char *key, HV *opts, int depth);
159             static SV * bson_oid_to_sv(const bson_iter_t * iter);
160              
161             /********************************************************************
162             * Some C libraries (e.g. MSVCRT) do not have a "timegm" function.
163             * Here is a surrogate implementation.
164             ********************************************************************/
165              
166             #if defined(WIN32) || defined(sun)
167              
168             static int
169             is_leap_year(unsigned year) {
170             year += 1900;
171             return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
172             }
173              
174             static time_t
175             timegm(struct tm *tm) {
176             static const unsigned month_start[2][12] = {
177             { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
178             { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
179             };
180             time_t ret = 0;
181             int i;
182              
183             for (i = 70; i < tm->tm_year; ++i)
184             ret += is_leap_year(i) ? 366 : 365;
185              
186             ret += month_start[is_leap_year(tm->tm_year)][tm->tm_mon];
187             ret += tm->tm_mday - 1;
188             ret *= 24;
189             ret += tm->tm_hour;
190             ret *= 60;
191             ret += tm->tm_min;
192             ret *= 60;
193             ret += tm->tm_sec;
194             return ret;
195             }
196              
197             #endif /* WIN32 */
198              
199             /********************************************************************
200             * perl call helpers
201             ********************************************************************/
202              
203             /* call_method_va -- calls a method with a variable number
204             * of SV * arguments. The SV* arguments are NOT mortalized.
205             * Must give the number of arguments before the variable list */
206              
207             static SV *
208 3452           call_method_va (SV *self, const char *method, int num, ...) {
209 3452           dSP;
210             SV *ret;
211             I32 count;
212             va_list args;
213              
214 3452           ENTER;
215 3452           SAVETMPS;
216 3452 50         PUSHMARK (SP);
217 3452 50         XPUSHs (self);
218              
219 3452           va_start (args, num);
220 6536 100         for( ; num > 0; num-- ) {
221 3084 50         XPUSHs (va_arg( args, SV* ));
    50          
222             }
223 3452           va_end(args);
224              
225 3452           PUTBACK;
226 3452           count = call_method (method, G_SCALAR);
227              
228 3452           SPAGAIN;
229 3452 50         if (count != 1) {
230 0           croak ("method didn't return a value");
231             }
232 3452           ret = POPs;
233 3452           SvREFCNT_inc (ret);
234              
235 3452           PUTBACK;
236 3452 50         FREETMPS;
237 3452           LEAVE;
238              
239 3452           return ret;
240             }
241              
242             /* call_method_va_paris -- calls a method with a variable number
243             * of key/value pairs as paired char* and SV* arguments. The SV* arguments
244             * are NOT mortalized. The final argument must be a NULL key. */
245              
246             static SV *
247 0           call_method_with_pairs_va (SV *self, const char *method, ...) {
248             SV *ret;
249             va_list args;
250 0           va_start (args, method);
251 0           ret = call_method_with_arglist(self, method, args);
252 0           va_end(args);
253 0           return ret;
254             }
255              
256             /* new_object_from_pairs -- calls 'new' with a variable number of
257             * of key/value pairs as paired char* and SV* arguments. The SV* arguments
258             * are NOT mortalized. The final argument must be a NULL key. */
259              
260             static SV *
261 2913           new_object_from_pairs(const char *klass, ...) {
262             SV *ret;
263             va_list args;
264 2913           va_start (args, klass);
265 2913           ret = call_method_with_arglist(sv_2mortal(newSVpv(klass,0)), "new", args);
266 2913           va_end(args);
267 2913           return ret;
268             }
269              
270             static SV *
271 2913           call_method_with_arglist (SV *self, const char *method, va_list args) {
272 2913           dSP;
273 2913           SV *ret = NULL;
274             char *key;
275             I32 count;
276              
277 2913           ENTER;
278 2913           SAVETMPS;
279 2913 50         PUSHMARK (SP);
280 2913 50         XPUSHs (self);
281              
282 4434 50         while ((key = va_arg (args, char *))) {
    100          
283 1521 50         mXPUSHp (key, strlen (key));
284 1521 50         XPUSHs (va_arg (args, SV *));
    50          
285             }
286              
287 2913           PUTBACK;
288 2913           count = call_method (method, G_SCALAR);
289              
290 2913           SPAGAIN;
291 2913 50         if (count != 1) {
292 0           croak ("method didn't return a value");
293             }
294 2913           ret = POPs;
295 2913           SvREFCNT_inc (ret);
296              
297 2913           PUTBACK;
298 2913 50         FREETMPS;
299 2913           LEAVE;
300              
301 2913           return ret;
302             }
303              
304             static SV *
305 0           call_sv_va (SV *func, int num, ...) {
306 0           dSP;
307             SV *ret;
308             I32 count;
309             va_list args;
310              
311 0           ENTER;
312 0           SAVETMPS;
313 0 0         PUSHMARK (SP);
314              
315 0           va_start (args, num);
316 0 0         for( ; num > 0; num-- ) {
317 0 0         XPUSHs (va_arg( args, SV* ));
    0          
318             }
319 0           va_end(args);
320              
321 0           PUTBACK;
322 0           count = call_sv(func, G_SCALAR);
323              
324 0           SPAGAIN;
325 0 0         if (count != 1) {
326 0           croak ("method didn't return a value");
327             }
328 0           ret = POPs;
329 0           SvREFCNT_inc (ret);
330              
331 0           PUTBACK;
332 0 0         FREETMPS;
333 0           LEAVE;
334              
335 0           return ret;
336             }
337              
338              
339             /* Call func and return key value pairs.
340             *
341             * ret is address of (SV*)[2] where key and value will be put.
342             *
343             * return value is true if key is defined and false otherwise.
344             */
345             static bool
346 40           call_key_value_iter (SV *func, SV **ret ) {
347 40           dSP;
348             I32 count;
349             bool ok;
350              
351 40           ENTER;
352 40           SAVETMPS;
353 40 50         PUSHMARK (SP);
354 40           PUTBACK;
355              
356 40           count = call_sv(func, G_ARRAY);
357              
358 40           SPAGAIN;
359              
360 40 100         if ( count == 0 ) {
361 17           ok = false;
362             }
363             else {
364 23           SvREFCNT_inc (ret[1] = POPs);
365 23           SvREFCNT_inc (ret[0] = POPs);
366              
367 23 50         ok = SvOK(ret[0]) != 0;
    0          
    0          
368             }
369              
370 40           PUTBACK;
371 40 100         FREETMPS;
372 40           LEAVE;
373              
374 40           return ok;
375             }
376              
377             static SV *
378 1           call_pv_va (char *func, int num, ...) {
379 1           dSP;
380             SV *ret;
381             I32 count;
382             va_list args;
383              
384 1           ENTER;
385 1           SAVETMPS;
386 1 50         PUSHMARK (SP);
387              
388 1           va_start (args, num);
389 2 100         for( ; num > 0; num-- ) {
390 1 50         XPUSHs (va_arg( args, SV* ));
    50          
391             }
392 1           va_end(args);
393              
394 1           PUTBACK;
395 1           count = call_pv(func, G_SCALAR);
396              
397 1           SPAGAIN;
398 1 50         if (count != 1) {
399 0           croak ("function %s didn't return a value", func);
400             }
401 1           ret = POPs;
402 1           SvREFCNT_inc (ret);
403              
404 1           PUTBACK;
405 1 50         FREETMPS;
406 1           LEAVE;
407              
408 1           return ret;
409             }
410              
411             /********************************************************************
412             * BSON encoding
413             ********************************************************************/
414              
415             void
416 1965           perl_mongo_sv_to_bson (bson_t * bson, SV *sv, HV *opts) {
417              
418 1965 50         if (!SvROK (sv)) {
419 0           croak ("not a reference");
420             }
421              
422 1965 100         if ( ! sv_isobject(sv) ) {
423 1945 50         switch ( SvTYPE(SvRV(sv)) ) {
424             case SVt_PVHV:
425 1945           hv_doc_to_bson (bson, sv, opts, EMPTY_STACK, 0);
426 1936           break;
427             default:
428 0           sv_dump(sv);
429 0           croak ("Can't encode unhandled variable type");
430             }
431             }
432             else {
433             SV *obj;
434             char *class;
435              
436 20           obj = SvRV(sv);
437 20 50         class = HvNAME(SvSTASH(obj));
    50          
    50          
    0          
    50          
    50          
438              
439 20 100         if ( strEQ(class, "Tie::IxHash") ) {
440 3           ixhash_doc_to_bson(bson, sv, opts, EMPTY_STACK, 0);
441             }
442 17 100         else if ( strEQ(class, "BSON::Doc") ) {
443 14           iter_doc_to_bson(bson, sv, opts, EMPTY_STACK, 0);
444             }
445 3 100         else if ( strEQ(class, "BSON::Raw") ) {
446             STRLEN str_len;
447             SV *encoded;
448             const char *bson_str;
449             bson_t *child;
450              
451 1           encoded = sv_2mortal(call_perl_reader(sv, "bson"));
452 1 50         bson_str = SvPV(encoded, str_len);
453 1           child = bson_new_from_data((uint8_t*) bson_str, str_len);
454 1           bson_concat(bson, child);
455 1           bson_destroy(child);
456             }
457 2 50         else if ( strEQ(class, "MongoDB::BSON::_EncodedDoc") ) {
458             STRLEN str_len;
459             SV **svp;
460             SV *encoded;
461             const char *bson_str;
462             bson_t *child;
463              
464 0 0         encoded = _hv_fetchs_sv((HV *)obj, "bson");
    0          
465 0 0         bson_str = SvPV(encoded, str_len);
466 0           child = bson_new_from_data((uint8_t*) bson_str, str_len);
467 0           bson_concat(bson, child);
468 0           bson_destroy(child);
469             }
470 2 100         else if ( strEQ(class, "MongoDB::BSON::Raw") ) {
471             SV *str_sv;
472             char *str;
473             STRLEN str_len;
474             bson_t *child;
475              
476 1           str_sv = SvRV(sv);
477              
478             // check type ok
479 1 50         if (!SvPOK(str_sv)) {
480 0           croak("MongoDB::BSON::Raw must be a blessed string reference");
481             }
482              
483 1 50         str = SvPV(str_sv, str_len);
484              
485 1           child = bson_new_from_data((uint8_t*) str, str_len);
486 1           bson_concat(bson, child);
487 1           bson_destroy(child);
488             }
489 1 50         else if (SvTYPE(obj) == SVt_PVHV) {
490 0           hv_doc_to_bson(bson, sv, opts, EMPTY_STACK, 0);
491             }
492             else {
493 1           croak ("Can't encode non-container of type '%s'", class);
494             }
495             }
496 1954           }
497              
498             static void
499 2879           hv_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc) {
500             HE *he;
501             HV *hv;
502 2879           const char *first_key = NULL;
503              
504 2879           depth++;
505 2879 100         if ( depth > MAX_DEPTH ) {
506 2           croak("Exceeded max object depth of %d", MAX_DEPTH);
507             }
508 2877           hv = (HV*)SvRV(sv);
509 2877 100         if (!(stack = check_circular_ref(hv, stack))) {
510 3           croak("circular reference detected");
511             }
512              
513 2874 100         if ( ! subdoc ) {
514 1945           first_key = maybe_append_first_key(bson, opts, stack, depth);
515             }
516              
517 2874           (void)hv_iterinit (hv);
518 5582 100         while ((he = hv_iternext (hv))) {
519             SV **hval;
520             STRLEN len;
521 2916 100         const char *key = HePV (he, len);
    50          
522 2916 100         uint32_t utf8 = HeUTF8(he);
523 2916           assert_valid_key(key, len);
524              
525             /* if we've already added the first key, continue */
526 2915 50         if (first_key && strcmp(key, first_key) == 0) {
    0          
527 0           continue;
528             }
529              
530             /*
531             * HeVAL doesn't return the correct value for tie(%foo, 'Tie::IxHash')
532             * so we're using hv_fetch
533             */
534 2915 100         if ((hval = hv_fetch(hv, key, utf8 ? -len : len, 0)) == 0) {
    50          
535 0           croak("could not find hash value for key %s, len:%lu", key, (long unsigned int)len);
536             }
537 2915 100         if (!utf8) {
538 2181           key = (const char *) bytes_to_utf8((U8 *)key, &len);
539 2181           SAVEFREEPV(key);
540             }
541              
542 2915 50         if ( ! is_utf8_string((const U8*)key,len)) {
543 0           croak( "Invalid UTF-8 detected while encoding BSON" );
544             }
545              
546 2915           sv_to_bson_elem (bson, key, *hval, opts, stack, depth);
547             }
548              
549 2666           depth--;
550 2666           }
551              
552             static void
553 26           ixhash_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc) {
554             int i;
555             SV **keys_sv, **values_sv;
556             AV *array, *keys, *values;
557 26           const char *first_key = NULL;
558              
559 26           depth++;
560 26 50         if ( depth > MAX_DEPTH ) {
561 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
562             }
563              
564             /*
565             * a Tie::IxHash is of the form:
566             * [ {hash}, [keys], [order], 0 ]
567             */
568 26           array = (AV*)SvRV(sv);
569              
570             /* check if we're in an infinite loop */
571 26 100         if (!(stack = check_circular_ref(array, stack))) {
572 1           croak("circular ref");
573             }
574              
575             /* keys in order, from position 1 */
576 25           keys_sv = av_fetch(array, 1, 0);
577 25           keys = (AV*)SvRV(*keys_sv);
578              
579             /* values in order, from position 2 */
580 25           values_sv = av_fetch(array, 2, 0);
581 25           values = (AV*)SvRV(*values_sv);
582              
583 25 100         if ( ! subdoc ) {
584 3           first_key = maybe_append_first_key(bson, opts, stack, depth);
585             }
586              
587 79 100         for (i=0; i<=av_len(keys); i++) {
588             SV **k, **v;
589             STRLEN len;
590             const char *str;
591              
592 55 50         if (!(k = av_fetch(keys, i, 0)) ||
    50          
593 55           !(v = av_fetch(values, i, 0))) {
594 0           croak ("failed to fetch associative array value");
595             }
596              
597 55 100         str = SvPVutf8(*k, len);
598 55           assert_valid_key(str,len);
599              
600 55 50         if (first_key && strcmp(str, first_key) == 0) {
    0          
601 0           continue;
602             }
603              
604 55           sv_to_bson_elem(bson, str, *v, opts, stack, depth);
605             }
606              
607 24           depth--;
608 24           }
609              
610             /* Construct a BSON document from an iterator code ref that returns key
611             * value pairs */
612              
613             static void
614 17           iter_src_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc) {
615             int i;
616             SV *iter;
617             SV * kv[2];
618 17           const char *first_key = NULL;
619              
620 17           depth++;
621 17 50         if ( depth > MAX_DEPTH ) {
622 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
623             }
624              
625             /* check if we're in an infinite loop */
626 17 50         if (!(stack = check_circular_ref(SvRV(sv), stack))) {
627 0 0         croak("circular ref: %s", SvPV_nolen(sv));
628             }
629              
630 17 100         if ( ! subdoc ) {
631 14           first_key = maybe_append_first_key(bson, opts, stack, depth);
632             }
633              
634 17           iter = sv_2mortal(call_perl_reader(sv, "_iterator"));
635 17 50         if ( !SvROK(iter) || SvTYPE(SvRV(iter)) != SVt_PVCV ) {
    50          
636 0 0         croak("invalid iterator from %s", SvPV_nolen(sv));
637             }
638              
639 40 100         while ( call_key_value_iter( iter, kv ) ) {
640 23           sv_2mortal(kv[0]);
641 23           sv_2mortal(kv[1]);
642             STRLEN len;
643             const char *str;
644              
645 23 100         str = SvPVutf8(kv[0], len);
646 23           assert_valid_key(str,len);
647              
648 23 100         if (first_key && strcmp(str, first_key) == 0) {
    100          
649 1           continue;
650             }
651              
652 22           sv_to_bson_elem(bson, str, kv[1], opts, stack, depth);
653             }
654              
655 17           depth--;
656 17           }
657              
658             /* This is for an array reference contained *within* a document */
659             static void
660 17           av_to_bson (bson_t * bson, AV *av, HV *opts, stackette *stack, int depth) {
661             I32 i;
662              
663 17           depth++;
664 17 50         if ( depth > MAX_DEPTH ) {
665 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
666             }
667              
668 17 50         if (!(stack = check_circular_ref(av, stack))) {
669 0           croak("circular ref");
670             }
671              
672 144 100         for (i = 0; i <= av_len (av); i++) {
673             SV **sv;
674 128           SV *key = sv_2mortal(newSViv (i));
675 128 50         if (!(sv = av_fetch (av, i, 0)))
676 0 0         sv_to_bson_elem (bson, SvPV_nolen(key), newSV(0), opts, stack, depth);
677             else
678 128 50         sv_to_bson_elem (bson, SvPV_nolen(key), *sv, opts, stack, depth);
679             }
680              
681 16           depth--;
682 16           }
683              
684             /* verify and transform key, if necessary */
685             static const char *
686 3124           bson_key(const char * str, HV *opts) {
687             SV **svp;
688             SV *tempsv;
689             STRLEN len;
690              
691             /* first swap op_char if necessary */
692 3124 100         if (
693 3124 100         (tempsv = _hv_fetchs_sv(opts, "op_char"))
    50          
694 2 50         && SvOK(tempsv)
    0          
    0          
695 2 50         && SvPV_nolen(tempsv)[0] == str[0]
    100          
696             ) {
697 1           char *out = savepv(str);
698 1           SAVEFREEPV(out);
699 1           *out = '$';
700 1           str = out;
701             }
702              
703             /* then check for validity */
704 3124 50         if (
705 3124 50         (tempsv = _hv_fetchs_sv(opts, "invalid_chars"))
    50          
706 3124 50         && SvOK(tempsv)
    0          
    0          
707 3124 100         && (len = sv_len(tempsv))
708             ) {
709             STRLEN i;
710 2 50         const char *invalid = SvPV_nolen(tempsv);
711              
712 2 50         for (i=0; i
713 2 50         if (strchr(str, invalid[i])) {
714 2           croak("key '%s' has invalid character(s) '%s'", str, invalid);
715             }
716             }
717             }
718              
719 3122           return str;
720             }
721              
722             static void
723 3124           sv_to_bson_elem (bson_t * bson, const char * in_key, SV *sv, HV *opts, stackette *stack, int depth) {
724             SV **svp;
725 3124           const char * key = bson_key(in_key,opts);
726              
727 3122 100         if (!SvOK(sv)) {
    50          
    50          
728 1788 100         if (SvGMAGICAL(sv)) {
729 1779           mg_get(sv);
730             }
731             }
732              
733 3122 100         if (!SvOK(sv)) {
    50          
    50          
734 16           bson_append_null(bson, key, -1);
735 16           return;
736             }
737 3106 100         else if (SvROK (sv)) {
738 2846 100         if (sv_isobject (sv)) {
739 1908           const char* obj_type = sv_reftype(SvRV(sv), true);
740 1908           SV* parent = bson_parent_type(SvRV(sv));
741 1908 100         if ( parent != NULL ) {
742 1873 50         obj_type = (const char *) SvPV_nolen(parent);
743             }
744              
745             /* OIDs */
746 1908 100         if (strEQ(obj_type, "BSON::OID")) {
747 28           SV *attr = sv_2mortal(call_perl_reader(sv, "oid"));
748 28 50         char *bytes = SvPV_nolen(attr);
749             bson_oid_t oid;
750 28           bson_oid_init_from_data(&oid, (uint8_t*) bytes);
751              
752 28           bson_append_oid(bson, key, -1, &oid);
753              
754             }
755 1880 50         else if (strEQ(obj_type, "MongoDB::OID")) {
756 0           SV *attr = sv_2mortal(call_perl_reader(sv, "value"));
757 0 0         char *str = SvPV_nolen (attr);
758             bson_oid_t oid;
759 0           bson_oid_init_from_string(&oid, str);
760              
761 0           bson_append_oid(bson, key, -1, &oid);
762              
763             }
764             /* Tie::IxHash */
765 1880 100         else if (strEQ(obj_type, "Tie::IxHash")) {
766             bson_t child;
767              
768 3           bson_append_document_begin(bson, key, -1, &child);
769 3           ixhash_elem_to_bson(&child, sv, opts, stack, depth);
770 2           bson_append_document_end(bson, &child);
771             }
772 1877 100         else if (strEQ(obj_type, "BSON::Doc")) {
773             bson_t child;
774              
775 3           bson_append_document_begin(bson, key, -1, &child);
776 3           iter_elem_to_bson(&child, sv, opts, stack, depth);
777 3           bson_append_document_end(bson, &child);
778             }
779 1874 100         else if (strEQ(obj_type, "BSON::Array")) {
780             bson_t child;
781              
782 1           bson_append_array_begin(bson, key, -1, &child);
783 1           av_to_bson (&child, (AV *)SvRV (sv), opts, stack, depth);
784 1           bson_append_array_end(bson, &child);
785             }
786 1873 100         else if (strEQ(obj_type, "BSON::Raw")) {
787             STRLEN str_len;
788             SV *encoded;
789             const char *bson_str;
790             bson_t *child;
791              
792 102           encoded = sv_2mortal(call_perl_reader(sv, "bson"));
793 102 50         bson_str = SvPV(encoded, str_len);
794              
795 102           child = bson_new_from_data((uint8_t*) bson_str, str_len);
796 102           bson_append_document(bson, key, -1, child);
797 102           bson_destroy(child);
798             }
799 1771 100         else if (strEQ(obj_type, "MongoDB::BSON::Raw")) {
800             SV *str_sv;
801             char *str;
802             STRLEN str_len;
803             bson_t *child;
804              
805 2           str_sv = SvRV(sv);
806              
807             // check type ok
808 2 50         if (!SvPOK(str_sv)) {
809 0           croak("MongoDB::BSON::Raw must be a blessed string reference");
810             }
811              
812 2 50         str = SvPV(str_sv, str_len);
813              
814 2           child = bson_new_from_data((uint8_t*) str, str_len);
815 2           bson_append_document(bson, key, -1, child);
816 2           bson_destroy(child);
817             }
818 1769 100         else if (strEQ(obj_type, "BSON::Time")) {
819 19           SV *ms = sv_2mortal(call_perl_reader(sv, "value"));
820 19 50         if ( sv_isa(ms, "Math::BigInt") ) {
821 0           int64_t t = math_bigint_to_int64(ms,key);
822 0           bson_append_date_time(bson, key, -1, t);
823             }
824             else {
825 19 50         bson_append_date_time(bson, key, -1, (int64_t)SvIV(ms));
826             }
827             }
828             /* Time::Moment */
829 1750 100         else if (strEQ(obj_type, "Time::Moment")) {
830 1           SV *sec = sv_2mortal(call_perl_reader(sv, "epoch"));
831 1           SV *ms = sv_2mortal(call_perl_reader(sv, "millisecond"));
832 1 50         bson_append_date_time(bson, key, -1, (int64_t)SvIV(sec)*1000+SvIV(ms));
    50          
833             }
834             /* DateTime */
835 1749 50         else if (strEQ(obj_type, "DateTime")) {
836             SV *sec, *ms, *tz, *tz_name;
837             STRLEN len;
838             char *str;
839              
840             /* check for floating tz */
841 0           tz = sv_2mortal(call_perl_reader (sv, "time_zone"));
842 0           tz_name = sv_2mortal(call_perl_reader (tz, "name"));
843 0 0         str = SvPV(tz_name, len);
844 0 0         if (len == 8 && strncmp("floating", str, 8) == 0) {
    0          
845 0           warn("saving floating timezone as UTC");
846             }
847              
848 0           sec = sv_2mortal(call_perl_reader (sv, "epoch"));
849 0           ms = sv_2mortal(call_perl_reader(sv, "millisecond"));
850              
851 0 0         bson_append_date_time(bson, key, -1, (int64_t)SvIV(sec)*1000+SvIV(ms));
    0          
852             }
853             /* DateTime::TIny */
854 1749 50         else if (strEQ(obj_type, "DateTime::Tiny")) {
855             struct tm t;
856 0           time_t epoch_secs = time(NULL);
857             int64_t epoch_ms;
858              
859 0 0         t.tm_year = SvIV( sv_2mortal(call_perl_reader( sv, "year" )) ) - 1900;
860 0 0         t.tm_mon = SvIV( sv_2mortal(call_perl_reader( sv, "month" )) ) - 1;
861 0 0         t.tm_mday = SvIV( sv_2mortal(call_perl_reader( sv, "day" )) ) ;
862 0 0         t.tm_hour = SvIV( sv_2mortal(call_perl_reader( sv, "hour" )) ) ;
863 0 0         t.tm_min = SvIV( sv_2mortal(call_perl_reader( sv, "minute" )) ) ;
864 0 0         t.tm_sec = SvIV( sv_2mortal(call_perl_reader( sv, "second" )) ) ;
865 0           t.tm_isdst = -1; /* no dst/tz info in DateTime::Tiny */
866              
867 0           epoch_secs = timegm( &t );
868              
869             /* no miliseconds in DateTime::Tiny, so just multiply by 1000 */
870 0           epoch_ms = (int64_t)epoch_secs*1000;
871 0           bson_append_date_time(bson, key, -1, epoch_ms);
872             }
873 1749 50         else if (strEQ(obj_type, "Mango::BSON::Time")) {
874 0 0         SV *ms = _hv_fetchs_sv((HV *)SvRV(sv), "time");
    0          
875 0 0         bson_append_date_time(bson, key, -1, (int64_t)SvIV(ms));
876             }
877             /* DBRef */
878 1769 100         else if (strEQ(obj_type, "BSON::DBRef") || strEQ(obj_type, "MongoDB::DBRef")) {
    50          
879             SV *dbref;
880             bson_t child;
881 20           dbref = sv_2mortal(call_perl_reader(sv, "_ordered"));
882 20           bson_append_document_begin(bson, key, -1, &child);
883 20           ixhash_elem_to_bson(&child, dbref, opts, stack, depth);
884 20           bson_append_document_end(bson, &child);
885             }
886              
887             /* boolean -- these are the most well-known boolean libraries
888             * on CPAN. Type::Serialiser::Boolean now aliases to
889             * JSON::PP::Boolean so it is listed at the end for compatibility
890             * with old versions of it. Old versions of Cpanel::JSON::XS
891             * similarly have their own type, but now use JSON::PP::Boolean.
892             */
893 1729 100         else if (
894 1722 100         strEQ(obj_type, "boolean") ||
895 1721 100         strEQ(obj_type, "BSON::Bool") ||
896 1720 100         strEQ(obj_type, "JSON::XS::Boolean") ||
897 1715 100         strEQ(obj_type, "JSON::PP::Boolean") ||
898 1714 100         strEQ(obj_type, "JSON::Tiny::_Bool") ||
899 1713 100         strEQ(obj_type, "Mojo::JSON::_Bool") ||
900 1712 100         strEQ(obj_type, "Cpanel::JSON::XS::Boolean") ||
901 1712           strEQ(obj_type, "Types::Serialiser::Boolean")
902             ) {
903 18 50         bson_append_bool(bson, key, -1, SvIV(SvRV(sv)));
904             }
905 1735 100         else if (strEQ(obj_type, "BSON::Code") || strEQ(obj_type, "MongoDB::Code")) {
    50          
906             SV *code, *scope;
907             char *code_str;
908             STRLEN code_len;
909              
910 24           code = sv_2mortal(call_perl_reader (sv, "code"));
911 24 100         code_str = SvPVutf8(code, code_len);
912              
913 24 50         if ( ! is_utf8_string((const U8*)code_str,code_len)) {
914 0 0         croak( "Invalid UTF-8 detected while encoding BSON from %s", SvPV_nolen(sv) );
915             }
916              
917 24           scope = sv_2mortal(call_perl_reader(sv, "scope"));
918              
919 38 100         if (SvOK(scope)) {
    50          
    50          
920 14           bson_t * child = bson_new();
921 14           hv_elem_to_bson(child, scope, opts, EMPTY_STACK, 0);
922 14           bson_append_code_with_scope(bson, key, -1, code_str, code_len, child);
923 14           bson_destroy(child);
924             } else {
925 10           bson_append_code(bson, key, -1, code_str);
926             }
927              
928             }
929 1687 100         else if (strEQ(obj_type, "BSON::Timestamp")) {
930             SV *sec, *inc;
931              
932 11           inc = sv_2mortal(call_perl_reader(sv, "increment"));
933 11           sec = sv_2mortal(call_perl_reader(sv, "seconds"));
934              
935 11 50         bson_append_timestamp(bson, key, -1, SvIV(sec), SvIV(inc));
    50          
936             }
937 1676 50         else if (strEQ(obj_type, "MongoDB::Timestamp")) {
938             SV *sec, *inc;
939              
940 0           inc = sv_2mortal(call_perl_reader(sv, "inc"));
941 0           sec = sv_2mortal(call_perl_reader(sv, "sec"));
942              
943 0 0         bson_append_timestamp(bson, key, -1, SvIV(sec), SvIV(inc));
    0          
944             }
945 1676 100         else if (strEQ(obj_type, "BSON::MinKey") || strEQ(obj_type, "MongoDB::MinKey")) {
    100          
946 6           bson_append_minkey(bson, key, -1);
947             }
948 1670 100         else if (strEQ(obj_type, "BSON::MaxKey") || strEQ(obj_type, "MongoDB::MaxKey")) {
    100          
949 6           bson_append_maxkey(bson, key, -1);
950             }
951 1664 50         else if (strEQ(obj_type, "MongoDB::BSON::_EncodedDoc")) {
952             STRLEN str_len;
953             SV **svp;
954             SV *encoded;
955             const char *bson_str;
956             bson_t *child;
957              
958 0 0         encoded = _hv_fetchs_sv((HV *)SvRV(sv), "bson");
    0          
959 0 0         bson_str = SvPV(encoded, str_len);
960 0           child = bson_new_from_data((uint8_t*) bson_str, str_len);
961 0           bson_append_document(bson, key, -1, child);
962 0           bson_destroy(child);
963             }
964 1664 100         else if (strEQ(obj_type, "BSON::String")) {
965             SV *str_sv;
966             char *str;
967             STRLEN str_len;
968              
969 8           str_sv = sv_2mortal(call_perl_reader(sv,"value"));
970 8           append_utf8(bson, key, str_sv);
971             }
972 1656 100         else if (strEQ(obj_type, "MongoDB::BSON::String")) {
973             SV *str_sv;
974             char *str;
975             STRLEN str_len;
976              
977 2           str_sv = SvRV(sv);
978              
979             /* check type ok */
980 2 50         if (!SvPOK(str_sv)) {
981 0           croak("MongoDB::BSON::String must be a blessed string reference");
982             }
983              
984 2           append_utf8(bson, key, str_sv);
985             }
986 3558 100         else if (strEQ(obj_type, "BSON::Bytes") || strEQ(obj_type, "MongoDB::BSON::Binary")) {
    50          
987             SV *data, *subtype;
988              
989 25           subtype = sv_2mortal(call_perl_reader(sv, "subtype"));
990 25           data = sv_2mortal(call_perl_reader(sv, "data"));
991              
992 25 50         append_binary(bson, key, SvIV(subtype), data);
993             }
994 1629 100         else if (strEQ(obj_type, "BSON::Binary")) {
995             SV *data, *packed, *subtype;
996             bson_subtype_t int_subtype;
997 1           char *pat = "C*";
998              
999 1           subtype = sv_2mortal(call_perl_reader(sv, "subtype"));
1000 1 50         int_subtype = SvOK(subtype) ? SvIV(subtype) : 0;
    0          
    0          
    50          
1001 1           data = sv_2mortal(call_perl_reader(sv, "data"));
1002 1           packed = sv_2mortal(newSVpvs(""));
1003              
1004             /* if data is an array ref, pack it; othewise, pack an empty binary */
1005 1 50         if ( SvOK(data) && ( SvTYPE(SvRV(data)) == SVt_PVAV) ) {
    0          
    0          
    50          
1006 1           AV *d_array = (AV*) SvRV(data);
1007 1           packlist(packed, pat, pat+2,
1008             av_fetch(d_array,0,0), av_fetch(d_array,av_len(d_array),0)
1009             );
1010             }
1011              
1012 1           append_binary(bson, key, int_subtype, packed);
1013             }
1014 1628 100         else if (strEQ(obj_type, "Regexp")) {
1015             #if PERL_REVISION==5 && PERL_VERSION>=12
1016 1           REGEXP * re = SvRX(sv);
1017             #else
1018             REGEXP * re = (REGEXP *) mg_find((SV*)SvRV(sv), PERL_MAGIC_qr)->mg_obj;
1019             #endif
1020              
1021 1           append_regex(bson, key, re, sv);
1022             }
1023 1652 100         else if (strEQ(obj_type, "BSON::Regex") || strEQ(obj_type, "MongoDB::BSON::Regexp") ) {
    50          
1024             /* Abstract regexp object */
1025             SV *pattern, *flags;
1026 25           pattern = sv_2mortal(call_perl_reader( sv, "pattern" ));
1027 25           flags = sv_2mortal(call_perl_reader( sv, "flags" ));
1028              
1029 25 50         append_decomposed_regex( bson, key, SvPV_nolen( pattern ), SvPV_nolen( flags ) );
    50          
1030             }
1031             /* 64-bit integers */
1032 1602 100         else if (strEQ(obj_type, "Math::BigInt")) {
1033 6           bson_append_int64(bson, key, -1, math_bigint_to_int64(sv,key));
1034             }
1035 1596 100         else if (strEQ(obj_type, "BSON::Int64") ) {
1036 16           SV *v = sv_2mortal(call_perl_reader(sv, "value"));
1037              
1038 16 100         if ( SvROK(v) ) {
1039             /* delegate to wrapped value type */
1040 2           return sv_to_bson_elem(bson,in_key,v,opts,stack,depth);
1041             }
1042              
1043 14 50         bson_append_int64(bson, key, -1, (int64_t)SvIV(sv));
1044             }
1045 1580 50         else if (strEQ(obj_type, "Math::Int64")) {
1046             uint64_t v_int;
1047 0           SV *v_sv = call_pv_va("Math::Int64::int64_to_native",1,sv);
1048 0 0         Copy(SvPVbyte_nolen(v_sv), &v_int, 1, uint64_t);
1049 0           bson_append_int64(bson, key, -1, v_int);
1050             }
1051 1580 100         else if (strEQ(obj_type, "BSON::Int32") ) {
1052 35 50         bson_append_int32(bson, key, -1, (int32_t)SvIV(sv));
1053             }
1054 1545 100         else if (strEQ(obj_type, "BSON::Double") ) {
1055 32 50         bson_append_double(bson, key, -1, (double)SvNV(sv));
1056             }
1057 1513 100         else if (strEQ(obj_type, "BSON::Decimal128") ) {
1058             bson_decimal128_t dec;
1059             SV *dec_sv;
1060             char *bid_bytes;
1061              
1062 1512           dec_sv = sv_2mortal(call_perl_reader( sv, "bytes" ));
1063 1512 50         bid_bytes = SvPV_nolen(dec_sv);
1064              
1065             /* normalize from little endian back to native byte order */
1066 1512           Copy(bid_bytes, &dec.low, 1, uint64_t);
1067 1512           Copy(bid_bytes + 8, &dec.high, 1, uint64_t);
1068 1512           dec.low = BSON_UINT64_FROM_LE(dec.low);
1069 1512           dec.high = BSON_UINT64_FROM_LE(dec.high);
1070              
1071 1512           bson_append_decimal128(bson, key, -1, &dec);
1072             }
1073             else {
1074 1 50         croak ("For key '%s', can't encode value of type '%s'", key, HvNAME(SvSTASH(SvRV(sv))));
    50          
    50          
    0          
    50          
    50          
1075             }
1076             } else {
1077 938           SV *deref = SvRV(sv);
1078 938           switch (SvTYPE (deref)) {
1079             case SVt_PVHV: {
1080             /* hash */
1081             bson_t child;
1082 920           bson_append_document_begin(bson, key, -1, &child);
1083             /* don't add a _id to inner objs */
1084 920           hv_elem_to_bson (&child, sv, opts, stack, depth);
1085 716           bson_append_document_end(bson, &child);
1086 716           break;
1087             }
1088             case SVt_PVAV: {
1089             /* array */
1090             bson_t child;
1091 16           bson_append_array_begin(bson, key, -1, &child);
1092 16           av_to_bson (&child, (AV *)SvRV (sv), opts, stack, depth);
1093 15           bson_append_array_end(bson, &child);
1094 15           break;
1095             }
1096             default: {
1097 2 50         if ( SvPOK(deref) ) {
1098             /* binary */
1099 2           append_binary(bson, key, BSON_SUBTYPE_BINARY, deref);
1100             }
1101             else {
1102 2637 0         croak ("For key '%s', can't encode value '%s'", key, SvPV_nolen(sv));
1103             }
1104             }
1105             }
1106             }
1107             } else {
1108             /* Value is a defined, non-reference scalar */
1109             SV *tempsv;
1110             bool prefer_numeric;
1111              
1112 260 100         tempsv = _hv_fetchs_sv(opts, "prefer_numeric");
    50          
1113 260 100         prefer_numeric = SvTRUE(tempsv);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1114              
1115             #if PERL_REVISION==5 && PERL_VERSION<=18
1116             /* Before 5.18, get magic would clear public flags. This restores them
1117             * from private flags but ONLY if there is no public flag already, as
1118             * we have nothing else to go on for serialization.
1119             */
1120             if (!(SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK))) {
1121             SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
1122             }
1123             #endif
1124              
1125 260           I32 is_number = looks_like_number(sv);
1126              
1127 260 100         if ( SvNOK(sv) ) {
1128 13 50         bson_append_double(bson, key, -1, (double)SvNV(sv));
1129 247 100         } else if ( SvIOK(sv) ) {
1130 131           append_fit_int(bson, key, sv);
1131 116 100         } else if ( prefer_numeric && is_number ) {
    100          
1132             /* copy to avoid modifying flags of the original */
1133 3           tempsv = sv_2mortal(newSVsv(sv));
1134 6 100         if (is_number & IS_NUMBER_NOT_INT) { /* double */
1135 1 50         bson_append_double(bson, key, -1, (double)SvNV(tempsv));
1136             } else {
1137 2           append_fit_int(bson, key, tempsv);
1138             }
1139             } else {
1140 113           append_utf8(bson, key, sv);
1141             }
1142              
1143             }
1144             }
1145              
1146             const char *
1147 1962           maybe_append_first_key(bson_t *bson, HV *opts, stackette *stack, int depth) {
1148             SV *tempsv;
1149             SV **svp;
1150 1962           const char *first_key = NULL;
1151              
1152 1962 100         if ( (tempsv = _hv_fetchs_sv(opts, "first_key")) && SvOK (tempsv) ) {
    50          
    100          
    50          
    0          
    0          
1153             STRLEN len;
1154 2 50         first_key = SvPVutf8(tempsv, len);
1155 2           assert_valid_key(first_key, len);
1156 2 50         if ( (tempsv = _hv_fetchs_sv(opts, "first_value")) ) {
    50          
    50          
1157 2           sv_to_bson_elem(bson, first_key, tempsv, opts, stack, depth);
1158             }
1159             else {
1160 2           bson_append_null(bson, first_key, -1);
1161             }
1162             }
1163              
1164 1962           return first_key;
1165             }
1166              
1167             static void
1168 25           append_decomposed_regex(bson_t *bson, const char *key, const char *pattern, const char *flags ) {
1169 25           size_t pattern_length = strlen( pattern );
1170             char *buf;
1171              
1172 25           Newx(buf, pattern_length + 1, char );
1173 25           Copy(pattern, buf, pattern_length, char );
1174 25           buf[ pattern_length ] = '\0';
1175 25           bson_append_regex(bson, key, -1, buf, flags);
1176 25           Safefree(buf);
1177 25           }
1178              
1179             static void
1180 1           append_regex(bson_t * bson, const char *key, REGEXP *re, SV * sv) {
1181 1           char flags[] = {0,0,0,0,0,0,0}; /* space for imxslu + \0 */
1182             char *buf;
1183             int i, j;
1184              
1185 1           get_regex_flags(flags, sv);
1186              
1187             /* sort flags -- how cool to write a sort algorithm by hand! Since we're
1188             * only sorting a tiny array, who cares if it's n-squared? */
1189 4 100         for ( i=0; flags[i]; i++ ) {
1190 6 100         for ( j=i+1; flags[j] ; j++ ) {
1191 3 100         if ( flags[i] > flags[j] ) {
1192 1           char t = flags[j];
1193 1           flags[j] = flags[i];
1194 1           flags[i] = t;
1195             }
1196             }
1197             }
1198              
1199 1           Newx(buf, (RX_PRELEN(re) + 1), char );
1200 1           Copy(RX_PRECOMP(re), buf, RX_PRELEN(re), char );
1201 1           buf[RX_PRELEN(re)] = '\0';
1202              
1203 1           bson_append_regex(bson, key, -1, buf, flags);
1204              
1205 1           Safefree(buf);
1206 1           }
1207              
1208             static void
1209 28           append_binary(bson_t * bson, const char * key, bson_subtype_t subtype, SV * sv) {
1210             STRLEN len;
1211 28 50         uint8_t * bytes = (uint8_t *) SvPVbyte(sv, len);
1212              
1213 28           bson_append_binary(bson, key, -1, subtype, bytes, len);
1214 28           }
1215              
1216             static void
1217 133           append_fit_int(bson_t * bson, const char *key, SV * sv) {
1218             #if defined(MONGO_USE_64_BIT_INT)
1219 133 100         IV i = SvIV(sv);
1220 133 50         if ( i >= INT32_MIN && i <= INT32_MAX) {
    50          
1221 133           bson_append_int32(bson, key, -1, (int32_t)i);
1222             }
1223             else {
1224 0           bson_append_int64(bson, key, -1, (int64_t)i);
1225             }
1226             #else
1227             bson_append_int32(bson, key, -1, (int32_t)SvIV(sv));
1228             #endif
1229 133           return;
1230             }
1231              
1232             static void
1233 123           append_utf8(bson_t * bson, const char *key, SV * sv) {
1234             STRLEN len;
1235 123 100         const char *str = SvPVutf8(sv, len);
1236              
1237 123 50         if ( ! is_utf8_string((const U8*)str,len)) {
1238 0           croak( "Invalid UTF-8 detected while encoding BSON" );
1239             }
1240              
1241 123           bson_append_utf8(bson, key, -1, str, len);
1242 123           return;
1243             }
1244              
1245             static void
1246 2996           assert_valid_key(const char* str, STRLEN len) {
1247 2996 100         if(strlen(str) < len) {
1248 1           SV *clean = call_pv_va("BSON::XS::_printable",1,sv_2mortal(newSVpvn(str,len)));
1249 1 50         croak("Key '%s' contains null character", SvPV_nolen(clean));
1250             }
1251 2995           }
1252              
1253             static void
1254 1           get_regex_flags(char * flags, SV *sv) {
1255 1           unsigned int i = 0, f = 0;
1256              
1257             #if PERL_REVISION == 5 && PERL_VERSION < 10
1258             /* pre-5.10 doesn't have the re API */
1259             STRLEN string_length;
1260             char *re_string = SvPV( sv, string_length );
1261              
1262             /* pre-5.14 regexes are stringified in the format: (?ix-sm:foo) where
1263             everything between ? and - are the current flags. The format changed
1264             around 5.14, but for everything after 5.10 we use the re API anyway. */
1265             for( i = 2; i < string_length && re_string[i] != '-'; i++ ) {
1266             if ( re_string[i] == 'i' ||
1267             re_string[i] == 'm' ||
1268             re_string[i] == 'x' ||
1269             re_string[i] == 'l' ||
1270             re_string[i] == 'u' ||
1271             re_string[i] == 's' ) {
1272             flags[f++] = re_string[i];
1273             } else if ( re_string[i] == ':' ) {
1274             break;
1275             }
1276             }
1277             #else
1278             /* 5.10 added an API to extract flags, so we use that */
1279             int ret_count;
1280             SV *flags_sv;
1281             SV *pat_sv;
1282             char *flags_tmp;
1283 1           dSP;
1284 1           ENTER;
1285 1           SAVETMPS;
1286 1 50         PUSHMARK (SP);
1287 1 50         XPUSHs (sv);
1288 1           PUTBACK;
1289              
1290 1           ret_count = call_pv( "re::regexp_pattern", G_ARRAY );
1291 1           SPAGAIN;
1292              
1293 1 50         if ( ret_count != 2 ) {
1294 0           croak( "error introspecting regex" );
1295             }
1296              
1297             /* regexp_pattern returns two items (in list context), the pattern and a list of flags */
1298 1           flags_sv = POPs;
1299 1           pat_sv = POPs; /* too bad we throw this away */
1300              
1301 1 50         flags_tmp = SvPVutf8_nolen(flags_sv);
1302 4 50         for ( i = 0; i < sizeof( flags_tmp ); i++ ) {
1303 4 100         if ( flags_tmp[i] == 0 ) break;
1304              
1305             /* MongoDB supports only flags /imxslu */
1306 3 100         if ( flags_tmp[i] == 'i' ||
    100          
1307 1 50         flags_tmp[i] == 'm' ||
1308 0 0         flags_tmp[i] == 'x' ||
1309 0 0         flags_tmp[i] == 'l' ||
1310 0 0         flags_tmp[i] == 'u' ||
1311 0           flags_tmp[i] == 's' ) {
1312 3           flags[f++] = flags_tmp[i];
1313             }
1314             else {
1315             /* do nothing; just ignore it */
1316             }
1317             }
1318              
1319 1           PUTBACK;
1320 1 50         FREETMPS;
1321 1           LEAVE;
1322             #endif
1323 1           }
1324              
1325             /* Converts Math::BigInt to int64_t; sv must be Math::BigInt */
1326 6           static int64_t math_bigint_to_int64(SV *sv, const char *key) {
1327             SV *tempsv;
1328             char *str;
1329             int64_t big;
1330 6           char *end = NULL;
1331              
1332 6           tempsv = sv_2mortal(call_perl_reader(sv, "bstr"));
1333 6 100         str = SvPV_nolen(tempsv);
1334 6           errno = 0;
1335 6           big = Strtoll(str, &end, 10);
1336              
1337             /* check for conversion problems */
1338 6 50         if ( end && (*end != '\0') ) {
    50          
1339 0 0         if ( errno == ERANGE && ( big == LLONG_MAX || big == LLONG_MIN ) ) {
    0          
    0          
1340 0           croak( "For key '%s', Math::BigInt '%s' can't fit into a 64-bit integer", key, str );
1341             }
1342             else {
1343 0           croak( "For key '%s', couldn't convert Math::BigInt '%s' to 64-bit integer", key, str );
1344             }
1345             }
1346              
1347 6           return big;
1348             }
1349              
1350 0           static SV* int64_to_math_bigint(int64_t value) {
1351             char buf[22];
1352             SV *class;
1353             SV *as_str;
1354             SV *bigint;
1355              
1356 0           sprintf(buf, "%" PRIi64, value);
1357 0           as_str = sv_2mortal(newSVpv(buf,strlen(buf)));
1358 0           class = sv_2mortal(newSVpvs("Math::BigInt"));
1359 0           bigint = call_method_va(class, "new", 1, as_str);
1360 0           return bigint;
1361             }
1362              
1363             /**
1364             * checks if a ptr has been parsed already and, if not, adds it to the stack. If
1365             * we do have a circular ref, this function returns 0.
1366             */
1367             static stackette*
1368 2937           check_circular_ref(void *ptr, stackette *stack) {
1369 2937           stackette *ette, *start = stack;
1370              
1371 47568 100         while (stack) {
1372 44635 100         if (ptr == stack->ptr) {
1373 4           return 0;
1374             }
1375 44631           stack = stack->prev;
1376             }
1377              
1378             /* push this onto the circular ref stack */
1379 2933           Newx(ette, 1, stackette);
1380 2933           SAVEFREEPV(ette);
1381 2933           ette->ptr = ptr;
1382             /* if stack has not been initialized, stack will be 0 so this will work out */
1383 2933           ette->prev = start;
1384              
1385 2933           return ette;
1386             }
1387              
1388             /**
1389             * Given an object SV, finds the first superclass in reverse mro order that
1390             * starts with "BSON::" and returns it as a mortal SV. Otherwise, returns
1391             * NULL if no such type is found.
1392             */
1393             static SV*
1394 1908           bson_parent_type(SV* sv) {
1395             SV** handle;
1396             AV* mro;
1397             int i;
1398              
1399 1908 50         if (! SvOBJECT(sv)) {
1400 0           return NULL;
1401             }
1402              
1403 1908           mro = mro_get_linear_isa(SvSTASH(sv));
1404              
1405 1908 50         if (av_len(mro) == -1) {
1406 0           return NULL;
1407             }
1408             /* iterate backwards */
1409 3818 100         for ( i=av_len(mro); i >= 0; i-- ) {
1410 3783           handle = av_fetch(mro, i, 0);
1411 3783 50         if (handle != NULL) {
1412 3783 50         char* klass = SvPV_nolen(*handle);
1413 3783 100         if (strnEQ(klass, "BSON::", 6)) {
1414 1873           return sv_2mortal(newSVpvn(klass,strlen(klass)));
1415             }
1416             }
1417             }
1418 35           return NULL;
1419             }
1420              
1421             /********************************************************************
1422             * BSON decoding
1423             ********************************************************************/
1424              
1425             static SV *
1426 1825           bson_doc_to_hashref(bson_iter_t * iter, HV *opts, int depth, bool top) {
1427             SV **svp;
1428             SV *wrap;
1429             SV *ordered;
1430             SV *ret;
1431 1825           HV *hv = newHV();
1432              
1433 1825           depth++;
1434 1825 100         if ( depth > MAX_DEPTH ) {
1435 1           croak("Exceeded max object depth of %d", MAX_DEPTH);
1436             }
1437              
1438             /* delegate if 'ordered' option is true */
1439 1824 100         if ( (ordered = _hv_fetchs_sv(opts, "ordered")) && SvTRUE(ordered) ) {
    50          
    100          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
1440 1472           return bson_doc_to_tiedhash(iter, opts, depth, top);
1441             }
1442              
1443 352           int is_dbref = 1;
1444 352           int key_num = 0;
1445              
1446 603 100         while (bson_iter_next(iter)) {
1447             const char *name;
1448             SV *value;
1449              
1450 359           name = bson_iter_key(iter);
1451              
1452 359 50         if ( ! is_utf8_string((const U8*)name,strlen(name))) {
1453 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1454             }
1455              
1456 359           key_num++;
1457             /* check if this is a DBref. We must see the keys
1458             $ref, $id, and optionally $db in that order, with no extra keys */
1459 359 100         if ( key_num == 1 && strcmp( name, "$ref" ) ) is_dbref = 0;
    100          
1460 359 100         if ( key_num == 2 && is_dbref == 1 && strcmp( name, "$id" ) ) is_dbref = 0;
    100          
    50          
1461              
1462             /* get value and store into hash */
1463 359           value = bson_elem_to_sv(iter, name, opts, depth);
1464 251 50         if (!hv_store (hv, name, 0-strlen(name), value, 0)) {
1465 0           croak ("failed storing value in hash");
1466             }
1467             }
1468              
1469 244           ret = newRV_noinc ((SV *)hv);
1470              
1471             /* XXX shouldn't need to limit to size 3 */
1472 244 100         if ( ! top && key_num >= 2 && is_dbref == 1
    100          
    50          
1473 3 50         && (wrap = _hv_fetchs_sv(opts, "wrap_dbrefs")) && SvTRUE(wrap)
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
1474             ) {
1475 2           SV *class = sv_2mortal(newSVpvs("BSON::DBRef"));
1476 2           SV *dbref = call_method_va(class, "new", 1, sv_2mortal(ret) );
1477 2           return dbref;
1478             }
1479              
1480 242           depth--;
1481 242           return ret;
1482             }
1483              
1484             static SV *
1485 1472           bson_doc_to_tiedhash(bson_iter_t * iter, HV *opts, int depth, bool top) {
1486             SV **svp;
1487             SV *wrap;
1488             SV *ret;
1489             SV *ixhash;
1490             SV *tie;
1491             SV *key;
1492 1472           HV *hv = newHV();
1493              
1494 1472           int is_dbref = 1;
1495 1472           int key_num = 0;
1496              
1497 1472           depth++;
1498 1472 50         if ( depth > MAX_DEPTH ) {
1499 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
1500             }
1501              
1502 1472           ixhash = new_object_from_pairs("Tie::IxHash",NULL);
1503              
1504 3008 100         while (bson_iter_next(iter)) {
1505             const char *name;
1506             SV *value;
1507              
1508 1536           name = bson_iter_key(iter);
1509              
1510 1536 50         if ( ! is_utf8_string((const U8*)name,strlen(name))) {
1511 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1512             }
1513              
1514 1536           key_num++;
1515             /* check if this is a DBref. We must see the keys
1516             $ref, $id, and optionally $db in that order, with no extra keys */
1517 1536 100         if ( key_num == 1 && strcmp( name, "$ref" ) ) is_dbref = 0;
    100          
1518 1536 100         if ( key_num == 2 && is_dbref == 1 && strcmp( name, "$id" ) ) is_dbref = 0;
    100          
    50          
1519              
1520             /* get key and value and store into hash */
1521 1536           key = sv_2mortal( newSVpvn(name, strlen(name)) );
1522 1536           SvUTF8_on(key);
1523 1536           value = bson_elem_to_sv(iter, name, opts, depth);
1524 1536           call_method_va(ixhash, "STORE", 2, key, value);
1525             }
1526              
1527             /* tie the ixhash to the return hash */
1528 1472           sv_magic((SV*) hv, ixhash, PERL_MAGIC_tied, NULL, 0);
1529 1472           ret = newRV_noinc((SV*) hv);
1530              
1531             /* XXX shouldn't need to limit to size 3 */
1532 1472 100         if ( !top && key_num >= 2 && is_dbref == 1
    100          
    100          
1533 10 50         && (wrap = _hv_fetchs_sv(opts, "wrap_dbrefs")) && SvTRUE(wrap)
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
1534             ) {
1535 10           SV *class = sv_2mortal(newSVpvs("BSON::DBRef"));
1536 10           SV *dbref = call_method_va(class, "new", 1, ret );
1537 10           return dbref;
1538             }
1539              
1540 1462           depth--;
1541 1462           return ret;
1542             }
1543              
1544             static SV *
1545 14           bson_array_to_arrayref(bson_iter_t * iter, HV *opts, int depth) {
1546 14           AV *ret = newAV ();
1547              
1548 14           depth++;
1549 14 50         if ( depth > MAX_DEPTH ) {
1550 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
1551             }
1552              
1553 36 100         while (bson_iter_next(iter)) {
1554             SV *sv;
1555 22           const char *name = bson_iter_key(iter);
1556              
1557             /* get value */
1558 22 50         if ((sv = bson_elem_to_sv(iter, name, opts, depth))) {
1559 22           av_push (ret, sv);
1560             }
1561             }
1562              
1563 14           depth--;
1564 14           return newRV_noinc ((SV *)ret);
1565             }
1566              
1567             static SV *
1568 1917           bson_elem_to_sv (const bson_iter_t * iter, const char *key, HV *opts, int depth) {
1569             SV **svp;
1570 1917           SV *value = 0;
1571              
1572 1917           switch(bson_iter_type(iter)) {
1573             case BSON_TYPE_OID: {
1574 21           value = bson_oid_to_sv(iter);
1575 21           break;
1576             }
1577             case BSON_TYPE_DOUBLE: {
1578             SV *tempsv;
1579 59           SV *d = newSVnv(bson_iter_double(iter));
1580              
1581             /* Check for Inf and NaN */
1582 59 50         if (Perl_isinf(SvNV(d)) || Perl_isnan(SvNV(d)) ) {
    100          
    50          
    100          
1583 24 50         SvPV_nolen(d); /* force to PVNV for compatibility */
1584             }
1585              
1586 59 100         if ( (tempsv = _hv_fetchs_sv(opts, "wrap_numbers")) && SvTRUE(tempsv) ) {
    50          
    100          
    50          
    50          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
1587 51           value = new_object_from_pairs("BSON::Double", "value", sv_2mortal(d), NULL);
1588             }
1589             else {
1590 8           value = d;
1591             }
1592 59           break;
1593             }
1594             case BSON_TYPE_SYMBOL:
1595             case BSON_TYPE_UTF8: {
1596             SV *wrap;
1597             SV *s;
1598             const char * str;
1599             uint32_t len;
1600              
1601 117 100         if (bson_iter_type(iter) == BSON_TYPE_SYMBOL) {
1602 12           str = bson_iter_symbol(iter, &len);
1603             } else {
1604 105           str = bson_iter_utf8(iter, &len);
1605             }
1606              
1607 117 100         if ( ! is_utf8_string((const U8*)str,len)) {
1608 3           croak( "Invalid UTF-8 detected while decoding BSON" );
1609             }
1610              
1611             /* this makes a copy of the buffer */
1612             /* len includes \0 */
1613 114           s = newSVpvn(str, len);
1614 114           SvUTF8_on(s);
1615              
1616 114 100         if ( (wrap = _hv_fetchs_sv(opts, "wrap_strings")) && SvTRUE(wrap) ) {
    50          
    100          
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
1617 6           value = new_object_from_pairs("BSON::String", "value", sv_2mortal(s), NULL);
1618             }
1619             else {
1620 108           value = s;
1621             }
1622              
1623 114           break;
1624             }
1625             case BSON_TYPE_DOCUMENT: {
1626             bson_iter_t child;
1627 248           bson_iter_recurse(iter, &child);
1628              
1629 248           value = bson_doc_to_hashref(&child, opts, depth, FALSE);
1630              
1631 148           break;
1632             }
1633             case BSON_TYPE_ARRAY: {
1634             bson_iter_t child;
1635 14           bson_iter_recurse(iter, &child);
1636              
1637 14           value = bson_array_to_arrayref(&child, opts, depth);
1638              
1639 14           break;
1640             }
1641             case BSON_TYPE_BINARY: {
1642             const char * buf;
1643             uint32_t len;
1644             bson_subtype_t type;
1645 29           bson_iter_binary(iter, &type, &len, (const uint8_t **)&buf);
1646              
1647 29 100         if ( BSON_UNLIKELY(type == BSON_SUBTYPE_BINARY_DEPRECATED) ) {
1648             /* for the deprecated subtype, bson_iter_binary gives
1649             * buffer pointer just past the inner length and adjusted len */
1650             int32_t sublen;
1651 5           Copy(buf-4, &sublen, 1, int32_t);
1652 5           sublen = BSON_UINT32_FROM_LE(sublen);
1653              
1654             /* adjusted len must match sublen */
1655 5 100         if ( sublen != len ) {
1656 5           croak("key '%s' (binary subtype 0x02) is invalid", key);
1657             }
1658             }
1659              
1660 26           value = new_object_from_pairs(
1661             "BSON::Bytes",
1662             "data", sv_2mortal(newSVpvn(buf, len)),
1663             "subtype", sv_2mortal(newSViv(type)),
1664             NULL
1665             );
1666              
1667 26           break;
1668             }
1669             case BSON_TYPE_BOOL: {
1670 18           value = bson_iter_bool(iter)
1671 12           ? newSVsv(get_sv("BSON::XS::_boolean_true", GV_ADD))
1672 30 100         : newSVsv(get_sv("BSON::XS::_boolean_false", GV_ADD));
1673 18           break;
1674             }
1675             case BSON_TYPE_UNDEFINED:
1676             case BSON_TYPE_NULL: {
1677 10           value = newSV(0);
1678 10           break;
1679             }
1680             case BSON_TYPE_INT32: {
1681             SV *tempsv;
1682 70           SV *i = newSViv(bson_iter_int32(iter));
1683 70 100         if ( (tempsv = _hv_fetchs_sv(opts, "wrap_numbers")) && SvTRUE(tempsv) ) {
    50          
    100          
    50          
    50          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
1684 38           value = new_object_from_pairs("BSON::Int32", "value", sv_2mortal(i), NULL);
1685             }
1686             else {
1687 32           value = i;
1688             }
1689 70           break;
1690             }
1691             case BSON_TYPE_INT64: {
1692             SV *tempsv;
1693             #if defined(MONGO_USE_64_BIT_INT)
1694 25           SV *i = newSViv(bson_iter_int64(iter));
1695 25 100         if ( (tempsv = _hv_fetchs_sv(opts, "wrap_numbers")) && SvTRUE(tempsv) ) {
    50          
    100          
    50          
    50          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
1696 21           value = new_object_from_pairs("BSON::Int64", "value", sv_2mortal(i), NULL);
1697             }
1698             else {
1699 4           value = i;
1700             }
1701             #else
1702             SV *bigint = int64_to_math_bigint(bson_iter_int64(iter));
1703             if ( (tempsv = _hv_fetchs_sv(opts, "wrap_numbers")) && SvTRUE(tempsv) ) {
1704             value = new_object_from_pairs("BSON::Int64", "value", sv_2mortal(bigint), NULL);
1705             }
1706             else {
1707             value = bigint;
1708             }
1709             #endif
1710 25           break;
1711             }
1712             case BSON_TYPE_DATE_TIME: {
1713 23           const int64_t msec = bson_iter_date_time(iter);
1714             SV *obj;
1715             SV *temp;
1716             SV *dt_type_sv;
1717              
1718              
1719             #if defined(MONGO_USE_64_BIT_INT)
1720 23           obj = new_object_from_pairs("BSON::Time", "value", sv_2mortal(newSViv(msec)), NULL);
1721             #else
1722             obj = new_object_from_pairs("BSON::Time", "value", sv_2mortal(int64_to_math_bigint(msec)), NULL);
1723             #endif
1724              
1725 25 100         if ( (dt_type_sv = _hv_fetchs_sv(opts, "dt_type")) && SvOK(dt_type_sv) ) {
    50          
    100          
    100          
    50          
    50          
1726 3 50         char *dt_type = SvPV_nolen(dt_type_sv);
1727 3 100         if ( strEQ(dt_type, "BSON::Time") ) {
1728             /* already BSON::Time */
1729 1           value = obj;
1730 2 100         } else if ( strEQ(dt_type, "Time::Moment") ) {
1731 1           value = call_perl_reader(sv_2mortal(obj),"as_time_moment");
1732 1 50         } else if ( strEQ(dt_type, "DateTime") ) {
1733 0           value = call_perl_reader(sv_2mortal(obj),"as_datetime");
1734 1 50         } else if ( strEQ(dt_type, "DateTime::Tiny") ) {
1735 0           value = call_perl_reader(sv_2mortal(obj),"as_datetime_tiny");
1736 1 50         } else if ( strEQ(dt_type, "Mango::BSON::Time") ) {
1737 0           value = call_perl_reader(sv_2mortal(obj),"as_mango_time");
1738             } else {
1739 1           croak( "unsupported dt_type \"%s\"", dt_type );
1740             }
1741             }
1742             else {
1743 20           value = obj;
1744             }
1745              
1746 22           break;
1747             }
1748             case BSON_TYPE_REGEX: {
1749             const char * regex_str;
1750             const char * options;
1751 24           regex_str = bson_iter_regex(iter, &options);
1752              
1753             /* always make a BSON::Regex object instead of a native Perl
1754             * regexp to prevent the risk of compilation failure as well as
1755             * security risks compiling unknown regular expressions. */
1756              
1757 24           value = new_object_from_pairs(
1758             "BSON::Regex",
1759             "pattern", sv_2mortal(newSVpv(regex_str,0)),
1760             "flags", sv_2mortal(newSVpv(options,0)),
1761             NULL
1762             );
1763 24           break;
1764             }
1765             case BSON_TYPE_CODE: {
1766             const char * code;
1767             uint32_t len;
1768             SV *code_sv;
1769              
1770 10           code = bson_iter_code(iter, &len);
1771              
1772 10 50         if ( ! is_utf8_string((const U8*)code,len)) {
1773 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1774             }
1775              
1776 10           code_sv = sv_2mortal(newSVpvn(code, len));
1777 10           SvUTF8_on(code_sv);
1778              
1779 10           value = new_object_from_pairs("BSON::Code", "code", code_sv, NULL);
1780              
1781 10           break;
1782             }
1783             case BSON_TYPE_CODEWSCOPE: {
1784             const char * code;
1785             const uint8_t * scope;
1786             uint32_t code_len, scope_len;
1787             SV * code_sv;
1788             SV * scope_sv;
1789             bson_t bson;
1790             bson_iter_t child;
1791              
1792 14           code = bson_iter_codewscope(iter, &code_len, &scope_len, &scope);
1793              
1794 14 50         if ( ! is_utf8_string((const U8*)code,code_len)) {
1795 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1796             }
1797              
1798 14           code_sv = sv_2mortal(newSVpvn(code, code_len));
1799 14           SvUTF8_on(code_sv);
1800              
1801 14 50         if ( ! ( bson_init_static(&bson, scope, scope_len) && bson_iter_init(&child, &bson) ) ) {
    50          
1802 0           croak("error iterating BSON type %d\n", bson_iter_type(iter));
1803             }
1804              
1805 14           scope_sv = sv_2mortal(bson_doc_to_hashref(&child, opts, depth, TRUE));
1806 14           value = new_object_from_pairs("BSON::Code", "code", code_sv, "scope", scope_sv, NULL);
1807              
1808 14           break;
1809             }
1810             case BSON_TYPE_TIMESTAMP: {
1811             SV *sec_sv, *inc_sv;
1812             uint32_t sec, inc;
1813              
1814 10           bson_iter_timestamp(iter, &sec, &inc);
1815              
1816 10           sec_sv = sv_2mortal(newSVuv(sec));
1817 10           inc_sv = sv_2mortal(newSVuv(inc));
1818              
1819 10           value = new_object_from_pairs("BSON::Timestamp", "seconds", sec_sv, "increment", inc_sv, NULL);
1820 10           break;
1821             }
1822             case BSON_TYPE_MINKEY: {
1823 6           HV *stash = gv_stashpv("BSON::MinKey", GV_ADD);
1824 6           value = sv_bless(newRV_noinc((SV*)newHV()), stash);
1825 6           break;
1826             }
1827             case BSON_TYPE_MAXKEY: {
1828 6           HV *stash = gv_stashpv("BSON::MaxKey", GV_ADD);
1829 6           value = sv_bless(newRV_noinc((SV*)newHV()), stash);
1830 6           break;
1831             }
1832             case BSON_TYPE_DECIMAL128: {
1833             bson_decimal128_t dec;
1834             char bid_bytes[16];
1835             SV *dec_sv;
1836              
1837 1206 50         if ( ! bson_iter_decimal128(iter, &dec) ) {
1838 0           croak("could not decode decimal128");
1839             }
1840              
1841             /* normalize to little endian regardless of native byte order */
1842 1206           dec.low = BSON_UINT64_TO_LE(dec.low);
1843 1206           dec.high = BSON_UINT64_TO_LE(dec.high);
1844 1206           Copy(&dec.low, bid_bytes, 1, uint64_t);
1845 1206           Copy(&dec.high, bid_bytes + 8, 1, uint64_t);
1846              
1847 1206           dec_sv = sv_2mortal(newSVpvn(bid_bytes, 16));
1848 1206           value = new_object_from_pairs("BSON::Decimal128", "bytes", dec_sv, NULL);
1849              
1850 1206           break;
1851             }
1852             case BSON_TYPE_DBPOINTER: {
1853             uint32_t len;
1854             const char *collection;
1855             const bson_oid_t *oid_ptr;
1856             SV *coll;
1857             SV *oid;
1858              
1859 7           bson_iter_dbpointer(iter, &len, &collection, &oid_ptr);
1860              
1861 7 100         if ( ! is_utf8_string((const U8*)collection,len)) {
1862 1           croak( "Invalid UTF-8 detected while decoding BSON" );
1863             }
1864              
1865 6           coll = newSVpvn(collection, len);
1866 6           SvUTF8_on(coll);
1867              
1868 6           oid = new_object_from_pairs(
1869 6           "BSON::OID", "oid", newSVpvn((const char *) oid_ptr->bytes, 12), NULL
1870             );
1871              
1872 6           value = new_object_from_pairs( "BSON::DBRef",
1873             "ref", sv_2mortal(coll), "id", sv_2mortal(oid), NULL
1874             );
1875              
1876 6           break;
1877             }
1878             default: {
1879             /* Should already have been caught during bson_validate() but in case not: */
1880 0           croak("unsupported BSON type \\x%02X for key '%s'. Are you using the latest version of BSON::XS?", bson_iter_type(iter), key );
1881             }
1882             }
1883 1809           return value;
1884             }
1885              
1886             static SV *
1887 21           bson_oid_to_sv (const bson_iter_t * iter) {
1888             HV *stash, *id_hv;
1889              
1890 21           const bson_oid_t * oid = bson_iter_oid(iter);
1891              
1892 21           id_hv = newHV();
1893 21           (void)hv_stores(id_hv, "oid", newSVpvn((const char *) oid->bytes, 12));
1894              
1895 21           stash = gv_stashpv("BSON::OID", 0);
1896 21           return sv_bless(newRV_noinc((SV *)id_hv), stash);
1897             }
1898              
1899             MODULE = BSON::XS PACKAGE = BSON::XS
1900              
1901             PROTOTYPES: DISABLE
1902              
1903             void
1904             _decode_bson(msg, options)
1905             SV *msg
1906             SV *options
1907              
1908             PREINIT:
1909             char * data;
1910             bson_t bson;
1911             bson_iter_t iter;
1912             size_t error_offset;
1913             STRLEN length;
1914             HV *opts;
1915             uint32_t invalid_type;
1916             const char *invalid_key;
1917              
1918             PPCODE:
1919 1631 50         data = SvPV(msg, length);
1920 1631           opts = NULL;
1921              
1922 1631 50         if ( options ) {
1923 1631 50         if ( SvROK(options) && SvTYPE(SvRV(options)) == SVt_PVHV ) {
    50          
1924 1631           opts = (HV *) SvRV(options);
1925             }
1926             else {
1927 0           croak("options must be a reference to a hash");
1928             }
1929             }
1930              
1931 1631 100         if ( ! bson_init_static(&bson, (uint8_t *) data, length) ) {
1932 15           croak("Error reading BSON document");
1933             }
1934              
1935 1616 100         if ( ! bson_validate(&bson, BSON_VALIDATE_NONE, &error_offset, &invalid_key, &invalid_type) ) {
1936 48           croak( "Invalid BSON input" );
1937             }
1938              
1939 1568 100         if ( invalid_type != 0 ) {
1940 5           croak("unsupported BSON type \\x%02X for key '%s'. Are you using the latest version of BSON::XS?", invalid_type, invalid_key );
1941             }
1942              
1943 1563 50         if ( ! bson_iter_init(&iter, &bson) ) {
1944 0           croak( "Error creating BSON iterator" );
1945             }
1946              
1947 1563 50         XPUSHs(sv_2mortal(bson_doc_to_hashref(&iter, opts, 0, TRUE)));
1948              
1949             void
1950             _encode_bson(doc, options)
1951             SV *doc
1952             SV *options
1953             PREINIT:
1954             bson_t * bson;
1955             HV *opts;
1956             PPCODE:
1957 1965           opts = NULL;
1958 1965           bson = bson_new();
1959 1965 50         if ( options ) {
1960 1965 50         if ( SvROK(options) && SvTYPE(SvRV(options)) == SVt_PVHV ) {
    50          
1961 1965           opts = (HV *) SvRV(options);
1962             }
1963             else {
1964 0           croak("options must be a reference to a hash");
1965             }
1966             }
1967 1965           perl_mongo_sv_to_bson(bson, doc, opts);
1968 1954 50         XPUSHs(sv_2mortal(newSVpvn((const char *)bson_get_data(bson), bson->len)));
1969 1954           bson_destroy(bson);
1970              
1971             SV *
1972             _generate_oid ()
1973             PREINIT:
1974             bson_oid_t boid;
1975             CODE:
1976 0           bson_oid_init(&boid, NULL);
1977 0           RETVAL = newSVpvn((const char *) boid.bytes, 12);
1978             OUTPUT:
1979             RETVAL