Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.openwrt.org/project/libubox.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-10-13 23:17:51 +0400
committerFelix Fietkau <nbd@openwrt.org>2010-10-13 23:29:08 +0400
commite82d74f89809c6c01f71168b3b8fdcf490e93fa7 (patch)
treeb031179f224fda2ab77077fa64878fd37879655e /blobmsg.c
Initial import
Diffstat (limited to 'blobmsg.c')
-rw-r--r--blobmsg.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/blobmsg.c b/blobmsg.c
new file mode 100644
index 0000000..25b72ae
--- /dev/null
+++ b/blobmsg.c
@@ -0,0 +1,148 @@
+/*
+ * blobmsg - library for generating/parsing structured blob messages
+ *
+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "blobmsg.h"
+
+int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len,
+ struct blob_attr **tb, void *data, int len)
+{
+ struct blobmsg_hdr *hdr;
+ struct blob_attr *attr;
+ uint8_t *pslen;
+ int i;
+
+ memset(tb, 0, policy_len * sizeof(*tb));
+ pslen = alloca(policy_len);
+ for (i = 0; i < policy_len; i++) {
+ if (!policy[i].name)
+ continue;
+
+ pslen[i] = strlen(policy[i].name);
+ }
+
+ __blob_for_each_attr(attr, data, len) {
+ hdr = blob_data(attr);
+ for (i = 0; i < policy_len; i++) {
+ if (!policy[i].name)
+ continue;
+
+ if (policy[i].type != BLOBMSG_TYPE_UNSPEC &&
+ blob_id(attr) != policy[i].type)
+ continue;
+
+ if (hdr->namelen != pslen[i])
+ continue;
+
+ if (!hdr->namelen)
+ return -1;
+
+ if (sizeof(*attr) + blobmsg_hdrlen(hdr->namelen) > blob_pad_len(attr))
+ return -1;
+
+ if (hdr->name[hdr->namelen] != 0)
+ return -1;
+
+ if (tb[i])
+ return -1;
+
+ if (strcmp(policy[i].name, (char *) hdr->name) != 0)
+ continue;
+
+ tb[i] = attr;
+ }
+ }
+
+ return 0;
+}
+
+
+static struct blob_attr *
+blobmsg_new(struct blob_buf *buf, int type, const char *name, int payload_len, void **data)
+{
+ struct blob_attr *attr;
+ struct blobmsg_hdr *hdr;
+ int attrlen, namelen;
+
+ if (blob_id(buf->head) == BLOBMSG_TYPE_ARRAY && !name) {
+ attr = blob_new(buf, type, payload_len);
+ *data = blob_data(attr);
+ return attr;
+ }
+
+ if (blob_id(buf->head) != BLOBMSG_TYPE_TABLE || !name)
+ return NULL;
+
+ namelen = strlen(name);
+ attrlen = blobmsg_hdrlen(namelen) + payload_len;
+ attr = blob_new(buf, type, attrlen);
+ if (!attr)
+ return NULL;
+
+ hdr = blob_data(attr);
+ hdr->namelen = namelen;
+ strcpy((char *) hdr->name, (const char *)name);
+ *data = blobmsg_data(attr);
+
+ return attr;
+}
+
+static inline int
+attr_to_offset(struct blob_buf *buf, struct blob_attr *attr)
+{
+ return (char *)attr - (char *) buf->buf;
+}
+
+
+void *
+blobmsg_open_nested(struct blob_buf *buf, const char *name, bool array)
+{
+ struct blob_attr *head = buf->head;
+ int type = array ? BLOBMSG_TYPE_ARRAY : BLOBMSG_TYPE_TABLE;
+ unsigned long offset = attr_to_offset(buf, buf->head);
+ void *data;
+
+ if (blob_id(head) == BLOBMSG_TYPE_ARRAY && !name)
+ return blob_nest_start(buf, type);
+
+ if (blob_id(head) == BLOBMSG_TYPE_TABLE && name) {
+ head = blobmsg_new(buf, type, name, 0, &data);
+ blob_set_raw_len(buf->head, blob_pad_len(buf->head) - blobmsg_hdrlen(strlen(name)));
+ buf->head = head;
+ return (void *)offset;
+ }
+
+ return NULL;
+}
+
+int
+blobmsg_add_field(struct blob_buf *buf, int type, const char *name,
+ const void *data, int len)
+{
+ struct blob_attr *attr;
+ void *data_dest;
+
+ if (type == BLOBMSG_TYPE_ARRAY ||
+ type == BLOBMSG_TYPE_TABLE)
+ return -1;
+
+ attr = blobmsg_new(buf, type, name, len, &data_dest);
+ if (!attr)
+ return -1;
+
+ if (len > 0)
+ memcpy(data_dest, data, len);
+
+ return 0;
+}