Permalink
Browse files

CDRIVER-165 BCON Notation for insert key/value only when value meets …

…condition

Reference interpolation for basic interpolation
Pointer(=to=reference) interpolation for conditional interpolation.
  • Loading branch information...
1 parent dc70faf commit dfb15c7a2269333fcf9617bb5d615b819d7438fc @gjmurakami-10gen gjmurakami-10gen committed Aug 9, 2012
Showing with 451 additions and 172 deletions.
  1. +1 −1 runtests.sh
  2. +84 −29 src/bcon.c
  3. +196 −98 src/bcon.h
  4. +170 −44 test/bcon_test.c
View
2 runtests.sh
@@ -27,7 +27,7 @@ do
esac
done
-for i in `find . -name test_\*`
+for i in `find . -name test_\* | grep -v '\.dSYM'`
do
if [ $valgrind -eq 1 ]
then
View
113 src/bcon.c
@@ -46,7 +46,7 @@ bcon_token_t bcon_token(char *s) {
if (s == 0) return Token_EOD;
switch (s[0]) {
case ':': if (s[1] != '\0' && s[2] != '\0' && s[3] != '\0' && s[4] == '\0' &&
- s[3] == ':' && (s[1] == '_' || s[1] == 'P'))
+ s[3] == ':' && (s[1] == '_' || s[1] == 'P' || s[1] == 'R'))
return Token_Typespec; break;
case '{': if (s[1] == '\0') return Token_OpenBrace; break;
case '}': if (s[1] == '\0') return Token_CloseBrace; break;
@@ -66,8 +66,18 @@ bcon_error_t bson_bcon_key_value(bson *b, const char *key, const char *typespec,
case '_': /* kv(b, key, utype, bci) */
switch (utype) {
case '_': /* fall through */
- case 's': bson_append_string( b, key, bci.s ); break;
+ case 's': bson_append_string( b, key, bci.s ); break; /* common case */
case 'f': bson_append_double( b, key, bci.f ); break;
+ case 'D':
+ bson_append_start_object( b, key );
+ ret = bson_append_bcon( b, bci.D );
+ bson_append_finish_object( b );
+ break;
+ case 'A':
+ bson_append_start_array( b, key );
+ ret = bson_append_bcon_array( b, bci.A );
+ bson_append_finish_array( b );
+ break;
case 'o': if (*bci.o == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, bci.o ); bson_append_oid( b, key, &oid ); break;
case 'b': bson_append_bool( b, key, bci.b ); break;
case 't': bson_append_time_t( b, key, bci.t ); break;
@@ -78,30 +88,57 @@ bcon_error_t bson_bcon_key_value(bson *b, const char *key, const char *typespec,
default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break;
}
break;
- case 'P': /* kpv(b, key, utype, bci) */
+ case 'R': /* krv(b, key, utype, bci) */
switch (utype) {
- /*case '_': */ /* fall through */
- case 's': bson_append_string( b, key, *bci.Ps ); break;
- case 'f': bson_append_double( b, key, *bci.Pf ); break;
- case 'o': if (**bci.Po == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, *bci.Po ); bson_append_oid( b, key, &oid ); break;
- case 'b': bson_append_bool( b, key, *bci.Pb ); break;
- case 't': bson_append_time_t( b, key, *bci.Pt ); break;
- case 'x': bson_append_symbol( b, key, *bci.Px ); break;
- case 'i': bson_append_int( b, key, *bci.Pi ); break;
- case 'l': bson_append_long( b, key, *bci.Pl ); break;
+ case 'f': bson_append_double( b, key, *bci.Rf ); break;
+ case 's': bson_append_string( b, key, bci.Rs ); break;
case 'D':
- bson_append_start_object( b, key );
- ret = bson_append_bcon( b, bci.PD );
- bson_append_finish_object( b );
+ bson_append_start_object( b, key );
+ ret = bson_append_bcon( b, bci.RD );
+ bson_append_finish_object( b );
break;
case 'A':
- bson_append_start_array( b, key );
- ret = bson_append_bcon_array( b, bci.PA );
- bson_append_finish_array( b );
+ bson_append_start_array( b, key );
+ ret = bson_append_bcon_array( b, bci.RA );
+ bson_append_finish_array( b );
break;
+ case 'o': if (*bci.o == '\0') bson_oid_gen( &oid ); else bson_oid_from_string( &oid, bci.o ); bson_append_oid( b, key, &oid ); break;
+ case 'b': bson_append_bool( b, key, *bci.Rb ); break;
+ case 't': bson_append_time_t( b, key, *bci.Rt ); break;
+ case 'x': bson_append_symbol( b, key, bci.Rx ); break;
+ case 'i': bson_append_int( b, key, *bci.Ri ); break;
+ case 'l': bson_append_long( b, key, *bci.Rl ); break;
default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break;
}
break;
+ case 'P': /* kpv(b, key, utype, bci) */
+ if (*bci.Pv != 0) {
+ switch (utype) {
+ case 'f': bson_append_double( b, key, **bci.Pf ); break;
+ case 's': bson_append_string( b, key, *bci.Ps ); break;
+ case 'D':
+ bson_append_start_object( b, key );
+ ret = bson_append_bcon( b, *bci.PD );
+ bson_append_finish_object( b );
+ break;
+ case 'A':
+ bson_append_start_array( b, key );
+ ret = bson_append_bcon_array( b, *bci.PA );
+ bson_append_finish_array( b );
+ break;
+ case 'o': if (**bci.Po == '\0') bson_oid_gen( &oid );
+ else bson_oid_from_string( &oid, *bci.Po );
+ bson_append_oid( b, key, &oid );
+ break;
+ case 'b': bson_append_bool( b, key, **bci.Pb ); break;
+ case 't': bson_append_time_t( b, key, **bci.Pt ); break;
+ case 'x': if (*bci.Px != 0) bson_append_symbol( b, key, *bci.Px ); break;
+ case 'i': bson_append_int( b, key, **bci.Pi ); break;
+ case 'l': bson_append_long( b, key, **bci.Pl ); break;
+ default: printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED); break;
+ }
+ }
+ break;
default:
printf("\nptype:'%c' utype:'%c'\n", ptype, utype); assert(NOT_REACHED);
break;
@@ -269,8 +306,10 @@ void bcon_print(const bcon *bc) { /* prints internal representation, not JSON */
switch (typespec[1]) {
case '_':
switch (typespec[2]) {
- case 's': printf("%s\"%s\"", delim, bci.s); break;
case 'f': printf("%s%f", delim, bci.f); break;
+ case 's': printf("%s\"%s\"", delim, bci.s); break;
+ case 'D': printf("%sPD(0x%lx,..)", delim, (unsigned long)bci.D); break;
+ case 'A': printf("%sPA(0x%lx,....)", delim, (unsigned long)bci.A); break;
case 'o': printf("%s\"%s\"", delim, bci.o); break;
case 'b': printf("%s%d", delim, bci.b); break;
case 't': printf("%s%ld", delim, (long)bci.t); break;
@@ -281,18 +320,34 @@ void bcon_print(const bcon *bc) { /* prints internal representation, not JSON */
default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break;
}
break;
+ case 'R':
+ switch (typespec[2]) {
+ case 'f': printf("%sRf(0x%lx,%f)", delim, (unsigned long)bci.Rf, *bci.Rf); break;
+ case 's': printf("%sRs(0x%lx,\"%s\")", delim, (unsigned long)bci.Rs, bci.Rs); break;
+ case 'D': printf("%sRD(0x%lx,..)", delim, (unsigned long)bci.RD); break;
+ case 'A': printf("%sRA(0x%lx,....)", delim, (unsigned long)bci.RA); break;
+ case 'o': printf("%sRo(0x%lx,\"%s\")", delim, (unsigned long)bci.Ro, bci.Ro); break;
+ case 'b': printf("%sRb(0x%lx,%d)", delim, (unsigned long)bci.Rb, *bci.Rb); break;
+ case 't': printf("%sRt(0x%lx,%ld)", delim, (unsigned long)bci.Rt, (long)*bci.Rt); break;
+ case 'x': printf("%sRx(0x%lx,\"%s\")", delim, (unsigned long)bci.Rx, bci.Rx); break;
+ case 'i': printf("%sRi(0x%lx,%d)", delim, (unsigned long)bci.Ri, *bci.Ri); break;
+ case 'l': printf("%sRl(0x%lx,%ld)", delim, (unsigned long)bci.Rl, *bci.Rl); break;
+ default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break;
+ }
+ break;
case 'P':
switch (typespec[2]) {
- case 's': printf("%sPs(0x%lx,\"%s\")", delim, (unsigned long)bci.Ps, *bci.Ps); break;
- case 'f': printf("%sPf(0x%lx,%f)", delim, (unsigned long)bci.Pf, *bci.Pf); break;
- case 'o': printf("%sPo(0x%lx,\"%s\")", delim, (unsigned long)bci.Po, *bci.Po); break;
- case 'b': printf("%sPb(0x%lx,%d)", delim, (unsigned long)bci.Pb, *bci.Pb); break;
- case 't': printf("%sPt(0x%lx,%ld)", delim, (unsigned long)bci.Pt, (long)*bci.Pt); break;
- case 'x': printf("%sPx(0x%lx,\"%s\")", delim, (unsigned long)bci.Px, *bci.Px); break;
- case 'i': printf("%sPi(0x%lx,%d)", delim, (unsigned long)bci.Pi, *bci.Pi); break;
- case 'l': printf("%sPl(0x%lx,%ld)", delim, (unsigned long)bci.Pl, *bci.Pl); break;
- case 'D': printf("%sPD(0x%lx,..)", delim, (unsigned long)bci.PD); break;
- case 'A': printf("%sPA(0x%lx,....)", delim, (unsigned long)bci.PA); break;
+ case 'f': printf("%sPf(0x%lx,0x%lx,%f)", delim, (unsigned long)bci.Pf, (unsigned long)(bci.Pf ? *bci.Pf : 0), bci.Pf && *bci.Pf ? **bci.Pf : 0.0); break;
+ case 's': printf("%sPs(0x%lx,0x%lx,\"%s\")", delim, (unsigned long)bci.Ps, (unsigned long)(bci.Ps ? *bci.Ps : 0), bci.Ps && *bci.Ps ? *bci.Ps : ""); break;
+ case 'D': printf("%sPD(0x%lx,0x%lx,..)", delim, (unsigned long)bci.PD, (unsigned long)(bci.PD ? *bci.PD : 0)); break;
+ case 'A': printf("%sPA(0x%lx,0x%lx,....)", delim, (unsigned long)bci.PA, (unsigned long)(bci.PA ? *bci.PA : 0)); break;
+ case 'o': printf("%sPo(0x%lx,0x%lx,\"%s\")", delim, (unsigned long)bci.Po, (unsigned long)(bci.Po ? *bci.Po : 0), bci.Po && *bci.Po ? *bci.Po : ""); break;
+ case 'b': printf("%sPb(0x%lx,0x%lx,%d)", delim, (unsigned long)bci.Pb, (unsigned long)(bci.Pb ? *bci.Pb : 0), bci.Pb && *bci.Pb ? **bci.Pb : 0); break;
+ case 't': printf("%sPt(0x%lx,0x%lx,%ld)", delim, (unsigned long)bci.Pt, (unsigned long)(bci.Pt ? *bci.Pt : 0), bci.Pt && *bci.Pt ? (long)**bci.Pt : 0); break;
+ case 'x': printf("%sPx(0x%lx,0x%lx,\"%s\")", delim, (unsigned long)bci.Px, (unsigned long)(bci.Px ? *bci.Px : 0), bci.Px && *bci.Px ? *bci.Px : ""); break;
+ case 'i': printf("%sPi(0x%lx,0x%lx,%d)", delim, (unsigned long)bci.Pi, (unsigned long)(bci.Pi ? *bci.Pi : 0), bci.Pi && *bci.Pi ? **bci.Pi : 0); break;
+ case 'l': printf("%sPl(0x%lx,0x%lx,%ld)", delim, (unsigned long)bci.Pl, (unsigned long)(bci.Pl ? *bci.Pl : 0), bci.Pl && *bci.Pl ? **bci.Pl : 0); break;
+
default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break;
}
break;
View
294 src/bcon.h
@@ -32,8 +32,8 @@ MONGO_EXTERN_C_START
/**
* BCON - BSON C Object Notation.
*
- * Description
- * -----------
+ * Overview
+ * --------
* BCON provides for JSON-like (or BSON-like) initializers in C.
* Without this, BSON must be constructed by procedural coding via explicit function calls.
* With this, you now have convenient data-driven definition of BSON documents.
@@ -42,22 +42,28 @@ MONGO_EXTERN_C_START
* bcon hello[] = { "hello", "world", "." };
* bcon pi[] = { "pi", BF(3.14159), BEND };
*
- * BCON is an array of bcon union elements with the default type of cstring (char *).
- * A BCON document must be terminated with a cstring containing a single dot, i.e., ".", or the macro equivalent BEND.
+ * BCON is an array of bcon union elements with the default type of char* cstring.
+ * A BCON document must be terminated with a char* cstring containing a single dot, i.e., ".", or the macro equivalent BEND.
*
* Cstring literals in double quotes are used for keys as well as for string values.
* There is no explicit colon (':') separator between key and value, just a comma,
* however it must be explicit or C will quietly concatenate the key and value strings for you.
* Readability may be improved by using multiple lines with a key-value pair per line.
*
* Macros are used to enclose specific types, and an internal type-specifier string prefixes a typed value.
- * Macros are also used to specify interpolation of values from pointers to specified types.
+ * Macros are also used to specify interpolation of values from references (or pointers to references) of specified types.
*
* Sub-documents are framed by "{" "}" string literals, and sub-arrays are framed by "[" "]" literals.
*
* All of this is needed because C arrays and initializers are mono-typed unlike dict/array types in modern languages.
* BCON attempts to be readable and JSON-like within the context and restrictions of the C language.
*
+ * Specification
+ * -------------
+ * This specification parallels the BSON specification ( http://bsonspec.org/#/specification ).
+ * The specific types and their corresponding macros are documented in the bcon (union bcon) structure.
+ * The base values use two-character macros starting with "B" for the simple initialization using static values.
+ *
* Examples
* --------
*
@@ -110,68 +116,111 @@ MONGO_EXTERN_C_START
*
* Peformance
* ----------
- * BCON costs about three times as much as the equivalent bson function calls required to explicitly construct the document.
- * This is significantly less than the cost of parsing JSON and constructing BSON, and BCON allows value interpolation via pointers.
+ * With compiler optimization -O3, BCON costs about 1.1 to 1.2 times as much
+ * as the equivalent bson function calls required to explicitly construct the document.
+ * This is significantly less than the cost of parsing JSON and constructing BSON,
+ * and BCON allows value interpolation via pointers.
*
- * Specification
- * -------------
- * This specification parallels the BSON specification - http://bsonspec.org/#/specification
- *
- * document ::= elist
- * e_list ::= element e_list
- * element ::= e_name value
- * value ::= cstring String
- * | ":_f:" double Floating point
- * | ":Pf:" *double *Floating point interpolation
- * | ":_s" cstring String
- * | ":Ps" *cstring *String interpolation
- * | "{" document "}" Embedded document
- * | ":PD" *document *Embedded document interpolation
- * | "[" v_list "]" Array
- * | ":PA" *v_list *Array interpolation
- * | ":_b:" "\x00" Boolean "false"
- * | ":_b:" "\x01" Boolean "true"
- * | ":Pb:" *int *Boolean interpolation
- * | ":_t:" long UTC datetime
- * | ":Pt:" *long *UTC datetime interpolation
- * | ":_v:" "" Null value (empty string arg ignored)
- * | ":_x:" cstring Symbol
- * | ":Px:" *cstring *Symbol interpolation
- * | ":_i:" int 32-bit integer
- * | ":_i:" *int *32-bit integer
- * | ":_l:" long 64-bit integer
- * | ":_l:" *long *64-bit integer
- * vlist ::= value v_list
- * | ""
- * e_name ::= cstring
- * cstring ::= (byte*) "\x00"
- *
- * Notes
- * -----
+ * Reference Interpolation
+ * -----------------------
+ * Reference interpolation uses three-character macros starting with "BR" for simple dynamic values.
+ * You can change the referenced content and the new values will be interpolated when you generate BSON from BCON.
+ *
+ * bson b[1];
+ * char name[] = "pi";
+ * double value = 3.14159;
+ * bcon bc[] = { "name", BRS(name), "value", BRF(&value), BEND };
+ * bson_from_bcon( b, bc ); // generates { name: "pi", "value", 3.14159 }
+ * strcpy(name, "e");
+ * value = 2.71828;
+ * bson_from_bcon( b, bc ); // generates { name: "pi", "value", 3.14159 }
+ *
+ * Please remember that in C, the array type is anomalous in that an identifier is (already) a reference,
+ * therefore there is no ampersand '&' preceding the identifier for reference interpolation.
+ * This applies to BRS(cstring), BRD(doc), BRA(array), BRO(oid), and BRX(symbol).
+ * An ampersand '&' is needed for value types BRF(&double), BRB(&boolean), BRT(&time), BRI(&int), and BRL(&long).
+ * For completeness, BRS, BRD, BRA, BRO, and BRX are defined even though BS, BD, BA, BO, and BX are equivalent.
+ *
+ * Pointer Interpolation
+ * ---------------------
+ * Pointer(-to-reference) interpolation uses three-character macros starting with "BP" for _conditional_ dynamic values.
+ * You can change the pointer content and the new values will be interpolated when you generate BSON from BCON.
+ * If you set the pointer to null, the element will skipped and not inserted into the generated BSON document.
+ *
+ * bson b[1];
+ * char name[] = "pi";
+ * char new_name[] = "log(0)";
+ * char **pname = (char**)&name;
+ * double value = 3.14159;
+ * double *pvalue = &value;
+ * bcon bc[] = { "name", BPS(&pname), "value", BPF(&pvalue), BEND };
+ * bson_from_bcon( b, bc ); // generates { name: "pi", "value", 3.14159 }
+ * pname = (char**)&new_name;
+ * pvalue = 0;
+ * bson_from_bcon( b, bc ); // generates { name: "log(0)" }
+ *
+ * Pointer interpolation necessarily adds an extra level of indirection and complexity.
+ * All macro pointer arguments are preceded by '&'.
+ * Underlying pointer types are double-indirect (**) for array types and single-indirect (*) for value types.
+ * Char name[] is used above to highlight that the array reference is not assignable (in contrast to char *array).
+ * Please note the (char**)& cast-address sequence required to silence the "incompatible-pointer-types" warning.
+ *
+ * Additional Notes
+ * ----------------
* Use the BS macro or the ":_s:" type specifier for string to allow string values that collide with type specifiers, braces, or square brackets.
+ *
+ * bson b[1];
+ * bcon bc[] = { "spec", BS(":_s:"), BEND };
+ * bson_from_bcon( b, bc ); // generates { spec: ":_s:" }
+ *
+ * BCON does not yet support the following BSON types.
+ *
+ * 05 e_name binary Binary data
+ * 06 e_name undefined - deprecated
+ * 0B e_name cstring cstring Regular expression
+ * 0C e_name string (byte*12) DBPointer - Deprecated
+ * 0D e_name string JavaScript code
+ * 0F e_name code_w_s JavaScript code w/ scope
+ * 11 e_name int64 Timestamp
+ * FF e_name Min key
+ * 7F e_name Max key
+ *
*/
typedef union bcon {
- char *s; /**< 02 e_name string UTF-8 string */
- char **Ps; /**< 02 e_name string UTF-8 string interpolation */
- double f; /**< 01 e_name double Floating point */
- double *Pf; /**< 01 e_name double Floating point interpolation */
- union bcon *PD; /**< 03 e_name document Embedded document interpolation */
- union bcon *PA; /**< 04 e_name document Array interpolation */
- char *o; /**< 07 e_name (byte*12) ObjectId */
- char **Po; /**< 07 e_name (byte*12) ObjectId interpolation */
- bson_bool_t b; /**< 08 e_name 00 Boolean "false"
- 08 e_name 01 Boolean "true" */
- bson_bool_t *Pb; /**< 08 e_name 01 Boolean interpolation */
- time_t t; /**< 09 e_name int64 UTC datetime */
- time_t *Pt; /**< 09 e_name int64 UTC datetime interpolation */
- char *v; /**< 0A e_name Null value */
- char *x; /**< 0E e_name string Symbol */
- char **Px; /**< 0E e_name string Symbol interpolation */
- int i; /**< 10 e_name int32 32-bit Integer */
- int *Pi; /**< 10 e_name int32 32-bit Integer interpolation */
- long l; /**< 12 e_name int64 64-bit Integer */
- long *Pl; /**< 12 e_name int64 64-bit Integer interpolation */
+ char *s; /**< 02 e_name string Macro BS(v) - UTF-8 string */ /* must be first to be default */
+ char *Rs; /**< 02 e_name string Macro BRS(v) - UTF-8 string reference interpolation */
+ char **Ps; /**< 02 e_name string Macro BPS(v) - UTF-8 string pointer interpolation */
+ double f; /**< 01 e_name double Macro BF(v) - Floating point */
+ double *Rf; /**< 01 e_name double Macro BRF(v) - Floating point reference interpolation */
+ double **Pf; /**< 01 e_name double Macro BPF(v) - Floating point pointer interpolation */
+ union bcon *D; /**< 03 e_name document Macro BD(v) - Embedded document interpolation */
+ union bcon *RD; /**< 03 e_name document Macro BRD(v) - Embedded document reference interpolation */
+ union bcon **PD; /**< 03 e_name document Macro BPD(v) - Embedded document pointer interpolation */
+ union bcon *A; /**< 04 e_name document Macro BA(v) - Array interpolation */
+ union bcon *RA; /**< 04 e_name document Macro BRA(v) - Array reference interpolation */
+ union bcon **PA; /**< 04 e_name document Macro BPA(v) - Array pointer interpolation */
+ char *o; /**< 07 e_name (byte*12) Macro BO(v) - ObjectId */
+ char *Ro; /**< 07 e_name (byte*12) Macro BRO(v) - ObjectId reference interpolation */
+ char **Po; /**< 07 e_name (byte*12) Macro BPO(v) - ObjectId pointer interpolation */
+ bson_bool_t b; /**< 08 e_name 00 Macro BB(v) - Boolean "false"
+ 08 e_name 01 Macro BB(v) - Boolean "true" */
+ bson_bool_t *Rb; /**< 08 e_name 01 Macro BRB(v) - Boolean reference interpolation */
+ bson_bool_t **Pb;/**< 08 e_name 01 Macro BPB(v) - Boolean pointer interpolation */
+ time_t t; /**< 09 e_name int64 Macro BT(v) - UTC datetime */
+ time_t *Rt; /**< 09 e_name int64 Macro BRT(v) - UTC datetime reference interpolation */
+ time_t **Pt; /**< 09 e_name int64 Macro BPT(v) - UTC datetime pointer interpolation */
+ char *v; /**< 0A e_name Macro BNULL - Null value */
+ char *x; /**< 0E e_name string Macro BX(v) - Symbol */
+ char *Rx; /**< 0E e_name string Macro BRX(v) - Symbol reference interpolation */
+ char **Px; /**< 0E e_name string Macro BPX(v) - Symbol pointer interpolation */
+ int i; /**< 10 e_name int32 Macro BI(v) - 32-bit Integer */
+ int *Ri; /**< 10 e_name int32 Macro BRI(v) - 32-bit Integer reference interpolation */
+ int **Pi; /**< 10 e_name int32 Macro BPI(v) - 32-bit Integer pointer interpolation */
+ long l; /**< 12 e_name int64 Macro BL(v) - 64-bit Integer */
+ long *Rl; /**< 12 e_name int64 Macro BRL(v) - 64-bit Integer reference interpolation */
+ long **Pl; /**< 12 e_name int64 Macro BPL(v) - 64-bit Integer pointer interpolation */
+ void **Pv; /* generic pointer internal */
/* "{" "}" */ /* 03 e_name document Embedded document */
/* "[" "]" */ /* 04 e_name document Array */
/* 05 e_name binary Binary data */
@@ -188,86 +237,135 @@ typedef union bcon {
/** BCON document terminator */
#define BEND "."
-/** BCON internal 02 cstring string type-specifier */
-#define BTS ":_s:"
/** BCON internal 01 double Floating point type-specifier */
#define BTF ":_f:"
-/** BCON internal 07 cstring ObjectId type-specifier */
+/** BCON internal 02 char* string type-specifier */
+#define BTS ":_s:"
+/** BCON internal 03 union bcon* Embedded document interpolation type-specifier */
+#define BTD ":_D:"
+/** BCON internal 04 union bcon* Array interpolation type-specifier */
+#define BTA ":_A:"
+/** BCON internal 07 char* ObjectId type-specifier */
#define BTO ":_o:"
/** BCON internal 08 int Boolean type-specifier */
#define BTB ":_b:"
/** BCON internal 09 int64 UTC datetime type-specifier */
#define BTT ":_t:"
/** BCON internal 0A Null type-specifier */
#define BTN ":_v:"
-/** BCON internal 0E cstring Symbol type-specifier */
+/** BCON internal 0E char* Symbol type-specifier */
#define BTX ":_x:"
/** BCON internal 10 int32 64-bit Integer type-specifier */
#define BTI ":_i:"
/** BCON internal 12 int64 64-bit Integer type-specifier */
#define BTL ":_l:"
-/** BCON internal 02 cstring* string interpolation type-specifier */
-#define BTPS ":Ps:"
-/** BCON internal 01 double* Floating point interpolation type-specifier */
+/** BCON internal 01 double* Floating point reference interpolation type-specifier */
+#define BTRF ":Rf:"
+/** BCON internal 02 char* string reference interpolation type-specifier */
+#define BTRS ":Rs:"
+/** BCON internal 03 union bcon* Embedded document reference interpolation type-specifier */
+#define BTRD ":RD:"
+/** BCON internal 04 union bcon* Array reference interpolation type-specifier */
+#define BTRA ":RA:"
+/** BCON internal 07 char* ObjectId reference interpolation type-specifier */
+#define BTRO ":Ro:"
+/** BCON internal 08 int* Boolean reference interpolation type-specifier */
+#define BTRB ":Rb:"
+/** BCON internal 09 int64* UTC datetime reference interpolation type-specifier */
+#define BTRT ":Rt:"
+/** BCON internal 0E char* Symbol reference interpolation type-specifier */
+#define BTRX ":Rx:"
+/** BCON internal 10 int32* 23-bit Integer reference interpolation type-specifier */
+#define BTRI ":Ri:"
+/** BCON internal 12 int64* 64-bit Integer reference interpolation type-specifier */
+#define BTRL ":Rl:"
+
+/** BCON internal 01 double** Floating point pointer interpolation type-specifier */
#define BTPF ":Pf:"
-/** BCON internal 07 cstring* ObjectId interpolation type-specifier */
+/** BCON internal 02 char** string pointer interpolation type-specifier */
+#define BTPS ":Ps:"
+/** BCON internal 03 union bcon** Embedded document pointer interpolation type-specifier */
+#define BTPD ":PD:"
+/** BCON internal 04 union bcon** Array pointer interpolation type-specifier */
+#define BTPA ":PA:"
+/** BCON internal 07 char** ObjectId pointer interpolation type-specifier */
#define BTPO ":Po:"
-/** BCON internal 08 int* Boolean interpolation type-specifier */
+/** BCON internal 08 int** Boolean pointer interpolation type-specifier */
#define BTPB ":Pb:"
-/** BCON internal 09 int64* UTC datetime interpolation type-specifier */
+/** BCON internal 09 int64** UTC datetime pointer interpolation type-specifier */
#define BTPT ":Pt:"
-/** BCON internal 0E cstring* Symbol interpolation type-specifier */
+/** BCON internal 0E char** Symbol pointer interpolation type-specifier */
#define BTPX ":Px:"
-/** BCON internal 10 int32* 64-bit Integer interpolation type-specifier */
+/** BCON internal 10 int32** 23-bit Integer pointer interpolation type-specifier */
#define BTPI ":Pi:"
-/** BCON internal 12 int64* 64-bit Integer interpolation type-specifier */
+/** BCON internal 12 int64** 64-bit Integer pointer interpolation type-specifier */
#define BTPL ":Pl:"
-/** BCON internal 03 union bcon * Embedded document interpolation type-specifier */
-#define BTPD ":PD:"
-/** BCON internal 04 union bcon * Array interpolation type-specifier */
-#define BTPA ":PA:"
-
-/** BCON 02 cstring string value */
-#define BS(v) BTS, { .s = (v) }
/** BCON 01 double Floating point value */
#define BF(v) BTF, { .f = (v) }
-/** BCON 07 cstring ObjectId value */
+/** BCON 02 char* string value */
+#define BS(v) BTS, { .s = (v) }
+/** BCON 03 union bcon* Embedded document interpolation value */
+#define BD(v) BTD, { .D = (v) }
+/** BCON 04 union bcon* Array interpolation value */
+#define BA(v) BTA, { .A = (v) }
+/** BCON 07 char* ObjectId value */
#define BO(v) BTO, { .o = (v) }
/** BCON 08 int Boolean value */
#define BB(v) BTB, { .b = (v) }
/** BCON 09 int64 UTC datetime value */
#define BT(v) BTT, { .t = (v) }
/** BCON 0A Null value */
#define BNULL BTN, { .v = ("") }
-/** BCON 0E cstring Symbol value */
+/** BCON 0E char* Symbol value */
#define BX(v) BTX, { .x = (v) }
/** BCON 10 int32 32-bit Integer value */
#define BI(v) BTI, { .i = (v) }
/** BCON 12 int64 64-bit Integer value */
#define BL(v) BTL, { .l = (v) }
-/** BCON 02 cstring* string interpolation value */
-#define BPS(v) BTPS, { .Ps = (v) }
/** BCON 01 double* Floating point interpolation value */
-#define BPF(v) BTPF, { .Pf = (v) }
-/** BCON 07 cstring* ObjectId interpolation value */
-#define BPO(v) BTPO, { .Po = (v) }
+#define BRF(v) BTRF, { .Rf = (v) }
+/** BCON 02 char* string interpolation value */
+#define BRS(v) BTRS, { .Rs = (v) }
+/** BCON 03 union bcon* Embedded document interpolation value */
+#define BRD(v) BTRD, { .RD = (v) }
+/** BCON 04 union bcon* Array interpolation value */
+#define BRA(v) BTRA, { .RA = (v) }
+/** BCON 07 char* ObjectId interpolation value */
+#define BRO(v) BTRO, { .Ro = (v) }
/** BCON 08 int* Boolean interpolation value */
-#define BPB(v) BTPB, { .Pb = (v) }
+#define BRB(v) BTRB, { .Rb = (v) }
/** BCON 09 int64* UTC datetime value */
-#define BPT(v) BTPT, { .Pt = (v) }
-/** BCON 0E cstring* Symbol interpolation value */
-#define BPX(v) BTPX, { .Px = (v) }
+#define BRT(v) BTRT, { .Rt = (v) }
+/** BCON 0E char* Symbol interpolation value */
+#define BRX(v) BTRX, { .Rx = (v) }
/** BCON 10 int32* 32-bit Integer interpolation value */
-#define BPI(v) BTPI, { .Pi = (v) }
+#define BRI(v) BTRI, { .Ri = (v) }
/** BCON 12 int64* 64-bit Integer interpolation value */
+#define BRL(v) BTRL, { .Rl = (v) }
+
+/** BCON 01 double** Floating point interpolation value */
+#define BPF(v) BTPF, { .Pf = (v) }
+/** BCON 02 char** string interpolation value */
+#define BPS(v) BTPS, { .Ps = ((char**)v) }
+/** BCON 03 union bcon** Embedded document interpolation value */
+#define BPD(v) BTPD, { .PD = ((union bcon **)v) }
+/** BCON 04 union bcon** Array interpolation value */
+#define BPA(v) BTPA, { .PA = ((union bcon **)v) }
+/** BCON 07 char** ObjectId interpolation value */
+#define BPO(v) BTPO, { .Po = ((char**)v) }
+/** BCON 08 int** Boolean interpolation value */
+#define BPB(v) BTPB, { .Pb = (v) }
+/** BCON 09 int64** UTC datetime value */
+#define BPT(v) BTPT, { .Pt = (v) }
+/** BCON 0E char** Symbol interpolation value */
+#define BPX(v) BTPX, { .Px = ((char**)v) }
+/** BCON 10 int32** 32-bit Integer interpolation value */
+#define BPI(v) BTPI, { .Pi = (v) }
+/** BCON 12 int64** 64-bit Integer interpolation value */
#define BPL(v) BTPL, { .Pl = (v) }
-/** BCON 03 union bcon * Embedded document interpolation value */
-#define BPD(v) BTPD, { .PD = (v) }
-/** BCON 04 union bcon * Array interpolation value */
-#define BPA(v) BTPA, { .PA = (v) }
/*
* References on codes used for types
View
214 test/bcon_test.c
@@ -25,17 +25,18 @@ int verbose = 0;
int bcon_token(char *s);
-void test_bcon_token() {
+void test_bcon_token( void ) {
assert(Token_Default == bcon_token(":_i:X"));
assert(Token_Typespec == bcon_token(":_i:"));
assert(Token_OpenBrace == bcon_token("{"));
assert(Token_CloseBrace == bcon_token("}"));
assert(Token_OpenBracket == bcon_token("["));
assert(Token_CloseBracket == bcon_token("]"));
+ assert(Token_End == bcon_token("."));
assert(Token_EOD == bcon_token(0));
}
-void test_bson_from_bcon(const bcon *bc, bcon_error_t bc_err, int bv_err ) {
+void test_bson_from_bcon( const bcon *bc, bcon_error_t bc_err, int bv_err ) {
bcon_error_t ret;
bson b[1];
if ( verbose ) { putchar('\t'); bcon_print(bc); putchar('\n'); }
@@ -50,36 +51,12 @@ void test_bson_from_bcon(const bcon *bc, bcon_error_t bc_err, int bv_err ) {
bson_destroy( b );
}
-void test_basic_types() {
- bcon basic_types[] = {"string", BS("a string"), "f(double)", BF(3.14159), "boolean", BB(1), "time", BT(time(0)), "null", BNULL, "symbol", BX("a symbol"), "int", BI(123), "long", BL(456789L), BEND};
- test_bson_from_bcon( basic_types, BCON_OK, BSON_VALID );
-}
-
-void test_basic_interpolation() {
- char *s = "a_string";
- double f = 3.14159;
- bson_bool_t bb = 1;
- time_t t = time(0);
- char *x = "a symbol";
- int i = 123;
- long l = 456789L;
- bcon basic_interpolation[] = {"string", BPS(&s), "f(double)", BPF(&f), "boolean", BPB(&bb), "time", BPT(&t), "symbol", BPX(&x), "int", BPI(&i), "long", BPL(&l), BEND};
- test_bson_from_bcon( basic_interpolation, BCON_OK, BSON_VALID );
-}
-
-void test_oid_and_interpolation() {
- char *oid_s = "010203040506070809101112";
- bcon oid_bc[] = { "_id", BO(""), "user_id", BO("010203040506070809101112"), "admin_id", BPO(&oid_s), BEND };
- if ( verbose ) { putchar('\t'); bcon_print( oid_bc ); putchar('\n'); }
- test_bson_from_bcon( oid_bc, BCON_OK, BSON_VALID );;
-}
-
-void test_invalid_structure() {
+void test_invalid_structure( void ) {
bcon bc_incomplete[] = { "k0", BEND };
test_bson_from_bcon( bc_incomplete, BCON_DOCUMENT_INCOMPLETE, BSON_VALID );
}
-void test_problematic_structure() {
+void test_problematic_structure( void ) {
bcon bc_incomplete[] = { "k0", BEND };
test_bson_from_bcon( bc_incomplete, BCON_DOCUMENT_INCOMPLETE, BSON_VALID );
bcon bc_bracket_brace[] = { "k0", "v0", "k1", "{", "k11", "v11", "]", "v12", "}", BEND };
@@ -88,7 +65,7 @@ void test_problematic_structure() {
test_bson_from_bcon( bc_brace_bracket, BCON_OK, BSON_VALID ); /* key for now */
}
-void test_valid_structure() {
+void test_valid_structure( void ) {
bcon bc_key_value[] = { "k0", "v0", BEND };
test_bson_from_bcon( bc_key_value, BCON_OK, BSON_VALID );
bcon bc_key_spec_value[] = { "k0", ":_s:", "v0", BEND };
@@ -111,16 +88,162 @@ void test_valid_structure() {
test_bson_from_bcon( bc_array_doc, BCON_OK, BSON_VALID );
}
-void test_high_order_interpolation() {
- bcon bc_child_doc[] = { "k10", "v10", "k11", "v11", BEND };
- bcon bc_parent_doc[] = { "k0", "v0", "k1", BPD(bc_child_doc), "k2", "v2", BEND };
- test_bson_from_bcon( bc_parent_doc, BCON_OK, BSON_VALID );
- bcon bc_child_array[] = { "k10", "v10", "k11", "v11", BEND };
- bcon bc_parent_doc_array[] = { "k0", "v0", "k1", BPA(bc_child_array), "k2", "v2", BEND };
- test_bson_from_bcon( bc_parent_doc_array, BCON_OK, BSON_VALID );
+void test_basic_types( void ) {
+ bcon doc[] = { "k0", "v0", "k1", "v1", BEND };
+ bcon array[] = { "v0", "v1", "v2", BEND };
+ bcon basic_types[] = {
+ "f(double)", BF(3.14159),
+ "string", BS("a string"),
+ "doc", BD(doc),
+ "array", BA(array),
+ "oid", BO("010203040506070809101112"),
+ "boolean", BB(1),
+ "time", BT(time(0)),
+ "null", BNULL,
+ "symbol", BX("a symbol"),
+ "int", BI(123),
+ "long", BL(456789L),
+ BEND
+ };
+ test_bson_from_bcon( basic_types, BCON_OK, BSON_VALID );
+}
+
+void test_reference_interpolation( void ) {
+ double f = 3.14159;
+ char s[] = "a_string";
+ bcon doc[] = { "k0", "v0", "k1", "v1", BEND };
+ bcon array[] = { "v0", "v1", "v2", BEND };
+ char oid_s[] = "010203040506070809101112";
+ bson_bool_t bb = 1;
+ time_t t = time(0);
+ char x[] = "a symbol";
+ int i = 123;
+ long l = 456789L;
+ bcon reference_interpolation[] = {
+ "f", BRF(&f),
+ "string", BRS(s),
+ "doc", BRD(doc),
+ "array", BRA(array),
+ "oid", BRO(oid_s),
+ "boolean", BRB(&bb),
+ "time", BRT(&t),
+ "symbol", BRX(x),
+ "int", BRI(&i),
+ "long", BRL(&l),
+ BEND
+ };
+ test_bson_from_bcon( reference_interpolation, BCON_OK, BSON_VALID );
+ f = 2.71828;
+ strcpy(s, "b_string");
+ doc[0].s = "key";
+ array[1].s = "val";
+ strcpy(oid_s, "987654321506070809101112");
+ bb = 0;
+ t = time(0);
+ strcpy(x, "b symbol");
+ i = 456;
+ l = 123456L;
+ test_bson_from_bcon( reference_interpolation, BCON_OK, BSON_VALID );
+}
+
+void test_pointer_interpolation( void ) {
+ double f = 3.14159;
+ double *pf = &f;
+ char s[] = "a_string";
+ char **ps = (char**)&s;
+ bcon doc[] = { "k0", "v0", "k1", "v1", BEND };
+ bcon **pdoc = (bcon**)&doc;
+ bcon array[] = { "v0", "v1", "v2", BEND };
+ bcon **parray = (bcon**)&array;
+ char oid_s[] = "010203040506070809101112";
+ char **poid_s = (char**)&oid_s;
+ bson_bool_t bb = 1;
+ bson_bool_t *pbb = &bb;
+ time_t t = time(0);
+ time_t *pt = &t;
+ char x[] = "a symbol";
+ char **px = (char**)&x;
+ int i = 123;
+ int *pi = &i;
+ long l = 456789L;
+ long *pl = &l;
+ bcon pointer_interpolation[] = {
+ "alpha", "0",
+ "f", BPF(&pf),
+ "string", BPS(&ps),
+ "doc", BPD(&pdoc),
+ "array", BPA(&parray),
+ "oid", BPO(&poid_s),
+ "boolean", BPB(&pbb),
+ "time", BPT(&pt),
+ "symbol", BPX(&px),
+ "int", BPI(&pi),
+ "long", BPL(&pl),
+ "omega", "1",
+ BEND
+ };
+ test_bson_from_bcon( pointer_interpolation, BCON_OK, BSON_VALID );
+ f = 2.71828;
+ strcpy(s, "b_string");
+ doc[0].s = "key";
+ array[1].s = "val";
+ strcpy(oid_s, "987654321506070809101112");
+ bb = 0;
+ t = time(0);
+ strcpy(x, "b symbol");
+ i = 456;
+ l = 123456L;
+ test_bson_from_bcon( pointer_interpolation, BCON_OK, BSON_VALID );
+ pf = 0; ps = 0; pdoc = 0; parray = 0; poid_s = 0; pbb = 0; pt = 0; px = 0; pi = 0; pl = 0;
+ test_bson_from_bcon( pointer_interpolation, BCON_OK, BSON_VALID );
+}
+
+void test_oid_generation( void ) {
+ char oid_s[] = "010203040506070809101112";
+ char **poid_s = (char**)&oid_s;
+ bcon oid_bc[] = { "_id", BO(""), "user_id", BRO(oid_s), "admin_id", BPO(&poid_s), BEND };
+ test_bson_from_bcon( oid_bc, BCON_OK, BSON_VALID );
+ oid_s[0] = '\0';
+ test_bson_from_bcon( oid_bc, BCON_OK, BSON_VALID );
}
-void test_example_hello_world() {
+void test_reference_interpolation_example( void ) {
+ bson b[1];
+ char name[] = "pi";
+ double value = 3.14159;
+ bcon bc[] = { "name", BRS(name), "value", BRF(&value), BEND };
+ bson_from_bcon( b, bc ); /* generates { name: "pi", "value", 3.14159 } */
+ if (verbose) bson_print( b );
+ strcpy(name, "e");
+ value = 2.71828;
+ bson_from_bcon( b, bc ); /* generates { name: "pi", "value", 3.14159 } */
+ if (verbose) bson_print( b );
+}
+
+void test_pointer_interpolation_example( void ) {
+ bson b[1];
+ char name[] = "pi";
+ char new_name[] = "log(0)";
+ char **pname = (char**)&name;
+ double value = 3.14159;
+ double *pvalue = &value;
+ bcon bc[] = { "name", BPS(&pname), "value", BPF(&pvalue), BEND };
+ bson_from_bcon( b, bc ); /* generates { name: "pi", "value", 3.14159 } */
+ test_bson_from_bcon( bc, BCON_OK, BSON_VALID );
+ pname = (char**)&new_name;
+ pvalue = 0;
+ bson_from_bcon( b, bc ); /* generates { name: "log(0)" } */
+ test_bson_from_bcon( bc, BCON_OK, BSON_VALID );
+}
+
+void test_additional_notes_example( void ) {
+ bson b[1];
+ bcon bc[] = { "spec", BS(":_s:"), BEND };
+ bson_from_bcon( b, bc ); /* generates { spec: ":_s:" } */
+ test_bson_from_bcon( bc, BCON_OK, BSON_VALID );
+}
+
+void test_example_hello_world( void ) {
bcon_error_t ret;
bson b[1];
@@ -140,7 +263,7 @@ void test_example_hello_world() {
bson_destroy( b );
}
-void test_example_awesome() {
+void test_example_awesome( void ) {
bcon_error_t ret;
bson b[1];
@@ -230,7 +353,7 @@ void test_example_wikipedia_bson(size_t iterations) {
assert(ret == BSON_OK);
}
-void test_example_wikipedia() {
+void test_example_wikipedia( void ) {
bson b[1];
/*
http://en.wikipedia.org/wiki/JSON
@@ -273,16 +396,19 @@ void test_example_wikipedia() {
struct test_suite {
char *name;
- void (*fn)();
+ void (*fn)( void );
} test_suite[] = {
NAME_VALUE(test_bcon_token),
- NAME_VALUE(test_basic_types),
- NAME_VALUE(test_basic_interpolation),
- NAME_VALUE(test_oid_and_interpolation),
NAME_VALUE(test_invalid_structure),
NAME_VALUE(test_valid_structure),
NAME_VALUE(test_problematic_structure),
- NAME_VALUE(test_high_order_interpolation),
+ NAME_VALUE(test_basic_types),
+ NAME_VALUE(test_reference_interpolation),
+ NAME_VALUE(test_pointer_interpolation),
+ NAME_VALUE(test_oid_generation),
+ NAME_VALUE(test_reference_interpolation_example),
+ NAME_VALUE(test_pointer_interpolation_example),
+ NAME_VALUE(test_additional_notes_example),
NAME_VALUE(test_example_hello_world),
NAME_VALUE(test_example_awesome),
/* NAME_VALUE(test_example_wikipedia), */

0 comments on commit dfb15c7

Please sign in to comment.