diff --git a/blob.h b/blob.h index 67bcfd6..bdd8f70 100644 --- a/blob.h +++ b/blob.h @@ -49,6 +49,7 @@ enum { BLOB_FIELD_FLOAT64, // a packed 64 bit float BLOB_FIELD_ARRAY, // only unnamed elements BLOB_FIELD_TABLE, // only named elements + BLOB_FIELD_ANY, // to be used only as a wildcard BLOB_FIELD_LAST }; @@ -57,6 +58,12 @@ struct blob { void *buf; // raw buffer data }; +struct blob_policy { + const char *name; + int type; + struct blob_field *value; +}; + //! Initializes a blob structure. Optionally takes memory area to be copied into the buffer which must represent a valid blob buf. void blob_init(struct blob *buf, const char *data, size_t size); //! Frees the memory allocated with the buffer diff --git a/blob_field.c b/blob_field.c index ca9f009..73afb5e 100644 --- a/blob_field.c +++ b/blob_field.c @@ -377,3 +377,30 @@ bool blob_field_parse(struct blob_field *attr, const char *signature, struct blo } return true; } + +bool blob_field_parse_values(struct blob_field *attr, struct blob_policy *policy, int policy_size){ + bool valid = true; + if(blob_field_type(attr) == BLOB_FIELD_TABLE){ + struct blob_field *key, *value; + blob_field_for_each_kv(attr, key, value){ + for(int c = 0; c < policy_size; c++){ + if(strcmp(blob_field_get_string(key), policy[c].name) == 0){ + if(policy[c].type == BLOB_FIELD_ANY || blob_field_type(value) == policy[c].type) { + policy[c].value = value; + } else { policy[c].value = NULL; valid = false; } + break; + } + } + } + } else if(blob_field_type(attr) == BLOB_FIELD_ARRAY){ + struct blob_field *child; + int pidx = 0; + blob_field_for_each_child(attr, child){ + if(policy[pidx].type == BLOB_FIELD_ANY || blob_field_type(child) == policy[pidx].type) { + policy[pidx].value = child; + } else { policy[pidx].value = NULL; valid = false; } + pidx++; + } + } + return valid; +} diff --git a/blob_field.h b/blob_field.h index 3371f11..7caddeb 100644 --- a/blob_field.h +++ b/blob_field.h @@ -79,6 +79,9 @@ bool blob_field_validate(struct blob_field *attr, const char *signature); bool blob_field_parse(struct blob_field *attr, const char *signature, struct blob_field **out, int out_size); +struct blob_policy; +bool blob_field_parse_values(struct blob_field *attr, struct blob_policy *policy, int policy_size); + #define blob_field_for_each_kv(attr, key, value) \ for(key = blob_field_first_child(attr), value = blob_field_next_child(attr, key); \ key && value; \ diff --git a/blob_json.c b/blob_json.c index 4902210..332d9ee 100644 --- a/blob_json.c +++ b/blob_json.c @@ -227,7 +227,7 @@ static void blob_format_element(struct strbuf *s, struct blob_field *attr, bool switch(blob_field_type(attr)) { case BLOB_FIELD_INVALID: - sprintf(buf, "(invalid)"); + sprintf(buf, "null"); break; //case BLOB_FIELD_BOOL: // sprintf(buf, "%s", *(uint8_t *)data ? "true" : "false"); diff --git a/blob_json.h b/blob_json.h index 57bd345..88efff6 100644 --- a/blob_json.h +++ b/blob_json.h @@ -38,5 +38,6 @@ char *blob_field_to_json(struct blob_field *self); static inline char *blob_to_json(struct blob *self){ return blob_field_to_json(blob_head(self)); } bool blob_put_json(struct blob *self, const char *json); +bool blob_put_json_from_file(struct blob *self, const char *file); #endif diff --git a/blob_ujson.c b/blob_ujson.c index 344461e..9356c79 100644 --- a/blob_ujson.c +++ b/blob_ujson.c @@ -25,6 +25,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Added blob parsing code: +Copyright (C) 2016 Martin K. Schröder Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ @@ -39,6 +41,9 @@ http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms #include "blobpack.h" #include #include +#include +#include +#include #include "ujson.h" #define DEBUG(...) {} @@ -161,3 +166,23 @@ bool blob_put_json(struct blob *self, const char *json){ return true; } +bool blob_put_json_from_file(struct blob *self, const char *file){ + // this is a rather simplistic approach where we just load the whole file into memory and then parse the buffer. + // there can probably be better ways where we parse data in place.. + // TODO: solve if this becomes a problem later + size_t file_size = 0; + int fd = open(file, O_RDONLY); + if(fd < 0) return false; + file_size = lseek(fd, SEEK_END, 0); + if(file_size > 1000000UL) { close(fd); return false; } + lseek(fd, SEEK_SET, 0); + char *buffer = alloca(file_size + 1); // allocate on stack + memset(buffer, 0, file_size + 1); + if(file_size != read(fd, buffer, file_size)){ + close(fd); + return false; + } + close(fd); + return blob_put_json(self, buffer); +} +