summaryrefslogtreecommitdiffstats
path: root/src/bencoding.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bencoding.c')
-rw-r--r--src/bencoding.c65
1 files changed, 59 insertions, 6 deletions
diff --git a/src/bencoding.c b/src/bencoding.c
index d1324c7..d1ac517 100644
--- a/src/bencoding.c
+++ b/src/bencoding.c
@@ -21,11 +21,12 @@ struct bencoding {
struct bencoding * next; /**< NULL if element is not member of a list or dict */
struct bencoding * prev;
struct bencoding * child; /**< NULL if element is not a list or dict or if it has 0 children */
+ struct bencoding * parent;
enum benc type; /**< type | opts of this element */
struct bencoding * key; /**< the key element, string according to the spec, applicable for dict */
char * value; /**< set to the content of the element, value is not null terminated unless terminate opt is set. NULL for dict and list. */
size_t valuelen; /**< length of string value, as value is not null terminated, internal value for list or dict. */
- int intvalue;
+ long int intvalue;
int index;
char oldterminator; /**< when opts&terminate, the character that was replaced with \0 is stored here */
char oldterminatorls; /**< when opts&terminate when there was no more space, replaced character is stored here.
@@ -60,7 +61,7 @@ void free_bencoding (struct bencoding * b) {
* @param a [in] the character in question
*/
-int b2json_charsize (char a) {
+int b2json_charsize (unsigned char a) {
if (a == '"')
return 2;
if (a == '\\')
@@ -88,7 +89,7 @@ int b2json_charsize (char a) {
* @return the destination pointer, incremented for the number of bytes written
*/
-char * b2json_charrepr (char * dest, char a) {
+char * b2json_charrepr (char * dest, unsigned char a) {
switch (a) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
@@ -147,7 +148,7 @@ int b2json_length (struct bencoding * b) {
}
if (b->type & num) {
char buf[512];
- sprintf(buf, "%d", b->intvalue);
+ sprintf(buf, "%ld", b->intvalue);
return strlen(buf);
}
if (b->type & list) {
@@ -204,7 +205,7 @@ char * b2json (char * dest, struct bencoding * b) {
}
if (b->type & num) {
char buf[512];
- sprintf(buf, "%d", b->intvalue);
+ sprintf(buf, "%ld", b->intvalue);
strncpy(dest, buf, strlen(buf));
return dest+strlen(buf);
}
@@ -318,6 +319,8 @@ struct bencoding * bdecode (char * s, int len, enum benc opts) {
if (oldarbeit && oldarbeit->type & string && oldarbeit->type & terminate && oldarbeit->oldterminator)
c[0] = oldarbeit->oldterminator;
arbeit = bdecode(c, len == -1 ? -1 : len-(c-s), opts);
+ if (arbeit)
+ arbeit->parent = b;
if (oldarbeit && oldarbeit->type & string && oldarbeit->type & terminate && oldarbeit->oldterminator)
c[0] = '\0';
if (!arbeit) /* bdecoding failed or last element */
@@ -362,6 +365,7 @@ struct bencoding * bdecode (char * s, int len, enum benc opts) {
return NULL;
default:
if (!(s[0] >= '0' && s[0] <= '9')) { /* not a string. not checking this would allow DoS for parsing "lx" */
+ fprintf(stderr, "bencoding: unknown type %c\n", s[0]);
free(b);
return NULL;
}
@@ -389,6 +393,55 @@ struct bencoding * bdecode (char * s, int len, enum benc opts) {
/**
* returns a pointer to bencoding struct matching bencoding path or NULL if not found
+ *
+ * path key/key2/key3 will given object {"key":{"key2":{"key3":val}}} return val
*
- * [xxx] specifies xxxth child of a dict or list. if
+ * @param benc [in] the bencoding dict to look in
+ * @param key [in] the path
*/
+
+struct bencoding * bpath (struct bencoding * benc, const char * key) {
+ if (!benc)
+ return NULL;
+ if (!benc->child)
+ return NULL;
+ benc = benc->child;
+ if (key[0] == '/')
+ key++;
+ size_t len = strlen(key);
+ char * c = strchr(key, '/');
+ if (c)
+ len = c - key;
+ while (benc) {
+ if (benc->key && benc->key->type & num) {
+ char buf[512];
+ sprintf(buf, "%ld", strtol(key, NULL, 10));
+ if (!strncmp(buf, key, len) && benc->key->intvalue == strtol(key, NULL, 10)) {
+ if (!c)
+ return benc;
+ else
+ return bpath(benc, key+len);
+ }
+ }
+ if (benc->key && benc->key->type & string) {
+ if (!strncmp(key, benc->key->value, MIN(benc->key->valuelen, len))) {
+ if (!c)
+ return benc;
+ else
+ return bpath(benc, key+len);
+ }
+ }
+ benc = benc->next;
+ }
+ return NULL;
+}
+
+/**
+ * macro that loops following code body across a list or values of dict
+ *
+ * @param elem [out] name of element that will be used for value while looping
+ * @param list [in] list/dict of values
+ */
+
+#define bforeach(elem, list) \
+ for (struct bencoding * elem = list ? list->child : NULL; elem; elem = elem->next)