Files
emacs/lisp/zmq/src/msg.c

250 lines
7.6 KiB
C

#include "msg.h"
static void
ezmq_free_message(void *data, void *hint)
{
free(data);
}
/**
Return a copy of the data contained in VAL. VAL is either a string or vector
of bytes. SIZE will be updated with the number of bytes contained in VAL. In
the case that VAL is a vector, an `args-out-ouf-range` error is raised if
the integers are not within range of a byte.
*/
static char *
_ezmq_extract_message_data(emacs_value val, ptrdiff_t *size)
{
emacs_value type = TYPE(val);
*size = 0;
if(EQ(type, Qstring)) {
EZMQ_EXTRACT_STRING(content, clen, val);
*size = clen;
return content;
} else if(EQ(type, Qvector)) {
ptrdiff_t clen = VEC_LENGTH(val);
char *content = ezmq_malloc(clen);
ptrdiff_t i;
for(i = 0; !NONLOCAL_EXIT() && i < clen; i++) {
EZMQ_EXTRACT_INT(byte, AREF(val, i));
if(0 <= byte && byte <= 255) {
content[i] = (char)byte;
} else {
ezmq_args_out_of_range(INT(byte), CONS(INT(0), INT(255)));
}
}
*size = clen;
return content;
} else
ezmq_wrong_type_argument(val, 2, Qstring, Qvector);
return NULL;
}
EZMQ_DOC(ezmq_message,
"&optional DATA",
"Initialize a ZMQ message.\n"
"If DATA is non-nil, initialize the message using DATA.\n"
"DATA can be either a string or a vector of byte integers.\n"
"If DATA is nil, initialize an empty message.");
emacs_value
ezmq_message(emacs_value edata)
{
ezmq_obj_t *msg = ezmq_new_obj(EZMQ_MESSAGE, NULL);
if(!NILP(edata)) {
ptrdiff_t size = 0;
char *data = _ezmq_extract_message_data(edata, &size);
EZMQ_CHECK_ERROR(zmq_msg_init_data(msg->obj,
data,
size,
&ezmq_free_message,
NULL));
if(NONLOCAL_EXIT()) free(data);
} else {
EZMQ_CHECK_ERROR(zmq_msg_init(msg->obj));
}
if(NONLOCAL_EXIT()) ezmq_free_obj(msg);
return ezmq_new_obj_ptr(msg);
}
EZMQ_DOC(ezmq_message_size, "MESSAGE", "Get the size of MESSAGE.");
emacs_value
ezmq_message_size(emacs_value emessage)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
return INT(zmq_msg_size(msg->obj));
}
EZMQ_DOC(ezmq_message_data, "MESSAGE", "Get the data of MESSAGE.");
emacs_value
ezmq_message_data(emacs_value emessage)
{
emacs_value retval = Qnil;
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
const char *content = zmq_msg_data(msg->obj);
if(content) {
size_t size = zmq_msg_size(msg->obj);
retval = STRING(content, size);
}
return retval;
}
EZMQ_DOC(ezmq_message_more, "MESSAGE", "Does MESSAGE have more parts?");
emacs_value
ezmq_message_more(emacs_value emessage)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
int retval = zmq_msg_more(msg->obj);
EZMQ_CHECK_ERROR(retval);
return retval ? Qt : Qnil;
}
EZMQ_DOC(ezmq_message_copy, "MESSAGE", "Copy MESSAGE.");
emacs_value
ezmq_message_copy(emacs_value emessage)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
ezmq_obj_t *dest = ezmq_new_obj(EZMQ_MESSAGE, NULL);
zmq_msg_init(dest->obj);
EZMQ_CHECK_ERROR(zmq_msg_copy(dest->obj, msg->obj));
return ezmq_new_obj_ptr(dest);
}
EZMQ_DOC(ezmq_message_move, "SRC DEST", "Move a message from SRC to DEST.");
emacs_value
ezmq_message_move(emacs_value esrc, emacs_value edest)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, esrc);
EZMQ_EXTRACT_OBJ(dest, EZMQ_MESSAGE, edest);
EZMQ_CHECK_ERROR(zmq_msg_move(dest->obj, msg->obj));
return Qnil;
}
EZMQ_DOC(ezmq_message_close, "MESSAGE", "Close a message");
emacs_value
ezmq_message_close(emacs_value emessage)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_CHECK_ERROR(zmq_msg_close(msg->obj));
return Qnil;
}
EZMQ_DOC(ezmq_message_set, "MESSAGE PROPERTY VALUE", "Set a MESSAGE's PROPERTY to VALUE.");
emacs_value
ezmq_message_set(emacs_value emessage, emacs_value eproperty, emacs_value evalue)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_EXTRACT_INT(property, eproperty);
switch(property) {
case ZMQ_MORE:
EZMQ_CHECK_ERROR(zmq_msg_set(msg->obj,
property,
!NILP(evalue)));
break;
default: {
EZMQ_EXTRACT_INT(value, evalue);
EZMQ_CHECK_ERROR(zmq_msg_set(msg->obj, property, value));
}
}
return Qnil;
}
EZMQ_DOC(ezmq_message_get, "MESSAGE PROPERTY", "Get a MESSAGE PROPERTY.");
emacs_value
ezmq_message_get(emacs_value emessage, emacs_value eproperty)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_EXTRACT_INT(property, eproperty);
int retval = zmq_msg_get(msg->obj, property);
EZMQ_CHECK_ERROR(retval);
if(property == ZMQ_MORE)
return retval ? Qt : Qnil;
else
return INT(retval);
}
EZMQ_DOC(ezmq_message_recv, "MESSAGE SOCK &optional FLAGS",
"Receive a MESSAGE from SOCK with additional FLAGS.\n"
"MESSAGE should be an initialized message.");
emacs_value
ezmq_message_recv(emacs_value emessage, emacs_value esock, emacs_value eflags)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_EXTRACT_OBJ(sock, EZMQ_SOCKET, esock);
EZMQ_EXTRACT_OPTIONAL_INT(flags, eflags);
EZMQ_CHECK_ERROR(zmq_msg_recv(msg->obj, sock->obj, flags));
return emessage;
}
EZMQ_DOC(ezmq_message_send, "MESSAGE SOCK &optional FLAGS",
"Send a MESSAGE on SOCK with additional FLAGS.");
emacs_value
ezmq_message_send(emacs_value emessage, emacs_value esock, emacs_value eflags)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_EXTRACT_OBJ(sock, EZMQ_SOCKET, esock);
EZMQ_EXTRACT_OPTIONAL_INT(flags, eflags);
EZMQ_CHECK_ERROR(zmq_msg_send(msg->obj, sock->obj, flags));
return Qnil;
}
EZMQ_DOC(ezmq_message_gets, "MESSAGE PROPERTY",
"Get a MESSAGE's metadata PROPERTY.\n"
"PROPERTY is a keyword and can only be one of those in\n"
"`zmq-message-properties'.");
emacs_value
ezmq_message_gets(emacs_value emessage, emacs_value eproperty)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_EXTRACT_STRING(property, plen, eproperty);
const char *retval = zmq_msg_gets(msg->obj, property);
free(property);
EZMQ_CHECK_NULL_ERROR(retval);
return STRING(retval, strlen(retval));
}
EZMQ_DOC(ezmq_message_routing_id, "MESSAGE", "Get the routing ID of MESSAGE.");
emacs_value
ezmq_message_routing_id(emacs_value emessage)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
return INT(zmq_msg_routing_id(msg->obj));
}
EZMQ_DOC(ezmq_message_set_routing_id, "MESSAGE ID", "Set MESSAGE's routing ID.");
emacs_value
ezmq_message_set_routing_id(emacs_value emessage, emacs_value eid)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_EXTRACT_INT(id, eid);
EZMQ_CHECK_ERROR(zmq_msg_set_routing_id(msg->obj, id));
return Qnil;
}
EZMQ_DOC(ezmq_message_group, "MESSAGE", "Get MESSAGE's GROUP.");
emacs_value
ezmq_message_group(emacs_value emessage)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
const char *group = zmq_msg_group(msg->obj);
EZMQ_CHECK_NULL_ERROR(group);
return NONLOCAL_EXIT() ? Qnil : STRING(group, strlen(group));
}
EZMQ_DOC(ezmq_message_set_group, "MESSAGE GROUP", "Set MESSAGE's GROUP.");
emacs_value
ezmq_message_set_group(emacs_value emessage, emacs_value egroup)
{
EZMQ_EXTRACT_OBJ(msg, EZMQ_MESSAGE, emessage);
EZMQ_EXTRACT_STRING(group, elen, egroup);
EZMQ_CHECK_ERROR(zmq_msg_set_group(msg->obj, group));
return Qnil;
}