fastapi.c
上传用户:myichia
上传日期:2019-01-05
资源大小:217k
文件大小:34k
源码类别:

TAPI编程

开发平台:

C/C++

  1. // $Id: fastapi.c,v 1.2 2006/02/09 19:14:24 Daniel.May Exp $
  2. //
  3. // FIX Adapted for STreaming (sm) (FAST Protocol (sm)) 
  4. //
  5. // Copyright (c) 2005-2006, Pantor Engineering AB (http://www.pantor.com)
  6. // Copyright (c) 2005-2006, SpryWare LLC (http://www.spryware.com)
  7. // Copyright (c) 2005-2006, FIX Protocol Ltd (http://www.fixprotocol.org)
  8. // All Rights Reserved.
  9. //
  10. // This work is distributed under the W3C® Software License [1] in the
  11. // hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. // implied warranty of MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS 
  13. // FOR A PARTICULAR PURPOSE.
  14. //
  15. // [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
  16. // [FPL's Intellectual Property details] http://www.fixprotocol.org/ip
  17. // [FAST Protocol details] http://www.fixprotocol.org/fast
  18. // [FAST Protocol credits] http://fixprotocol.org/fastcredits
  19. #include "common.h"
  20. #include "fastapi.h"
  21. //////////////////////////////////////////////////////////////////////
  22. static void reset_buffer (fast_buffer_t* buffer)
  23. {
  24.    buffer->head = buffer->data;
  25.    buffer->tail = buffer->data;
  26.    buffer->end  = buffer->data + sizeof (buffer->data);
  27. }
  28. static void init_buffer (fast_buffer_t* buffer, int fd)
  29. {
  30.    reset_buffer (buffer);
  31.    buffer->fd = fd;
  32. }
  33. static inline int buffer_empty_p (fast_buffer_t* buffer)
  34. {
  35.    return buffer->head >= buffer->tail;
  36. }
  37. static inline int get_buffer_left (fast_buffer_t* buffer)
  38. {
  39.    return buffer->end - buffer->tail;
  40. }
  41. static inline int get_buffer_size (fast_buffer_t* buffer)
  42. {
  43.    return buffer->end - buffer->data;
  44. }
  45. static inline int get_buffer_used (fast_buffer_t* buffer)
  46. {
  47.    return buffer->tail - buffer->head;
  48. }
  49. //////////////////////////////////////////////////////////////////////
  50. static inline u32 get_tag_op (u32 tag)
  51. {
  52.    return (tag >> TAG_SHIFT_OP) & TAG_MAX_OP;
  53. }
  54. static inline u32 get_tag_slot (u32 tag)
  55. {
  56.    return (tag >> TAG_SHIFT_SLOT) & TAG_MAX_SLOT;
  57. }
  58. static inline u32 get_tag_tid (u32 tag)
  59. {
  60.    return (tag >> TAG_SHIFT_TID) & TAG_MAX_TID;
  61. }
  62. static inline u32 get_tag_type (u32 tag)
  63. {
  64.    return (tag >> TAG_SHIFT_TYPE) & TAG_MAX_TYPE;
  65. }
  66. static inline fast_cv_t* cv_get_tag_state (fast_codec_t* codec, u32 tag)
  67. {
  68.    u32 slot = get_tag_tid (tag);
  69.    return & codec->cv [slot];
  70. }
  71. static inline i32* cv_get_i32_values (fast_codec_t* codec, u32 tag)
  72. {
  73.    return cv_get_tag_state (codec, tag)->i32_values;
  74. }
  75. static inline u32* cv_get_u32_values (fast_codec_t* codec, u32 tag)
  76. {
  77.    return cv_get_tag_state (codec, tag)->u32_values;
  78. }
  79. static inline u8** cv_get_str_values (fast_codec_t* codec, u32 tag)
  80. {
  81.    return cv_get_tag_state (codec, tag)->str_values;
  82. }
  83. static inline u32* cv_get_valid_values (fast_codec_t* codec, u32 tag)
  84. {
  85.    return cv_get_tag_state (codec, tag)->valid;
  86. }
  87. //////////////////////////////////////////////////////////////////////
  88. static inline i32 cv_get_i32 (fast_codec_t* codec, u32 tag)
  89. {
  90.    return cv_get_i32_values (codec, tag) [get_tag_slot (tag)];
  91. }
  92. static inline u32 cv_get_u32 (fast_codec_t* codec, u32 tag)
  93. {
  94.    return cv_get_u32_values (codec, tag) [get_tag_slot (tag)];
  95. }
  96. static inline u8* cv_get_str (fast_codec_t* codec, u32 tag)
  97. {
  98.    u8** str_values = cv_get_str_values (codec, tag);
  99.    u32 slot = get_tag_slot (tag);
  100.    if (str_values [slot] == NULL)
  101.    {
  102.       str_values [slot] = malloc (1024);
  103.       assert (str_values [slot] != NULL);
  104.       strcpy ((char*) str_values [slot], "");
  105.    }
  106.    return str_values [slot];
  107. }
  108. //////////////////////////////////////////////////////////////////////
  109. static inline void cv_set_valid (fast_codec_t* codec, u32 tag)
  110. {
  111.    cv_get_valid_values (codec, tag) [get_tag_slot (tag)] = 1;
  112. }
  113. static inline int cv_is_valid (fast_codec_t* codec, u32 tag)
  114. {
  115.    return cv_get_valid_values (codec, tag) [get_tag_slot (tag)] != 0;
  116. }
  117. //////////////////////////////////////////////////////////////////////
  118. static inline int cv_eq_i32 (fast_codec_t* codec, u32 tag, i32 data)
  119. {
  120.    return cv_is_valid (codec, tag) && cv_get_i32 (codec, tag) == data;
  121. }
  122. static inline int cv_eq_u32 (fast_codec_t* codec, u32 tag, u32 data)
  123. {
  124.    return cv_is_valid (codec, tag) && cv_get_u32 (codec, tag) == data;
  125. }
  126. static inline int cv_eq_str (fast_codec_t* codec, u32 tag, u8* data, int size)
  127. {
  128.    u8* cp = cv_get_str (codec, tag);
  129.    // Invalid or not the same length
  130.    // Fixme: cp [size] != '' not a valid test?
  131.    if (cv_is_valid (codec, tag) == 0 || cp [size] != '')
  132.       return 0;
  133.    return memcmp (cp, data, size) == 0;
  134. }
  135. //////////////////////////////////////////////////////////////////////
  136. //! @brief Set the current signed integer value for the specified tag
  137. static inline void cv_set_i32 (fast_codec_t* codec, u32 tag, i32 data)
  138. {
  139.    cv_get_i32_values (codec, tag) [get_tag_slot (tag)] = data;
  140.    cv_set_valid (codec, tag);
  141. }
  142. //! @brief Set the current unsigned integer value for the specified tag
  143. static inline void cv_set_u32 (fast_codec_t* codec, u32 tag, u32 data)
  144. {
  145.    cv_get_u32_values (codec, tag) [get_tag_slot (tag)] = data;
  146.    cv_set_valid (codec, tag);
  147. }
  148. //! @brief Set the current string value for the specified tag
  149. static inline void cv_set_str (fast_codec_t* codec, u32 tag,
  150.                                u8* data, int size)
  151. {
  152.    u8* cp = cv_get_str (codec, tag);
  153.    memcpy (cp, data, size);
  154.    cp [size] = '';
  155.    cv_set_valid (codec, tag);
  156. }
  157. //////////////////////////////////////////////////////////////////////
  158. static int u32_to_size (u32 data)
  159. {
  160.    if (data < 0x00000080) return 1; // 128
  161.    if (data < 0x00004000) return 2; // 16384
  162.    if (data < 0x00200000) return 3; // 2097152
  163.    if (data < 0x10000000) return 4; // 268435456
  164.    return 5;
  165. }
  166. static int i32_to_size (i32 data)
  167. {
  168.    if (data < 0)
  169.    {
  170.       if (data >= 0xffffffc0) return 1; // -64
  171.       if (data >= 0xffffe000) return 2; // -8192
  172.       if (data >= 0xfff00000) return 3; // -1048576
  173.       if (data >= 0xf8000000) return 4; // -124317728
  174.    }
  175.    else
  176.    {
  177.       if (data <  0x00000040) return 1; // 64
  178.       if (data <  0x00002000) return 2; // 8192
  179.       if (data <  0x00100000) return 3; // 1048576
  180.       if (data <  0x08000000) return 4; // 134217728
  181.    }
  182.    return 5;
  183. }
  184. //////////////////////////////////////////////////////////////////////
  185. static const char* format_error_code (fast_error_t code)
  186. {
  187.    switch (code)
  188.    {
  189.     case FAST_ERR_NONE:     return "none";
  190.     case FAST_ERR_CODEC:    return "bad codec";
  191.     case FAST_ERR_SIZE:     return "size error";
  192.     case FAST_ERR_VALUE:    return "missing value";
  193.     case FAST_ERR_TAG_OP:   return "tag op unsupported";
  194.     case FAST_ERR_TAG_TYPE: return "bad tag type";
  195.     case FAST_ERR_CALL_SEQ: return "bad call sequence";
  196.     case FAST_ERR_IO:       return "I/O library error";
  197.     default:                return "??";
  198.    }
  199. }
  200. static const char* format_tag_op (fast_op_t op)
  201. {
  202.    static char buffer [32];
  203.    switch (op)
  204.    {
  205.     case FAST_OP_NONE:  return "NONE";
  206.     case FAST_OP_COPY:  return "COPY";
  207.     case FAST_OP_INCR:  return "INCR";
  208.     case FAST_OP_DELTA: return "DELTA";
  209.     default:
  210.       snprintf (buffer, sizeof (buffer), "%u", op);
  211.       return buffer;
  212.    }
  213. }
  214. static const char* format_tag_type (fast_type_t type)
  215. {
  216.    static char buffer [32];
  217.    switch (type)
  218.    {
  219.     case FAST_TYPE_NULL: return "NULL";
  220.     case FAST_TYPE_U32:  return "U32";
  221.     case FAST_TYPE_I32:  return "I32";
  222.     case FAST_TYPE_STR:  return "STR";
  223.     default:
  224.       snprintf (buffer, sizeof (buffer), "%u", type);
  225.       return buffer;
  226.    }
  227. }
  228. //////////////////////////////////////////////////////////////////////
  229. static int set_err (const char* fn, fast_codec_t* codec,
  230.                      fast_tag_t tag, fast_error_t code,
  231.                      const char* format, ...)
  232. {
  233.    char buffer [1024];
  234.    va_list ap;
  235.    codec->error->fn   = fn;
  236.    codec->error->tag  = tag;
  237.    codec->error->code = code;
  238.    va_start (ap, format);
  239.    vsnprintf (buffer, sizeof (buffer), format, ap);
  240.    va_end   (ap);
  241.    if (codec->error->text != NULL)
  242.       free (codec->error->text);
  243.    codec->error->text = malloc (strlen (buffer) + 1);
  244.    strcpy (codec->error->text, buffer);
  245.    if (codec->verbose >= 1)
  246.       fprintf (stderr, "error: %sn", fast_error_string (codec));
  247.    return -1;
  248. }
  249. static int check_codec (const char* fn, fast_codec_t* codec)
  250. {
  251.    if (codec == NULL)
  252.    {
  253.       fprintf (stderr, "error: [%s] NULL codecn", fn);
  254.       return -1;
  255.    }
  256.    if (codec->magic != FAST_CODEC_MAGIC)
  257.       return set_err (fn, codec, -1, FAST_ERR_CODEC,
  258.                       "bad codec magic number");
  259.    return 0;
  260. }
  261. static int check_type (const char* fn, fast_codec_t* codec,
  262.                        fast_tag_t tag, u32 type)
  263. {
  264.    if (get_tag_type (tag) != type)
  265.       return set_err (fn, codec, tag, FAST_ERR_TAG_TYPE,
  266.                       "type=%s (%s expected)",
  267.                       format_tag_type (get_tag_type (tag)),
  268.                       format_tag_type (type));
  269.    return 0;
  270. }
  271. static int bad_op_error (const char* fn, fast_codec_t* codec, fast_tag_t tag)
  272. {
  273.    return set_err (fn, codec, tag, FAST_ERR_TAG_OP, "");
  274. }
  275.                                 
  276. static int value_error (const char* fn, fast_codec_t* codec, fast_tag_t tag)
  277. {
  278.    return set_err (fn, codec, tag, FAST_ERR_VALUE, "");
  279. }
  280. //! @brief Generate an error string using the current error info
  281. const char* fast_error_string (fast_codec_t* codec)
  282. {
  283.    fast_tag_t tag = codec->error->tag;
  284.    static char buffer [1024];
  285.    snprintf (buffer, sizeof (buffer), "[%s] %s|%s|%u|%u %s: %s",
  286.              codec->error->fn,
  287.              format_tag_type (get_tag_type (tag)),
  288.              format_tag_op (get_tag_op (tag)),
  289.              get_tag_tid (tag),
  290.              get_tag_slot (tag),
  291.              format_error_code (codec->error->code),
  292.              codec->error->text ? codec->error->text : "");
  293.    return buffer;
  294. }
  295. int fast_print_error (fast_codec_t* codec, FILE* fp)
  296. {
  297.    const char* msg = fast_error_string (codec);
  298.    fprintf (fp, "%sn", msg);
  299.    return 0;
  300. }
  301. //////////////////////////////////////////////////////////////////////
  302. //! @brief Get a presence bit from the current presence map
  303. static int get_pmap (fast_codec_t* codec, fast_tag_t tag)
  304. {
  305.    u32 pos = get_tag_slot (tag);
  306.    // Optimization: Don't range check pos separately
  307.    // We only need to check for the current size.
  308.    if (pos >= codec->pmap->size)
  309.       return 0;
  310.    return codec->pmap->bits [pos];
  311. }
  312. //! @brief Reset the current presence map
  313. static void reset_pmap (fast_codec_t* codec)
  314. {
  315.    // Fixme: Consider memset'ing to max_pos.
  316.    memset (codec->pmap->bits, 0, MAX_PMAP_BITS);
  317.    codec->pmap->max_pos = 0;
  318. }
  319. //! @brief Set a presence bit in the current presence map
  320. static int set_pmap (fast_codec_t* codec, fast_tag_t tag)
  321. {
  322.    u32 pos = get_tag_slot (tag);
  323.    if (pos > codec->pmap->max_pos)
  324.    {
  325.       // Optimization: Only range check pos if pos
  326.       // is larger than the current max_pos
  327.       if (pos >= MAX_PMAP_BITS)
  328.          return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
  329.                          "pmap slot=%d (< %d expected)",
  330.                          pos, MAX_PMAP_BITS);
  331.       codec->pmap->max_pos = pos;
  332.    }
  333.    codec->pmap->bits [pos] = 1;
  334.    return 0;
  335. }
  336. static u32 bit_mask [8] = { 64, 32, 16, 8, 4, 2, 1, 0 };
  337. // emit_pmap copies the pmap into the data buffer
  338. // and returns the size of the pmap
  339. //! Serialize the current presence map
  340. static int emit_pmap (fast_codec_t* codec, u8* data)
  341. {
  342.    int bytes = align7 (codec->pmap->max_pos + 1); // get map size in bytes
  343.    int offset;
  344.    int p1;
  345.    // pack slots from map->bits (seven at a time) into
  346.    // data to form a STOP bit coded field.
  347.    for (p1 = 0, offset = 0 ; p1 < bytes ; p1 ++, offset += 7)
  348.    {
  349.       u8* bits = & codec->pmap->bits [offset];
  350.       u32 temp = 0;
  351.       int p2;
  352.       for (p2 = 0 ; p2 < 7 ; p2 ++) // pack 7 slot into temp
  353.       {
  354.          if (bits [p2] > 0)
  355.             temp |= bit_mask [p2];
  356.       }
  357.       data [p1] = temp;
  358.    }
  359.    data [bytes - 1] |= 0x80; // Set the STOP bit
  360.    return bytes;
  361. }
  362. //////////////////////////////////////////////////////////////////////
  363. //! @brief Append a byte to the message buffer
  364. static inline void emit_byte (fast_codec_t* codec, u8 data)
  365. {
  366.    *codec->msg->tail ++ = data;
  367. }
  368. //////////////////////////////////////////////////////////////////////
  369. //! @brief Verify that there is enough room in the output buffer
  370. //! to store size bytes of data into the buffer.
  371. static inline  int check_msg_avail (const char* fn, fast_codec_t* codec,
  372.                                     fast_tag_t tag, int size)
  373. {
  374.    if (get_buffer_left (codec->msg) < size)
  375.       return set_err (fn, codec, tag, FAST_ERR_SIZE,
  376.                       "message buffer overflow avail=%d needed=%d",
  377.                       get_buffer_left (codec->msg), size);
  378.    return 0;
  379. }
  380. //! @callgraph
  381. //! @brief Serialize a 32-bit signed integer field
  382. static int emit_i32 (fast_codec_t* codec, fast_tag_t tag, i32 data)
  383. {
  384.    int size = i32_to_size (data);
  385.    // Check buffer space once, not for every byte
  386.    if (check_msg_avail (FUNCTION, codec, tag, size) < 0)
  387.       return -1;
  388.    switch (size)
  389.    {
  390.       // Shifts are arithmetic (signed)
  391.       // The sign bit of data will be copied on right shifts
  392.     case 5: emit_byte (codec, (data >> 28) & 0x7f);
  393.     case 4: emit_byte (codec, (data >> 21) & 0x7f);
  394.     case 3: emit_byte (codec, (data >> 14) & 0x7f);
  395.     case 2: emit_byte (codec, (data >>  7) & 0x7f);
  396.     case 1: emit_byte (codec, (data & 0x7f) | 0x80);
  397.       {
  398.          int code = set_pmap (codec, tag);
  399.          if (code < 0)
  400.             return code;
  401.       }
  402.       return size;
  403.     default:
  404.       return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
  405.                       "size=%d data=%d (%08x)", size, data, data);
  406.    }
  407. }
  408. //! @brief Serielize a 32-bit unsigned integer field
  409. static int emit_u32 (fast_codec_t* codec, fast_tag_t tag, u32 data)
  410. {
  411.    int size = u32_to_size (data);
  412.    // Check buffer space once, not for every byte
  413.    if (check_msg_avail (FUNCTION, codec, tag, size) < 0)
  414.       return -1;
  415.    switch (size)
  416.    {
  417.       // Shifts are logical (unsigned)
  418.     case 5: emit_byte (codec,  data >> 28);
  419.     case 4: emit_byte (codec, (data >> 21) & 0x7f);
  420.     case 3: emit_byte (codec, (data >> 14) & 0x7f);
  421.     case 2: emit_byte (codec, (data >>  7) & 0x7f);
  422.     case 1: emit_byte (codec, (data & 0x7f) | 0x80);
  423.       {
  424.          int code = set_pmap (codec, tag);
  425.          if (code < 0)
  426.             return code;
  427.       }
  428.       return size;
  429.     default:
  430.       return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
  431.                       "size=%d data=%d (%08x)", size, data, data);
  432.    }
  433. }
  434. //! @brief Serialize an ASCII string field
  435. static int emit_str (fast_codec_t* codec, fast_tag_t tag, u8* data, int size)
  436. {
  437.    // Zero length strings cannot be encoded
  438.    if (size <= 0)
  439.       return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
  440.                       "size=%d (>0 expected)", size);
  441.    // Check buffer space once, not for every byte
  442.    if (check_msg_avail (FUNCTION, codec, tag, size) < 0)
  443.       return -1;
  444.    {
  445.       int p1;
  446.       for (p1 = 0 ; p1 < size - 1 ; p1 ++)
  447.          emit_byte (codec, data [p1]);
  448.       emit_byte (codec, data [p1] | 0x80); // Last byte
  449.    }
  450.    {
  451.       int code = set_pmap (codec, tag);
  452.       if (code < 0)
  453.          return code;
  454.    }
  455.    return size;
  456. }
  457. //////////////////////////////////////////////////////////////////////
  458. //! @brief Deserialize an SBIT coded field
  459. static int parse_bytes (fast_codec_t* codec, u8* data, int size)
  460. {
  461.    int p1;
  462.    // Fixme: Filler may be other than space?
  463.    memset (data, 0, size);
  464.    for (p1 = 0 ; p1 < size ; p1 ++)
  465.    {
  466.       u8 temp;
  467.       fast_buffer_t* input = codec->input;
  468.       if (buffer_empty_p (input))
  469.       {
  470.          int bytes;
  471.          if (codec->skip_io == 1)
  472.             return -1;
  473.          bytes = read (input->fd, input->data, get_buffer_size (input));
  474.          if (bytes <= 0)
  475.          {
  476.             if (bytes < 0)
  477.                fprintf (stderr, "read failed: %sn", strerror (errno));
  478.             return -1;
  479.          }
  480.          input->head = input->data;
  481.          input->tail = input->head + bytes;
  482.       }
  483.       temp = *input->head ++;
  484.       data [p1] = temp;
  485.       if (temp >= 0x80)
  486.       {
  487.          data [p1] &= 0x7f;
  488.          return p1 + 1;
  489.       }
  490.    }
  491.    // Fixme: calculate the real number of bytes in the field.
  492.    return set_err (FUNCTION, codec, -1, FAST_ERR_SIZE,
  493.                    "parse buffer overflow size=%d", size);
  494. }
  495. static int parse_pmap (fast_codec_t* codec)
  496. {
  497.    fast_pmap_t* pmap = codec->pmap;
  498.    u8  data [MAX_PMAP_BYTES];
  499.    int bytes = parse_bytes (codec, data, MAX_PMAP_BYTES);
  500.    int offset;
  501.    int p1;
  502.    if (bytes < 0)
  503.       return bytes;
  504.    for (p1 = 0, offset = 0 ; p1 < bytes ; p1 ++, offset += 7)
  505.    {
  506.       u32 temp = data [p1];
  507.       int p2;
  508.       for (p2 = 0 ; p2 < 7 ; p2 ++)
  509.       {
  510.          pmap->bits [offset + p2] = (temp & bit_mask [p2]) != 0;
  511.       }
  512.    }
  513.    codec->pmap->size = 7 * bytes;
  514.    return bytes;
  515. }
  516. #define SIGN_MASK_I32 0x40
  517. #define SIGN_MASK_U32 0x00
  518. static int parse_32 (fast_codec_t* codec, fast_tag_t tag,
  519.                      u32* data, int sign_mask)
  520. {
  521.    u8  buffer [5];
  522.    int bytes;
  523.    int p1;
  524.    i32 temp;
  525.    if (get_pmap (codec, tag) == 0)
  526.       return 0;
  527.    bytes = parse_bytes (codec, buffer, sizeof (buffer));
  528.    if (bytes < 0)
  529.       return bytes;
  530.    temp = 0 - ((buffer [0] & sign_mask) != 0);
  531.    for (p1 = 0 ; p1 < bytes ; p1 ++)
  532.       temp = (temp << 7) | buffer [p1];
  533.    *data = temp;
  534.    return bytes;
  535. }
  536. //////////////////////////////////////////////////////////////////////
  537. //! @brief Deserialize a 32-bit unsigned integer
  538. static int parse_u32 (fast_codec_t* codec, fast_tag_t tag, u32* data)
  539. {
  540.    return parse_32 (codec, tag, data, SIGN_MASK_U32);
  541. }
  542. //! @brief Deserialize a 32-bit signed integer
  543. static int parse_i32 (fast_codec_t* codec, fast_tag_t tag, i32* data)
  544. {
  545.    return parse_32 (codec, tag, (u32*) data, SIGN_MASK_I32);
  546. }
  547. //! @brief Deserialize an ASCII string
  548. static int parse_str (fast_codec_t* codec, fast_tag_t tag, u8* data, int size)
  549. {
  550.    return get_pmap (codec, tag) == 0 ? 0 : parse_bytes (codec, data, size);
  551. }
  552. //////////////////////////////////////////////////////////////////////
  553. // Decoder functions
  554. //! @brief Start decoding a message
  555. //! Parse the presence map
  556. int fast_decode_new_msg (fast_codec_t* codec, fast_tag_t tag)
  557. {
  558.    if (check_codec (FUNCTION, codec) < 0)
  559.       return -1;
  560.    return parse_pmap (codec);
  561. }
  562. //! @brief Finish decoding a message
  563. int fast_decode_end_msg (fast_codec_t* codec, fast_tag_t tag)
  564. {
  565.    if (check_codec (FUNCTION, codec) < 0)
  566.       return -1;
  567.    return 0;
  568. }
  569. //////////////////////////////////////////////////////////////////////
  570. //! @brief Decode an ASCII string
  571. int fast_decode_str (fast_codec_t* codec, fast_tag_t tag,
  572.                      u8* data, int size)
  573. {
  574.    fast_op_t op = get_tag_op (tag);
  575.    int bytes;
  576.    if (check_codec (FUNCTION, codec) < 0)
  577.       return -1;
  578.    if (check_type  (FUNCTION, codec, tag, FAST_TYPE_STR) < 0)
  579.       return -1;
  580. #if 0
  581.    // Fixme: Remove arbitrary limit
  582.    if (size <= 0 || size >= 1024)
  583.       return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
  584.                       "size=%d (1-1023 expected)", size);
  585. #endif
  586.    switch (op)
  587.    {
  588.     case FAST_OP_NONE:
  589.       bytes = parse_str (codec, tag, data, size);
  590.       if (bytes < 0) // End of input
  591.          return -1;
  592.       if (bytes == 0)
  593.          return value_error (FUNCTION, codec, tag);
  594.       break;
  595.     case FAST_OP_COPY:
  596.       bytes = parse_str (codec, tag, data, size);
  597.       if (bytes < 0)
  598.          return -1;
  599.       if (bytes > 0)
  600.       {
  601.          // Set current value
  602.          cv_set_str (codec, tag, data, size);
  603.       }
  604.       else
  605.       {
  606.          // Copy current value
  607.          memcpy (data, cv_get_str (codec, tag), size);
  608.       }
  609.       return size;
  610.     case FAST_OP_INCR:
  611.       return bad_op_error (FUNCTION, codec, tag);
  612.     case FAST_OP_DELTA:
  613.       {
  614.          u8  buffer [1024];
  615.          u8* curr = cv_get_str (codec, tag);
  616.          u32 bytes = parse_str (codec, tag, buffer, size);
  617.          if (cv_is_valid (codec, tag))
  618.          {
  619.             int temp;
  620.             if (bytes > (u32)size)
  621.                return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
  622.                                "oversized value %d > size=%d", bytes, size);
  623.             // This implementation requires delta string field values
  624.             // to be exactly the size of the field.
  625.             temp = strlen ((char*) curr);
  626.             if (temp != size)
  627.                return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
  628.                                "size mismatch %d != %d", temp, size);
  629.             // Replace (tail of) current value
  630.             memcpy (curr + size - bytes, buffer, bytes);
  631.          }
  632.          else
  633.          {
  634.             // Set current value
  635.             cv_set_str (codec, tag, buffer, bytes);
  636.          }
  637.          memcpy (data, cv_get_str (codec, tag), size);
  638.       }
  639.       break;
  640.     default:
  641.       bad_op_error (FUNCTION, codec, tag);
  642.    }
  643.    return 0;
  644. }
  645. //////////////////////////////////////////////////////////////////////
  646. //! @brief Decode a 32-bit signed integer
  647. int fast_decode_i32 (fast_codec_t* codec, fast_tag_t tag, i32* value)
  648. {
  649.    fast_op_t op = get_tag_op (tag);
  650.    i32 temp = 0;
  651.    int bytes;
  652.    if (check_codec (FUNCTION, codec) < 0)
  653.       return -1;
  654.    if (check_type  (FUNCTION, codec, tag, FAST_TYPE_I32) < 0)
  655.       return -1;
  656.    switch (op)
  657.    {
  658.     case FAST_OP_NONE: // Value must be present
  659.       bytes = parse_i32 (codec, tag, & temp);
  660.       if (bytes > 0)
  661.       {
  662.          cv_set_i32 (codec, tag, temp);
  663.          break;
  664.       }
  665.       if (bytes < 0) // End of input
  666.          return -1;
  667.       return value_error (FUNCTION, codec, tag);
  668.     case FAST_OP_COPY: // Use previous value if not present
  669.       bytes = parse_i32 (codec, tag, & temp);
  670.       if (bytes == 0) // No value - use previous [common case]
  671.          break;
  672.       if (bytes < 0) // End of input
  673.          return -1;
  674.       cv_set_i32 (codec, tag, temp);
  675.       break;
  676.     case FAST_OP_INCR: // Use previous value plus one if not present
  677.       bytes = parse_i32 (codec, tag, & temp);
  678.       if (bytes < 0) // End of input
  679.          return -1;
  680.       if (bytes == 0) // No value - use previous plus one
  681.       {
  682.          // Rule: The previous value must be valid
  683.          if (cv_is_valid (codec, tag) == 0)
  684.             return value_error (FUNCTION, codec, tag);
  685.          temp = cv_get_i32 (codec, tag) + 1;
  686.       }
  687.       cv_set_i32 (codec, tag, (u32) temp);
  688.       break;
  689.     case FAST_OP_DELTA:
  690.       if (cv_is_valid (codec, tag))
  691.       {
  692.          // Rule: delta defaults to ZERO if there is
  693.          // no value present
  694.          i32 delta;
  695.          bytes = parse_i32 (codec, tag, & delta);
  696.          if (bytes < 0) // error state already set
  697.             return -1;
  698.          if (bytes > 0)
  699.          {
  700.             temp = cv_get_i32 (codec, tag) + delta;
  701.             cv_set_i32 (codec, tag, temp);
  702.          }
  703.       }
  704.       else
  705.       {
  706.          // Rule: A field must be present it the
  707.          // current value isn't valid
  708.          bytes = parse_i32 (codec, tag, & temp);
  709.          if (bytes < 0) // error state already set
  710.             return -1;
  711.          if (bytes == 0)
  712.             return value_error (FUNCTION, codec, tag);
  713.          cv_set_i32 (codec, tag, temp);
  714.       }
  715.       break;
  716.     default:
  717.       return bad_op_error (FUNCTION, codec, tag);
  718.    }
  719.    *value = cv_get_i32 (codec, tag);
  720.    return 0;
  721. }
  722. //////////////////////////////////////////////////////////////////////
  723. //! @brief Decode a 32-bit unsigned integer
  724. int fast_decode_u32 (fast_codec_t* codec, fast_tag_t tag, u32* value)
  725. {
  726.    fast_op_t op = get_tag_op (tag);
  727.    u32 next = 0;
  728.    int bytes;
  729.    if (check_codec (FUNCTION, codec) < 0)
  730.       return -1;
  731.    if (check_type  (FUNCTION, codec, tag, FAST_TYPE_U32) < 0)
  732.       return -1;
  733.    switch (op)
  734.    {
  735.     case FAST_OP_NONE: // Value must be present
  736.       bytes = parse_u32 (codec, tag, & next);
  737.       if (bytes < 0) // End of input
  738.          return -1;
  739.       if (bytes == 0) // No data
  740.          return value_error (FUNCTION, codec, tag);
  741.       break;
  742.     case FAST_OP_COPY: // Use previous value if not present
  743.       bytes = parse_u32 (codec, tag, & next);
  744.       if (bytes < 0) // End of input
  745.          return -1;
  746.       if (bytes == 0) // No value - use previous [common case]
  747.       {
  748.          if (cv_is_valid (codec, tag) == 0) // must be valid
  749.             return value_error (FUNCTION, codec, tag);
  750.          
  751.          next = cv_get_u32 (codec, tag);
  752.          break;
  753.       }
  754.       break;
  755.     case FAST_OP_INCR: // use previous value plus one if not present
  756.       bytes = parse_u32 (codec, tag, & next);
  757.       if (bytes < 0) // End of input
  758.          return -1;
  759.       if (bytes == 0) // No value - use previous plus one
  760.       {
  761.          if (cv_is_valid (codec, tag) == 0) // must be valid
  762.             return value_error (FUNCTION, codec, tag);
  763.          next = cv_get_u32 (codec, tag) + 1;
  764.       }
  765.       break;
  766.     case FAST_OP_DELTA:
  767.       if (cv_is_valid (codec, tag))
  768.       {
  769.          // Rule: delta defaults to ZERO if there is
  770.          // no value present
  771.          i32 delta;
  772.          bytes = parse_i32 (codec, tag, & delta);
  773.          
  774.          if (bytes < 0)
  775.             return -1;
  776.          next = cv_get_u32 (codec, tag);
  777.          if (bytes > 0)
  778.             next += delta;
  779.       }
  780.       else
  781.       {
  782.          // Rule: A field must be present if the
  783.          // current value isn't valid
  784.          bytes = parse_u32 (codec, tag, & next);
  785.          if (bytes < 0)
  786.             return -1;
  787.          if (bytes == 0)
  788.             return value_error (FUNCTION, codec, tag);
  789.       }
  790.       break;
  791.     default:
  792.       return bad_op_error (FUNCTION, codec, tag);
  793.    }
  794.    cv_set_u32 (codec, tag, next);
  795.    *value = cv_get_u32 (codec, tag);
  796.    return 0;
  797. }
  798. //////////////////////////////////////////////////////////////////////
  799. // flush_group moves the current pmap and body data to the output
  800. // buffer.
  801. // Currently, flush_group is only called from flush_msg, but will
  802. // also be called from other sites when repeating groups become
  803. // supported in this implementation. 
  804. //! @brief Flush a group of fields
  805. //! Emit the presence map for the group and the serialized field data
  806. //
  807. //! @param codec
  808. static int flush_group (fast_codec_t* codec)
  809. {
  810.    fast_buffer_t* output = codec->output;
  811.    fast_buffer_t* msg = codec->msg;
  812.    int map_size;
  813.    //! @remark Make sure there is room in the output buffer
  814.    int size = get_buffer_used (msg);
  815.    int need = MAX_PMAP_BYTES + size;
  816.       
  817.    if (get_buffer_left (output) <= need)
  818.       return set_err (FUNCTION, codec, -1, FAST_ERR_SIZE,
  819.                       "output buffer overflow left=%d need=%d",
  820.                       get_buffer_left (output), need);
  821.    //! Copy the pmap into the output buffer
  822.    map_size = emit_pmap (codec, output->tail);
  823.    output->tail += map_size;
  824.    //! Copy the message body into the output buffer
  825.    memcpy (output->tail, msg->head, size);
  826.    output->tail += size;
  827.    //! Reset the presence map
  828.    reset_pmap (codec);
  829.    reset_buffer (codec->msg);
  830.    return 0;
  831. }
  832. //! @brief Flush a message
  833. //! Flush the last group of the message and write serialized data
  834. static int flush_msg (fast_codec_t* codec)
  835. {
  836.    fast_buffer_t* output = codec->output;
  837.    flush_group (codec);
  838.    if (codec->skip_io == 0)
  839.    {
  840.       if (write_n (output->fd, output->head, get_buffer_used (output)) < 0)
  841.          return set_err (FUNCTION, codec, -1, FAST_ERR_IO,
  842.                          "write_n failed: %s", strerror (errno));
  843.       reset_buffer (output);
  844.    }
  845.    return 0;
  846. }
  847. //////////////////////////////////////////////////////////////////////
  848. // fast_encode_new_msg is called to setup encoding for a message.
  849. // It must not be called again without calling fast_encode_end_msg
  850. // in between.
  851. //! @brief Start encoding a new message
  852. int fast_encode_new_msg (fast_codec_t* codec, fast_tag_t tag)
  853. {
  854.    check_codec (FUNCTION, codec);
  855.    if (codec->in_message != 0)
  856.       return set_err (FUNCTION, codec, tag, FAST_ERR_CALL_SEQ,
  857.                       "already in a message");
  858.    codec->in_message = 1;
  859.    codec->curr_tag = tag;
  860.    return 0;
  861. }
  862. //! @brief Finish encoding a message
  863. int fast_encode_end_msg (fast_codec_t* codec, fast_tag_t tag)
  864. {
  865.    check_codec (FUNCTION, codec);
  866.    if (codec->in_message == 0)
  867.       return set_err (FUNCTION, codec, tag, FAST_ERR_CALL_SEQ,
  868.                       "not in a message");
  869.    codec->in_message = 0;
  870.    return flush_msg (codec);
  871. }
  872. //////////////////////////////////////////////////////////////////////
  873. //! @brief Encode a 32-bit signed integer
  874. int fast_encode_i32 (fast_codec_t* codec, fast_tag_t tag, i32 value)
  875. {
  876.    fast_op_t op = get_tag_op (tag);
  877.    if (check_codec (FUNCTION, codec) < 0)
  878.       return -1;
  879.    if (check_type  (FUNCTION, codec, tag, FAST_TYPE_I32) < 0)
  880.       return -1;
  881.    switch (op)
  882.    {
  883.     case FAST_OP_NONE: // Always emit value
  884.       break;
  885.     case FAST_OP_COPY: // Emit value if not equal to previous value
  886.       if (cv_eq_i32 (codec, tag, value))
  887.          return 0;
  888.       break;
  889.     case FAST_OP_INCR: // Fixme: Implement
  890.       return bad_op_error (FUNCTION, codec, tag);
  891.     case FAST_OP_DELTA: // Fixme: Implement
  892.       return bad_op_error (FUNCTION, codec, tag);
  893.     default:
  894.       return bad_op_error (FUNCTION, codec, tag);
  895.    }
  896.    cv_set_i32 (codec, tag, value);
  897.    return emit_i32 (codec, tag, value);
  898. }
  899. static int find_char_delta_offset (u8* a, u8* b, int size)
  900. {
  901.    int p1;
  902.    for (p1 = 0 ; p1 < size ; p1 ++)
  903.       if (a [p1] != b [p1])
  904.          break;
  905.    return p1;
  906. }
  907. //! @brief Encode an ASCII string
  908. int fast_encode_str (fast_codec_t* codec, fast_tag_t tag,
  909.                      u8* data, int size)
  910. {
  911.    fast_op_t op = get_tag_op (tag);
  912.    if (check_codec (FUNCTION, codec) < 0)
  913.       return -1;
  914.    if (check_type  (FUNCTION, codec, tag, FAST_TYPE_STR) < 0)
  915.       return -1;
  916.    // Note: We don't prune the string in the codec layer
  917.    // Pruning should be done by the app codec
  918.    switch (op)
  919.    {
  920.     case FAST_OP_NONE:
  921.       break; // Always emit value
  922.     case FAST_OP_COPY: // Emit value if not equal to previous value
  923.       if (cv_eq_str (codec, tag, data, size))
  924.          return 0;
  925.       break;
  926.     case FAST_OP_INCR: // Not defined in the spec
  927.       return bad_op_error (FUNCTION, codec, tag);
  928.     case FAST_OP_DELTA:
  929.       {
  930.          u8* curr = cv_get_str (codec, tag);
  931.          u32 offset = find_char_delta_offset (curr, data, size);
  932.          if (offset == size)
  933.             return 0;
  934.          memcpy (curr + offset, data + offset, size - offset);
  935.          data += offset;
  936.          size -= offset;
  937.          return emit_str (codec, tag, data, size);
  938.       }
  939.     default:
  940.       return bad_op_error (FUNCTION, codec, tag);
  941.    }
  942.    cv_set_str (codec, tag, data, size);
  943.    return emit_str (codec, tag, data, size);
  944. }
  945. //! @brief Encode a 32-bit unsigned integer
  946. int fast_encode_u32 (fast_codec_t* codec, fast_tag_t tag, u32 value)
  947. {
  948.    fast_op_t op = get_tag_op (tag);
  949.    u32 next = value;
  950.    if (check_codec (FUNCTION, codec) < 0)
  951.       return -1;
  952.    if (check_type  (FUNCTION, codec, tag, FAST_TYPE_U32) < 0)
  953.       return -1;
  954.    switch (op)
  955.    {
  956.     case FAST_OP_NONE: // Always emit value
  957.       break;
  958.     case FAST_OP_COPY: // Emit value if not equal to previous value
  959.       if (cv_eq_u32 (codec, tag, value))
  960.          return 0;
  961.       break;
  962.     case FAST_OP_INCR: // Emit value if not previous value plus one
  963.       next = value + 1;
  964.       if (cv_eq_u32 (codec, tag, value))
  965.       {
  966.          cv_set_u32 (codec, tag, next);
  967.          return 0;
  968.       }
  969.       break;
  970.     case FAST_OP_DELTA:
  971.       if (cv_is_valid (codec, tag)) // Emit value if not equal to previous
  972.       {
  973.          i32 delta = (i32) value - cv_get_u32 (codec, tag);
  974.          // Fixme: use parameter to control zero deltas
  975.          if (delta == 0)
  976.             return 0;
  977.          cv_set_u32 (codec, tag, value);
  978.          return emit_i32 (codec, tag, delta);
  979.       }
  980.       break;
  981.     default:
  982.       return bad_op_error (FUNCTION, codec, tag);
  983.    }
  984.    cv_set_u32 (codec, tag, next); // update previous value state
  985.    return emit_u32 (codec, tag, value); // emit the value
  986. }
  987. //////////////////////////////////////////////////////////////////////
  988. //! @brief Create a CODEC (encoder/decoder)
  989. fast_codec_t* fast_create_codec (void)
  990. {
  991.    fast_codec_t* codec = malloc (sizeof (*codec));
  992.    if (codec == NULL)
  993.    {
  994.       fprintf (stderr, "error: [%s] malloc failedn", FUNCTION);
  995.       return NULL;
  996.    }
  997.    memset (codec, 0, sizeof (*codec));
  998.    codec->magic  = FAST_CODEC_MAGIC;
  999.    init_buffer (codec->msg,   -1);
  1000.    init_buffer (codec->input,  0);
  1001.    init_buffer (codec->output, 1);
  1002.    return codec;
  1003. }
  1004. int fast_destroy_codec (fast_codec_t* codec)
  1005. {
  1006.    if (codec == NULL)
  1007.    {
  1008.       fprintf (stderr, "error: [%s] null codecn", FUNCTION);
  1009.       return -1;
  1010.    }
  1011.    if (codec->magic != FAST_CODEC_MAGIC)
  1012.    {
  1013.       fprintf (stderr, "error: [%s] bad codec magic numbern", FUNCTION);
  1014.       return -1;
  1015.    }
  1016.    codec->magic = 0; // To prevent dangling references
  1017.    free (codec);
  1018.    return 0;
  1019. }
  1020. u32 fast_ascii_to_u32 (u8* data, int size)
  1021. {
  1022.    u32 temp = 0;
  1023.    int p1;
  1024.    for (p1 = 0 ; p1 < size ; p1 ++)
  1025.    {
  1026.       int chr = data [p1];
  1027.       temp = temp * 10 + chr - '0';
  1028.    }
  1029.    return temp;
  1030. }