File Coverage

xs/XS.xs
Criterion Covered Total %
statement 678 809 83.8
branch 554 1046 52.9
condition n/a
subroutine n/a
pod n/a
total 1232 1855 66.4


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 3435           call_method_va (SV *self, const char *method, int num, ...) {
209 3435           dSP;
210             SV *ret;
211             I32 count;
212             va_list args;
213              
214 3435           ENTER;
215 3435           SAVETMPS;
216 3435 50         PUSHMARK (SP);
217 3435 50         XPUSHs (self);
218              
219 3435           va_start (args, num);
220 6518 100         for( ; num > 0; num-- ) {
221 3083 50         XPUSHs (va_arg( args, SV* ));
    50          
222             }
223 3435           va_end(args);
224              
225 3435           PUTBACK;
226 3435           count = call_method (method, G_SCALAR);
227              
228 3435           SPAGAIN;
229 3435 50         if (count != 1) {
230 0           croak ("method didn't return a value");
231             }
232 3435           ret = POPs;
233 3435           SvREFCNT_inc (ret);
234              
235 3435           PUTBACK;
236 3435 50         FREETMPS;
237 3435           LEAVE;
238              
239 3435           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 2906           new_object_from_pairs(const char *klass, ...) {
262             SV *ret;
263             va_list args;
264 2906           va_start (args, klass);
265 2906           ret = call_method_with_arglist(sv_2mortal(newSVpv(klass,0)), "new", args);
266 2906           va_end(args);
267 2906           return ret;
268             }
269              
270             static SV *
271 2906           call_method_with_arglist (SV *self, const char *method, va_list args) {
272 2906           dSP;
273 2906           SV *ret = NULL;
274             char *key;
275             I32 count;
276              
277 2906           ENTER;
278 2906           SAVETMPS;
279 2906 50         PUSHMARK (SP);
280 2906 50         XPUSHs (self);
281              
282 4416 50         while ((key = va_arg (args, char *))) {
    100          
283 1510 50         mXPUSHp (key, strlen (key));
284 1510 50         XPUSHs (va_arg (args, SV *));
    50          
285             }
286              
287 2906           PUTBACK;
288 2906           count = call_method (method, G_SCALAR);
289              
290 2906           SPAGAIN;
291 2906 50         if (count != 1) {
292 0           croak ("method didn't return a value");
293             }
294 2906           ret = POPs;
295 2906           SvREFCNT_inc (ret);
296              
297 2906           PUTBACK;
298 2906 50         FREETMPS;
299 2906           LEAVE;
300              
301 2906           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 1956           perl_mongo_sv_to_bson (bson_t * bson, SV *sv, HV *opts) {
417              
418 1956 50         if (!SvROK (sv)) {
419 0           croak ("not a reference");
420             }
421              
422 1956 100         if ( ! sv_isobject(sv) ) {
423 1936 50         switch ( SvTYPE(SvRV(sv)) ) {
424             case SVt_PVHV:
425 1936           hv_doc_to_bson (bson, sv, opts, EMPTY_STACK, 0);
426 1927           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 1945           }
497              
498             static void
499 2869           hv_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc) {
500             HE *he;
501             HV *hv;
502 2869           const char *first_key = NULL;
503              
504 2869           depth++;
505 2869 100         if ( depth > MAX_DEPTH ) {
506 2           croak("Exceeded max object depth of %d", MAX_DEPTH);
507             }
508 2867           hv = (HV*)SvRV(sv);
509 2867 100         if (!(stack = check_circular_ref(hv, stack))) {
510 3           croak("circular reference detected");
511             }
512              
513 2864 100         if ( ! subdoc ) {
514 1936           first_key = maybe_append_first_key(bson, opts, stack, depth);
515             }
516              
517 2864           (void)hv_iterinit (hv);
518 5562 100         while ((he = hv_iternext (hv))) {
519             SV **hval;
520             STRLEN len;
521 2906 100         const char *key = HePV (he, len);
    50          
522 2906 100         uint32_t utf8 = HeUTF8(he);
523 2906           assert_valid_key(key, len);
524              
525             /* if we've already added the first key, continue */
526 2905 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 2905 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 2905 100         if (!utf8) {
538 2171           key = (const char *) bytes_to_utf8((U8 *)key, &len);
539             }
540              
541 2905 50         if ( ! is_utf8_string((const U8*)key,len)) {
542 0           croak( "Invalid UTF-8 detected while encoding BSON" );
543             }
544              
545 2905           sv_to_bson_elem (bson, key, *hval, opts, stack, depth);
546 2698 100         if (!utf8) {
547 2698           Safefree(key);
548             }
549             }
550              
551             /* free the hv elem */
552 2656 100         if ( ! subdoc ) {
553 1927           Safefree(stack);
554             }
555 2656           depth--;
556 2656           }
557              
558             static void
559 25           ixhash_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc) {
560             int i;
561             SV **keys_sv, **values_sv;
562             AV *array, *keys, *values;
563 25           const char *first_key = NULL;
564              
565 25           depth++;
566 25 50         if ( depth > MAX_DEPTH ) {
567 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
568             }
569              
570             /*
571             * a Tie::IxHash is of the form:
572             * [ {hash}, [keys], [order], 0 ]
573             */
574 25           array = (AV*)SvRV(sv);
575              
576             /* check if we're in an infinite loop */
577 25 100         if (!(stack = check_circular_ref(array, stack))) {
578 1           croak("circular ref");
579             }
580              
581             /* keys in order, from position 1 */
582 24           keys_sv = av_fetch(array, 1, 0);
583 24           keys = (AV*)SvRV(*keys_sv);
584              
585             /* values in order, from position 2 */
586 24           values_sv = av_fetch(array, 2, 0);
587 24           values = (AV*)SvRV(*values_sv);
588              
589 24 100         if ( ! subdoc ) {
590 3           first_key = maybe_append_first_key(bson, opts, stack, depth);
591             }
592              
593 76 100         for (i=0; i<=av_len(keys); i++) {
594             SV **k, **v;
595             STRLEN len;
596             const char *str;
597              
598 53 50         if (!(k = av_fetch(keys, i, 0)) ||
    50          
599 53           !(v = av_fetch(values, i, 0))) {
600 0           croak ("failed to fetch associative array value");
601             }
602              
603 53 100         str = SvPVutf8(*k, len);
604 53           assert_valid_key(str,len);
605              
606 53 50         if (first_key && strcmp(str, first_key) == 0) {
    0          
607 0           continue;
608             }
609              
610 53           sv_to_bson_elem(bson, str, *v, opts, stack, depth);
611             }
612              
613             /* free the ixhash elem */
614 23 100         if ( ! subdoc ) {
615 2           Safefree(stack);
616             }
617 23           depth--;
618 23           }
619              
620             /* Construct a BSON document from an iterator code ref that returns key
621             * value pairs */
622              
623             static void
624 17           iter_src_to_bson(bson_t * bson, SV *sv, HV *opts, stackette *stack, int depth, bool subdoc) {
625             int i;
626             SV *iter;
627             SV * kv[2];
628 17           const char *first_key = NULL;
629              
630 17           depth++;
631 17 50         if ( depth > MAX_DEPTH ) {
632 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
633             }
634              
635             /* check if we're in an infinite loop */
636 17 50         if (!(stack = check_circular_ref(SvRV(sv), stack))) {
637 0 0         croak("circular ref: %s", SvPV_nolen(sv));
638             }
639              
640 17 100         if ( ! subdoc ) {
641 14           first_key = maybe_append_first_key(bson, opts, stack, depth);
642             }
643              
644 17           iter = sv_2mortal(call_perl_reader(sv, "_iterator"));
645 17 50         if ( !SvROK(iter) || SvTYPE(SvRV(iter)) != SVt_PVCV ) {
    50          
646 0 0         croak("invalid iterator from %s", SvPV_nolen(sv));
647             }
648              
649 40 100         while ( call_key_value_iter( iter, kv ) ) {
650 23           sv_2mortal(kv[0]);
651 23           sv_2mortal(kv[1]);
652             STRLEN len;
653             const char *str;
654              
655 23 100         str = SvPVutf8(kv[0], len);
656 23           assert_valid_key(str,len);
657              
658 23 100         if (first_key && strcmp(str, first_key) == 0) {
    100          
659 1           continue;
660             }
661              
662 22           sv_to_bson_elem(bson, str, kv[1], opts, stack, depth);
663             }
664              
665             /* free the stack elem for sv */
666 17 100         if ( ! subdoc ) {
667 14           Safefree(stack);
668             }
669 17           depth--;
670 17           }
671              
672             /* This is for an array reference contained *within* a document */
673             static void
674 17           av_to_bson (bson_t * bson, AV *av, HV *opts, stackette *stack, int depth) {
675             I32 i;
676              
677 17           depth++;
678 17 50         if ( depth > MAX_DEPTH ) {
679 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
680             }
681              
682 17 50         if (!(stack = check_circular_ref(av, stack))) {
683 0           croak("circular ref");
684             }
685              
686 144 100         for (i = 0; i <= av_len (av); i++) {
687             SV **sv;
688 128           SV *key = sv_2mortal(newSViv (i));
689 128 50         if (!(sv = av_fetch (av, i, 0)))
690 0 0         sv_to_bson_elem (bson, SvPV_nolen(key), newSV(0), opts, stack, depth);
691             else
692 128 50         sv_to_bson_elem (bson, SvPV_nolen(key), *sv, opts, stack, depth);
693             }
694              
695             /* free the av elem */
696 16           Safefree(stack);
697 16           depth--;
698 16           }
699              
700             /* verify and transform key, if necessary */
701             static const char *
702 3112           bson_key(const char * str, HV *opts) {
703             SV **svp;
704             SV *tempsv;
705             STRLEN len;
706              
707             /* first swap op_char if necessary */
708 3112 100         if (
709 3112 100         (tempsv = _hv_fetchs_sv(opts, "op_char"))
    50          
710 2 50         && SvOK(tempsv)
    0          
    0          
711 2 50         && SvPV_nolen(tempsv)[0] == str[0]
    100          
712             ) {
713 1           char *out = savepv(str);
714 1           SAVEFREEPV(out);
715 1           *out = '$';
716 1           str = out;
717             }
718              
719             /* then check for validity */
720 3112 50         if (
721 3112 50         (tempsv = _hv_fetchs_sv(opts, "invalid_chars"))
    50          
722 3112 50         && SvOK(tempsv)
    0          
    0          
723 3112 100         && (len = sv_len(tempsv))
724             ) {
725             STRLEN i;
726 2 50         const char *invalid = SvPV_nolen(tempsv);
727              
728 2 50         for (i=0; i
729 2 50         if (strchr(str, invalid[i])) {
730 2           croak("key '%s' has invalid character(s) '%s'", str, invalid);
731             }
732             }
733             }
734              
735 3110           return str;
736             }
737              
738             static void
739 3112           sv_to_bson_elem (bson_t * bson, const char * in_key, SV *sv, HV *opts, stackette *stack, int depth) {
740             SV **svp;
741 3112           const char * key = bson_key(in_key,opts);
742              
743 3110 100         if (!SvOK(sv)) {
    50          
    50          
744 1788 100         if (SvGMAGICAL(sv)) {
745 1779           mg_get(sv);
746             }
747             }
748              
749 3110 100         if (!SvOK(sv)) {
    50          
    50          
750 16           bson_append_null(bson, key, -1);
751 16           return;
752             }
753 3094 100         else if (SvROK (sv)) {
754 2837 100         if (sv_isobject (sv)) {
755 1899           const char* obj_type = sv_reftype(SvRV(sv), true);
756 1899           SV* parent = bson_parent_type(SvRV(sv));
757 1899 100         if ( parent != NULL ) {
758 1865 50         obj_type = (const char *) SvPV_nolen(parent);
759             }
760              
761             /* OIDs */
762 1899 100         if (strEQ(obj_type, "BSON::OID")) {
763 27           SV *attr = sv_2mortal(call_perl_reader(sv, "oid"));
764 27 50         char *bytes = SvPV_nolen(attr);
765             bson_oid_t oid;
766 27           bson_oid_init_from_data(&oid, (uint8_t*) bytes);
767              
768 27           bson_append_oid(bson, key, -1, &oid);
769              
770             }
771 1872 50         else if (strEQ(obj_type, "MongoDB::OID")) {
772 0           SV *attr = sv_2mortal(call_perl_reader(sv, "value"));
773 0 0         char *str = SvPV_nolen (attr);
774             bson_oid_t oid;
775 0           bson_oid_init_from_string(&oid, str);
776              
777 0           bson_append_oid(bson, key, -1, &oid);
778              
779             }
780             /* Tie::IxHash */
781 1872 100         else if (strEQ(obj_type, "Tie::IxHash")) {
782             bson_t child;
783              
784 3           bson_append_document_begin(bson, key, -1, &child);
785 3           ixhash_elem_to_bson(&child, sv, opts, stack, depth);
786 2           bson_append_document_end(bson, &child);
787             }
788 1869 100         else if (strEQ(obj_type, "BSON::Doc")) {
789             bson_t child;
790              
791 3           bson_append_document_begin(bson, key, -1, &child);
792 3           iter_elem_to_bson(&child, sv, opts, stack, depth);
793 3           bson_append_document_end(bson, &child);
794             }
795 1866 100         else if (strEQ(obj_type, "BSON::Array")) {
796             bson_t child;
797              
798 1           bson_append_array_begin(bson, key, -1, &child);
799 1           av_to_bson (&child, (AV *)SvRV (sv), opts, stack, depth);
800 1           bson_append_array_end(bson, &child);
801             }
802 1865 100         else if (strEQ(obj_type, "BSON::Raw")) {
803             STRLEN str_len;
804             SV *encoded;
805             const char *bson_str;
806             bson_t *child;
807              
808 102           encoded = sv_2mortal(call_perl_reader(sv, "bson"));
809 102 50         bson_str = SvPV(encoded, str_len);
810              
811 102           child = bson_new_from_data((uint8_t*) bson_str, str_len);
812 102           bson_append_document(bson, key, -1, child);
813 102           bson_destroy(child);
814             }
815 1763 100         else if (strEQ(obj_type, "MongoDB::BSON::Raw")) {
816             SV *str_sv;
817             char *str;
818             STRLEN str_len;
819             bson_t *child;
820              
821 2           str_sv = SvRV(sv);
822              
823             // check type ok
824 2 50         if (!SvPOK(str_sv)) {
825 0           croak("MongoDB::BSON::Raw must be a blessed string reference");
826             }
827              
828 2 50         str = SvPV(str_sv, str_len);
829              
830 2           child = bson_new_from_data((uint8_t*) str, str_len);
831 2           bson_append_document(bson, key, -1, child);
832 2           bson_destroy(child);
833             }
834 1761 100         else if (strEQ(obj_type, "BSON::Time")) {
835 18           SV *ms = sv_2mortal(call_perl_reader(sv, "value"));
836 18 50         if ( sv_isa(ms, "Math::BigInt") ) {
837 0           int64_t t = math_bigint_to_int64(ms,key);
838 0           bson_append_date_time(bson, key, -1, t);
839             }
840             else {
841 18 50         bson_append_date_time(bson, key, -1, (int64_t)SvIV(ms));
842             }
843             }
844             /* Time::Moment */
845 1743 50         else if (strEQ(obj_type, "Time::Moment")) {
846 0           SV *sec = sv_2mortal(call_perl_reader(sv, "epoch"));
847 0           SV *ms = sv_2mortal(call_perl_reader(sv, "millisecond"));
848 0 0         bson_append_date_time(bson, key, -1, (int64_t)SvIV(sec)*1000+SvIV(ms));
    0          
849             }
850             /* DateTime */
851 1743 50         else if (strEQ(obj_type, "DateTime")) {
852             SV *sec, *ms, *tz, *tz_name;
853             STRLEN len;
854             char *str;
855              
856             /* check for floating tz */
857 0           tz = sv_2mortal(call_perl_reader (sv, "time_zone"));
858 0           tz_name = sv_2mortal(call_perl_reader (tz, "name"));
859 0 0         str = SvPV(tz_name, len);
860 0 0         if (len == 8 && strncmp("floating", str, 8) == 0) {
    0          
861 0           warn("saving floating timezone as UTC");
862             }
863              
864 0           sec = sv_2mortal(call_perl_reader (sv, "epoch"));
865 0           ms = sv_2mortal(call_perl_reader(sv, "millisecond"));
866              
867 0 0         bson_append_date_time(bson, key, -1, (int64_t)SvIV(sec)*1000+SvIV(ms));
    0          
868             }
869             /* DateTime::TIny */
870 1743 50         else if (strEQ(obj_type, "DateTime::Tiny")) {
871             struct tm t;
872 0           time_t epoch_secs = time(NULL);
873             int64_t epoch_ms;
874              
875 0 0         t.tm_year = SvIV( sv_2mortal(call_perl_reader( sv, "year" )) ) - 1900;
876 0 0         t.tm_mon = SvIV( sv_2mortal(call_perl_reader( sv, "month" )) ) - 1;
877 0 0         t.tm_mday = SvIV( sv_2mortal(call_perl_reader( sv, "day" )) ) ;
878 0 0         t.tm_hour = SvIV( sv_2mortal(call_perl_reader( sv, "hour" )) ) ;
879 0 0         t.tm_min = SvIV( sv_2mortal(call_perl_reader( sv, "minute" )) ) ;
880 0 0         t.tm_sec = SvIV( sv_2mortal(call_perl_reader( sv, "second" )) ) ;
881 0           t.tm_isdst = -1; /* no dst/tz info in DateTime::Tiny */
882              
883 0           epoch_secs = timegm( &t );
884              
885             /* no miliseconds in DateTime::Tiny, so just multiply by 1000 */
886 0           epoch_ms = (int64_t)epoch_secs*1000;
887 0           bson_append_date_time(bson, key, -1, epoch_ms);
888             }
889 1743 50         else if (strEQ(obj_type, "Mango::BSON::Time")) {
890 0 0         SV *ms = _hv_fetchs_sv((HV *)SvRV(sv), "time");
    0          
891 0 0         bson_append_date_time(bson, key, -1, (int64_t)SvIV(ms));
892             }
893             /* DBRef */
894 1762 100         else if (strEQ(obj_type, "BSON::DBRef") || strEQ(obj_type, "MongoDB::DBRef")) {
    50          
895             SV *dbref;
896             bson_t child;
897 19           dbref = sv_2mortal(call_perl_reader(sv, "_ordered"));
898 19           bson_append_document_begin(bson, key, -1, &child);
899 19           ixhash_elem_to_bson(&child, dbref, opts, stack, depth);
900 19           bson_append_document_end(bson, &child);
901             }
902              
903             /* boolean -- these are the most well-known boolean libraries
904             * on CPAN. Type::Serialiser::Boolean now aliases to
905             * JSON::PP::Boolean so it is listed at the end for compatibility
906             * with old versions of it. Old versions of Cpanel::JSON::XS
907             * similarly have their own type, but now use JSON::PP::Boolean.
908             */
909 1724 100         else if (
910 1717 100         strEQ(obj_type, "boolean") ||
911 1716 100         strEQ(obj_type, "BSON::Bool") ||
912 1715 100         strEQ(obj_type, "JSON::XS::Boolean") ||
913 1710 100         strEQ(obj_type, "JSON::PP::Boolean") ||
914 1709 100         strEQ(obj_type, "JSON::Tiny::_Bool") ||
915 1708 100         strEQ(obj_type, "Mojo::JSON::_Bool") ||
916 1707 100         strEQ(obj_type, "Cpanel::JSON::XS::Boolean") ||
917 1707           strEQ(obj_type, "Types::Serialiser::Boolean")
918             ) {
919 18 50         bson_append_bool(bson, key, -1, SvIV(SvRV(sv)));
920             }
921 1728 100         else if (strEQ(obj_type, "BSON::Code") || strEQ(obj_type, "MongoDB::Code")) {
    50          
922             SV *code, *scope;
923             char *code_str;
924             STRLEN code_len;
925              
926 22           code = sv_2mortal(call_perl_reader (sv, "code"));
927 22 100         code_str = SvPVutf8(code, code_len);
928              
929 22 50         if ( ! is_utf8_string((const U8*)code_str,code_len)) {
930 0 0         croak( "Invalid UTF-8 detected while encoding BSON from %s", SvPV_nolen(sv) );
931             }
932              
933 22           scope = sv_2mortal(call_perl_reader(sv, "scope"));
934              
935 35 100         if (SvOK(scope)) {
    50          
    50          
936 13           bson_t * child = bson_new();
937 13           hv_elem_to_bson(child, scope, opts, EMPTY_STACK, 0);
938 13           bson_append_code_with_scope(bson, key, -1, code_str, code_len, child);
939 13           bson_destroy(child);
940             } else {
941 9           bson_append_code(bson, key, -1, code_str);
942             }
943              
944             }
945 1684 100         else if (strEQ(obj_type, "BSON::Timestamp")) {
946             SV *sec, *inc;
947              
948 10           inc = sv_2mortal(call_perl_reader(sv, "increment"));
949 10           sec = sv_2mortal(call_perl_reader(sv, "seconds"));
950              
951 10 50         bson_append_timestamp(bson, key, -1, SvIV(sec), SvIV(inc));
    50          
952             }
953 1674 50         else if (strEQ(obj_type, "MongoDB::Timestamp")) {
954             SV *sec, *inc;
955              
956 0           inc = sv_2mortal(call_perl_reader(sv, "inc"));
957 0           sec = sv_2mortal(call_perl_reader(sv, "sec"));
958              
959 0 0         bson_append_timestamp(bson, key, -1, SvIV(sec), SvIV(inc));
    0          
960             }
961 1674 100         else if (strEQ(obj_type, "BSON::MinKey") || strEQ(obj_type, "MongoDB::MinKey")) {
    100          
962 6           bson_append_minkey(bson, key, -1);
963             }
964 1668 100         else if (strEQ(obj_type, "BSON::MaxKey") || strEQ(obj_type, "MongoDB::MaxKey")) {
    100          
965 6           bson_append_maxkey(bson, key, -1);
966             }
967 1662 50         else if (strEQ(obj_type, "MongoDB::BSON::_EncodedDoc")) {
968             STRLEN str_len;
969             SV **svp;
970             SV *encoded;
971             const char *bson_str;
972             bson_t *child;
973              
974 0 0         encoded = _hv_fetchs_sv((HV *)SvRV(sv), "bson");
    0          
975 0 0         bson_str = SvPV(encoded, str_len);
976 0           child = bson_new_from_data((uint8_t*) bson_str, str_len);
977 0           bson_append_document(bson, key, -1, child);
978 0           bson_destroy(child);
979             }
980 1662 100         else if (strEQ(obj_type, "BSON::String")) {
981             SV *str_sv;
982             char *str;
983             STRLEN str_len;
984              
985 8           str_sv = sv_2mortal(call_perl_reader(sv,"value"));
986 8           append_utf8(bson, key, str_sv);
987             }
988 1654 100         else if (strEQ(obj_type, "MongoDB::BSON::String")) {
989             SV *str_sv;
990             char *str;
991             STRLEN str_len;
992              
993 2           str_sv = SvRV(sv);
994              
995             /* check type ok */
996 2 50         if (!SvPOK(str_sv)) {
997 0           croak("MongoDB::BSON::String must be a blessed string reference");
998             }
999              
1000 2           append_utf8(bson, key, str_sv);
1001             }
1002 3547 100         else if (strEQ(obj_type, "BSON::Bytes") || strEQ(obj_type, "MongoDB::BSON::Binary")) {
    50          
1003             SV *data, *subtype;
1004              
1005 24           subtype = sv_2mortal(call_perl_reader(sv, "subtype"));
1006 24           data = sv_2mortal(call_perl_reader(sv, "data"));
1007              
1008 24 50         append_binary(bson, key, SvIV(subtype), data);
1009             }
1010 1628 100         else if (strEQ(obj_type, "BSON::Binary")) {
1011             SV *data, *packed, *subtype;
1012             bson_subtype_t int_subtype;
1013 1           char *pat = "C*";
1014              
1015 1           subtype = sv_2mortal(call_perl_reader(sv, "subtype"));
1016 1 50         int_subtype = SvOK(subtype) ? SvIV(subtype) : 0;
    0          
    0          
    50          
1017 1           data = sv_2mortal(call_perl_reader(sv, "data"));
1018 1           packed = sv_2mortal(newSVpvs(""));
1019              
1020             /* if data is an array ref, pack it; othewise, pack an empty binary */
1021 1 50         if ( SvOK(data) && ( SvTYPE(SvRV(data)) == SVt_PVAV) ) {
    0          
    0          
    50          
1022 1           AV *d_array = (AV*) SvRV(data);
1023 1           packlist(packed, pat, pat+2,
1024             av_fetch(d_array,0,0), av_fetch(d_array,av_len(d_array),0)
1025             );
1026             }
1027              
1028 1           append_binary(bson, key, int_subtype, packed);
1029             }
1030 1627 100         else if (strEQ(obj_type, "Regexp")) {
1031             #if PERL_REVISION==5 && PERL_VERSION>=12
1032 1           REGEXP * re = SvRX(sv);
1033             #else
1034             REGEXP * re = (REGEXP *) mg_find((SV*)SvRV(sv), PERL_MAGIC_qr)->mg_obj;
1035             #endif
1036              
1037 1           append_regex(bson, key, re, sv);
1038             }
1039 1650 100         else if (strEQ(obj_type, "BSON::Regex") || strEQ(obj_type, "MongoDB::BSON::Regexp") ) {
    50          
1040             /* Abstract regexp object */
1041             SV *pattern, *flags;
1042 24           pattern = sv_2mortal(call_perl_reader( sv, "pattern" ));
1043 24           flags = sv_2mortal(call_perl_reader( sv, "flags" ));
1044              
1045 24 50         append_decomposed_regex( bson, key, SvPV_nolen( pattern ), SvPV_nolen( flags ) );
    50          
1046             }
1047             /* 64-bit integers */
1048 1602 100         else if (strEQ(obj_type, "Math::BigInt")) {
1049 6           bson_append_int64(bson, key, -1, math_bigint_to_int64(sv,key));
1050             }
1051 1596 100         else if (strEQ(obj_type, "BSON::Int64") ) {
1052 16           SV *v = sv_2mortal(call_perl_reader(sv, "value"));
1053              
1054 16 100         if ( SvROK(v) ) {
1055             /* delegate to wrapped value type */
1056 2           return sv_to_bson_elem(bson,in_key,v,opts,stack,depth);
1057             }
1058              
1059 14 50         bson_append_int64(bson, key, -1, (int64_t)SvIV(sv));
1060             }
1061 1580 50         else if (strEQ(obj_type, "Math::Int64")) {
1062             uint64_t v_int;
1063 0           SV *v_sv = call_pv_va("Math::Int64::int64_to_native",1,sv);
1064 0 0         Copy(SvPVbyte_nolen(v_sv), &v_int, 1, uint64_t);
1065 0           bson_append_int64(bson, key, -1, v_int);
1066             }
1067 1580 100         else if (strEQ(obj_type, "BSON::Int32") ) {
1068 35 50         bson_append_int32(bson, key, -1, (int32_t)SvIV(sv));
1069             }
1070 1545 100         else if (strEQ(obj_type, "BSON::Double") ) {
1071 32 50         bson_append_double(bson, key, -1, (double)SvNV(sv));
1072             }
1073 1513 100         else if (strEQ(obj_type, "BSON::Decimal128") ) {
1074             bson_decimal128_t dec;
1075             SV *dec_sv;
1076             char *bid_bytes;
1077              
1078 1512           dec_sv = sv_2mortal(call_perl_reader( sv, "bytes" ));
1079 1512 50         bid_bytes = SvPV_nolen(dec_sv);
1080              
1081             /* normalize from little endian back to native byte order */
1082 1512           Copy(bid_bytes, &dec.low, 1, uint64_t);
1083 1512           Copy(bid_bytes + 8, &dec.high, 1, uint64_t);
1084 1512           dec.low = BSON_UINT64_FROM_LE(dec.low);
1085 1512           dec.high = BSON_UINT64_FROM_LE(dec.high);
1086              
1087 1512           bson_append_decimal128(bson, key, -1, &dec);
1088             }
1089             else {
1090 1 50         croak ("For key '%s', can't encode value of type '%s'", key, HvNAME(SvSTASH(SvRV(sv))));
    50          
    50          
    0          
    50          
    50          
1091             }
1092             } else {
1093 938           SV *deref = SvRV(sv);
1094 938           switch (SvTYPE (deref)) {
1095             case SVt_PVHV: {
1096             /* hash */
1097             bson_t child;
1098 920           bson_append_document_begin(bson, key, -1, &child);
1099             /* don't add a _id to inner objs */
1100 920           hv_elem_to_bson (&child, sv, opts, stack, depth);
1101 716           bson_append_document_end(bson, &child);
1102 716           break;
1103             }
1104             case SVt_PVAV: {
1105             /* array */
1106             bson_t child;
1107 16           bson_append_array_begin(bson, key, -1, &child);
1108 16           av_to_bson (&child, (AV *)SvRV (sv), opts, stack, depth);
1109 15           bson_append_array_end(bson, &child);
1110 15           break;
1111             }
1112             default: {
1113 2 50         if ( SvPOK(deref) ) {
1114             /* binary */
1115 2           append_binary(bson, key, BSON_SUBTYPE_BINARY, deref);
1116             }
1117             else {
1118 2628 0         croak ("For key '%s', can't encode value '%s'", key, SvPV_nolen(sv));
1119             }
1120             }
1121             }
1122             }
1123             } else {
1124             /* Value is a defined, non-reference scalar */
1125             SV *tempsv;
1126             bool prefer_numeric;
1127              
1128 257 100         tempsv = _hv_fetchs_sv(opts, "prefer_numeric");
    50          
1129 257 100         prefer_numeric = SvTRUE(tempsv);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
1130              
1131             #if PERL_REVISION==5 && PERL_VERSION<=18
1132             /* Before 5.18, get magic would clear public flags. This restores them
1133             * from private flags but ONLY if there is no public flag already, as
1134             * we have nothing else to go on for serialization.
1135             */
1136             if (!(SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK))) {
1137             SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
1138             }
1139             #endif
1140              
1141 257           I32 is_number = looks_like_number(sv);
1142              
1143 257 100         if ( SvNOK(sv) ) {
1144 13 50         bson_append_double(bson, key, -1, (double)SvNV(sv));
1145 244 100         } else if ( SvIOK(sv) ) {
1146 130           append_fit_int(bson, key, sv);
1147 114 100         } else if ( prefer_numeric && is_number ) {
    100          
1148             /* copy to avoid modifying flags of the original */
1149 3           tempsv = sv_2mortal(newSVsv(sv));
1150 6 100         if (is_number & IS_NUMBER_NOT_INT) { /* double */
1151 1 50         bson_append_double(bson, key, -1, (double)SvNV(tempsv));
1152             } else {
1153 2           append_fit_int(bson, key, tempsv);
1154             }
1155             } else {
1156 111           append_utf8(bson, key, sv);
1157             }
1158              
1159             }
1160             }
1161              
1162             const char *
1163 1953           maybe_append_first_key(bson_t *bson, HV *opts, stackette *stack, int depth) {
1164             SV *tempsv;
1165             SV **svp;
1166 1953           const char *first_key = NULL;
1167              
1168 1953 100         if ( (tempsv = _hv_fetchs_sv(opts, "first_key")) && SvOK (tempsv) ) {
    50          
    100          
    50          
    0          
    0          
1169             STRLEN len;
1170 2 50         first_key = SvPVutf8(tempsv, len);
1171 2           assert_valid_key(first_key, len);
1172 2 50         if ( (tempsv = _hv_fetchs_sv(opts, "first_value")) ) {
    50          
    50          
1173 2           sv_to_bson_elem(bson, first_key, tempsv, opts, stack, depth);
1174             }
1175             else {
1176 2           bson_append_null(bson, first_key, -1);
1177             }
1178             }
1179              
1180 1953           return first_key;
1181             }
1182              
1183             static void
1184 24           append_decomposed_regex(bson_t *bson, const char *key, const char *pattern, const char *flags ) {
1185 24           size_t pattern_length = strlen( pattern );
1186             char *buf;
1187              
1188 24           Newx(buf, pattern_length + 1, char );
1189 24           Copy(pattern, buf, pattern_length, char );
1190 24           buf[ pattern_length ] = '\0';
1191 24           bson_append_regex(bson, key, -1, buf, flags);
1192 24           Safefree(buf);
1193 24           }
1194              
1195             static void
1196 1           append_regex(bson_t * bson, const char *key, REGEXP *re, SV * sv) {
1197 1           char flags[] = {0,0,0,0,0,0,0}; /* space for imxslu + \0 */
1198             char *buf;
1199             int i, j;
1200              
1201 1           get_regex_flags(flags, sv);
1202              
1203             /* sort flags -- how cool to write a sort algorithm by hand! Since we're
1204             * only sorting a tiny array, who cares if it's n-squared? */
1205 4 100         for ( i=0; flags[i]; i++ ) {
1206 6 100         for ( j=i+1; flags[j] ; j++ ) {
1207 3 100         if ( flags[i] > flags[j] ) {
1208 1           char t = flags[j];
1209 1           flags[j] = flags[i];
1210 1           flags[i] = t;
1211             }
1212             }
1213             }
1214              
1215 1           Newx(buf, (RX_PRELEN(re) + 1), char );
1216 1           Copy(RX_PRECOMP(re), buf, RX_PRELEN(re), char );
1217 1           buf[RX_PRELEN(re)] = '\0';
1218              
1219 1           bson_append_regex(bson, key, -1, buf, flags);
1220              
1221 1           Safefree(buf);
1222 1           }
1223              
1224             static void
1225 27           append_binary(bson_t * bson, const char * key, bson_subtype_t subtype, SV * sv) {
1226             STRLEN len;
1227 27 50         uint8_t * bytes = (uint8_t *) SvPVbyte(sv, len);
1228              
1229 27           bson_append_binary(bson, key, -1, subtype, bytes, len);
1230 27           }
1231              
1232             static void
1233 132           append_fit_int(bson_t * bson, const char *key, SV * sv) {
1234             #if defined(MONGO_USE_64_BIT_INT)
1235 132 100         IV i = SvIV(sv);
1236 132 50         if ( i >= INT32_MIN && i <= INT32_MAX) {
    50          
1237 132           bson_append_int32(bson, key, -1, (int32_t)i);
1238             }
1239             else {
1240 0           bson_append_int64(bson, key, -1, (int64_t)i);
1241             }
1242             #else
1243             bson_append_int32(bson, key, -1, (int32_t)SvIV(sv));
1244             #endif
1245 132           return;
1246             }
1247              
1248             static void
1249 121           append_utf8(bson_t * bson, const char *key, SV * sv) {
1250             STRLEN len;
1251 121 100         const char *str = SvPVutf8(sv, len);
1252              
1253 121 50         if ( ! is_utf8_string((const U8*)str,len)) {
1254 0           croak( "Invalid UTF-8 detected while encoding BSON" );
1255             }
1256              
1257 121           bson_append_utf8(bson, key, -1, str, len);
1258 121           return;
1259             }
1260              
1261             static void
1262 2984           assert_valid_key(const char* str, STRLEN len) {
1263 2984 100         if(strlen(str) < len) {
1264 1           SV *clean = call_pv_va("BSON::XS::_printable",1,sv_2mortal(newSVpvn(str,len)));
1265 1 50         croak("Key '%s' contains null character", SvPV_nolen(clean));
1266             }
1267 2983           }
1268              
1269             static void
1270 1           get_regex_flags(char * flags, SV *sv) {
1271 1           unsigned int i = 0, f = 0;
1272              
1273             #if PERL_REVISION == 5 && PERL_VERSION < 10
1274             /* pre-5.10 doesn't have the re API */
1275             STRLEN string_length;
1276             char *re_string = SvPV( sv, string_length );
1277              
1278             /* pre-5.14 regexes are stringified in the format: (?ix-sm:foo) where
1279             everything between ? and - are the current flags. The format changed
1280             around 5.14, but for everything after 5.10 we use the re API anyway. */
1281             for( i = 2; i < string_length && re_string[i] != '-'; i++ ) {
1282             if ( re_string[i] == 'i' ||
1283             re_string[i] == 'm' ||
1284             re_string[i] == 'x' ||
1285             re_string[i] == 'l' ||
1286             re_string[i] == 'u' ||
1287             re_string[i] == 's' ) {
1288             flags[f++] = re_string[i];
1289             } else if ( re_string[i] == ':' ) {
1290             break;
1291             }
1292             }
1293             #else
1294             /* 5.10 added an API to extract flags, so we use that */
1295             int ret_count;
1296             SV *flags_sv;
1297             SV *pat_sv;
1298             char *flags_tmp;
1299 1           dSP;
1300 1           ENTER;
1301 1           SAVETMPS;
1302 1 50         PUSHMARK (SP);
1303 1 50         XPUSHs (sv);
1304 1           PUTBACK;
1305              
1306 1           ret_count = call_pv( "re::regexp_pattern", G_ARRAY );
1307 1           SPAGAIN;
1308              
1309 1 50         if ( ret_count != 2 ) {
1310 0           croak( "error introspecting regex" );
1311             }
1312              
1313             /* regexp_pattern returns two items (in list context), the pattern and a list of flags */
1314 1           flags_sv = POPs;
1315 1           pat_sv = POPs; /* too bad we throw this away */
1316              
1317 1 50         flags_tmp = SvPVutf8_nolen(flags_sv);
1318 4 50         for ( i = 0; i < sizeof( flags_tmp ); i++ ) {
1319 4 100         if ( flags_tmp[i] == 0 ) break;
1320              
1321             /* MongoDB supports only flags /imxslu */
1322 3 100         if ( flags_tmp[i] == 'i' ||
    100          
1323 1 50         flags_tmp[i] == 'm' ||
1324 0 0         flags_tmp[i] == 'x' ||
1325 0 0         flags_tmp[i] == 'l' ||
1326 0 0         flags_tmp[i] == 'u' ||
1327 0           flags_tmp[i] == 's' ) {
1328 3           flags[f++] = flags_tmp[i];
1329             }
1330             else {
1331             /* do nothing; just ignore it */
1332             }
1333             }
1334              
1335 1           PUTBACK;
1336 1 50         FREETMPS;
1337 1           LEAVE;
1338             #endif
1339 1           }
1340              
1341             /* Converts Math::BigInt to int64_t; sv must be Math::BigInt */
1342 6           static int64_t math_bigint_to_int64(SV *sv, const char *key) {
1343             SV *tempsv;
1344             char *str;
1345             int64_t big;
1346 6           char *end = NULL;
1347              
1348 6           tempsv = sv_2mortal(call_perl_reader(sv, "bstr"));
1349 6 100         str = SvPV_nolen(tempsv);
1350 6           errno = 0;
1351 6           big = Strtoll(str, &end, 10);
1352              
1353             /* check for conversion problems */
1354 6 50         if ( end && (*end != '\0') ) {
    50          
1355 0 0         if ( errno == ERANGE && ( big == LLONG_MAX || big == LLONG_MIN ) ) {
    0          
    0          
1356 0           croak( "For key '%s', Math::BigInt '%s' can't fit into a 64-bit integer", key, str );
1357             }
1358             else {
1359 0           croak( "For key '%s', couldn't convert Math::BigInt '%s' to 64-bit integer", key, str );
1360             }
1361             }
1362              
1363 6           return big;
1364             }
1365              
1366 0           static SV* int64_to_math_bigint(int64_t value) {
1367             char buf[22];
1368             SV *class;
1369             SV *as_str;
1370             SV *bigint;
1371              
1372 0           sprintf(buf, "%" PRIi64, value);
1373 0           as_str = sv_2mortal(newSVpv(buf,strlen(buf)));
1374 0           class = sv_2mortal(newSVpvs("Math::BigInt"));
1375 0           bigint = call_method_va(class, "new", 1, as_str);
1376 0           return bigint;
1377             }
1378              
1379             /**
1380             * checks if a ptr has been parsed already and, if not, adds it to the stack. If
1381             * we do have a circular ref, this function returns 0.
1382             */
1383             static stackette*
1384 2926           check_circular_ref(void *ptr, stackette *stack) {
1385 2926           stackette *ette, *start = stack;
1386              
1387 47556 100         while (stack) {
1388 44634 100         if (ptr == stack->ptr) {
1389 4           return 0;
1390             }
1391 44630           stack = stack->prev;
1392             }
1393              
1394             /* push this onto the circular ref stack */
1395 2922           Newx(ette, 1, stackette);
1396 2922           ette->ptr = ptr;
1397             /* if stack has not been initialized, stack will be 0 so this will work out */
1398 2922           ette->prev = start;
1399              
1400 2922           return ette;
1401             }
1402              
1403             /**
1404             * Given an object SV, finds the first superclass in reverse mro order that
1405             * starts with "BSON::" and returns it as a mortal SV. Otherwise, returns
1406             * NULL if no such type is found.
1407             */
1408             static SV*
1409 1899           bson_parent_type(SV* sv) {
1410             SV** handle;
1411             AV* mro;
1412             int i;
1413              
1414 1899 50         if (! SvOBJECT(sv)) {
1415 0           return NULL;
1416             }
1417              
1418 1899           mro = mro_get_linear_isa(SvSTASH(sv));
1419              
1420 1899 50         if (av_len(mro) == -1) {
1421 0           return NULL;
1422             }
1423             /* iterate backwards */
1424 3800 100         for ( i=av_len(mro); i >= 0; i-- ) {
1425 3766           handle = av_fetch(mro, i, 0);
1426 3766 50         if (handle != NULL) {
1427 3766 50         char* klass = SvPV_nolen(*handle);
1428 3766 100         if (strnEQ(klass, "BSON::", 6)) {
1429 1865           return sv_2mortal(newSVpvn(klass,strlen(klass)));
1430             }
1431             }
1432             }
1433 34           return NULL;
1434             }
1435              
1436             /********************************************************************
1437             * BSON decoding
1438             ********************************************************************/
1439              
1440             static SV *
1441 1814           bson_doc_to_hashref(bson_iter_t * iter, HV *opts, int depth, bool top) {
1442             SV **svp;
1443             SV *wrap;
1444             SV *ordered;
1445             SV *ret;
1446 1814           HV *hv = newHV();
1447              
1448 1814           depth++;
1449 1814 100         if ( depth > MAX_DEPTH ) {
1450 1           croak("Exceeded max object depth of %d", MAX_DEPTH);
1451             }
1452              
1453             /* delegate if 'ordered' option is true */
1454 1813 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          
1455 1472           return bson_doc_to_tiedhash(iter, opts, depth, top);
1456             }
1457              
1458 341           int is_dbref = 1;
1459 341           int key_num = 0;
1460              
1461 580 100         while (bson_iter_next(iter)) {
1462             const char *name;
1463             SV *value;
1464              
1465 347           name = bson_iter_key(iter);
1466              
1467 347 50         if ( ! is_utf8_string((const U8*)name,strlen(name))) {
1468 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1469             }
1470              
1471 347           key_num++;
1472             /* check if this is a DBref. We must see the keys
1473             $ref, $id, and optionally $db in that order, with no extra keys */
1474 347 100         if ( key_num == 1 && strcmp( name, "$ref" ) ) is_dbref = 0;
    100          
1475 347 100         if ( key_num == 2 && is_dbref == 1 && strcmp( name, "$id" ) ) is_dbref = 0;
    100          
    50          
1476              
1477             /* get value and store into hash */
1478 347           value = bson_elem_to_sv(iter, name, opts, depth);
1479 239 50         if (!hv_store (hv, name, 0-strlen(name), value, 0)) {
1480 0           croak ("failed storing value in hash");
1481             }
1482             }
1483              
1484 233           ret = newRV_noinc ((SV *)hv);
1485              
1486             /* XXX shouldn't need to limit to size 3 */
1487 233 100         if ( ! top && key_num >= 2 && is_dbref == 1
    100          
    50          
1488 2 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          
1489             ) {
1490 1           SV *class = sv_2mortal(newSVpvs("BSON::DBRef"));
1491 1           SV *dbref = call_method_va(class, "new", 1, sv_2mortal(ret) );
1492 1           return dbref;
1493             }
1494              
1495 232           depth--;
1496 232           return ret;
1497             }
1498              
1499             static SV *
1500 1472           bson_doc_to_tiedhash(bson_iter_t * iter, HV *opts, int depth, bool top) {
1501             SV **svp;
1502             SV *wrap;
1503             SV *ret;
1504             SV *ixhash;
1505             SV *tie;
1506             SV *key;
1507 1472           HV *hv = newHV();
1508              
1509 1472           int is_dbref = 1;
1510 1472           int key_num = 0;
1511              
1512 1472           depth++;
1513 1472 50         if ( depth > MAX_DEPTH ) {
1514 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
1515             }
1516              
1517 1472           ixhash = new_object_from_pairs("Tie::IxHash",NULL);
1518              
1519 3008 100         while (bson_iter_next(iter)) {
1520             const char *name;
1521             SV *value;
1522              
1523 1536           name = bson_iter_key(iter);
1524              
1525 1536 50         if ( ! is_utf8_string((const U8*)name,strlen(name))) {
1526 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1527             }
1528              
1529 1536           key_num++;
1530             /* check if this is a DBref. We must see the keys
1531             $ref, $id, and optionally $db in that order, with no extra keys */
1532 1536 100         if ( key_num == 1 && strcmp( name, "$ref" ) ) is_dbref = 0;
    100          
1533 1536 100         if ( key_num == 2 && is_dbref == 1 && strcmp( name, "$id" ) ) is_dbref = 0;
    100          
    50          
1534              
1535             /* get key and value and store into hash */
1536 1536           key = sv_2mortal( newSVpvn(name, strlen(name)) );
1537 1536           SvUTF8_on(key);
1538 1536           value = bson_elem_to_sv(iter, name, opts, depth);
1539 1536           call_method_va(ixhash, "STORE", 2, key, value);
1540             }
1541              
1542             /* tie the ixhash to the return hash */
1543 1472           sv_magic((SV*) hv, ixhash, PERL_MAGIC_tied, NULL, 0);
1544 1472           ret = newRV_noinc((SV*) hv);
1545              
1546             /* XXX shouldn't need to limit to size 3 */
1547 1472 100         if ( !top && key_num >= 2 && is_dbref == 1
    100          
    100          
1548 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          
1549             ) {
1550 10           SV *class = sv_2mortal(newSVpvs("BSON::DBRef"));
1551 10           SV *dbref = call_method_va(class, "new", 1, ret );
1552 10           return dbref;
1553             }
1554              
1555 1462           depth--;
1556 1462           return ret;
1557             }
1558              
1559             static SV *
1560 14           bson_array_to_arrayref(bson_iter_t * iter, HV *opts, int depth) {
1561 14           AV *ret = newAV ();
1562              
1563 14           depth++;
1564 14 50         if ( depth > MAX_DEPTH ) {
1565 0           croak("Exceeded max object depth of %d", MAX_DEPTH);
1566             }
1567              
1568 36 100         while (bson_iter_next(iter)) {
1569             SV *sv;
1570 22           const char *name = bson_iter_key(iter);
1571              
1572             /* get value */
1573 22 50         if ((sv = bson_elem_to_sv(iter, name, opts, depth))) {
1574 22           av_push (ret, sv);
1575             }
1576             }
1577              
1578 14           depth--;
1579 14           return newRV_noinc ((SV *)ret);
1580             }
1581              
1582             static SV *
1583 1905           bson_elem_to_sv (const bson_iter_t * iter, const char *key, HV *opts, int depth) {
1584             SV **svp;
1585 1905           SV *value = 0;
1586              
1587 1905           switch(bson_iter_type(iter)) {
1588             case BSON_TYPE_OID: {
1589 20           value = bson_oid_to_sv(iter);
1590 20           break;
1591             }
1592             case BSON_TYPE_DOUBLE: {
1593             SV *tempsv;
1594 59           SV *d = newSVnv(bson_iter_double(iter));
1595              
1596             /* Check for Inf and NaN */
1597 59 50         if (Perl_isinf(SvNV(d)) || Perl_isnan(SvNV(d)) ) {
    100          
    50          
    100          
1598 24 50         SvPV_nolen(d); /* force to PVNV for compatibility */
1599             }
1600              
1601 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          
1602 51           value = new_object_from_pairs("BSON::Double", "value", sv_2mortal(d), NULL);
1603             }
1604             else {
1605 8           value = d;
1606             }
1607 59           break;
1608             }
1609             case BSON_TYPE_SYMBOL:
1610             case BSON_TYPE_UTF8: {
1611             SV *wrap;
1612             SV *s;
1613             const char * str;
1614             uint32_t len;
1615              
1616 115 100         if (bson_iter_type(iter) == BSON_TYPE_SYMBOL) {
1617 12           str = bson_iter_symbol(iter, &len);
1618             } else {
1619 103           str = bson_iter_utf8(iter, &len);
1620             }
1621              
1622 115 100         if ( ! is_utf8_string((const U8*)str,len)) {
1623 3           croak( "Invalid UTF-8 detected while decoding BSON" );
1624             }
1625              
1626             /* this makes a copy of the buffer */
1627             /* len includes \0 */
1628 112           s = newSVpvn(str, len);
1629 112           SvUTF8_on(s);
1630              
1631 112 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          
1632 6           value = new_object_from_pairs("BSON::String", "value", sv_2mortal(s), NULL);
1633             }
1634             else {
1635 106           value = s;
1636             }
1637              
1638 112           break;
1639             }
1640             case BSON_TYPE_DOCUMENT: {
1641             bson_iter_t child;
1642 247           bson_iter_recurse(iter, &child);
1643              
1644 247           value = bson_doc_to_hashref(&child, opts, depth, FALSE);
1645              
1646 147           break;
1647             }
1648             case BSON_TYPE_ARRAY: {
1649             bson_iter_t child;
1650 14           bson_iter_recurse(iter, &child);
1651              
1652 14           value = bson_array_to_arrayref(&child, opts, depth);
1653              
1654 14           break;
1655             }
1656             case BSON_TYPE_BINARY: {
1657             const char * buf;
1658             uint32_t len;
1659             bson_subtype_t type;
1660 28           bson_iter_binary(iter, &type, &len, (const uint8_t **)&buf);
1661              
1662 28 100         if ( BSON_UNLIKELY(type == BSON_SUBTYPE_BINARY_DEPRECATED) ) {
1663             /* for the deprecated subtype, bson_iter_binary gives
1664             * buffer pointer just past the inner length and adjusted len */
1665             int32_t sublen;
1666 5           Copy(buf-4, &sublen, 1, int32_t);
1667 5           sublen = BSON_UINT32_FROM_LE(sublen);
1668              
1669             /* adjusted len must match sublen */
1670 5 100         if ( sublen != len ) {
1671 5           croak("key '%s' (binary subtype 0x02) is invalid", key);
1672             }
1673             }
1674              
1675 25           value = new_object_from_pairs(
1676             "BSON::Bytes",
1677             "data", sv_2mortal(newSVpvn(buf, len)),
1678             "subtype", sv_2mortal(newSViv(type)),
1679             NULL
1680             );
1681              
1682 25           break;
1683             }
1684             case BSON_TYPE_BOOL: {
1685 18           value = bson_iter_bool(iter)
1686 12           ? newSVsv(get_sv("BSON::XS::_boolean_true", GV_ADD))
1687 30 100         : newSVsv(get_sv("BSON::XS::_boolean_false", GV_ADD));
1688 18           break;
1689             }
1690             case BSON_TYPE_UNDEFINED:
1691             case BSON_TYPE_NULL: {
1692 10           value = newSV(0);
1693 10           break;
1694             }
1695             case BSON_TYPE_INT32: {
1696             SV *tempsv;
1697 69           SV *i = newSViv(bson_iter_int32(iter));
1698 69 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          
1699 38           value = new_object_from_pairs("BSON::Int32", "value", sv_2mortal(i), NULL);
1700             }
1701             else {
1702 31           value = i;
1703             }
1704 69           break;
1705             }
1706             case BSON_TYPE_INT64: {
1707             SV *tempsv;
1708             #if defined(MONGO_USE_64_BIT_INT)
1709 25           SV *i = newSViv(bson_iter_int64(iter));
1710 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          
1711 21           value = new_object_from_pairs("BSON::Int64", "value", sv_2mortal(i), NULL);
1712             }
1713             else {
1714 4           value = i;
1715             }
1716             #else
1717             SV *bigint = int64_to_math_bigint(bson_iter_int64(iter));
1718             if ( (tempsv = _hv_fetchs_sv(opts, "wrap_numbers")) && SvTRUE(tempsv) ) {
1719             value = new_object_from_pairs("BSON::Int64", "value", sv_2mortal(bigint), NULL);
1720             }
1721             else {
1722             value = bigint;
1723             }
1724             #endif
1725 25           break;
1726             }
1727             case BSON_TYPE_DATE_TIME: {
1728 21           const int64_t msec = bson_iter_date_time(iter);
1729             SV *obj;
1730             SV *temp;
1731             SV *dt_type_sv;
1732              
1733              
1734             #if defined(MONGO_USE_64_BIT_INT)
1735 21           obj = new_object_from_pairs("BSON::Time", "value", sv_2mortal(newSViv(msec)), NULL);
1736             #else
1737             obj = new_object_from_pairs("BSON::Time", "value", sv_2mortal(int64_to_math_bigint(msec)), NULL);
1738             #endif
1739              
1740 22 100         if ( (dt_type_sv = _hv_fetchs_sv(opts, "dt_type")) && SvOK(dt_type_sv) ) {
    50          
    100          
    100          
    50          
    50          
1741 2 50         char *dt_type = SvPV_nolen(dt_type_sv);
1742 2 100         if ( strEQ(dt_type, "BSON::Time") ) {
1743             /* already BSON::Time */
1744 1           value = obj;
1745 1 50         } else if ( strEQ(dt_type, "Time::Moment") ) {
1746 0           value = call_perl_reader(sv_2mortal(obj),"as_time_moment");
1747 1 50         } else if ( strEQ(dt_type, "DateTime") ) {
1748 0           value = call_perl_reader(sv_2mortal(obj),"as_datetime");
1749 1 50         } else if ( strEQ(dt_type, "DateTime::Tiny") ) {
1750 0           value = call_perl_reader(sv_2mortal(obj),"as_datetime_tiny");
1751 1 50         } else if ( strEQ(dt_type, "Mango::BSON::Time") ) {
1752 0           value = call_perl_reader(sv_2mortal(obj),"as_mango_time");
1753             } else {
1754 1           croak( "unsupported dt_type \"%s\"", dt_type );
1755             }
1756             }
1757             else {
1758 19           value = obj;
1759             }
1760              
1761 20           break;
1762             }
1763             case BSON_TYPE_REGEX: {
1764             const char * regex_str;
1765             const char * options;
1766 23           regex_str = bson_iter_regex(iter, &options);
1767              
1768             /* always make a BSON::Regex object instead of a native Perl
1769             * regexp to prevent the risk of compilation failure as well as
1770             * security risks compiling unknown regular expressions. */
1771              
1772 23           value = new_object_from_pairs(
1773             "BSON::Regex",
1774             "pattern", sv_2mortal(newSVpv(regex_str,0)),
1775             "flags", sv_2mortal(newSVpv(options,0)),
1776             NULL
1777             );
1778 23           break;
1779             }
1780             case BSON_TYPE_CODE: {
1781             const char * code;
1782             uint32_t len;
1783             SV *code_sv;
1784              
1785 9           code = bson_iter_code(iter, &len);
1786              
1787 9 50         if ( ! is_utf8_string((const U8*)code,len)) {
1788 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1789             }
1790              
1791 9           code_sv = sv_2mortal(newSVpvn(code, len));
1792 9           SvUTF8_on(code_sv);
1793              
1794 9           value = new_object_from_pairs("BSON::Code", "code", code_sv, NULL);
1795              
1796 9           break;
1797             }
1798             case BSON_TYPE_CODEWSCOPE: {
1799             const char * code;
1800             const uint8_t * scope;
1801             uint32_t code_len, scope_len;
1802             SV * code_sv;
1803             SV * scope_sv;
1804             bson_t bson;
1805             bson_iter_t child;
1806              
1807 13           code = bson_iter_codewscope(iter, &code_len, &scope_len, &scope);
1808              
1809 13 50         if ( ! is_utf8_string((const U8*)code,code_len)) {
1810 0           croak( "Invalid UTF-8 detected while decoding BSON" );
1811             }
1812              
1813 13           code_sv = sv_2mortal(newSVpvn(code, code_len));
1814 13           SvUTF8_on(code_sv);
1815              
1816 13 50         if ( ! ( bson_init_static(&bson, scope, scope_len) && bson_iter_init(&child, &bson) ) ) {
    50          
1817 0           croak("error iterating BSON type %d\n", bson_iter_type(iter));
1818             }
1819              
1820 13           scope_sv = sv_2mortal(bson_doc_to_hashref(&child, opts, depth, TRUE));
1821 13           value = new_object_from_pairs("BSON::Code", "code", code_sv, "scope", scope_sv, NULL);
1822              
1823 13           break;
1824             }
1825             case BSON_TYPE_TIMESTAMP: {
1826             SV *sec_sv, *inc_sv;
1827             uint32_t sec, inc;
1828              
1829 9           bson_iter_timestamp(iter, &sec, &inc);
1830              
1831 9           sec_sv = sv_2mortal(newSVuv(sec));
1832 9           inc_sv = sv_2mortal(newSVuv(inc));
1833              
1834 9           value = new_object_from_pairs("BSON::Timestamp", "seconds", sec_sv, "increment", inc_sv, NULL);
1835 9           break;
1836             }
1837             case BSON_TYPE_MINKEY: {
1838 6           HV *stash = gv_stashpv("BSON::MinKey", GV_ADD);
1839 6           value = sv_bless(newRV_noinc((SV*)newHV()), stash);
1840 6           break;
1841             }
1842             case BSON_TYPE_MAXKEY: {
1843 6           HV *stash = gv_stashpv("BSON::MaxKey", GV_ADD);
1844 6           value = sv_bless(newRV_noinc((SV*)newHV()), stash);
1845 6           break;
1846             }
1847             case BSON_TYPE_DECIMAL128: {
1848             bson_decimal128_t dec;
1849             char bid_bytes[16];
1850             SV *dec_sv;
1851              
1852 1206 50         if ( ! bson_iter_decimal128(iter, &dec) ) {
1853 0           croak("could not decode decimal128");
1854             }
1855              
1856             /* normalize to little endian regardless of native byte order */
1857 1206           dec.low = BSON_UINT64_TO_LE(dec.low);
1858 1206           dec.high = BSON_UINT64_TO_LE(dec.high);
1859 1206           Copy(&dec.low, bid_bytes, 1, uint64_t);
1860 1206           Copy(&dec.high, bid_bytes + 8, 1, uint64_t);
1861              
1862 1206           dec_sv = sv_2mortal(newSVpvn(bid_bytes, 16));
1863 1206           value = new_object_from_pairs("BSON::Decimal128", "bytes", dec_sv, NULL);
1864              
1865 1206           break;
1866             }
1867             case BSON_TYPE_DBPOINTER: {
1868             uint32_t len;
1869             const char *collection;
1870             const bson_oid_t *oid_ptr;
1871             SV *coll;
1872             SV *oid;
1873              
1874 7           bson_iter_dbpointer(iter, &len, &collection, &oid_ptr);
1875              
1876 7 100         if ( ! is_utf8_string((const U8*)collection,len)) {
1877 1           croak( "Invalid UTF-8 detected while decoding BSON" );
1878             }
1879              
1880 6           coll = newSVpvn(collection, len);
1881 6           SvUTF8_on(coll);
1882              
1883 6           oid = new_object_from_pairs(
1884 6           "BSON::OID", "oid", newSVpvn((const char *) oid_ptr->bytes, 12), NULL
1885             );
1886              
1887 6           value = new_object_from_pairs( "BSON::DBRef",
1888             "ref", sv_2mortal(coll), "id", sv_2mortal(oid), NULL
1889             );
1890              
1891 6           break;
1892             }
1893             default: {
1894             /* Should already have been caught during bson_validate() but in case not: */
1895 0           croak("unsupported BSON type \\x%02X for key '%s'. Are you using the latest version of BSON::XS?", bson_iter_type(iter), key );
1896             }
1897             }
1898 1797           return value;
1899             }
1900              
1901             static SV *
1902 20           bson_oid_to_sv (const bson_iter_t * iter) {
1903             HV *stash, *id_hv;
1904              
1905 20           const bson_oid_t * oid = bson_iter_oid(iter);
1906              
1907 20           id_hv = newHV();
1908 20           (void)hv_stores(id_hv, "oid", newSVpvn((const char *) oid->bytes, 12));
1909              
1910 20           stash = gv_stashpv("BSON::OID", 0);
1911 20           return sv_bless(newRV_noinc((SV *)id_hv), stash);
1912             }
1913              
1914             MODULE = BSON::XS PACKAGE = BSON::XS
1915              
1916             PROTOTYPES: DISABLE
1917              
1918             void
1919             _decode_bson(msg, options)
1920             SV *msg
1921             SV *options
1922              
1923             PREINIT:
1924             char * data;
1925             bson_t bson;
1926             bson_iter_t iter;
1927             size_t error_offset;
1928             STRLEN length;
1929             HV *opts;
1930             uint32_t invalid_type;
1931             const char *invalid_key;
1932              
1933             PPCODE:
1934 1622 50         data = SvPV(msg, length);
1935 1622           opts = NULL;
1936              
1937 1622 50         if ( options ) {
1938 1622 50         if ( SvROK(options) && SvTYPE(SvRV(options)) == SVt_PVHV ) {
    50          
1939 1622           opts = (HV *) SvRV(options);
1940             }
1941             else {
1942 0           croak("options must be a reference to a hash");
1943             }
1944             }
1945              
1946 1622 100         if ( ! bson_init_static(&bson, (uint8_t *) data, length) ) {
1947 15           croak("Error reading BSON document");
1948             }
1949              
1950 1607 100         if ( ! bson_validate(&bson, BSON_VALIDATE_NONE, &error_offset, &invalid_key, &invalid_type) ) {
1951 48           croak( "Invalid BSON input" );
1952             }
1953              
1954 1559 100         if ( invalid_type != 0 ) {
1955 5           croak("unsupported BSON type \\x%02X for key '%s'. Are you using the latest version of BSON::XS?", invalid_type, invalid_key );
1956             }
1957              
1958 1554 50         if ( ! bson_iter_init(&iter, &bson) ) {
1959 0           croak( "Error creating BSON iterator" );
1960             }
1961              
1962 1554 50         XPUSHs(sv_2mortal(bson_doc_to_hashref(&iter, opts, 0, TRUE)));
1963              
1964             void
1965             _encode_bson(doc, options)
1966             SV *doc
1967             SV *options
1968             PREINIT:
1969             bson_t * bson;
1970             HV *opts;
1971             PPCODE:
1972 1956           opts = NULL;
1973 1956           bson = bson_new();
1974 1956 50         if ( options ) {
1975 1956 50         if ( SvROK(options) && SvTYPE(SvRV(options)) == SVt_PVHV ) {
    50          
1976 1956           opts = (HV *) SvRV(options);
1977             }
1978             else {
1979 0           croak("options must be a reference to a hash");
1980             }
1981             }
1982 1956           perl_mongo_sv_to_bson(bson, doc, opts);
1983 1945 50         XPUSHs(sv_2mortal(newSVpvn((const char *)bson_get_data(bson), bson->len)));
1984 1945           bson_destroy(bson);
1985              
1986             SV *
1987             _generate_oid ()
1988             PREINIT:
1989             bson_oid_t boid;
1990             CODE:
1991 0           bson_oid_init(&boid, NULL);
1992 0           RETVAL = newSVpvn((const char *) boid.bytes, 12);
1993             OUTPUT:
1994             RETVAL