From c349162a71f62434e0b6246de57513600af451ce Mon Sep 17 00:00:00 2001 From: scottmk Date: Sat, 14 Nov 2009 18:39:32 +0000 Subject: [PATCH] Pulled the creation of a single osrfMessage from a jsonObject into a separate function. This change simplifies osrf_message_deserialize(), and will make it easier to create a replacement for it. Also: tinkered with some of the comments and white space. M src/libopensrf/osrf_message.c git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1850 9efc2488-bf62-4759-914b-345cdb29e865 --- src/libopensrf/osrf_message.c | 259 +++++++++++++++++----------------- 1 file changed, 132 insertions(+), 127 deletions(-) diff --git a/src/libopensrf/osrf_message.c b/src/libopensrf/osrf_message.c index 4b9567c..0e97dd3 100644 --- a/src/libopensrf/osrf_message.c +++ b/src/libopensrf/osrf_message.c @@ -6,6 +6,7 @@ */ static jsonObject* osrfMessageToJSON( const osrfMessage* msg ); +static osrfMessage* deserialize_one_message( const jsonObject* message ); static char default_locale[17] = "en-US\0\0\0\0\0\0\0\0\0\0\0\0"; static char* current_locale = NULL; @@ -284,9 +285,9 @@ void osrfMessageFree( osrfMessage* msg ) { @param count Maximum number of messages to serialize. @return Pointer to the JSON string. - Traverse the array, adding each osrfMessage in turn to a JSON_ARRAY. Stop when you have added the - maximum number of messages, or when you encounter a NULL pointer in the array. Then translate the - JSON_ARRAY into a JSON string. + Traverse the array, adding each osrfMessage in turn to a JSON_ARRAY. Stop when you have added + the maximum number of messages, or when you encounter a NULL pointer in the array. Then + translate the JSON_ARRAY into a JSON string. The calling code is responsible for freeing the returned string. */ @@ -350,15 +351,16 @@ char* osrf_message_serialize(const osrfMessage* msg) { The data for "payload" is also a JSON_HASH, whose structure depends on the message type: - For a STATUS message, the payload's classname is msg->status_name. The keys are "status" (carrying - msg->status_text) and "statusCode" (carrying the status code as a string). + For a STATUS message, the payload's classname is msg->status_name. The keys are "status" + (carrying msg->status_text) and "statusCode" (carrying the status code as a string). - For a REQUEST message, the payload's classname is "osrfMethod". The keys are "method" (carrying - msg->method_name) and "params" (carrying a jsonObject to pass any parameters to the method call). + For a REQUEST message, the payload's classname is "osrfMethod". The keys are "method" + (carrying msg->method_name) and "params" (carrying a jsonObject to pass any parameters + to the method call). - For a RESULT message, the payload's classname is "osrfResult". The keys are "status" (carrying - msg->status_text), "statusCode" (carrying the status code as a string), and "content" (carrying a jsonObject - to return any results from the method call). + For a RESULT message, the payload's classname is "osrfResult". The keys are "status" + (carrying msg->status_text), "statusCode" (carrying the status code as a string), and + "content" (carrying a jsonObject to return any results from the method call). The calling code is responsible for freeing the returned jsonObject. */ @@ -457,137 +459,140 @@ int osrf_message_deserialize(const char* string, osrfMessage* msgs[], int count) int x; for( x = 0; x < json->size && x < count; x++ ) { - const jsonObject* message = jsonObjectGetIndex(json, x); - - if(message && message->type != JSON_NULL && - message->classname && !strcmp(message->classname, "osrfMessage")) { - - osrfMessage* new_msg = safe_malloc(sizeof(osrfMessage)); - new_msg->m_type = 0; - new_msg->thread_trace = 0; - new_msg->protocol = 0; - new_msg->status_name = NULL; - new_msg->status_text = NULL; - new_msg->status_code = 0; - new_msg->is_exception = 0; - new_msg->_result_content = NULL; - new_msg->result_string = NULL; - new_msg->method_name = NULL; - new_msg->_params = NULL; - new_msg->next = NULL; - new_msg->sender_locale = NULL; - new_msg->sender_tz_offset = 0; - - // Get the message type. If not specified, default to CONNECT. - const jsonObject* tmp = jsonObjectGetKeyConst(message, "type"); - - const char* t; - if( ( t = jsonObjectGetString(tmp)) ) { - - if(!strcmp(t, "CONNECT")) new_msg->m_type = CONNECT; - else if(!strcmp(t, "DISCONNECT")) new_msg->m_type = DISCONNECT; - else if(!strcmp(t, "STATUS")) new_msg->m_type = STATUS; - else if(!strcmp(t, "REQUEST")) new_msg->m_type = REQUEST; - else if(!strcmp(t, "RESULT")) new_msg->m_type = RESULT; - } - - // Get the thread trace, defaulting to zero. - tmp = jsonObjectGetKeyConst(message, "threadTrace"); - if(tmp) { - const char* tt = jsonObjectGetString(tmp); - if(tt) { - new_msg->thread_trace = atoi(tt); - } - } - - // Get the sender's locale, or leave it NULL if not specified. - if (current_locale) - free( current_locale ); - - tmp = jsonObjectGetKeyConst(message, "locale"); - - if(tmp && (new_msg->sender_locale = jsonObjectToSimpleString(tmp))) { - current_locale = strdup( new_msg->sender_locale ); - } else { - current_locale = NULL; - } - - // Get the protocol, defaulting to zero. - tmp = jsonObjectGetKeyConst(message, "protocol"); - - if(tmp) { - const char* proto = jsonObjectGetString(tmp); - if(proto) { - new_msg->protocol = atoi(proto); - } - } - - tmp = jsonObjectGetKeyConst(message, "payload"); - if(tmp) { - // Get method name and parameters for a REQUEST - const jsonObject* tmp0 = jsonObjectGetKeyConst(tmp,"method"); - const char* tmp_str = jsonObjectGetString(tmp0); - if(tmp_str) - new_msg->method_name = strdup(tmp_str); - - tmp0 = jsonObjectGetKeyConst(tmp,"params"); - if(tmp0) { - // Note that we use jsonObjectDecodeClass() instead of - // jsonObjectClone(). The classnames are already decoded, - // but jsonObjectDecodeClass removes the decoded classnames. - new_msg->_params = jsonObjectDecodeClass( tmp0 ); - if(new_msg->_params && new_msg->_params->type == JSON_NULL) - new_msg->_params->type = JSON_ARRAY; - } - - // Get status fields for a RESULT or STATUS - if(tmp->classname) - new_msg->status_name = strdup(tmp->classname); - - tmp0 = jsonObjectGetKeyConst(tmp,"status"); - tmp_str = jsonObjectGetString(tmp0); - if(tmp_str) - new_msg->status_text = strdup(tmp_str); - - tmp0 = jsonObjectGetKeyConst(tmp,"statusCode"); - if(tmp0) { - tmp_str = jsonObjectGetString(tmp0); - if(tmp_str) - new_msg->status_code = atoi(tmp_str); - if(tmp0->type == JSON_NUMBER) - new_msg->status_code = (int) jsonObjectGetNumber(tmp0); - } - - // Get the content for a RESULT - tmp0 = jsonObjectGetKeyConst(tmp,"content"); - if(tmp0) { - // Note that we use jsonObjectDecodeClass() instead of - // jsonObjectClone(). The classnames are already decoded, - // but jsonObjectDecodeClass removes the decoded classnames. - new_msg->_result_content = jsonObjectDecodeClass( tmp0 ); - } - - } - msgs[numparsed++] = new_msg; + const jsonObject* message = jsonObjectGetIndex( json, x ); + + if( message && message->type != JSON_NULL && + message->classname && !strcmp(message->classname, "osrfMessage" )) { + msgs[numparsed++] = deserialize_one_message( message ); } } - jsonObjectFree(json); + jsonObjectFree( json ); return numparsed; } +/** + @brief Translate a jsonObject into a single osrfMessage. + @param obj Pointer to the jsonObject to be translated. + @return Pointer to a newly created osrfMessage. + + It is assumed that @a obj is non-NULL and points to a valid representation of a message. + For a description of the expected structure of this representations, see osrfMessageToJSON(). + + The calling code is responsible for freeing the osrfMessage by calling osrfMessageFree(). +*/ +static osrfMessage* deserialize_one_message( const jsonObject* obj ) { + + // Get the message type. If it isn't present, default to CONNECT. + const jsonObject* tmp = jsonObjectGetKeyConst( obj, "type" ); + + enum M_TYPE type; + const char* t = jsonObjectGetString( tmp ); + if( t ) { + + if( !strcmp( t, "CONNECT" )) type = CONNECT; + else if( !strcmp( t, "DISCONNECT" )) type = DISCONNECT; + else if( !strcmp( t, "STATUS" )) type = STATUS; + else if( !strcmp( t, "REQUEST" )) type = REQUEST; + else if( !strcmp( t, "RESULT" )) type = RESULT; + } + + // Get the thread trace, defaulting to zero. + int trace = 0; + tmp = jsonObjectGetKeyConst( obj, "threadTrace" ); + if( tmp ) { + const char* tt = jsonObjectGetString( tmp ); + if( tt ) { + trace = atoi( tt ); + } + } + + // Get the protocol, defaulting to zero. + int protocol = 0; + tmp = jsonObjectGetKeyConst( obj, "protocol" ); + if(tmp) { + const char* proto = jsonObjectGetString(tmp); + if( proto ) { + protocol = atoi( proto ); + } + } + + // Now that we have the essentials, create an osrfMessage + osrfMessage* msg = osrf_message_init( type, trace, protocol ); + + // Get the sender's locale, or leave it NULL if not specified. + if ( current_locale ) + free( current_locale ); + + tmp = jsonObjectGetKeyConst( obj, "locale" ); + if(tmp && ( msg->sender_locale = jsonObjectToSimpleString(tmp))) { + current_locale = strdup( msg->sender_locale ); + } else { + current_locale = NULL; + } + + tmp = jsonObjectGetKeyConst( obj, "payload" ); + if(tmp) { + // Get method name and parameters for a REQUEST + const jsonObject* tmp0 = jsonObjectGetKeyConst(tmp,"method"); + const char* tmp_str = jsonObjectGetString(tmp0); + if(tmp_str) + msg->method_name = strdup(tmp_str); + + tmp0 = jsonObjectGetKeyConst(tmp,"params"); + if(tmp0) { + // Note that we use jsonObjectDecodeClass() instead of + // jsonObjectClone(). The classnames are already decoded, + // but jsonObjectDecodeClass removes the decoded classnames. + msg->_params = jsonObjectDecodeClass( tmp0 ); + if(msg->_params && msg->_params->type == JSON_NULL) + msg->_params->type = JSON_ARRAY; + } + + // Get status fields for a RESULT or STATUS + if(tmp->classname) + msg->status_name = strdup(tmp->classname); + + tmp0 = jsonObjectGetKeyConst(tmp,"status"); + tmp_str = jsonObjectGetString(tmp0); + if(tmp_str) + msg->status_text = strdup(tmp_str); + + tmp0 = jsonObjectGetKeyConst(tmp,"statusCode"); + if(tmp0) { + tmp_str = jsonObjectGetString(tmp0); + if(tmp_str) + msg->status_code = atoi(tmp_str); + if(tmp0->type == JSON_NUMBER) + msg->status_code = (int) jsonObjectGetNumber(tmp0); + } + + // Get the content for a RESULT + tmp0 = jsonObjectGetKeyConst(tmp,"content"); + if(tmp0) { + // Note that we use jsonObjectDecodeClass() instead of + // jsonObjectClone(). The classnames are already decoded, + // but jsonObjectDecodeClass removes the decoded classnames. + msg->_result_content = jsonObjectDecodeClass( tmp0 ); + } + + } + + return msg; +} + /** @brief Return a pointer to the result content of an osrfMessage. @param msg Pointer to the osrfMessage whose result content is to be returned. - @return Pointer to the result content (or NULL if there is no such content, or if @a msg is NULL). + @return Pointer to the result content (or NULL if there is no such content, or if @a msg is + NULL). - The returned pointer points into the innards of the osrfMessage. The calling code should @em not call - jsonObjectFree() on it, because the osrfMessage still owns it. + The returned pointer points into the innards of the osrfMessage. The calling code should + @em not call jsonObjectFree() on it, because the osrfMessage still owns it. */ jsonObject* osrfMessageGetResult( osrfMessage* msg ) { if(msg) return msg->_result_content; return NULL; } - -- 2.43.2