├── .gitignore ├── 3rdparty └── yajl │ ├── COPYING │ ├── Makefile │ ├── README │ ├── api │ ├── yajl_common.h │ ├── yajl_gen.h │ ├── yajl_parse.h │ ├── yajl_tree.h │ └── yajl_version.h │ ├── yajl.c │ ├── yajl_alloc.c │ ├── yajl_alloc.h │ ├── yajl_buf.c │ ├── yajl_buf.h │ ├── yajl_bytestack.h │ ├── yajl_encode.c │ ├── yajl_encode.h │ ├── yajl_gen.c │ ├── yajl_lex.c │ ├── yajl_lex.h │ ├── yajl_parser.c │ ├── yajl_parser.h │ ├── yajl_tree.c │ └── yajl_version.c ├── Makefile ├── device ├── index.xml ├── query │ └── apps ├── simulator.py └── start.sh ├── json.cpp ├── json.h ├── platforms ├── Darwin.mk ├── Linux.mk └── common.mk ├── player.cpp ├── render.h ├── renderGL.cpp ├── renderSDL2.cpp ├── renderStub.cpp └── tools └── expand.py /.gitignore: -------------------------------------------------------------------------------- 1 | .config 2 | testapp 3 | external 4 | player 5 | glplayer 6 | stubplayer 7 | build* 8 | .DS_Store 9 | *.swp 10 | *.o 11 | *.yuv 12 | -------------------------------------------------------------------------------- /3rdparty/yajl/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2014, Lloyd Hilaiel 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /3rdparty/yajl/Makefile: -------------------------------------------------------------------------------- 1 | # These should be defined in .geckopaths 2 | #GECKO_ROOT = /Volumes/fennec/gecko-desktop 3 | #GECKO_OBJ = $(GECKO_ROOT)/obj-x86_64-apple-darwin12.5.0 4 | #For Linux: 5 | #SDL_INCLUDE_PATH = path/to/sdl/header/files 6 | #SDL_LIB_PATH = path/to/sdl/libs 7 | 8 | DEPTH=../.. 9 | 10 | #include $(DEPTH)/.geckopaths 11 | PLATFORM:=$(shell uname) 12 | #include $(DEPTH)/platforms/common.mk 13 | #include $(DEPTH)/platforms/$(PLATFORM).mk 14 | 15 | BUILD_DIR=$(DEPTH)/build-$(PLATFORM) 16 | 17 | all: $(BUILD_DIR)/libyajl.a 18 | 19 | OBJECTS = \ 20 | $(BUILD_DIR)/yajl.o \ 21 | $(BUILD_DIR)/yajl_alloc.o \ 22 | $(BUILD_DIR)/yajl_buf.o \ 23 | $(BUILD_DIR)/yajl_encode.o \ 24 | $(BUILD_DIR)/yajl_gen.o \ 25 | $(BUILD_DIR)/yajl_lex.o \ 26 | $(BUILD_DIR)/yajl_parser.o \ 27 | $(BUILD_DIR)/yajl_tree.o \ 28 | $(BUILD_DIR)/yajl_version.o 29 | 30 | $(BUILD_DIR)/libyajl.a: $(OBJECTS) 31 | $(AR) cr $@ $^ 32 | 33 | $(BUILD_DIR)/%.o: %.c 34 | @mkdir -p $(BUILD_DIR) 35 | $(CC) -I. $^ -c -o $@ 36 | 37 | 38 | -------------------------------------------------------------------------------- /3rdparty/yajl/README: -------------------------------------------------------------------------------- 1 | ********************************************************************** 2 | This is YAJL 2. For the legacy version of YAJL see 3 | https://github.com/lloyd/yajl/tree/1.x 4 | ********************************************************************** 5 | 6 | Welcome to Yet Another JSON Library (YAJL) 7 | 8 | ## Why does the world need another C library for parsing JSON? 9 | 10 | Good question. In a review of current C JSON parsing libraries I was 11 | unable to find one that satisfies my requirements. Those are, 12 | 0. written in C 13 | 1. portable 14 | 2. robust -- as close to "crash proof" as possible 15 | 3. data representation independent 16 | 4. fast 17 | 5. generates verbose, useful error messages including context of where 18 | the error occurs in the input text. 19 | 6. can parse JSON data off a stream, incrementally 20 | 7. simple to use 21 | 8. tiny 22 | 23 | Numbers 3, 5, 6, and 7 were particularly hard to find, and were what 24 | caused me to ultimately create YAJL. This document is a tour of some 25 | of the more important aspects of YAJL. 26 | 27 | ## YAJL is Free. 28 | 29 | Permissive licensing means you can use it in open source and 30 | commercial products alike without any fees. My request beyond the 31 | licensing is that if you find bugs drop me a email, or better yet, 32 | fork and fix. 33 | 34 | Porting YAJL should be trivial, the implementation is ANSI C. If you 35 | port to new systems I'd love to hear of it and integrate your patches. 36 | 37 | ## YAJL is data representation independent. 38 | 39 | BYODR! Many JSON libraries impose a structure based data representation 40 | on you. This is a benefit in some cases and a drawback in others. 41 | YAJL uses callbacks to remain agnostic of the in-memory representation. 42 | So if you wish to build up an in-memory representation, you may do so 43 | using YAJL, but you must bring the code that defines and populates the 44 | in memory structure. 45 | 46 | This also means that YAJL can be used by other (higher level) JSON 47 | libraries if so desired. 48 | 49 | ## YAJL supports stream parsing 50 | 51 | This means you do not need to hold the whole JSON representation in 52 | textual form in memory. This makes YAJL ideal for filtering projects, 53 | where you're converting YAJL from one form to another (i.e. XML). The 54 | included JSON pretty printer is an example of such a filter program. 55 | 56 | ## YAJL is fast 57 | 58 | Minimal memory copying is performed. YAJL, when possible, returns 59 | pointers into the client provided text (i.e. for strings that have no 60 | embedded escape chars, hopefully the common case). I've put a lot of 61 | effort into profiling and tuning performance, but I have ignored a 62 | couple possible performance improvements to keep the interface clean, 63 | small, and flexible. My hope is that YAJL will perform comparably to 64 | the fastest JSON parser out there. 65 | 66 | YAJL should impose both minimal CPU and memory requirements on your 67 | application. 68 | 69 | ## YAJL is tiny. 70 | 71 | Fat free. No whip. 72 | 73 | enjoy, 74 | Lloyd - July, 2007 75 | -------------------------------------------------------------------------------- /3rdparty/yajl/api/yajl_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef __YAJL_COMMON_H__ 18 | #define __YAJL_COMMON_H__ 19 | 20 | #include 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #define YAJL_MAX_DEPTH 128 27 | 28 | /* msft dll export gunk. To build a DLL on windows, you 29 | * must define WIN32, YAJL_SHARED, and YAJL_BUILD. To use a shared 30 | * DLL, you must define YAJL_SHARED and WIN32 */ 31 | #if (defined(_WIN32) || defined(WIN32)) && defined(YAJL_SHARED) 32 | # ifdef YAJL_BUILD 33 | # define YAJL_API __declspec(dllexport) 34 | # else 35 | # define YAJL_API __declspec(dllimport) 36 | # endif 37 | #else 38 | # if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 39 | # define YAJL_API __attribute__ ((visibility("default"))) 40 | # else 41 | # define YAJL_API 42 | # endif 43 | #endif 44 | 45 | /** pointer to a malloc function, supporting client overriding memory 46 | * allocation routines */ 47 | typedef void * (*yajl_malloc_func)(void *ctx, size_t sz); 48 | 49 | /** pointer to a free function, supporting client overriding memory 50 | * allocation routines */ 51 | typedef void (*yajl_free_func)(void *ctx, void * ptr); 52 | 53 | /** pointer to a realloc function which can resize an allocation. */ 54 | typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz); 55 | 56 | /** A structure which can be passed to yajl_*_alloc routines to allow the 57 | * client to specify memory allocation functions to be used. */ 58 | typedef struct 59 | { 60 | /** pointer to a function that can allocate uninitialized memory */ 61 | yajl_malloc_func malloc; 62 | /** pointer to a function that can resize memory allocations */ 63 | yajl_realloc_func realloc; 64 | /** pointer to a function that can free memory allocated using 65 | * reallocFunction or mallocFunction */ 66 | yajl_free_func free; 67 | /** a context pointer that will be passed to above allocation routines */ 68 | void * ctx; 69 | } yajl_alloc_funcs; 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /3rdparty/yajl/api/yajl_gen.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /** 18 | * \file yajl_gen.h 19 | * Interface to YAJL's JSON generation facilities. 20 | */ 21 | 22 | #include 23 | 24 | #ifndef __YAJL_GEN_H__ 25 | #define __YAJL_GEN_H__ 26 | 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | /** generator status codes */ 33 | typedef enum { 34 | /** no error */ 35 | yajl_gen_status_ok = 0, 36 | /** at a point where a map key is generated, a function other than 37 | * yajl_gen_string was called */ 38 | yajl_gen_keys_must_be_strings, 39 | /** YAJL's maximum generation depth was exceeded. see 40 | * YAJL_MAX_DEPTH */ 41 | yajl_max_depth_exceeded, 42 | /** A generator function (yajl_gen_XXX) was called while in an error 43 | * state */ 44 | yajl_gen_in_error_state, 45 | /** A complete JSON document has been generated */ 46 | yajl_gen_generation_complete, 47 | /** yajl_gen_double was passed an invalid floating point value 48 | * (infinity or NaN). */ 49 | yajl_gen_invalid_number, 50 | /** A print callback was passed in, so there is no internal 51 | * buffer to get from */ 52 | yajl_gen_no_buf, 53 | /** returned from yajl_gen_string() when the yajl_gen_validate_utf8 54 | * option is enabled and an invalid was passed by client code. 55 | */ 56 | yajl_gen_invalid_string 57 | } yajl_gen_status; 58 | 59 | /** an opaque handle to a generator */ 60 | typedef struct yajl_gen_t * yajl_gen; 61 | 62 | /** a callback used for "printing" the results. */ 63 | typedef void (*yajl_print_t)(void * ctx, 64 | const char * str, 65 | size_t len); 66 | 67 | /** configuration parameters for the parser, these may be passed to 68 | * yajl_gen_config() along with option specific argument(s). In general, 69 | * all configuration parameters default to *off*. */ 70 | typedef enum { 71 | /** generate indented (beautiful) output */ 72 | yajl_gen_beautify = 0x01, 73 | /** 74 | * Set an indent string which is used when yajl_gen_beautify 75 | * is enabled. Maybe something like \\t or some number of 76 | * spaces. The default is four spaces ' '. 77 | */ 78 | yajl_gen_indent_string = 0x02, 79 | /** 80 | * Set a function and context argument that should be used to 81 | * output generated json. the function should conform to the 82 | * yajl_print_t prototype while the context argument is a 83 | * void * of your choosing. 84 | * 85 | * example: 86 | * yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr); 87 | */ 88 | yajl_gen_print_callback = 0x04, 89 | /** 90 | * Normally the generator does not validate that strings you 91 | * pass to it via yajl_gen_string() are valid UTF8. Enabling 92 | * this option will cause it to do so. 93 | */ 94 | yajl_gen_validate_utf8 = 0x08, 95 | /** 96 | * the forward solidus (slash or '/' in human) is not required to be 97 | * escaped in json text. By default, YAJL will not escape it in the 98 | * iterest of saving bytes. Setting this flag will cause YAJL to 99 | * always escape '/' in generated JSON strings. 100 | */ 101 | yajl_gen_escape_solidus = 0x10 102 | } yajl_gen_option; 103 | 104 | /** allow the modification of generator options subsequent to handle 105 | * allocation (via yajl_alloc) 106 | * \returns zero in case of errors, non-zero otherwise 107 | */ 108 | YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...); 109 | 110 | /** allocate a generator handle 111 | * \param allocFuncs an optional pointer to a structure which allows 112 | * the client to overide the memory allocation 113 | * used by yajl. May be NULL, in which case 114 | * malloc/free/realloc will be used. 115 | * 116 | * \returns an allocated handle on success, NULL on failure (bad params) 117 | */ 118 | YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs); 119 | 120 | /** free a generator handle */ 121 | YAJL_API void yajl_gen_free(yajl_gen handle); 122 | 123 | YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number); 124 | /** generate a floating point number. number may not be infinity or 125 | * NaN, as these have no representation in JSON. In these cases the 126 | * generator will return 'yajl_gen_invalid_number' */ 127 | YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number); 128 | YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand, 129 | const char * num, 130 | size_t len); 131 | YAJL_API yajl_gen_status yajl_gen_string(yajl_gen hand, 132 | const unsigned char * str, 133 | size_t len); 134 | YAJL_API yajl_gen_status yajl_gen_null(yajl_gen hand); 135 | YAJL_API yajl_gen_status yajl_gen_bool(yajl_gen hand, int boolean); 136 | YAJL_API yajl_gen_status yajl_gen_map_open(yajl_gen hand); 137 | YAJL_API yajl_gen_status yajl_gen_map_close(yajl_gen hand); 138 | YAJL_API yajl_gen_status yajl_gen_array_open(yajl_gen hand); 139 | YAJL_API yajl_gen_status yajl_gen_array_close(yajl_gen hand); 140 | 141 | /** access the null terminated generator buffer. If incrementally 142 | * outputing JSON, one should call yajl_gen_clear to clear the 143 | * buffer. This allows stream generation. */ 144 | YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand, 145 | const unsigned char ** buf, 146 | size_t * len); 147 | 148 | /** clear yajl's output buffer, but maintain all internal generation 149 | * state. This function will not "reset" the generator state, and is 150 | * intended to enable incremental JSON outputing. */ 151 | YAJL_API void yajl_gen_clear(yajl_gen hand); 152 | 153 | /** Reset the generator state. Allows a client to generate multiple 154 | * json entities in a stream. The "sep" string will be inserted to 155 | * separate the previously generated entity from the current, 156 | * NULL means *no separation* of entites (clients beware, generating 157 | * multiple JSON numbers without a separator, for instance, will result in ambiguous output) 158 | * 159 | * Note: this call will not clear yajl's output buffer. This 160 | * may be accomplished explicitly by calling yajl_gen_clear() */ 161 | YAJL_API void yajl_gen_reset(yajl_gen hand, const char * sep); 162 | 163 | #ifdef __cplusplus 164 | } 165 | #endif 166 | 167 | #endif 168 | -------------------------------------------------------------------------------- /3rdparty/yajl/api/yajl_parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /** 18 | * \file yajl_parse.h 19 | * Interface to YAJL's JSON stream parsing facilities. 20 | */ 21 | 22 | #include 23 | 24 | #ifndef __YAJL_PARSE_H__ 25 | #define __YAJL_PARSE_H__ 26 | 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | /** error codes returned from this interface */ 33 | typedef enum { 34 | /** no error was encountered */ 35 | yajl_status_ok, 36 | /** a client callback returned zero, stopping the parse */ 37 | yajl_status_client_canceled, 38 | /** An error occured during the parse. Call yajl_get_error for 39 | * more information about the encountered error */ 40 | yajl_status_error 41 | } yajl_status; 42 | 43 | /** attain a human readable, english, string for an error */ 44 | YAJL_API const char * yajl_status_to_string(yajl_status code); 45 | 46 | /** an opaque handle to a parser */ 47 | typedef struct yajl_handle_t * yajl_handle; 48 | 49 | /** yajl is an event driven parser. this means as json elements are 50 | * parsed, you are called back to do something with the data. The 51 | * functions in this table indicate the various events for which 52 | * you will be called back. Each callback accepts a "context" 53 | * pointer, this is a void * that is passed into the yajl_parse 54 | * function which the client code may use to pass around context. 55 | * 56 | * All callbacks return an integer. If non-zero, the parse will 57 | * continue. If zero, the parse will be canceled and 58 | * yajl_status_client_canceled will be returned from the parse. 59 | * 60 | * \attention { 61 | * A note about the handling of numbers: 62 | * 63 | * yajl will only convert numbers that can be represented in a 64 | * double or a 64 bit (long long) int. All other numbers will 65 | * be passed to the client in string form using the yajl_number 66 | * callback. Furthermore, if yajl_number is not NULL, it will 67 | * always be used to return numbers, that is yajl_integer and 68 | * yajl_double will be ignored. If yajl_number is NULL but one 69 | * of yajl_integer or yajl_double are defined, parsing of a 70 | * number larger than is representable in a double or 64 bit 71 | * integer will result in a parse error. 72 | * } 73 | */ 74 | typedef struct { 75 | int (* yajl_null)(void * ctx); 76 | int (* yajl_boolean)(void * ctx, int boolVal); 77 | int (* yajl_integer)(void * ctx, long long integerVal); 78 | int (* yajl_double)(void * ctx, double doubleVal); 79 | /** A callback which passes the string representation of the number 80 | * back to the client. Will be used for all numbers when present */ 81 | int (* yajl_number)(void * ctx, const char * numberVal, 82 | size_t numberLen); 83 | 84 | /** strings are returned as pointers into the JSON text when, 85 | * possible, as a result, they are _not_ null padded */ 86 | int (* yajl_string)(void * ctx, const unsigned char * stringVal, 87 | size_t stringLen); 88 | 89 | int (* yajl_start_map)(void * ctx); 90 | int (* yajl_map_key)(void * ctx, const unsigned char * key, 91 | size_t stringLen); 92 | int (* yajl_end_map)(void * ctx); 93 | 94 | int (* yajl_start_array)(void * ctx); 95 | int (* yajl_end_array)(void * ctx); 96 | } yajl_callbacks; 97 | 98 | /** allocate a parser handle 99 | * \param callbacks a yajl callbacks structure specifying the 100 | * functions to call when different JSON entities 101 | * are encountered in the input text. May be NULL, 102 | * which is only useful for validation. 103 | * \param afs memory allocation functions, may be NULL for to use 104 | * C runtime library routines (malloc and friends) 105 | * \param ctx a context pointer that will be passed to callbacks. 106 | */ 107 | YAJL_API yajl_handle yajl_alloc(const yajl_callbacks * callbacks, 108 | yajl_alloc_funcs * afs, 109 | void * ctx); 110 | 111 | 112 | /** configuration parameters for the parser, these may be passed to 113 | * yajl_config() along with option specific argument(s). In general, 114 | * all configuration parameters default to *off*. */ 115 | typedef enum { 116 | /** Ignore javascript style comments present in 117 | * JSON input. Non-standard, but rather fun 118 | * arguments: toggled off with integer zero, on otherwise. 119 | * 120 | * example: 121 | * yajl_config(h, yajl_allow_comments, 1); // turn comment support on 122 | */ 123 | yajl_allow_comments = 0x01, 124 | /** 125 | * When set the parser will verify that all strings in JSON input are 126 | * valid UTF8 and will emit a parse error if this is not so. When set, 127 | * this option makes parsing slightly more expensive (~7% depending 128 | * on processor and compiler in use) 129 | * 130 | * example: 131 | * yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking 132 | */ 133 | yajl_dont_validate_strings = 0x02, 134 | /** 135 | * By default, upon calls to yajl_complete_parse(), yajl will 136 | * ensure the entire input text was consumed and will raise an error 137 | * otherwise. Enabling this flag will cause yajl to disable this 138 | * check. This can be useful when parsing json out of a that contains more 139 | * than a single JSON document. 140 | */ 141 | yajl_allow_trailing_garbage = 0x04, 142 | /** 143 | * Allow multiple values to be parsed by a single handle. The 144 | * entire text must be valid JSON, and values can be seperated 145 | * by any kind of whitespace. This flag will change the 146 | * behavior of the parser, and cause it continue parsing after 147 | * a value is parsed, rather than transitioning into a 148 | * complete state. This option can be useful when parsing multiple 149 | * values from an input stream. 150 | */ 151 | yajl_allow_multiple_values = 0x08, 152 | /** 153 | * When yajl_complete_parse() is called the parser will 154 | * check that the top level value was completely consumed. I.E., 155 | * if called whilst in the middle of parsing a value 156 | * yajl will enter an error state (premature EOF). Setting this 157 | * flag suppresses that check and the corresponding error. 158 | */ 159 | yajl_allow_partial_values = 0x10 160 | } yajl_option; 161 | 162 | /** allow the modification of parser options subsequent to handle 163 | * allocation (via yajl_alloc) 164 | * \returns zero in case of errors, non-zero otherwise 165 | */ 166 | YAJL_API int yajl_config(yajl_handle h, yajl_option opt, ...); 167 | 168 | /** free a parser handle */ 169 | YAJL_API void yajl_free(yajl_handle handle); 170 | 171 | /** Parse some json! 172 | * \param hand - a handle to the json parser allocated with yajl_alloc 173 | * \param jsonText - a pointer to the UTF8 json text to be parsed 174 | * \param jsonTextLength - the length, in bytes, of input text 175 | */ 176 | YAJL_API yajl_status yajl_parse(yajl_handle hand, 177 | const unsigned char * jsonText, 178 | size_t jsonTextLength); 179 | 180 | /** Parse any remaining buffered json. 181 | * Since yajl is a stream-based parser, without an explicit end of 182 | * input, yajl sometimes can't decide if content at the end of the 183 | * stream is valid or not. For example, if "1" has been fed in, 184 | * yajl can't know whether another digit is next or some character 185 | * that would terminate the integer token. 186 | * 187 | * \param hand - a handle to the json parser allocated with yajl_alloc 188 | */ 189 | YAJL_API yajl_status yajl_complete_parse(yajl_handle hand); 190 | 191 | /** get an error string describing the state of the 192 | * parse. 193 | * 194 | * If verbose is non-zero, the message will include the JSON 195 | * text where the error occured, along with an arrow pointing to 196 | * the specific char. 197 | * 198 | * \returns A dynamically allocated string will be returned which should 199 | * be freed with yajl_free_error 200 | */ 201 | YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose, 202 | const unsigned char * jsonText, 203 | size_t jsonTextLength); 204 | 205 | /** 206 | * get the amount of data consumed from the last chunk passed to YAJL. 207 | * 208 | * In the case of a successful parse this can help you understand if 209 | * the entire buffer was consumed (which will allow you to handle 210 | * "junk at end of input"). 211 | * 212 | * In the event an error is encountered during parsing, this function 213 | * affords the client a way to get the offset into the most recent 214 | * chunk where the error occured. 0 will be returned if no error 215 | * was encountered. 216 | */ 217 | YAJL_API size_t yajl_get_bytes_consumed(yajl_handle hand); 218 | 219 | /** free an error returned from yajl_get_error */ 220 | YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str); 221 | 222 | #ifdef __cplusplus 223 | } 224 | #endif 225 | 226 | #endif 227 | -------------------------------------------------------------------------------- /3rdparty/yajl/api/yajl_tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2011 Florian Forster 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /** 18 | * \file yajl_tree.h 19 | * 20 | * Parses JSON data and returns the data in tree form. 21 | * 22 | * \author Florian Forster 23 | * \date August 2010 24 | * 25 | * This interface makes quick parsing and extraction of 26 | * smallish JSON docs trivial: 27 | * 28 | * \include example/parse_config.c 29 | */ 30 | 31 | #ifndef YAJL_TREE_H 32 | #define YAJL_TREE_H 1 33 | 34 | #include 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /** possible data types that a yajl_val_s can hold */ 41 | typedef enum { 42 | yajl_t_string = 1, 43 | yajl_t_number = 2, 44 | yajl_t_object = 3, 45 | yajl_t_array = 4, 46 | yajl_t_true = 5, 47 | yajl_t_false = 6, 48 | yajl_t_null = 7, 49 | /** The any type isn't valid for yajl_val_s.type, but can be 50 | * used as an argument to routines like yajl_tree_get(). 51 | */ 52 | yajl_t_any = 8 53 | } yajl_type; 54 | 55 | #define YAJL_NUMBER_INT_VALID 0x01 56 | #define YAJL_NUMBER_DOUBLE_VALID 0x02 57 | 58 | /** A pointer to a node in the parse tree */ 59 | typedef struct yajl_val_s * yajl_val; 60 | 61 | /** 62 | * A JSON value representation capable of holding one of the seven 63 | * types above. For "string", "number", "object", and "array" 64 | * additional data is available in the union. The "YAJL_IS_*" 65 | * and "YAJL_GET_*" macros below allow type checking and convenient 66 | * value extraction. 67 | */ 68 | struct yajl_val_s 69 | { 70 | /** Type of the value contained. Use the "YAJL_IS_*" macros to check for a 71 | * specific type. */ 72 | yajl_type type; 73 | /** Type-specific data. You may use the "YAJL_GET_*" macros to access these 74 | * members. */ 75 | union 76 | { 77 | char * string; 78 | struct { 79 | long long i; /*< integer value, if representable. */ 80 | double d; /*< double value, if representable. */ 81 | char *r; /*< unparsed number in string form. */ 82 | /** Signals whether the \em i and \em d members are 83 | * valid. See \c YAJL_NUMBER_INT_VALID and 84 | * \c YAJL_NUMBER_DOUBLE_VALID. */ 85 | unsigned int flags; 86 | } number; 87 | struct { 88 | const char **keys; /*< Array of keys */ 89 | yajl_val *values; /*< Array of values. */ 90 | size_t len; /*< Number of key-value-pairs. */ 91 | } object; 92 | struct { 93 | yajl_val *values; /*< Array of elements. */ 94 | size_t len; /*< Number of elements. */ 95 | } array; 96 | } u; 97 | }; 98 | 99 | /** 100 | * Parse a string. 101 | * 102 | * Parses an null-terminated string containing JSON data and returns a pointer 103 | * to the top-level value (root of the parse tree). 104 | * 105 | * \param input Pointer to a null-terminated utf8 string containing 106 | * JSON data. 107 | * \param error_buffer Pointer to a buffer in which an error message will 108 | * be stored if \em yajl_tree_parse fails, or 109 | * \c NULL. The buffer will be initialized before 110 | * parsing, so its content will be destroyed even if 111 | * \em yajl_tree_parse succeeds. 112 | * \param error_buffer_size Size of the memory area pointed to by 113 | * \em error_buffer_size. If \em error_buffer_size is 114 | * \c NULL, this argument is ignored. 115 | * 116 | * \returns Pointer to the top-level value or \c NULL on error. The memory 117 | * pointed to must be freed using \em yajl_tree_free. In case of an error, a 118 | * null terminated message describing the error in more detail is stored in 119 | * \em error_buffer if it is not \c NULL. 120 | */ 121 | YAJL_API yajl_val yajl_tree_parse (const char *input, 122 | char *error_buffer, size_t error_buffer_size); 123 | 124 | 125 | /** 126 | * Free a parse tree returned by "yajl_tree_parse". 127 | * 128 | * \param v Pointer to a JSON value returned by "yajl_tree_parse". Passing NULL 129 | * is valid and results in a no-op. 130 | */ 131 | YAJL_API void yajl_tree_free (yajl_val v); 132 | 133 | /** 134 | * Access a nested value inside a tree. 135 | * 136 | * \param parent the node under which you'd like to extract values. 137 | * \param path A null terminated array of strings, each the name of an object key 138 | * \param type the yajl_type of the object you seek, or yajl_t_any if any will do. 139 | * 140 | * \returns a pointer to the found value, or NULL if we came up empty. 141 | * 142 | * Future Ideas: it'd be nice to move path to a string and implement support for 143 | * a teeny tiny micro language here, so you can extract array elements, do things 144 | * like .first and .last, even .length. Inspiration from JSONPath and css selectors? 145 | * No it wouldn't be fast, but that's not what this API is about. 146 | */ 147 | YAJL_API yajl_val yajl_tree_get(yajl_val parent, const char ** path, yajl_type type); 148 | 149 | /* Various convenience macros to check the type of a `yajl_val` */ 150 | #define YAJL_IS_STRING(v) (((v) != NULL) && ((v)->type == yajl_t_string)) 151 | #define YAJL_IS_NUMBER(v) (((v) != NULL) && ((v)->type == yajl_t_number)) 152 | #define YAJL_IS_INTEGER(v) (YAJL_IS_NUMBER(v) && ((v)->u.number.flags & YAJL_NUMBER_INT_VALID)) 153 | #define YAJL_IS_DOUBLE(v) (YAJL_IS_NUMBER(v) && ((v)->u.number.flags & YAJL_NUMBER_DOUBLE_VALID)) 154 | #define YAJL_IS_OBJECT(v) (((v) != NULL) && ((v)->type == yajl_t_object)) 155 | #define YAJL_IS_ARRAY(v) (((v) != NULL) && ((v)->type == yajl_t_array )) 156 | #define YAJL_IS_TRUE(v) (((v) != NULL) && ((v)->type == yajl_t_true )) 157 | #define YAJL_IS_FALSE(v) (((v) != NULL) && ((v)->type == yajl_t_false )) 158 | #define YAJL_IS_NULL(v) (((v) != NULL) && ((v)->type == yajl_t_null )) 159 | 160 | /** Given a yajl_val_string return a ptr to the bare string it contains, 161 | * or NULL if the value is not a string. */ 162 | #define YAJL_GET_STRING(v) (YAJL_IS_STRING(v) ? (v)->u.string : NULL) 163 | 164 | /** Get the string representation of a number. You should check type first, 165 | * perhaps using YAJL_IS_NUMBER */ 166 | #define YAJL_GET_NUMBER(v) ((v)->u.number.r) 167 | 168 | /** Get the double representation of a number. You should check type first, 169 | * perhaps using YAJL_IS_DOUBLE */ 170 | #define YAJL_GET_DOUBLE(v) ((v)->u.number.d) 171 | 172 | /** Get the 64bit (long long) integer representation of a number. You should 173 | * check type first, perhaps using YAJL_IS_INTEGER */ 174 | #define YAJL_GET_INTEGER(v) ((v)->u.number.i) 175 | 176 | /** Get a pointer to a yajl_val_object or NULL if the value is not an object. */ 177 | #define YAJL_GET_OBJECT(v) (YAJL_IS_OBJECT(v) ? &(v)->u.object : NULL) 178 | 179 | /** Get a pointer to a yajl_val_array or NULL if the value is not an object. */ 180 | #define YAJL_GET_ARRAY(v) (YAJL_IS_ARRAY(v) ? &(v)->u.array : NULL) 181 | 182 | #ifdef __cplusplus 183 | } 184 | #endif 185 | 186 | #endif /* YAJL_TREE_H */ 187 | -------------------------------------------------------------------------------- /3rdparty/yajl/api/yajl_version.h: -------------------------------------------------------------------------------- 1 | #ifndef YAJL_VERSION_H_ 2 | #define YAJL_VERSION_H_ 3 | 4 | #include 5 | 6 | #define YAJL_MAJOR 2 7 | #define YAJL_MINOR 1 8 | #define YAJL_MICRO 1 9 | 10 | #define YAJL_VERSION ((YAJL_MAJOR * 10000) + (YAJL_MINOR * 100) + YAJL_MICRO) 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | extern int YAJL_API yajl_version(void); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif /* YAJL_VERSION_H_ */ 23 | 24 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "api/yajl_parse.h" 18 | #include "yajl_lex.h" 19 | #include "yajl_parser.h" 20 | #include "yajl_alloc.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | const char * 28 | yajl_status_to_string(yajl_status stat) 29 | { 30 | const char * statStr = "unknown"; 31 | switch (stat) { 32 | case yajl_status_ok: 33 | statStr = "ok, no error"; 34 | break; 35 | case yajl_status_client_canceled: 36 | statStr = "client canceled parse"; 37 | break; 38 | case yajl_status_error: 39 | statStr = "parse error"; 40 | break; 41 | } 42 | return statStr; 43 | } 44 | 45 | yajl_handle 46 | yajl_alloc(const yajl_callbacks * callbacks, 47 | yajl_alloc_funcs * afs, 48 | void * ctx) 49 | { 50 | yajl_handle hand = NULL; 51 | yajl_alloc_funcs afsBuffer; 52 | 53 | /* first order of business is to set up memory allocation routines */ 54 | if (afs != NULL) { 55 | if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL) 56 | { 57 | return NULL; 58 | } 59 | } else { 60 | yajl_set_default_alloc_funcs(&afsBuffer); 61 | afs = &afsBuffer; 62 | } 63 | 64 | hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t)); 65 | 66 | /* copy in pointers to allocation routines */ 67 | memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs)); 68 | 69 | hand->callbacks = callbacks; 70 | hand->ctx = ctx; 71 | hand->lexer = NULL; 72 | hand->bytesConsumed = 0; 73 | hand->decodeBuf = yajl_buf_alloc(&(hand->alloc)); 74 | hand->flags = 0; 75 | yajl_bs_init(hand->stateStack, &(hand->alloc)); 76 | yajl_bs_push(hand->stateStack, yajl_state_start); 77 | 78 | return hand; 79 | } 80 | 81 | int 82 | yajl_config(yajl_handle h, yajl_option opt, ...) 83 | { 84 | int rv = 1; 85 | va_list ap; 86 | va_start(ap, opt); 87 | 88 | switch(opt) { 89 | case yajl_allow_comments: 90 | case yajl_dont_validate_strings: 91 | case yajl_allow_trailing_garbage: 92 | case yajl_allow_multiple_values: 93 | case yajl_allow_partial_values: 94 | if (va_arg(ap, int)) h->flags |= opt; 95 | else h->flags &= ~opt; 96 | break; 97 | default: 98 | rv = 0; 99 | } 100 | va_end(ap); 101 | 102 | return rv; 103 | } 104 | 105 | void 106 | yajl_free(yajl_handle handle) 107 | { 108 | yajl_bs_free(handle->stateStack); 109 | yajl_buf_free(handle->decodeBuf); 110 | if (handle->lexer) { 111 | yajl_lex_free(handle->lexer); 112 | handle->lexer = NULL; 113 | } 114 | YA_FREE(&(handle->alloc), handle); 115 | } 116 | 117 | yajl_status 118 | yajl_parse(yajl_handle hand, const unsigned char * jsonText, 119 | size_t jsonTextLen) 120 | { 121 | yajl_status status; 122 | 123 | /* lazy allocation of the lexer */ 124 | if (hand->lexer == NULL) { 125 | hand->lexer = yajl_lex_alloc(&(hand->alloc), 126 | hand->flags & yajl_allow_comments, 127 | !(hand->flags & yajl_dont_validate_strings)); 128 | } 129 | 130 | status = yajl_do_parse(hand, jsonText, jsonTextLen); 131 | return status; 132 | } 133 | 134 | 135 | yajl_status 136 | yajl_complete_parse(yajl_handle hand) 137 | { 138 | /* The lexer is lazy allocated in the first call to parse. if parse is 139 | * never called, then no data was provided to parse at all. This is a 140 | * "premature EOF" error unless yajl_allow_partial_values is specified. 141 | * allocating the lexer now is the simplest possible way to handle this 142 | * case while preserving all the other semantics of the parser 143 | * (multiple values, partial values, etc). */ 144 | if (hand->lexer == NULL) { 145 | hand->lexer = yajl_lex_alloc(&(hand->alloc), 146 | hand->flags & yajl_allow_comments, 147 | !(hand->flags & yajl_dont_validate_strings)); 148 | } 149 | 150 | return yajl_do_finish(hand); 151 | } 152 | 153 | unsigned char * 154 | yajl_get_error(yajl_handle hand, int verbose, 155 | const unsigned char * jsonText, size_t jsonTextLen) 156 | { 157 | return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose); 158 | } 159 | 160 | size_t 161 | yajl_get_bytes_consumed(yajl_handle hand) 162 | { 163 | if (!hand) return 0; 164 | else return hand->bytesConsumed; 165 | } 166 | 167 | 168 | void 169 | yajl_free_error(yajl_handle hand, unsigned char * str) 170 | { 171 | /* use memory allocation functions if set */ 172 | YA_FREE(&(hand->alloc), str); 173 | } 174 | 175 | /* XXX: add utility routines to parse from file */ 176 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_alloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /** 18 | * \file yajl_alloc.h 19 | * default memory allocation routines for yajl which use malloc/realloc and 20 | * free 21 | */ 22 | 23 | #include "yajl_alloc.h" 24 | #include 25 | 26 | static void * yajl_internal_malloc(void *ctx, size_t sz) 27 | { 28 | (void)ctx; 29 | return malloc(sz); 30 | } 31 | 32 | static void * yajl_internal_realloc(void *ctx, void * previous, 33 | size_t sz) 34 | { 35 | (void)ctx; 36 | return realloc(previous, sz); 37 | } 38 | 39 | static void yajl_internal_free(void *ctx, void * ptr) 40 | { 41 | (void)ctx; 42 | free(ptr); 43 | } 44 | 45 | void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf) 46 | { 47 | yaf->malloc = yajl_internal_malloc; 48 | yaf->free = yajl_internal_free; 49 | yaf->realloc = yajl_internal_realloc; 50 | yaf->ctx = NULL; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_alloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /** 18 | * \file yajl_alloc.h 19 | * default memory allocation routines for yajl which use malloc/realloc and 20 | * free 21 | */ 22 | 23 | #ifndef __YAJL_ALLOC_H__ 24 | #define __YAJL_ALLOC_H__ 25 | 26 | #include "api/yajl_common.h" 27 | 28 | #define YA_MALLOC(afs, sz) (afs)->malloc((afs)->ctx, (sz)) 29 | #define YA_FREE(afs, ptr) (afs)->free((afs)->ctx, (ptr)) 30 | #define YA_REALLOC(afs, ptr, sz) (afs)->realloc((afs)->ctx, (ptr), (sz)) 31 | 32 | void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_buf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "yajl_buf.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define YAJL_BUF_INIT_SIZE 2048 24 | 25 | struct yajl_buf_t { 26 | size_t len; 27 | size_t used; 28 | unsigned char * data; 29 | yajl_alloc_funcs * alloc; 30 | }; 31 | 32 | static 33 | void yajl_buf_ensure_available(yajl_buf buf, size_t want) 34 | { 35 | size_t need; 36 | 37 | assert(buf != NULL); 38 | 39 | /* first call */ 40 | if (buf->data == NULL) { 41 | buf->len = YAJL_BUF_INIT_SIZE; 42 | buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len); 43 | buf->data[0] = 0; 44 | } 45 | 46 | need = buf->len; 47 | 48 | while (want >= (need - buf->used)) need <<= 1; 49 | 50 | if (need != buf->len) { 51 | buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need); 52 | buf->len = need; 53 | } 54 | } 55 | 56 | yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc) 57 | { 58 | yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t)); 59 | memset((void *) b, 0, sizeof(struct yajl_buf_t)); 60 | b->alloc = alloc; 61 | return b; 62 | } 63 | 64 | void yajl_buf_free(yajl_buf buf) 65 | { 66 | assert(buf != NULL); 67 | if (buf->data) YA_FREE(buf->alloc, buf->data); 68 | YA_FREE(buf->alloc, buf); 69 | } 70 | 71 | void yajl_buf_append(yajl_buf buf, const void * data, size_t len) 72 | { 73 | yajl_buf_ensure_available(buf, len); 74 | if (len > 0) { 75 | assert(data != NULL); 76 | memcpy(buf->data + buf->used, data, len); 77 | buf->used += len; 78 | buf->data[buf->used] = 0; 79 | } 80 | } 81 | 82 | void yajl_buf_clear(yajl_buf buf) 83 | { 84 | buf->used = 0; 85 | if (buf->data) buf->data[buf->used] = 0; 86 | } 87 | 88 | const unsigned char * yajl_buf_data(yajl_buf buf) 89 | { 90 | return buf->data; 91 | } 92 | 93 | size_t yajl_buf_len(yajl_buf buf) 94 | { 95 | return buf->used; 96 | } 97 | 98 | void 99 | yajl_buf_truncate(yajl_buf buf, size_t len) 100 | { 101 | assert(len <= buf->used); 102 | buf->used = len; 103 | } 104 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_buf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef __YAJL_BUF_H__ 18 | #define __YAJL_BUF_H__ 19 | 20 | #include "api/yajl_common.h" 21 | #include "yajl_alloc.h" 22 | 23 | /* 24 | * Implementation/performance notes. If this were moved to a header 25 | * only implementation using #define's where possible we might be 26 | * able to sqeeze a little performance out of the guy by killing function 27 | * call overhead. YMMV. 28 | */ 29 | 30 | /** 31 | * yajl_buf is a buffer with exponential growth. the buffer ensures that 32 | * you are always null padded. 33 | */ 34 | typedef struct yajl_buf_t * yajl_buf; 35 | 36 | /* allocate a new buffer */ 37 | yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc); 38 | 39 | /* free the buffer */ 40 | void yajl_buf_free(yajl_buf buf); 41 | 42 | /* append a number of bytes to the buffer */ 43 | void yajl_buf_append(yajl_buf buf, const void * data, size_t len); 44 | 45 | /* empty the buffer */ 46 | void yajl_buf_clear(yajl_buf buf); 47 | 48 | /* get a pointer to the beginning of the buffer */ 49 | const unsigned char * yajl_buf_data(yajl_buf buf); 50 | 51 | /* get the length of the buffer */ 52 | size_t yajl_buf_len(yajl_buf buf); 53 | 54 | /* truncate the buffer */ 55 | void yajl_buf_truncate(yajl_buf buf, size_t len); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_bytestack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /* 18 | * A header only implementation of a simple stack of bytes, used in YAJL 19 | * to maintain parse state. 20 | */ 21 | 22 | #ifndef __YAJL_BYTESTACK_H__ 23 | #define __YAJL_BYTESTACK_H__ 24 | 25 | #include "api/yajl_common.h" 26 | 27 | #define YAJL_BS_INC 128 28 | 29 | typedef struct yajl_bytestack_t 30 | { 31 | unsigned char * stack; 32 | size_t size; 33 | size_t used; 34 | yajl_alloc_funcs * yaf; 35 | } yajl_bytestack; 36 | 37 | /* initialize a bytestack */ 38 | #define yajl_bs_init(obs, _yaf) { \ 39 | (obs).stack = NULL; \ 40 | (obs).size = 0; \ 41 | (obs).used = 0; \ 42 | (obs).yaf = (_yaf); \ 43 | } \ 44 | 45 | 46 | /* initialize a bytestack */ 47 | #define yajl_bs_free(obs) \ 48 | if ((obs).stack) (obs).yaf->free((obs).yaf->ctx, (obs).stack); 49 | 50 | #define yajl_bs_current(obs) \ 51 | (assert((obs).used > 0), (obs).stack[(obs).used - 1]) 52 | 53 | #define yajl_bs_push(obs, byte) { \ 54 | if (((obs).size - (obs).used) == 0) { \ 55 | (obs).size += YAJL_BS_INC; \ 56 | (obs).stack = (obs).yaf->realloc((obs).yaf->ctx,\ 57 | (void *) (obs).stack, (obs).size);\ 58 | } \ 59 | (obs).stack[((obs).used)++] = (byte); \ 60 | } 61 | 62 | /* removes the top item of the stack, returns nothing */ 63 | #define yajl_bs_pop(obs) { ((obs).used)--; } 64 | 65 | #define yajl_bs_set(obs, byte) \ 66 | (obs).stack[((obs).used) - 1] = (byte); 67 | 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_encode.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "yajl_encode.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | static void CharToHex(unsigned char c, char * hexBuf) 25 | { 26 | const char * hexchar = "0123456789ABCDEF"; 27 | hexBuf[0] = hexchar[c >> 4]; 28 | hexBuf[1] = hexchar[c & 0x0F]; 29 | } 30 | 31 | void 32 | yajl_string_encode(const yajl_print_t print, 33 | void * ctx, 34 | const unsigned char * str, 35 | size_t len, 36 | int escape_solidus) 37 | { 38 | size_t beg = 0; 39 | size_t end = 0; 40 | char hexBuf[7]; 41 | hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0'; 42 | hexBuf[6] = 0; 43 | 44 | while (end < len) { 45 | const char * escaped = NULL; 46 | switch (str[end]) { 47 | case '\r': escaped = "\\r"; break; 48 | case '\n': escaped = "\\n"; break; 49 | case '\\': escaped = "\\\\"; break; 50 | /* it is not required to escape a solidus in JSON: 51 | * read sec. 2.5: http://www.ietf.org/rfc/rfc4627.txt 52 | * specifically, this production from the grammar: 53 | * unescaped = %x20-21 / %x23-5B / %x5D-10FFFF 54 | */ 55 | case '/': if (escape_solidus) escaped = "\\/"; break; 56 | case '"': escaped = "\\\""; break; 57 | case '\f': escaped = "\\f"; break; 58 | case '\b': escaped = "\\b"; break; 59 | case '\t': escaped = "\\t"; break; 60 | default: 61 | if ((unsigned char) str[end] < 32) { 62 | CharToHex(str[end], hexBuf + 4); 63 | escaped = hexBuf; 64 | } 65 | break; 66 | } 67 | if (escaped != NULL) { 68 | print(ctx, (const char *) (str + beg), end - beg); 69 | print(ctx, escaped, (unsigned int)strlen(escaped)); 70 | beg = ++end; 71 | } else { 72 | ++end; 73 | } 74 | } 75 | print(ctx, (const char *) (str + beg), end - beg); 76 | } 77 | 78 | static void hexToDigit(unsigned int * val, const unsigned char * hex) 79 | { 80 | unsigned int i; 81 | for (i=0;i<4;i++) { 82 | unsigned char c = hex[i]; 83 | if (c >= 'A') c = (c & ~0x20) - 7; 84 | c -= '0'; 85 | assert(!(c & 0xF0)); 86 | *val = (*val << 4) | c; 87 | } 88 | } 89 | 90 | static void Utf32toUtf8(unsigned int codepoint, char * utf8Buf) 91 | { 92 | if (codepoint < 0x80) { 93 | utf8Buf[0] = (char) codepoint; 94 | utf8Buf[1] = 0; 95 | } else if (codepoint < 0x0800) { 96 | utf8Buf[0] = (char) ((codepoint >> 6) | 0xC0); 97 | utf8Buf[1] = (char) ((codepoint & 0x3F) | 0x80); 98 | utf8Buf[2] = 0; 99 | } else if (codepoint < 0x10000) { 100 | utf8Buf[0] = (char) ((codepoint >> 12) | 0xE0); 101 | utf8Buf[1] = (char) (((codepoint >> 6) & 0x3F) | 0x80); 102 | utf8Buf[2] = (char) ((codepoint & 0x3F) | 0x80); 103 | utf8Buf[3] = 0; 104 | } else if (codepoint < 0x200000) { 105 | utf8Buf[0] =(char)((codepoint >> 18) | 0xF0); 106 | utf8Buf[1] =(char)(((codepoint >> 12) & 0x3F) | 0x80); 107 | utf8Buf[2] =(char)(((codepoint >> 6) & 0x3F) | 0x80); 108 | utf8Buf[3] =(char)((codepoint & 0x3F) | 0x80); 109 | utf8Buf[4] = 0; 110 | } else { 111 | utf8Buf[0] = '?'; 112 | utf8Buf[1] = 0; 113 | } 114 | } 115 | 116 | void yajl_string_decode(yajl_buf buf, const unsigned char * str, 117 | size_t len) 118 | { 119 | size_t beg = 0; 120 | size_t end = 0; 121 | 122 | while (end < len) { 123 | if (str[end] == '\\') { 124 | char utf8Buf[5]; 125 | const char * unescaped = "?"; 126 | yajl_buf_append(buf, str + beg, end - beg); 127 | switch (str[++end]) { 128 | case 'r': unescaped = "\r"; break; 129 | case 'n': unescaped = "\n"; break; 130 | case '\\': unescaped = "\\"; break; 131 | case '/': unescaped = "/"; break; 132 | case '"': unescaped = "\""; break; 133 | case 'f': unescaped = "\f"; break; 134 | case 'b': unescaped = "\b"; break; 135 | case 't': unescaped = "\t"; break; 136 | case 'u': { 137 | unsigned int codepoint = 0; 138 | hexToDigit(&codepoint, str + ++end); 139 | end+=3; 140 | /* check if this is a surrogate */ 141 | if ((codepoint & 0xFC00) == 0xD800) { 142 | end++; 143 | if (str[end] == '\\' && str[end + 1] == 'u') { 144 | unsigned int surrogate = 0; 145 | hexToDigit(&surrogate, str + end + 2); 146 | codepoint = 147 | (((codepoint & 0x3F) << 10) | 148 | ((((codepoint >> 6) & 0xF) + 1) << 16) | 149 | (surrogate & 0x3FF)); 150 | end += 5; 151 | } else { 152 | unescaped = "?"; 153 | break; 154 | } 155 | } 156 | 157 | Utf32toUtf8(codepoint, utf8Buf); 158 | unescaped = utf8Buf; 159 | 160 | if (codepoint == 0) { 161 | yajl_buf_append(buf, unescaped, 1); 162 | beg = ++end; 163 | continue; 164 | } 165 | 166 | break; 167 | } 168 | default: 169 | assert("this should never happen" == NULL); 170 | } 171 | yajl_buf_append(buf, unescaped, (unsigned int)strlen(unescaped)); 172 | beg = ++end; 173 | } else { 174 | end++; 175 | } 176 | } 177 | yajl_buf_append(buf, str + beg, end - beg); 178 | } 179 | 180 | #define ADV_PTR s++; if (!(len--)) return 0; 181 | 182 | int yajl_string_validate_utf8(const unsigned char * s, size_t len) 183 | { 184 | if (!len) return 1; 185 | if (!s) return 0; 186 | 187 | while (len--) { 188 | /* single byte */ 189 | if (*s <= 0x7f) { 190 | /* noop */ 191 | } 192 | /* two byte */ 193 | else if ((*s >> 5) == 0x6) { 194 | ADV_PTR; 195 | if (!((*s >> 6) == 0x2)) return 0; 196 | } 197 | /* three byte */ 198 | else if ((*s >> 4) == 0x0e) { 199 | ADV_PTR; 200 | if (!((*s >> 6) == 0x2)) return 0; 201 | ADV_PTR; 202 | if (!((*s >> 6) == 0x2)) return 0; 203 | } 204 | /* four byte */ 205 | else if ((*s >> 3) == 0x1e) { 206 | ADV_PTR; 207 | if (!((*s >> 6) == 0x2)) return 0; 208 | ADV_PTR; 209 | if (!((*s >> 6) == 0x2)) return 0; 210 | ADV_PTR; 211 | if (!((*s >> 6) == 0x2)) return 0; 212 | } else { 213 | return 0; 214 | } 215 | 216 | s++; 217 | } 218 | 219 | return 1; 220 | } 221 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_encode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef __YAJL_ENCODE_H__ 18 | #define __YAJL_ENCODE_H__ 19 | 20 | #include "yajl_buf.h" 21 | #include "api/yajl_gen.h" 22 | 23 | void yajl_string_encode(const yajl_print_t printer, 24 | void * ctx, 25 | const unsigned char * str, 26 | size_t length, 27 | int escape_solidus); 28 | 29 | void yajl_string_decode(yajl_buf buf, const unsigned char * str, 30 | size_t length); 31 | 32 | int yajl_string_validate_utf8(const unsigned char * s, size_t len); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_gen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "api/yajl_gen.h" 18 | #include "yajl_buf.h" 19 | #include "yajl_encode.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | typedef enum { 28 | yajl_gen_start, 29 | yajl_gen_map_start, 30 | yajl_gen_map_key, 31 | yajl_gen_map_val, 32 | yajl_gen_array_start, 33 | yajl_gen_in_array, 34 | yajl_gen_complete, 35 | yajl_gen_error 36 | } yajl_gen_state; 37 | 38 | struct yajl_gen_t 39 | { 40 | unsigned int flags; 41 | unsigned int depth; 42 | const char * indentString; 43 | yajl_gen_state state[YAJL_MAX_DEPTH]; 44 | yajl_print_t print; 45 | void * ctx; /* yajl_buf */ 46 | /* memory allocation routines */ 47 | yajl_alloc_funcs alloc; 48 | }; 49 | 50 | int 51 | yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...) 52 | { 53 | int rv = 1; 54 | va_list ap; 55 | va_start(ap, opt); 56 | 57 | switch(opt) { 58 | case yajl_gen_beautify: 59 | case yajl_gen_validate_utf8: 60 | case yajl_gen_escape_solidus: 61 | if (va_arg(ap, int)) g->flags |= opt; 62 | else g->flags &= ~opt; 63 | break; 64 | case yajl_gen_indent_string: { 65 | const char *indent = va_arg(ap, const char *); 66 | g->indentString = indent; 67 | for (; *indent; indent++) { 68 | if (*indent != '\n' 69 | && *indent != '\v' 70 | && *indent != '\f' 71 | && *indent != '\t' 72 | && *indent != '\r' 73 | && *indent != ' ') 74 | { 75 | g->indentString = NULL; 76 | rv = 0; 77 | } 78 | } 79 | break; 80 | } 81 | case yajl_gen_print_callback: 82 | yajl_buf_free(g->ctx); 83 | g->print = va_arg(ap, const yajl_print_t); 84 | g->ctx = va_arg(ap, void *); 85 | break; 86 | default: 87 | rv = 0; 88 | } 89 | 90 | va_end(ap); 91 | 92 | return rv; 93 | } 94 | 95 | 96 | 97 | yajl_gen 98 | yajl_gen_alloc(const yajl_alloc_funcs * afs) 99 | { 100 | yajl_gen g = NULL; 101 | yajl_alloc_funcs afsBuffer; 102 | 103 | /* first order of business is to set up memory allocation routines */ 104 | if (afs != NULL) { 105 | if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL) 106 | { 107 | return NULL; 108 | } 109 | } else { 110 | yajl_set_default_alloc_funcs(&afsBuffer); 111 | afs = &afsBuffer; 112 | } 113 | 114 | g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t)); 115 | if (!g) return NULL; 116 | 117 | memset((void *) g, 0, sizeof(struct yajl_gen_t)); 118 | /* copy in pointers to allocation routines */ 119 | memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs)); 120 | 121 | g->print = (yajl_print_t)&yajl_buf_append; 122 | g->ctx = yajl_buf_alloc(&(g->alloc)); 123 | g->indentString = " "; 124 | 125 | return g; 126 | } 127 | 128 | void 129 | yajl_gen_reset(yajl_gen g, const char * sep) 130 | { 131 | g->depth = 0; 132 | memset((void *) &(g->state), 0, sizeof(g->state)); 133 | if (sep != NULL) g->print(g->ctx, sep, strlen(sep)); 134 | } 135 | 136 | void 137 | yajl_gen_free(yajl_gen g) 138 | { 139 | if (g->print == (yajl_print_t)&yajl_buf_append) yajl_buf_free((yajl_buf)g->ctx); 140 | YA_FREE(&(g->alloc), g); 141 | } 142 | 143 | #define INSERT_SEP \ 144 | if (g->state[g->depth] == yajl_gen_map_key || \ 145 | g->state[g->depth] == yajl_gen_in_array) { \ 146 | g->print(g->ctx, ",", 1); \ 147 | if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); \ 148 | } else if (g->state[g->depth] == yajl_gen_map_val) { \ 149 | g->print(g->ctx, ":", 1); \ 150 | if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1); \ 151 | } 152 | 153 | #define INSERT_WHITESPACE \ 154 | if ((g->flags & yajl_gen_beautify)) { \ 155 | if (g->state[g->depth] != yajl_gen_map_val) { \ 156 | unsigned int _i; \ 157 | for (_i=0;_idepth;_i++) \ 158 | g->print(g->ctx, \ 159 | g->indentString, \ 160 | (unsigned int)strlen(g->indentString)); \ 161 | } \ 162 | } 163 | 164 | #define ENSURE_NOT_KEY \ 165 | if (g->state[g->depth] == yajl_gen_map_key || \ 166 | g->state[g->depth] == yajl_gen_map_start) { \ 167 | return yajl_gen_keys_must_be_strings; \ 168 | } \ 169 | 170 | /* check that we're not complete, or in error state. in a valid state 171 | * to be generating */ 172 | #define ENSURE_VALID_STATE \ 173 | if (g->state[g->depth] == yajl_gen_error) { \ 174 | return yajl_gen_in_error_state;\ 175 | } else if (g->state[g->depth] == yajl_gen_complete) { \ 176 | return yajl_gen_generation_complete; \ 177 | } 178 | 179 | #define INCREMENT_DEPTH \ 180 | if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded; 181 | 182 | #define DECREMENT_DEPTH \ 183 | if (--(g->depth) >= YAJL_MAX_DEPTH) return yajl_gen_generation_complete; 184 | 185 | #define APPENDED_ATOM \ 186 | switch (g->state[g->depth]) { \ 187 | case yajl_gen_start: \ 188 | g->state[g->depth] = yajl_gen_complete; \ 189 | break; \ 190 | case yajl_gen_map_start: \ 191 | case yajl_gen_map_key: \ 192 | g->state[g->depth] = yajl_gen_map_val; \ 193 | break; \ 194 | case yajl_gen_array_start: \ 195 | g->state[g->depth] = yajl_gen_in_array; \ 196 | break; \ 197 | case yajl_gen_map_val: \ 198 | g->state[g->depth] = yajl_gen_map_key; \ 199 | break; \ 200 | default: \ 201 | break; \ 202 | } \ 203 | 204 | #define FINAL_NEWLINE \ 205 | if ((g->flags & yajl_gen_beautify) && g->state[g->depth] == yajl_gen_complete) \ 206 | g->print(g->ctx, "\n", 1); 207 | 208 | yajl_gen_status 209 | yajl_gen_integer(yajl_gen g, long long int number) 210 | { 211 | char i[32]; 212 | ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; 213 | sprintf(i, "%lld", number); 214 | g->print(g->ctx, i, (unsigned int)strlen(i)); 215 | APPENDED_ATOM; 216 | FINAL_NEWLINE; 217 | return yajl_gen_status_ok; 218 | } 219 | 220 | #if defined(_WIN32) || defined(WIN32) 221 | #include 222 | #define isnan _isnan 223 | #define isinf !_finite 224 | #endif 225 | 226 | yajl_gen_status 227 | yajl_gen_double(yajl_gen g, double number) 228 | { 229 | char i[32]; 230 | ENSURE_VALID_STATE; ENSURE_NOT_KEY; 231 | if (isnan(number) || isinf(number)) return yajl_gen_invalid_number; 232 | INSERT_SEP; INSERT_WHITESPACE; 233 | sprintf(i, "%.20g", number); 234 | if (strspn(i, "0123456789-") == strlen(i)) { 235 | strcat(i, ".0"); 236 | } 237 | g->print(g->ctx, i, (unsigned int)strlen(i)); 238 | APPENDED_ATOM; 239 | FINAL_NEWLINE; 240 | return yajl_gen_status_ok; 241 | } 242 | 243 | yajl_gen_status 244 | yajl_gen_number(yajl_gen g, const char * s, size_t l) 245 | { 246 | ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; 247 | g->print(g->ctx, s, l); 248 | APPENDED_ATOM; 249 | FINAL_NEWLINE; 250 | return yajl_gen_status_ok; 251 | } 252 | 253 | yajl_gen_status 254 | yajl_gen_string(yajl_gen g, const unsigned char * str, 255 | size_t len) 256 | { 257 | // if validation is enabled, check that the string is valid utf8 258 | // XXX: This checking could be done a little faster, in the same pass as 259 | // the string encoding 260 | if (g->flags & yajl_gen_validate_utf8) { 261 | if (!yajl_string_validate_utf8(str, len)) { 262 | return yajl_gen_invalid_string; 263 | } 264 | } 265 | ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE; 266 | g->print(g->ctx, "\"", 1); 267 | yajl_string_encode(g->print, g->ctx, str, len, g->flags & yajl_gen_escape_solidus); 268 | g->print(g->ctx, "\"", 1); 269 | APPENDED_ATOM; 270 | FINAL_NEWLINE; 271 | return yajl_gen_status_ok; 272 | } 273 | 274 | yajl_gen_status 275 | yajl_gen_null(yajl_gen g) 276 | { 277 | ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; 278 | g->print(g->ctx, "null", strlen("null")); 279 | APPENDED_ATOM; 280 | FINAL_NEWLINE; 281 | return yajl_gen_status_ok; 282 | } 283 | 284 | yajl_gen_status 285 | yajl_gen_bool(yajl_gen g, int boolean) 286 | { 287 | const char * val = boolean ? "true" : "false"; 288 | 289 | ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; 290 | g->print(g->ctx, val, (unsigned int)strlen(val)); 291 | APPENDED_ATOM; 292 | FINAL_NEWLINE; 293 | return yajl_gen_status_ok; 294 | } 295 | 296 | yajl_gen_status 297 | yajl_gen_map_open(yajl_gen g) 298 | { 299 | ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; 300 | INCREMENT_DEPTH; 301 | 302 | g->state[g->depth] = yajl_gen_map_start; 303 | g->print(g->ctx, "{", 1); 304 | if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); 305 | FINAL_NEWLINE; 306 | return yajl_gen_status_ok; 307 | } 308 | 309 | yajl_gen_status 310 | yajl_gen_map_close(yajl_gen g) 311 | { 312 | ENSURE_VALID_STATE; 313 | DECREMENT_DEPTH; 314 | 315 | if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); 316 | APPENDED_ATOM; 317 | INSERT_WHITESPACE; 318 | g->print(g->ctx, "}", 1); 319 | FINAL_NEWLINE; 320 | return yajl_gen_status_ok; 321 | } 322 | 323 | yajl_gen_status 324 | yajl_gen_array_open(yajl_gen g) 325 | { 326 | ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; 327 | INCREMENT_DEPTH; 328 | g->state[g->depth] = yajl_gen_array_start; 329 | g->print(g->ctx, "[", 1); 330 | if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); 331 | FINAL_NEWLINE; 332 | return yajl_gen_status_ok; 333 | } 334 | 335 | yajl_gen_status 336 | yajl_gen_array_close(yajl_gen g) 337 | { 338 | ENSURE_VALID_STATE; 339 | DECREMENT_DEPTH; 340 | if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); 341 | APPENDED_ATOM; 342 | INSERT_WHITESPACE; 343 | g->print(g->ctx, "]", 1); 344 | FINAL_NEWLINE; 345 | return yajl_gen_status_ok; 346 | } 347 | 348 | yajl_gen_status 349 | yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf, 350 | size_t * len) 351 | { 352 | if (g->print != (yajl_print_t)&yajl_buf_append) return yajl_gen_no_buf; 353 | *buf = yajl_buf_data((yajl_buf)g->ctx); 354 | *len = yajl_buf_len((yajl_buf)g->ctx); 355 | return yajl_gen_status_ok; 356 | } 357 | 358 | void 359 | yajl_gen_clear(yajl_gen g) 360 | { 361 | if (g->print == (yajl_print_t)&yajl_buf_append) yajl_buf_clear((yajl_buf)g->ctx); 362 | } 363 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_lex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "yajl_lex.h" 18 | #include "yajl_buf.h" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #ifdef YAJL_LEXER_DEBUG 26 | static const char * 27 | tokToStr(yajl_tok tok) 28 | { 29 | switch (tok) { 30 | case yajl_tok_bool: return "bool"; 31 | case yajl_tok_colon: return "colon"; 32 | case yajl_tok_comma: return "comma"; 33 | case yajl_tok_eof: return "eof"; 34 | case yajl_tok_error: return "error"; 35 | case yajl_tok_left_brace: return "brace"; 36 | case yajl_tok_left_bracket: return "bracket"; 37 | case yajl_tok_null: return "null"; 38 | case yajl_tok_integer: return "integer"; 39 | case yajl_tok_double: return "double"; 40 | case yajl_tok_right_brace: return "brace"; 41 | case yajl_tok_right_bracket: return "bracket"; 42 | case yajl_tok_string: return "string"; 43 | case yajl_tok_string_with_escapes: return "string_with_escapes"; 44 | } 45 | return "unknown"; 46 | } 47 | #endif 48 | 49 | /* Impact of the stream parsing feature on the lexer: 50 | * 51 | * YAJL support stream parsing. That is, the ability to parse the first 52 | * bits of a chunk of JSON before the last bits are available (still on 53 | * the network or disk). This makes the lexer more complex. The 54 | * responsibility of the lexer is to handle transparently the case where 55 | * a chunk boundary falls in the middle of a token. This is 56 | * accomplished is via a buffer and a character reading abstraction. 57 | * 58 | * Overview of implementation 59 | * 60 | * When we lex to end of input string before end of token is hit, we 61 | * copy all of the input text composing the token into our lexBuf. 62 | * 63 | * Every time we read a character, we do so through the readChar function. 64 | * readChar's responsibility is to handle pulling all chars from the buffer 65 | * before pulling chars from input text 66 | */ 67 | 68 | struct yajl_lexer_t { 69 | /* the overal line and char offset into the data */ 70 | size_t lineOff; 71 | size_t charOff; 72 | 73 | /* error */ 74 | yajl_lex_error error; 75 | 76 | /* a input buffer to handle the case where a token is spread over 77 | * multiple chunks */ 78 | yajl_buf buf; 79 | 80 | /* in the case where we have data in the lexBuf, bufOff holds 81 | * the current offset into the lexBuf. */ 82 | size_t bufOff; 83 | 84 | /* are we using the lex buf? */ 85 | unsigned int bufInUse; 86 | 87 | /* shall we allow comments? */ 88 | unsigned int allowComments; 89 | 90 | /* shall we validate utf8 inside strings? */ 91 | unsigned int validateUTF8; 92 | 93 | yajl_alloc_funcs * alloc; 94 | }; 95 | 96 | #define readChar(lxr, txt, off) \ 97 | (((lxr)->bufInUse && yajl_buf_len((lxr)->buf) && lxr->bufOff < yajl_buf_len((lxr)->buf)) ? \ 98 | (*((const unsigned char *) yajl_buf_data((lxr)->buf) + ((lxr)->bufOff)++)) : \ 99 | ((txt)[(*(off))++])) 100 | 101 | #define unreadChar(lxr, off) ((*(off) > 0) ? (*(off))-- : ((lxr)->bufOff--)) 102 | 103 | yajl_lexer 104 | yajl_lex_alloc(yajl_alloc_funcs * alloc, 105 | unsigned int allowComments, unsigned int validateUTF8) 106 | { 107 | yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t)); 108 | memset((void *) lxr, 0, sizeof(struct yajl_lexer_t)); 109 | lxr->buf = yajl_buf_alloc(alloc); 110 | lxr->allowComments = allowComments; 111 | lxr->validateUTF8 = validateUTF8; 112 | lxr->alloc = alloc; 113 | return lxr; 114 | } 115 | 116 | void 117 | yajl_lex_free(yajl_lexer lxr) 118 | { 119 | yajl_buf_free(lxr->buf); 120 | YA_FREE(lxr->alloc, lxr); 121 | return; 122 | } 123 | 124 | /* a lookup table which lets us quickly determine three things: 125 | * VEC - valid escaped control char 126 | * note. the solidus '/' may be escaped or not. 127 | * IJC - invalid json char 128 | * VHC - valid hex char 129 | * NFP - needs further processing (from a string scanning perspective) 130 | * NUC - needs utf8 checking when enabled (from a string scanning perspective) 131 | */ 132 | #define VEC 0x01 133 | #define IJC 0x02 134 | #define VHC 0x04 135 | #define NFP 0x08 136 | #define NUC 0x10 137 | 138 | static const char charLookupTable[256] = 139 | { 140 | /*00*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , 141 | /*08*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , 142 | /*10*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , 143 | /*18*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , 144 | 145 | /*20*/ 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 , 0 , 0 , 146 | /*28*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , VEC , 147 | /*30*/ VHC , VHC , VHC , VHC , VHC , VHC , VHC , VHC , 148 | /*38*/ VHC , VHC , 0 , 0 , 0 , 0 , 0 , 0 , 149 | 150 | /*40*/ 0 , VHC , VHC , VHC , VHC , VHC , VHC , 0 , 151 | /*48*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 152 | /*50*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 153 | /*58*/ 0 , 0 , 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 , 154 | 155 | /*60*/ 0 , VHC , VEC|VHC, VHC , VHC , VHC , VEC|VHC, 0 , 156 | /*68*/ 0 , 0 , 0 , 0 , 0 , 0 , VEC , 0 , 157 | /*70*/ 0 , 0 , VEC , 0 , VEC , 0 , 0 , 0 , 158 | /*78*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 159 | 160 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 161 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 162 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 163 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 164 | 165 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 166 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 167 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 168 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 169 | 170 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 171 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 172 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 173 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 174 | 175 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 176 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 177 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , 178 | NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC 179 | }; 180 | 181 | /** process a variable length utf8 encoded codepoint. 182 | * 183 | * returns: 184 | * yajl_tok_string - if valid utf8 char was parsed and offset was 185 | * advanced 186 | * yajl_tok_eof - if end of input was hit before validation could 187 | * complete 188 | * yajl_tok_error - if invalid utf8 was encountered 189 | * 190 | * NOTE: on error the offset will point to the first char of the 191 | * invalid utf8 */ 192 | #define UTF8_CHECK_EOF if (*offset >= jsonTextLen) { return yajl_tok_eof; } 193 | 194 | static yajl_tok 195 | yajl_lex_utf8_char(yajl_lexer lexer, const unsigned char * jsonText, 196 | size_t jsonTextLen, size_t * offset, 197 | unsigned char curChar) 198 | { 199 | if (curChar <= 0x7f) { 200 | /* single byte */ 201 | return yajl_tok_string; 202 | } else if ((curChar >> 5) == 0x6) { 203 | /* two byte */ 204 | UTF8_CHECK_EOF; 205 | curChar = readChar(lexer, jsonText, offset); 206 | if ((curChar >> 6) == 0x2) return yajl_tok_string; 207 | } else if ((curChar >> 4) == 0x0e) { 208 | /* three byte */ 209 | UTF8_CHECK_EOF; 210 | curChar = readChar(lexer, jsonText, offset); 211 | if ((curChar >> 6) == 0x2) { 212 | UTF8_CHECK_EOF; 213 | curChar = readChar(lexer, jsonText, offset); 214 | if ((curChar >> 6) == 0x2) return yajl_tok_string; 215 | } 216 | } else if ((curChar >> 3) == 0x1e) { 217 | /* four byte */ 218 | UTF8_CHECK_EOF; 219 | curChar = readChar(lexer, jsonText, offset); 220 | if ((curChar >> 6) == 0x2) { 221 | UTF8_CHECK_EOF; 222 | curChar = readChar(lexer, jsonText, offset); 223 | if ((curChar >> 6) == 0x2) { 224 | UTF8_CHECK_EOF; 225 | curChar = readChar(lexer, jsonText, offset); 226 | if ((curChar >> 6) == 0x2) return yajl_tok_string; 227 | } 228 | } 229 | } 230 | 231 | return yajl_tok_error; 232 | } 233 | 234 | /* lex a string. input is the lexer, pointer to beginning of 235 | * json text, and start of string (offset). 236 | * a token is returned which has the following meanings: 237 | * yajl_tok_string: lex of string was successful. offset points to 238 | * terminating '"'. 239 | * yajl_tok_eof: end of text was encountered before we could complete 240 | * the lex. 241 | * yajl_tok_error: embedded in the string were unallowable chars. offset 242 | * points to the offending char 243 | */ 244 | #define STR_CHECK_EOF \ 245 | if (*offset >= jsonTextLen) { \ 246 | tok = yajl_tok_eof; \ 247 | goto finish_string_lex; \ 248 | } 249 | 250 | /** scan a string for interesting characters that might need further 251 | * review. return the number of chars that are uninteresting and can 252 | * be skipped. 253 | * (lth) hi world, any thoughts on how to make this routine faster? */ 254 | static size_t 255 | yajl_string_scan(const unsigned char * buf, size_t len, int utf8check) 256 | { 257 | unsigned char mask = IJC|NFP|(utf8check ? NUC : 0); 258 | size_t skip = 0; 259 | while (skip < len && !(charLookupTable[*buf] & mask)) 260 | { 261 | skip++; 262 | buf++; 263 | } 264 | return skip; 265 | } 266 | 267 | static yajl_tok 268 | yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText, 269 | size_t jsonTextLen, size_t * offset) 270 | { 271 | yajl_tok tok = yajl_tok_error; 272 | int hasEscapes = 0; 273 | 274 | for (;;) { 275 | unsigned char curChar; 276 | 277 | /* now jump into a faster scanning routine to skip as much 278 | * of the buffers as possible */ 279 | { 280 | const unsigned char * p; 281 | size_t len; 282 | 283 | if ((lexer->bufInUse && yajl_buf_len(lexer->buf) && 284 | lexer->bufOff < yajl_buf_len(lexer->buf))) 285 | { 286 | p = ((const unsigned char *) yajl_buf_data(lexer->buf) + 287 | (lexer->bufOff)); 288 | len = yajl_buf_len(lexer->buf) - lexer->bufOff; 289 | lexer->bufOff += yajl_string_scan(p, len, lexer->validateUTF8); 290 | } 291 | else if (*offset < jsonTextLen) 292 | { 293 | p = jsonText + *offset; 294 | len = jsonTextLen - *offset; 295 | *offset += yajl_string_scan(p, len, lexer->validateUTF8); 296 | } 297 | } 298 | 299 | STR_CHECK_EOF; 300 | 301 | curChar = readChar(lexer, jsonText, offset); 302 | 303 | /* quote terminates */ 304 | if (curChar == '"') { 305 | tok = yajl_tok_string; 306 | break; 307 | } 308 | /* backslash escapes a set of control chars, */ 309 | else if (curChar == '\\') { 310 | hasEscapes = 1; 311 | STR_CHECK_EOF; 312 | 313 | /* special case \u */ 314 | curChar = readChar(lexer, jsonText, offset); 315 | if (curChar == 'u') { 316 | unsigned int i = 0; 317 | 318 | for (i=0;i<4;i++) { 319 | STR_CHECK_EOF; 320 | curChar = readChar(lexer, jsonText, offset); 321 | if (!(charLookupTable[curChar] & VHC)) { 322 | /* back up to offending char */ 323 | unreadChar(lexer, offset); 324 | lexer->error = yajl_lex_string_invalid_hex_char; 325 | goto finish_string_lex; 326 | } 327 | } 328 | } else if (!(charLookupTable[curChar] & VEC)) { 329 | /* back up to offending char */ 330 | unreadChar(lexer, offset); 331 | lexer->error = yajl_lex_string_invalid_escaped_char; 332 | goto finish_string_lex; 333 | } 334 | } 335 | /* when not validating UTF8 it's a simple table lookup to determine 336 | * if the present character is invalid */ 337 | else if(charLookupTable[curChar] & IJC) { 338 | /* back up to offending char */ 339 | unreadChar(lexer, offset); 340 | lexer->error = yajl_lex_string_invalid_json_char; 341 | goto finish_string_lex; 342 | } 343 | /* when in validate UTF8 mode we need to do some extra work */ 344 | else if (lexer->validateUTF8) { 345 | yajl_tok t = yajl_lex_utf8_char(lexer, jsonText, jsonTextLen, 346 | offset, curChar); 347 | 348 | if (t == yajl_tok_eof) { 349 | tok = yajl_tok_eof; 350 | goto finish_string_lex; 351 | } else if (t == yajl_tok_error) { 352 | lexer->error = yajl_lex_string_invalid_utf8; 353 | goto finish_string_lex; 354 | } 355 | } 356 | /* accept it, and move on */ 357 | } 358 | finish_string_lex: 359 | /* tell our buddy, the parser, wether he needs to process this string 360 | * again */ 361 | if (hasEscapes && tok == yajl_tok_string) { 362 | tok = yajl_tok_string_with_escapes; 363 | } 364 | 365 | return tok; 366 | } 367 | 368 | #define RETURN_IF_EOF if (*offset >= jsonTextLen) return yajl_tok_eof; 369 | 370 | static yajl_tok 371 | yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText, 372 | size_t jsonTextLen, size_t * offset) 373 | { 374 | /** XXX: numbers are the only entities in json that we must lex 375 | * _beyond_ in order to know that they are complete. There 376 | * is an ambiguous case for integers at EOF. */ 377 | 378 | unsigned char c; 379 | 380 | yajl_tok tok = yajl_tok_integer; 381 | 382 | RETURN_IF_EOF; 383 | c = readChar(lexer, jsonText, offset); 384 | 385 | /* optional leading minus */ 386 | if (c == '-') { 387 | RETURN_IF_EOF; 388 | c = readChar(lexer, jsonText, offset); 389 | } 390 | 391 | /* a single zero, or a series of integers */ 392 | if (c == '0') { 393 | RETURN_IF_EOF; 394 | c = readChar(lexer, jsonText, offset); 395 | } else if (c >= '1' && c <= '9') { 396 | do { 397 | RETURN_IF_EOF; 398 | c = readChar(lexer, jsonText, offset); 399 | } while (c >= '0' && c <= '9'); 400 | } else { 401 | unreadChar(lexer, offset); 402 | lexer->error = yajl_lex_missing_integer_after_minus; 403 | return yajl_tok_error; 404 | } 405 | 406 | /* optional fraction (indicates this is floating point) */ 407 | if (c == '.') { 408 | int numRd = 0; 409 | 410 | RETURN_IF_EOF; 411 | c = readChar(lexer, jsonText, offset); 412 | 413 | while (c >= '0' && c <= '9') { 414 | numRd++; 415 | RETURN_IF_EOF; 416 | c = readChar(lexer, jsonText, offset); 417 | } 418 | 419 | if (!numRd) { 420 | unreadChar(lexer, offset); 421 | lexer->error = yajl_lex_missing_integer_after_decimal; 422 | return yajl_tok_error; 423 | } 424 | tok = yajl_tok_double; 425 | } 426 | 427 | /* optional exponent (indicates this is floating point) */ 428 | if (c == 'e' || c == 'E') { 429 | RETURN_IF_EOF; 430 | c = readChar(lexer, jsonText, offset); 431 | 432 | /* optional sign */ 433 | if (c == '+' || c == '-') { 434 | RETURN_IF_EOF; 435 | c = readChar(lexer, jsonText, offset); 436 | } 437 | 438 | if (c >= '0' && c <= '9') { 439 | do { 440 | RETURN_IF_EOF; 441 | c = readChar(lexer, jsonText, offset); 442 | } while (c >= '0' && c <= '9'); 443 | } else { 444 | unreadChar(lexer, offset); 445 | lexer->error = yajl_lex_missing_integer_after_exponent; 446 | return yajl_tok_error; 447 | } 448 | tok = yajl_tok_double; 449 | } 450 | 451 | /* we always go "one too far" */ 452 | unreadChar(lexer, offset); 453 | 454 | return tok; 455 | } 456 | 457 | static yajl_tok 458 | yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText, 459 | size_t jsonTextLen, size_t * offset) 460 | { 461 | unsigned char c; 462 | 463 | yajl_tok tok = yajl_tok_comment; 464 | 465 | RETURN_IF_EOF; 466 | c = readChar(lexer, jsonText, offset); 467 | 468 | /* either slash or star expected */ 469 | if (c == '/') { 470 | /* now we throw away until end of line */ 471 | do { 472 | RETURN_IF_EOF; 473 | c = readChar(lexer, jsonText, offset); 474 | } while (c != '\n'); 475 | } else if (c == '*') { 476 | /* now we throw away until end of comment */ 477 | for (;;) { 478 | RETURN_IF_EOF; 479 | c = readChar(lexer, jsonText, offset); 480 | if (c == '*') { 481 | RETURN_IF_EOF; 482 | c = readChar(lexer, jsonText, offset); 483 | if (c == '/') { 484 | break; 485 | } else { 486 | unreadChar(lexer, offset); 487 | } 488 | } 489 | } 490 | } else { 491 | lexer->error = yajl_lex_invalid_char; 492 | tok = yajl_tok_error; 493 | } 494 | 495 | return tok; 496 | } 497 | 498 | yajl_tok 499 | yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText, 500 | size_t jsonTextLen, size_t * offset, 501 | const unsigned char ** outBuf, size_t * outLen) 502 | { 503 | yajl_tok tok = yajl_tok_error; 504 | unsigned char c; 505 | size_t startOffset = *offset; 506 | 507 | *outBuf = NULL; 508 | *outLen = 0; 509 | 510 | for (;;) { 511 | assert(*offset <= jsonTextLen); 512 | 513 | if (*offset >= jsonTextLen) { 514 | tok = yajl_tok_eof; 515 | goto lexed; 516 | } 517 | 518 | c = readChar(lexer, jsonText, offset); 519 | 520 | switch (c) { 521 | case '{': 522 | tok = yajl_tok_left_bracket; 523 | goto lexed; 524 | case '}': 525 | tok = yajl_tok_right_bracket; 526 | goto lexed; 527 | case '[': 528 | tok = yajl_tok_left_brace; 529 | goto lexed; 530 | case ']': 531 | tok = yajl_tok_right_brace; 532 | goto lexed; 533 | case ',': 534 | tok = yajl_tok_comma; 535 | goto lexed; 536 | case ':': 537 | tok = yajl_tok_colon; 538 | goto lexed; 539 | case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': 540 | startOffset++; 541 | break; 542 | case 't': { 543 | const char * want = "rue"; 544 | do { 545 | if (*offset >= jsonTextLen) { 546 | tok = yajl_tok_eof; 547 | goto lexed; 548 | } 549 | c = readChar(lexer, jsonText, offset); 550 | if (c != *want) { 551 | unreadChar(lexer, offset); 552 | lexer->error = yajl_lex_invalid_string; 553 | tok = yajl_tok_error; 554 | goto lexed; 555 | } 556 | } while (*(++want)); 557 | tok = yajl_tok_bool; 558 | goto lexed; 559 | } 560 | case 'f': { 561 | const char * want = "alse"; 562 | do { 563 | if (*offset >= jsonTextLen) { 564 | tok = yajl_tok_eof; 565 | goto lexed; 566 | } 567 | c = readChar(lexer, jsonText, offset); 568 | if (c != *want) { 569 | unreadChar(lexer, offset); 570 | lexer->error = yajl_lex_invalid_string; 571 | tok = yajl_tok_error; 572 | goto lexed; 573 | } 574 | } while (*(++want)); 575 | tok = yajl_tok_bool; 576 | goto lexed; 577 | } 578 | case 'n': { 579 | const char * want = "ull"; 580 | do { 581 | if (*offset >= jsonTextLen) { 582 | tok = yajl_tok_eof; 583 | goto lexed; 584 | } 585 | c = readChar(lexer, jsonText, offset); 586 | if (c != *want) { 587 | unreadChar(lexer, offset); 588 | lexer->error = yajl_lex_invalid_string; 589 | tok = yajl_tok_error; 590 | goto lexed; 591 | } 592 | } while (*(++want)); 593 | tok = yajl_tok_null; 594 | goto lexed; 595 | } 596 | case '"': { 597 | tok = yajl_lex_string(lexer, (const unsigned char *) jsonText, 598 | jsonTextLen, offset); 599 | goto lexed; 600 | } 601 | case '-': 602 | case '0': case '1': case '2': case '3': case '4': 603 | case '5': case '6': case '7': case '8': case '9': { 604 | /* integer parsing wants to start from the beginning */ 605 | unreadChar(lexer, offset); 606 | tok = yajl_lex_number(lexer, (const unsigned char *) jsonText, 607 | jsonTextLen, offset); 608 | goto lexed; 609 | } 610 | case '/': 611 | /* hey, look, a probable comment! If comments are disabled 612 | * it's an error. */ 613 | if (!lexer->allowComments) { 614 | unreadChar(lexer, offset); 615 | lexer->error = yajl_lex_unallowed_comment; 616 | tok = yajl_tok_error; 617 | goto lexed; 618 | } 619 | /* if comments are enabled, then we should try to lex 620 | * the thing. possible outcomes are 621 | * - successful lex (tok_comment, which means continue), 622 | * - malformed comment opening (slash not followed by 623 | * '*' or '/') (tok_error) 624 | * - eof hit. (tok_eof) */ 625 | tok = yajl_lex_comment(lexer, (const unsigned char *) jsonText, 626 | jsonTextLen, offset); 627 | if (tok == yajl_tok_comment) { 628 | /* "error" is silly, but that's the initial 629 | * state of tok. guilty until proven innocent. */ 630 | tok = yajl_tok_error; 631 | yajl_buf_clear(lexer->buf); 632 | lexer->bufInUse = 0; 633 | startOffset = *offset; 634 | break; 635 | } 636 | /* hit error or eof, bail */ 637 | goto lexed; 638 | default: 639 | lexer->error = yajl_lex_invalid_char; 640 | tok = yajl_tok_error; 641 | goto lexed; 642 | } 643 | } 644 | 645 | 646 | lexed: 647 | /* need to append to buffer if the buffer is in use or 648 | * if it's an EOF token */ 649 | if (tok == yajl_tok_eof || lexer->bufInUse) { 650 | if (!lexer->bufInUse) yajl_buf_clear(lexer->buf); 651 | lexer->bufInUse = 1; 652 | yajl_buf_append(lexer->buf, jsonText + startOffset, *offset - startOffset); 653 | lexer->bufOff = 0; 654 | 655 | if (tok != yajl_tok_eof) { 656 | *outBuf = yajl_buf_data(lexer->buf); 657 | *outLen = yajl_buf_len(lexer->buf); 658 | lexer->bufInUse = 0; 659 | } 660 | } else if (tok != yajl_tok_error) { 661 | *outBuf = jsonText + startOffset; 662 | *outLen = *offset - startOffset; 663 | } 664 | 665 | /* special case for strings. skip the quotes. */ 666 | if (tok == yajl_tok_string || tok == yajl_tok_string_with_escapes) 667 | { 668 | assert(*outLen >= 2); 669 | (*outBuf)++; 670 | *outLen -= 2; 671 | } 672 | 673 | 674 | #ifdef YAJL_LEXER_DEBUG 675 | if (tok == yajl_tok_error) { 676 | printf("lexical error: %s\n", 677 | yajl_lex_error_to_string(yajl_lex_get_error(lexer))); 678 | } else if (tok == yajl_tok_eof) { 679 | printf("EOF hit\n"); 680 | } else { 681 | printf("lexed %s: '", tokToStr(tok)); 682 | fwrite(*outBuf, 1, *outLen, stdout); 683 | printf("'\n"); 684 | } 685 | #endif 686 | 687 | return tok; 688 | } 689 | 690 | const char * 691 | yajl_lex_error_to_string(yajl_lex_error error) 692 | { 693 | switch (error) { 694 | case yajl_lex_e_ok: 695 | return "ok, no error"; 696 | case yajl_lex_string_invalid_utf8: 697 | return "invalid bytes in UTF8 string."; 698 | case yajl_lex_string_invalid_escaped_char: 699 | return "inside a string, '\\' occurs before a character " 700 | "which it may not."; 701 | case yajl_lex_string_invalid_json_char: 702 | return "invalid character inside string."; 703 | case yajl_lex_string_invalid_hex_char: 704 | return "invalid (non-hex) character occurs after '\\u' inside " 705 | "string."; 706 | case yajl_lex_invalid_char: 707 | return "invalid char in json text."; 708 | case yajl_lex_invalid_string: 709 | return "invalid string in json text."; 710 | case yajl_lex_missing_integer_after_exponent: 711 | return "malformed number, a digit is required after the exponent."; 712 | case yajl_lex_missing_integer_after_decimal: 713 | return "malformed number, a digit is required after the " 714 | "decimal point."; 715 | case yajl_lex_missing_integer_after_minus: 716 | return "malformed number, a digit is required after the " 717 | "minus sign."; 718 | case yajl_lex_unallowed_comment: 719 | return "probable comment found in input text, comments are " 720 | "not enabled."; 721 | } 722 | return "unknown error code"; 723 | } 724 | 725 | 726 | /** allows access to more specific information about the lexical 727 | * error when yajl_lex_lex returns yajl_tok_error. */ 728 | yajl_lex_error 729 | yajl_lex_get_error(yajl_lexer lexer) 730 | { 731 | if (lexer == NULL) return (yajl_lex_error) -1; 732 | return lexer->error; 733 | } 734 | 735 | size_t yajl_lex_current_line(yajl_lexer lexer) 736 | { 737 | return lexer->lineOff; 738 | } 739 | 740 | size_t yajl_lex_current_char(yajl_lexer lexer) 741 | { 742 | return lexer->charOff; 743 | } 744 | 745 | yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText, 746 | size_t jsonTextLen, size_t offset) 747 | { 748 | const unsigned char * outBuf; 749 | size_t outLen; 750 | size_t bufLen = yajl_buf_len(lexer->buf); 751 | size_t bufOff = lexer->bufOff; 752 | unsigned int bufInUse = lexer->bufInUse; 753 | yajl_tok tok; 754 | 755 | tok = yajl_lex_lex(lexer, jsonText, jsonTextLen, &offset, 756 | &outBuf, &outLen); 757 | 758 | lexer->bufOff = bufOff; 759 | lexer->bufInUse = bufInUse; 760 | yajl_buf_truncate(lexer->buf, bufLen); 761 | 762 | return tok; 763 | } 764 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_lex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef __YAJL_LEX_H__ 18 | #define __YAJL_LEX_H__ 19 | 20 | #include "api/yajl_common.h" 21 | 22 | typedef enum { 23 | yajl_tok_bool, 24 | yajl_tok_colon, 25 | yajl_tok_comma, 26 | yajl_tok_eof, 27 | yajl_tok_error, 28 | yajl_tok_left_brace, 29 | yajl_tok_left_bracket, 30 | yajl_tok_null, 31 | yajl_tok_right_brace, 32 | yajl_tok_right_bracket, 33 | 34 | /* we differentiate between integers and doubles to allow the 35 | * parser to interpret the number without re-scanning */ 36 | yajl_tok_integer, 37 | yajl_tok_double, 38 | 39 | /* we differentiate between strings which require further processing, 40 | * and strings that do not */ 41 | yajl_tok_string, 42 | yajl_tok_string_with_escapes, 43 | 44 | /* comment tokens are not currently returned to the parser, ever */ 45 | yajl_tok_comment 46 | } yajl_tok; 47 | 48 | typedef struct yajl_lexer_t * yajl_lexer; 49 | 50 | yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc, 51 | unsigned int allowComments, 52 | unsigned int validateUTF8); 53 | 54 | void yajl_lex_free(yajl_lexer lexer); 55 | 56 | /** 57 | * run/continue a lex. "offset" is an input/output parameter. 58 | * It should be initialized to zero for a 59 | * new chunk of target text, and upon subsetquent calls with the same 60 | * target text should passed with the value of the previous invocation. 61 | * 62 | * the client may be interested in the value of offset when an error is 63 | * returned from the lexer. This allows the client to render useful 64 | * error messages. 65 | * 66 | * When you pass the next chunk of data, context should be reinitialized 67 | * to zero. 68 | * 69 | * Finally, the output buffer is usually just a pointer into the jsonText, 70 | * however in cases where the entity being lexed spans multiple chunks, 71 | * the lexer will buffer the entity and the data returned will be 72 | * a pointer into that buffer. 73 | * 74 | * This behavior is abstracted from client code except for the performance 75 | * implications which require that the client choose a reasonable chunk 76 | * size to get adequate performance. 77 | */ 78 | yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText, 79 | size_t jsonTextLen, size_t * offset, 80 | const unsigned char ** outBuf, size_t * outLen); 81 | 82 | /** have a peek at the next token, but don't move the lexer forward */ 83 | yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText, 84 | size_t jsonTextLen, size_t offset); 85 | 86 | 87 | typedef enum { 88 | yajl_lex_e_ok = 0, 89 | yajl_lex_string_invalid_utf8, 90 | yajl_lex_string_invalid_escaped_char, 91 | yajl_lex_string_invalid_json_char, 92 | yajl_lex_string_invalid_hex_char, 93 | yajl_lex_invalid_char, 94 | yajl_lex_invalid_string, 95 | yajl_lex_missing_integer_after_decimal, 96 | yajl_lex_missing_integer_after_exponent, 97 | yajl_lex_missing_integer_after_minus, 98 | yajl_lex_unallowed_comment 99 | } yajl_lex_error; 100 | 101 | const char * yajl_lex_error_to_string(yajl_lex_error error); 102 | 103 | /** allows access to more specific information about the lexical 104 | * error when yajl_lex_lex returns yajl_tok_error. */ 105 | yajl_lex_error yajl_lex_get_error(yajl_lexer lexer); 106 | 107 | /** get the current offset into the most recently lexed json string. */ 108 | size_t yajl_lex_current_offset(yajl_lexer lexer); 109 | 110 | /** get the number of lines lexed by this lexer instance */ 111 | size_t yajl_lex_current_line(yajl_lexer lexer); 112 | 113 | /** get the number of chars lexed by this lexer instance since the last 114 | * \n or \r */ 115 | size_t yajl_lex_current_char(yajl_lexer lexer); 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "api/yajl_parse.h" 18 | #include "yajl_lex.h" 19 | #include "yajl_parser.h" 20 | #include "yajl_encode.h" 21 | #include "yajl_bytestack.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #define MAX_VALUE_TO_MULTIPLY ((LLONG_MAX / 10) + (LLONG_MAX % 10)) 33 | 34 | /* same semantics as strtol */ 35 | long long 36 | yajl_parse_integer(const unsigned char *number, unsigned int length) 37 | { 38 | long long ret = 0; 39 | long sign = 1; 40 | const unsigned char *pos = number; 41 | if (*pos == '-') { pos++; sign = -1; } 42 | if (*pos == '+') { pos++; } 43 | 44 | while (pos < number + length) { 45 | if ( ret > MAX_VALUE_TO_MULTIPLY ) { 46 | errno = ERANGE; 47 | return sign == 1 ? LLONG_MAX : LLONG_MIN; 48 | } 49 | ret *= 10; 50 | if (LLONG_MAX - ret < (*pos - '0')) { 51 | errno = ERANGE; 52 | return sign == 1 ? LLONG_MAX : LLONG_MIN; 53 | } 54 | if (*pos < '0' || *pos > '9') { 55 | errno = ERANGE; 56 | return sign == 1 ? LLONG_MAX : LLONG_MIN; 57 | } 58 | ret += (*pos++ - '0'); 59 | } 60 | 61 | return sign * ret; 62 | } 63 | 64 | unsigned char * 65 | yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, 66 | size_t jsonTextLen, int verbose) 67 | { 68 | size_t offset = hand->bytesConsumed; 69 | unsigned char * str; 70 | const char * errorType = NULL; 71 | const char * errorText = NULL; 72 | char text[72]; 73 | const char * arrow = " (right here) ------^\n"; 74 | 75 | if (yajl_bs_current(hand->stateStack) == yajl_state_parse_error) { 76 | errorType = "parse"; 77 | errorText = hand->parseError; 78 | } else if (yajl_bs_current(hand->stateStack) == yajl_state_lexical_error) { 79 | errorType = "lexical"; 80 | errorText = yajl_lex_error_to_string(yajl_lex_get_error(hand->lexer)); 81 | } else { 82 | errorType = "unknown"; 83 | } 84 | 85 | { 86 | size_t memneeded = 0; 87 | memneeded += strlen(errorType); 88 | memneeded += strlen(" error"); 89 | if (errorText != NULL) { 90 | memneeded += strlen(": "); 91 | memneeded += strlen(errorText); 92 | } 93 | str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2); 94 | if (!str) return NULL; 95 | str[0] = 0; 96 | strcat((char *) str, errorType); 97 | strcat((char *) str, " error"); 98 | if (errorText != NULL) { 99 | strcat((char *) str, ": "); 100 | strcat((char *) str, errorText); 101 | } 102 | strcat((char *) str, "\n"); 103 | } 104 | 105 | /* now we append as many spaces as needed to make sure the error 106 | * falls at char 41, if verbose was specified */ 107 | if (verbose) { 108 | size_t start, end, i; 109 | size_t spacesNeeded; 110 | 111 | spacesNeeded = (offset < 30 ? 40 - offset : 10); 112 | start = (offset >= 30 ? offset - 30 : 0); 113 | end = (offset + 30 > jsonTextLen ? jsonTextLen : offset + 30); 114 | 115 | for (i=0;ialloc), (unsigned int)(strlen((char *) str) + 133 | strlen((char *) text) + 134 | strlen(arrow) + 1)); 135 | if (newStr) { 136 | newStr[0] = 0; 137 | strcat((char *) newStr, (char *) str); 138 | strcat((char *) newStr, text); 139 | strcat((char *) newStr, arrow); 140 | } 141 | YA_FREE(&(hand->alloc), str); 142 | str = (unsigned char *) newStr; 143 | } 144 | } 145 | return str; 146 | } 147 | 148 | /* check for client cancelation */ 149 | #define _CC_CHK(x) \ 150 | if (!(x)) { \ 151 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); \ 152 | hand->parseError = \ 153 | "client cancelled parse via callback return value"; \ 154 | return yajl_status_client_canceled; \ 155 | } 156 | 157 | 158 | yajl_status 159 | yajl_do_finish(yajl_handle hand) 160 | { 161 | yajl_status stat; 162 | stat = yajl_do_parse(hand,(const unsigned char *) " ",1); 163 | 164 | if (stat != yajl_status_ok) return stat; 165 | 166 | switch(yajl_bs_current(hand->stateStack)) 167 | { 168 | case yajl_state_parse_error: 169 | case yajl_state_lexical_error: 170 | return yajl_status_error; 171 | case yajl_state_got_value: 172 | case yajl_state_parse_complete: 173 | return yajl_status_ok; 174 | default: 175 | if (!(hand->flags & yajl_allow_partial_values)) 176 | { 177 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 178 | hand->parseError = "premature EOF"; 179 | return yajl_status_error; 180 | } 181 | return yajl_status_ok; 182 | } 183 | } 184 | 185 | yajl_status 186 | yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, 187 | size_t jsonTextLen) 188 | { 189 | yajl_tok tok; 190 | const unsigned char * buf; 191 | size_t bufLen; 192 | size_t * offset = &(hand->bytesConsumed); 193 | 194 | *offset = 0; 195 | 196 | around_again: 197 | switch (yajl_bs_current(hand->stateStack)) { 198 | case yajl_state_parse_complete: 199 | if (hand->flags & yajl_allow_multiple_values) { 200 | yajl_bs_set(hand->stateStack, yajl_state_got_value); 201 | goto around_again; 202 | } 203 | if (!(hand->flags & yajl_allow_trailing_garbage)) { 204 | if (*offset != jsonTextLen) { 205 | tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, 206 | offset, &buf, &bufLen); 207 | if (tok != yajl_tok_eof) { 208 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 209 | hand->parseError = "trailing garbage"; 210 | } 211 | goto around_again; 212 | } 213 | } 214 | return yajl_status_ok; 215 | case yajl_state_lexical_error: 216 | case yajl_state_parse_error: 217 | return yajl_status_error; 218 | case yajl_state_start: 219 | case yajl_state_got_value: 220 | case yajl_state_map_need_val: 221 | case yajl_state_array_need_val: 222 | case yajl_state_array_start: { 223 | /* for arrays and maps, we advance the state for this 224 | * depth, then push the state of the next depth. 225 | * If an error occurs during the parsing of the nesting 226 | * enitity, the state at this level will not matter. 227 | * a state that needs pushing will be anything other 228 | * than state_start */ 229 | 230 | yajl_state stateToPush = yajl_state_start; 231 | 232 | tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, 233 | offset, &buf, &bufLen); 234 | 235 | switch (tok) { 236 | case yajl_tok_eof: 237 | return yajl_status_ok; 238 | case yajl_tok_error: 239 | yajl_bs_set(hand->stateStack, yajl_state_lexical_error); 240 | goto around_again; 241 | case yajl_tok_string: 242 | if (hand->callbacks && hand->callbacks->yajl_string) { 243 | _CC_CHK(hand->callbacks->yajl_string(hand->ctx, 244 | buf, bufLen)); 245 | } 246 | break; 247 | case yajl_tok_string_with_escapes: 248 | if (hand->callbacks && hand->callbacks->yajl_string) { 249 | yajl_buf_clear(hand->decodeBuf); 250 | yajl_string_decode(hand->decodeBuf, buf, bufLen); 251 | _CC_CHK(hand->callbacks->yajl_string( 252 | hand->ctx, yajl_buf_data(hand->decodeBuf), 253 | yajl_buf_len(hand->decodeBuf))); 254 | } 255 | break; 256 | case yajl_tok_bool: 257 | if (hand->callbacks && hand->callbacks->yajl_boolean) { 258 | _CC_CHK(hand->callbacks->yajl_boolean(hand->ctx, 259 | *buf == 't')); 260 | } 261 | break; 262 | case yajl_tok_null: 263 | if (hand->callbacks && hand->callbacks->yajl_null) { 264 | _CC_CHK(hand->callbacks->yajl_null(hand->ctx)); 265 | } 266 | break; 267 | case yajl_tok_left_bracket: 268 | if (hand->callbacks && hand->callbacks->yajl_start_map) { 269 | _CC_CHK(hand->callbacks->yajl_start_map(hand->ctx)); 270 | } 271 | stateToPush = yajl_state_map_start; 272 | break; 273 | case yajl_tok_left_brace: 274 | if (hand->callbacks && hand->callbacks->yajl_start_array) { 275 | _CC_CHK(hand->callbacks->yajl_start_array(hand->ctx)); 276 | } 277 | stateToPush = yajl_state_array_start; 278 | break; 279 | case yajl_tok_integer: 280 | if (hand->callbacks) { 281 | if (hand->callbacks->yajl_number) { 282 | _CC_CHK(hand->callbacks->yajl_number( 283 | hand->ctx,(const char *) buf, bufLen)); 284 | } else if (hand->callbacks->yajl_integer) { 285 | long long int i = 0; 286 | errno = 0; 287 | i = yajl_parse_integer(buf, bufLen); 288 | if ((i == LLONG_MIN || i == LLONG_MAX) && 289 | errno == ERANGE) 290 | { 291 | yajl_bs_set(hand->stateStack, 292 | yajl_state_parse_error); 293 | hand->parseError = "integer overflow" ; 294 | /* try to restore error offset */ 295 | if (*offset >= bufLen) *offset -= bufLen; 296 | else *offset = 0; 297 | goto around_again; 298 | } 299 | _CC_CHK(hand->callbacks->yajl_integer(hand->ctx, 300 | i)); 301 | } 302 | } 303 | break; 304 | case yajl_tok_double: 305 | if (hand->callbacks) { 306 | if (hand->callbacks->yajl_number) { 307 | _CC_CHK(hand->callbacks->yajl_number( 308 | hand->ctx, (const char *) buf, bufLen)); 309 | } else if (hand->callbacks->yajl_double) { 310 | double d = 0.0; 311 | yajl_buf_clear(hand->decodeBuf); 312 | yajl_buf_append(hand->decodeBuf, buf, bufLen); 313 | buf = yajl_buf_data(hand->decodeBuf); 314 | errno = 0; 315 | d = strtod((char *) buf, NULL); 316 | if ((d == HUGE_VAL || d == -HUGE_VAL) && 317 | errno == ERANGE) 318 | { 319 | yajl_bs_set(hand->stateStack, 320 | yajl_state_parse_error); 321 | hand->parseError = "numeric (floating point) " 322 | "overflow"; 323 | /* try to restore error offset */ 324 | if (*offset >= bufLen) *offset -= bufLen; 325 | else *offset = 0; 326 | goto around_again; 327 | } 328 | _CC_CHK(hand->callbacks->yajl_double(hand->ctx, 329 | d)); 330 | } 331 | } 332 | break; 333 | case yajl_tok_right_brace: { 334 | if (yajl_bs_current(hand->stateStack) == 335 | yajl_state_array_start) 336 | { 337 | if (hand->callbacks && 338 | hand->callbacks->yajl_end_array) 339 | { 340 | _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx)); 341 | } 342 | yajl_bs_pop(hand->stateStack); 343 | goto around_again; 344 | } 345 | /* intentional fall-through */ 346 | } 347 | case yajl_tok_colon: 348 | case yajl_tok_comma: 349 | case yajl_tok_right_bracket: 350 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 351 | hand->parseError = 352 | "unallowed token at this point in JSON text"; 353 | goto around_again; 354 | default: 355 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 356 | hand->parseError = "invalid token, internal error"; 357 | goto around_again; 358 | } 359 | /* got a value. transition depends on the state we're in. */ 360 | { 361 | yajl_state s = yajl_bs_current(hand->stateStack); 362 | if (s == yajl_state_start || s == yajl_state_got_value) { 363 | yajl_bs_set(hand->stateStack, yajl_state_parse_complete); 364 | } else if (s == yajl_state_map_need_val) { 365 | yajl_bs_set(hand->stateStack, yajl_state_map_got_val); 366 | } else { 367 | yajl_bs_set(hand->stateStack, yajl_state_array_got_val); 368 | } 369 | } 370 | if (stateToPush != yajl_state_start) { 371 | yajl_bs_push(hand->stateStack, stateToPush); 372 | } 373 | 374 | goto around_again; 375 | } 376 | case yajl_state_map_start: 377 | case yajl_state_map_need_key: { 378 | /* only difference between these two states is that in 379 | * start '}' is valid, whereas in need_key, we've parsed 380 | * a comma, and a string key _must_ follow */ 381 | tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, 382 | offset, &buf, &bufLen); 383 | switch (tok) { 384 | case yajl_tok_eof: 385 | return yajl_status_ok; 386 | case yajl_tok_error: 387 | yajl_bs_set(hand->stateStack, yajl_state_lexical_error); 388 | goto around_again; 389 | case yajl_tok_string_with_escapes: 390 | if (hand->callbacks && hand->callbacks->yajl_map_key) { 391 | yajl_buf_clear(hand->decodeBuf); 392 | yajl_string_decode(hand->decodeBuf, buf, bufLen); 393 | buf = yajl_buf_data(hand->decodeBuf); 394 | bufLen = yajl_buf_len(hand->decodeBuf); 395 | } 396 | /* intentional fall-through */ 397 | case yajl_tok_string: 398 | if (hand->callbacks && hand->callbacks->yajl_map_key) { 399 | _CC_CHK(hand->callbacks->yajl_map_key(hand->ctx, buf, 400 | bufLen)); 401 | } 402 | yajl_bs_set(hand->stateStack, yajl_state_map_sep); 403 | goto around_again; 404 | case yajl_tok_right_bracket: 405 | if (yajl_bs_current(hand->stateStack) == 406 | yajl_state_map_start) 407 | { 408 | if (hand->callbacks && hand->callbacks->yajl_end_map) { 409 | _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx)); 410 | } 411 | yajl_bs_pop(hand->stateStack); 412 | goto around_again; 413 | } 414 | default: 415 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 416 | hand->parseError = 417 | "invalid object key (must be a string)"; 418 | goto around_again; 419 | } 420 | } 421 | case yajl_state_map_sep: { 422 | tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, 423 | offset, &buf, &bufLen); 424 | switch (tok) { 425 | case yajl_tok_colon: 426 | yajl_bs_set(hand->stateStack, yajl_state_map_need_val); 427 | goto around_again; 428 | case yajl_tok_eof: 429 | return yajl_status_ok; 430 | case yajl_tok_error: 431 | yajl_bs_set(hand->stateStack, yajl_state_lexical_error); 432 | goto around_again; 433 | default: 434 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 435 | hand->parseError = "object key and value must " 436 | "be separated by a colon (':')"; 437 | goto around_again; 438 | } 439 | } 440 | case yajl_state_map_got_val: { 441 | tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, 442 | offset, &buf, &bufLen); 443 | switch (tok) { 444 | case yajl_tok_right_bracket: 445 | if (hand->callbacks && hand->callbacks->yajl_end_map) { 446 | _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx)); 447 | } 448 | yajl_bs_pop(hand->stateStack); 449 | goto around_again; 450 | case yajl_tok_comma: 451 | yajl_bs_set(hand->stateStack, yajl_state_map_need_key); 452 | goto around_again; 453 | case yajl_tok_eof: 454 | return yajl_status_ok; 455 | case yajl_tok_error: 456 | yajl_bs_set(hand->stateStack, yajl_state_lexical_error); 457 | goto around_again; 458 | default: 459 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 460 | hand->parseError = "after key and value, inside map, " 461 | "I expect ',' or '}'"; 462 | /* try to restore error offset */ 463 | if (*offset >= bufLen) *offset -= bufLen; 464 | else *offset = 0; 465 | goto around_again; 466 | } 467 | } 468 | case yajl_state_array_got_val: { 469 | tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, 470 | offset, &buf, &bufLen); 471 | switch (tok) { 472 | case yajl_tok_right_brace: 473 | if (hand->callbacks && hand->callbacks->yajl_end_array) { 474 | _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx)); 475 | } 476 | yajl_bs_pop(hand->stateStack); 477 | goto around_again; 478 | case yajl_tok_comma: 479 | yajl_bs_set(hand->stateStack, yajl_state_array_need_val); 480 | goto around_again; 481 | case yajl_tok_eof: 482 | return yajl_status_ok; 483 | case yajl_tok_error: 484 | yajl_bs_set(hand->stateStack, yajl_state_lexical_error); 485 | goto around_again; 486 | default: 487 | yajl_bs_set(hand->stateStack, yajl_state_parse_error); 488 | hand->parseError = 489 | "after array element, I expect ',' or ']'"; 490 | goto around_again; 491 | } 492 | } 493 | } 494 | 495 | abort(); 496 | return yajl_status_error; 497 | } 498 | 499 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef __YAJL_PARSER_H__ 18 | #define __YAJL_PARSER_H__ 19 | 20 | #include "api/yajl_parse.h" 21 | #include "yajl_bytestack.h" 22 | #include "yajl_buf.h" 23 | #include "yajl_lex.h" 24 | 25 | 26 | typedef enum { 27 | yajl_state_start = 0, 28 | yajl_state_parse_complete, 29 | yajl_state_parse_error, 30 | yajl_state_lexical_error, 31 | yajl_state_map_start, 32 | yajl_state_map_sep, 33 | yajl_state_map_need_val, 34 | yajl_state_map_got_val, 35 | yajl_state_map_need_key, 36 | yajl_state_array_start, 37 | yajl_state_array_got_val, 38 | yajl_state_array_need_val, 39 | yajl_state_got_value, 40 | } yajl_state; 41 | 42 | struct yajl_handle_t { 43 | const yajl_callbacks * callbacks; 44 | void * ctx; 45 | yajl_lexer lexer; 46 | const char * parseError; 47 | /* the number of bytes consumed from the last client buffer, 48 | * in the case of an error this will be an error offset, in the 49 | * case of an error this can be used as the error offset */ 50 | size_t bytesConsumed; 51 | /* temporary storage for decoded strings */ 52 | yajl_buf decodeBuf; 53 | /* a stack of states. access with yajl_state_XXX routines */ 54 | yajl_bytestack stateStack; 55 | /* memory allocation routines */ 56 | yajl_alloc_funcs alloc; 57 | /* bitfield */ 58 | unsigned int flags; 59 | }; 60 | 61 | yajl_status 62 | yajl_do_parse(yajl_handle handle, const unsigned char * jsonText, 63 | size_t jsonTextLen); 64 | 65 | yajl_status 66 | yajl_do_finish(yajl_handle handle); 67 | 68 | unsigned char * 69 | yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, 70 | size_t jsonTextLen, int verbose); 71 | 72 | /* A little built in integer parsing routine with the same semantics as strtol 73 | * that's unaffected by LOCALE. */ 74 | long long 75 | yajl_parse_integer(const unsigned char *number, unsigned int length); 76 | 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_tree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010-2011 Florian Forster 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "api/yajl_tree.h" 24 | #include "api/yajl_parse.h" 25 | 26 | #include "yajl_parser.h" 27 | 28 | #if defined(_WIN32) || defined(WIN32) 29 | #define snprintf sprintf_s 30 | #endif 31 | 32 | #define STATUS_CONTINUE 1 33 | #define STATUS_ABORT 0 34 | 35 | struct stack_elem_s; 36 | typedef struct stack_elem_s stack_elem_t; 37 | struct stack_elem_s 38 | { 39 | char * key; 40 | yajl_val value; 41 | stack_elem_t *next; 42 | }; 43 | 44 | struct context_s 45 | { 46 | stack_elem_t *stack; 47 | yajl_val root; 48 | char *errbuf; 49 | size_t errbuf_size; 50 | }; 51 | typedef struct context_s context_t; 52 | 53 | #define RETURN_ERROR(ctx,retval,...) { \ 54 | if ((ctx)->errbuf != NULL) \ 55 | snprintf ((ctx)->errbuf, (ctx)->errbuf_size, __VA_ARGS__); \ 56 | return (retval); \ 57 | } 58 | 59 | static yajl_val value_alloc (yajl_type type) 60 | { 61 | yajl_val v; 62 | 63 | v = malloc (sizeof (*v)); 64 | if (v == NULL) return (NULL); 65 | memset (v, 0, sizeof (*v)); 66 | v->type = type; 67 | 68 | return (v); 69 | } 70 | 71 | static void yajl_object_free (yajl_val v) 72 | { 73 | size_t i; 74 | 75 | if (!YAJL_IS_OBJECT(v)) return; 76 | 77 | for (i = 0; i < v->u.object.len; i++) 78 | { 79 | free((char *) v->u.object.keys[i]); 80 | v->u.object.keys[i] = NULL; 81 | yajl_tree_free (v->u.object.values[i]); 82 | v->u.object.values[i] = NULL; 83 | } 84 | 85 | free((void*) v->u.object.keys); 86 | free(v->u.object.values); 87 | free(v); 88 | } 89 | 90 | static void yajl_array_free (yajl_val v) 91 | { 92 | size_t i; 93 | 94 | if (!YAJL_IS_ARRAY(v)) return; 95 | 96 | for (i = 0; i < v->u.array.len; i++) 97 | { 98 | yajl_tree_free (v->u.array.values[i]); 99 | v->u.array.values[i] = NULL; 100 | } 101 | 102 | free(v->u.array.values); 103 | free(v); 104 | } 105 | 106 | /* 107 | * Parsing nested objects and arrays is implemented using a stack. When a new 108 | * object or array starts (a curly or a square opening bracket is read), an 109 | * appropriate value is pushed on the stack. When the end of the object is 110 | * reached (an appropriate closing bracket has been read), the value is popped 111 | * off the stack and added to the enclosing object using "context_add_value". 112 | */ 113 | static int context_push(context_t *ctx, yajl_val v) 114 | { 115 | stack_elem_t *stack; 116 | 117 | stack = malloc (sizeof (*stack)); 118 | if (stack == NULL) 119 | RETURN_ERROR (ctx, ENOMEM, "Out of memory"); 120 | memset (stack, 0, sizeof (*stack)); 121 | 122 | assert ((ctx->stack == NULL) 123 | || YAJL_IS_OBJECT (v) 124 | || YAJL_IS_ARRAY (v)); 125 | 126 | stack->value = v; 127 | stack->next = ctx->stack; 128 | ctx->stack = stack; 129 | 130 | return (0); 131 | } 132 | 133 | static yajl_val context_pop(context_t *ctx) 134 | { 135 | stack_elem_t *stack; 136 | yajl_val v; 137 | 138 | if (ctx->stack == NULL) 139 | RETURN_ERROR (ctx, NULL, "context_pop: " 140 | "Bottom of stack reached prematurely"); 141 | 142 | stack = ctx->stack; 143 | ctx->stack = stack->next; 144 | 145 | v = stack->value; 146 | 147 | free (stack); 148 | 149 | return (v); 150 | } 151 | 152 | static int object_add_keyval(context_t *ctx, 153 | yajl_val obj, char *key, yajl_val value) 154 | { 155 | const char **tmpk; 156 | yajl_val *tmpv; 157 | 158 | /* We're checking for NULL in "context_add_value" or its callers. */ 159 | assert (ctx != NULL); 160 | assert (obj != NULL); 161 | assert (key != NULL); 162 | assert (value != NULL); 163 | 164 | /* We're assuring that "obj" is an object in "context_add_value". */ 165 | assert(YAJL_IS_OBJECT(obj)); 166 | 167 | tmpk = realloc((void *) obj->u.object.keys, sizeof(*(obj->u.object.keys)) * (obj->u.object.len + 1)); 168 | if (tmpk == NULL) 169 | RETURN_ERROR(ctx, ENOMEM, "Out of memory"); 170 | obj->u.object.keys = tmpk; 171 | 172 | tmpv = realloc(obj->u.object.values, sizeof (*obj->u.object.values) * (obj->u.object.len + 1)); 173 | if (tmpv == NULL) 174 | RETURN_ERROR(ctx, ENOMEM, "Out of memory"); 175 | obj->u.object.values = tmpv; 176 | 177 | obj->u.object.keys[obj->u.object.len] = key; 178 | obj->u.object.values[obj->u.object.len] = value; 179 | obj->u.object.len++; 180 | 181 | return (0); 182 | } 183 | 184 | static int array_add_value (context_t *ctx, 185 | yajl_val array, yajl_val value) 186 | { 187 | yajl_val *tmp; 188 | 189 | /* We're checking for NULL pointers in "context_add_value" or its 190 | * callers. */ 191 | assert (ctx != NULL); 192 | assert (array != NULL); 193 | assert (value != NULL); 194 | 195 | /* "context_add_value" will only call us with array values. */ 196 | assert(YAJL_IS_ARRAY(array)); 197 | 198 | tmp = realloc(array->u.array.values, 199 | sizeof(*(array->u.array.values)) * (array->u.array.len + 1)); 200 | if (tmp == NULL) 201 | RETURN_ERROR(ctx, ENOMEM, "Out of memory"); 202 | array->u.array.values = tmp; 203 | array->u.array.values[array->u.array.len] = value; 204 | array->u.array.len++; 205 | 206 | return 0; 207 | } 208 | 209 | /* 210 | * Add a value to the value on top of the stack or the "root" member in the 211 | * context if the end of the parsing process is reached. 212 | */ 213 | static int context_add_value (context_t *ctx, yajl_val v) 214 | { 215 | /* We're checking for NULL values in all the calling functions. */ 216 | assert (ctx != NULL); 217 | assert (v != NULL); 218 | 219 | /* 220 | * There are three valid states in which this function may be called: 221 | * - There is no value on the stack => This is the only value. This is the 222 | * last step done when parsing a document. We assign the value to the 223 | * "root" member and return. 224 | * - The value on the stack is an object. In this case store the key on the 225 | * stack or, if the key has already been read, add key and value to the 226 | * object. 227 | * - The value on the stack is an array. In this case simply add the value 228 | * and return. 229 | */ 230 | if (ctx->stack == NULL) 231 | { 232 | assert (ctx->root == NULL); 233 | ctx->root = v; 234 | return (0); 235 | } 236 | else if (YAJL_IS_OBJECT (ctx->stack->value)) 237 | { 238 | if (ctx->stack->key == NULL) 239 | { 240 | if (!YAJL_IS_STRING (v)) 241 | RETURN_ERROR (ctx, EINVAL, "context_add_value: " 242 | "Object key is not a string (%#04x)", 243 | v->type); 244 | 245 | ctx->stack->key = v->u.string; 246 | v->u.string = NULL; 247 | free(v); 248 | return (0); 249 | } 250 | else /* if (ctx->key != NULL) */ 251 | { 252 | char * key; 253 | 254 | key = ctx->stack->key; 255 | ctx->stack->key = NULL; 256 | return (object_add_keyval (ctx, ctx->stack->value, key, v)); 257 | } 258 | } 259 | else if (YAJL_IS_ARRAY (ctx->stack->value)) 260 | { 261 | return (array_add_value (ctx, ctx->stack->value, v)); 262 | } 263 | else 264 | { 265 | RETURN_ERROR (ctx, EINVAL, "context_add_value: Cannot add value to " 266 | "a value of type %#04x (not a composite type)", 267 | ctx->stack->value->type); 268 | } 269 | } 270 | 271 | static int handle_string (void *ctx, 272 | const unsigned char *string, size_t string_length) 273 | { 274 | yajl_val v; 275 | 276 | v = value_alloc (yajl_t_string); 277 | if (v == NULL) 278 | RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); 279 | 280 | v->u.string = malloc (string_length + 1); 281 | if (v->u.string == NULL) 282 | { 283 | free (v); 284 | RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); 285 | } 286 | memcpy(v->u.string, string, string_length); 287 | v->u.string[string_length] = 0; 288 | 289 | return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 290 | } 291 | 292 | static int handle_number (void *ctx, const char *string, size_t string_length) 293 | { 294 | yajl_val v; 295 | char *endptr; 296 | 297 | v = value_alloc(yajl_t_number); 298 | if (v == NULL) 299 | RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory"); 300 | 301 | v->u.number.r = malloc(string_length + 1); 302 | if (v->u.number.r == NULL) 303 | { 304 | free(v); 305 | RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory"); 306 | } 307 | memcpy(v->u.number.r, string, string_length); 308 | v->u.number.r[string_length] = 0; 309 | 310 | v->u.number.flags = 0; 311 | 312 | errno = 0; 313 | v->u.number.i = yajl_parse_integer((const unsigned char *) v->u.number.r, 314 | strlen(v->u.number.r)); 315 | if (errno == 0) 316 | v->u.number.flags |= YAJL_NUMBER_INT_VALID; 317 | 318 | endptr = NULL; 319 | errno = 0; 320 | v->u.number.d = strtod(v->u.number.r, &endptr); 321 | if ((errno == 0) && (endptr != NULL) && (*endptr == 0)) 322 | v->u.number.flags |= YAJL_NUMBER_DOUBLE_VALID; 323 | 324 | return ((context_add_value(ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 325 | } 326 | 327 | static int handle_start_map (void *ctx) 328 | { 329 | yajl_val v; 330 | 331 | v = value_alloc(yajl_t_object); 332 | if (v == NULL) 333 | RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); 334 | 335 | v->u.object.keys = NULL; 336 | v->u.object.values = NULL; 337 | v->u.object.len = 0; 338 | 339 | return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 340 | } 341 | 342 | static int handle_end_map (void *ctx) 343 | { 344 | yajl_val v; 345 | 346 | v = context_pop (ctx); 347 | if (v == NULL) 348 | return (STATUS_ABORT); 349 | 350 | return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 351 | } 352 | 353 | static int handle_start_array (void *ctx) 354 | { 355 | yajl_val v; 356 | 357 | v = value_alloc(yajl_t_array); 358 | if (v == NULL) 359 | RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); 360 | 361 | v->u.array.values = NULL; 362 | v->u.array.len = 0; 363 | 364 | return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 365 | } 366 | 367 | static int handle_end_array (void *ctx) 368 | { 369 | yajl_val v; 370 | 371 | v = context_pop (ctx); 372 | if (v == NULL) 373 | return (STATUS_ABORT); 374 | 375 | return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 376 | } 377 | 378 | static int handle_boolean (void *ctx, int boolean_value) 379 | { 380 | yajl_val v; 381 | 382 | v = value_alloc (boolean_value ? yajl_t_true : yajl_t_false); 383 | if (v == NULL) 384 | RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); 385 | 386 | return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 387 | } 388 | 389 | static int handle_null (void *ctx) 390 | { 391 | yajl_val v; 392 | 393 | v = value_alloc (yajl_t_null); 394 | if (v == NULL) 395 | RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); 396 | 397 | return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); 398 | } 399 | 400 | /* 401 | * Public functions 402 | */ 403 | yajl_val yajl_tree_parse (const char *input, 404 | char *error_buffer, size_t error_buffer_size) 405 | { 406 | static const yajl_callbacks callbacks = 407 | { 408 | /* null = */ handle_null, 409 | /* boolean = */ handle_boolean, 410 | /* integer = */ NULL, 411 | /* double = */ NULL, 412 | /* number = */ handle_number, 413 | /* string = */ handle_string, 414 | /* start map = */ handle_start_map, 415 | /* map key = */ handle_string, 416 | /* end map = */ handle_end_map, 417 | /* start array = */ handle_start_array, 418 | /* end array = */ handle_end_array 419 | }; 420 | 421 | yajl_handle handle; 422 | yajl_status status; 423 | char * internal_err_str; 424 | context_t ctx = { NULL, NULL, NULL, 0 }; 425 | 426 | ctx.errbuf = error_buffer; 427 | ctx.errbuf_size = error_buffer_size; 428 | 429 | if (error_buffer != NULL) 430 | memset (error_buffer, 0, error_buffer_size); 431 | 432 | handle = yajl_alloc (&callbacks, NULL, &ctx); 433 | yajl_config(handle, yajl_allow_comments, 1); 434 | 435 | status = yajl_parse(handle, 436 | (unsigned char *) input, 437 | strlen (input)); 438 | status = yajl_complete_parse (handle); 439 | if (status != yajl_status_ok) { 440 | if (error_buffer != NULL && error_buffer_size > 0) { 441 | internal_err_str = (char *) yajl_get_error(handle, 1, 442 | (const unsigned char *) input, 443 | strlen(input)); 444 | snprintf(error_buffer, error_buffer_size, "%s", internal_err_str); 445 | YA_FREE(&(handle->alloc), internal_err_str); 446 | } 447 | yajl_free (handle); 448 | return NULL; 449 | } 450 | 451 | yajl_free (handle); 452 | return (ctx.root); 453 | } 454 | 455 | yajl_val yajl_tree_get(yajl_val n, const char ** path, yajl_type type) 456 | { 457 | if (!path) return NULL; 458 | while (n && *path) { 459 | size_t i; 460 | size_t len; 461 | 462 | if (n->type != yajl_t_object) return NULL; 463 | len = n->u.object.len; 464 | for (i = 0; i < len; i++) { 465 | if (!strcmp(*path, n->u.object.keys[i])) { 466 | n = n->u.object.values[i]; 467 | break; 468 | } 469 | } 470 | if (i == len) return NULL; 471 | path++; 472 | } 473 | if (n && type != yajl_t_any && type != n->type) n = NULL; 474 | return n; 475 | } 476 | 477 | void yajl_tree_free (yajl_val v) 478 | { 479 | if (v == NULL) return; 480 | 481 | if (YAJL_IS_STRING(v)) 482 | { 483 | free(v->u.string); 484 | free(v); 485 | } 486 | else if (YAJL_IS_NUMBER(v)) 487 | { 488 | free(v->u.number.r); 489 | free(v); 490 | } 491 | else if (YAJL_GET_OBJECT(v)) 492 | { 493 | yajl_object_free(v); 494 | } 495 | else if (YAJL_GET_ARRAY(v)) 496 | { 497 | yajl_array_free(v); 498 | } 499 | else /* if (yajl_t_true or yajl_t_false or yajl_t_null) */ 500 | { 501 | free(v); 502 | } 503 | } 504 | -------------------------------------------------------------------------------- /3rdparty/yajl/yajl_version.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int yajl_version(void) 4 | { 5 | return YAJL_VERSION; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # These should be defined in .config 2 | #GECKO_ROOT = /Volumes/fennec/gecko-desktop 3 | #GECKO_OBJ = $(GECKO_ROOT)/obj-x86_64-apple-darwin12.5.0 4 | #For Linux: 5 | #SDL_INCLUDE_PATH = path/to/sdl/header/files 6 | #SDL_LIB_PATH = path/to/sdl/libs 7 | 8 | include .config 9 | PLATFORM:=$(shell uname) 10 | include platforms/common.mk 11 | include platforms/$(PLATFORM).mk 12 | 13 | BUILD_DIR=./build-$(PLATFORM) 14 | 15 | LIBS = \ 16 | $(GECKO_OBJ)/mfbt/libmfbt.a.desc \ 17 | $(GECKO_OBJ)/layout/media/webrtc/libwebrtc.a.desc \ 18 | $(GECKO_OBJ)/media/libopus/libmedia_libopus.a.desc \ 19 | $(GECKO_OBJ)/media/libvpx/libmedia_libvpx.a.desc \ 20 | $(GECKO_OBJ)/media/libjpeg/libmedia_libjpeg.a.desc \ 21 | $(GECKO_OBJ)/media/libspeex_resampler/src/libspeex.a.desc \ 22 | $(GECKO_OBJ)/netwerk/srtp/src/libnksrtp_s.a.desc \ 23 | $(GECKO_OBJ)/media/mtransport/standalone/libmtransport_standalone.a.desc \ 24 | $(GECKO_OBJ)/media/webrtc/signalingstandalone/signaling_ecc/libecc.a.desc \ 25 | $(GECKO_OBJ)/xpcom/libxpcomrt/libxpcomrt.a.desc \ 26 | $(GECKO_OBJ)/dom/media/standalone/libmedia_standalone.a.desc \ 27 | $(GECKO_OBJ)/netwerk/standalone/libnecko_standalone.a.desc \ 28 | $(GECKO_OBJ)/intl/unicharutil/util/standalone/libunicharutil_standalone.a.desc \ 29 | $(GECKO_OBJ)/security/nss/lib/pk11wrap/static/libpk11wrap_s.a.desc \ 30 | $(GECKO_OBJ)/security/nss/lib/freebl/static/libfreebl_s.a.desc \ 31 | $(GECKO_OBJ)/db/sqlite3/src/libdb_sqlite3_src.a.desc \ 32 | $(GECKO_OBJ)/memory/fallible/libfallible.a.desc \ 33 | $(GECKO_OBJ)/media/libyuv/libyuv_libyuv/libyuv.a.desc 34 | 35 | LIB_ROLLUP = $(BUILD_DIR)/librollup.a 36 | 37 | JSON = $(BUILD_DIR)/libyajl.a 38 | 39 | all: player glplayer 40 | 41 | $(JSON): 42 | cd 3rdparty/yajl; make 43 | 44 | OBJS = \ 45 | $(BUILD_DIR)/player.o \ 46 | $(BUILD_DIR)/json.o 47 | 48 | player: $(OBJS) $(LIB_ROLLUP) $(BUILD_DIR)/renderSDL2.o $(JSON) 49 | $(CXX) $(OBJS) $(BUILD_DIR)/renderSDL2.o $(LIB_ROLLUP) $(JSON) $(SDL_LFLAGS) $(LFLAGS) -o $@ 50 | 51 | glplayer: $(OBJS) $(LIB_ROLLUP) $(BUILD_DIR)/renderGL.o $(JSON) 52 | $(CXX) $(OBJS) $(BUILD_DIR)/renderGL.o $(LIB_ROLLUP) $(JSON) $(SDL_LFLAGS) $(LFLAGS) -o $@ 53 | 54 | stubplayer: $(OBJS) $(LIB_ROLLUP) $(BUILD_DIR)/renderStub.o $(JSON) 55 | $(CXX) $(OBJS) $(BUILD_DIR)/renderStub.o $(LIB_ROLLUP) $(JSON) $(SDL_LFLAGS) $(LFLAGS) -o $@ 56 | 57 | $(BUILD_DIR)/%.o: %.cpp 58 | @mkdir -p $(BUILD_DIR) 59 | $(CXX) $(CFLAGS) $(SDL_CFLAGS) $(INCLUDE) $^ -c -o $@ 60 | 61 | $(LIB_ROLLUP): $(LIBS) 62 | @mkdir -p $(BUILD_DIR) 63 | $(AR) cr $@ `python ./tools/expand.py $(LIBS)` 64 | 65 | clean: 66 | rm -f $(LIB_ROLLUP) $(JSON) $(BUILD_DIR)/*.o 67 | 68 | clobber: clean 69 | rm -f player 70 | rm -f glplayer 71 | rm -rf $(BUILD_DIR) 72 | -------------------------------------------------------------------------------- /device/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Test Roku Device 4 | A4CAF641-606F-4720-9A23-EEF414CF8C94 5 | Roku, Inc. 6 | Roku 3 7 | 8 | -------------------------------------------------------------------------------- /device/query/apps: -------------------------------------------------------------------------------- 1 | 2 | WebRTC Player 3 | 4 | -------------------------------------------------------------------------------- /device/simulator.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.1' 2 | 3 | import os 4 | import posixpath 5 | import BaseHTTPServer 6 | import urllib 7 | import cgi 8 | import shutil 9 | import mimetypes 10 | import SocketServer 11 | import threading 12 | import socket 13 | import struct 14 | try: 15 | from cStringIO import StringIO 16 | except ImportError: 17 | from StringIO import StringIO 18 | 19 | from subprocess import Popen, PIPE 20 | 21 | class ECPRestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 22 | 23 | server_version = "PeerConnectionTestHTTP/" + __version__ 24 | 25 | def do_GET(self): 26 | print 'do_GET: ' + self.path 27 | f = self.send_head() 28 | if f: 29 | self.copyfile(f, self.wfile) 30 | f.close() 31 | 32 | def do_HEAD(self): 33 | print 'do_HEAD: ' + self.path 34 | f = self.send_head() 35 | if f: 36 | f.close() 37 | 38 | # def do_PUT(self): 39 | # print 'do_PUT: ' + self.path 40 | # if self.path == '/launch/99999': 41 | # self.send_response(200) 42 | # else: 43 | # self.send_response(500) 44 | # self.end_headers() 45 | 46 | def do_POST(self): 47 | print 'do_POST: ' + self.path 48 | if self.path == '/launch/99999': 49 | # print 'LAUNCH!!!!!' 50 | pc = Popen(['../glplayer',]) 51 | self.send_response(200) 52 | else: 53 | self.send_response(500) 54 | self.end_headers() 55 | 56 | def send_head(self): 57 | path = self.translate_path(self.path) 58 | f = None 59 | if os.path.isdir(path): 60 | if not self.path.endswith('/'): 61 | # redirect browser - doing basically what apache does 62 | self.send_response(301) 63 | self.send_header("Location", self.path + "/") 64 | self.end_headers() 65 | return None 66 | for index in "index.xml", "index.html", "index.htm": 67 | index = os.path.join(path, index) 68 | if os.path.exists(index): 69 | path = index 70 | break 71 | else: 72 | self.send_error(404, "File not found") 73 | return None 74 | ctype = self.guess_type(path) 75 | try: 76 | # Always read in binary mode. Opening files in text mode may cause 77 | # newline translations, making the actual size of the content 78 | # transmitted *less* than the content-length! 79 | f = open(path, 'rb') 80 | except IOError: 81 | self.send_error(404, "File not found") 82 | return None 83 | self.send_response(200) 84 | self.send_header("Content-type", ctype) 85 | fs = os.fstat(f.fileno()) 86 | self.send_header("Content-Length", str(fs[6])) 87 | self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) 88 | self.end_headers() 89 | return f 90 | 91 | def translate_path(self, path): 92 | # abandon query parameters 93 | path = path.split('?',1)[0] 94 | path = path.split('#',1)[0] 95 | path = posixpath.normpath(urllib.unquote(path)) 96 | words = path.split('/') 97 | words = filter(None, words) 98 | path = os.getcwd() 99 | for word in words: 100 | drive, word = os.path.splitdrive(word) 101 | head, word = os.path.split(word) 102 | if word in (os.curdir, os.pardir): continue 103 | path = os.path.join(path, word) 104 | return path 105 | 106 | def copyfile(self, source, outputfile): 107 | shutil.copyfileobj(source, outputfile) 108 | 109 | def guess_type(self, path): 110 | base, ext = posixpath.splitext(path) 111 | if ext in self.extensions_map: 112 | return self.extensions_map[ext] 113 | ext = ext.lower() 114 | if ext in self.extensions_map: 115 | return self.extensions_map[ext] 116 | else: 117 | return self.extensions_map[''] 118 | 119 | if not mimetypes.inited: 120 | mimetypes.init() # try to read system mime.types 121 | extensions_map = mimetypes.types_map.copy() 122 | extensions_map.update({ 123 | '': 'application/octet-stream', # Default 124 | '.py': 'text/plain', 125 | '.c': 'text/plain', 126 | '.h': 'text/plain', 127 | }) 128 | 129 | tempSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 130 | tempSocket.connect(("gmail.com",80)) 131 | hostIP = tempSocket.getsockname()[0]; 132 | tempSocket.close() 133 | 134 | reply = """HTTP/1.1 200 OK 135 | Cache-Control: max-age=300 136 | ST: roku:ecp 137 | Location: http://""" + hostIP + """:8060/ 138 | USN: uuid:roku:ecp:P0A070000007 139 | 140 | """ 141 | 142 | HOST_NAME = '' 143 | PORT_NUMBER=8060 144 | 145 | def ssdpWorker(): 146 | print "Starting SSDP thread" 147 | MCAST_GRP = "239.255.255.250" 148 | MCAST_PORT = 1900 149 | 150 | insock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 151 | insock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 152 | insock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 153 | insock.bind((MCAST_GRP, MCAST_PORT)) 154 | mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) 155 | insock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) 156 | 157 | outsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 158 | outsock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) 159 | 160 | while True: 161 | packet = insock.recv(10240) 162 | # print "recv->" 163 | # print packet 164 | values = packet.split('\r\n') 165 | if len(values) > 2 and values[0].find('M-SEARCH') == 0: 166 | for line in values[1:]: 167 | if line == 'ST: roku:ecp': 168 | # print "send->" 169 | # print reply 170 | outsock.sendto(reply, (MCAST_GRP, MCAST_PORT)) 171 | 172 | print "Starting Simulator" 173 | t = threading.Thread(target=ssdpWorker) 174 | t.setDaemon(True) 175 | t.start() 176 | 177 | server_class = BaseHTTPServer.HTTPServer 178 | httpd = server_class((HOST_NAME, PORT_NUMBER), ECPRestHandler) 179 | 180 | 181 | try: 182 | while True: 183 | httpd.handle_request() 184 | except KeyboardInterrupt: 185 | pass 186 | 187 | print "\nEXIT" 188 | httpd.server_close() 189 | -------------------------------------------------------------------------------- /device/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PATH_FILE=../.config 4 | 5 | if [ ! -f $PATH_FILE ] ; then 6 | echo $PATH_FILE not found! 7 | exit 1 8 | fi 9 | 10 | # strip out the parenthesis from the Makefile config so it can be used by sh 11 | eval `tr -d '()' < $PATH_FILE` 12 | 13 | # Setup for both Linux and Mac to run player 14 | export LD_LIBRARY_PATH=$GECKO_OBJ/dist/lib 15 | export DYLD_LIBRARY_PATH=$GECKO_OBJ/dist/lib 16 | #export NSPR_LOG_MODULES=all:5 17 | 18 | # Start simulator 19 | python simulator.py 20 | -------------------------------------------------------------------------------- /json.cpp: -------------------------------------------------------------------------------- 1 | #include "api/yajl_gen.h" 2 | #include "api/yajl_tree.h" 3 | #include "json.h" 4 | #include 5 | 6 | #define VALIDATE_STATE() if(!mState) { return false; } 7 | 8 | struct JSONParser::State { 9 | yajl_val mTree; 10 | bool mValid; 11 | std::string mError; 12 | 13 | State() : mTree(NULL), mValid(true) {}; 14 | ~State() 15 | { 16 | yajl_tree_free(mTree); mTree = NULL; 17 | } 18 | }; 19 | 20 | JSONParser::JSONParser(const char* data) : mState(NULL) 21 | { 22 | const int errorSize = 1024; 23 | char error[errorSize]; 24 | mState = new State; 25 | 26 | mState->mTree = yajl_tree_parse(data, error, errorSize); 27 | 28 | if (!mState->mTree) { 29 | mState->mValid = false; 30 | mState->mError = error; 31 | } 32 | } 33 | 34 | JSONParser::~JSONParser() 35 | { 36 | delete mState; mState = NULL; 37 | } 38 | 39 | bool 40 | JSONParser::isValid(std::string& error) 41 | { 42 | VALIDATE_STATE(); 43 | error = mState->mError; 44 | return mState->mValid; 45 | } 46 | 47 | bool 48 | JSONParser::find(const std::string& key, std::string& value) 49 | { 50 | VALIDATE_STATE(); 51 | bool result = false; 52 | 53 | if (mState->mTree) { 54 | const char* path[2] = { key.c_str(), NULL }; 55 | yajl_val str = yajl_tree_get(mState->mTree, path, yajl_t_string); 56 | if (str) { 57 | result = true; 58 | value = YAJL_GET_STRING(str); 59 | } 60 | } 61 | return result; 62 | } 63 | 64 | bool 65 | JSONParser::find(const std::string& key, int& value) 66 | { 67 | VALIDATE_STATE(); 68 | bool result = false; 69 | 70 | if (mState->mTree) { 71 | const char* path[2] = { key.c_str(), NULL }; 72 | yajl_val num = yajl_tree_get(mState->mTree, path, yajl_t_number); 73 | if (YAJL_IS_INTEGER(num)) { 74 | result = true; 75 | value = (int)YAJL_GET_INTEGER(num); 76 | } 77 | } 78 | return result; 79 | } 80 | 81 | struct JSONGenerator::State { 82 | yajl_gen mGen; 83 | State() : mGen(yajl_gen_alloc(NULL)) {} 84 | ~State() 85 | { 86 | yajl_gen_free(mGen); 87 | } 88 | }; 89 | 90 | JSONGenerator::JSONGenerator() : mState (NULL) 91 | { 92 | mState = new State; 93 | } 94 | 95 | JSONGenerator::~JSONGenerator() 96 | { 97 | delete mState; mState = NULL; 98 | } 99 | 100 | bool 101 | JSONGenerator::openMap() 102 | { 103 | VALIDATE_STATE(); 104 | if (yajl_gen_map_open(mState->mGen) != yajl_gen_status_ok) { 105 | return false; 106 | } 107 | return true; 108 | } 109 | 110 | bool 111 | JSONGenerator::closeMap() 112 | { 113 | VALIDATE_STATE(); 114 | if (yajl_gen_map_close(mState->mGen) != yajl_gen_status_ok) { 115 | return false; 116 | } 117 | return true; 118 | } 119 | 120 | bool 121 | JSONGenerator::addPair(const std::string& key, const std::string& value) 122 | { 123 | VALIDATE_STATE(); 124 | if (yajl_gen_string(mState->mGen, (const unsigned char *)key.c_str(), key.length()) != yajl_gen_status_ok) { 125 | return false; 126 | } else if (yajl_gen_string(mState->mGen, (const unsigned char *)value.c_str(), value.length()) != yajl_gen_status_ok) { 127 | return false; 128 | } 129 | return true; 130 | } 131 | 132 | bool 133 | JSONGenerator::addPair(const std::string& key, const int value) 134 | { 135 | VALIDATE_STATE(); 136 | std::stringstream stream; 137 | stream << value; 138 | std::string str = stream.str(); 139 | if (yajl_gen_string(mState->mGen, (const unsigned char *)key.c_str(), key.length()) != yajl_gen_status_ok) { 140 | return false; 141 | } else if (yajl_gen_number(mState->mGen, str.c_str(), str.length()) != yajl_gen_status_ok) { 142 | return false; 143 | } 144 | return true; 145 | } 146 | 147 | bool 148 | JSONGenerator::getJSON(std::string& key) 149 | { 150 | VALIDATE_STATE(); 151 | const unsigned char* buf = NULL; 152 | size_t len = 0; 153 | if (yajl_gen_get_buf(mState->mGen, &buf, &len) != yajl_gen_status_ok) { 154 | return false; 155 | } 156 | key = (const char*)buf; 157 | return true; 158 | } 159 | 160 | -------------------------------------------------------------------------------- /json.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_DOT_H 2 | #define JSON_DOT_H 3 | 4 | #include 5 | 6 | class JSONParser { 7 | public: 8 | JSONParser(const char* data); 9 | ~JSONParser(); 10 | 11 | bool isValid(std::string& error); 12 | bool find(const std::string& key, std::string& value); 13 | bool find(const std::string& key, int& value); 14 | 15 | protected: 16 | struct State; 17 | State* mState; 18 | }; 19 | 20 | class JSONGenerator { 21 | public: 22 | JSONGenerator(); 23 | ~JSONGenerator(); 24 | 25 | bool openMap(); 26 | bool closeMap(); 27 | bool addPair(const std::string& key, const std::string& value); 28 | bool addPair(const char* key, const std::string& value) 29 | { 30 | const std::string strKey(key); 31 | return addPair(strKey, value); 32 | } 33 | bool addPair(const std::string& key, const int value); 34 | bool addPair(const char* key, const int value) 35 | { 36 | const std::string strKey(key); 37 | return addPair(strKey, value); 38 | } 39 | bool getJSON(std::string& key); 40 | 41 | protected: 42 | struct State; 43 | State* mState; 44 | }; 45 | 46 | #endif // #define JSON_DOT_H 47 | -------------------------------------------------------------------------------- /platforms/Darwin.mk: -------------------------------------------------------------------------------- 1 | RENDERNAME=renderGL 2 | 3 | 4 | CFLAGS = \ 5 | -fvisibility=hidden \ 6 | -DCHROMIUM_BUILD \ 7 | -DUSE_LIBJPEG_TURBO='1' \ 8 | -DENABLE_ONE_CLICK_SIGNIN \ 9 | -DENABLE_REMOTING='1' \ 10 | -DENABLE_WEBRTC='1' \ 11 | -DENABLE_CONFIGURATION_POLICY \ 12 | -DENABLE_INPUT_SPEECH \ 13 | -DENABLE_NOTIFICATIONS \ 14 | -DENABLE_HIDPI='1' \ 15 | -DENABLE_GPU='1' \ 16 | -DENABLE_EGLIMAGE='1' \ 17 | -DUSE_SKIA='1' \ 18 | -DENABLE_TASK_MANAGER='1' \ 19 | -DENABLE_WEB_INTENTS='1' \ 20 | -DENABLE_EXTENSIONS='1' \ 21 | -DENABLE_PLUGIN_INSTALLATION='1' \ 22 | -DENABLE_PROTECTOR_SERVICE='1' \ 23 | -DENABLE_SESSION_SERVICE='1' \ 24 | -DENABLE_THEMES='1' \ 25 | -DENABLE_BACKGROUND='1' \ 26 | -DENABLE_AUTOMATION='1' \ 27 | -DENABLE_PRINTING='1' \ 28 | -DENABLE_CAPTIVE_PORTAL_DETECTION='1' \ 29 | -DLOG4CXX_STATIC \ 30 | -D_NO_LOG4CXX \ 31 | -DUSE_SSLEAY \ 32 | -D_CPR_USE_EXTERNAL_LOGGER \ 33 | -DWEBRTC_RELATIVE_PATH \ 34 | -DHAVE_WEBRTC_VIDEO \ 35 | -DHAVE_WEBRTC_VOICE \ 36 | -DHAVE_STDINT_H='1' \ 37 | -DHAVE_STDLIB_H='1' \ 38 | -DHAVE_UINT8_T='1' \ 39 | -DHAVE_UINT16_T='1' \ 40 | -DHAVE_UINT32_T='1' \ 41 | -DHAVE_UINT64_T='1' \ 42 | -DMOZILLA_INTERNAL_API \ 43 | -DMOZILLA_XPCOMRT_API \ 44 | -DNO_CHROMIUM_LOGGING \ 45 | -DUSE_FAKE_MEDIA_STREAMS \ 46 | -DUSE_FAKE_PCOBSERVER \ 47 | -DOS_MACOSX \ 48 | -DSIP_OS_OSX \ 49 | -DOSX \ 50 | -D_FORTIFY_SOURCE='2' \ 51 | -D__STDC_FORMAT_MACROS \ 52 | -DDYNAMIC_ANNOTATIONS_ENABLED='1' \ 53 | -DWTF_USE_DYNAMIC_ANNOTATIONS='1' \ 54 | -DAB_CD=en-US \ 55 | -DNO_NSPR_10_SUPPORT \ 56 | -fPIC \ 57 | -Qunused-arguments \ 58 | -DMOZILLA_CLIENT \ 59 | -MD \ 60 | -MP \ 61 | -Qunused-arguments \ 62 | -Qunused-arguments \ 63 | -Wall \ 64 | -Wempty-body \ 65 | -Woverloaded-virtual \ 66 | -Wsign-compare \ 67 | -Wwrite-strings \ 68 | -Wno-invalid-offsetof \ 69 | -Wno-c++0x-extensions \ 70 | -Wno-extended-offsetof \ 71 | -Wno-unknown-warning-option \ 72 | -Wno-return-type-c-linkage \ 73 | -Wno-inline-new-delete \ 74 | -fno-exceptions \ 75 | -fno-strict-aliasing \ 76 | -fno-rtti \ 77 | -fno-exceptions \ 78 | -fno-math-errno \ 79 | -std=gnu++0x \ 80 | -pthread \ 81 | -DNO_X11 \ 82 | -pipe \ 83 | -DDEBUG \ 84 | -DTRACING \ 85 | -g \ 86 | -fno-omit-frame-pointer 87 | 88 | XXXXX_CFLAGS = \ 89 | -fvisibility=hidden \ 90 | -DOS_POSIX=1 \ 91 | -DOS_MACOSX=1 \ 92 | -DNR_SOCKET_IS_VOID_PTR \ 93 | -DHAVE_STRDUP \ 94 | -DNO_NSPR_10_SUPPORT \ 95 | -DNO_X11 \ 96 | -DMOZILLA_CLIENT \ 97 | -DNDEBUG \ 98 | -DTRIMMED \ 99 | -DUSE_FAKE_MEDIA_STREAMS \ 100 | -DUSE_FAKE_PCOBSERVER \ 101 | -DMOZILLA_INTERNAL_API \ 102 | -DMOZILLA_XPCOMRT_API \ 103 | -fPIC \ 104 | -Qunused-arguments \ 105 | -MD \ 106 | -MP \ 107 | -Wall \ 108 | -Wpointer-arith \ 109 | -Woverloaded-virtual \ 110 | -Werror=return-type \ 111 | -Wtype-limits \ 112 | -Wempty-body \ 113 | -Wsign-compare \ 114 | -Wno-invalid-offsetof \ 115 | -Wno-c++0x-extensions \ 116 | -Wno-extended-offsetof \ 117 | -Wno-unknown-warning-option \ 118 | -Wno-return-type-c-linkage \ 119 | -Wno-mismatched-tags \ 120 | -Wno-inline-new-delete \ 121 | -fno-exceptions \ 122 | -fno-strict-aliasing \ 123 | -fno-rtti \ 124 | -fno-exceptions \ 125 | -fno-math-errno \ 126 | -std=gnu++0x \ 127 | -pipe \ 128 | -g \ 129 | -fomit-frame-pointer 130 | 131 | LFLAGS = \ 132 | -L$(GECKO_OBJ)/dist/sdk/lib \ 133 | -L$(GECKO_OBJ)/dist/lib \ 134 | -pipe \ 135 | -framework Cocoa \ 136 | -lobjc \ 137 | -framework ExceptionHandling \ 138 | -Wl,-executable_path,$(GECKO_OBJ)/dist/bin \ 139 | -Wl,-rpath,$(GECKO_OBJ)/dist/bin \ 140 | $(GECKO_OBJ)/dist/lib/libssl.a \ 141 | $(GECKO_OBJ)/dist/lib/libplc4.a \ 142 | $(GECKO_OBJ)/dist/lib/libnspr4.a \ 143 | $(GECKO_OBJ)/dist/lib/libcertdb.a \ 144 | $(GECKO_OBJ)/dist/lib/libcerthi.a \ 145 | $(GECKO_OBJ)/dist/lib/libcryptohi.a \ 146 | $(GECKO_OBJ)/dist/lib/libpkixpki.a \ 147 | $(GECKO_OBJ)/dist/lib/libpkixtop.a \ 148 | $(GECKO_OBJ)/dist/lib/libpkixchecker.a \ 149 | $(GECKO_OBJ)/dist/lib/libpkixstore.a \ 150 | $(GECKO_OBJ)/dist/lib/libpkixcrlsel.a \ 151 | $(GECKO_OBJ)/dist/lib/libpkixpki.a \ 152 | $(GECKO_OBJ)/dist/lib/libpkixresults.a \ 153 | $(GECKO_OBJ)/dist/lib/libpkixutil.a \ 154 | $(GECKO_OBJ)/dist/lib/libpkixparams.a \ 155 | $(GECKO_OBJ)/dist/lib/libpkixcertsel.a \ 156 | $(GECKO_OBJ)/dist/lib/libpkixsystem.a \ 157 | $(GECKO_OBJ)/dist/lib/libpkixchecker.a \ 158 | $(GECKO_OBJ)/dist/lib/libpkixmodule.a \ 159 | $(GECKO_OBJ)/dist/lib/libnsspki.a \ 160 | $(GECKO_OBJ)/dist/lib/libnssdev.a \ 161 | $(GECKO_OBJ)/dist/lib/libnssb.a \ 162 | $(GECKO_OBJ)/dist/lib/libnss.a \ 163 | $(GECKO_OBJ)/dist/lib/libcerthi.a \ 164 | $(GECKO_OBJ)/dist/lib/libsmime.a \ 165 | $(GECKO_OBJ)/dist/lib/libnssutil.a \ 166 | $(GECKO_OBJ)/dist/lib/libplds4.a \ 167 | $(GECKO_OBJ)/dist/lib/libplc4.a \ 168 | $(GECKO_OBJ)/dist/lib/libsoftokn.a \ 169 | -lcrmf \ 170 | -framework QTKit \ 171 | -framework QuartzCore \ 172 | -framework Security \ 173 | -framework SystemConfiguration \ 174 | -lmozglue 175 | 176 | CFLAGS+=-I$(SDL_INCLUDE_PATH) -D_THREAD_SAFE -DDARWIN_GL 177 | LFLAGS+=-L$(SDL_LIB_PATH) \ 178 | -lSDL2 \ 179 | -lSDL2main 180 | 181 | LFLAGS+=-lm \ 182 | -liconv \ 183 | -framework OpenGL \ 184 | -framework ForceFeedback \ 185 | -lobjc \ 186 | -framework Cocoa \ 187 | -framework Carbon \ 188 | -framework IOKit \ 189 | -framework CoreAudio \ 190 | -framework AudioToolbox \ 191 | -framework AudioUnit 192 | 193 | -------------------------------------------------------------------------------- /platforms/Linux.mk: -------------------------------------------------------------------------------- 1 | RENDERNAME=renderSDL2 2 | 3 | CFLAGS = \ 4 | -DDEBUG -D_DEBUG -DTRACING \ 5 | -DOS_POSIX=1 \ 6 | -DOS_LINUX=1 \ 7 | -DUSE_FAKE_MEDIA_STREAMS \ 8 | -DUSE_FAKE_PCOBSERVER \ 9 | -DNR_SOCKET_IS_VOID_PTR \ 10 | -DHAVE_STRDUP \ 11 | -DMOZ_GLUE_IN_PROGRAM \ 12 | -DNO_NSPR_10_SUPPORT \ 13 | -DNDEBUG \ 14 | -DTRIMMED \ 15 | -DMOZILLA_CLIENT \ 16 | -DMOZILLA_INTERNAL_API \ 17 | -DMOZILLA_XPCOMRT_API \ 18 | -fPIC \ 19 | -MD \ 20 | -MP \ 21 | -Wall \ 22 | -Wpointer-arith \ 23 | -Woverloaded-virtual \ 24 | -Werror=return-type \ 25 | -Werror=int-to-pointer-cast \ 26 | -Wtype-limits \ 27 | -Wempty-body \ 28 | -Wsign-compare \ 29 | -Wno-invalid-offsetof \ 30 | -Wcast-align \ 31 | -fno-exceptions \ 32 | -fno-strict-aliasing \ 33 | -fno-rtti \ 34 | -fno-exceptions \ 35 | -fno-math-errno \ 36 | -std=gnu++0x \ 37 | -pthread \ 38 | -pipe \ 39 | -g \ 40 | -Os \ 41 | -freorder-blocks \ 42 | -fomit-frame-pointer 43 | 44 | LFLAGS = \ 45 | -Wall \ 46 | -Wpointer-arith \ 47 | -Woverloaded-virtual \ 48 | -Werror=return-type \ 49 | -Werror=int-to-pointer-cast \ 50 | -Wtype-limits \ 51 | -Wempty-body \ 52 | -Wsign-compare \ 53 | -Wno-invalid-offsetof \ 54 | -Wcast-align \ 55 | -fno-exceptions \ 56 | -fno-strict-aliasing \ 57 | -fno-rtti \ 58 | -fno-exceptions \ 59 | -fno-math-errno \ 60 | -std=gnu++0x \ 61 | -pthread \ 62 | -pipe \ 63 | -DNDEBUG \ 64 | -DTRIMMED \ 65 | -g \ 66 | -Os \ 67 | -freorder-blocks \ 68 | -fomit-frame-pointer \ 69 | -lpthread \ 70 | -Wl,-z,noexecstack \ 71 | -Wl,-z,text \ 72 | -Wl,--build-id \ 73 | -B $(GECKO_OBJ)/build/unix/gold \ 74 | -Wl,-rpath-link,$(GECKO_OBJ)/dist/lib \ 75 | -Wl,-rpath-link,/usr/local/lib \ 76 | -L$(GECKO_OBJ)/dist/lib \ 77 | -lssl \ 78 | -lcryptohi \ 79 | -lplc4 \ 80 | -lnspr4 \ 81 | -lcertdb \ 82 | -lcerthi \ 83 | -lpkixpki \ 84 | -lpkixtop \ 85 | -lpkixchecker \ 86 | -lpkixstore \ 87 | -lpkixcrlsel \ 88 | -lpkixpki \ 89 | -lpkixresults \ 90 | -lpkixutil \ 91 | -lpkixparams \ 92 | -lpkixcertsel \ 93 | -lpkixsystem \ 94 | -lpkixchecker \ 95 | -lpkixmodule \ 96 | -lnsspki \ 97 | -lnssdev \ 98 | -lnssb \ 99 | -lnss \ 100 | -lpk11wrap \ 101 | -lcerthi \ 102 | -lnssutil \ 103 | -lplds4 \ 104 | -rdynamic \ 105 | -lXext \ 106 | -lXcomposite \ 107 | -lXdamage \ 108 | -lXfixes \ 109 | -lX11 \ 110 | -lmozglue \ 111 | -ldl 112 | 113 | #$(GECKO_OBJ)/memory/mozalloc/Unified_cpp_memory_mozalloc0.o \ 114 | 115 | CFLAGS+=-I$(SDL_INCLUDE_PATH) -D_THREAD_SAFE 116 | LFLAGS+=-L$(SDL_LIB_PATH) -lSDL2 -lGL 117 | -------------------------------------------------------------------------------- /platforms/common.mk: -------------------------------------------------------------------------------- 1 | INCLUDE = \ 2 | -I$(GECKO_ROOT)/dom/media \ 3 | -I$(GECKO_ROOT)/media/standalone/include \ 4 | -I$(GECKO_ROOT)/media/webrtc/signaling/test \ 5 | -I$(GECKO_ROOT)/media/webrtc/trunk/testing/gtest/include \ 6 | -I$(GECKO_ROOT)/media/mtransport \ 7 | -I$(GECKO_ROOT)/media/webrtc/signaling/include \ 8 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/sipcc/core/sdp \ 9 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/sipcc/cpr/include \ 10 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/sipcc/core/includes \ 11 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/common/browser_logging \ 12 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/common/time_profiling \ 13 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/media \ 14 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/media-conduit \ 15 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/mediapipeline \ 16 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/sipcc/include \ 17 | -I$(GECKO_ROOT)/media/webrtc/signaling/src/peerconnection \ 18 | -I$(GECKO_ROOT)/media/webrtc/signaling/media-conduit \ 19 | -I$(GECKO_ROOT)/media/webrtc/trunk/third_party/libjingle/source/ \ 20 | -I$(GECKO_ROOT)/media/mtransport/third_party/nICEr/src/ice \ 21 | -I$(GECKO_ROOT)/media/mtransport/third_party/nICEr/src/net \ 22 | -I$(GECKO_ROOT)/media/mtransport/third_party/nICEr/src/stun \ 23 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/share \ 24 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/util/libekr \ 25 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/log \ 26 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/registry \ 27 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/stats \ 28 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/plugin \ 29 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/event \ 30 | -I$(GECKO_ROOT)/media/mtransport/third_party/nrappkit/src/port/darwin/include \ 31 | -I$(GECKO_ROOT)/media/webrtc/trunk/webrtc \ 32 | -I$(GECKO_ROOT)/media/webrtc \ 33 | -I$(GECKO_ROOT)/xpcom/libxpcomrt \ 34 | -I$(GECKO_OBJ)/dist/include/nspr \ 35 | -I$(GECKO_OBJ)/dist/include \ 36 | -I$(GECKO_OBJ)/dist/include/mozilla \ 37 | -I$(GECKO_OBJ)/dist/include/nss \ 38 | -I./3rdparty/yajl 39 | 40 | -------------------------------------------------------------------------------- /player.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include // For mode constants 10 | #include 11 | 12 | #include "mozilla/RefPtr.h" 13 | #include "FakeMediaStreams.h" 14 | #include "FakeMediaStreamsImpl.h" 15 | #include "FakePCObserver.h" 16 | 17 | #include "prio.h" 18 | #include "nsASocketHandler.h" 19 | #include "mozilla/Mutex.h" 20 | #include "nsRefPtr.h" 21 | #include "nsIRunnable.h" 22 | #include "VideoSegment.h" 23 | #include "nsISocketTransportService.h" 24 | #include "nsIThread.h" 25 | #include "nsITimer.h" 26 | #include "nsThreadUtils.h" 27 | 28 | #include "PeerConnectionCtx.h" 29 | #include "PeerConnectionImpl.h" 30 | 31 | #include "XPCOMRTInit.h" 32 | 33 | #include "nss.h" 34 | #include "ssl.h" 35 | 36 | #include "prthread.h" 37 | #include "prerror.h" 38 | 39 | #include "json.h" 40 | #include "render.h" 41 | 42 | #define LOG(format, ...) fprintf(stderr, format, ##__VA_ARGS__); 43 | 44 | const char JSONTerminator[] = "\r\n"; 45 | const int JSONTerminatorSize = sizeof(JSONTerminator) - 1; 46 | 47 | namespace { 48 | 49 | void 50 | LogPRError() 51 | { 52 | PRInt32 len = PR_GetErrorTextLength() + 1; 53 | if (len > 0) { 54 | char* buf = new char[len]; 55 | memset(buf, 0, len); 56 | PR_GetErrorText(buf); 57 | LOG("PR Error: %s\n", buf); 58 | delete []buf; 59 | } 60 | else { 61 | LOG("PR Error number: %d\n", (int)PR_GetError()); 62 | } 63 | } 64 | 65 | class PCObserver; 66 | typedef mozilla::MutexAutoLock MutexAutoLock; 67 | 68 | struct State { 69 | mozilla::RefPtr mStream; 70 | mozilla::RefPtr mPeerConnection; 71 | mozilla::RefPtr mPeerConnectionObserver; 72 | PRFileDesc* mSocket; 73 | State() : mSocket(nullptr) {} 74 | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(State) 75 | protected: 76 | ~State(){} 77 | }; 78 | 79 | static const int32_t PCOFFER = 0; 80 | static const int32_t PCANSWER = 1; 81 | 82 | class VideoSink : public Fake_VideoSink { 83 | public: 84 | VideoSink(const mozilla::RefPtr& aState) : mState(aState) {} 85 | virtual ~VideoSink() {} 86 | 87 | virtual void SegmentReady(mozilla::MediaSegment* aSegment) 88 | { 89 | mozilla::VideoSegment* segment = reinterpret_cast(aSegment); 90 | if (segment && mState) { 91 | const mozilla::VideoFrame *frame = segment->GetLastFrame(); 92 | unsigned int size; 93 | nsRefPtr buf = frame->GetImage(); 94 | const unsigned char *image = buf->GetImage(&size); 95 | if (size > 0) { 96 | int width = 0, height = 0; 97 | buf->GetWidthAndHeight(&width, &height); 98 | render::Draw(image, size, width, height); 99 | } 100 | } 101 | } 102 | protected: 103 | mozilla::RefPtr mState; 104 | }; 105 | 106 | static const int sBufferLength = 2048; 107 | 108 | class SocketHandler : public nsASocketHandler { 109 | NS_DECL_THREADSAFE_ISUPPORTS 110 | public: 111 | SocketHandler(mozilla::RefPtr& aState) : mState(aState), mSent(0), mReceived(0) { 112 | mPollFlags = PR_POLL_READ; 113 | } 114 | virtual void OnSocketReady(PRFileDesc *fd, int16_t outFlags); 115 | virtual void OnSocketDetached(PRFileDesc *fd); 116 | virtual void IsLocal(bool *aIsLocal) { if (aIsLocal) { *aIsLocal = false; } } 117 | virtual uint64_t ByteCountSent() { return mSent; } 118 | virtual uint64_t ByteCountReceived() { return mReceived; } 119 | 120 | protected: 121 | virtual ~SocketHandler() {} 122 | char mBuffer[sBufferLength]; 123 | std::string mMessage; 124 | mozilla::RefPtr mState; 125 | uint64_t mSent; 126 | uint64_t mReceived; 127 | }; 128 | 129 | NS_IMPL_ISUPPORTS0(SocketHandler) 130 | 131 | class PCObserver : public test::AFakePCObserver 132 | { 133 | NS_DECL_THREADSAFE_ISUPPORTS 134 | public: 135 | PCObserver(const mozilla::RefPtr& aState) : mState(aState) {} 136 | 137 | // PeerConnectionObserverExternal 138 | NS_IMETHODIMP OnCreateOfferSuccess(const char* offer, ER&) { return NS_OK; } 139 | NS_IMETHODIMP OnCreateOfferError(uint32_t code, const char *msg, ER&) { return NS_OK; } 140 | NS_IMETHODIMP OnCreateAnswerSuccess(const char* answer, ER&); 141 | NS_IMETHODIMP OnCreateAnswerError(uint32_t code, const char *msg, ER&); 142 | NS_IMETHODIMP OnSetLocalDescriptionSuccess(ER&) { return NS_OK; } 143 | NS_IMETHODIMP OnSetRemoteDescriptionSuccess(ER&) { return NS_OK; } 144 | NS_IMETHODIMP OnSetLocalDescriptionError(uint32_t code, const char *msg, ER&) { return NS_OK; } 145 | NS_IMETHODIMP OnSetRemoteDescriptionError(uint32_t code, const char *msg, ER&) { return NS_OK; } 146 | NS_IMETHODIMP NotifyConnection(ER&) { return NS_OK; } 147 | NS_IMETHODIMP NotifyClosedConnection(ER&) { return NS_OK; } 148 | NS_IMETHODIMP NotifyDataChannel(nsIDOMDataChannel *channel, ER&) { return NS_OK; } 149 | NS_IMETHODIMP OnStateChange(mozilla::dom::PCObserverStateType state_type, ER&, void*); 150 | NS_IMETHODIMP OnAddStream(mozilla::DOMMediaStream& stream, ER&); 151 | NS_IMETHODIMP OnRemoveStream(mozilla::DOMMediaStream&, ER&); 152 | NS_IMETHODIMP OnReplaceTrackSuccess(ER&) { return NS_OK; } 153 | NS_IMETHODIMP OnReplaceTrackError(uint32_t code, const char *msg, ER&) { return NS_OK; } 154 | NS_IMETHODIMP OnAddTrack(mozilla::MediaStreamTrack&, ER&) { return NS_OK; } 155 | NS_IMETHODIMP OnRemoveTrack(mozilla::MediaStreamTrack&, ER&) { return NS_OK; } 156 | NS_IMETHODIMP OnNegotiationNeeded(ER&) { return NS_OK; } 157 | NS_IMETHODIMP OnAddIceCandidateSuccess(ER&) 158 | { 159 | LOG("OnAddIceCandidateSuccessn\n"); 160 | return NS_OK; 161 | } 162 | NS_IMETHODIMP OnAddIceCandidateError(uint32_t code, const char *msg, ER&) 163 | { 164 | LOG("OnAddIceCandidateError: %u %s\n", code, msg); 165 | return NS_OK; 166 | } 167 | NS_IMETHODIMP OnIceCandidate(uint16_t level, const char *mid, const char *cand, ER&); 168 | 169 | protected: 170 | virtual ~PCObserver() {} 171 | mozilla::RefPtr mState; 172 | }; 173 | 174 | NS_IMPL_ISUPPORTS(PCObserver, nsISupportsWeakReference) 175 | 176 | class PullTimer : public nsITimerCallback 177 | { 178 | NS_DECL_THREADSAFE_ISUPPORTS 179 | public: 180 | PullTimer(const mozilla::RefPtr& aState) : mState(aState) {} 181 | NS_IMETHOD Notify(nsITimer *timer); 182 | protected: 183 | virtual ~PullTimer() {} 184 | mozilla::RefPtr mState; 185 | }; 186 | 187 | NS_IMPL_ISUPPORTS(PullTimer, nsITimerCallback) 188 | 189 | class ProcessMessage : public nsIRunnable { 190 | NS_DECL_THREADSAFE_ISUPPORTS 191 | NS_DECL_NSIRUNNABLE 192 | public: 193 | ProcessMessage(mozilla::RefPtr& aState) : 194 | mState(aState) {} 195 | void addMessage(const std::string& aMessage) 196 | { 197 | mMessageList.push_back(aMessage); 198 | } 199 | protected: 200 | virtual ~ProcessMessage(){} 201 | mozilla::RefPtr mState; 202 | std::vector mMessageList; 203 | }; 204 | 205 | NS_IMPL_ISUPPORTS(ProcessMessage, nsIRunnable) 206 | 207 | class DispatchSocketHandler : public nsIRunnable { 208 | NS_DECL_THREADSAFE_ISUPPORTS 209 | NS_DECL_NSIRUNNABLE 210 | public: 211 | DispatchSocketHandler(PRFileDesc* aSocket, mozilla::RefPtr& aHandler) : 212 | mSocket(aSocket), 213 | mHandler(aHandler) {} 214 | protected: 215 | virtual ~DispatchSocketHandler() {} 216 | PRFileDesc* mSocket; 217 | mozilla::RefPtr mHandler; 218 | }; 219 | 220 | NS_IMPL_ISUPPORTS(DispatchSocketHandler, nsIRunnable) 221 | 222 | nsresult 223 | DispatchSocketHandler::Run(void) 224 | { 225 | nsresult rv; 226 | nsCOMPtr sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); 227 | sts->AttachSocket(mSocket, mHandler); 228 | return NS_OK; 229 | } 230 | 231 | void 232 | SocketHandler::OnSocketReady(PRFileDesc *fd, int16_t outFlags) 233 | { 234 | static const std::string Term(JSONTerminator); 235 | if (outFlags & PR_POLL_READ) { 236 | memset(mBuffer, 0, sBufferLength); 237 | PRInt32 read = PR_Recv(fd, mBuffer, sBufferLength, 0, PR_INTERVAL_NO_WAIT); 238 | if (read > 0) { 239 | mReceived += read; 240 | LOG("Received ->\n%s\n", mBuffer); 241 | mozilla::RefPtr pmsg = new ProcessMessage(mState); 242 | mMessage += mBuffer; 243 | 244 | size_t start = 0; 245 | size_t found = mMessage.find(Term); 246 | if (found != std::string::npos) { 247 | while (found != std::string::npos) { 248 | pmsg->addMessage(mMessage.substr(start, found - start)); 249 | start = found + JSONTerminatorSize; 250 | found = mMessage.find(Term, start); 251 | } 252 | // Save any partial messages until the rest is received. 253 | if (start < mMessage.length()) { 254 | std::string remainder = mMessage.substr(start); 255 | mMessage = remainder; 256 | LOG("Saved: '%s'\n", mMessage.c_str()); 257 | } 258 | else { 259 | mMessage.clear(); 260 | } 261 | 262 | NS_DispatchToMainThread(pmsg); 263 | } 264 | } 265 | else { 266 | mCondition = NS_BASE_STREAM_CLOSED; 267 | static bool failed = false; 268 | if (!failed) { 269 | LOG("No data on socket ready. Assuming connection lost.\n"); 270 | failed = true; 271 | } 272 | } 273 | } 274 | if (outFlags & PR_POLL_WRITE) { 275 | LOG("\n*** PR_POLL_WRITE\n"); 276 | } 277 | if (outFlags & PR_POLL_EXCEPT) { 278 | LOG("\n*** PR_POLL_EXCEPT\n"); 279 | } 280 | if (outFlags & PR_POLL_ERR) { 281 | LOG("\n*** PR_POLL_ERR\n"); 282 | } 283 | if (outFlags & PR_POLL_NVAL) { 284 | LOG("\n*** PR_POLL_NVAL\n"); 285 | } 286 | if (outFlags & PR_POLL_HUP) { 287 | LOG("\n*** PR_POLL_HUP\n"); 288 | } 289 | } 290 | 291 | void 292 | SocketHandler::OnSocketDetached(PRFileDesc *fd) 293 | { 294 | LOG("Socket Detached!\n"); 295 | if (fd == mState->mSocket) { 296 | PR_Close(fd); 297 | mState->mSocket = 0; 298 | } 299 | } 300 | 301 | NS_IMETHODIMP 302 | PCObserver::OnCreateAnswerSuccess(const char* answer, ER&) 303 | { 304 | if (answer && mState.get() && mState->mSocket && mState->mPeerConnection.get()) { 305 | mState->mPeerConnection->SetLocalDescription(PCANSWER, answer); 306 | LOG("Answer ->\n%s\n", answer); 307 | JSONGenerator gen; 308 | gen.openMap(); 309 | gen.addPair("type", std::string("answer")); 310 | gen.addPair("sdp", std::string(answer)); 311 | gen.closeMap(); 312 | std::string value; 313 | if (gen.getJSON(value)) { 314 | PR_Send(mState->mSocket, value.c_str(), value.length(), 0, PR_INTERVAL_NO_TIMEOUT); 315 | PR_Send(mState->mSocket, JSONTerminator, JSONTerminatorSize, 0, PR_INTERVAL_NO_TIMEOUT); 316 | } 317 | } 318 | 319 | return NS_OK; 320 | } 321 | 322 | NS_IMETHODIMP 323 | PCObserver::OnCreateAnswerError(uint32_t code, const char *message, ER&) 324 | { 325 | return NS_OK; 326 | } 327 | 328 | NS_IMETHODIMP 329 | PCObserver::OnStateChange(mozilla::dom::PCObserverStateType state_type, ER&, void*) 330 | { 331 | if (!mState || mState->mPeerConnection.get()) { 332 | return NS_OK; 333 | } 334 | 335 | nsresult rv; 336 | mozilla::dom::PCImplIceConnectionState gotice; 337 | mozilla::dom::PCImplIceGatheringState goticegathering; 338 | mozilla::dom::PCImplSignalingState gotsignaling; 339 | 340 | switch (state_type) { 341 | case mozilla::dom::PCObserverStateType::IceConnectionState: 342 | rv = mState->mPeerConnection->IceConnectionState(&gotice); 343 | NS_ENSURE_SUCCESS(rv, rv); 344 | break; 345 | case mozilla::dom::PCObserverStateType::IceGatheringState: 346 | rv = mState->mPeerConnection->IceGatheringState(&goticegathering); 347 | NS_ENSURE_SUCCESS(rv, rv); 348 | break; 349 | case mozilla::dom::PCObserverStateType::SdpState: 350 | // NS_ENSURE_SUCCESS(rv, rv); 351 | break; 352 | case mozilla::dom::PCObserverStateType::SignalingState: 353 | rv = mState->mPeerConnection->SignalingState(&gotsignaling); 354 | NS_ENSURE_SUCCESS(rv, rv); 355 | break; 356 | default: 357 | // Unknown State 358 | MOZ_CRASH("Unknown state change type."); 359 | break; 360 | } 361 | return NS_OK; 362 | } 363 | 364 | 365 | NS_IMETHODIMP 366 | PCObserver::OnAddStream(mozilla::DOMMediaStream &stream, ER&) 367 | { 368 | mState->mStream = &stream; 369 | 370 | Fake_DOMMediaStream* fake = reinterpret_cast(mState->mStream.get()); 371 | if (fake) { 372 | Fake_MediaStream* ms = reinterpret_cast(fake->GetStream()); 373 | Fake_SourceMediaStream* sms = ms->AsSourceStream(); 374 | if (sms) { 375 | nsRefPtr sink = new VideoSink(mState); 376 | sms->AddVideoSink(sink); 377 | } 378 | } 379 | return NS_OK; 380 | } 381 | 382 | NS_IMETHODIMP 383 | PCObserver::OnRemoveStream(mozilla::DOMMediaStream&, ER&) 384 | { 385 | // Not being called? 386 | return NS_OK; 387 | } 388 | 389 | NS_IMETHODIMP 390 | PCObserver::OnIceCandidate(uint16_t level, const char *mid, const char *cand, ER&) { 391 | if (cand && (cand[0] != '\0')) { 392 | LOG("OnIceCandidate: candidate: %s mid: %s level: %d\n", cand, mid, (int)level); 393 | JSONGenerator gen; 394 | gen.openMap(); 395 | gen.addPair("candidate", std::string(cand)); 396 | gen.addPair("sdpMid", std::string(mid)); 397 | gen.addPair("sdpMLineIndex", (int)level); 398 | gen.closeMap(); 399 | std::string value; 400 | if (gen.getJSON(value)) { 401 | LOG("Sending candidate JSON: %s\n", value.c_str()); 402 | PRInt32 amount = PR_Send(mState->mSocket, value.c_str(), value.length(), 0, PR_INTERVAL_NO_TIMEOUT); 403 | if (amount < (PRInt32)value.length()) { 404 | LogPRError(); 405 | } 406 | amount = PR_Send(mState->mSocket, JSONTerminator, JSONTerminatorSize, 0, PR_INTERVAL_NO_TIMEOUT); 407 | if (amount < JSONTerminatorSize) { 408 | LogPRError(); 409 | } 410 | } 411 | } 412 | else { 413 | LOG("OnIceCandidate ignoring null ice candidate\n"); 414 | } 415 | return NS_OK; 416 | } 417 | 418 | NS_IMETHODIMP 419 | PullTimer::Notify(nsITimer *timer) 420 | { 421 | if (mState.get()) { 422 | Fake_DOMMediaStream* fake = reinterpret_cast(mState->mStream.get()); 423 | if (fake) { 424 | Fake_MediaStream* ms = reinterpret_cast(fake->GetStream()); 425 | static uint64_t value = 0; 426 | if (ms) { ms->NotifyPull(nullptr, value++); } 427 | } 428 | } 429 | return NS_OK; 430 | } 431 | 432 | typedef std::vector::size_type vsize_t; 433 | 434 | nsresult 435 | ProcessMessage::Run() 436 | { 437 | if (NS_IsMainThread() == false) { 438 | LOG("ProcessMessage must be run on the main thread.\n"); 439 | return NS_ERROR_FAILURE; 440 | } 441 | 442 | const vsize_t size = mMessageList.size(); 443 | for (vsize_t ix = 0; ix < size; ix++) { 444 | std::string message = mMessageList[ix]; 445 | JSONParser parse(message.c_str()); 446 | std::string type; 447 | if (parse.find("type", type)) { 448 | std::string sdp; 449 | if ((type == "offer") && parse.find("sdp", sdp)) { 450 | mState->mPeerConnection->SetRemoteDescription(PCOFFER, sdp.c_str()); 451 | mState->mPeerConnection->CreateAnswer(); 452 | } 453 | else { 454 | LOG("ERROR: Failed to parse offer:\n%s\n", message.c_str()); 455 | } 456 | } 457 | else { 458 | std::string candidate, mid; 459 | int index = 0; 460 | if (parse.find("candidate", candidate) && parse.find("sdpMid", mid) && parse.find("sdpMLineIndex", index)) { 461 | if (candidate[0] != '\0') { 462 | mState->mPeerConnection->AddIceCandidate(candidate.c_str(), mid.c_str(), (unsigned short)index); 463 | } 464 | else { 465 | LOG("ERROR: Received NULL ice candidate:\n%s\n", message.c_str()); 466 | } 467 | } 468 | else { 469 | LOG("ERROR: Ice candidate failed to parse: %s candidate:%s sdpMid:%s sdpMLineIndex:%s\n", message.c_str(), (parse.find("candidate", candidate) ? "True" : "False"), (parse.find("sdpMid", mid) ? "True" : "False"), (parse.find("sdpMLineIndex", index) ? "True" : "False")); 470 | } 471 | } 472 | } 473 | 474 | return NS_OK; 475 | } 476 | 477 | } // namespace 478 | 479 | bool 480 | CheckPRError(PRStatus result) 481 | { 482 | if (result != PR_SUCCESS) { 483 | PRInt32 len = PR_GetErrorTextLength() + 1; 484 | if (len > 0) { 485 | char* buf = new char[len]; 486 | memset(buf, 0, len); 487 | PR_GetErrorText(buf); 488 | LOG("PR Error: %s\n", buf); 489 | delete []buf; 490 | } 491 | else { 492 | LOG("PR Error number: %d\n", (int)PR_GetError()); 493 | } 494 | return false; 495 | } 496 | return true; 497 | } 498 | 499 | int 500 | main(int argc, char* argv[]) 501 | { 502 | NS_InitXPCOMRT(); 503 | NSS_NoDB_Init(nullptr); 504 | NSS_SetDomesticPolicy(); 505 | mozilla::RefPtr state = new State; 506 | 507 | PRNetAddr addr; 508 | memset(&addr, 0, sizeof(addr)); 509 | PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, 8011, &addr); 510 | PRFileDesc* sock = PR_OpenTCPSocket(PR_AF_INET); 511 | 512 | if (!sock) { 513 | LOG("ERROR: Failed to create socket\n."); 514 | } 515 | 516 | PRSocketOptionData opt; 517 | 518 | opt.option = PR_SockOpt_Reuseaddr; 519 | opt.value.reuse_addr = true; 520 | PR_SetSocketOption(sock, &opt); 521 | 522 | CheckPRError(PR_Bind(sock, &addr)); 523 | 524 | if (CheckPRError(PR_Listen(sock, 5))) { 525 | state->mSocket = PR_Accept(sock, &addr, PR_INTERVAL_NO_TIMEOUT); 526 | PR_Shutdown(sock, PR_SHUTDOWN_BOTH); 527 | PR_Close(sock); 528 | sock = nullptr; 529 | } 530 | else { 531 | exit(-1); 532 | } 533 | 534 | if (!state->mSocket) { 535 | LOG("ERROR: Failed to create socket\n"); 536 | exit(-1); 537 | } 538 | 539 | mozilla::IceConfiguration cfg; 540 | 541 | state->mPeerConnection = mozilla::PeerConnectionImpl::CreatePeerConnection(); 542 | state->mPeerConnectionObserver = new PCObserver(state); 543 | state->mPeerConnection->Initialize(*(state->mPeerConnectionObserver), nullptr, cfg, NS_GetCurrentThread()); 544 | 545 | nsresult rv; 546 | 547 | nsCOMPtr timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); 548 | mozilla::RefPtr pull = new PullTimer(state); 549 | 550 | timer->InitWithCallback( 551 | pull, 552 | PR_MillisecondsToInterval(16), 553 | nsITimer::TYPE_REPEATING_PRECISE); 554 | 555 | mozilla::RefPtr handler = new SocketHandler(state); 556 | mozilla::RefPtr dispatch = new DispatchSocketHandler(state->mSocket, handler); 557 | nsCOMPtr sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); 558 | nsCOMPtr ststhread = do_QueryInterface(sts, &rv); 559 | ststhread->Dispatch(dispatch, NS_DISPATCH_NORMAL); 560 | 561 | render::Initialize(); 562 | while (render::KeepRunning()) { NS_ProcessNextEvent(nullptr, true); } 563 | 564 | if (state->mStream) { state->mStream->GetStream()->AsSourceStream()->StopStream(); } 565 | state->mPeerConnection->CloseStreams(); 566 | state->mPeerConnection->Close(); 567 | state->mPeerConnection = nullptr; 568 | 569 | render::Shutdown(); 570 | NS_ShutdownXPCOMRT(); 571 | 572 | return 0; 573 | } 574 | -------------------------------------------------------------------------------- /render.h: -------------------------------------------------------------------------------- 1 | #ifndef media_render_dot_h_ 2 | #define media_render_dot_h_ 3 | 4 | namespace render { 5 | 6 | void Initialize(); 7 | void Shutdown(); 8 | void Draw(const unsigned char* aImage, int size, int aWidth, int aHeight); 9 | bool KeepRunning(); 10 | 11 | } // namespace standalone 12 | #endif // ifndef media_render_dot_h_ 13 | -------------------------------------------------------------------------------- /renderGL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define GL_GLEXT_PROTOTYPES 4 | #if defined(DARWIN_GL) 5 | #include 6 | #include 7 | #else 8 | #include 9 | #include 10 | #endif 11 | 12 | #include 13 | #define PROGRAM_NAME "WebRTC GL Player" 14 | 15 | namespace render { 16 | static const GLchar* vertexSource = 17 | "#version 120\n" 18 | "attribute vec2 position;" 19 | "attribute vec2 texcoord;" 20 | "varying vec2 varTexcoord;" 21 | "void main() {" 22 | " gl_Position = vec4(position, 0.0, 1.0);" 23 | " varTexcoord = texcoord;" 24 | "}"; 25 | 26 | static const GLchar *fragmentSource = 27 | "varying vec2 varTexcoord;\n" 28 | "uniform sampler2D texY;\n" 29 | "uniform sampler2D texU;\n" 30 | "uniform sampler2D texV;\n" 31 | "void main(void) {\n" 32 | " float r,g,b,y,u,v;\n" 33 | " y=texture2D(texY, varTexcoord).r;\n" 34 | " u=texture2D(texU, varTexcoord).r;\n" 35 | " v=texture2D(texV, varTexcoord).r;\n" 36 | " y=1.1643*(y-0.0625);\n" 37 | " u=u-0.5;\n" 38 | " v=v-0.5;\n" 39 | " r=y+1.5958*v;\n" 40 | " g=y-0.39173*u-0.81290*v;\n" 41 | " b=y+2.017*u;\n" 42 | " gl_FragColor=vec4(r,g,b,1.0);\n" 43 | "}\n"; 44 | 45 | static SDL_Window *mainwindow; 46 | static SDL_GLContext maincontext; 47 | static GLuint textureY; 48 | static GLuint textureU; 49 | static GLuint textureV; 50 | static GLuint vertexShader; 51 | static GLuint fragmentShader; 52 | static GLuint shaderProgram; 53 | static int sWidth = 640; 54 | static int sHeight = 480; 55 | 56 | static GLfloat vertices[] = { 57 | -1.0f, -1.0f, 58 | 1.0f, -1.0f, 59 | 1.0f, 1.0f, 60 | -1.0f, 1.0f 61 | }; 62 | 63 | static GLfloat texcoord[] = { 64 | 0.0f, 1.0f, 65 | 1.0f, 1.0f, 66 | 1.0f, 0.0f, 67 | 0.0f, 0.0f 68 | }; 69 | 70 | void sdldie(const char *msg) 71 | { 72 | printf("%s: %s\n", msg, SDL_GetError()); 73 | SDL_Quit(); 74 | exit(1); 75 | } 76 | 77 | void checkSDLError(int line = -1) 78 | { 79 | const char *error = SDL_GetError(); 80 | if (*error != '\0') { 81 | fprintf(stderr, "SDL Error: %s\n", error); 82 | if (line != -1) { 83 | fprintf(stderr, " + line: %i\n", line); 84 | } 85 | SDL_ClearError(); 86 | } 87 | } 88 | 89 | void 90 | Initialize() 91 | { 92 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { 93 | sdldie("Unable to initialize SDL"); 94 | } 95 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 96 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 97 | 98 | mainwindow = SDL_CreateWindow(PROGRAM_NAME, 99 | SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 100 | sWidth, sHeight, 101 | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); 102 | if (!mainwindow) { 103 | sdldie("Unable to create window"); 104 | } 105 | 106 | checkSDLError(__LINE__); 107 | 108 | maincontext = SDL_GL_CreateContext(mainwindow); 109 | checkSDLError(__LINE__); 110 | 111 | SDL_GL_SetSwapInterval(1); 112 | 113 | glGenTextures(1, &textureY); 114 | glBindTexture(GL_TEXTURE_2D, textureY); 115 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 116 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 117 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 118 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 119 | 120 | glGenTextures(1, &textureU); 121 | glBindTexture(GL_TEXTURE_2D, textureU); 122 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 123 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 124 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 125 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 126 | 127 | glGenTextures(1, &textureV); 128 | glBindTexture(GL_TEXTURE_2D, textureV); 129 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 130 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 131 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 132 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 133 | 134 | vertexShader = glCreateShader(GL_VERTEX_SHADER); 135 | glShaderSource(vertexShader, 1, &vertexSource, NULL); 136 | glCompileShader(vertexShader); 137 | GLint status; 138 | glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); 139 | if (status != GL_TRUE) { 140 | char buffer[1024]; 141 | glGetShaderInfoLog(vertexShader, 1024, NULL, buffer); 142 | fprintf(stderr, "Compiler error: %s\n", buffer); 143 | } 144 | 145 | fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 146 | glShaderSource(fragmentShader, 1, &fragmentSource, NULL); 147 | glCompileShader(fragmentShader); 148 | glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); 149 | if (status != GL_TRUE) { 150 | char buffer[1024]; 151 | glGetShaderInfoLog(vertexShader, 1024, NULL, buffer); 152 | fprintf(stderr, "Compiler error: %s\n", buffer); 153 | } 154 | 155 | shaderProgram = glCreateProgram(); 156 | glAttachShader(shaderProgram, vertexShader); 157 | glAttachShader(shaderProgram, fragmentShader); 158 | glLinkProgram(shaderProgram); 159 | glGetProgramiv(vertexShader, GL_LINK_STATUS, &status); 160 | if (status != GL_TRUE) { 161 | char buffer[1024]; 162 | glGetProgramInfoLog(vertexShader, 1024, NULL, buffer); 163 | fprintf(stderr, "Program error: %s\n", buffer); 164 | } 165 | 166 | glUseProgram(shaderProgram); 167 | 168 | glActiveTexture(GL_TEXTURE0); 169 | glBindTexture(GL_TEXTURE_2D, textureY); 170 | glActiveTexture(GL_TEXTURE1); 171 | glBindTexture(GL_TEXTURE_2D, textureU); 172 | glActiveTexture(GL_TEXTURE2); 173 | glBindTexture(GL_TEXTURE_2D, textureV); 174 | 175 | GLint texY = glGetUniformLocation(shaderProgram, "texY"); 176 | glUniform1i(texY, 0); 177 | GLint texU = glGetUniformLocation(shaderProgram, "texU"); 178 | glUniform1i(texU, 1); 179 | GLint texV = glGetUniformLocation(shaderProgram, "texV"); 180 | glUniform1i(texV, 2); 181 | 182 | GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); 183 | GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord"); 184 | glEnableVertexAttribArray(posAttrib); 185 | glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, vertices); 186 | glEnableVertexAttribArray(texAttrib); 187 | glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, texcoord); 188 | } 189 | 190 | // const int MaxWidth = 800; 191 | // const int MaxHeight = 600; 192 | 193 | void 194 | Draw(const unsigned char* aImage, int size, int aWidth, int aHeight) 195 | { 196 | if (mainwindow) { 197 | 198 | int tWidth = aWidth; 199 | int tHeight = aHeight; 200 | 201 | #if 0 202 | if ((tWidth > MaxWidth) || (aHeight > MaxHeight)) { 203 | if ((float(tWidth) / float(MaxWidth)) > (float(tHeight) / float(MaxHeight))) { 204 | tHeight = int((float(MaxWidth) / float(tWidth)) * float(tHeight)); 205 | tWidth = MaxWidth; 206 | } 207 | else { 208 | tWidth = int((float(MaxHeight) / float(tHeight)) * float(tWidth)); 209 | tHeight = MaxHeight; 210 | } 211 | } 212 | #endif 213 | 214 | if ((tWidth != sWidth) || (tHeight != sHeight)) { 215 | fprintf(stderr, "Width: %d Height: %d\n", tWidth, tHeight); 216 | 217 | SDL_SetWindowSize(mainwindow, tWidth, tHeight); 218 | glViewport(0, 0, tWidth, tHeight); 219 | sWidth = tWidth; 220 | sHeight = tHeight; 221 | } 222 | 223 | 224 | const unsigned char* chanY = aImage; 225 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 226 | glPixelStorei(GL_UNPACK_ROW_LENGTH, aWidth); 227 | glBindTexture(GL_TEXTURE_2D, textureY); 228 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, aWidth, aHeight, 0, GL_RED, GL_UNSIGNED_BYTE, chanY); 229 | 230 | const unsigned char* chanU = aImage + (aWidth * aHeight); 231 | const int halfWidth = (aWidth + 1) / 2; 232 | const int halfHeight = (aHeight + 1) / 2; 233 | 234 | glPixelStorei(GL_UNPACK_ROW_LENGTH, halfWidth); 235 | glBindTexture(GL_TEXTURE_2D, textureU); 236 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, halfWidth, halfHeight, 0, GL_RED, GL_UNSIGNED_BYTE, chanU); 237 | 238 | const unsigned char* chanV = aImage + (aWidth * aHeight) + (halfWidth * halfHeight); 239 | glBindTexture(GL_TEXTURE_2D, textureV); 240 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, halfWidth, halfHeight, 0, GL_RED, GL_UNSIGNED_BYTE, chanV); 241 | 242 | glClearColor ( 0.0, 0.0, 0.0, 1.0 ); 243 | glClear ( GL_COLOR_BUFFER_BIT ); 244 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 245 | SDL_GL_SwapWindow(mainwindow); 246 | } 247 | } 248 | 249 | bool 250 | KeepRunning() 251 | { 252 | bool result = true; 253 | SDL_Event event; 254 | while (SDL_PollEvent(&event)) { 255 | switch (event.type) { 256 | case SDL_KEYDOWN: 257 | if (event.key.keysym.sym == SDLK_ESCAPE) { 258 | result = false; 259 | } 260 | break; 261 | case SDL_QUIT: 262 | result = false; 263 | break; 264 | } 265 | } 266 | 267 | return result; 268 | } 269 | 270 | void 271 | Shutdown() { 272 | // delete textures here. 273 | glDeleteProgram(shaderProgram); 274 | glDeleteShader(fragmentShader); 275 | glDeleteShader(vertexShader); 276 | 277 | SDL_GL_DeleteContext(maincontext); 278 | SDL_DestroyWindow(mainwindow); 279 | SDL_Quit(); 280 | } 281 | 282 | } // namespace render 283 | -------------------------------------------------------------------------------- /renderSDL2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "SDL.h" 4 | 5 | #include 6 | #define LOG(format, ...) fprintf(stderr, format, ##__VA_ARGS__); 7 | 8 | static void 9 | quit(int rc) 10 | { 11 | SDL_Quit(); 12 | exit(rc); 13 | } 14 | 15 | namespace render { 16 | 17 | struct State { 18 | SDL_Window *window; 19 | SDL_Renderer *renderer; 20 | SDL_Texture *texture; 21 | int width; 22 | int height; 23 | State() : window(0), renderer(0), texture(0), width(0), height(0) {} 24 | }; 25 | 26 | static State* sState = nullptr; 27 | 28 | void 29 | Initialize() 30 | { 31 | if (sState) { 32 | return; 33 | } 34 | 35 | sState = new State; 36 | } 37 | 38 | void 39 | Shutdown() 40 | { 41 | SDL_DestroyRenderer(sState->renderer); 42 | delete sState; 43 | sState = 0; 44 | } 45 | 46 | void 47 | Draw(const unsigned char* aImage, int size, int aWidth, int aHeight) 48 | { 49 | if (!sState) { 50 | return; 51 | } 52 | 53 | if (!sState->window) { 54 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 55 | 56 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { 57 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); 58 | return; 59 | } 60 | 61 | sState->window = SDL_CreateWindow("WebRTC Player", 62 | SDL_WINDOWPOS_UNDEFINED, 63 | SDL_WINDOWPOS_UNDEFINED, 64 | aWidth, aHeight, 65 | 0); 66 | // SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL); 67 | if (!sState->window) { 68 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError()); 69 | quit(3); 70 | } 71 | 72 | sState->renderer = SDL_CreateRenderer(sState->window, -1, 0); 73 | if (!sState->renderer) { 74 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError()); 75 | quit(4); 76 | } 77 | 78 | sState->width = aWidth; 79 | sState->height = aHeight; 80 | } 81 | 82 | if (!sState->texture) { 83 | sState->texture = SDL_CreateTexture(sState->renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, aWidth, aHeight); 84 | if (!sState->texture) { 85 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError()); 86 | quit(5); 87 | } 88 | } 89 | 90 | if ((sState->width != aWidth) || (sState->height != aHeight)) { 91 | if (sState->texture) { 92 | SDL_DestroyTexture(sState->texture); sState->texture = 0; 93 | } 94 | 95 | sState->texture = SDL_CreateTexture(sState->renderer, 96 | SDL_PIXELFORMAT_IYUV, 97 | SDL_TEXTUREACCESS_STREAMING, 98 | aWidth, aHeight); 99 | SDL_SetWindowSize(sState->window, aWidth, aHeight); 100 | sState->width = aWidth; 101 | sState->height = aHeight; 102 | } 103 | 104 | Uint8* dst = nullptr; 105 | void* pixels = nullptr; 106 | int pitch = 0; 107 | 108 | if (SDL_LockTexture(sState->texture, NULL, &pixels, &pitch) < 0) { 109 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock texture: %s\n", SDL_GetError()); 110 | quit(5); 111 | } 112 | 113 | dst = (Uint8*)pixels; 114 | memcpy(dst, aImage, size); 115 | SDL_UnlockTexture(sState->texture); 116 | 117 | SDL_RenderClear(sState->renderer); 118 | SDL_RenderCopy(sState->renderer, sState->texture, NULL, NULL); 119 | SDL_RenderPresent(sState->renderer); 120 | } 121 | 122 | bool 123 | KeepRunning() 124 | { 125 | bool result = true; 126 | if (sState->window) { 127 | SDL_Event event; 128 | while (SDL_PollEvent(&event)) { 129 | switch (event.type) { 130 | case SDL_KEYDOWN: 131 | if (event.key.keysym.sym == SDLK_ESCAPE) { 132 | result = false; 133 | } 134 | break; 135 | case SDL_QUIT: 136 | result = false; 137 | break; 138 | } 139 | } 140 | } 141 | return result; 142 | } 143 | 144 | } // namespace standalone 145 | -------------------------------------------------------------------------------- /renderStub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace render { 4 | 5 | 6 | struct State { 7 | FILE* Out; 8 | State() : Out(nullptr) {} 9 | ~State() { 10 | if (Out) { fclose(Out); } 11 | } 12 | }; 13 | 14 | static State* sState = nullptr; 15 | 16 | void 17 | Initialize() 18 | { 19 | if (sState) { 20 | return; 21 | } 22 | // fprintf(stderr, "render::Initialize\n"); 23 | sState = new State; 24 | } 25 | 26 | void 27 | Shutdown() 28 | { 29 | delete sState; 30 | sState = 0; 31 | } 32 | 33 | void 34 | Draw(const unsigned char* aImage, int size, int aWidth, int aHeight) 35 | { 36 | //play with "mplayer -demuxer rawvideo -rawvideo w=640:h=480:format=i420 video.yuv" 37 | if (!sState->Out) { sState->Out = fopen("video.yuv", "w"); } 38 | fprintf(stderr, "Got image: %d %dx%d\n", size, aWidth, aHeight); 39 | if (sState && sState->Out && aImage && size) { fwrite(aImage, size, 1, sState->Out); } 40 | 41 | #if 0 42 | static int count = 0; 43 | count++; 44 | if (count == 16) { 45 | FILE* tmp = fopen("frame.yuv", "w"); 46 | if (tmp && aImage && size) { 47 | fwrite(aImage, size, 1, tmp); 48 | fclose(tmp); tmp = 0; 49 | } 50 | } 51 | #endif // 0 52 | } 53 | 54 | bool 55 | KeepRunning() 56 | { 57 | bool result = true; 58 | 59 | return result; 60 | } 61 | 62 | } // namespace standalone 63 | -------------------------------------------------------------------------------- /tools/expand.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def expand(file): 4 | with open(file) as f: 5 | for line in f: 6 | val = line.split() 7 | if val[0] == 'LIBS': 8 | for item in val[2:]: 9 | expand(item + '.desc') 10 | elif val[0] == 'OBJS': 11 | for item in val[2:]: 12 | sys.stdout.write(' ' + item) 13 | 14 | for lib in sys.argv[1:]: 15 | expand(lib) 16 | --------------------------------------------------------------------------------