00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "common.h"
00021 #include "fastapi.h"
00022
00024
00025 static void reset_buffer (fast_buffer_t* buffer)
00026 {
00027 buffer->head = buffer->data;
00028 buffer->tail = buffer->data;
00029 buffer->end = buffer->data + sizeof (buffer->data);
00030 }
00031
00032 static void init_buffer (fast_buffer_t* buffer, int fd)
00033 {
00034 reset_buffer (buffer);
00035
00036 buffer->fd = fd;
00037 }
00038
00039 static inline int buffer_empty_p (fast_buffer_t* buffer)
00040 {
00041 return buffer->head >= buffer->tail;
00042 }
00043
00044 static inline int get_buffer_left (fast_buffer_t* buffer)
00045 {
00046 return buffer->end - buffer->tail;
00047 }
00048
00049 static inline int get_buffer_size (fast_buffer_t* buffer)
00050 {
00051 return buffer->end - buffer->data;
00052 }
00053
00054 static inline int get_buffer_used (fast_buffer_t* buffer)
00055 {
00056 return buffer->tail - buffer->head;
00057 }
00058
00060
00061 static inline u32 get_tag_op (u32 tag)
00062 {
00063 return (tag >> TAG_SHIFT_OP) & TAG_MAX_OP;
00064 }
00065
00066 static inline u32 get_tag_slot (u32 tag)
00067 {
00068 return (tag >> TAG_SHIFT_SLOT) & TAG_MAX_SLOT;
00069 }
00070
00071 static inline u32 get_tag_tid (u32 tag)
00072 {
00073 return (tag >> TAG_SHIFT_TID) & TAG_MAX_TID;
00074 }
00075
00076 static inline u32 get_tag_type (u32 tag)
00077 {
00078 return (tag >> TAG_SHIFT_TYPE) & TAG_MAX_TYPE;
00079 }
00080
00081 static inline fast_cv_t* cv_get_tag_state (fast_codec_t* codec, u32 tag)
00082 {
00083 u32 slot = get_tag_tid (tag);
00084
00085 return & codec->cv [slot];
00086 }
00087
00088 static inline i32* cv_get_i32_values (fast_codec_t* codec, u32 tag)
00089 {
00090 return cv_get_tag_state (codec, tag)->i32_values;
00091 }
00092
00093 static inline u32* cv_get_u32_values (fast_codec_t* codec, u32 tag)
00094 {
00095 return cv_get_tag_state (codec, tag)->u32_values;
00096 }
00097
00098 static inline u8** cv_get_str_values (fast_codec_t* codec, u32 tag)
00099 {
00100 return cv_get_tag_state (codec, tag)->str_values;
00101 }
00102
00103 static inline u32* cv_get_valid_values (fast_codec_t* codec, u32 tag)
00104 {
00105 return cv_get_tag_state (codec, tag)->valid;
00106 }
00107
00109
00110 static inline i32 cv_get_i32 (fast_codec_t* codec, u32 tag)
00111 {
00112 return cv_get_i32_values (codec, tag) [get_tag_slot (tag)];
00113 }
00114
00115 static inline u32 cv_get_u32 (fast_codec_t* codec, u32 tag)
00116 {
00117 return cv_get_u32_values (codec, tag) [get_tag_slot (tag)];
00118 }
00119
00120 static inline u8* cv_get_str (fast_codec_t* codec, u32 tag)
00121 {
00122 u8** str_values = cv_get_str_values (codec, tag);
00123 u32 slot = get_tag_slot (tag);
00124
00125 if (str_values [slot] == NULL)
00126 {
00127 str_values [slot] = malloc (1024);
00128 assert (str_values [slot] != NULL);
00129 strcpy ((char*) str_values [slot], "");
00130 }
00131
00132 return str_values [slot];
00133 }
00134
00136
00137 static inline void cv_set_valid (fast_codec_t* codec, u32 tag)
00138 {
00139 cv_get_valid_values (codec, tag) [get_tag_slot (tag)] = 1;
00140 }
00141
00142 static inline int cv_is_valid (fast_codec_t* codec, u32 tag)
00143 {
00144 return cv_get_valid_values (codec, tag) [get_tag_slot (tag)] != 0;
00145 }
00146
00148
00149 static inline int cv_eq_i32 (fast_codec_t* codec, u32 tag, i32 data)
00150 {
00151 return cv_is_valid (codec, tag) && cv_get_i32 (codec, tag) == data;
00152 }
00153
00154 static inline int cv_eq_u32 (fast_codec_t* codec, u32 tag, u32 data)
00155 {
00156 return cv_is_valid (codec, tag) && cv_get_u32 (codec, tag) == data;
00157 }
00158
00159 static inline int cv_eq_str (fast_codec_t* codec, u32 tag, u8* data, int size)
00160 {
00161 u8* cp = cv_get_str (codec, tag);
00162
00163
00164
00165 if (cv_is_valid (codec, tag) == 0 || cp [size] != '\0')
00166 return 0;
00167
00168 return memcmp (cp, data, size) == 0;
00169 }
00170
00172
00174
00175 static inline void cv_set_i32 (fast_codec_t* codec, u32 tag, i32 data)
00176 {
00177 cv_get_i32_values (codec, tag) [get_tag_slot (tag)] = data;
00178 cv_set_valid (codec, tag);
00179 }
00180
00182
00183 static inline void cv_set_u32 (fast_codec_t* codec, u32 tag, u32 data)
00184 {
00185 cv_get_u32_values (codec, tag) [get_tag_slot (tag)] = data;
00186 cv_set_valid (codec, tag);
00187 }
00188
00190
00191 static inline void cv_set_str (fast_codec_t* codec, u32 tag,
00192 u8* data, int size)
00193 {
00194 u8* cp = cv_get_str (codec, tag);
00195
00196 memcpy (cp, data, size);
00197 cp [size] = '\0';
00198
00199 cv_set_valid (codec, tag);
00200 }
00202
00203 static int u32_to_size (u32 data)
00204 {
00205 if (data < 0x00000080) return 1;
00206 if (data < 0x00004000) return 2;
00207 if (data < 0x00200000) return 3;
00208 if (data < 0x10000000) return 4;
00209
00210 return 5;
00211 }
00212
00213 static int i32_to_size (i32 data)
00214 {
00215 if (data < 0)
00216 {
00217 if (data >= 0xffffffc0) return 1;
00218 if (data >= 0xffffe000) return 2;
00219 if (data >= 0xfff00000) return 3;
00220 if (data >= 0xf8000000) return 4;
00221 }
00222 else
00223 {
00224 if (data < 0x00000040) return 1;
00225 if (data < 0x00002000) return 2;
00226 if (data < 0x00100000) return 3;
00227 if (data < 0x08000000) return 4;
00228 }
00229 return 5;
00230 }
00231
00233
00234 static const char* format_error_code (fast_error_t code)
00235 {
00236 switch (code)
00237 {
00238 case FAST_ERR_NONE: return "none";
00239 case FAST_ERR_CODEC: return "bad codec";
00240 case FAST_ERR_SIZE: return "size error";
00241 case FAST_ERR_VALUE: return "missing value";
00242 case FAST_ERR_TAG_OP: return "tag op unsupported";
00243 case FAST_ERR_TAG_TYPE: return "bad tag type";
00244 case FAST_ERR_CALL_SEQ: return "bad call sequence";
00245 case FAST_ERR_IO: return "I/O library error";
00246 default: return "??";
00247 }
00248 }
00249
00250 static const char* format_tag_op (fast_op_t op)
00251 {
00252 static char buffer [32];
00253
00254 switch (op)
00255 {
00256 case FAST_OP_NONE: return "NONE";
00257 case FAST_OP_COPY: return "COPY";
00258 case FAST_OP_INCR: return "INCR";
00259 case FAST_OP_DELTA: return "DELTA";
00260
00261 default:
00262 snprintf (buffer, sizeof (buffer), "%u", op);
00263 return buffer;
00264 }
00265 }
00266
00267 static const char* format_tag_type (fast_type_t type)
00268 {
00269 static char buffer [32];
00270
00271 switch (type)
00272 {
00273 case FAST_TYPE_NULL: return "NULL";
00274 case FAST_TYPE_U32: return "U32";
00275 case FAST_TYPE_I32: return "I32";
00276 case FAST_TYPE_STR: return "STR";
00277
00278 default:
00279 snprintf (buffer, sizeof (buffer), "%u", type);
00280 return buffer;
00281 }
00282 }
00283
00285
00286 static int set_err (const char* fn, fast_codec_t* codec,
00287 fast_tag_t tag, fast_error_t code,
00288 const char* format, ...)
00289 {
00290 char buffer [1024];
00291 va_list ap;
00292
00293 codec->error->fn = fn;
00294 codec->error->tag = tag;
00295 codec->error->code = code;
00296
00297 va_start (ap, format);
00298 vsnprintf (buffer, sizeof (buffer), format, ap);
00299 va_end (ap);
00300
00301 if (codec->error->text != NULL)
00302 free (codec->error->text);
00303
00304 codec->error->text = malloc (strlen (buffer) + 1);
00305 strcpy (codec->error->text, buffer);
00306
00307 if (codec->verbose >= 1)
00308 fprintf (stderr, "error: %s\n", fast_error_string (codec));
00309
00310 return -1;
00311 }
00312
00313 static int check_codec (const char* fn, fast_codec_t* codec)
00314 {
00315 if (codec == NULL)
00316 {
00317 fprintf (stderr, "error: [%s] NULL codec\n", fn);
00318 return -1;
00319 }
00320 if (codec->magic != FAST_CODEC_MAGIC)
00321 return set_err (fn, codec, -1, FAST_ERR_CODEC,
00322 "bad codec magic number");
00323
00324 return 0;
00325 }
00326
00327 static int check_type (const char* fn, fast_codec_t* codec,
00328 fast_tag_t tag, u32 type)
00329 {
00330 if (get_tag_type (tag) != type)
00331 return set_err (fn, codec, tag, FAST_ERR_TAG_TYPE,
00332 "type=%s (%s expected)",
00333 format_tag_type (get_tag_type (tag)),
00334 format_tag_type (type));
00335
00336 return 0;
00337 }
00338
00339 static int bad_op_error (const char* fn, fast_codec_t* codec, fast_tag_t tag)
00340 {
00341 return set_err (fn, codec, tag, FAST_ERR_TAG_OP, "");
00342 }
00343
00344 static int value_error (const char* fn, fast_codec_t* codec, fast_tag_t tag)
00345 {
00346 return set_err (fn, codec, tag, FAST_ERR_VALUE, "");
00347 }
00348
00350
00351 const char* fast_error_string (fast_codec_t* codec)
00352 {
00353 fast_tag_t tag = codec->error->tag;
00354
00355 static char buffer [1024];
00356
00357 snprintf (buffer, sizeof (buffer), "[%s] %s|%s|%u|%u %s: %s",
00358 codec->error->fn,
00359 format_tag_type (get_tag_type (tag)),
00360 format_tag_op (get_tag_op (tag)),
00361 get_tag_tid (tag),
00362 get_tag_slot (tag),
00363 format_error_code (codec->error->code),
00364 codec->error->text ? codec->error->text : "");
00365
00366 return buffer;
00367 }
00368
00369 int fast_print_error (fast_codec_t* codec, FILE* fp)
00370 {
00371 const char* msg = fast_error_string (codec);
00372
00373 fprintf (fp, "%s\n", msg);
00374 return 0;
00375 }
00376
00378
00380
00381 static int get_pmap (fast_codec_t* codec, fast_tag_t tag)
00382 {
00383 u32 pos = get_tag_slot (tag);
00384
00385
00386
00387 if (pos >= codec->pmap->size)
00388 return 0;
00389
00390 return codec->pmap->bits [pos];
00391 }
00392
00394
00395 static void reset_pmap (fast_codec_t* codec)
00396 {
00397
00398 memset (codec->pmap->bits, 0, MAX_PMAP_BITS);
00399 codec->pmap->max_pos = 0;
00400 }
00401
00403
00404 static int set_pmap (fast_codec_t* codec, fast_tag_t tag)
00405 {
00406 u32 pos = get_tag_slot (tag);
00407
00408 if (pos > codec->pmap->max_pos)
00409 {
00410
00411
00412 if (pos >= MAX_PMAP_BITS)
00413 return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
00414 "pmap slot=%d (< %d expected)",
00415 pos, MAX_PMAP_BITS);
00416
00417 codec->pmap->max_pos = pos;
00418 }
00419 codec->pmap->bits [pos] = 1;
00420 return 0;
00421 }
00422
00423 static u32 bit_mask [8] = { 64, 32, 16, 8, 4, 2, 1, 0 };
00424
00425
00426
00427
00429
00430 static int emit_pmap (fast_codec_t* codec, u8* data)
00431 {
00432 int bytes = align7 (codec->pmap->max_pos + 1);
00433 int offset;
00434 int p1;
00435
00436
00437
00438
00439 for (p1 = 0, offset = 0 ; p1 < bytes ; p1 ++, offset += 7)
00440 {
00441 u8* bits = & codec->pmap->bits [offset];
00442 u32 temp = 0;
00443 int p2;
00444
00445 for (p2 = 0 ; p2 < 7 ; p2 ++)
00446 {
00447 if (bits [p2] > 0)
00448 temp |= bit_mask [p2];
00449 }
00450
00451 data [p1] = temp;
00452 }
00453
00454 data [bytes - 1] |= 0x80;
00455 return bytes;
00456 }
00457
00459
00461
00462 static inline void emit_byte (fast_codec_t* codec, u8 data)
00463 {
00464 *codec->msg->tail ++ = data;
00465 }
00466
00468
00471
00472 static inline int check_msg_avail (const char* fn, fast_codec_t* codec,
00473 fast_tag_t tag, int size)
00474 {
00475 if (get_buffer_left (codec->msg) < size)
00476 return set_err (fn, codec, tag, FAST_ERR_SIZE,
00477 "message buffer overflow avail=%d needed=%d",
00478 get_buffer_left (codec->msg), size);
00479 return 0;
00480 }
00481
00483
00485
00486 static int emit_i32 (fast_codec_t* codec, fast_tag_t tag, i32 data)
00487 {
00488 int size = i32_to_size (data);
00489
00490
00491 if (check_msg_avail (FUNCTION, codec, tag, size) < 0)
00492 return -1;
00493
00494 switch (size)
00495 {
00496
00497
00498 case 5: emit_byte (codec, (data >> 28) & 0x7f);
00499 case 4: emit_byte (codec, (data >> 21) & 0x7f);
00500 case 3: emit_byte (codec, (data >> 14) & 0x7f);
00501 case 2: emit_byte (codec, (data >> 7) & 0x7f);
00502 case 1: emit_byte (codec, (data & 0x7f) | 0x80);
00503 {
00504 int code = set_pmap (codec, tag);
00505
00506 if (code < 0)
00507 return code;
00508 }
00509 return size;
00510
00511 default:
00512 return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
00513 "size=%d data=%d (%08x)", size, data, data);
00514 }
00515 }
00516
00518
00519 static int emit_u32 (fast_codec_t* codec, fast_tag_t tag, u32 data)
00520 {
00521 int size = u32_to_size (data);
00522
00523
00524 if (check_msg_avail (FUNCTION, codec, tag, size) < 0)
00525 return -1;
00526
00527 switch (size)
00528 {
00529
00530 case 5: emit_byte (codec, data >> 28);
00531 case 4: emit_byte (codec, (data >> 21) & 0x7f);
00532 case 3: emit_byte (codec, (data >> 14) & 0x7f);
00533 case 2: emit_byte (codec, (data >> 7) & 0x7f);
00534 case 1: emit_byte (codec, (data & 0x7f) | 0x80);
00535 {
00536 int code = set_pmap (codec, tag);
00537
00538 if (code < 0)
00539 return code;
00540 }
00541 return size;
00542
00543 default:
00544 return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
00545 "size=%d data=%d (%08x)", size, data, data);
00546 }
00547 }
00548
00550
00551 static int emit_str (fast_codec_t* codec, fast_tag_t tag, u8* data, int size)
00552 {
00553
00554 if (size <= 0)
00555 return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
00556 "size=%d (>0 expected)", size);
00557
00558
00559 if (check_msg_avail (FUNCTION, codec, tag, size) < 0)
00560 return -1;
00561
00562 {
00563 int p1;
00564
00565 for (p1 = 0 ; p1 < size - 1 ; p1 ++)
00566 emit_byte (codec, data [p1]);
00567
00568 emit_byte (codec, data [p1] | 0x80);
00569 }
00570
00571 {
00572 int code = set_pmap (codec, tag);
00573
00574 if (code < 0)
00575 return code;
00576 }
00577 return size;
00578 }
00579
00581
00583
00584 static int parse_bytes (fast_codec_t* codec, u8* data, int size)
00585 {
00586 int p1;
00587
00588
00589 memset (data, 0, size);
00590
00591 for (p1 = 0 ; p1 < size ; p1 ++)
00592 {
00593 u8 temp;
00594
00595 fast_buffer_t* input = codec->input;
00596
00597 if (buffer_empty_p (input))
00598 {
00599 int bytes;
00600
00601 if (codec->skip_io == 1)
00602 return -1;
00603
00604 bytes = read (input->fd, input->data, get_buffer_size (input));
00605
00606 if (bytes <= 0)
00607 {
00608 if (bytes < 0)
00609 fprintf (stderr, "read failed: %s\n", strerror (errno));
00610
00611 return -1;
00612 }
00613
00614 input->head = input->data;
00615 input->tail = input->head + bytes;
00616
00617 }
00618 temp = *input->head ++;
00619
00620 data [p1] = temp;
00621
00622 if (temp >= 0x80)
00623 {
00624 data [p1] &= 0x7f;
00625 return p1 + 1;
00626 }
00627 }
00628
00629
00630
00631 return set_err (FUNCTION, codec, -1, FAST_ERR_SIZE,
00632 "parse buffer overflow size=%d", size);
00633 }
00634
00635 static int parse_pmap (fast_codec_t* codec)
00636 {
00637 fast_pmap_t* pmap = codec->pmap;
00638
00639 u8 data [MAX_PMAP_BYTES];
00640
00641 int bytes = parse_bytes (codec, data, MAX_PMAP_BYTES);
00642 int offset;
00643 int p1;
00644
00645 if (bytes < 0)
00646 return bytes;
00647
00648 for (p1 = 0, offset = 0 ; p1 < bytes ; p1 ++, offset += 7)
00649 {
00650 u32 temp = data [p1];
00651 int p2;
00652
00653 for (p2 = 0 ; p2 < 7 ; p2 ++)
00654 {
00655 pmap->bits [offset + p2] = (temp & bit_mask [p2]) != 0;
00656 }
00657 }
00658
00659 codec->pmap->size = 7 * bytes;
00660 return bytes;
00661 }
00662
00663 #define SIGN_MASK_I32 0x40
00664 #define SIGN_MASK_U32 0x00
00665
00666 static int parse_32 (fast_codec_t* codec, fast_tag_t tag,
00667 u32* data, int sign_mask)
00668 {
00669 u8 buffer [5];
00670 int bytes;
00671 int p1;
00672 i32 temp;
00673
00674 if (get_pmap (codec, tag) == 0)
00675 return 0;
00676
00677 bytes = parse_bytes (codec, buffer, sizeof (buffer));
00678
00679 if (bytes < 0)
00680 return bytes;
00681
00682 temp = 0 - ((buffer [0] & sign_mask) != 0);
00683
00684 for (p1 = 0 ; p1 < bytes ; p1 ++)
00685 temp = (temp << 7) | buffer [p1];
00686
00687 *data = temp;
00688 return bytes;
00689 }
00690
00692
00694
00695 static int parse_u32 (fast_codec_t* codec, fast_tag_t tag, u32* data)
00696 {
00697 return parse_32 (codec, tag, data, SIGN_MASK_U32);
00698 }
00699
00701
00702 static int parse_i32 (fast_codec_t* codec, fast_tag_t tag, i32* data)
00703 {
00704 return parse_32 (codec, tag, (u32*) data, SIGN_MASK_I32);
00705 }
00706
00708
00709 static int parse_str (fast_codec_t* codec, fast_tag_t tag, u8* data, int size)
00710 {
00711 return get_pmap (codec, tag) == 0 ? 0 : parse_bytes (codec, data, size);
00712 }
00713
00715
00716
00719
00720 int fast_decode_new_msg (fast_codec_t* codec, fast_tag_t tag)
00721 {
00722 if (check_codec (FUNCTION, codec) < 0)
00723 return -1;
00724
00725 return parse_pmap (codec);
00726 }
00727
00729
00730 int fast_decode_end_msg (fast_codec_t* codec, fast_tag_t tag)
00731 {
00732 if (check_codec (FUNCTION, codec) < 0)
00733 return -1;
00734
00735 return 0;
00736 }
00737
00739
00741
00742 int fast_decode_str (fast_codec_t* codec, fast_tag_t tag,
00743 u8* data, int size)
00744 {
00745 fast_op_t op = get_tag_op (tag);
00746
00747 int bytes;
00748
00749 if (check_codec (FUNCTION, codec) < 0)
00750 return -1;
00751
00752 if (check_type (FUNCTION, codec, tag, FAST_TYPE_STR) < 0)
00753 return -1;
00754
00755 #if 0
00756
00757 if (size <= 0 || size >= 1024)
00758 return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
00759 "size=%d (1-1023 expected)", size);
00760 #endif
00761
00762 switch (op)
00763 {
00764 case FAST_OP_NONE:
00765 bytes = parse_str (codec, tag, data, size);
00766
00767 if (bytes < 0)
00768 return -1;
00769
00770 if (bytes == 0)
00771 return value_error (FUNCTION, codec, tag);
00772
00773 break;
00774
00775 case FAST_OP_COPY:
00776 bytes = parse_str (codec, tag, data, size);
00777
00778 if (bytes < 0)
00779 return -1;
00780
00781 if (bytes > 0)
00782 {
00783
00784 cv_set_str (codec, tag, data, size);
00785 }
00786 else
00787 {
00788
00789 memcpy (data, cv_get_str (codec, tag), size);
00790 }
00791 return size;
00792
00793 case FAST_OP_INCR:
00794 return bad_op_error (FUNCTION, codec, tag);
00795
00796 case FAST_OP_DELTA:
00797 {
00798 u8 buffer [1024];
00799 u8* curr = cv_get_str (codec, tag);
00800
00801 u32 bytes = parse_str (codec, tag, buffer, size);
00802
00803 if (cv_is_valid (codec, tag))
00804 {
00805 int temp;
00806
00807 if (bytes > (u32)size)
00808 return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
00809 "oversized value %d > size=%d", bytes, size);
00810
00811
00812
00813
00814 temp = strlen ((char*) curr);
00815
00816 if (temp != size)
00817 return set_err (FUNCTION, codec, tag, FAST_ERR_SIZE,
00818 "size mismatch %d != %d", temp, size);
00819
00820
00821 memcpy (curr + size - bytes, buffer, bytes);
00822 }
00823 else
00824 {
00825
00826 cv_set_str (codec, tag, buffer, bytes);
00827 }
00828
00829 memcpy (data, cv_get_str (codec, tag), size);
00830 }
00831 break;
00832
00833 default:
00834 bad_op_error (FUNCTION, codec, tag);
00835 }
00836 return 0;
00837 }
00838
00840
00842
00843 int fast_decode_i32 (fast_codec_t* codec, fast_tag_t tag, i32* value)
00844 {
00845 fast_op_t op = get_tag_op (tag);
00846
00847 i32 temp = 0;
00848 int bytes;
00849
00850 if (check_codec (FUNCTION, codec) < 0)
00851 return -1;
00852
00853 if (check_type (FUNCTION, codec, tag, FAST_TYPE_I32) < 0)
00854 return -1;
00855
00856 switch (op)
00857 {
00858 case FAST_OP_NONE:
00859 bytes = parse_i32 (codec, tag, & temp);
00860
00861 if (bytes > 0)
00862 {
00863 cv_set_i32 (codec, tag, temp);
00864 break;
00865 }
00866
00867 if (bytes < 0)
00868 return -1;
00869
00870 return value_error (FUNCTION, codec, tag);
00871
00872 case FAST_OP_COPY:
00873 bytes = parse_i32 (codec, tag, & temp);
00874
00875 if (bytes == 0)
00876 break;
00877
00878 if (bytes < 0)
00879 return -1;
00880
00881 cv_set_i32 (codec, tag, temp);
00882 break;
00883
00884 case FAST_OP_INCR:
00885 bytes = parse_i32 (codec, tag, & temp);
00886
00887 if (bytes < 0)
00888 return -1;
00889
00890 if (bytes == 0)
00891 {
00892
00893 if (cv_is_valid (codec, tag) == 0)
00894 return value_error (FUNCTION, codec, tag);
00895
00896 temp = cv_get_i32 (codec, tag) + 1;
00897 }
00898
00899 cv_set_i32 (codec, tag, (u32) temp);
00900 break;
00901
00902 case FAST_OP_DELTA:
00903 if (cv_is_valid (codec, tag))
00904 {
00905
00906
00907
00908 i32 delta;
00909
00910 bytes = parse_i32 (codec, tag, & delta);
00911
00912 if (bytes < 0)
00913 return -1;
00914
00915 if (bytes > 0)
00916 {
00917 temp = cv_get_i32 (codec, tag) + delta;
00918 cv_set_i32 (codec, tag, temp);
00919 }
00920 }
00921 else
00922 {
00923
00924
00925
00926 bytes = parse_i32 (codec, tag, & temp);
00927
00928 if (bytes < 0)
00929 return -1;
00930
00931 if (bytes == 0)
00932 return value_error (FUNCTION, codec, tag);
00933
00934 cv_set_i32 (codec, tag, temp);
00935 }
00936 break;
00937
00938 default:
00939 return bad_op_error (FUNCTION, codec, tag);
00940 }
00941
00942 *value = cv_get_i32 (codec, tag);
00943 return 0;
00944 }
00945
00947
00949
00950 int fast_decode_u32 (fast_codec_t* codec, fast_tag_t tag, u32* value)
00951 {
00952 fast_op_t op = get_tag_op (tag);
00953
00954 u32 next = 0;
00955 int bytes;
00956
00957 if (check_codec (FUNCTION, codec) < 0)
00958 return -1;
00959
00960 if (check_type (FUNCTION, codec, tag, FAST_TYPE_U32) < 0)
00961 return -1;
00962
00963 switch (op)
00964 {
00965 case FAST_OP_NONE:
00966 bytes = parse_u32 (codec, tag, & next);
00967
00968 if (bytes < 0)
00969 return -1;
00970
00971 if (bytes == 0)
00972 return value_error (FUNCTION, codec, tag);
00973
00974 break;
00975
00976 case FAST_OP_COPY:
00977 bytes = parse_u32 (codec, tag, & next);
00978
00979 if (bytes < 0)
00980 return -1;
00981
00982 if (bytes == 0)
00983 {
00984 if (cv_is_valid (codec, tag) == 0)
00985 return value_error (FUNCTION, codec, tag);
00986
00987 next = cv_get_u32 (codec, tag);
00988 break;
00989 }
00990 break;
00991
00992 case FAST_OP_INCR:
00993 bytes = parse_u32 (codec, tag, & next);
00994
00995 if (bytes < 0)
00996 return -1;
00997
00998 if (bytes == 0)
00999 {
01000 if (cv_is_valid (codec, tag) == 0)
01001 return value_error (FUNCTION, codec, tag);
01002
01003 next = cv_get_u32 (codec, tag) + 1;
01004 }
01005 break;
01006
01007 case FAST_OP_DELTA:
01008 if (cv_is_valid (codec, tag))
01009 {
01010
01011
01012
01013 i32 delta;
01014
01015 bytes = parse_i32 (codec, tag, & delta);
01016
01017 if (bytes < 0)
01018 return -1;
01019
01020 next = cv_get_u32 (codec, tag);
01021
01022 if (bytes > 0)
01023 next += delta;
01024 }
01025 else
01026 {
01027
01028
01029
01030 bytes = parse_u32 (codec, tag, & next);
01031
01032 if (bytes < 0)
01033 return -1;
01034
01035 if (bytes == 0)
01036 return value_error (FUNCTION, codec, tag);
01037 }
01038 break;
01039
01040 default:
01041 return bad_op_error (FUNCTION, codec, tag);
01042 }
01043
01044 cv_set_u32 (codec, tag, next);
01045
01046 *value = cv_get_u32 (codec, tag);
01047 return 0;
01048 }
01049
01051
01052
01053
01054
01055
01056
01057
01058
01061
01063
01064 static int flush_group (fast_codec_t* codec)
01065 {
01066 fast_buffer_t* output = codec->output;
01067 fast_buffer_t* msg = codec->msg;
01068
01069 int map_size;
01070
01072
01073 int size = get_buffer_used (msg);
01074 int need = MAX_PMAP_BYTES + size;
01075
01076 if (get_buffer_left (output) <= need)
01077 return set_err (FUNCTION, codec, -1, FAST_ERR_SIZE,
01078 "output buffer overflow left=%d need=%d",
01079 get_buffer_left (output), need);
01080
01082 map_size = emit_pmap (codec, output->tail);
01083
01084 output->tail += map_size;
01085
01087 memcpy (output->tail, msg->head, size);
01088
01089 output->tail += size;
01090
01092 reset_pmap (codec);
01093
01094 reset_buffer (codec->msg);
01095 return 0;
01096 }
01097
01100
01101 static int flush_msg (fast_codec_t* codec)
01102 {
01103 fast_buffer_t* output = codec->output;
01104
01105 flush_group (codec);
01106
01107 if (codec->skip_io == 0)
01108 {
01109 if (write_n (output->fd, output->head, get_buffer_used (output)) < 0)
01110 return set_err (FUNCTION, codec, -1, FAST_ERR_IO,
01111 "write_n failed: %s", strerror (errno));
01112
01113 reset_buffer (output);
01114 }
01115
01116 return 0;
01117 }
01118
01120
01121
01122
01123
01124
01126
01127 int fast_encode_new_msg (fast_codec_t* codec, fast_tag_t tag)
01128 {
01129 check_codec (FUNCTION, codec);
01130
01131 if (codec->in_message != 0)
01132 return set_err (FUNCTION, codec, tag, FAST_ERR_CALL_SEQ,
01133 "already in a message");
01134
01135 codec->in_message = 1;
01136 codec->curr_tag = tag;
01137 return 0;
01138 }
01139
01141
01142 int fast_encode_end_msg (fast_codec_t* codec, fast_tag_t tag)
01143 {
01144 check_codec (FUNCTION, codec);
01145
01146 if (codec->in_message == 0)
01147 return set_err (FUNCTION, codec, tag, FAST_ERR_CALL_SEQ,
01148 "not in a message");
01149
01150 codec->in_message = 0;
01151 return flush_msg (codec);
01152 }
01153
01155
01157
01158 int fast_encode_i32 (fast_codec_t* codec, fast_tag_t tag, i32 value)
01159 {
01160 fast_op_t op = get_tag_op (tag);
01161
01162 if (check_codec (FUNCTION, codec) < 0)
01163 return -1;
01164
01165 if (check_type (FUNCTION, codec, tag, FAST_TYPE_I32) < 0)
01166 return -1;
01167
01168 switch (op)
01169 {
01170 case FAST_OP_NONE:
01171 break;
01172
01173 case FAST_OP_COPY:
01174 if (cv_eq_i32 (codec, tag, value))
01175 return 0;
01176 break;
01177
01178 case FAST_OP_INCR:
01179 return bad_op_error (FUNCTION, codec, tag);
01180
01181 case FAST_OP_DELTA:
01182 return bad_op_error (FUNCTION, codec, tag);
01183
01184 default:
01185 return bad_op_error (FUNCTION, codec, tag);
01186 }
01187
01188 cv_set_i32 (codec, tag, value);
01189 return emit_i32 (codec, tag, value);
01190 }
01191
01192 static int find_char_delta_offset (u8* a, u8* b, int size)
01193 {
01194 int p1;
01195
01196 for (p1 = 0 ; p1 < size ; p1 ++)
01197 if (a [p1] != b [p1])
01198 break;
01199
01200 return p1;
01201 }
01202
01204
01205 int fast_encode_str (fast_codec_t* codec, fast_tag_t tag,
01206 u8* data, int size)
01207 {
01208 fast_op_t op = get_tag_op (tag);
01209
01210 if (check_codec (FUNCTION, codec) < 0)
01211 return -1;
01212
01213 if (check_type (FUNCTION, codec, tag, FAST_TYPE_STR) < 0)
01214 return -1;
01215
01216
01217
01218
01219 switch (op)
01220 {
01221 case FAST_OP_NONE:
01222 break;
01223
01224 case FAST_OP_COPY:
01225 if (cv_eq_str (codec, tag, data, size))
01226 return 0;
01227
01228 break;
01229
01230 case FAST_OP_INCR:
01231 return bad_op_error (FUNCTION, codec, tag);
01232
01233 case FAST_OP_DELTA:
01234 {
01235 u8* curr = cv_get_str (codec, tag);
01236 u32 offset = find_char_delta_offset (curr, data, size);
01237
01238 if (offset == size)
01239 return 0;
01240
01241 memcpy (curr + offset, data + offset, size - offset);
01242
01243 data += offset;
01244 size -= offset;
01245
01246 return emit_str (codec, tag, data, size);
01247 }
01248
01249 default:
01250 return bad_op_error (FUNCTION, codec, tag);
01251 }
01252
01253 cv_set_str (codec, tag, data, size);
01254 return emit_str (codec, tag, data, size);
01255 }
01256
01258
01259 int fast_encode_u32 (fast_codec_t* codec, fast_tag_t tag, u32 value)
01260 {
01261 fast_op_t op = get_tag_op (tag);
01262 u32 next = value;
01263
01264 if (check_codec (FUNCTION, codec) < 0)
01265 return -1;
01266
01267 if (check_type (FUNCTION, codec, tag, FAST_TYPE_U32) < 0)
01268 return -1;
01269
01270 switch (op)
01271 {
01272 case FAST_OP_NONE:
01273 break;
01274
01275 case FAST_OP_COPY:
01276 if (cv_eq_u32 (codec, tag, value))
01277 return 0;
01278
01279 break;
01280
01281 case FAST_OP_INCR:
01282 next = value + 1;
01283
01284 if (cv_eq_u32 (codec, tag, value))
01285 {
01286 cv_set_u32 (codec, tag, next);
01287 return 0;
01288 }
01289 break;
01290
01291 case FAST_OP_DELTA:
01292 if (cv_is_valid (codec, tag))
01293 {
01294 i32 delta = (i32) value - cv_get_u32 (codec, tag);
01295
01296
01297 if (delta == 0)
01298 return 0;
01299
01300 cv_set_u32 (codec, tag, value);
01301 return emit_i32 (codec, tag, delta);
01302 }
01303 break;
01304
01305 default:
01306 return bad_op_error (FUNCTION, codec, tag);
01307 }
01308
01309 cv_set_u32 (codec, tag, next);
01310 return emit_u32 (codec, tag, value);
01311 }
01312
01314
01316
01317 fast_codec_t* fast_create_codec (void)
01318 {
01319 fast_codec_t* codec = malloc (sizeof (*codec));
01320
01321 if (codec == NULL)
01322 {
01323 fprintf (stderr, "error: [%s] malloc failed\n", FUNCTION);
01324 return NULL;
01325 }
01326
01327 memset (codec, 0, sizeof (*codec));
01328
01329 codec->magic = FAST_CODEC_MAGIC;
01330
01331 init_buffer (codec->msg, -1);
01332 init_buffer (codec->input, 0);
01333 init_buffer (codec->output, 1);
01334
01335 return codec;
01336 }
01337
01338 int fast_destroy_codec (fast_codec_t* codec)
01339 {
01340 if (codec == NULL)
01341 {
01342 fprintf (stderr, "error: [%s] null codec\n", FUNCTION);
01343 return -1;
01344 }
01345
01346 if (codec->magic != FAST_CODEC_MAGIC)
01347 {
01348 fprintf (stderr, "error: [%s] bad codec magic number\n", FUNCTION);
01349 return -1;
01350 }
01351
01352 codec->magic = 0;
01353 free (codec);
01354 return 0;
01355 }
01356
01357 u32 fast_ascii_to_u32 (u8* data, int size)
01358 {
01359 u32 temp = 0;
01360 int p1;
01361
01362 for (p1 = 0 ; p1 < size ; p1 ++)
01363 {
01364 int chr = data [p1];
01365 temp = temp * 10 + chr - '0';
01366 }
01367 return temp;
01368 }