String* Highlighter_Highlight_IMP(Highlighter *self, String *text) { HighlighterIVARS *const ivars = Highlighter_IVARS(self); size_t size = Str_Get_Size(text) + Str_Get_Size(ivars->pre_tag) + Str_Get_Size(ivars->post_tag); CharBuf *buf = CB_new(size); CB_Cat(buf, ivars->pre_tag); CB_Cat(buf, text); CB_Cat(buf, ivars->post_tag); String *retval = CB_Yield_String(buf); DECREF(buf); return retval; }
static void test_Cat(TestBatchRunner *runner) { String *wanted = Str_newf("a%s", smiley); CharBuf *got = S_get_cb(""); CB_Cat(got, wanted); TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat"); DECREF(got); got = S_get_cb("a"); CB_Cat_Char(got, 0x263A); TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Char"); DECREF(got); got = S_get_cb("a"); CB_Cat_Utf8(got, smiley, smiley_len); TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Utf8"); DECREF(got); got = S_get_cb("a"); CB_Cat_Trusted_Utf8(got, smiley, smiley_len); TEST_TRUE(runner, S_cb_equals(got, wanted), "Cat_Trusted_Utf8"); DECREF(got); DECREF(wanted); }
static void test_Cat(TestBatch *batch) { CharBuf *wanted = CB_newf("a%s", smiley); CharBuf *got = S_get_cb(""); CB_Cat(got, wanted); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat"); DECREF(got); got = S_get_cb("a"); CB_Cat_Char(got, 0x263A); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Char"); DECREF(got); got = S_get_cb("a"); CB_Cat_Str(got, smiley, smiley_len); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Str"); DECREF(got); got = S_get_cb("a"); CB_Cat_Trusted_Str(got, smiley, smiley_len); TEST_TRUE(batch, CB_Equals(wanted, (Obj*)got), "Cat_Trusted_Str"); DECREF(got); DECREF(wanted); }
static void S_cat_seg_name(CharBuf *seg_name, u32_t seg_num) { CharBuf *base_36 = StrHelp_to_base36(seg_num); CB_Cat_Str(seg_name, "seg_", 4); CB_Cat(seg_name, base_36); DECREF(base_36); }
CharBuf* Compiler_to_string(Compiler *self) { CharBuf *stringified_query = Query_To_String(self->parent); CharBuf *string = CB_new_from_trusted_utf8("compiler(", 9); CB_Cat(string, stringified_query); CB_Cat_Trusted_Str(string, ")", 1); DECREF(stringified_query); return string; }
String* PhraseQuery_To_String_IMP(PhraseQuery *self) { PhraseQueryIVARS *const ivars = PhraseQuery_IVARS(self); uint32_t num_terms = Vec_Get_Size(ivars->terms); CharBuf *buf = CB_new(0); CB_Cat(buf, ivars->field); CB_Cat_Trusted_Utf8(buf, ":\"", 2); for (uint32_t i = 0; i < num_terms; i++) { Obj *term = Vec_Fetch(ivars->terms, i); String *term_string = Obj_To_String(term); CB_Cat(buf, term_string); DECREF(term_string); if (i < num_terms - 1) { CB_Cat_Trusted_Utf8(buf, " ", 1); } } CB_Cat_Trusted_Utf8(buf, "\"", 1); String *retval = CB_Yield_String(buf); DECREF(buf); return retval; }
CharBuf* PhraseQuery_to_string(PhraseQuery *self) { uint32_t i; uint32_t num_terms = VA_Get_Size(self->terms); CharBuf *retval = CB_Clone(self->field); CB_Cat_Trusted_Str(retval, ":\"", 2); for (i = 0; i < num_terms; i++) { Obj *term = VA_Fetch(self->terms, i); CharBuf *term_string = Obj_To_String(term); CB_Cat(retval, term_string); DECREF(term_string); if (i < num_terms - 1) { CB_Cat_Trusted_Str(retval, " ", 1); } } CB_Cat_Trusted_Str(retval, "\"", 1); return retval; }
void Err_Add_Frame_IMP(Err *self, const char *file, int line, const char *func) { CharBuf *buf = CB_new(0); CB_Cat(buf, self->mess); if (!Str_Ends_With_Utf8(self->mess, "\n", 1)) { CB_Cat_Char(buf, '\n'); } if (func != NULL) { CB_catf(buf, "\t%s at %s line %i32\n", func, file, (int32_t)line); } else { CB_catf(buf, "\tat %s line %i32\n", file, (int32_t)line); } DECREF(self->mess); self->mess = CB_Yield_String(buf); DECREF(buf); }
String* ProximityQuery_To_String_IMP(ProximityQuery *self) { ProximityQueryIVARS *const ivars = ProximityQuery_IVARS(self); uint32_t num_terms = VA_Get_Size(ivars->terms); CharBuf *buf = CB_new_from_str(ivars->field); CB_Cat_Trusted_Utf8(buf, ":\"", 2); for (uint32_t i = 0; i < num_terms; i++) { Obj *term = VA_Fetch(ivars->terms, i); String *term_string = Obj_To_String(term); CB_Cat(buf, term_string); DECREF(term_string); if (i < num_terms - 1) { CB_Cat_Trusted_Utf8(buf, " ", 1); } } CB_Cat_Trusted_Utf8(buf, "\"", 1); CB_catf(buf, "~%u32", ivars->within); String *retval = CB_Yield_String(buf); DECREF(buf); return retval; }
String* ORQuery_To_String_IMP(ORQuery *self) { ORQueryIVARS *const ivars = ORQuery_IVARS(self); uint32_t num_kids = Vec_Get_Size(ivars->children); if (!num_kids) { return Str_new_from_trusted_utf8("()", 2); } else { CharBuf *buf = CB_new_from_trusted_utf8("(", 1); uint32_t last_kid = num_kids - 1; for (uint32_t i = 0; i < num_kids; i++) { String *kid_string = Obj_To_String(Vec_Fetch(ivars->children, i)); CB_Cat(buf, kid_string); DECREF(kid_string); if (i == last_kid) { CB_Cat_Trusted_Utf8(buf, ")", 1); } else { CB_Cat_Trusted_Utf8(buf, " OR ", 4); } } String *retval = CB_Yield_String(buf); DECREF(buf); return retval; } }
void CB_vcatf(CharBuf *self, const char *pattern, va_list args) { size_t pattern_len = strlen(pattern); const char *pattern_start = pattern; const char *pattern_end = pattern + pattern_len; char buf[64]; for (; pattern < pattern_end; pattern++) { const char *slice_end = pattern; // Consume all characters leading up to a '%'. while (slice_end < pattern_end && *slice_end != '%') { slice_end++; } if (pattern != slice_end) { size_t size = slice_end - pattern; CB_Cat_Trusted_Str(self, pattern, size); pattern = slice_end; } if (pattern < pattern_end) { pattern++; // Move past '%'. switch (*pattern) { case '%': { CB_Cat_Trusted_Str(self, "%", 1); } break; case 'o': { Obj *obj = va_arg(args, Obj*); if (!obj) { CB_Cat_Trusted_Str(self, "[NULL]", 6); } else if (Obj_Is_A(obj, CHARBUF)) { CB_Cat(self, (CharBuf*)obj); } else { CharBuf *string = Obj_To_String(obj); CB_Cat(self, string); DECREF(string); } } break; case 'i': { int64_t val = 0; size_t size; if (pattern[1] == '8') { val = va_arg(args, int32_t); pattern++; } else if (pattern[1] == '3' && pattern[2] == '2') { val = va_arg(args, int32_t); pattern += 2; } else if (pattern[1] == '6' && pattern[2] == '4') { val = va_arg(args, int64_t); pattern += 2; } else { S_die_invalid_pattern(pattern_start); } size = sprintf(buf, "%" I64P, val); CB_Cat_Trusted_Str(self, buf, size); } break; case 'u': { uint64_t val = 0; size_t size; if (pattern[1] == '8') { val = va_arg(args, uint32_t); pattern += 1; } else if (pattern[1] == '3' && pattern[2] == '2') { val = va_arg(args, uint32_t); pattern += 2; } else if (pattern[1] == '6' && pattern[2] == '4') { val = va_arg(args, uint64_t); pattern += 2; } else { S_die_invalid_pattern(pattern_start); } size = sprintf(buf, "%" U64P, val); CB_Cat_Trusted_Str(self, buf, size); } break; case 'f': { if (pattern[1] == '6' && pattern[2] == '4') { double num = va_arg(args, double); char bigbuf[512]; size_t size = sprintf(bigbuf, "%g", num); CB_Cat_Trusted_Str(self, bigbuf, size); pattern += 2; } else { S_die_invalid_pattern(pattern_start); } } break; case 'x': { if (pattern[1] == '3' && pattern[2] == '2') { unsigned long val = va_arg(args, uint32_t); size_t size = sprintf(buf, "%.8lx", val); CB_Cat_Trusted_Str(self, buf, size); pattern += 2; } else { S_die_invalid_pattern(pattern_start); } } break; case 's': { char *string = va_arg(args, char*); if (string == NULL) { CB_Cat_Trusted_Str(self, "[NULL]", 6); } else { size_t size = strlen(string); if (StrHelp_utf8_valid(string, size)) { CB_Cat_Trusted_Str(self, string, size); } else { CB_Cat_Trusted_Str(self, "[INVALID UTF8]", 14); } } } break; default: { // Assume NULL-terminated pattern string, which // eliminates the need for bounds checking if '%' is // the last visible character. S_die_invalid_pattern(pattern_start); } }
void Err_cat_mess(Err *self, const CharBuf *mess) { CB_Cat(self->mess, mess); }
String* Highlighter_Highlight_Excerpt_IMP(Highlighter *self, VArray *spans, String *raw_excerpt, int32_t top) { int32_t hl_start = 0; int32_t hl_end = 0; StringIterator *iter = Str_Top(raw_excerpt); StringIterator *temp = Str_Top(raw_excerpt); CharBuf *buf = CB_new(Str_Get_Size(raw_excerpt) + 32); CharBuf *encode_buf = NULL; int32_t raw_excerpt_end = top + Str_Length(raw_excerpt); for (uint32_t i = 0, max = VA_Get_Size(spans); i < max; i++) { Span *span = (Span*)VA_Fetch(spans, i); int32_t offset = Span_Get_Offset(span); if (offset < top) { continue; } else if (offset >= raw_excerpt_end) { break; } else { int32_t relative_start = offset - top; int32_t relative_end = relative_start + Span_Get_Length(span); if (relative_start <= hl_end) { if (relative_end > hl_end) { hl_end = relative_end; } } else { if (hl_start < hl_end) { // Highlight previous section int32_t highlighted_len = hl_end - hl_start; StrIter_Assign(temp, iter); StrIter_Advance(iter, highlighted_len); String *to_cat = StrIter_substring(temp, iter); String *encoded = S_do_encode(self, to_cat, &encode_buf); String *hl_frag = Highlighter_Highlight(self, encoded); CB_Cat(buf, hl_frag); DECREF(hl_frag); DECREF(encoded); DECREF(to_cat); } int32_t non_highlighted_len = relative_start - hl_end; StrIter_Assign(temp, iter); StrIter_Advance(iter, non_highlighted_len); String *to_cat = StrIter_substring(temp, iter); String *encoded = S_do_encode(self, to_cat, &encode_buf); CB_Cat(buf, (String*)encoded); DECREF(encoded); DECREF(to_cat); hl_start = relative_start; hl_end = relative_end; } } } if (hl_start < hl_end) { // Highlight final section int32_t highlighted_len = hl_end - hl_start; StrIter_Assign(temp, iter); StrIter_Advance(iter, highlighted_len); String *to_cat = StrIter_substring(temp, iter); String *encoded = S_do_encode(self, to_cat, &encode_buf); String *hl_frag = Highlighter_Highlight(self, encoded); CB_Cat(buf, hl_frag); DECREF(hl_frag); DECREF(encoded); DECREF(to_cat); } // Last text, beyond last highlight span. if (StrIter_Has_Next(iter)) { String *to_cat = StrIter_substring(iter, NULL); String *encoded = S_do_encode(self, to_cat, &encode_buf); CB_Cat(buf, encoded); DECREF(encoded); DECREF(to_cat); } String *highlighted = CB_Yield_String(buf); DECREF(encode_buf); DECREF(buf); DECREF(temp); DECREF(iter); return highlighted; }
String* Highlighter_Raw_Excerpt_IMP(Highlighter *self, String *field_val, int32_t *start_ptr, HeatMap *heat_map) { HighlighterIVARS *const ivars = Highlighter_IVARS(self); // Find start of excerpt. StringIterator *top = Str_Top(field_val); int32_t best_location = S_hottest(heat_map); int32_t start; uint32_t max_skip; if ((uint32_t)best_location <= ivars->slop) { // If the beginning of the string falls within the window centered // around the hottest point in the field, start the fragment at the // beginning. start = 0; max_skip = best_location; } else { start = best_location - ivars->slop; max_skip = ivars->slop; StrIter_Advance(top, start); } uint32_t num_skipped; bool found_starting_edge = S_find_starting_boundary(top, max_skip, &num_skipped); start += num_skipped; // Find end of excerpt. StringIterator *tail = StrIter_Clone(top); uint32_t max_len = ivars->excerpt_length; if (!found_starting_edge) { // Leave space for starting ellipsis and space character. max_len -= 2; } bool found_ending_edge = true; uint32_t excerpt_len = StrIter_Advance(tail, max_len); // Skip up to slop code points but keep at least max_len - slop. if (excerpt_len > max_len - ivars->slop) { max_skip = excerpt_len - (max_len - ivars->slop); found_ending_edge = S_find_ending_boundary(tail, max_skip, &num_skipped); if (num_skipped >= excerpt_len) { excerpt_len = 0; } else { excerpt_len -= num_skipped; } } // Extract excerpt. String *raw_excerpt; if (!excerpt_len) { raw_excerpt = Str_new_from_trusted_utf8("", 0); } else { String *substring = StrIter_substring(top, tail); CharBuf *buf = CB_new(Str_Get_Size(substring) + 8); // If not starting on a sentence boundary, prepend an ellipsis. if (!found_starting_edge) { CB_Cat_Char(buf, ELLIPSIS_CODE_POINT); CB_Cat_Char(buf, ' '); start -= 2; } CB_Cat(buf, substring); // If not ending on a sentence boundary, append an ellipsis. if (!found_ending_edge) { CB_Cat_Char(buf, ELLIPSIS_CODE_POINT); } raw_excerpt = CB_Yield_String(buf); DECREF(buf); DECREF(substring); } *start_ptr = start; DECREF(top); DECREF(tail); return raw_excerpt; }