static void test_iterator_whitespace(TestBatchRunner *runner) { int num_spaces; String *ws_smiley = S_smiley_with_whitespace(&num_spaces); { StringIterator *iter = Str_Top(ws_smiley); TEST_INT_EQ(runner, StrIter_Skip_Whitespace(iter), num_spaces, "Skip_Whitespace"); TEST_INT_EQ(runner, StrIter_Skip_Whitespace(iter), 0, "Skip_Whitespace without whitespace"); DECREF(iter); } { StringIterator *iter = Str_Tail(ws_smiley); TEST_INT_EQ(runner, StrIter_Skip_Whitespace_Back(iter), num_spaces, "Skip_Whitespace_Back"); TEST_INT_EQ(runner, StrIter_Skip_Whitespace_Back(iter), 0, "Skip_Whitespace_Back without whitespace"); DECREF(iter); } DECREF(ws_smiley); }
String* Str_Trim_IMP(String *self) { StringIterator *top = STACK_ITER(self, 0); StrIter_Skip_Whitespace(top); StringIterator *tail = NULL; if (top->byte_offset < self->size) { tail = STACK_ITER(self, self->size); StrIter_Skip_Whitespace_Back(tail); } return StrIter_crop((StringIterator*)top, (StringIterator*)tail); }
Vector* QueryLexer_Tokenize_IMP(QueryLexer *self, String *query_string) { QueryLexerIVARS *const ivars = QueryLexer_IVARS(self); Vector *elems = Vec_new(0); if (!query_string) { return elems; } StringIterator *iter = Str_Top(query_string); while (StrIter_Has_Next(iter)) { ParserElem *elem = NULL; if (StrIter_Skip_Whitespace(iter)) { // Fast-forward past whitespace. continue; } if (ivars->heed_colons) { ParserElem *elem = S_consume_field(iter); if (elem) { Vec_Push(elems, (Obj*)elem); } } int32_t code_point = StrIter_Next(iter); switch (code_point) { case '(': elem = ParserElem_new(TOKEN_OPEN_PAREN, NULL); break; case ')': elem = ParserElem_new(TOKEN_CLOSE_PAREN, NULL); break; case '+': if (StrIter_Has_Next(iter) && !StrIter_Skip_Whitespace(iter) ) { elem = ParserElem_new(TOKEN_PLUS, NULL); } else { elem = ParserElem_new(TOKEN_STRING, (Obj*)Str_newf("+")); } break; case '-': if (StrIter_Has_Next(iter) && !StrIter_Skip_Whitespace(iter) ) { elem = ParserElem_new(TOKEN_MINUS, NULL); } else { elem = ParserElem_new(TOKEN_STRING, (Obj*)Str_newf("-")); } break; case '"': StrIter_Recede(iter, 1); elem = S_consume_quoted_string(iter); break; case 'O': StrIter_Recede(iter, 1); elem = S_consume_keyword(iter, "OR", 2, TOKEN_OR); if (!elem) { elem = S_consume_text(iter); } break; case 'A': StrIter_Recede(iter, 1); elem = S_consume_keyword(iter, "AND", 3, TOKEN_AND); if (!elem) { elem = S_consume_text(iter); } break; case 'N': StrIter_Recede(iter, 1); elem = S_consume_keyword(iter, "NOT", 3, TOKEN_NOT); if (!elem) { elem = S_consume_text(iter); } break; default: StrIter_Recede(iter, 1); elem = S_consume_text(iter); break; } Vec_Push(elems, (Obj*)elem); } DECREF(iter); return elems; }
String* Str_Trim_Top_IMP(String *self) { StringIterator *top = STACK_ITER(self, 0); StrIter_Skip_Whitespace(top); return StrIter_crop((StringIterator*)top, NULL); }