CStrLineIterator クラス てすとけーすつき
CStrLineIterator クラスを導入して listbox を高速化 - fujidigの雑記 で作った CStrLineIterator クラスをてすとけーすつきで。
CStrLineIterator::next メソッドでバッファサイズが足りないときに -1 を返してるんですけど、次に next を呼んだときにはもう次の行にいっちゃっているので、たとえばバッファサイズを倍々にしていってバッファサイズが足りるようになるまで何度も呼ぶ、みたいなことができないのが個人的に心残り。
#include <stdio.h> #include <string.h> #include <assert.h> class CStrLineIterator { public: CStrLineIterator( char *str ); ~CStrLineIterator(); bool hasNext(); int next( char *dest, int len ); private: char *str; int offset; }; int getLineMax(char *str) { int result = 0; CStrLineIterator iterator(str); while(iterator.hasNext()) { iterator.next(NULL, 0); result ++; } return result; } int main(void) { { CStrLineIterator iterator("a\nb\nc"); char dest[1024]; iterator.next(dest, sizeof dest); assert(strcmp(dest, "a") == 0); iterator.next(dest, sizeof dest); assert(strcmp(dest, "b") == 0); iterator.next(dest, sizeof dest); assert(strcmp(dest, "c") == 0); } { CStrLineIterator iterator("a\nb\nc"); assert(iterator.hasNext() == true); iterator.next(NULL, 0); assert(iterator.hasNext() == true); iterator.next(NULL, 0); assert(iterator.hasNext() == true); iterator.next(NULL, 0); assert(iterator.hasNext() == false); } { CStrLineIterator iterator("aaaaa\n\nc"); char dest[1024]; int ret; ret = iterator.next(dest, sizeof dest); assert(ret == 5); ret = iterator.next(dest, sizeof dest); assert(ret == 0); ret = iterator.next(dest, sizeof dest); assert(ret == 1); } { assert(getLineMax("") == 0); assert(getLineMax(" ") == 1); assert(getLineMax("\n") == 1); assert(getLineMax("\n ") == 2); assert(getLineMax("\n\n") == 2); assert(getLineMax("a\n\nb") == 3); assert(getLineMax("a\n\nb\n") == 3); } { CStrLineIterator iterator(""); char dest[1024]; int ret; assert(iterator.hasNext() == false); ret = iterator.next(dest, sizeof dest); assert(strcmp(dest, "") == 0); assert(ret == 0); } { assert(getLineMax("\r") == 1); assert(getLineMax("\r ") == 2); assert(getLineMax("\r\n") == 1); assert(getLineMax("\r\n ") == 2); assert(getLineMax("a\r\rb\r") == 3); assert(getLineMax("a\r\n\r\nb\r\n") == 3); } { CStrLineIterator iterator("abcd"); char dest[1024]; memset(dest, '\xff', sizeof dest); int ret = iterator.next(dest, 3); assert(ret == -1); assert(dest[0] == 'a'); assert(dest[1] == 'b'); assert(dest[2] == 'c'); assert(dest[3] == '\xff'); } { CStrLineIterator iterator("abc"); char dest[1024]; memset(dest, '\xff', sizeof dest); int ret = iterator.next(dest, 3); assert(ret == 3); assert(dest[0] == 'a'); assert(dest[1] == 'b'); assert(dest[2] == 'c'); assert(dest[3] == '\xff'); } printf("all ok\n"); } CStrLineIterator::CStrLineIterator( char *str ) { this->str = str; offset = 0; } CStrLineIterator::~CStrLineIterator() { } bool CStrLineIterator::hasNext() { return str[offset] != '\0'; } int CStrLineIterator::next( char *dest, int len ) { int i = 0; bool over = false; while(1) { char c = str[offset]; if( c == '\0' ) { break; } #if 1 if( c == '\n' ) { offset ++; break; } #endif if( c == '\r' ) { offset ++; if( str[offset] == '\n' ) { offset ++; } break; } if( i < len ) { dest[i] = c; } else { over = true; } i ++, offset ++; } if( over ) { return -1; } if( i < len ) { dest[i] = '\0'; } return i; }