void test_bcon_token() { 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_EOD == bcon_token(0)); }
void bcon_print(const bcon *bc) { /* prints internal representation, not JSON */ char *typespec = 0; const char *delim = ""; int end_of_data; bcon *bcp; putchar('{'); for (end_of_data = 0, bcp = (bcon*)bc; !end_of_data; bcp++) { bcon bci = *bcp; char *typespec_next = 0; if (typespec) { switch (typespec[1]) { case '_': switch (typespec[2]) { case 'f': printf("%s%f", delim, bci.f); break; case 's': printf("%s\"%s\"", delim, bci.s); break; case 'D': printf("%sPD(0x%"POINTER_PRINTSPEC",..)", delim, ( POINTER_TO_INT )bci.D); break; case 'A': printf("%sPA(0x%"POINTER_PRINTSPEC",....)", delim, ( POINTER_TO_INT )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; case 'v': printf("%s\"%s\"", delim, bci.v); break; case 'x': printf("%s\"%s\"", delim, bci.x); break; case 'i': printf("%s%d", delim, bci.i); break; case 'l': printf("%s%ld", delim, bci.l); break; default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break; } break; case 'R': switch (typespec[2]) { case 'f': printf("%sRf(0x%"POINTER_PRINTSPEC",%f)", delim, ( POINTER_TO_INT )bci.Rf, *bci.Rf); break; case 's': printf("%sRs(0x%"POINTER_PRINTSPEC",\"%s\")", delim, ( POINTER_TO_INT )bci.Rs, bci.Rs); break; case 'D': printf("%sRD(0x%"POINTER_PRINTSPEC",..)", delim, ( POINTER_TO_INT )bci.RD); break; case 'A': printf("%sRA(0x%"POINTER_PRINTSPEC",....)", delim, ( POINTER_TO_INT )bci.RA); break; case 'o': printf("%sRo(0x%"POINTER_PRINTSPEC",\"%s\")", delim, ( POINTER_TO_INT )bci.Ro, bci.Ro); break; case 'b': printf("%sRb(0x%"POINTER_PRINTSPEC",%d)", delim, ( POINTER_TO_INT )bci.Rb, *bci.Rb); break; case 't': printf("%sRt(0x%"POINTER_PRINTSPEC",%ld)", delim, ( POINTER_TO_INT )bci.Rt, (long)*bci.Rt); break; case 'x': printf("%sRx(0x%"POINTER_PRINTSPEC",\"%s\")", delim, ( POINTER_TO_INT )bci.Rx, bci.Rx); break; case 'i': printf("%sRi(0x%"POINTER_PRINTSPEC",%d)", delim, ( POINTER_TO_INT )bci.Ri, *bci.Ri); break; case 'l': printf("%sRl(0x%"POINTER_PRINTSPEC",%ld)", delim, ( POINTER_TO_INT )bci.Rl, *bci.Rl); break; default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break; } break; case 'P': switch (typespec[2]) { case 'f': printf("%sPf(0x%"POINTER_PRINTSPEC",%f)", delim, ( POINTER_TO_INT )bci.Pf, *bci.Pf); break; case 's': printf("%sPs(0x%"POINTER_PRINTSPEC",\"%s\")", delim, ( POINTER_TO_INT )bci.Ps, *bci.Ps); break; case 'D': printf("%sPD(0x%"POINTER_PRINTSPEC",..)", delim, ( POINTER_TO_INT )bci.PD); break; case 'A': printf("%sPA(0x%"POINTER_PRINTSPEC",....)", delim, (POINTER_TO_INT)bci.PA); break; case 'o': printf("%sPo(0x%"POINTER_PRINTSPEC",\"%s\")", delim, ( POINTER_TO_INT )bci.Po, *bci.Po); break; case 'b': printf("%sPb(0x%"POINTER_PRINTSPEC",%d)", delim, ( POINTER_TO_INT )bci.Pb, *bci.Pb); break; case 't': printf("%sPt(0x%"POINTER_PRINTSPEC",%"TIME_T_PRINTSPEC")", delim, ( POINTER_TO_INT )bci.Pt, ( TIME_T_TO_INT )*bci.Pt); break; case 'x': printf("%sPx(0x%"POINTER_PRINTSPEC",\"%s\")", delim, ( POINTER_TO_INT )bci.Px, *bci.Px); break; case 'i': printf("%sPi(0x%"POINTER_PRINTSPEC",%d)", delim, ( POINTER_TO_INT )bci.Pi, *bci.Pi); break; case 'l': printf("%sPl(0x%"POINTER_PRINTSPEC",%ld)", delim, ( POINTER_TO_INT )bci.Pl, *bci.Pl); break; default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break; } break; default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break; } } else { char *s = bci.s; switch (s[0]) { case '.': end_of_data = (s[1] == '\0'); break; case ':': typespec_next = bcon_token(s) == Token_Typespec ? s : 0; break; } printf("%s\"%s\"", delim, s); } typespec = typespec_next; delim = ","; } putchar('}'); }
/* * simplified FSM to parse BCON structure, uses stacks for sub-documents and sub-arrays */ static bcon_error_t bson_append_bcon_with_state(bson *b, const bcon *bc, bcon_state_t start_state) { bcon_error_t ret = BCON_OK; bcon_state_t state = start_state; char *key = 0; char *typespec = 0; unsigned char doc_stack[DOC_STACK_SIZE]; size_t doc_stack_pointer = 0; size_t array_index = 0; size_t array_index_stack[ARRAY_INDEX_STACK_SIZE]; size_t array_index_stack_pointer = 0; char array_index_buffer[ARRAY_INDEX_BUFFER_SIZE]; /* max BSON size */ int end_of_data; const bcon *bcp; for (end_of_data = 0, bcp = bc; ret == BCON_OK && !end_of_data; bcp++) { bcon bci = *bcp; char *s = bci.s; switch (state) { case State_Element: switch (bcon_token(s)) { case Token_CloseBrace: bson_append_finish_object( b ); DOC_POP_STATE; /* state = ...; */ break; case Token_End: end_of_data = 1; break; default: key = s; state = State_DocSpecValue; break; } break; case State_DocSpecValue: switch (bcon_token(s)) { case Token_Typespec: typespec = s; state = State_DocValue; break; case Token_OpenBrace: bson_append_start_object( b, key ); DOC_PUSH_STATE(State_Element); state = State_Element; break; case Token_OpenBracket: bson_append_start_array( b, key ); ARRAY_PUSH_RESET_INDEX_STATE(State_Element); state = State_ArraySpecValue; break; case Token_End: end_of_data = 1; break; default: ret = bson_bcon_key_value(b, key, typespec, bci); state = State_Element; break; } break; case State_DocValue: ret = bson_bcon_key_value(b, key, typespec, bci); state = State_Element; typespec = 0; break; case State_ArraySpecValue: switch (bcon_token(s)) { case Token_Typespec: typespec = s; state = State_ArrayValue; break; case Token_OpenBrace: key = ARRAY_KEY_STRING(array_index++); bson_append_start_object( b, key ); DOC_PUSH_STATE(State_ArraySpecValue); state = State_Element; break; case Token_OpenBracket: key = ARRAY_KEY_STRING(array_index++); bson_append_start_array( b, key ); ARRAY_PUSH_RESET_INDEX_STATE(State_ArraySpecValue); /* state = State_ArraySpecValue; */ break; case Token_CloseBracket: bson_append_finish_array( b ); ARRAY_POP_INDEX_STATE; /* state = ...; */ break; case Token_End: end_of_data = 1; break; default: key = ARRAY_KEY_STRING(array_index++); ret = bson_bcon_key_value(b, key, typespec, bci); /* state = State_ArraySpecValue; */ break; } break; case State_ArrayValue: key = ARRAY_KEY_STRING(array_index++); ret = bson_bcon_key_value(b, key, typespec, bci); state = State_ArraySpecValue; typespec = 0; break; default: assert(NOT_REACHED); break; } } return state == start_state ? BCON_OK : BCON_DOCUMENT_INCOMPLETE; }
void bcon_print(const bcon *bc) { /* prints internal representation, not JSON */ char *typespec = 0; char *delim = ""; int end_of_data; bcon *bcp; putchar('{'); for (end_of_data = 0, bcp = (bcon*)bc; !end_of_data; bcp++) { bcon bci = *bcp; char *typespec_next = 0; if (typespec) { switch (typespec[1]) { case '_': switch (typespec[2]) { 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; case 'v': printf("%s\"%s\"", delim, bci.v); break; case 'x': printf("%s\"%s\"", delim, bci.x); break; case 'i': printf("%s%d", delim, bci.i); break; case 'l': printf("%s%ld", delim, bci.l); break; 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 '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; default: printf("\ntypespec:\"%s\"\n", typespec); assert(NOT_REACHED); break; } } else { char *s = bci.s; switch (s[0]) { case '.': end_of_data = (s[1] == '\0'); break; case ':': typespec_next = bcon_token(s) == Token_Typespec ? s : 0; break; } printf("%s\"%s\"", delim, s); } typespec = typespec_next; delim = ","; } putchar('}'); }