From 7b0c07d54a340a5ef1bf230ed5817d221482a238 Mon Sep 17 00:00:00 2001 From: Mark Wieder Date: Tue, 24 Jun 2014 20:27:41 -0700 Subject: [PATCH 1/2] latest master --- mergJSON/external.h | 1144 ++++++++++++++++++++----------------------- mergJSON/jansson | 2 +- mergJSON/mergJSON.c | 2 + 3 files changed, 531 insertions(+), 617 deletions(-) diff --git a/mergJSON/external.h b/mergJSON/external.h index 9c57b2d..98c999b 100644 --- a/mergJSON/external.h +++ b/mergJSON/external.h @@ -1,616 +1,528 @@ -#ifndef __REVOLUTION_EXTERNAL__ -#define __REVOLUTION_EXTERNAL__ - -#ifdef __cplusplus -extern "C" -{ -#endif - - /////////////////////////////////////////////////////////////////////////////// - // - // External API declarations - // - -#define EXTERNAL_SUCCESS 0 -#define EXTERNAL_FAILURE 1 - -#ifndef Bool -#define Bool int -#define True 1 -#define False 0 -#endif - - typedef void (*ExternalHandler)(char *p_arguments[], int p_argument_count, char **r_result, Bool *r_pass, Bool *r_error); - - typedef struct _ExternalDeclaration - { - const char *name; - const char *type; - unsigned long __not_used_1; - ExternalHandler handler; - void *__not_used_2; - } ExternalDeclaration; - - typedef struct _ExternalString - { - const char *buffer; - int length; - } ExternalString; - - typedef struct _ExternalArray - { - int nelements; - ExternalString *strings; - char **keys; - } ExternalArray; - - // Function: - // SendCardMessage - // Parameters: - // p_message: const char * - // r_success: int * - // Semantics: - // Send the message to this card of this stack. The message may - // contain parameters, but these should be pre-evaluated. - // - // If the call succeeds *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void SendCardMessage(const char *p_message, int *r_success); - - // Function: - // EvalExpr - // Parameters: - // p_expression: const char * - // r_success: int * - // Returns: - // char * - // Semantics: - // Evaluate the Revolution expression in the context of the - // handler that invoked the current external command or function. - // - // The result of the evaluation will be returned as a C-string that the - // caller then takes ownership of. i.e. You need to 'free' the result of - // EvalExpr when you are finished with it. - // - // If the call succeeds *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern char *EvalExpr(const char *p_expression, int *r_success); - - // Function: - // GetGlobal - // Parameters: - // p_name: const char * - // r_success: int * - // Returns: - // char * - // Semantics: - // Return the contents of the global variable called . - // - // The contents is returned as a C-string - meaning you cannot use it to - // fetch binary data. (The data will be truncated at the first NUL - // character). - // - // The caller takes ownership of the returned C-string. i.e. You need to - // 'free' the result of GetGlobal when you are finished with it. - // - // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern char *GetGlobal(const char *p_name, int *r_success); - - // Function: - // SetGlobal - // Parameters: - // p_name: const char * - // p_value: const char * - // r_success: int * - // Semantics: - // Set the value of a global variable called to . - // - // The value must be a (NUL-terminated) C-string - meaning it is unsuitable - // to use this call to set binary data. - // - // If the variable does not exist it will be created. - // - // Revolution copies the contents of so ownership of the memory - // pointed to by it does not change. - // - // If the call succeeds *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void SetGlobal(const char *p_name, const char *p_value, int *r_success); - - // Function: - // GetVariable - // Parameters: - // p_name: const char * - // r_success: int * - // Returns: - // char * - // Semantics: - // Get the value of a variable with name that is accessible within - // the scope of the handler that invoked the external command or function. - // - // The contents is returned as a C-string - meaning you cannot use it to - // fetch binary data. (The data will be truncated at the first NUL - // character). - // - // The caller takes ownership of the returned C-string. i.e. You need to - // 'free' the result of GetGlobal when you are finished with it. - // - // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern char *GetVariable(const char *p_name, int *r_success); - - // Function: - // SetVariable - // Parameters: - // p_name: const char * - // p_value: const char * - // r_success: int * - // Semantics: - // Set the value of a variable with name that is accessible within - // the scope of the handler that invoked the external command or function to - // . - // - // The value must be a (NUL-terminated) C-string - meaning it is unsuitable - // to use this call to set binary data. - // - // Revolution copies the contents of so ownership of the memory - // pointed to by it does not change. - // - // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void SetVariable(const char *p_name, const char *p_value, int *r_success); - - // Function: - // GetVariableEx - // Parameters: - // p_name: const char * - // p_key: const char * - // r_value: ExternalString * - // r_success: int * - // Semantics: - // Get the value of a variable with name that is accessible within - // the scope of the handler that invoked the external command or function. - // - // If is the empty string ("") then the value fetched will be that - // of the variable as a non-array (i.e. if the variable is an array the - // resulting value will be empty). - // - // If is not the empty string then the value fetched will be the - // value of the element of the variable with key , or empty if - // there is no such key or the variable is not an array. - // - // The value is returned in and Revolution retains ownership of - // the memory. The pointer r_value -> buffer is only guaranteed to be valid - // until control returns to Revolution or the variable, or variable's element - // is next modified. - // - // This call is safe to use with binary and text data as an 'ExternalString' - // need not be NUL-terminated - it carries the length of the data alongside - // the pointer to the data. - // - // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void GetVariableEx(const char *p_name, const char *p_key, ExternalString *r_value, int *r_success); - - // Function: - // SetVariableEx - // Parameters: - // p_name: const char * - // p_key: const char * - // p_value: ExternalString * - // r_success: int * - // Semantics: - // Set the value of a variable with name that is accessible within - // the scope of the handler that invoked the external command or function to - // . - // - // If is the empty string (""), then the variable will be set as - // a non-array. In particular, if it was previously an array its elements - // will be deleted. - // - // If is not the empty string (""), then the element with key - // will be set to . In particular, if the variable was not previously - // an array it's value will be cleared and it will become one. Similarly, if - // the element with the given key does not exist, it will be created. - // - // Revolution copies the data referenced in and so ownership of the - // memory does not change. - // - // This call is safe to use with binary and text data as an 'ExternalString' - // need not be NUL-terminated - it carries the length of the data alongside - // the pointer to the data. - // - // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void SetVariableEx(const char *p_name, const char *p_key, const ExternalString *p_value, int *r_success); - - // Function: - // GetArray - // Parameters: - // p_name: const char * - // r_element_count: int * - // r_values: ExternalString * - // r_keys: char ** - // r_success: int * - // Semantics: - // Fetch contents of an array variable with name that is accessible - // within the scope of the handler that invoked the external command or - // function. - // - // On entry if *r_element_count is 0, *r_element_count will be updated with - // the number of elements of the array and the call will return. - // - // If *r_element_count is not 0, then r_keys must point to an array of char * - // pointers of length *r_element_count. Additionally, r_values may point to an - // array of ExternalString's of length *r_element_count. - // - // On exit, if *r_element_count is not 0, then: - // - *r_element_count will be updated with the number of entries fetched - // (min(number of elements of array, *r_element_count). - // - each entry in the r_keys array will point to a C-string of the key of - // each element fetched - // - each entry in the r_values array (if non-NULL) will point to the value - // of each element fetched - // - // The ownership of all pointers returned (both in r_keys and r_values) remains - // with Revolution. Therefore these pointers are only guaranteed to be valid - // until control returns to Revolution or the variable is next modified. - // - // This call is safe to use with binary and text data as an 'ExternalString' - // need not be NUL-terminated - it carries the length of the data alongside - // the pointer to the data. - // - // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void GetArray(const char *p_name, int *r_element_count, ExternalString *r_values, char **r_keys, int *r_success); - - // Function: - // SetArray - // Parameters: - // p_name: const char * - // p_element_count: int - // p_values: ExternalString * - // p_keys: char ** - // r_success: int * - // Semantics: - // Set the contents of an array variable with name that is accessible - // within the scope of the handler that invoked the external command or - // function to elements with keys and values . - // - // On entry, must contain the number of elements to set and - // must point to an array of ExternalString's of length - // . Additionally, may point to an array of char *'s - // of length . - // - // This call clear the contents of the named variable and then set it up as - // an array with the specified values. - // - // If is NULL, the variable will be made into an integer-keyed array, - // entry mapping to p_values[n]. - // If is non-NULL, the variable will be made into a string-keyed array, - // entry p_key[n] mapping to p_values[n]. - // - // Revolution copies all data referenced and so the ownership of any memory - // does not change. - // - // This call is safe to use with binary and text data as an 'ExternalString' - // need not be NUL-terminated - it carries the length of the data alongside - // the pointer to the data. - // - // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void SetArray(const char *p_name, int p_element_count, ExternalString *p_values, char **p_keys, int *r_success); - - // Function: - // GetFieldBy* - // Parameters: - // p_group: const char * - // p_name: const char * - // p_index: int - // p_id: unsigned long - // r_success: int * - // Result: - // char * - // Semantics: - // These functions fetch the contents of the specified field. The field - // searched for depends on the form of the function: - // - // For Name: - // field of this card of this stack - // For Num: - // field of this card of this stack - // For Id: - // field id of this card of this stack - // - // If p_group is "true" then it has the same effect as searching for - // 'card field'. - // If p_group is "false" then it has the same effect as searching for - // 'background field"'. - // If p_group is NULL then no modifier is used. - // - // The contents is returned as a C-string - meaning you cannot use it to - // fetch binary data. (The data will be truncated at the first NUL - // character). - // - // The caller takes ownership of the returned C-string. i.e. You need to - // 'free' the result of GetGlobal when you are finished with it. - // - // If the field exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern char *GetFieldByName(const char *p_group, const char *p_name, int *r_success); - extern char *GetFieldByNum(const char *p_group, int p_index, int *r_success); - extern char *GetFieldById(const char *p_group, unsigned long p_id, int *r_success); - - // Function: - // SetFieldBy* - // Parameters: - // p_group: const char * - // p_name: const char * - // p_index: int - // p_id: unsigned long - // p_value: const char * - // r_success: int * - // Semantics: - // These functions set the contents of the specified field. The field - // searched for depends on the form of the function: - // - // For Name: - // field of this card of this stack - // For Num: - // field of this card of this stack - // For Id: - // field id of this card of this stack - // - // If p_group is "true" then it has the same effect as searching for - // 'card field'. - // If p_group is "false" then it has the same effect as searching for - // 'background field"'. - // If p_group is NULL then no modifier is used. - // - // The value must be a (NUL-terminated) C-string - meaning it is unsuitable - // to use this call to set binary data. - // - // Revolution copies the contents of so ownership of the memory - // pointed to by it does not change. - // - // If the field exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void SetFieldByName(const char *p_group, const char *p_name, const char *p_value, int *r_success); - extern void SetFieldByNum(const char *p_group, int p_index, const char *p_value, int *r_success); - extern void SetFieldById(const char *p_group, unsigned long p_id, const char *p_value, int *r_success); - - // Function: - // ShowImageBy* - // Parameters: - // p_group: const char * - // p_name: const char * - // p_index: int - // p_id: unsigned long - // r_success: int * - // Semantics: - // These functions cause the specified image to be redrawn. The image - // searched for depends on the form of the function: - // - // For Name: - // field of this card of this stack - // For Num: - // field of this card of this stack - // For Id: - // field id of this card of this stack - // - // If p_group is "true" then it has the same effect as searching for - // 'card field'. - // If p_group is "false" then it has the same effect as searching for - // 'background field"'. - // If p_group is NULL then no modifier is used. - // - // If the field exists *r_success will be EXTERNAL_SUCCESS, otherwise it - // will be EXTERNAL_FAILURE. - // - extern void ShowImageByName(const char *p_group, const char *p_name, int *r_success); - extern void ShowImageByNum(const char *p_group, int p_index, int *r_success); - extern void ShowImageById(const char *p_group, unsigned long p_id, int *r_success); - extern void ShowImageByLongId(const char *p_long_id, int *r_success); - - // - extern Bool SecurityCanAccessFile(const char *p_file); - extern Bool SecurityCanAccessHost(const char *p_host); - extern Bool SecurityCanAccessLibrary(const char *p_library); - -#ifdef __cplusplus -}; -#endif - -/////////////////////////////////////////////////////////////////////////////// -// -// External declaration macros -// - -#ifdef _MACOSX - -#ifdef __cplusplus - -#define EXTERNAL_REFERENCE_LIBRARY \ -extern "C" void getXtable(void); \ -void __dummy_function(void) \ -{ \ -getXtable(); \ -} - -#else - -#define EXTERNAL_REFERENCE_LIBRARY \ -void getXtable(void); \ -void __dummy_function(void) \ -{ \ -getXtable(); \ -} - -#endif - -#else - -#define EXTERNAL_REFERENCE_LIBRARY - -#endif - - -#ifdef __cplusplus - -#define EXTERNAL_BEGIN_DECLARATIONS(m_name) \ -extern "C" { \ -EXTERNAL_REFERENCE_LIBRARY \ -const char *g_external_name = m_name; \ -ExternalDeclaration g_external_table[] = \ -{ \ - -#define EXTERNAL_END_DECLARATIONS \ -{ "", "", 0, 0, 0 } \ -}; \ -} - -#else - -#define EXTERNAL_BEGIN_DECLARATIONS(m_name) \ -EXTERNAL_REFERENCE_LIBRARY \ -const char *g_external_name = m_name; \ -ExternalDeclaration g_external_table[] = \ -{ \ - -#define EXTERNAL_END_DECLARATIONS \ -{ "", "", 0, 0, 0 } \ -}; - -#endif - -#if defined(__cplusplus) && defined(__EXCEPTIONS) - -#include -#include -#include - -template void ExternalWrapper(char *p_arguments[], int p_argument_count, char **r_result, Bool *r_pass, Bool *r_err) -{ - *r_result = NULL; - - try - { - u_handler(p_arguments, p_argument_count, r_result, r_pass, r_err); - } - catch(std::exception& t_exception) - { - if (*r_result != NULL) - free(*r_result); - - *r_result = strdup(t_exception . what()); - *r_err = True; - } - catch(...) - { - if (*r_result != NULL) - free(*r_result); - - *r_result = strdup("unknown C++ exception"); - *r_err = True; - } -} - -#define EXTERNAL_DECLARE_COMMAND(m_name, m_function) \ -{ m_name, "C", 0, ExternalWrapper, NULL }, - -#define EXTERNAL_DECLARE_FUNCTION(m_name, m_function) \ -{ m_name, "F", 0, ExternalWrapper, NULL }, - - -#ifdef __OBJC__ - -#include - -inline void ExternalWrapperObjCCall(ExternalHandler p_handler, char *p_arguments[], int p_argument_count, char **r_result, Bool *r_pass, Bool *r_err) -{ - NS_DURING - p_handler(p_arguments, p_argument_count, r_result, r_pass, r_err); - NS_HANDLER - *r_result = strdup([[localException reason] cStringUsingEncoding:NSMacOSRomanStringEncoding]); - *r_err = True; - NS_ENDHANDLER -} - -template void ExternalWrapperObjC(char *p_arguments[], int p_argument_count, char **r_result, Bool *r_pass, Bool *r_err) -{ - *r_result = NULL; - - try - { - NSAutoreleasePool *t_pool; - t_pool = [[NSAutoreleasePool alloc] init]; - if (t_pool != NULL) - { - ExternalWrapperObjCCall(u_handler, p_arguments, p_argument_count, r_result, r_pass, r_err); - [t_pool release]; - } - } - catch(std::exception& t_exception) - { - if (*r_result != NULL) - free(*r_result); - - *r_result = strdup(t_exception . what()); - *r_err = True; - } - catch(...) - { - if (*r_result != NULL) - free(*r_result); - - *r_result = strdup("unknown C++ exception"); - *r_err = True; - } -} - -#define EXTERNAL_DECLARE_COMMAND_OBJC(m_name, m_function) \ -{ m_name, "C", 0, ExternalWrapperObjC, NULL }, - -#define EXTERNAL_DECLARE_FUNCTION_OBJC(m_name, m_function) \ -{ m_name, "F", 0, ExternalWrapperObjC, NULL }, - -#else - - -#define EXTERNAL_DECLARE_COMMAND_OBJC(m_name, m_function) \ -{ m_name, "C", 0, ExternalWrapper, NULL }, - -#define EXTERNAL_DECLARE_FUNCTION_OBJC(m_name, m_function) \ -{ m_name, "F", 0, ExternalWrapper, NULL }, - -#endif - -#else - -#define EXTERNAL_DECLARE_COMMAND(m_name, m_function) \ -{ m_name, "C", 0, m_function, 0 }, - -#define EXTERNAL_DECLARE_FUNCTION(m_name, m_function) \ -{ m_name, "F", 0, m_function, 0 }, - -#endif - -#endif - -#define EXTERNAL_LIBINFO(m_name) \ -extern struct LibInfo __libinfo; \ -__attribute((section("__DATA,__libs"))) volatile struct LibInfo *__libinfoptr_##m_name = &__libinfo; - +#ifndef __REVOLUTION_EXTERNAL__ +#define __REVOLUTION_EXTERNAL__ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /////////////////////////////////////////////////////////////////////////////// + // + // External API declarations + // + +#define EXTERNAL_SUCCESS 0 +#define EXTERNAL_FAILURE 1 + +#ifndef Bool +#define Bool int +#define True 1 +#define False 0 +#endif + + typedef void (*ExternalHandler)(char *p_arguments[], int p_argument_count, char **r_result, Bool *r_pass, Bool *r_error); + + typedef struct _ExternalDeclaration + { + const char *name; + const char *type; + unsigned long __not_used_1; + ExternalHandler handler; + void *__not_used_2; + } ExternalDeclaration; + + typedef struct _ExternalString + { + const char *buffer; + int length; + } ExternalString; + + typedef struct _ExternalArray + { + int nelements; + ExternalString *strings; + char **keys; + } ExternalArray; + + // Function: + // SendCardMessage + // Parameters: + // p_message: const char * + // r_success: int * + // Semantics: + // Send the message to this card of this stack. The message may + // contain parameters, but these should be pre-evaluated. + // + // If the call succeeds *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void SendCardMessage(const char *p_message, int *r_success); + + // Function: + // EvalExpr + // Parameters: + // p_expression: const char * + // r_success: int * + // Returns: + // char * + // Semantics: + // Evaluate the Revolution expression in the context of the + // handler that invoked the current external command or function. + // + // The result of the evaluation will be returned as a C-string that the + // caller then takes ownership of. i.e. You need to 'free' the result of + // EvalExpr when you are finished with it. + // + // If the call succeeds *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern char *EvalExpr(const char *p_expression, int *r_success); + + // Function: + // GetGlobal + // Parameters: + // p_name: const char * + // r_success: int * + // Returns: + // char * + // Semantics: + // Return the contents of the global variable called . + // + // The contents is returned as a C-string - meaning you cannot use it to + // fetch binary data. (The data will be truncated at the first NUL + // character). + // + // The caller takes ownership of the returned C-string. i.e. You need to + // 'free' the result of GetGlobal when you are finished with it. + // + // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern char *GetGlobal(const char *p_name, int *r_success); + + // Function: + // SetGlobal + // Parameters: + // p_name: const char * + // p_value: const char * + // r_success: int * + // Semantics: + // Set the value of a global variable called to . + // + // The value must be a (NUL-terminated) C-string - meaning it is unsuitable + // to use this call to set binary data. + // + // If the variable does not exist it will be created. + // + // Revolution copies the contents of so ownership of the memory + // pointed to by it does not change. + // + // If the call succeeds *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void SetGlobal(const char *p_name, const char *p_value, int *r_success); + + // Function: + // GetVariable + // Parameters: + // p_name: const char * + // r_success: int * + // Returns: + // char * + // Semantics: + // Get the value of a variable with name that is accessible within + // the scope of the handler that invoked the external command or function. + // + // The contents is returned as a C-string - meaning you cannot use it to + // fetch binary data. (The data will be truncated at the first NUL + // character). + // + // The caller takes ownership of the returned C-string. i.e. You need to + // 'free' the result of GetGlobal when you are finished with it. + // + // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern char *GetVariable(const char *p_name, int *r_success); + + // Function: + // SetVariable + // Parameters: + // p_name: const char * + // p_value: const char * + // r_success: int * + // Semantics: + // Set the value of a variable with name that is accessible within + // the scope of the handler that invoked the external command or function to + // . + // + // The value must be a (NUL-terminated) C-string - meaning it is unsuitable + // to use this call to set binary data. + // + // Revolution copies the contents of so ownership of the memory + // pointed to by it does not change. + // + // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void SetVariable(const char *p_name, const char *p_value, int *r_success); + + // Function: + // GetVariableEx + // Parameters: + // p_name: const char * + // p_key: const char * + // r_value: ExternalString * + // r_success: int * + // Semantics: + // Get the value of a variable with name that is accessible within + // the scope of the handler that invoked the external command or function. + // + // If is the empty string ("") then the value fetched will be that + // of the variable as a non-array (i.e. if the variable is an array the + // resulting value will be empty). + // + // If is not the empty string then the value fetched will be the + // value of the element of the variable with key , or empty if + // there is no such key or the variable is not an array. + // + // The value is returned in and Revolution retains ownership of + // the memory. The pointer r_value -> buffer is only guaranteed to be valid + // until control returns to Revolution or the variable, or variable's element + // is next modified. + // + // This call is safe to use with binary and text data as an 'ExternalString' + // need not be NUL-terminated - it carries the length of the data alongside + // the pointer to the data. + // + // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void GetVariableEx(const char *p_name, const char *p_key, ExternalString *r_value, int *r_success); + + // Function: + // SetVariableEx + // Parameters: + // p_name: const char * + // p_key: const char * + // p_value: ExternalString * + // r_success: int * + // Semantics: + // Set the value of a variable with name that is accessible within + // the scope of the handler that invoked the external command or function to + // . + // + // If is the empty string (""), then the variable will be set as + // a non-array. In particular, if it was previously an array its elements + // will be deleted. + // + // If is not the empty string (""), then the element with key + // will be set to . In particular, if the variable was not previously + // an array it's value will be cleared and it will become one. Similarly, if + // the element with the given key does not exist, it will be created. + // + // Revolution copies the data referenced in and so ownership of the + // memory does not change. + // + // This call is safe to use with binary and text data as an 'ExternalString' + // need not be NUL-terminated - it carries the length of the data alongside + // the pointer to the data. + // + // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void SetVariableEx(const char *p_name, const char *p_key, const ExternalString *p_value, int *r_success); + + // Function: + // GetArray + // Parameters: + // p_name: const char * + // r_element_count: int * + // r_values: ExternalString * + // r_keys: char ** + // r_success: int * + // Semantics: + // Fetch contents of an array variable with name that is accessible + // within the scope of the handler that invoked the external command or + // function. + // + // On entry if *r_element_count is 0, *r_element_count will be updated with + // the number of elements of the array and the call will return. + // + // If *r_element_count is not 0, then r_keys must point to an array of char * + // pointers of length *r_element_count. Additionally, r_values may point to an + // array of ExternalString's of length *r_element_count. + // + // On exit, if *r_element_count is not 0, then: + // - *r_element_count will be updated with the number of entries fetched + // (min(number of elements of array, *r_element_count). + // - each entry in the r_keys array will point to a C-string of the key of + // each element fetched + // - each entry in the r_values array (if non-NULL) will point to the value + // of each element fetched + // + // The ownership of all pointers returned (both in r_keys and r_values) remains + // with Revolution. Therefore these pointers are only guaranteed to be valid + // until control returns to Revolution or the variable is next modified. + // + // This call is safe to use with binary and text data as an 'ExternalString' + // need not be NUL-terminated - it carries the length of the data alongside + // the pointer to the data. + // + // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void GetArray(const char *p_name, int *r_element_count, ExternalString *r_values, char **r_keys, int *r_success); + + // Function: + // SetArray + // Parameters: + // p_name: const char * + // p_element_count: int + // p_values: ExternalString * + // p_keys: char ** + // r_success: int * + // Semantics: + // Set the contents of an array variable with name that is accessible + // within the scope of the handler that invoked the external command or + // function to elements with keys and values . + // + // On entry, must contain the number of elements to set and + // must point to an array of ExternalString's of length + // . Additionally, may point to an array of char *'s + // of length . + // + // This call clear the contents of the named variable and then set it up as + // an array with the specified values. + // + // If is NULL, the variable will be made into an integer-keyed array, + // entry mapping to p_values[n]. + // If is non-NULL, the variable will be made into a string-keyed array, + // entry p_key[n] mapping to p_values[n]. + // + // Revolution copies all data referenced and so the ownership of any memory + // does not change. + // + // This call is safe to use with binary and text data as an 'ExternalString' + // need not be NUL-terminated - it carries the length of the data alongside + // the pointer to the data. + // + // If the variable exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void SetArray(const char *p_name, int p_element_count, ExternalString *p_values, char **p_keys, int *r_success); + + // Function: + // GetFieldBy* + // Parameters: + // p_group: const char * + // p_name: const char * + // p_index: int + // p_id: unsigned long + // r_success: int * + // Result: + // char * + // Semantics: + // These functions fetch the contents of the specified field. The field + // searched for depends on the form of the function: + // + // For Name: + // field of this card of this stack + // For Num: + // field of this card of this stack + // For Id: + // field id of this card of this stack + // + // If p_group is "true" then it has the same effect as searching for + // 'card field'. + // If p_group is "false" then it has the same effect as searching for + // 'background field"'. + // If p_group is NULL then no modifier is used. + // + // The contents is returned as a C-string - meaning you cannot use it to + // fetch binary data. (The data will be truncated at the first NUL + // character). + // + // The caller takes ownership of the returned C-string. i.e. You need to + // 'free' the result of GetGlobal when you are finished with it. + // + // If the field exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern char *GetFieldByName(const char *p_group, const char *p_name, int *r_success); + extern char *GetFieldByNum(const char *p_group, int p_index, int *r_success); + extern char *GetFieldById(const char *p_group, unsigned long p_id, int *r_success); + + // Function: + // SetFieldBy* + // Parameters: + // p_group: const char * + // p_name: const char * + // p_index: int + // p_id: unsigned long + // p_value: const char * + // r_success: int * + // Semantics: + // These functions set the contents of the specified field. The field + // searched for depends on the form of the function: + // + // For Name: + // field of this card of this stack + // For Num: + // field of this card of this stack + // For Id: + // field id of this card of this stack + // + // If p_group is "true" then it has the same effect as searching for + // 'card field'. + // If p_group is "false" then it has the same effect as searching for + // 'background field"'. + // If p_group is NULL then no modifier is used. + // + // The value must be a (NUL-terminated) C-string - meaning it is unsuitable + // to use this call to set binary data. + // + // Revolution copies the contents of so ownership of the memory + // pointed to by it does not change. + // + // If the field exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void SetFieldByName(const char *p_group, const char *p_name, const char *p_value, int *r_success); + extern void SetFieldByNum(const char *p_group, int p_index, const char *p_value, int *r_success); + extern void SetFieldById(const char *p_group, unsigned long p_id, const char *p_value, int *r_success); + + // Function: + // ShowImageBy* + // Parameters: + // p_group: const char * + // p_name: const char * + // p_index: int + // p_id: unsigned long + // r_success: int * + // Semantics: + // These functions cause the specified image to be redrawn. The image + // searched for depends on the form of the function: + // + // For Name: + // field of this card of this stack + // For Num: + // field of this card of this stack + // For Id: + // field id of this card of this stack + // + // If p_group is "true" then it has the same effect as searching for + // 'card field'. + // If p_group is "false" then it has the same effect as searching for + // 'background field"'. + // If p_group is NULL then no modifier is used. + // + // If the field exists *r_success will be EXTERNAL_SUCCESS, otherwise it + // will be EXTERNAL_FAILURE. + // + extern void ShowImageByName(const char *p_group, const char *p_name, int *r_success); + extern void ShowImageByNum(const char *p_group, int p_index, int *r_success); + extern void ShowImageById(const char *p_group, unsigned long p_id, int *r_success); + +#ifdef __cplusplus +}; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// External declaration macros +// + +#if defined(_MACOSX) || defined(_LINUX) + +#define EXTERNAL_REFERENCE_LIBRARY \ +void getXtable(void); \ +void __dummy_function(void) \ +{ \ +getXtable(); \ +} + +#else + +#define EXTERNAL_REFERENCE_LIBRARY + +#endif + + +#ifdef __cplusplus + +#define EXTERNAL_BEGIN_DECLARATIONS(m_name) \ +extern "C" { \ +EXTERNAL_REFERENCE_LIBRARY \ +const char *g_external_name = m_name; \ +ExternalDeclaration g_external_table[] = \ +{ \ + +#define EXTERNAL_END_DECLARATIONS \ +{ "", "", 0, 0, 0 } \ +}; \ +} + +#else + +#define EXTERNAL_BEGIN_DECLARATIONS(m_name) \ +EXTERNAL_REFERENCE_LIBRARY \ +const char *g_external_name = m_name; \ +ExternalDeclaration g_external_table[] = \ +{ \ + +#define EXTERNAL_END_DECLARATIONS \ +{ "", "", 0, 0, 0 } \ +}; + +#endif + +#if defined(__cplusplus) && defined(__EXCEPTIONS) + +#include +#include + +template void ExternalWrapper(char *p_arguments[], int p_argument_count, char **r_result, Bool *r_pass, Bool *r_err) +{ + *r_result = NULL; + + try + { + u_handler(p_arguments, p_argument_count, r_result, r_pass, r_err); + } + catch(std::exception& t_exception) + { + if (*r_result != NULL) + free(*r_result); + + *r_result = strdup(t_exception . what()); + *r_err = True; + } + catch(...) + { + if (*r_result != NULL) + free(*r_result); + + *r_result = strdup("unknown C++ exception"); + *r_err = True; + } +} + +#define EXTERNAL_DECLARE_COMMAND(m_name, m_function) \ +{ m_name, "C", 0, ExternalWrapper, NULL }, + +#define EXTERNAL_DECLARE_FUNCTION(m_name, m_function) \ +{ m_name, "F", 0, ExternalWrapper, NULL }, + +#else + +#define EXTERNAL_DECLARE_COMMAND(m_name, m_function) \ +{ m_name, "C", 0, m_function, 0 }, + +#define EXTERNAL_DECLARE_FUNCTION(m_name, m_function) \ +{ m_name, "F", 0, m_function, 0 }, + +#endif + +#endif + diff --git a/mergJSON/jansson b/mergJSON/jansson index dc2d54d..30a4c88 160000 --- a/mergJSON/jansson +++ b/mergJSON/jansson @@ -1 +1 @@ -Subproject commit dc2d54d9c6a6a72fd8ed0214e257a47698d20d57 +Subproject commit 30a4c88843788e2fd5155816fcc10539e277400b diff --git a/mergJSON/mergJSON.c b/mergJSON/mergJSON.c index 4676693..b4e6f73 100644 --- a/mergJSON/mergJSON.c +++ b/mergJSON/mergJSON.c @@ -24,6 +24,8 @@ */ #define LIVECODE_FUNCTION(x) void x(char *p_arguments[], int p_argument_count, char **r_result, Bool *r_pass, Bool *r_err) +// note: returning r_err=True will cause a runtime error. +// This is pretty drastic and should only be reserved for fatal errors. #define LIVECODE_ERROR(x) { *r_err = True; *r_pass = False; *r_result = strdup(x); return; } #define LIVECODE_WRITEVARIABLE(var,number) { \ From ff6cb0c68bc1a681c803484cae7d93e9081a5525 Mon Sep 17 00:00:00 2001 From: Mark Wieder Date: Tue, 8 Aug 2017 20:18:21 -0700 Subject: [PATCH 2/2] let JSONToArray handle empty argument --- mergJSON/mergJSONLibrary.livecodescript | 70 ++++++++++++++----------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/mergJSON/mergJSONLibrary.livecodescript b/mergJSON/mergJSONLibrary.livecodescript index cd3c1a9..798c511 100644 --- a/mergJSON/mergJSONLibrary.livecodescript +++ b/mergJSON/mergJSONLibrary.livecodescript @@ -4,9 +4,9 @@ on revLoadLibrary if the target is not me then pass revLoadLibrary end if - + insert the script of me into back - + if the environment contains "development" then set the _ideoverride of me to true end if @@ -16,7 +16,7 @@ on revUnloadLibrary if the target is not me then pass revUnloadLibrary end if - + remove the script of me from back end revUnloadLibrary @@ -52,7 +52,7 @@ pJSON (string): A UTF8 encoded JSON string Returns: A LiveCode array Description: -JSON arrays are translated to LiveCode numerically indexed arrays +JSON arrays are translated to LiveCode numerically indexed arrays with keys 1...N and JSON objects are translated to LiveCode array key -> value pairs. @@ -60,23 +60,27 @@ key -> value pairs. function JSONToArray pJSON local tArray,tRecurse, tKeys - - put mergJSONDecode(pJSON,"tArray") into tRecurse - if tArray is an array then - put the keys of tArray into tKeys - - split tRecurse by return as set - repeat for each line tKey in tKeys - if tRecurse[tKey] then - put JSONToArray(tArray[tKey]) into tArray[tKey] - else - put textDecode(tArray[tKey],"UTF8") into tArray[tKey] - end if - end repeat - - return tArray + + if pJSON is not empty then + put mergJSONDecode(pJSON,"tArray") into tRecurse + if tArray is an array then + put the keys of tArray into tKeys + + split tRecurse by return as set + repeat for each line tKey in tKeys + if tRecurse[tKey] then + put JSONToArray(tArray[tKey]) into tArray[tKey] + else + put textDecode(tArray[tKey],"UTF8") into tArray[tKey] + end if + end repeat + + return tArray + else + return textDecode(tArray,"UTF8") + end if else - return textDecode(tArray,"UTF8") + return empty end if end JSONToArray @@ -90,7 +94,7 @@ ask question "What do you want to send?" if it is not empty then put it into tMessage["text"] put ArrayToJSON(tMessage) into tMessage - + set the httpHeaders to "Content-type: application/json" post tMessage to url kSlackWebhookURL end if @@ -113,14 +117,18 @@ translated to JSON objects. */ function ArrayToJSON pArray,pForceRootType,pPretty - repeat for each key tKey in pArray - if pArray[tKey] is an array then - put "}"&ArrayToJSON(pArray[tKey],pForceRootType) into pArray[tKey] - else if char 1 of pArray[tKey] = "}" then - put "}}" before pArray[tKey] - else - put textEncode(pArray[tKey],"UTF8") into pArray[tKey] - end if - end repeat - return(mergJSONEncode("pArray",pForceRootType,pPretty)) + if pArray is not empty then + repeat for each key tKey in pArray + if pArray[tKey] is an array then + put "}"&ArrayToJSON(pArray[tKey],pForceRootType) into pArray[tKey] + else if char 1 of pArray[tKey] = "}" then + put "}}" before pArray[tKey] + else + put textEncode(pArray[tKey],"UTF8") into pArray[tKey] + end if + end repeat + return(mergJSONEncode("pArray",pForceRootType,pPretty)) + else + return empty + end if end ArrayToJSON