@@ -1506,6 +1506,72 @@ static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) {
1506
1506
return result ;
1507
1507
}
1508
1508
1509
+ /*
1510
+ * Hook for optional decoding BSON documents to DBRef.
1511
+ */
1512
+ static PyObject * _decode_as_dbref (PyObject * self , PyObject * value ) {
1513
+ struct module_state * state = GETSTATE (self );
1514
+ PyObject * dbref = NULL ;
1515
+ PyObject * dbref_type = NULL ;
1516
+ PyObject * ref = NULL ;
1517
+ PyObject * id = NULL ;
1518
+ PyObject * database = NULL ;
1519
+ PyObject * ret = NULL ;
1520
+ int db_present = 0 ;
1521
+
1522
+ /* Decoding for DBRefs */
1523
+ if (PyMapping_HasKeyString (value , "$ref" ) && PyMapping_HasKeyString (value , "$id" )) { /* DBRef */
1524
+ ref = PyMapping_GetItemString (value , "$ref" );
1525
+ /* PyMapping_GetItemString returns NULL to indicate error. */
1526
+ if (!ref ) {
1527
+ goto invalid ;
1528
+ }
1529
+ id = PyMapping_GetItemString (value , "$id" );
1530
+ /* PyMapping_GetItemString returns NULL to indicate error. */
1531
+ if (!id ) {
1532
+ goto invalid ;
1533
+ }
1534
+
1535
+ if (PyMapping_HasKeyString (value , "$db" )) {
1536
+ database = PyMapping_GetItemString (value , "$db" );
1537
+ if (!database ) {
1538
+ goto invalid ;
1539
+ }
1540
+ db_present = 1 ;
1541
+ } else {
1542
+ database = Py_None ;
1543
+ Py_INCREF (database );
1544
+ }
1545
+
1546
+ // check types
1547
+ if (!(PyUnicode_Check (ref ) && (database == Py_None || PyUnicode_Check (database )))) {
1548
+ ret = value ;
1549
+ goto invalid ;
1550
+ }
1551
+
1552
+ PyMapping_DelItemString (value , "$ref" );
1553
+ PyMapping_DelItemString (value , "$id" );
1554
+ if (db_present ) {
1555
+ PyMapping_DelItemString (value , "$db" );
1556
+ }
1557
+
1558
+ if ((dbref_type = _get_object (state -> DBRef , "bson.dbref" , "DBRef" ))) {
1559
+ dbref = PyObject_CallFunctionObjArgs (dbref_type , ref , id , database , value , NULL );
1560
+ Py_DECREF (value );
1561
+ value = dbref ;
1562
+ }
1563
+ } else {
1564
+ ret = value ;
1565
+ }
1566
+ invalid :
1567
+ Py_XDECREF (dbref );
1568
+ Py_XDECREF (dbref_type );
1569
+ Py_XDECREF (ref );
1570
+ Py_XDECREF (id );
1571
+ Py_XDECREF (database );
1572
+ return ret ;
1573
+ }
1574
+
1509
1575
static PyObject * get_value (PyObject * self , PyObject * name , const char * buffer ,
1510
1576
unsigned * position , unsigned char type ,
1511
1577
unsigned max , const codec_options_t * options ) {
@@ -1552,7 +1618,6 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
1552
1618
}
1553
1619
case 3 :
1554
1620
{
1555
- PyObject * collection ;
1556
1621
uint32_t size ;
1557
1622
1558
1623
if (max < 4 ) {
@@ -1585,55 +1650,10 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
1585
1650
goto invalid ;
1586
1651
}
1587
1652
1588
- /* Decoding for DBRefs */
1589
- if (PyMapping_HasKeyString (value , "$ref" )) { /* DBRef */
1590
- PyObject * dbref = NULL ;
1591
- PyObject * dbref_type ;
1592
- PyObject * id ;
1593
- PyObject * database ;
1594
-
1595
- collection = PyMapping_GetItemString (value , "$ref" );
1596
- /* PyMapping_GetItemString returns NULL to indicate error. */
1597
- if (!collection ) {
1598
- goto invalid ;
1599
- }
1600
- PyMapping_DelItemString (value , "$ref" );
1601
-
1602
- if (PyMapping_HasKeyString (value , "$id" )) {
1603
- id = PyMapping_GetItemString (value , "$id" );
1604
- if (!id ) {
1605
- Py_DECREF (collection );
1606
- goto invalid ;
1607
- }
1608
- PyMapping_DelItemString (value , "$id" );
1609
- } else {
1610
- id = Py_None ;
1611
- Py_INCREF (id );
1612
- }
1613
-
1614
- if (PyMapping_HasKeyString (value , "$db" )) {
1615
- database = PyMapping_GetItemString (value , "$db" );
1616
- if (!database ) {
1617
- Py_DECREF (collection );
1618
- Py_DECREF (id );
1619
- goto invalid ;
1620
- }
1621
- PyMapping_DelItemString (value , "$db" );
1622
- } else {
1623
- database = Py_None ;
1624
- Py_INCREF (database );
1625
- }
1626
-
1627
- if ((dbref_type = _get_object (state -> DBRef , "bson.dbref" , "DBRef" ))) {
1628
- dbref = PyObject_CallFunctionObjArgs (dbref_type , collection , id , database , value , NULL );
1629
- Py_DECREF (dbref_type );
1630
- }
1631
- Py_DECREF (value );
1632
- value = dbref ;
1633
-
1634
- Py_DECREF (id );
1635
- Py_DECREF (collection );
1636
- Py_DECREF (database );
1653
+ /* Hook for DBRefs */
1654
+ value = _decode_as_dbref (self , value );
1655
+ if (!value ) {
1656
+ goto invalid ;
1637
1657
}
1638
1658
1639
1659
* position += size ;
0 commit comments