CStrLineIterator クラスを導入して listbox を高速化
CStrNote で行頭位置をキャッシュするパッチが投稿されていました。 listbox が高速になっていい感じなんですが、 note 系命令を使ったプログラムは逆に遅くなってしまいます。これは CStrNote::Select が呼ばれるたびにキャッシュを作っていて、しかも各種 note 系命令を呼び出したときには毎回 CStrNote::Select を呼ぶからかなと思います。
そこで、 CStrNote には触らず新しく CStrLineIterator クラスを作って listbox の処理にはそれを使うようにしてみました。
Index: strnote.cpp =================================================================== --- strnote.cpp (リビジョン 164) +++ strnote.cpp (作業コピー) @@ -240,3 +240,62 @@ return 0; } +//------------------------------------------------------------// +/* + CStrLineIterator +*/ +//------------------------------------------------------------// + +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; + } +#ifdef HSPLINUX + 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; +} Index: strnote.h =================================================================== --- strnote.h (リビジョン 164) +++ strnote.h (作業コピー) @@ -31,4 +31,17 @@ char nulltmp[4]; }; +//------------------------------------------------------------// + +class CStrLineIterator { +public: + CStrLineIterator( char *str ); + ~CStrLineIterator(); + bool hasNext(); + int next( char *dest, int len ); +private: + char *str; + int offset; +}; + #endif Index: win32gui/hspwnd_obj.cpp =================================================================== --- win32gui/hspwnd_obj.cpp (リビジョン 164) +++ win32gui/hspwnd_obj.cpp (作業コピー) @@ -161,16 +161,16 @@ static void Object_SetMultiBox( HSPOBJINFO *info, int type, void *ptr ) { - int i,max; + int i; char res[256]; UINT m_ini,m_add; HWND hw; - CStrNote note; hw = info->hCld; switch( type ) { - case TYPE_STRING: + case TYPE_STRING:{ + CStrLineIterator iterator( (char *)ptr ); if ( info->owid ) { m_ini=CB_RESETCONTENT; m_add=CB_ADDSTRING; @@ -178,14 +178,14 @@ m_ini=LB_RESETCONTENT; m_add=LB_ADDSTRING; } - note.Select( (char *)ptr ); - max = note.GetMaxLine(); SendMessage( hw, m_ini, 0, 0L ); - for( i=0;i<max;i++ ) { - note.GetLine( res, i, 255 ); + while ( iterator.hasNext() ) { + iterator.next( res, sizeof res ); + res[sizeof res-1] = '\0'; SendMessage( hw, m_add, 0, (long)res ); } break; + } case TYPE_INUM: if ( info->owid ) { m_ini=CB_SETCURSEL;
で、以下のスクリプトを素の OpenHSP 、>>525 のパッチを当てた OpenHSP 、 私の CStrLineIterator のパッチを当てた OpenHSP で速度比較してみました。
listbox の処理と noteget ですべての行をなめる処理が入ったスクリプトです。
n = 50000 gosub *build gsel 0, 1 wait 10 #uselib "winmm" #cfunc d3timer "timeGetTime" time = d3timer() listbox x, 100, a time = d3timer() - time pos 70, 0 mes time wait 100 n = 5000 gosub *build time = d3timer() notesel a repeat notemax noteget t, cnt loop time = d3timer() - time mes time stop *build #define ctype format(%1) strf("%%05d\n", %1) sdim a, n * strlen(format(0)) + 1 i = 0 repeat n poke a, i, format(cnt) i += strsize loop return