// Read one record completely and return it as a Ruby String object. static VALUE sedna_read(SC *conn, int strip_n) { int bytes_read = 0; char buffer[RESULT_BUF_LEN]; VALUE str = rb_str_buf_new(0); OBJ_TAINT(str); do { bytes_read = SEgetData(conn, buffer, RESULT_BUF_LEN - 1); if(bytes_read == SEDNA_ERROR) { sedna_err(conn, SEDNA_ERROR); } else { if(bytes_read > 0) { if(strip_n) { // Strange bug adds newlines to beginning of every result // except the first. Strip them! This a known issue in the // network protocol and serialization mechanism. // See: http://sourceforge.net/mailarchive/forum.php?thread_name=3034886f0812030132v3bbd8e2erd86480d3dc640664%40mail.gmail.com&forum_name=sedna-discussion STR_CAT(str, buffer + 1, bytes_read - 1); // Do not strip newlines from subsequent buffer reads. strip_n = 0; } else { STR_CAT(str, buffer, bytes_read); } } } } while(bytes_read > 0); return str; }
/** * Add header line to the `headers' hash for specified field name. * A private copy of the `field' name and of the `text' data is made. */ static void add_header(header_t *o, const char *field, const char *text) { htable_t *ht; str_t *v; header_check(o); ht = header_get_table(o); v = htable_lookup(ht, field); if (v) { /* * Header already exists, according to RFC2616 we need to append * the value, comma-separated. */ STR_CAT(v, ", "); str_cat(v, text); } else { char *key; /* * Create a new header entry in the hash table. */ key = h_strdup(field); v = str_new_from(text); htable_insert(ht, key, v); } }
/** * Terminate header, emitting the trailing "\r\n". * Further appending is forbidden. */ void header_fmt_end(header_fmt_t *hf) { header_fmt_check(hf); g_assert(!hf->frozen); if (!hf->empty) STR_CAT(hf->header, "\r\n"); hf->frozen = TRUE; g_assert(str_len(hf->header) < hf->max_size); }
/** * Create a new formatting context for a header line. * * @param `field' is the header field name, without trailing ':'. * * @param `separator' is the optional default separator to emit between * the values added via header_fmd_append_value(). To supersede the * default separator, use header_fmd_append() and specify another separator * explicitly. If set to NULL, there will be no default separator and * values will be simply concatenated together. The value given must * NOT be freed before the header_fmt_end() call (usually it will just * be a static string). Trailing spaces in the separator will be stripped * if it is emitted at the end of a line before a continuation. * * @param `len_hint' is the expected line size, for pre-sizing purposes. * (0 to guess). * * @param `max_size' is the maximum header size, including the final "\r\n" * and the trailing NUL. If the initial field name is larger than the * configured maximum size, the header field will remain completely empty. * * @return pointer to the formatting object. */ header_fmt_t * header_fmt_make(const char *field, const char *separator, size_t len_hint, size_t max_size) { struct header_fmt *hf; g_assert(size_is_non_negative(len_hint)); WALLOC(hf); hf->magic = HEADER_FMT_MAGIC; hf->header = str_new(len_hint ? len_hint : HEADER_FMT_DFLT_LEN); hf->maxlen = HEADER_FMT_LINE_LEN; hf->data_emitted = FALSE; hf->frozen = FALSE; hf->max_size = max_size; hf->sep = atom_str_get(separator ? separator : ""); hf->seplen = strlen(hf->sep); hf->stripped_seplen = stripped_strlen(hf->sep, hf->seplen); str_cat(hf->header, field); STR_CAT(hf->header, ": "); hf->current_len = str_len(hf->header); /* * If right from the start the header would be larger than the configured * size, force it to stay empty. That means, the final string returned * will be "", the empty string. */ if (str_len(hf->header) + sizeof("\r\n") > hf->max_size) { hf->empty = TRUE; str_setlen(hf->header, 0); } else { hf->empty = FALSE; } header_fmt_check(hf); return hf; }
/* * @return stringified host vector as newly allocated string via halloc() */ char * gnet_host_vec_to_string(const gnet_host_vec_t *hvec) { str_t *s; uint i, n; g_return_val_if_fail(hvec, NULL); s = str_new(0); n = gnet_host_vec_count(hvec); for (i = 0; i < n; i++) { gnet_host_t host; gchar buf[128]; if (i > 0) { STR_CAT(s, ", "); } host = gnet_host_vec_get(hvec, i); host_addr_port_to_string_buf(gnet_host_get_addr(&host), gnet_host_get_port(&host), buf, sizeof buf); str_cat(s, buf); } return str_s2c_null(&s); }
/** * Append data `str' to the header line, atomically. * * @param `hf' no brief description. * @param `str' no brief description. * @param `separator' is an optional separator string that will be emitted * BEFORE outputting the data, and only when nothing has been emitted * already. * @param `slen' is the separator length, 0 if empty. * @param `sslen' is the stripped separator length, (size_t)-1 if unknown yet. * * @return TRUE if we were able to fit the string, FALSE if it would have * resulted in the header being larger than the configured max size (the * header line is left in the state it was in upon entry, in that case). */ static bool header_fmt_append_full(header_fmt_t *hf, const char *str, const char *separator, size_t slen, size_t sslen) { size_t len, curlen; gsize gslen; bool success; header_fmt_check(hf); g_assert(size_is_non_negative(slen)); g_assert((size_t)-1 == sslen || size_is_non_negative(sslen)); if (hf->empty) return FALSE; gslen = str_len(hf->header); len = strlen(str); curlen = hf->current_len; g_assert(size_is_non_negative(curlen)); g_assert(len <= INT_MAX); /* Legacy bug */ if ( size_saturate_add(curlen, size_saturate_add(len, slen)) > UNSIGNED(hf->maxlen) ) { /* * Emit sperator, if any and data was already emitted. */ if (separator != NULL && hf->data_emitted) { sslen = (size_t)-1 != sslen ? sslen : stripped_strlen(separator, slen); str_cat_len(hf->header, separator, sslen); } STR_CAT(hf->header, "\r\n\t"); /* Includes continuation */ curlen = 1; /* One tab */ } else if (hf->data_emitted) { str_cat(hf->header, separator); curlen += slen; } str_cat(hf->header, str); /* * Check for overflows, undoing string changes if needed. */ if (str_len(hf->header) + sizeof("\r\n") > hf->max_size) { success = FALSE; str_setlen(hf->header, gslen); /* Undo! */ } else { success = TRUE; hf->data_emitted = TRUE; hf->current_len = curlen + len; } g_assert(str_len(hf->header) + sizeof("\r\n") <= hf->max_size); return success; }