@@ -362,20 +362,27 @@ _noop (void)
362
362
return; \
363
363
} else \
364
364
(void) 0
365
- #define HANDLE_OPTION (_selection_statement , _key , _type , _state ) \
366
- _selection_statement (len == strlen (_key) && strncmp ((const char *) val, (_key), len) == 0) \
367
- { \
368
- if (bson->bson_type && bson->bson_type != (_type)) { \
369
- _bson_json_read_set_error (reader, \
370
- "Invalid key \"%s\". Looking for values " \
371
- "for type \"%s\", got \"%s\"", \
372
- (_key), \
373
- _bson_json_type_name (bson->bson_type), \
374
- _bson_json_type_name (_type)); \
375
- return; \
376
- } \
377
- bson->bson_type = (_type); \
378
- bson->bson_state = (_state); \
365
+
366
+ #define HANDLE_OPTION_KEY_COMPARE (_key ) (len == strlen (_key) && memcmp (key, (_key), len) == 0)
367
+
368
+ #define HANDLE_OPTION_TYPE_CHECK (_key , _type ) \
369
+ if (bson->bson_type && bson->bson_type != (_type)) { \
370
+ _bson_json_read_set_error (reader, \
371
+ "Invalid key \"%s\". Looking for values " \
372
+ "for type \"%s\", got \"%s\"", \
373
+ (_key), \
374
+ _bson_json_type_name (bson->bson_type), \
375
+ _bson_json_type_name (_type)); \
376
+ return; \
377
+ } \
378
+ ((void) 0)
379
+
380
+ #define HANDLE_OPTION (_selection_statement , _key , _type , _state ) \
381
+ _selection_statement (HANDLE_OPTION_KEY_COMPARE (_key)) \
382
+ { \
383
+ HANDLE_OPTION_TYPE_CHECK (_key, _type); \
384
+ bson->bson_type = (_type); \
385
+ bson->bson_state = (_state); \
379
386
}
380
387
381
388
@@ -1159,23 +1166,40 @@ _bson_json_read_start_map (bson_json_reader_t *reader) /* IN */
1159
1166
}
1160
1167
1161
1168
1169
+ #define BSON_PRIVATE_SPECIAL_KEYS_XMACRO (X ) \
1170
+ X (binary) \
1171
+ X (code) \
1172
+ X (date) \
1173
+ X (dbPointer) \
1174
+ X (maxKey) \
1175
+ X (minKey) \
1176
+ X (numberDecimal) \
1177
+ X (numberDouble) \
1178
+ X (numberInt) \
1179
+ X (numberLong) \
1180
+ X (oid) \
1181
+ X (options) \
1182
+ X (regex) \
1183
+ X (regularExpression) \
1184
+ X (scope) \
1185
+ X (symbol) \
1186
+ X (timestamp) \
1187
+ X (type) \
1188
+ X (undefined) \
1189
+ X (uuid)
1190
+
1191
+
1162
1192
static bool
1163
1193
_is_known_key (const char * key , size_t len )
1164
1194
{
1165
- bool ret ;
1166
-
1167
- #define IS_KEY (k ) (len == strlen (k) && (0 == memcmp (k, key, len)))
1168
-
1169
- ret = (IS_KEY ("$regularExpression" ) || IS_KEY ("$regex" ) || IS_KEY ("$options" ) || IS_KEY ("$code" ) ||
1170
- IS_KEY ("$scope" ) || IS_KEY ("$oid" ) || IS_KEY ("$binary" ) || IS_KEY ("$type" ) || IS_KEY ("$date" ) ||
1171
- IS_KEY ("$undefined" ) || IS_KEY ("$maxKey" ) || IS_KEY ("$minKey" ) || IS_KEY ("$timestamp" ) ||
1172
- IS_KEY ("$numberInt" ) || IS_KEY ("$numberLong" ) || IS_KEY ("$numberDouble" ) || IS_KEY ("$numberDecimal" ) ||
1173
- IS_KEY ("$numberInt" ) || IS_KEY ("$numberLong" ) || IS_KEY ("$numberDouble" ) || IS_KEY ("$numberDecimal" ) ||
1174
- IS_KEY ("$dbPointer" ) || IS_KEY ("$symbol" ) || IS_KEY ("$uuid" ));
1175
-
1195
+ #define IS_KEY (k ) \
1196
+ if (len == strlen ("$" #k) && (0 == memcmp ("$" #k, key, len))) { \
1197
+ return true; \
1198
+ }
1199
+ BSON_PRIVATE_SPECIAL_KEYS_XMACRO (IS_KEY )
1176
1200
#undef IS_KEY
1177
1201
1178
- return ret ;
1202
+ return false ;
1179
1203
}
1180
1204
1181
1205
static void
@@ -1242,9 +1266,10 @@ _bson_json_read_map_key (bson_json_reader_t *reader, /* IN */
1242
1266
return ;
1243
1267
}
1244
1268
1269
+ const char * const key = (const char * ) val ;
1270
+
1245
1271
if (bson -> read_state == BSON_JSON_IN_START_MAP ) {
1246
- if (len > 0 && val [0 ] == '$' && _is_known_key ((const char * ) val , len ) &&
1247
- bson -> n >= 0 /* key is in subdocument */ ) {
1272
+ if (len > 0 && key [0 ] == '$' && _is_known_key (key , len ) && bson -> n >= 0 /* key is in subdocument */ ) {
1248
1273
bson -> read_state = BSON_JSON_IN_BSON_TYPE ;
1249
1274
bson -> bson_type = (bson_type_t ) 0 ;
1250
1275
memset (& bson -> bson_type_data , 0 , sizeof bson -> bson_type_data );
@@ -1281,30 +1306,42 @@ _bson_json_read_map_key (bson_json_reader_t *reader, /* IN */
1281
1306
HANDLE_OPTION (else if , "$numberDouble" , BSON_TYPE_DOUBLE , BSON_JSON_LF_DOUBLE )
1282
1307
HANDLE_OPTION (else if , "$symbol" , BSON_TYPE_SYMBOL , BSON_JSON_LF_SYMBOL )
1283
1308
HANDLE_OPTION (else if , "$numberDecimal" , BSON_TYPE_DECIMAL128 , BSON_JSON_LF_DECIMAL128 )
1284
- else if (! strcmp ("$timestamp" , ( const char * ) val ))
1309
+ else if (HANDLE_OPTION_KEY_COMPARE ("$timestamp" ))
1285
1310
{
1311
+ HANDLE_OPTION_TYPE_CHECK ("$timestamp" , BSON_TYPE_TIMESTAMP );
1286
1312
bson -> bson_type = BSON_TYPE_TIMESTAMP ;
1287
1313
bson -> read_state = BSON_JSON_IN_BSON_TYPE_TIMESTAMP_STARTMAP ;
1288
1314
}
1289
- else if (! strcmp ("$regularExpression" , ( const char * ) val ))
1315
+ else if (HANDLE_OPTION_KEY_COMPARE ("$regularExpression" ))
1290
1316
{
1317
+ HANDLE_OPTION_TYPE_CHECK ("$regularExpression" , BSON_TYPE_REGEX );
1291
1318
bson -> bson_type = BSON_TYPE_REGEX ;
1292
1319
bson -> read_state = BSON_JSON_IN_BSON_TYPE_REGEX_STARTMAP ;
1293
1320
}
1294
- else if (! strcmp ("$dbPointer" , ( const char * ) val ))
1321
+ else if (HANDLE_OPTION_KEY_COMPARE ("$dbPointer" ))
1295
1322
{
1323
+ HANDLE_OPTION_TYPE_CHECK ("$dbPointer" , BSON_TYPE_DBPOINTER );
1324
+
1296
1325
/* start parsing "key": {"$dbPointer": {...}}, save "key" for later */
1297
1326
_bson_json_buf_set (& bson -> dbpointer_key , bson -> key , bson -> key_buf .len );
1298
1327
1299
1328
bson -> bson_type = BSON_TYPE_DBPOINTER ;
1300
1329
bson -> read_state = BSON_JSON_IN_BSON_TYPE_DBPOINTER_STARTMAP ;
1301
1330
}
1302
- else if (! strcmp ("$code" , ( const char * ) val ))
1331
+ else if (HANDLE_OPTION_KEY_COMPARE ("$code" ))
1303
1332
{
1333
+ // "$code" may come after "$scope".
1334
+ if (bson -> bson_type != BSON_TYPE_CODEWSCOPE ) {
1335
+ HANDLE_OPTION_TYPE_CHECK ("$code" , BSON_TYPE_CODE );
1336
+ }
1304
1337
_bson_json_read_code_or_scope_key (bson , false /* is_scope */ , val , len );
1305
1338
}
1306
- else if (! strcmp ("$scope" , ( const char * ) val ))
1339
+ else if (HANDLE_OPTION_KEY_COMPARE ("$scope" ))
1307
1340
{
1341
+ // "$scope" may come after "$code".
1342
+ if (bson -> bson_type != BSON_TYPE_CODE ) {
1343
+ HANDLE_OPTION_TYPE_CHECK ("$scope" , BSON_TYPE_CODEWSCOPE );
1344
+ }
1308
1345
_bson_json_read_code_or_scope_key (bson , true /* is_scope */ , val , len );
1309
1346
}
1310
1347
else
0 commit comments