_bsonstrip moved into bson_strip in bson.c module
authoradam <adamansky@gmail.com>
Fri, 9 Aug 2013 08:12:22 +0000 (15:12 +0700)
committeradam <adamansky@gmail.com>
Fri, 9 Aug 2013 08:12:22 +0000 (15:12 +0700)
tcejdb/bson.c
tcejdb/bson.h
tcejdb/ejdb.c

index 5ec6e73..22e2580 100644 (file)
@@ -1649,6 +1649,151 @@ int bson_merge(const bson *b1, const bson *b2, bson_bool_t overwrite, bson *out)
     return bson_merge2(bson_data(b1), bson_data(b2), overwrite, out);
 }
 
+
+typedef struct {
+    bson *sbson;
+    TCMAP *ifields;
+    int nstack; //nested object stack pos
+    int matched; //number of matched include fields
+} _BSONSTRIPVISITORCTX;
+
+
+/* Discard excluded fields from BSON */
+static bson_visitor_cmd_t _bsonstripvisitor_exclude(const char *ipath, int ipathlen, const char *key, int keylen,
+        const bson_iterator *it, bool after, void *op) {
+    _BSONSTRIPVISITORCTX *ictx = op;
+    assert(ictx && ictx->sbson && ictx->ifields && ipath && key && it && op);
+    TCMAP *ifields = ictx->ifields;
+    const void *buf;
+    int bufsz;
+    const char* ifpath;
+    bson_type bt = bson_iterator_type(it);
+
+    buf = after ? NULL : tcmapget(ifields, ipath, ipathlen, &bufsz);
+    if (!buf) {
+        if (bt == BSON_OBJECT || bt == BSON_ARRAY) {
+            if (!after) {
+                tcmapiterinit(ifields); //check prefix
+                while ((ifpath = tcmapiternext2(ifields)) != NULL) {
+                    int i = 0;
+                    for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
+                    if (i == ipathlen) { //ipath prefixes some exclude object field
+                        ictx->nstack++;
+                        if (bt == BSON_OBJECT) {
+                            bson_append_start_object2(ictx->sbson, key, keylen);
+                        } else if (bt == BSON_ARRAY) {
+                            bson_append_start_array2(ictx->sbson, key, keylen);
+                        }
+                        return (BSON_VCMD_OK);
+                    }
+                }
+                bson_append_field_from_iterator(it, ictx->sbson);
+                return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
+            } else {
+                if (ictx->nstack > 0) {
+                    --ictx->nstack;
+                    if (bt == BSON_OBJECT) {
+                        bson_append_finish_object(ictx->sbson);
+                    } else if (bt == BSON_ARRAY) {
+                        bson_append_finish_array(ictx->sbson);
+                    }
+                }
+                return (BSON_VCMD_OK);
+            }
+        } else {
+            bson_append_field_from_iterator(it, ictx->sbson);
+            return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
+        }
+    }
+    return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
+}
+
+/* Accept only included fields into BSON */
+static bson_visitor_cmd_t _bsonstripvisitor_include(const char *ipath, int ipathlen, const char *key, int keylen,
+        const bson_iterator *it, bool after, void *op) {
+    _BSONSTRIPVISITORCTX *ictx = op;
+    assert(ictx && ictx->sbson && ictx->ifields && ipath && key && it && op);
+    bson_visitor_cmd_t rv = BSON_VCMD_OK;
+    TCMAP *ifields = ictx->ifields;
+    const void *buf;
+    const char* ifpath;
+    int bufsz;
+
+    bson_type bt = bson_iterator_type(it);
+    if (ictx->matched == TCMAPRNUM(ifields)) {
+        return BSON_VCMD_TERMINATE;
+    }
+    if (bt != BSON_OBJECT && bt != BSON_ARRAY) {
+        if (after) { //simple primitive case
+            return BSON_VCMD_OK;
+        }
+        buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
+        if (buf) {
+            ictx->matched++;
+            bson_append_field_from_iterator(it, ictx->sbson);
+        }
+        return (BSON_VCMD_SKIP_AFTER);
+    } else { //more complicated case
+        if (!after) {
+            buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
+            if (buf) { //field hitted
+                bson_iterator cit = *it; //copy iterator
+                bson_append_field_from_iterator(&cit, ictx->sbson);
+                ictx->matched++;
+                return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
+            } else { //check prefix
+                tcmapiterinit(ifields);
+                while ((ifpath = tcmapiternext2(ifields)) != NULL) {
+                    int i = 0;
+                    for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
+                    if (i == ipathlen) { //ipath prefixes some included field
+                        ictx->nstack++;
+                        if (bt == BSON_OBJECT) {
+                            bson_append_start_object2(ictx->sbson, key, keylen);
+                        } else if (bt == BSON_ARRAY) {
+                            bson_append_start_array2(ictx->sbson, key, keylen);
+                        } else {
+                            assert(0);
+                        }
+                        break;
+                    }
+                }
+            }
+        } else { //after
+            if (ictx->nstack > 0) {
+                --ictx->nstack;
+                if (bt == BSON_OBJECT) {
+                    bson_append_finish_object(ictx->sbson);
+                } else if (bt == BSON_ARRAY) {
+                    bson_append_finish_array(ictx->sbson);
+                } else {
+                    assert(0);
+                }
+            }
+        }
+    }
+    return rv;
+}
+
+/* Include or exclude fpaths in the specified BSON and put resulting data into `bsout`. */
+int bson_strip(TCMAP *ifields, bool imode, const void *bsbuf, bson *bsout) {
+        if (!ifields || bsout->finished) {
+        return false;
+    }
+    _BSONSTRIPVISITORCTX ictx = {
+        .sbson = bsout,
+        .ifields = ifields,
+        .nstack = 0,
+        .matched = 0
+    };
+    bson_iterator it;
+    bson_iterator_from_buffer(&it, bsbuf);
+    bson_visit_fields(&it, 0, (imode) ? _bsonstripvisitor_include : _bsonstripvisitor_exclude, &ictx);
+    assert(ictx.nstack == 0);
+    return bson_finish(bsout);
+}
+
+
 int bson_inplace_set_bool(bson_iterator *pos, bson_bool_t val) {
     assert(pos);
     bson_type bt = bson_iterator_type(pos);
index acdbc77..3bc489d 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdbool.h>
 #endif
 #include <time.h>
+#include <tcutil.h>
 
 #define BSON_IS_NUM_TYPE(atype) (atype == BSON_INT || atype == BSON_LONG || atype == BSON_DOUBLE)
 
@@ -1115,6 +1116,18 @@ EJDB_EXPORT int bson_inplace_set_bool(bson_iterator *pos, bson_bool_t val);
 EJDB_EXPORT int bson_inplace_set_long(bson_iterator *pos, int64_t val);
 EJDB_EXPORT int bson_inplace_set_double(bson_iterator *pos, double val);
 
+/**
+ * Include or exclude fpaths in the specified BSON and put resulting data into `bsout`.
+ * On completion it finishes `bsout` object.
+ * 
+ * @param ifields Map of fieldpaths. Map values are a simple boolean bufs.
+ * @param imode If true fpaths will be included. Otherwise fpaths will be excluded from bson.
+ * @param bsbuf BSON buffer to process.
+ * @param bsout Allocated output not finished bson* object
+ * @return BSON error code
+ */
+EJDB_EXPORT int bson_strip(TCMAP *ifields, bool imode, const void *bsbuf, bson *bsout);
+
 
 /**
  * Compares field path primitive values of two BSONs
index 3672cd8..9027c99 100644 (file)
@@ -127,7 +127,6 @@ static EJQ* _qryaddand(EJDB *jb, EJQ *q, const void *andbsdata);
 static bool _qrydup(const EJQ *src, EJQ *target, uint32_t qflags);
 static void _qrydel(EJQ *q, bool freequery);
 static bool _pushprocessedbson(EJDB *jb, EJQ *q, TCLIST *rs, TCMAP *dfields, TCMAP *ifields, bool imode, const void *bsbuf, int bsbufsz);
-static bool _stripbson(EJDB *jb, TCMAP *ifields, bool imode, const void *bsbuf, bson *bsout);
 static bool _exec$do(EJDB *jb, EJQ *q, TCMAP *dfields, const void *bsbuf, bson *bsout);
 static TCLIST* _qryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, int qflags, TCXSTR *log);
 EJDB_INLINE void _nufetch(_EJDBNUM *nu, const char *sval, bson_type bt);
@@ -2375,13 +2374,6 @@ static bool _qrydup(const EJQ *src, EJQ *target, uint32_t qflags) {
     return true;
 }
 
-typedef struct {
-    bson *sbson;
-    TCMAP *ifields;
-    int nstack; //nested object stack pos
-    int matched; //number of matched include fields
-} _BSONSTRIPVISITORCTX;
-
 typedef struct { /**> $do action visitor context */
     EJQ *q;
     EJDB *jb;
@@ -2389,122 +2381,6 @@ typedef struct { /**> $do action visitor context */
     bson *sbson;
 } _BSON$DOVISITORCTX;
 
-/* Discard excluded fields from BSON */
-static bson_visitor_cmd_t _bsonstripvisitor_exclude(const char *ipath, int ipathlen, const char *key, int keylen,
-        const bson_iterator *it, bool after, void *op) {
-    _BSONSTRIPVISITORCTX *ictx = op;
-    assert(ictx && ictx->sbson && ictx->ifields && ipath && key && it && op);
-    TCMAP *ifields = ictx->ifields;
-    const void *buf;
-    int bufsz;
-    const char* ifpath;
-    bson_type bt = bson_iterator_type(it);
-
-    buf = after ? NULL : tcmapget(ifields, ipath, ipathlen, &bufsz);
-    if (!buf) {
-        if (bt == BSON_OBJECT || bt == BSON_ARRAY) {
-            if (!after) {
-                tcmapiterinit(ifields); //check prefix
-                while ((ifpath = tcmapiternext2(ifields)) != NULL) {
-                    int i = 0;
-                    for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
-                    if (i == ipathlen) { //ipath prefixes some exclude object field
-                        ictx->nstack++;
-                        if (bt == BSON_OBJECT) {
-                            bson_append_start_object2(ictx->sbson, key, keylen);
-                        } else if (bt == BSON_ARRAY) {
-                            bson_append_start_array2(ictx->sbson, key, keylen);
-                        }
-                        return (BSON_VCMD_OK);
-                    }
-                }
-                bson_append_field_from_iterator(it, ictx->sbson);
-                return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
-            } else {
-                if (ictx->nstack > 0) {
-                    --ictx->nstack;
-                    if (bt == BSON_OBJECT) {
-                        bson_append_finish_object(ictx->sbson);
-                    } else if (bt == BSON_ARRAY) {
-                        bson_append_finish_array(ictx->sbson);
-                    }
-                }
-                return (BSON_VCMD_OK);
-            }
-        } else {
-            bson_append_field_from_iterator(it, ictx->sbson);
-            return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
-        }
-    }
-    return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
-}
-
-/* Accept only included fields into BSON */
-static bson_visitor_cmd_t _bsonstripvisitor_include(const char *ipath, int ipathlen, const char *key, int keylen,
-        const bson_iterator *it, bool after, void *op) {
-    _BSONSTRIPVISITORCTX *ictx = op;
-    assert(ictx && ictx->sbson && ictx->ifields && ipath && key && it && op);
-    bson_visitor_cmd_t rv = BSON_VCMD_OK;
-    TCMAP *ifields = ictx->ifields;
-    const void *buf;
-    const char* ifpath;
-    int bufsz;
-
-    bson_type bt = bson_iterator_type(it);
-    if (ictx->matched == TCMAPRNUM(ifields)) {
-        return BSON_VCMD_TERMINATE;
-    }
-    if (bt != BSON_OBJECT && bt != BSON_ARRAY) {
-        if (after) { //simple primitive case
-            return BSON_VCMD_OK;
-        }
-        buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
-        if (buf) {
-            ictx->matched++;
-            bson_append_field_from_iterator(it, ictx->sbson);
-        }
-        return (BSON_VCMD_SKIP_AFTER);
-    } else { //more complicated case
-        if (!after) {
-            buf = tcmapget(ifields, ipath, ipathlen, &bufsz);
-            if (buf) { //field hitted
-                bson_iterator cit = *it; //copy iterator
-                bson_append_field_from_iterator(&cit, ictx->sbson);
-                ictx->matched++;
-                return (BSON_VCMD_SKIP_NESTED | BSON_VCMD_SKIP_AFTER);
-            } else { //check prefix
-                tcmapiterinit(ifields);
-                while ((ifpath = tcmapiternext2(ifields)) != NULL) {
-                    int i = 0;
-                    for (; i < ipathlen && *(ifpath + i) == *(ipath + i); ++i);
-                    if (i == ipathlen) { //ipath prefixes some included field
-                        ictx->nstack++;
-                        if (bt == BSON_OBJECT) {
-                            bson_append_start_object2(ictx->sbson, key, keylen);
-                        } else if (bt == BSON_ARRAY) {
-                            bson_append_start_array2(ictx->sbson, key, keylen);
-                        } else {
-                            assert(0);
-                        }
-                        break;
-                    }
-                }
-            }
-        } else { //after
-            if (ictx->nstack > 0) {
-                --ictx->nstack;
-                if (bt == BSON_OBJECT) {
-                    bson_append_finish_object(ictx->sbson);
-                } else if (bt == BSON_ARRAY) {
-                    bson_append_finish_array(ictx->sbson);
-                } else {
-                    assert(0);
-                }
-            }
-        }
-    }
-    return rv;
-}
 
 static bson_visitor_cmd_t _bson$dovisitor(const char *ipath, int ipathlen, const char *key, int keylen,
         const bson_iterator *it, bool after, void *op) {
@@ -2627,7 +2503,9 @@ static bool _pushprocessedbson(EJDB *jb, EJQ *q, TCLIST *res, TCMAP *dfields, TC
         if (bsout.finished) {
             bson_init_size(&bsout, bson_size(&bsout));
         }
-        rv = _stripbson(jb, ifields, imode, inbuf, &bsout);
+        if (bson_strip(ifields, imode, inbuf, &bsout) != BSON_OK) {
+            _ejdbsetecode(jb, JBEINVALIDBSON, __FILE__, __LINE__, __func__);
+        }
         if (inbuf != bsbuf && inbuf != bstack) {
             TCFREE(inbuf);
         }
@@ -2664,29 +2542,6 @@ static bool _exec$do(EJDB *jb, EJQ *q, TCMAP *dfields, const void *bsbuf, bson *
     return true;
 }
 
-/* Pushes bson into rs with only fields matched included/excludes in $fields */
-static bool _stripbson(EJDB *jb, TCMAP *ifields, bool imode, const void *bsbuf, bson *bsout) {
-    if (!ifields || bsout->finished) {
-        return false;
-    }
-    _BSONSTRIPVISITORCTX ictx = {
-        .sbson = bsout,
-        .ifields = ifields,
-        .nstack = 0,
-        .matched = 0
-    };
-    bson_iterator it;
-    bson_iterator_from_buffer(&it, bsbuf);
-    bson_visit_fields(&it, 0, (imode) ? _bsonstripvisitor_include : _bsonstripvisitor_exclude, &ictx);
-    assert(ictx.nstack == 0);
-
-    if (bson_finish(bsout) != BSON_OK) {
-        _ejdbsetecode(jb, JBEINVALIDBSON, __FILE__, __LINE__, __func__);
-        return false;
-    }
-    return true;
-}
-
 static bool _qryupdate(EJCOLL *jcoll, const EJQ *ejq, void *bsbuf, int bsbufsz, TCLIST *didxctx, TCXSTR *log) {
     assert(ejq->flags & EJQUPDATING);
     assert(bsbuf && didxctx);