size_t hstcpcli::request_buf_append(const char *start, const char *finish) { /* if (num_req_sent > 0 || num_req_rcvd > 0) { */ if (num_req_rcvd > 0) { close(); set_error(-1, "request_buf_append: protocol out of sync"); return 0; } const char *nl = start; size_t num_req = 0; while ((nl = memchr_char(nl, '\n', finish - nl))) { if (nl == finish) break; num_req++; nl++; } num_req++; writebuf.append(start, finish); if (*(finish - 1) != '\n') writebuf.append_literal("\n"); num_req_bufd += num_req; return num_req; }
inline size_t find_char(const string_ref& s, char c) { const char *b = s.begin(); const char *e = s.end(); const char *const p = memchr_char(b, c, e - b); return p ? (p - b) : (e - b); }
int hstcpcli::response_recv(size_t& num_flds_r) { if (error_code < 0) { return error_code; } clear_error(); if (num_req_bufd > 0 || num_req_sent == 0 || num_req_rcvd > 0 || response_end_offset != 0) { close(); return set_error(-1, "response_recv: protocol out of sync"); } cur_row_offset = 0; num_flds_r = num_flds = 0; if (fd.get() < 0) { return set_error(-1, "read: closed"); } size_t offset = 0; while (true) { const char *const lbegin = readbuf.begin() + offset; const char *const lend = readbuf.end(); const char *const nl = memchr_char(lbegin, '\n', lend - lbegin); if (nl != 0) { offset = (nl + 1) - readbuf.begin(); break; } if (read_more() <= 0) { close(); return set_error(-1, "read: eof"); } } response_end_offset = offset; --num_req_sent; ++num_req_rcvd; char *start = readbuf.begin(); char *const finish = start + response_end_offset - 1; const size_t resp_code = read_ui32(start, finish); skip_one(start, finish); num_flds_r = num_flds = read_ui32(start, finish); if (resp_code != 0) { skip_one(start, finish); char *const err_begin = start; read_token(start, finish); char *const err_end = start; std::string e = std::string(err_begin, err_end - err_begin); if (e.empty()) { e = "unknown_error"; } return set_error(resp_code, e); } cur_row_offset = start - readbuf.begin(); DBG(fprintf(stderr, "[%s] ro=%zu eol=%zu\n", std::string(readbuf.begin(), readbuf.begin() + response_end_offset) .c_str(), cur_row_offset, response_end_offset)); DBG(fprintf(stderr, "RES 0\n")); return 0; }
inline void read_token(char *& start, char *finish) { char *const p = memchr_char(start, '\t', finish - start); if (p == 0) { start = finish; } else { start = p; } }
string_wref get_token(char *& wp, char *wp_end, char delim) { char *const wp_begin = wp; char *const p = memchr_char(wp_begin, delim, wp_end - wp_begin); if (p == 0) { wp = wp_end; return string_wref(wp_begin, wp_end - wp_begin); } wp = p + 1; return string_wref(wp_begin, p - wp_begin); }
template <typename T, typename V> size_t split_tmpl_vec(char delim, const T& buf, V& parts) { typedef typename T::value_type value_type; size_t i = 0; value_type *start = buf.begin(); value_type *const finish = buf.end(); while (true) { value_type *const p = memchr_char(start, delim, finish - start); if (p == 0) { parts.push_back(T(start, finish - start)); break; } parts.push_back(T(start, p - start)); start = p + 1; } const size_t r = i; return r; }
template <typename T> size_t split_tmpl_arr(char delim, const T& buf, T *parts, size_t parts_len) { typedef typename T::value_type value_type; size_t i = 0; value_type *start = buf.begin(); value_type *const finish = buf.end(); for (i = 0; i < parts_len; ++i) { value_type *const p = memchr_char(start, delim, finish - start); if (p == 0) { parts[i] = T(start, finish - start); ++i; break; } parts[i] = T(start, p - start); start = p + 1; } const size_t r = i; for (; i < parts_len; ++i) { parts[i] = T(); } return r; }
template <typename T> inline T *find_char(T *s, T *e, int c) { T *r = memchr_char(s, c, e - s); return r ? r : e; }
int hstcpcli::response_recv(size_t& num_flds_r) { if (error_code < 0) { return error_code; } clear_error(); if (num_req_bufd > 0 || num_req_sent == 0 || num_req_rcvd > 0 || response_end_offset != 0) { close(); return set_error(-1, "response_recv: protocol out of sync"); } cur_row_offset = 0; num_flds_r = num_flds = 0; if (fd.get() < 0) { return set_error(-1, "read: closed"); } size_t offset = 0; while (true) { const char *const lbegin = readbuf.begin() + offset; const char *const lend = readbuf.end(); if (lbegin < lend) { const char *const nl = memchr_char(lbegin, '\n', lend - lbegin); if (nl != 0) { offset += (nl + 1) - lbegin; break; } offset += lend - lbegin; } if (read_more() <= 0) { close(); error_code = -1; return error_code; } } response_end_offset = offset; --num_req_sent; ++num_req_rcvd; char *start = readbuf.begin(); char *const finish = start + response_end_offset - 1; const size_t resp_code = read_ui32(start, finish); skip_one(start, finish); num_flds_r = num_flds = read_ui32(start, finish); if (resp_code != 0) { skip_one(start, finish); char *const err_begin = start; read_token(start, finish); char *const err_end = start; String e = String(err_begin, err_end - err_begin, &my_charset_bin); if (!e.length()) { e = String("unknown_error", &my_charset_bin); } return set_error(resp_code, e); } cur_row_offset = start - readbuf.begin(); DBG(fprintf(stderr, "[%s] ro=%zu eol=%zu\n", String(readbuf.begin(), readbuf.begin() + response_end_offset) .c_str(), cur_row_offset, response_end_offset)); DBG(fprintf(stderr, "RES 0\n")); if (flds.max_element < num_flds) { if (allocate_dynamic(&flds, num_flds)) return set_error(-1, "out of memory"); } flds.elements = num_flds; return 0; }