tb_bool_t vm86_parser_get_number_value(tb_char_t const** pp, tb_char_t const* e, tb_uint32_t* value) { // check tb_assert(pp && e && value); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // check tb_check_break(p < e && (tb_isdigit16(*p) || *p == '-')); // is sign? tb_bool_t is_sign = tb_false; if (*p == '-') { is_sign = tb_true; p++; } // save the base tb_char_t const* b = p; // skip the value while (p < e && tb_isdigit16(*p)) p++; // is hex? tb_bool_t is_hex = tb_false; if (p < e && *p == 'h') { is_hex = tb_true; p++; } // check end, exclude variable name tb_check_break(!tb_isalpha(*p) && *p != '_'); // save value *value = is_hex? tb_s16tou32(b) : tb_s10tou32(b); if (is_sign) *value = (tb_uint32_t)(((tb_sint32_t)*value) * -1); // skip the space while (p < e && tb_isspace(*p)) p++; // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
/* chunked_data * * head data tail * ea5\r\n ..........\r\n e65\r\n..............\r\n 0\r\n\r\n * ---------------------- ------------------------- --------- * chunk0 chunk1 end */ static tb_long_t tb_filter_chunked_spak(tb_filter_t* filter, tb_static_stream_ref_t istream, tb_static_stream_ref_t ostream, tb_long_t sync) { // check tb_filter_chunked_t* cfilter = tb_filter_chunked_cast(filter); tb_assert_and_check_return_val(cfilter && istream && ostream, -1); tb_assert_and_check_return_val(tb_static_stream_valid(istream) && tb_static_stream_valid(ostream), -1); // the idata tb_byte_t const* ip = tb_static_stream_pos(istream); tb_byte_t const* ie = tb_static_stream_end(istream); // trace tb_trace_d("[%p]: isize: %lu, beof: %d", cfilter, tb_static_stream_size(istream), filter->beof); // find the eof: '\r\n 0\r\n\r\n' if ( !filter->beof && ip + 6 < ie && ie[-7] == '\r' && ie[-6] == '\n' && ie[-5] == '0' && ie[-4] == '\r' && ie[-3] == '\n' && ie[-2] == '\r' && ie[-1] == '\n') { // is eof filter->beof = tb_true; } // the odata tb_byte_t* op = (tb_byte_t*)tb_static_stream_pos(ostream); tb_byte_t* oe = (tb_byte_t*)tb_static_stream_end(ostream); tb_byte_t* ob = op; // parse chunked head and chunked tail if (!cfilter->size || cfilter->read >= cfilter->size) { // walk while (ip < ie) { // the charactor tb_char_t ch = *ip++; // trace tb_trace_d("[%p]: character: %x", cfilter, ch); // check tb_assert_and_check_return_val(ch, -1); // append char to line if (ch != '\n') tb_string_chrcat(&cfilter->line, ch); // is line end? else { // check tb_char_t const* pb = tb_string_cstr(&cfilter->line); tb_size_t pn = tb_string_size(&cfilter->line); tb_assert_and_check_return_val(pb, -1); // trace tb_trace_d("[%p]: line: %s", cfilter, tb_string_cstr(&cfilter->line)); // strip '\r' if exists if (pb[pn - 1] == '\r') tb_string_strip(&cfilter->line, pn - 1); // is chunked tail? only "\r\n" if (!tb_string_size(&cfilter->line)) { // reset size cfilter->read = 0; cfilter->size = 0; // trace tb_trace_d("[%p]: tail", cfilter); // continue continue ; } // is chunked head? parse size else { // parse size cfilter->size = tb_s16tou32(pb); // trace tb_trace_d("[%p]: size: %lu", cfilter, cfilter->size); // clear data tb_string_clear(&cfilter->line); // is eof? "0\r\n\r\n" if (!cfilter->size) { // trace tb_trace_d("[%p]: eof", cfilter); // is eof filter->beof = tb_true; // continue to spak the end data continue ; } // ok break; } } } } // check tb_assert_and_check_return_val(cfilter->read <= cfilter->size, -1); // read chunked data tb_size_t size = tb_min3(ie - ip, oe - op, cfilter->size - cfilter->read); if (size) { // copy data tb_memcpy((tb_byte_t*)op, ip, size); ip += size; op += size; // update read cfilter->read += size; } // update stream tb_static_stream_goto(istream, (tb_byte_t*)ip); tb_static_stream_goto(ostream, (tb_byte_t*)op); // trace tb_trace_d("[%p]: read: %lu, size: %lu, beof: %u, ileft: %lu", cfilter, cfilter->read, cfilter->size, filter->beof, tb_static_stream_left(istream)); // ok return (op - ob); }