Adding initial code jy.oak@samsung.com
[ric-app/kpimon.git] / asn1c_defs / all-defs / xer_decoder.c
diff --git a/asn1c_defs/all-defs/xer_decoder.c b/asn1c_defs/all-defs/xer_decoder.c
new file mode 100755 (executable)
index 0000000..c34a6c6
--- /dev/null
@@ -0,0 +1,369 @@
+/*\r
+ * Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.\r
+ * Redistribution and modifications are permitted subject to BSD license.\r
+ */\r
+#include <asn_application.h>\r
+#include <asn_internal.h>\r
+#include <xer_support.h>               /* XER/XML parsing support */\r
+\r
+\r
+/*\r
+ * Decode the XER encoding of a given type.\r
+ */\r
+asn_dec_rval_t\r
+xer_decode(const asn_codec_ctx_t *opt_codec_ctx,\r
+           const asn_TYPE_descriptor_t *td, void **struct_ptr,\r
+           const void *buffer, size_t size) {\r
+    asn_codec_ctx_t s_codec_ctx;\r
+\r
+       /*\r
+        * Stack checker requires that the codec context\r
+        * must be allocated on the stack.\r
+        */\r
+       if(opt_codec_ctx) {\r
+               if(opt_codec_ctx->max_stack_size) {\r
+                       s_codec_ctx = *opt_codec_ctx;\r
+                       opt_codec_ctx = &s_codec_ctx;\r
+               }\r
+       } else {\r
+               /* If context is not given, be security-conscious anyway */\r
+               memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));\r
+               s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;\r
+               opt_codec_ctx = &s_codec_ctx;\r
+       }\r
+\r
+       /*\r
+        * Invoke type-specific decoder.\r
+        */\r
+       return td->op->xer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size);\r
+}\r
+\r
+\r
+\r
+struct xer__cb_arg {\r
+       pxml_chunk_type_e       chunk_type;\r
+       size_t                  chunk_size;\r
+       const void              *chunk_buf;\r
+       int callback_not_invoked;\r
+};\r
+\r
+static int\r
+xer__token_cb(pxml_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) {\r
+       struct xer__cb_arg *arg = (struct xer__cb_arg *)key;\r
+       arg->chunk_type = type;\r
+       arg->chunk_size = _chunk_size;\r
+       arg->chunk_buf = _chunk_data;\r
+       arg->callback_not_invoked = 0;\r
+       return -1;      /* Terminate the XML parsing */\r
+}\r
+\r
+/*\r
+ * Fetch the next token from the XER/XML stream.\r
+ */\r
+ssize_t\r
+xer_next_token(int *stateContext, const void *buffer, size_t size, pxer_chunk_type_e *ch_type) {\r
+       struct xer__cb_arg arg;\r
+       int new_stateContext = *stateContext;\r
+       ssize_t ret;\r
+\r
+       arg.callback_not_invoked = 1;\r
+       ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);\r
+       if(ret < 0) return -1;\r
+       if(arg.callback_not_invoked) {\r
+               assert(ret == 0);       /* No data was consumed */\r
+        *ch_type = PXER_WMORE;\r
+               return 0;               /* Try again with more data */\r
+       } else {\r
+               assert(arg.chunk_size);\r
+               assert(arg.chunk_buf == buffer);\r
+       }\r
+\r
+       /*\r
+        * Translate the XML chunk types into more convenient ones.\r
+        */\r
+       switch(arg.chunk_type) {\r
+       case PXML_TEXT:\r
+               *ch_type = PXER_TEXT;\r
+               break;\r
+       case PXML_TAG:\r
+               *ch_type = PXER_WMORE;\r
+               return 0;       /* Want more */\r
+       case PXML_TAG_END:\r
+               *ch_type = PXER_TAG;\r
+               break;\r
+       case PXML_COMMENT:\r
+       case PXML_COMMENT_END:\r
+               *ch_type = PXER_COMMENT;\r
+               break;\r
+       }\r
+\r
+       *stateContext = new_stateContext;\r
+       return arg.chunk_size;\r
+}\r
+\r
+#define        CSLASH  0x2f    /* '/' */\r
+#define        LANGLE  0x3c    /* '<' */\r
+#define        RANGLE  0x3e    /* '>' */\r
+\r
+xer_check_tag_e\r
+xer_check_tag(const void *buf_ptr, int size, const char *need_tag) {\r
+       const char *buf = (const char *)buf_ptr;\r
+       const char *end;\r
+       xer_check_tag_e ct = XCT_OPENING;\r
+\r
+       if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) {\r
+               if(size >= 2)\r
+                       ASN_DEBUG("Broken XML tag: \"%c...%c\"",\r
+                       buf[0], buf[size - 1]);\r
+               return XCT_BROKEN;\r
+       }\r
+\r
+       /*\r
+        * Determine the tag class.\r
+        */\r
+       if(buf[1] == CSLASH) {\r
+               buf += 2;       /* advance past "</" */\r
+               size -= 3;      /* strip "</" and ">" */\r
+               ct = XCT_CLOSING;\r
+               if(size > 0 && buf[size-1] == CSLASH)\r
+                       return XCT_BROKEN;      /* </abc/> */\r
+       } else {\r
+               buf++;          /* advance past "<" */\r
+               size -= 2;      /* strip "<" and ">" */\r
+               if(size > 0 && buf[size-1] == CSLASH) {\r
+                       ct = XCT_BOTH;\r
+                       size--; /* One more, for "/" */\r
+               }\r
+       }\r
+\r
+       /* Sometimes we don't care about the tag */\r
+       if(!need_tag || !*need_tag)\r
+               return (xer_check_tag_e)(XCT__UNK__MASK | ct);\r
+\r
+       /*\r
+        * Determine the tag name.\r
+        */\r
+       for(end = buf + size; buf < end; buf++, need_tag++) {\r
+               int b = *buf, n = *need_tag;\r
+               if(b != n) {\r
+                       if(n == 0) {\r
+                               switch(b) {\r
+                               case 0x09: case 0x0a: case 0x0c: case 0x0d:\r
+                               case 0x20:\r
+                                       /* "<abc def/>": whitespace is normal */\r
+                                       return ct;\r
+                               }\r
+                       }\r
+                       return (xer_check_tag_e)(XCT__UNK__MASK | ct);\r
+               }\r
+               if(b == 0)\r
+                       return XCT_BROKEN;      /* Embedded 0 in buf?! */\r
+       }\r
+       if(*need_tag)\r
+               return (xer_check_tag_e)(XCT__UNK__MASK | ct);\r
+\r
+       return ct;\r
+}\r
+\r
+\r
+#undef ADVANCE\r
+#define        ADVANCE(num_bytes)      do {                            \\r
+               size_t num = (num_bytes);                       \\r
+               buf_ptr = ((const char *)buf_ptr) + num;        \\r
+               size -= num;                                    \\r
+               consumed_myself += num;                         \\r
+       } while(0)\r
+\r
+#undef RETURN\r
+#define        RETURN(_code)   do {                                    \\r
+               rval.code = _code;                              \\r
+               rval.consumed = consumed_myself;                \\r
+               if(rval.code != RC_OK)                          \\r
+                       ASN_DEBUG("Failed with %d", rval.code); \\r
+               return rval;                                    \\r
+       } while(0)\r
+\r
+#define        XER_GOT_BODY(chunk_buf, chunk_size, size)       do {    \\r
+               ssize_t converted_size = body_receiver          \\r
+                       (struct_key, chunk_buf, chunk_size,     \\r
+                               (size_t)chunk_size < size);     \\r
+               if(converted_size == -1) RETURN(RC_FAIL);       \\r
+               if(converted_size == 0                          \\r
+                       && size == (size_t)chunk_size)          \\r
+                       RETURN(RC_WMORE);                       \\r
+               chunk_size = converted_size;                    \\r
+       } while(0)\r
+#define        XER_GOT_EMPTY() do {                                    \\r
+       if(body_receiver(struct_key, 0, 0, size > 0) == -1)     \\r
+                       RETURN(RC_FAIL);                        \\r
+       } while(0)\r
+\r
+/*\r
+ * Generalized function for decoding the primitive values.\r
+ */\r
+asn_dec_rval_t\r
+xer_decode_general(const asn_codec_ctx_t *opt_codec_ctx,\r
+       asn_struct_ctx_t *ctx,  /* Type decoder context */\r
+       void *struct_key,\r
+       const char *xml_tag,    /* Expected XML tag */\r
+       const void *buf_ptr, size_t size,\r
+       int (*opt_unexpected_tag_decoder)\r
+               (void *struct_key, const void *chunk_buf, size_t chunk_size),\r
+       ssize_t (*body_receiver)\r
+               (void *struct_key, const void *chunk_buf, size_t chunk_size,\r
+                       int have_more)\r
+       ) {\r
+\r
+       asn_dec_rval_t rval;\r
+       ssize_t consumed_myself = 0;\r
+\r
+       (void)opt_codec_ctx;\r
+\r
+       /*\r
+        * Phases of XER/XML processing:\r
+        * Phase 0: Check that the opening tag matches our expectations.\r
+        * Phase 1: Processing body and reacting on closing tag.\r
+        */\r
+       if(ctx->phase > 1) RETURN(RC_FAIL);\r
+       for(;;) {\r
+               pxer_chunk_type_e ch_type;      /* XER chunk type */\r
+               ssize_t ch_size;                /* Chunk size */\r
+               xer_check_tag_e tcv;            /* Tag check value */\r
+\r
+               /*\r
+                * Get the next part of the XML stream.\r
+                */\r
+               ch_size = xer_next_token(&ctx->context, buf_ptr, size,\r
+                       &ch_type);\r
+               if(ch_size == -1) {\r
+            RETURN(RC_FAIL);\r
+        } else {\r
+                       switch(ch_type) {\r
+                       case PXER_WMORE:\r
+                RETURN(RC_WMORE);\r
+                       case PXER_COMMENT:              /* Got XML comment */\r
+                               ADVANCE(ch_size);       /* Skip silently */\r
+                               continue;\r
+                       case PXER_TEXT:\r
+                               if(ctx->phase == 0) {\r
+                                       /*\r
+                                        * We have to ignore whitespace here,\r
+                                        * but in order to be forward compatible\r
+                                        * with EXTENDED-XER (EMBED-VALUES, #25)\r
+                                        * any text is just ignored here.\r
+                                        */\r
+                               } else {\r
+                                       XER_GOT_BODY(buf_ptr, ch_size, size);\r
+                               }\r
+                               ADVANCE(ch_size);\r
+                               continue;\r
+                       case PXER_TAG:\r
+                               break;  /* Check the rest down there */\r
+                       }\r
+               }\r
+\r
+               assert(ch_type == PXER_TAG && size);\r
+\r
+               tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);\r
+               /*\r
+                * Phase 0:\r
+                *      Expecting the opening tag\r
+                *      for the type being processed.\r
+                * Phase 1:\r
+                *      Waiting for the closing XML tag.\r
+                */\r
+               switch(tcv) {\r
+               case XCT_BOTH:\r
+                       if(ctx->phase) break;\r
+                       /* Finished decoding of an empty element */\r
+                       XER_GOT_EMPTY();\r
+                       ADVANCE(ch_size);\r
+                       ctx->phase = 2; /* Phase out */\r
+                       RETURN(RC_OK);\r
+               case XCT_OPENING:\r
+                       if(ctx->phase) break;\r
+                       ADVANCE(ch_size);\r
+                       ctx->phase = 1; /* Processing body phase */\r
+                       continue;\r
+               case XCT_CLOSING:\r
+                       if(!ctx->phase) break;\r
+                       ADVANCE(ch_size);\r
+                       ctx->phase = 2; /* Phase out */\r
+                       RETURN(RC_OK);\r
+               case XCT_UNKNOWN_BO:\r
+                       /*\r
+                        * Certain tags in the body may be expected.\r
+                        */\r
+                       if(opt_unexpected_tag_decoder\r
+                       && opt_unexpected_tag_decoder(struct_key,\r
+                                       buf_ptr, ch_size) >= 0) {\r
+                               /* Tag's processed fine */\r
+                               ADVANCE(ch_size);\r
+                               if(!ctx->phase) {\r
+                                       /* We are not expecting\r
+                                        * the closing tag anymore. */\r
+                                       ctx->phase = 2; /* Phase out */\r
+                                       RETURN(RC_OK);\r
+                               }\r
+                               continue;\r
+                       }\r
+                       /* Fall through */\r
+               default:\r
+                       break;          /* Unexpected tag */\r
+               }\r
+\r
+               ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag);\r
+               break;  /* Dark and mysterious things have just happened */\r
+       }\r
+\r
+       RETURN(RC_FAIL);\r
+}\r
+\r
+\r
+size_t\r
+xer_whitespace_span(const void *chunk_buf, size_t chunk_size) {\r
+       const char *p = (const char *)chunk_buf;\r
+       const char *pend = p + chunk_size;\r
+\r
+       for(; p < pend; p++) {\r
+               switch(*p) {\r
+               /* X.693, #8.1.4\r
+                * HORISONTAL TAB (9)\r
+                * LINE FEED (10) \r
+                * CARRIAGE RETURN (13) \r
+                * SPACE (32)\r
+                */\r
+               case 0x09: case 0x0a: case 0x0d: case 0x20:\r
+                       continue;\r
+               default:\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+       return (p - (const char *)chunk_buf);\r
+}\r
+\r
+/*\r
+ * This is a vastly simplified, non-validating XML tree skipper.\r
+ */\r
+int\r
+xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) {\r
+       assert(*depth > 0);\r
+       switch(tcv) {\r
+       case XCT_BOTH:\r
+       case XCT_UNKNOWN_BO:\r
+               /* These negate each other. */\r
+               return 0;\r
+       case XCT_OPENING:\r
+       case XCT_UNKNOWN_OP:\r
+               ++(*depth);\r
+               return 0;\r
+       case XCT_CLOSING:\r
+       case XCT_UNKNOWN_CL:\r
+               if(--(*depth) == 0)\r
+                       return (tcv == XCT_CLOSING) ? 2 : 1;\r
+               return 0;\r
+       default:\r
+               return -1;\r
+       }\r
+}\r