wsencode.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:6k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  *
  3.  * wsencode.c
  4.  *
  5.  * Author: Markku Rossi <mtr@iki.fi>
  6.  *
  7.  * Copyright (c) 1999-2000 WAPIT OY LTD.
  8.  *  All rights reserved.
  9.  *
  10.  * Encoding and decoding routines.
  11.  *
  12.  */
  13. #include "wsint.h"
  14. /********************* Types and definitions ****************************/
  15. #define WS_MB_CONT_BIT 0x80
  16. #define WS_MB_DATA_MASK 0x7f
  17. /********************* Global functions *********************************/
  18. unsigned char *ws_encode_mb_uint32(WsUInt32 value, unsigned char *buffer,
  19.                                    size_t *len_return)
  20. {
  21.     unsigned char *p = buffer + WS_MB_UINT32_MAX_ENCODED_LEN;
  22.     size_t len = 1;
  23.     /* Set the terminator byte. */
  24.     *p = value & WS_MB_DATA_MASK;
  25.     value >>= 7;
  26.     p--;
  27.     /* And add the data. */
  28.     while (value > 0) {
  29.         *p = (value & WS_MB_DATA_MASK) | WS_MB_CONT_BIT;
  30.         value >>= 7;
  31.         p--;
  32.         len++;
  33.     }
  34.     *len_return = len;
  35.     return p + 1;
  36. }
  37. WsUInt32 ws_decode_mb_uint32(const unsigned char *buffer, size_t *len)
  38. {
  39.     WsUInt32 value = 0;
  40.     size_t i;
  41.     for (i = 0; i < *len; i++) {
  42.         value <<= 7;
  43.         value |= buffer[i] & WS_MB_DATA_MASK;
  44.         if ((buffer[i] & WS_MB_CONT_BIT) == 0)
  45.             break;
  46.     }
  47.     *len = i + 1;
  48.     return value;
  49. }
  50. WsBool ws_encode_buffer(WsBuffer *buffer, ...)
  51. {
  52.     va_list ap;
  53.     WsEncodingSpec spec;
  54.     int ival;
  55.     unsigned char *p;
  56.     unsigned char *cp;
  57.     size_t len;
  58.     WsUInt32 ui32;
  59.     unsigned char data[64];
  60.     va_start(ap, buffer);
  61.     while ((spec = va_arg(ap, int)) != WS_ENC_END)
  62.     {
  63.         switch (spec)
  64.         {
  65.         case WS_ENC_BYTE:
  66.         case WS_ENC_INT8:
  67.         case WS_ENC_UINT8:
  68.             ival = va_arg(ap, int);
  69.             if (!ws_buffer_append_space(buffer, &p, 1))
  70.                 goto error;
  71.             WS_PUT_UINT8(p, ival);
  72.             break;
  73.         case WS_ENC_INT16:
  74.         case WS_ENC_UINT16:
  75.             ival = va_arg(ap, int);
  76.             if (!ws_buffer_append_space(buffer, &p, 2))
  77.                 goto error;
  78.             WS_PUT_UINT16(p, ival);
  79.             break;
  80.         case WS_ENC_INT32:
  81.         case WS_ENC_UINT32:
  82.             ival = va_arg(ap, long);
  83.             if (!ws_buffer_append_space(buffer, &p, 4))
  84.                 goto error;
  85.             WS_PUT_UINT32(p, ival);
  86.             break;
  87.         case WS_ENC_MB_UINT16:
  88.         case WS_ENC_MB_UINT32:
  89.             if (spec == WS_ENC_MB_UINT16)
  90.                 ui32 = va_arg(ap, int);
  91.             else
  92.                 ui32 = va_arg(ap, long);
  93.             len = sizeof(data);
  94.             cp = ws_encode_mb_uint32(ui32, data, &len);
  95.             if (!ws_buffer_append_space(buffer, &p, len))
  96.                 goto error;
  97.             memcpy(p, cp, len);
  98.             break;
  99.         case WS_ENC_DATA:
  100.             cp = va_arg(ap, unsigned char *);
  101.             len = va_arg(ap, unsigned int);
  102.             if (!ws_buffer_append_space(buffer, &p, len))
  103.                 goto error;
  104.             memcpy(p, cp, len);
  105.             break;
  106.         default:
  107.             ws_fatal("ws_encode_buffer(): unknown type %d: probably a missing "
  108.                      "WS_ENC_END",
  109.                      spec);
  110.             break;
  111.         }
  112.     }
  113.     va_end(ap);
  114.     return WS_TRUE;
  115.     /*
  116.      * Error handling.
  117.      */
  118. error:
  119.     va_end(ap);
  120.     return WS_FALSE;
  121. }
  122. size_t ws_decode_buffer(const unsigned char *buffer, size_t buffer_len, ...)
  123. {
  124.     va_list ap;
  125.     WsEncodingSpec spec;
  126.     WsUInt8 *i8p;
  127.     WsUInt16 *i16p;
  128.     WsUInt32 *i32p;
  129.     unsigned char **cpp;
  130.     size_t len;
  131.     size_t orig_buffer_len = buffer_len;
  132.     va_start(ap, buffer_len);
  133.     while ((spec = va_arg(ap, int)) != WS_ENC_END) {
  134.         switch (spec) {
  135.         case WS_ENC_BYTE:
  136.         case WS_ENC_INT8:
  137.         case WS_ENC_UINT8:
  138.             if (buffer_len < 1)
  139.                 goto too_short_buffer;
  140.             i8p = va_arg(ap, WsUInt8 *);
  141.             WS_GET_UINT8(buffer, *i8p);
  142.             buffer++;
  143.             buffer_len--;
  144.             break;
  145.         case WS_ENC_INT16:
  146.         case WS_ENC_UINT16:
  147.             if (buffer_len < 2)
  148.                 goto too_short_buffer;
  149.             i16p = va_arg(ap, WsUInt16 *);
  150.             WS_GET_UINT16(buffer, *i16p);
  151.             buffer += 2;
  152.             buffer_len -= 2;
  153.             break;
  154.         case WS_ENC_INT32:
  155.         case WS_ENC_UINT32:
  156.             if (buffer_len < 4)
  157.                 goto too_short_buffer;
  158.             i32p = va_arg(ap, WsUInt32 *);
  159.             WS_GET_UINT32(buffer, *i32p);
  160.             buffer += 4;
  161.             buffer_len -= 4;
  162.             break;
  163.         case WS_ENC_MB_UINT16:
  164.         case WS_ENC_MB_UINT32:
  165.             {
  166.                 size_t len = buffer_len;
  167.                 WsUInt32 i32;
  168.                 if (buffer_len < 1)
  169.                     goto too_short_buffer;
  170.                 i32 = ws_decode_mb_uint32(buffer, &len);
  171.                 if (spec == WS_ENC_MB_UINT16) {
  172.                     i16p = va_arg(ap, WsUInt16 *);
  173.                     *i16p = i32;
  174.                 } else {
  175.                     i32p = va_arg(ap, WsUInt32 *);
  176.                     *i32p = i32;
  177.                 }
  178.                 buffer += len;
  179.                 buffer_len -= len;
  180.             }
  181.             break;
  182.         case WS_ENC_DATA:
  183.             cpp = va_arg(ap, unsigned char **);
  184.             len = va_arg(ap, size_t);
  185.             if (buffer_len < len)
  186.                 goto too_short_buffer;
  187.             *cpp = (unsigned char *) buffer;
  188.             buffer += len;
  189.             buffer_len -= len;
  190.             break;
  191.         default:
  192.             ws_fatal("ws_encode_buffer(): unknown type %d: probably a missing "
  193.                      "WS_ENC_END",
  194.                      spec);
  195.             break;
  196.         }
  197.     }
  198.     va_end(ap);
  199.     return orig_buffer_len - buffer_len;
  200. too_short_buffer:
  201.     va_end(ap);
  202.     return 0;
  203. }