#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include "build.h"
#include "htsmsg.h"
#include "misc/dbl.h"
#include "htsmsg_json.h"
+#include "memoryinfo.h"
+
+#if ENABLE_SLOW_MEMORYINFO
+memoryinfo_t htsmsg_memoryinfo = { .my_name = "htsmsg" };
+memoryinfo_t htsmsg_field_memoryinfo = { .my_name = "htsmsg field" };
+#endif
static void htsmsg_clear(htsmsg_t *msg);
-static htsmsg_t *
-htsmsg_field_get_msg ( htsmsg_field_t *f, int islist );
+static htsmsg_t *htsmsg_field_get_msg ( htsmsg_field_t *f, int islist );
/**
*
break;
case HMF_STR:
- if(f->hmf_flags & HMF_ALLOCED)
+ if(f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_remove(&htsmsg_field_memoryinfo, strlen(f->hmf_str) + 1);
+#endif
free((void *)f->hmf_str);
+ }
break;
case HMF_BIN:
- if(f->hmf_flags & HMF_ALLOCED)
+ if(f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_remove(&htsmsg_field_memoryinfo, f->hmf_binsize);
+#endif
free((void *)f->hmf_bin);
+ }
break;
default:
break;
void
htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f)
{
+#if ENABLE_SLOW_MEMORYINFO
+ size_t asize = 0;
+#endif
+
TAILQ_REMOVE(&msg->hm_fields, f, hmf_link);
htsmsg_field_data_destroy(f);
- if(f->hmf_flags & HMF_NAME_ALLOCED)
+ if (f->hmf_flags & HMF_NAME_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+ asize += strlen(f->hmf_name);
+#endif
free((void *)f->hmf_name);
+ }
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_field_memoryinfo,
+ sizeof(*f) + f->hmf_edata_size + asize);
+#endif
free(f);
}
{
size_t nsize = 0;
htsmsg_field_t *f;
+#if ENABLE_SLOW_MEMORYINFO
+ size_t asize = 0;
+#endif
if((flags & HMF_NAME_INALLOCED) && name)
nsize = strlen(name) + 1;
if (name) {
f->hmf_name = f->hmf_edata;
strcpy(f->hmf_edata, name);
+ } else {
+ f->hmf_name = NULL;
}
} else if(flags & HMF_NAME_ALLOCED) {
f->hmf_name = name ? strdup(name) : NULL;
+#if ENABLE_SLOW_MEMORYINFO
+ asize = name ? strlen(name) + 1 : 0;
+#endif
} else {
f->hmf_name = name;
}
- if(esize)
- f->hmf_str = f->hmf_edata + nsize;
+ if(esize) {
+ if(type == HMF_STR)
+ f->hmf_str = f->hmf_edata + nsize;
+ else if(type == HMF_BIN)
+ f->hmf_bin = f->hmf_edata + nsize;
+ }
f->hmf_type = type;
f->hmf_flags = flags;
+#if ENABLE_SLOW_MEMORYINFO
+ f->hmf_edata_size = nsize + esize;
+ memoryinfo_alloc(&htsmsg_field_memoryinfo,
+ sizeof(htsmsg_field_t) + f->hmf_edata_size + asize);
+#endif
return f;
}
htsmsg_t *msg;
msg = malloc(sizeof(htsmsg_t));
- TAILQ_INIT(&msg->hm_fields);
- msg->hm_data = NULL;
- msg->hm_islist = 0;
+ if (msg) {
+ TAILQ_INIT(&msg->hm_fields);
+ msg->hm_data = NULL;
+ msg->hm_data_size = 0;
+ msg->hm_islist = 0;
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_alloc(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
+ }
return msg;
}
htsmsg_t *msg;
msg = malloc(sizeof(htsmsg_t));
- TAILQ_INIT(&msg->hm_fields);
- msg->hm_data = NULL;
- msg->hm_islist = 1;
+ if (msg) {
+ TAILQ_INIT(&msg->hm_fields);
+ msg->hm_data = NULL;
+ msg->hm_data_size = 0;
+ msg->hm_islist = 1;
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_alloc(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
+ }
return msg;
}
void
htsmsg_destroy(htsmsg_t *msg)
{
+#if ENABLE_SLOW_MEMORYINFO
+ size_t size = 0;
+#endif
+
if(msg == NULL)
return;
htsmsg_clear(msg);
- free((void *)msg->hm_data);
+ if (msg->hm_data) {
+ free((void *)msg->hm_data);
+#if ENABLE_SLOW_MEMORYINFO
+ size += msg->hm_data_size;
+#endif
+ }
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t) + size);
+#endif
free(msg);
}
htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_STR, HMF_NAME_INALLOCED,
strlen(str) + 1);
strcpy((char *)f->hmf_str, str);
+ f->hmf_flags |= HMF_INALLOCED;
}
/*
{
if (f->hmf_type != HMF_STR)
return 1;
- if (f->hmf_flags & HMF_ALLOCED)
+ if (f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_remove(&htsmsg_field_memoryinfo, strlen(f->hmf_str) + 1);
+#endif
free((void *)f->hmf_str);
+ }
+ else if (f->hmf_flags & HMF_INALLOCED) {
+ if (strlen(f->hmf_str) >= strlen(str)) {
+ strcpy((char *)f->hmf_str, str);
+ return 0;
+ }
+ f->hmf_flags &= ~HMF_INALLOCED;
+ }
f->hmf_flags |= HMF_ALLOCED;
f->hmf_str = strdup(str);
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_alloc(&htsmsg_field_memoryinfo, strlen(str) + 1);
+#endif
return 0;
}
htsmsg_set_str(htsmsg_t *msg, const char *name, const char *str)
{
htsmsg_field_t *f = htsmsg_field_find(msg, name);
- if (!f)
- f = htsmsg_field_add(msg, name, HMF_STR, HMF_NAME_INALLOCED, 0);
+ if (!f) {
+ htsmsg_add_str(msg, name, str);
+ return 0;
+ }
return htsmsg_field_set_str(f, str);
}
htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_BIN, HMF_NAME_INALLOCED, len);
f->hmf_bin = f->hmf_str;
f->hmf_binsize = len;
+ f->hmf_flags |= HMF_INALLOCED;
memcpy((void *)f->hmf_bin, bin, len);
}
{
assert(sub->hm_data == NULL);
f->hmf_msg.hm_data = NULL;
+ f->hmf_msg.hm_data_size = 0;
f->hmf_msg.hm_islist = sub->hm_islist;
TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link);
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
free(sub);
if (f->hmf_type == (f->hmf_msg.hm_islist ? HMF_LIST : HMF_MAP))
assert(sub->hm_data == NULL);
f->hmf_msg.hm_data = NULL;
+ f->hmf_msg.hm_data_size = 0;
TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link);
f->hmf_msg.hm_islist = sub->hm_islist;
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
free(sub);
}
case HMF_STR:
break;
case HMF_BOOL:
- f->hmf_str = strdup(f->hmf_bool ? "true" : "false");
- f->hmf_type = HMF_STR;
- f->hmf_flags |= HMF_ALLOCED;
+ htsmsg_field_set_str(f, f->hmf_bool ? "true" : "false");
break;
case HMF_S64:
snprintf(buf, sizeof(buf), "%"PRId64, f->hmf_s64);
- f->hmf_str = strdup(buf);
- f->hmf_type = HMF_STR;
- f->hmf_flags |= HMF_ALLOCED;
+ htsmsg_field_set_str(f, buf);
break;
case HMF_DBL:
snprintf(buf, sizeof(buf), "%lf", f->hmf_dbl);
- f->hmf_str = strdup(buf);
- f->hmf_type = HMF_STR;
- f->hmf_flags |= HMF_ALLOCED;
+ htsmsg_field_set_str(f, buf);
break;
}
return f->hmf_str;
/* Deserialize JSON (will keep either list or map) */
if (f->hmf_type == HMF_STR) {
if ((m = htsmsg_json_deserialize(f->hmf_str))) {
- free((void*)f->hmf_str);
+ if (f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_field_memoryinfo, strlen(f->hmf_str) + 1);
+#endif
+ free((void*)f->hmf_str);
+ }
f->hmf_type = m->hm_islist ? HMF_LIST : HMF_MAP;
f->hmf_msg.hm_islist = m->hm_islist;
f->hmf_msg.hm_data = NULL;
+ f->hmf_msg.hm_data_size = 0;
TAILQ_MOVE(&f->hmf_msg.hm_fields, &m->hm_fields, hmf_link);
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
free(m);
}
}
const char *ssep;
if (!m->hm_islist) return NULL;
-#define MAX(a,b) ((a) < (b)) ? (a) : (b)
#define REALLOC(l)\
if ((alloc - used) < l) {\
alloc = MAX((l)*2, alloc*2);\
#include <string.h>
#include "htsmsg_binary.h"
+#include "memoryinfo.h"
/*
*
static int
htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
{
- unsigned type, namelen, datalen;
+ uint_fast32_t type, namelen, datalen;
+ size_t tlen;
htsmsg_field_t *f;
htsmsg_t *sub;
- char *n;
uint64_t u64;
- int i;
+ int i, bin = 0;
while(len > 5) {
if(len < namelen + datalen)
return -1;
- f = malloc(sizeof(htsmsg_field_t));
+ tlen = sizeof(htsmsg_field_t) +
+ (namelen ? namelen + 1 : 0) +
+ (type == HMF_STR ? datalen + 1 : 0);
+ f = malloc(tlen);
+ if (f == NULL)
+ return -1;
+#if ENABLE_SLOW_MEMORYINFO
+ f->hmf_edata_size = tlen - sizeof(htsmsg_field_t);
+ memoryinfo_alloc(&htsmsg_field_memoryinfo, tlen);
+#endif
f->hmf_type = type;
if(namelen > 0) {
- n = malloc(namelen + 1);
- memcpy(n, buf, namelen);
- n[namelen] = 0;
+ f->hmf_name = f->hmf_edata;
+ memcpy(f->hmf_edata, buf, namelen);
+ f->hmf_edata[namelen] = 0;
buf += namelen;
len -= namelen;
- f->hmf_flags = HMF_NAME_ALLOCED;
+ f->hmf_flags = HMF_NAME_INALLOCED;
} else {
- n = NULL;
+ f->hmf_name = NULL;
f->hmf_flags = 0;
}
- f->hmf_name = n;
-
switch(type) {
case HMF_STR:
- f->hmf_str = n = malloc(datalen + 1);
- memcpy(n, buf, datalen);
- n[datalen] = 0;
- f->hmf_flags |= HMF_ALLOCED;
+ f->hmf_str = f->hmf_edata + (namelen ? namelen + 1 : 0);
+ memcpy((char *)f->hmf_str, buf, datalen);
+ ((char *)f->hmf_str)[datalen] = 0;
break;
case HMF_BIN:
f->hmf_bin = (const void *)buf;
f->hmf_binsize = datalen;
+ bin = 1;
break;
case HMF_S64:
sub = &f->hmf_msg;
TAILQ_INIT(&sub->hm_fields);
sub->hm_data = NULL;
- if(htsmsg_binary_des0(sub, buf, datalen) < 0) {
- free(n);
+ i = htsmsg_binary_des0(sub, buf, datalen);
+ if (i < 0) {
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_field_memoryinfo, tlen);
+#endif
free(f);
return -1;
}
+ if (i > 0)
+ bin = 1;
break;
case HMF_BOOL:
break;
default:
- free(n);
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_free(&htsmsg_field_memoryinfo, tlen);
+#endif
free(f);
return -1;
}
buf += datalen;
len -= datalen;
}
- return 0;
+ return bin;
}
*
*/
htsmsg_t *
-htsmsg_binary_deserialize(const void *data, size_t len, const void *buf)
+htsmsg_binary_deserialize(void *data, size_t len, const void *buf)
{
htsmsg_t *msg = htsmsg_create_map();
- msg->hm_data = buf;
-
- if(htsmsg_binary_des0(msg, data, len) < 0) {
+ int r = htsmsg_binary_des0(msg, data, len);
+ if (r < 0) {
htsmsg_destroy(msg);
return NULL;
}
+ if (r > 0) {
+ msg->hm_data = buf;
+ msg->hm_data_size = len;
+#if ENABLE_SLOW_MEMORYINFO
+ memoryinfo_append(&htsmsg_memoryinfo, len);
+#endif
+ }
return msg;
}