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