250 lines
7.6 KiB
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;
|
|
}
|