#include "HvMessage.h"
#include "message.h"
#include <string.h>
HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp) {
m->timestamp = timestamp;
m->numElements = (hv_uint16_t) numElements;
m->numBytes = (hv_uint16_t) msg_getCoreSize(numElements);
return m;
}
HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f) {
m->timestamp = timestamp;
m->numElements = 1;
m->numBytes = sizeof(HvMessage);
msg_setFloat(m, 0, f);
return m;
}
HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp) {
m->timestamp = timestamp;
m->numElements = 1;
m->numBytes = sizeof(HvMessage);
msg_setBang(m, 0);
return m;
}
HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, const char *s) {
m->timestamp = timestamp;
m->numElements = 1;
m->numBytes = sizeof(HvMessage) + (hv_uint16_t) hv_strlen(s);
msg_setSymbol(m, 0, s);
return m;
}
HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h) {
m->timestamp = timestamp;
m->numElements = 1;
m->numBytes = sizeof(HvMessage);
msg_setHash(m, 0, h);
return m;
}
void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len) {
HvMessage *r = (HvMessage *) buffer;
hv_size_t len_r = msg_getCoreSize(msg_getNumElements(m));
hv_assert(len_r <= len);
hv_memcpy(r, m, len_r);
char *p = buffer + len_r; for (int i = 0; i < msg_getNumElements(m); ++i) {
if (msg_isSymbol(m,i)) {
const hv_size_t symLen = (hv_size_t) hv_strlen(msg_getSymbol(m,i)) + 1; hv_assert(len_r + symLen <= len); hv_strncpy(p, msg_getSymbol(m,i), symLen);
msg_setSymbol(r, i, p);
p += symLen;
len_r += symLen;
}
}
r->numBytes = (hv_uint16_t) len_r; }
HvMessage *msg_copy(const HvMessage *m) {
const hv_uint32_t heapSize = msg_getSize(m);
char *r = (char *) hv_malloc(heapSize);
hv_assert(r != NULL);
msg_copyToBuffer(m, r, heapSize);
return (HvMessage *) r;
}
void msg_free(HvMessage *m) {
hv_free(m); }
bool msg_hasFormat(const HvMessage *m, const char *fmt) {
hv_assert(fmt != NULL);
const int n = msg_getNumElements(m);
for (int i = 0; i < n; ++i) {
switch (fmt[i]) {
case 'b': if (!msg_isBang(m, i)) return false; break;
case 'f': if (!msg_isFloat(m, i)) return false; break;
case 'h': if (!msg_isHash(m, i)) return false; break;
case 's': if (!msg_isSymbol(m, i)) return false; break;
default: return false;
}
}
return (fmt[n] == '\0');
}
bool msg_compareSymbol(const HvMessage *m, int i, const char *s) {
switch (msg_getType(m,i)) {
case HV_MSG_SYMBOL: return !hv_strcmp(msg_getSymbol(m, i), s);
case HV_MSG_HASH: return (msg_getHash(m,i) == hv_string_to_hash(s));
default: return false;
}
}
bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n) {
if (i_m < msg_getNumElements(m) && i_n < msg_getNumElements(n)) {
if (msg_getType(m, i_m) == msg_getType(n, i_n)) {
switch (msg_getType(m, i_m)) {
case HV_MSG_BANG: return true;
case HV_MSG_FLOAT: return (msg_getFloat(m, i_m) == msg_getFloat(n, i_n));
case HV_MSG_SYMBOL: return msg_compareSymbol(m, i_m, msg_getSymbol(n, i_n));
case HV_MSG_HASH: return msg_getHash(m,i_m) == msg_getHash(n,i_n);
default: break;
}
}
}
return false;
}
void msg_setElementToFrom(HvMessage *n, int i_n, const HvMessage *const m, int i_m) {
switch (msg_getType(m, i_m)) {
case HV_MSG_BANG: msg_setBang(n, i_n); break;
case HV_MSG_FLOAT: msg_setFloat(n, i_n, msg_getFloat(m, i_m)); break;
case HV_MSG_SYMBOL: msg_setSymbol(n, i_n, msg_getSymbol(m, i_m)); break;
case HV_MSG_HASH: msg_setHash(n, i_n, msg_getHash(m, i_m));
default: break;
}
}
hv_uint32_t msg_getHash(const HvMessage *const m, int i) {
hv_assert(i < msg_getNumElements(m)); switch (msg_getType(m,i)) {
case HV_MSG_BANG: return 0xFFFFFFFF;
case HV_MSG_FLOAT: {
float f = msg_getFloat(m,i);
return *((hv_uint32_t *) &f);
}
case HV_MSG_SYMBOL: return hv_string_to_hash(msg_getSymbol(m,i));
case HV_MSG_HASH: return (&(m->elem)+i)->data.h;
default: return 0;
}
}
char *msg_toString(const HvMessage *m) {
hv_assert(msg_getNumElements(m) > 0);
int *len = (int *) hv_alloca(msg_getNumElements(m)*sizeof(int));
int size = 0;
for (int i = 0; i < msg_getNumElements(m); i++) {
switch (msg_getType(m, i)) {
case HV_MSG_BANG: len[i] = 5; break;
case HV_MSG_FLOAT: len[i] = strnlen(msg_ftoa(msg_getFloat(m, i), 10), 16)+1; break;
case HV_MSG_SYMBOL: len[i] = strnlen(msg_getSymbol(m, i), 16)+1; break;
case HV_MSG_HASH: len[i] = strnlen(msg_itoa(msg_getHash(m, i), 16), 8)+3; break;
default: break;
}
size += len[i];
}
hv_assert(size > 0);
char *finalString = (char *) hv_malloc(size*sizeof(char));
char* dst = finalString;
for (int i = 0; i < msg_getNumElements(m); i++) {
char* ptr;
switch (msg_getType(m, i)) {
case HV_MSG_BANG:
dst = stpcpy(dst, "bang");
break;
case HV_MSG_FLOAT:
ptr = msg_ftoa(msg_getFloat(m, i), 10);
dst = stpcpy(dst, ptr);
break;
case HV_MSG_SYMBOL:
ptr = (char*)msg_getSymbol(m, i);
dst = stpcpy(dst, ptr);
break;
case HV_MSG_HASH:
ptr = msg_itoa(msg_getHash(m, i), 16);
dst = stpcpy(dst, "0x");
dst = stpcpy(dst, ptr);
break;
default:
break;
}
dst = stpcpy(dst, " ");
}
hv_assert(dst - finalString == size);
finalString[size-1] = '\0'; return finalString;
}