Arrx.c
[大目次 | 目次 | 関数 | マクロ]
1|/****************************************************************
2|* 1. <<< 固定要素数配列 (ArrX) >>>
3|*・ArrX は任意の型の配列を統一的に用いるようにします。
4|*・要素数を配列と別の変数にしないので、配列自体を1つの識別子だけで
5|* 参照することができます。
6|* char arr[50]; ... char* pArr;
7|* int arr_n; int* pArr_n;
8|* ArrX arr; ... ArrX* pArr;
9|*
10|* 2. <<< 配列内の全要素を走査する >>>
11|*・配列内の全要素を走査するには、次のようにします。
12|* ArrX* arr; // 配列
13|* type* pElem; // 要素へのポインタ
14|* type* pElem_last; // 最終要素の次のアドレス
15|*
16|* pElem_last = arr->last;
17|* for ( pElem = arr->first; pElem < pElem_last; pElem++ ) {
18|* *pElem; // 要素へのアクセス、ポインタ参照 '*' に注意
19|* pElem->member;
20|* }
21|*****************************************************************/
22|#include "mixer_precomp.h" /* Auto precompiled header, Look at mixer-... folder */
23|// #pragma hdrstop ("mixer_precomp")
24|
25|#define STDLIBS_INCLUDE_STDIO_H
26|#define STDLIBS_INCLUDE_STRING_H
27|#define STDLIBS_INCLUDE_STDARG_H
28|
29|#if defined(USES_MXP_AUTOINC)
30| #include "arrx.ah" /* Auto include header, Look at mixer-... folder */
31|#endif
32|
33|#include <stdlib.h>
34|
35|#if defined(FOR_GHS) || defined(FOR_CA) || defined(FOR_WINCE)
36| #define ARRX_NO_STRICMP
37|#endif
38|
39|/*-------------------------------------------------------------------------*/
40|/* ◆3. <<<< (ArrX_C) C言語配列 >>>> */
41|/*-------------------------------------------------------------------------*/
42|
43|
44|
45|/***********************************************************************
46| 3-1. <<< [ArrX_C_shaffle] 配列の内容をランダムにシャッフルする >>>
47|【引数】
48| ・void* arr_adr; 配列の先頭アドレス
49| ・int elem_size; 配列の要素のサイズ(バイト)
50| ・int nElem; 配列の要素数
51| ・int seed; 乱数の種(時刻など, -1= seed を使わない, 1=再初期化)
52|************************************************************************/
53|void ArrX_C_shaffle( void* arr_adr, int elem_size, int nElem, int seed )
54|{
55| int i, j, x;
56| char elem;
57| char* p1;
58| char* p2;
59|
60| if ( seed != -1 ) srand( seed );
61|
62| for ( i = 0; i < nElem; i++ ) {
63| j = nElem * rand() / (RAND_MAX+1);
64|
65| p1 = (char*)arr_adr + elem_size * i;
66| p2 = (char*)arr_adr + elem_size * j;
67| for ( x = 0; x < elem_size; x++ ) {
68| elem = p1[x]; p1[x] = p2[x]; p2[x] = elem;
69| }
70| }
71|}
72|
73|
74|/*-------------------------------------------------------------------------*/
75|/* ◆4. <<<< 最小固定要素配列 (ArrX) >>>> */
76|/*-------------------------------------------------------------------------*/
77|
78|#ifdef USES_SYM
79|SYM_STRUCT_START( ArrX )
80|SYM_STRUCT_LOOP_FUNC( ArrX, ArrX_doLoopFunc )
81|SYM_STRUCT_MEMB( ArrX, void*, first )
82|SYM_STRUCT_MEMB( ArrX, void*, last )
83|SYM_STRUCT_END( ArrX )
84|#endif
85|
86|
87|/****************************************************************
88| 4-1. <<< [ArrX_init] 初期化する(type1) >>>
89|【引数】
90| ・int arr_sizeof; 全要素のデータのサイズ (byte)
91|【補足】
92|・次のように指定することで、確保したメモリ領域 arr のサイズに
93| 関わらず、任意の要素数 n の type 型配列とすることができます。
94| ArrX_init( &arrx, arr, sizeof(type)* n );
95|*****************************************************************/
96|void ArrX_init( ArrX* m, void* first, int arr_sizeof )
97|{
98| ERRORS_INITCHK( m, 0 );
99|
100| m->first = first;
101| m->last = (char*)first + arr_sizeof;
102|
103| ASSERT( ArrX_chk( m ) );
104|}
105|
106|
107|
108|/****************************************************************
109| 4-2. <<< [ArrX_init2] 初期化する(type2) >>>
110|【引数】
111| ・void* first; 配列の先頭アドレス
112| ・void* over; 配列の末尾の次の要素のアドレス
113|【補足】
114|・over には、たとえば、struct* p; に配列の末尾の要素のアドレスが
115| 格納されている場合、p+1( (char*)p + sizeof(struct))を指定します。
116|*****************************************************************/
117|void ArrX_init2( ArrX* m, void* first, void* over )
118|{
119| ERRORS_INITCHK( m, 0 );
120|
121| m->first = first;
122| m->last = over;
123|
124| ASSERT( ArrX_chk( m ) );
125|}
126|
127|
128|/****************************************************************
129| 4-3. <<< [ArrX_initByStr] 文字列を ArrX 型にする >>>
130|*****************************************************************/
131|void ArrX_initByStr( ArrX* m, char* str )
132|{
133| ERRORS_INITCHK( m, 0 );
134|
135| m->first = str;
136| m->last = str + strlen( str );
137|
138| ASSERT( ArrX_chk( m ) );
139|}
140|
141|
142|
143|/***********************************************************************
144| 4-4. <<< [ArrX_initPtrArr_imp] ポインタ配列を作る >>>
145|【補足】
146|・ArrX_initPtrArr の実装部です。
147|************************************************************************/
148|void ArrX_initPtrArr_imp( ArrX* m, ArrX_Buf* buf, ArrX* arr,
149| int elem_size )
150|{
151| char* pElem; /* arr の要素 */
152| char* pElem_over;
153| void** p_first;
154| void** p;
155| int nElem;
156|
157| ERRORS_INITCHK( m, 0 );
158| ASSERT( ArrX_Buf_chk( buf ) && ArrX_chk( arr ) );
159| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_size == 0 );
160|
161| /* ポインタ配列のメモリ領域を確保する */
162| nElem = ((char*)arr->last - (char*)arr->first) / elem_size;
163| p_first = ArrX_Buf_allocs( buf, void*, nElem );
164| p = p_first;
165|
166| /* アドレスをポインタ配列に格納する */
167| pElem_over = (char*)arr->last;
168| for ( pElem = (char*)arr->first; pElem < pElem_over; pElem += elem_size ) {
169| *p = pElem; p++;
170| }
171|
172| /* ポインタ配列を初期化する */
173| ArrX_init2( m, (void*)p_first, (void*)p );
174|
175| ASSERT( ArrX_chk( m ) );
176|}
177|
178|
179|
180|/****************************************************************
181| 4-5. <<< [ArrX_castFrom_ArrX_Buf_imp] ArrX 型にキャストする >>>
182|*****************************************************************/
183|ArrX* ArrX_castFrom_ArrX_Buf_imp( ArrX* arr, ArrX_Buf* buf )
184|{
185| ArrX_init2( arr, buf->first, buf->last );
186| return arr;
187|}
188|
189|
190|/****************************************************************
191| 4-6. <<< [ArrX_chk] 正規チェック >>>
192|*****************************************************************/
193|int ArrX_chk( ArrX* m )
194|{
195| ERRORS_INITCHK_FOR_SUB( m, 1 );
196| return m->first <= m->last;
197|}
198|
199|
200|/****************************************************************
201| 4-7. <<< [ArrX_getN_imp] 要素数を返す >>>
202|・ArrX_getN の実装部です。(デバッグ用)
203|*****************************************************************/
204|int ArrX_getN_imp( ArrX* m, int size )
205|{
206| ERRORS_INITCHK( m, 1 );
207| ASSERT( ArrX_chk( m ) );
208| ASSERT( ( (char*)m->last - (char*)m->first ) % size == 0 );
209|
210| return ( (char*)m->last - (char*)m->first ) / size;
211|}
212|
213|
214|/****************************************************************
215| 4-8. <<< [ArrX_get_imp] 配列番号から要素を返す >>>
216|【引数】
217| ・ArrX* m; 配列
218| ・int i; 配列番号
219| ・int size; 配列要素のサイズ
220|【補足】
221|・リリース時は、マクロ版 ArrX_get を呼び出します。
222|*****************************************************************/
223|void* ArrX_get_imp( ArrX* m, int i, int size )
224|{
225| void* p = (char*)m->first + i * size;
226|
227| ASSERT( p < m->last );
228| ASSERT( ( (char*)m->last - (char*)m->first ) % size == 0 );
229|
230| return p;
231|}
232|
233|
234|
235|/****************************************************************
236| 4-9. <<< [ArrX_Able_getNext_imp] ArrX_Able_getNext の実装部 >>>
237|*****************************************************************/
238|#ifdef USES_OFFSET
239|void* ArrX_Able_getNext_imp( ArrX_Able* m, void* base,
240| int elem_size, Offset inherit )
241|{
242| char* p = (char*)base;
243|
244| ASSERT( ( (char*)m->arr.last - (char*)m->arr.first ) % elem_size == 0 );
245|
246| p += elem_size;
247| while ( p < (char*)m->arr.last ) {
248| if ( Offset_ref( inherit, p, ArrX_AbleElem ) )
249| return (void*)p;
250| p += elem_size;
251| }
252| return NULL;
253|}
254|#endif
255|
256|/****************************************************************
257| 4-10. <<< [ArrX_setStrs] 複数の文字列を配列に入れる >>>
258|【機能】
259|・配列のすべての文字列要素を入れます。
260|【補足】
261|・引数 ... に指定する文字列は、配列の用素数だけ指定します。
262| それより多くても少なくてもいけません。
263| ArrX_init( &aa, buf, sizeof(char*)*3 ); のように、
264| 用素数を調整してください。
265|*****************************************************************/
266|#ifdef STDLIBS_INCLUDE_STDARG_H
267|void ArrX_setStrs( ArrX* m, ... )
268|{
269| va_list va;
270| char** p;
271|
272| va_start( va, m );
273|
274| for ( p = (char**)m->first; p < (char**)m->last; p++ )
275| *p = va_arg( va, char* );
276|
277| va_end( va );
278|}
279|#endif
280|
281|
282|
283|/***********************************************************************
284| 4-11. <<< [ArrX_memrot_imp] 配列の要素をローテーションする >>>
285|【引数】
286| ・void* ball; 配列の要素へのアドレス
287| ・void* target; 要素の移動先のアドレス
288| ・void* work; ワーク領域(配列の要素の型の変数へのアドレス)
289| ・int ball_size; 要素のメモリサイズ
290|【補足】
291|・ArrX_memrot の実装部です。
292|************************************************************************/
293|void ArrX_memrot_imp( void* ball, void* target, void* work, int ball_size )
294|{
295| memcpy( work, ball, ball_size );
296| if ( ball > target ) {
297| memmove( (char*)target + ball_size, target,
298| (char*)ball - (char*)target );
299| }
300| else {
301| memmove( ball, (char*)ball + ball_size,
302| (char*)target - (char*)ball );
303| }
304| memcpy( target, work, ball_size );
305|}
306|
307|
308|/***********************************************************************
309| 4-12. <<< [ArrX_print] 配列の要素をデバッグ表示する >>>
310|【引数】
311| ・ArrX* m; 配列
312| ・char* types; 型リスト
313|【補足】
314|・型リストは、配列要素の型を次の文字で指定した文字列です。
315| ・'i' ... 整数型(int)
316| ・'s' ... 文字列型(char*)
317| ・'p' ... アドレス型(void*)
318| 整数と文字列が1つずつ入った構造体の場合は、"is" と指定します。
319|************************************************************************/
320|#ifdef USES_ERRORS
321|#ifndef ERRORS_CUT_DEBUG_TOOL
322|void ArrX_print( ArrX* m, char* types )
323|{
324| char* t = types;
325| int* p;
326| int i = 0;
327|
328| for ( ArrX_forEach( m, &p, int ) ) {
329| switch ( *t ) {
330| case 'i':
331| Errors_printf( " [%d] = %d (0x%X) '%c'", i, *p, *p, *p );
332| break;
333| case 's':
334| Errors_printf( " [%d] = (%p) \"%s\"", i, *p, *p );
335| break;
336| case 'p':
337| Errors_printf( " [%d] = (%p)", i, *p );
338| break;
339| default:
340| error();
341| }
342| t++; if ( *t == '\0' ) t = types;
343| i++;
344| }
345|}
346|#endif
347|#endif
348|
349|/**************************************************************************
350| 4-13. <<< [ArrX_search_i_imp] int 型のキーを用いて線形検索する >>>
351|・この関数は、ArrX_search_i マクロの実装部です。
352|***************************************************************************/
353|#ifdef USES_OFFSET
354|void* ArrX_search_i_imp( ArrX* m, Offset_Key* key, int val,
355| int elem_sizeof )
356|{
357| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) );
358| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 );
359|
360| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof,
361| &val, key->offset, 0, sizeof(int) );
362|}
363|#endif /* USES_OFFSET */
364|
365|
366|
367|/**************************************************************************
368| 4-14. <<< [ArrX_search_d_imp] double 型のキーを用いて線形検索する >>>
369|・この関数は、ArrX_search_d マクロの実装部です。
370|***************************************************************************/
371|#ifdef USES_OFFSET
372|void* ArrX_search_d_imp( ArrX* m, Offset_Key* key, double val,
373| int elem_sizeof )
374|{
375| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) );
376| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 );
377|
378| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof,
379| &val, key->offset, 0, sizeof(double) );
380|}
381|#endif /* USES_OFFSET */
382|
383|
384|
385|/**************************************************************************
386| 4-15. <<< [ArrX_search_s_imp] 文字列型のキーを用いて線形検索する >>>
387|・この関数は、ArrX_search_s マクロの実装部です。
388|***************************************************************************/
389|#ifdef USES_OFFSET
390|void* ArrX_search_s_imp( ArrX* m, Offset_Key* key, const char* val,
391| int elem_sizeof )
392|{
393| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) );
394| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 );
395|
396| if ( key->type == Offset_CString )
397| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof,
398| val, key->offset, 0, -1 );
399| else if ( key->type == Offset_CStringP || key->type == Offset_StrV ) {
400| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof,
401| val, key->offset, 1, -1 );
402| }
403| #ifndef ARRX_NO_STRICMP
404| else if ( key->type == Offset_CStringPI ) {
405| return ArrX_Imp_linearSearchF( m->first, m->last, (int)elem_sizeof,
406| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr );
407| }
408| #endif
409| else {
410| ASSERT( key->type == Offset_CStringPW );
411| #ifdef USES_STRX
412| return ArrX_Imp_linearSearchF( m->first, m->last, (int)elem_sizeof,
413| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask );
414| #else
415| Errors_notSupport();
416| return NULL; /* dummy */
417| #endif
418| }
419|}
420|#endif /* USES_OFFSET */
421|
422|
423|
424|/**************************************************************************
425| 4-16. <<< [ArrX_search_ps_imp] 文字列型のキーを用いて線形検索する >>>
426|・この関数は、ArrX_search_ps マクロの実装部です。
427|***************************************************************************/
428|#ifdef USES_OFFSET
429|void* ArrX_search_ps_imp( ArrX* m, Offset_Key* key, const char* val )
430|{
431| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) );
432|
433| if ( key->type == Offset_CString )
434| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last,
435| val, key->offset, 0, -1 );
436| else if ( key->type == Offset_CStringP ) {
437| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last,
438| val, key->offset, 1, -1 );
439| }
440| #ifndef ARRX_NO_STRICMP
441| else if ( key->type == Offset_CStringPI ) {
442| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last,
443| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr );
444| }
445| #endif
446| else {
447| ASSERT( key->type == Offset_CStringPW );
448| #ifdef USES_STRX
449| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last,
450| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask );
451| #else
452| Errors_notSupport();
453| return NULL; /* dummy */
454| #endif
455| }
456|}
457|#endif /* USES_OFFSET */
458|
459|
460|/**************************************************************************
461| 4-17. <<< [ArrX_doLoopFunc] SYM_STRUCT_LOOP_FUNC に指定する関数 >>>
462|***************************************************************************/
463|#ifdef USES_SYM
464|bool ArrX_doLoopFunc( Sym_Ref* container, Sym_Ref* elem )
465|{
466| ArrX* m;
467|
468| if ( container->type == Sym_StructType ) m = (ArrX*)container->adr;
469| else m = *(ArrX**)container->adr;
470|
471| if ( elem->adr == NULL ) elem->adr = m->first;
472| else {
473| if ( elem->type == Sym_StructTypeP )
474| elem->adr = (void*)( (char*)elem->adr + sizeof(void*) );
475| else
476| elem->adr = (void*)( (char*)elem->adr + (int)container->elem_param );
477| }
478|
479| return elem->adr < m->last;
480|}
481|#endif
482|
483|
484|/*-------------------------------------------------------------------------*/
485|/* ◆5. <<<< バッファ (ArrX_Buf) >>>> */
486|/*-------------------------------------------------------------------------*/
487|
488|#ifdef USES_SYM
489|SYM_STRUCT_START( ArrX_Buf )
490|SYM_STRUCT_LOOP_FUNC( ArrX_Buf, ArrX_Buf_doLoopFunc )
491|SYM_STRUCT_MEMB( ArrX_Buf, void*, first )
492|SYM_STRUCT_MEMB( ArrX_Buf, void*, last )
493|SYM_STRUCT_END( ArrX_Buf )
494|#endif
495|
496|/***********************************************************************
497| 5-1. <<< ツリー構造におけるコンテナ >>>
498|
499|【メモ】(作成中)
500|
501|
502|
503| ツリーにノードを追加する関数とツリーからノードを削除する関数のうち、
504| インターフェイスとして必要な最低限の関数がどれか分析することで
505| より単純で効率のよいコンテナの種類を使うことが出来ます。
506|
507| 入力データにおいて、同じ親のノードが一個所に集まっている
508| (親ノードが所有する子ノードが十分揃っている)(シーケンシャル)
509| かどうかを分析することでも、より単純で効率のよいコンテナの種類を
510| 使うことが出来ます。
511|
512| コンテナは、シーケンシャル・タイプとランダム・タイプがあります。
513| シーケンシャル・タイプは、ArrX と ArrX_Buf の組み合わせ、
514| ランダム・レングス・タイプは ArrX2 コンポーネント(予定)が
515| あります。
516|
517| ツリーのリンク(関連)は、子配列タイプと、子ポインタ・タイプと、
518| 親ポインタ・タイプがあります。
519| ・子配列タイプは、子ノードをメモリ的に連続させる必要があるので、
520| 分配方法に工夫が必要になります。(静的データは除く)
521| シーケンシャル・タイプとランダム・レングス・タイプ
522| ・子ポインタ・タイプは、子ノードをリスト構造でつなげます。
523| ランダム・タイプ(例:ArrayU3)があります。
524| リスト構造でなく、使用/未使用または ID の配列でも構いません。
525| ・親ポインタ・タイプは、親ノードへのポインタを持ちます。
526| ただし、対応づけが逆なので後で検索が必要になります。
527|
528| ノードを削除する関数を決めることで、メモリ管理の配置位置が
529| 決まります。削除するノードのうち、最も子の方のノードには、
530| シーケンシャル・タイプをメンバに持たせます。そして、
531| その親のノードには、ランダム・タイプをメンバに持たせて、
532| 子ノードを削除できるようにします。
533|
534| ノードを削除ではなく再初期化する(再利用する領域を明示的に指定する)
535| 関数を決めた場合、親のノードには、シーケンシャル・タイプを
536| メンバに持たせることが出来ます。ただし、再初期化しても
537| メモリサイズを変更することはできません。変更する場合は、
538| 更に親のノードを削除するか再初期化して、
539| メモリサイズの設定を初めからやり直してください。
540|
541| シーケンシャルでなくても、子ポインタ・タイプや
542| 親ポインタ・タイプの場合、
543| シーケンシャル・タイプをメンバに持たせることが出来ます。
544|
545| 十分性が有れば、更に親の十分性も検討することが出来ます。
546| ランダム・レングス・タイプを使った場合、それより親のノードは
547| 必ずランダム・レングス・タイプにしなければなりません。
548|
549| ノードを追加する関数は、必要に応じて親ノードへの参照や
550| メモリ管理を引数に指定するようにします。
551| ノードを追加する関数の内部では、そのノードより子の方のノード
552| を追加する場合、追加するノードより親の方にあるメモリ管理から
553| 領域を確保します。
554|
555| 対多関連をシーケンシャルにすれば階層ごとにバッファを用意すればよい
556| シーケンシャルは抽象クラスでもよい(クラスIDが必要だが)
557|************************************************************************/
558|
559|
560|
561|/****************************************************************
562| 5-2. <<< [ArrX_Buf_init] 初期化する >>>
563|【補足】
564|・初期化するとバッファは空になります。
565|*****************************************************************/
566|void ArrX_Buf_init( ArrX_Buf* m, void* mem, int mem_sizeof )
567|{
568| ERRORS_INITCHK( m, 0 );
569|
570| m->first = mem;
571| m->last = mem;
572| m->bufLast = (char*)mem + mem_sizeof;
573|
574| ASSERT( ArrX_Buf_chk( m ) );
575|}
576|
577|
578|
579|/****************************************************************
580| 5-3. <<< [ArrX_Buf_inits] 複数のバッファを初期化する >>>
581|【引数】
582| ・void* mem; メモリ領域(サイズは ArrX_Buf_getMemSize より)
583| ・int* ms; 最大要素数が格納されている配列
584| ・int n; 初期化するバッファの数
585| ・... バッファ1、要素サイズ1、バッファ2、要素サイズ2...
586| ・void* 返り値; 使用しなかったメモリ領域の先頭アドレス
587|【補足】
588|・mem を各バッファに割り振ります。
589|・... には、初期化するバッファと要素サイズを複数並べます。
590| バッファは ArrX_Buf* 型、要素サイズは int 型です。
591|・初期化するとバッファは空になります。
592|【例】
593| next = ArrX_Buf_inits( mem, ms, 3,
594| &m->polys, sizeof(Pdo_Poly),
595| &m->materials, sizeof(Pdo_Material),
596| &m->points, sizeof(Pdo_Point) );
597|*****************************************************************/
598|#ifdef STDLIBS_INCLUDE_STDARG_H
599|void* ArrX_Buf_inits( void* mem, int* ms, int n, ... )
600|{
601| int i;
602| va_list va;
603| ArrX_Buf* buf;
604| int size;
605|
606| va_start( va, n );
607|
608| for ( i = 0; i < n; i++ ) {
609| buf = va_arg( va, ArrX_Buf* );
610| size = *ms * va_arg( va, int );
611| ArrX_Buf_init( buf, mem, size );
612| mem = (void*)( (char*)mem + size );
613| ms ++;
614| }
615|
616| va_end( va );
617|
618| return mem;
619|}
620|#endif
621|
622|
623|/****************************************************************
624| 5-4. <<< [ArrX_Buf_getMemSize] 必要なメモリサイズを返す >>>
625|【引数】
626| ・int* ms; 最大要素数が格納されている配列
627| ・int n; 初期化するバッファの数
628| ・... 要素サイズ1、要素サイズ2...
629| ・int 返り値; 必要なメモリサイズ
630|【補足】
631|・ArrX_Buf_inits の引数に指定するメモリ領域に必要なメモリサイズを
632| 計算します。
633|【例】
634| size = ArrX_Buf_getMemSize( ms, 3,
635| sizeof(Pdo_Poly), sizeof(Pdo_Material), sizeof(Pdo_Point) );
636|*****************************************************************/
637|#ifdef STDLIBS_INCLUDE_STDARG_H
638|int ArrX_Buf_getMemSize( int* ms, int n, ... )
639|{
640| int i;
641| int ret = 0;
642| va_list va;
643|
644| va_start( va, n );
645|
646| for ( i = 0; i < n ; i++ ) {
647| ret += va_arg( va, int ) * (*ms);
648| ms++;
649| }
650|
651| va_end( va );
652|
653| return ret;
654|}
655|#endif
656|
657|
658|/****************************************************************
659| 5-5. <<< [ArrX_Buf_chk] 正規チェック >>>
660|*****************************************************************/
661|int ArrX_Buf_chk( ArrX_Buf* m )
662|{
663| ERRORS_INITCHK_FOR_SUB( m, 1 );
664| return m->first <= m->last &&
665| m->first <= m->bufLast &&
666| m->last <= m->bufLast;
667|}
668|
669|
670|/****************************************************************
671| 5-6. <<< [ArrX_Buf_get_imp] 配列番号から要素を返す >>>
672|【引数】
673| ・ArrX* m; 配列
674| ・int i; 配列番号
675| ・int size; 配列要素のサイズ
676|【補足】
677|・リリース時は、マクロ版 ArrX_Buf_get を呼び出します。
678|*****************************************************************/
679|void* ArrX_Buf_get_imp( ArrX_Buf* m, int i, int size )
680|{
681| void* p = (char*)m->first + i * size;
682|
683| ASSERT( p < m->last );
684| ASSERT( ( (char*)m->last - (char*)m->first ) % size == 0 );
685|
686| return p;
687|}
688|
689|
690|
691|/**************************************************************************
692| 5-7. <<< [ArrX_Buf_alloc_imp] 指定サイズのバッファをアロケートする >>>
693|【引数】
694| ・int alloc_sizeof; 要素のサイズ
695| ・void* 返り値; 確保した領域の先頭アドレス
696|【補足】
697|・alloc_sizeof のサイズのメモリ領域を確保(アロケート)して、
698| その先頭アドレスを返します。
699|・アロケートしたら、メモリ領域( m->first から m->bufLast まで)
700| を超えてしまう場合(メモリ不足の場合)、error 関数を呼び出します。
701|・この関数は、ArrX_Buf_alloc マクロの実装部です。
702|***************************************************************************/
703|void* ArrX_Buf_alloc_imp( ArrX_Buf* m, int alloc_sizeof )
704|{
705| void* ret = m->last;
706| void* nextLast = (char*)m->last + alloc_sizeof;
707|
708| ASSERT( ArrX_Buf_chk( m ) );
709| if ( nextLast > m->bufLast ) {
710| #if !defined(NDEBUG) && !defined(ERRORS_CUT_DEBUG_TOOL)
711| ArrX_Buf_printElem( m, char, "" );
712| #endif
713| error2_0( ArrX_Err_Full, "バッファが満杯です" );
714| }
715|
716| /* メモリ領域を確保する */
717| m->last = nextLast;
718|
719| ASSERT( ArrX_Buf_chk( m ) );
720|
721| return ret;
722|}
723|
724|
725|
726|/**************************************************************************
727| 5-8. <<< [ArrX_Buf_allocs_imp] 指定サイズのバッファを複数アロケートする >>>
728|【引数】
729| ・int alloc_sizeof; 要素1つのサイズ
730| ・int nElem; 要素の数
731| ・void* 返り値; 確保した領域の先頭アドレス
732|【補足】
733|・alloc_sizeof * nElem のサイズのメモリ領域を確保(アロケート)して、
734| その先頭アドレスを返します。
735|・アロケートしたら、メモリ領域( m->first から m->bufLast まで)
736| を超えてしまう場合(メモリ不足の場合)、error 関数を呼び出します。
737|・この関数は、ArrX_Buf_allocs マクロの実装部です。
738|***************************************************************************/
739|void* ArrX_Buf_allocs_imp( ArrX_Buf* m, int alloc_sizeof, int nElem )
740|{
741| void* ret = m->last;
742| void* nextLast = (char*)m->last + alloc_sizeof * nElem;
743|
744| ASSERT( ArrX_Buf_chk( m ) );
745| if ( nextLast > m->bufLast )
746| error2_0( ArrX_Err_Full, "バッファが満杯です" );
747|
748| /* メモリ領域を確保する */
749| m->last = nextLast;
750|
751| ASSERT( ArrX_Buf_chk( m ) );
752|
753| return ret;
754|}
755|
756|
757|
758|/****************************************************************
759| 5-9. <<< [ArrX_Buf_addCopy] バッファに追加する >>>
760|【引数】
761| ・ArrX* plus; 追加するデータまたは配列へのポインタ
762|【補足】
763|・plus は、単一のデータでも配列でも構いません。
764|・単一のデータの場合、plus->first = ptr,plus->last = ptr+1 と
765| して引数に渡します。
766|*****************************************************************/
767|void ArrX_Buf_addCopy( ArrX_Buf* m, ArrX* plus )
768|{
769| int plus_size = (char*)plus->last - (char*)plus->first;
770|
771| ASSERT( ArrX_Buf_chk( m ) && ArrX_chk( plus ) );
772| if ( m->last >= m->bufLast ) {
773| char s1[20], s2[20];
774| strncpy( s1, (char*)m->first, sizeof(s1)-1 ); s1[19] = '\0';
775| strncpy( s2, (char*)m->last-19, sizeof(s2)-1 ); s2[19] = '\0';
776| Errors_printf_release( "バッファが満杯です\n%s 〜 %s", s1, s2 );
777| error2_0( ArrX_Err_Full, "バッファが満杯です" );
778| }
779|
780| /* バッファに余裕がある場合、*/
781| if ( (char*)m->last + plus_size <= (char*)m->bufLast ) {
782| memcpy( m->last, plus->first, plus_size );
783| m->last = (void*)((char*)m->last + plus_size);
784| }
785|
786| /* バッファに一部しか入らない場合、*/
787| else {
788| memcpy( m->last, plus->first,
789| (char*)m->bufLast - (char*)m->last );
790| m->last = m->bufLast;
791| }
792|
793| ASSERT( ArrX_Buf_chk( m ) );
794|}
795|
796|
797|
798|/****************************************************************
799| 5-10. <<< [ArrX_Buf_addChr] バッファに1バイト追加する >>>
800|【引数】
801| ・unsigned char c; 追加するデータ
802|*****************************************************************/
803|void ArrX_Buf_addChr( ArrX_Buf* m, unsigned char c )
804|{
805| ASSERT( ArrX_Buf_chk( m ) );
806|
807| /* バッファが満杯の場合、バッファの最後に追加する */
808| if ( m->last == m->bufLast )
809| m->last = (void*)((unsigned char*)m->last - 1);
810|
811| /* バッファに余裕がある場合、*/
812| *(unsigned char*)m->last = c;
813| m->last = (void*)((unsigned char*)m->last + 1);
814|
815| ASSERT( ArrX_Buf_chk( m ) );
816|}
817|
818|
819|
820|/****************************************************************
821| 5-11. <<< [ArrX_Buf_addStr] バッファに文字列を追加する >>>
822|【引数】
823| ・char* s; 追加するデータ
824|【補足】
825|・strcat と同じような機能です。
826|・バッファの内容の最後には、'\0' が付いています。ただし、一度も
827| 本関数を呼ばなかったときは、付いていないので、一度、空文字を
828| 追加しておいてください。
829|*****************************************************************/
830|void ArrX_Buf_addStr( ArrX_Buf* m, const char* s )
831|{
832| int left = (char*)m->bufLast - (char*)m->last;
833| int s_len = strlen( s );
834|
835| if ( s_len < left ) {
836| strcpy( (char*)m->last, s );
837| m->last = (char*)m->last + s_len;
838| }
839| else {
840| *( (char*)m->bufLast - 1 ) = '\0';
841| strncpy( (char*)m->last, s, left - 1 );
842| m->last = m->bufLast;
843| }
844|}
845|
846|
847|/****************************************************************
848| 5-12. <<< [ArrX_Buf_addMem] バッファにデータを追加する >>>
849|【引数】
850| ・char* s; 追加するデータの先頭アドレス
851| ・char* s_size; 追加するデータのサイズ
852|【補足】
853|・strcat と同じような機能ですが、最後(*s_over)に '\0' は付きません。
854|・容量が足りないときは、入れられる分だけ入れます。
855|*****************************************************************/
856|void ArrX_Buf_addMem( ArrX_Buf* m, const void* s,
857| int s_size )
858|{
859| int left = (char*)m->bufLast - (char*)m->last;
860|
861| if ( s_size <= left ) {
862| memcpy( m->last, s, s_size );
863| m->last = (char*)m->last + s_size;
864| }
865| else {
866| memcpy( m->last, s, left );
867| m->last = m->bufLast;
868| }
869|}
870|
871|
872|/*********************************************************************
873| 5-13. <<< [ArrX_Buf_addEndOfC] バッファに文字列の終端文字を追加する >>>
874|【補足】
875|・バッファが満杯の場合、バッファの最後の1バイトに入っていたデータの
876| 代わりに終端文字 '\0' を入れます。
877|**********************************************************************/
878|void ArrX_Buf_addEndOfC( ArrX_Buf* m )
879|{
880| ASSERT( ArrX_Buf_chk( m ) );
881|
882| /* バッファが満杯の場合、*/
883| if ( m->last == m->bufLast ) {
884| *((unsigned char*)m->last - 1) = '\0';
885| }
886|
887| /* バッファに余裕がある場合、*/
888| else {
889| *(unsigned char*)m->last = '\0';
890| m->last = (void*)((unsigned char*)m->last + 1);
891| }
892|
893| ASSERT( ArrX_Buf_chk( m ) );
894|}
895|
896|
897|
898|/**************************************************************************
899| 5-14. <<< [ArrX_Buf_getLast_f_imp] ArrX_Buf_getLast_f の実装部 >>>
900|***************************************************************************/
901|void* ArrX_Buf_getLast_f_imp( ArrX_Buf* m, int size )
902|{
903| ASSERT( m->first != m->last ); /* 要素数が0では使用できません */
904|
905| return (char*)(m->last) - size;
906|}
907|
908|/**************************************************************************
909| 5-15. <<< [ArrX_Buf_free_imp] 指定サイズのバッファを解放する >>>
910|【引数】
911| ・void* p; 解放する領域の先頭アドレス
912| ・int free_sizeof; 要素のサイズ
913|【補足】
914|・新しい領域(末尾)から順番に解放すれば、素早く解放することも出来ます。
915|・領域の途中を開放したときは、その部分より後の領域を手前に詰めます。
916|・この関数は、ArrX_Buf_free マクロの実装部です。
917|***************************************************************************/
918|void ArrX_Buf_free_imp( ArrX_Buf* m, void* p, int free_sizeof )
919|{
920| void* nextLast = (char*)m->last - free_sizeof;
921|
922| ASSERT( ArrX_Buf_chk( m ) );
923|
924| /* メモリの途中を開放する */
925| if ( nextLast != p ) {
926| ASSERT( (char*)p >= (char*)m->first && (char*)p < (char*)m->last );
927| memcpy( p, (char*)p + free_sizeof, (char*)m->last - ((char*)p + free_sizeof) );
928| }
929|
930| /* メモリ領域の末尾を解放する */
931| m->last = nextLast;
932|
933| ASSERT( ArrX_Buf_chk( m ) );
934|}
935|
936|
937|
938|/**************************************************************************
939| 5-16. <<< [ArrX_Buf_search_i_imp] int 型のキーを用いて線形検索する >>>
940|・この関数は、ArrX_Buf_search_i マクロの実装部です。
941|***************************************************************************/
942|#ifdef USES_OFFSET
943|void* ArrX_Buf_search_i_imp( ArrX_Buf* m, Offset_Key* key, int val,
944| int elem_sizeof )
945|{
946| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) );
947| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 );
948|
949| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof,
950| &val, key->offset, 0, sizeof(int) );
951|}
952|#endif /* USES_OFFSET */
953|
954|
955|
956|/**************************************************************************
957| 5-17. <<< [ArrX_Buf_search_d_imp] double 型のキーを用いて線形検索する >>>
958|・この関数は、ArrX_Buf_search_d マクロの実装部です。
959|***************************************************************************/
960|#ifdef USES_OFFSET
961|void* ArrX_Buf_search_d_imp( ArrX_Buf* m, Offset_Key* key, double val,
962| int elem_sizeof )
963|{
964| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) );
965| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 );
966|
967| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof,
968| &val, key->offset, 0, sizeof(double) );
969|}
970|#endif /* USES_OFFSET */
971|
972|
973|
974|/**************************************************************************
975| 5-18. <<< [ArrX_Buf_search_s_imp] ArrX_Buf_search_s マクロの実装部 >>>
976|【補足】
977|・start は、検索を開始する最初の要素です。最初から検索するときは、
978| m->first, 前回の検索結果の続きを検索するときは、p+1(p はポインタ)を
979| 指定します。
980|***************************************************************************/
981|#ifdef USES_OFFSET
982|void* ArrX_Buf_search_s_imp( ArrX_Buf* m, void* start, Offset_Key* key,
983| const char* val, int elem_sizeof )
984|{
985| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) );
986| ASSERT( ( (char*)m->last - (char*)start ) % elem_sizeof == 0 );
987|
988| if ( key->type == Offset_CString )
989| return ArrX_Imp_linearSearch( start, m->last, (int)elem_sizeof,
990| val, key->offset, 0, -1 );
991| else if ( key->type == Offset_CStringP || key->type == Offset_StrV ) {
992| return ArrX_Imp_linearSearch( start, m->last, (int)elem_sizeof,
993| val, key->offset, 1, -1 );
994| }
995| #ifndef ARRX_NO_STRICMP
996| else if ( key->type == Offset_CStringPI ) {
997| return ArrX_Imp_linearSearchF( start, m->last, (int)elem_sizeof,
998| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr );
999| }
1000| #endif
1001| else {
1002| ASSERT( key->type == Offset_CStringPW );
1003| #ifdef USES_STRX
1004| return ArrX_Imp_linearSearchF( start, m->last, (int)elem_sizeof,
1005| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask );
1006| #else
1007| Errors_notSupport();
1008| return NULL; /* dummy */
1009| #endif
1010| }
1011|}
1012|#endif /* USES_OFFSET */
1013|
1014|
1015|
1016|/**************************************************************************
1017| 5-19. <<< [ArrX_Buf_search_ps_imp] 文字列型のキーを用いて線形検索する >>>
1018|・この関数は、ArrX_Buf_search_ps マクロの実装部です。
1019|***************************************************************************/
1020|#ifdef USES_OFFSET
1021|void* ArrX_Buf_search_ps_imp( ArrX_Buf* m, Offset_Key* key, const char* val )
1022|{
1023| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) );
1024|
1025| if ( key->type == Offset_CString )
1026| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last,
1027| val, key->offset, 0, -1 );
1028| else if ( key->type == Offset_CStringP ) {
1029| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last,
1030| val, key->offset, 1, -1 );
1031| }
1032| #ifndef ARRX_NO_STRICMP
1033| else if ( key->type == Offset_CStringPI ) {
1034| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last,
1035| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr );
1036| }
1037| #endif
1038| else {
1039| ASSERT( key->type == Offset_CStringPW );
1040| #ifdef USES_STRX
1041| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last,
1042| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask );
1043| #else
1044| Errors_notSupport();
1045| return NULL; /* dummy */
1046| #endif
1047| }
1048|}
1049|#endif /* USES_OFFSET */
1050|
1051|
1052|/**************************************************************************
1053| 5-20. <<< [ArrX_Buf_print_imp] 内部状態を表示する >>>
1054|***************************************************************************/
1055|#ifndef ERRORS_CUT_DEBUG_TOOL
1056|void ArrX_Buf_print_imp( ArrX_Buf* m, const char* title )
1057|{
1058| ERRORS_INITCHK( m, 1 );
1059|
1060| Errors_printf( "%sArrX_Buf(%p) : first = %p, last = %p, bufLast = %p", title,
1061| m, m->first, m->last, m->bufLast );
1062|}
1063|#endif
1064|
1065|
1066|/**************************************************************************
1067| 5-21. <<< [ArrX_Buf_printElem_imp] 内部状態を表示する >>>
1068|***************************************************************************/
1069|#ifndef ERRORS_CUT_DEBUG_TOOL
1070|void ArrX_Buf_printElem_imp( ArrX_Buf* m, int elem_sizeof, const char* title )
1071|{
1072| int size = (char*)m->last - (char*)m->first;
1073| int bufSize = (char*)m->bufLast - (char*)m->first;
1074|
1075| ERRORS_INITCHK( m, 1 );
1076| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 );
1077|
1078| Errors_printf( "%sArrX_Buf(%p) : first = %p, last = %p, bufLast = %p", title,
1079| m, m->first, m->last, m->bufLast );
1080| if ( elem_sizeof == 1 ) {
1081| Errors_printf( "%ssize = %d/%d", title, size, bufSize );
1082| }
1083| else {
1084| Errors_printf( "%ssize = %d/%d count = %d/%d", title,
1085| size, bufSize, size/elem_sizeof, bufSize/elem_sizeof );
1086| }
1087|}
1088|#endif
1089|
1090|
1091|/**************************************************************************
1092| 5-22. <<< [ArrX_Buf_print2] 配列の要素をデバッグ表示する >>>
1093|【補足】
1094|・詳細は、ArrX_print 関数を参照してください。
1095|***************************************************************************/
1096|#ifdef USES_ERRORS
1097|#ifndef ERRORS_CUT_DEBUG_TOOL
1098|void ArrX_Buf_print2( ArrX_Buf* m, char* types )
1099|{
1100| ArrX arr;
1101|
1102| ArrX_castFrom_ArrX_Buf( &arr, m );
1103| ArrX_print( &arr, types );
1104|}
1105|#endif
1106|#endif
1107|
1108|/**************************************************************************
1109| 5-23. <<< [ArrX_Buf_doLoopFunc] SYM_STRUCT_LOOP_FUNC に指定する関数 >>>
1110|***************************************************************************/
1111|#ifdef USES_SYM
1112|bool ArrX_Buf_doLoopFunc( Sym_Ref* container, Sym_Ref* elem )
1113|{
1114| ArrX_Buf* m;
1115|
1116| if ( container->type == Sym_StructType ) m = (ArrX_Buf*)container->adr;
1117| else m = *(ArrX_Buf**)container->adr;
1118|
1119| if ( elem->adr == NULL ) elem->adr = m->first;
1120| else {
1121| if ( elem->type == Sym_StructTypeP )
1122| elem->adr = (void*)( (char*)elem->adr + sizeof(void*) );
1123| else
1124| elem->adr = (void*)( (char*)elem->adr + (int)container->elem_param );
1125| }
1126|
1127| return elem->adr < m->last;
1128|}
1129|#endif
1130|
1131|
1132|/*-------------------------------------------------------------------------*/
1133|/* ◆6. <<<< (ArrX_Able) 有効フラグ付き配列 >>>> */
1134|/*-------------------------------------------------------------------------*/
1135|
1136|
1137|
1138|/****************************************************************
1139| 6-1. <<< [ArrX_Able_init_imp] 初期化する(すべての要素を無効にする) >>>
1140|【引数】
1141| ・int arr_size; 全要素のデータのサイズ (byte)
1142|【補足】
1143|・ArrX_Able_init の実装部です。(本関数は内部用です)
1144|*****************************************************************/
1145|#ifdef USES_OFFSET
1146|void ArrX_Able_init_imp( ArrX_Able* m, void* arr_adr, int arr_size,
1147| int elem_size, Offset ofsFlag )
1148|{
1149| char* p;
1150| ERRORS_INITCHK( m, 0 );
1151| ASSERT( arr_size % elem_size == 0 );
1152|
1153| ArrX_init( &m->arr, arr_adr, arr_size );
1154|
1155| for ( p = (char*)m->arr.first; p < (char*)m->arr.last;
1156| p += elem_size ) {
1157|
1158| Offset_ref( ofsFlag, p, bool ) = false;
1159| }
1160|}
1161|#endif
1162|
1163|/***********************************************************************
1164| 6-2. <<< [ArrX_Able_getN_imp] 有効な要素数を返す >>>
1165|【補足】
1166|・ArrX_Able_getN の実装部です。(本関数は内部用です)
1167|************************************************************************/
1168|#ifdef USES_OFFSET
1169|int ArrX_Able_getN_imp( ArrX_Able* m, int elem_size, Offset ofsFlag )
1170|{
1171| char* p;
1172| int n = 0;
1173| ERRORS_INITCHK( m, 1 );
1174|
1175| for ( p = (char*)m->arr.first; p < (char*)m->arr.last;
1176| p += elem_size ) {
1177|
1178| if ( Offset_ref( ofsFlag, p, bool ) )
1179| n++;
1180| }
1181|
1182| return n;
1183|}
1184|#endif
1185|
1186|
1187|/***********************************************************************
1188| 6-3. <<< [ArrX_Able_getFirst_imp] 最初の有効な要素を返す >>>
1189|************************************************************************/
1190|#ifdef USES_OFFSET
1191|void* ArrX_Able_getFirst_imp( ArrX_Able* m, int elem_size, Offset ofsFlag )
1192|{
1193| char* p;
1194| ERRORS_INITCHK( m, 1 );
1195|
1196| for ( p = (char*)m->arr.first; p < (char*)m->arr.last;
1197| p += elem_size ) {
1198|
1199| if ( Offset_ref( ofsFlag, p, bool ) )
1200| return (void*)p;
1201| }
1202| return NULL;
1203|}
1204|#endif
1205|
1206|
1207|/***********************************************************************
1208| 6-4. <<< [ArrX_Able_getFirstDis_imp] 最初の無効な要素を返す >>>
1209|************************************************************************/
1210|#ifdef USES_OFFSET
1211|void* ArrX_Able_getFirstDis_imp( ArrX_Able* m, int elem_size, Offset ofsFlag )
1212|{
1213| char* p;
1214| ERRORS_INITCHK( m, 1 );
1215|
1216| for ( p = (char*)m->arr.first; p < (char*)m->arr.last;
1217| p += elem_size ) {
1218|
1219| if ( ! Offset_ref( ofsFlag, p, bool ) )
1220| return (void*)p;
1221| }
1222| error2_0( ArrX_Err_Full, "ArrX_Able が満杯です" );
1223| return NULL; /* dummy */
1224|}
1225|#endif
1226|
1227|
1228|/***********************************************************************
1229| 6-5. <<< [ArrX_Able_forEach_imp] ArrX_Able_forEach用カウントアップ >>>
1230|【引数】
1231| ・void* pp; カウントアップするポインタのアドレス
1232| ・int size; 配列要素サイズ
1233| ・Offset offset; 配列要素の ArrX_Able_flag メンバ変数へのオフセット
1234| ・void* over; カウント・オーバーする配列要素のアドレス
1235|【補足】
1236|・内部用です。
1237|************************************************************************/
1238|#ifdef USES_OFFSET
1239|void ArrX_Able_forEach_imp( void* pp, int size, Offset offset, void* over )
1240|{
1241| char** p = (char**)pp;
1242|
1243| while ( ! Offset_ref( offset, *p, bool ) && *p < (char*)over ) {
1244| *p += size;
1245| }
1246|}
1247|#endif
1248|
1249|
1250|
1251|/***********************************************************************
1252| 6-6. <<< [ArrX_Able_forEachDisabled_imp] ArrX_Able_forEachDisabled用カウントアップ >>>
1253|【引数】
1254| ・void* pp; カウントアップするポインタのアドレス
1255| ・int size; 配列要素サイズ
1256| ・Offset offset; 配列要素の ArrX_Able_flag メンバ変数へのオフセット
1257| ・void* over; カウント・オーバーする配列要素のアドレス
1258|【補足】
1259|・内部用です。
1260|************************************************************************/
1261|#ifdef USES_OFFSET
1262|void ArrX_Able_forEachDisabled_imp( void* pp, int size, Offset offset, void* over )
1263|{
1264| char** p = (char**)pp;
1265|
1266| while ( Offset_ref( offset, *p, bool ) && *p < (char*)over ) {
1267| *p += size;
1268| }
1269|}
1270|#endif
1271|
1272|
1273|
1274|/**************************************************************************
1275| 6-7. <<< [ArrX_Able_search_s_imp] 文字列型のキーを用いて線形検索する >>>
1276|***************************************************************************/
1277|#ifdef USES_OFFSET
1278|void* ArrX_Able_search_s_imp( ArrX_Able* m, Offset_Key* key, const char* val,
1279| int elem_sizeof, Offset elem_ofs )
1280|{
1281| void* ret;
1282| ERRORS_INITCHK( m, 1 );
1283| ASSERT( Offset_Key_chk( key ) );
1284|
1285| for (;;) {
1286| ret = ArrX_search_s_imp( &m->arr, key, val, elem_sizeof );
1287|
1288| /* 有効な要素を返す */
1289| if ( ret == NULL ) return NULL;
1290| if ( Offset_ref( elem_ofs, ret, ArrX_AbleElem ) ) return ret;
1291|
1292| ret = (char*)ret + elem_sizeof;
1293| }
1294|}
1295|#endif
1296|
1297|
1298|/*-------------------------------------------------------------------------*/
1299|/* ◆7. <<<< ソート・バッファ (ArrX_Sort) >>>> */
1300|/*-------------------------------------------------------------------------*/
1301|
1302|
1303|
1304|#ifdef USES_OFFSET
1305|
1306|/**************************************************************************
1307| 7-1. <<< [ArrX_Sort_init] 初期化する >>>
1308|【引数】
1309| ・void** mem; ソート・バッファ(ソート用ワーク領域)
1310| ・int mem_sizeof; mem のメモリサイズ
1311| ・Offset_Key* key; ソート・キー
1312|【補足】
1313|・mem には、void* 型の配列の先頭アドレスを渡します。要素数は、ソートする
1314| 要素の数と等しいかそれ以上にします。
1315|・初期化すると、ソート・バッファは空になります。
1316|***************************************************************************/
1317|#ifdef USES_OFFSET
1318|void ArrX_Sort_init( ArrX_Sort* m, void** mem, int mem_sizeof,
1319| Offset_Key* key )
1320|{
1321| ERRORS_INITCHK( m, 0 );
1322|
1323| ASSERT( Offset_Key_chk( key ) );
1324|
1325| m->first = mem;
1326| m->last = mem;
1327| m->bufLast = (void**)((char*)mem + mem_sizeof);
1328| m->key = key;
1329|
1330| ASSERT( ArrX_Sort_chk( m ) );
1331|}
1332|#endif
1333|
1334|
1335|/**************************************************************************
1336| 7-2. <<< [ArrX_Sort_chk] 正規チェック >>>
1337|【補足】
1338|・ツリー自体の正規チェックはしていません。
1339|***************************************************************************/
1340|#ifdef USES_OFFSET
1341|int ArrX_Sort_chk( ArrX_Sort* m )
1342|{
1343| ERRORS_INITCHK_FOR_SUB( m, 1 );
1344|
1345| return m->first <= m->last &&
1346| m->first < m->bufLast &&
1347| m->last <= m->bufLast &&
1348| Offset_Key_chk( m->key );
1349|}
1350|#endif
1351|
1352|
1353|/**************************************************************************
1354| 7-3. <<< [ArrX_Sort_print] デバッグ表示 >>>
1355|【補足】
1356|・プライオリティ・キューの要素については、データの先頭アドレスとキーの値のみ
1357| 表示します。
1358|***************************************************************************/
1359|#ifndef ERRORS_CUT_DEBUG_TOOL
1360|#ifdef USES_OFFSET
1361|void ArrX_Sort_print( ArrX_Sort* m, const char* title )
1362|{
1363| int width = 1;
1364| int x = 1, y = 1;
1365| void** p;
1366|
1367| Errors_printf( "%sArrX_Sort(%p) nElem=%d, mElem=%d, buf=(%p..%p)",
1368| title, m, m->last - m->first, m->bufLast - m->first,
1369| m->first, m->bufLast );
1370| Offset_Key_print( m->key, title );
1371|
1372| Errors_printf( "%s(1)", title );
1373| for ( p = m->first; p < m->last; p++ ) {
1374| Offset_Key_printData( m->key, *p, title );
1375|
1376| /* ツリーの次の段になったら1行空ける */
1377| x++;
1378| if ( x > width && p < m->last - 1 ) {
1379| x = 1; y++; width *= 2;
1380| Errors_printf( "%s(%d)", title, y );
1381| }
1382| }
1383|}
1384|#endif
1385|#endif
1386|
1387|
1388|
1389|/**************************************************************************
1390| 7-4. <<< [ArrX_Sort_pushPQ] プライオリティ・キューとしてバッファに追加する >>>
1391|【引数】
1392| ・void* plus; 追加するデータへのポインタ
1393|【補足】
1394|・プライオリティ・キューは、配列にすべての要素をプッシュすると、ソートされ
1395| た順番にポップされていきます。
1396|・配列にはデータへのポインタのみ格納されるので、データの有効期限に注意して
1397| ください。
1398|・オーダーは log(N) N:要素数 と高速です。
1399|
1400|【内部補足】
1401|・配列を、親ノード番号が、(i-1)/2、子ノード番号が、i*2+1、i*2+2 になるような
1402| ツリー構造とみなしています。
1403|
1404|
1405|・プッシュすると、すべてのノードのキー値を子ノードのキー値より優先順位が高い
1406| (昇順の場合は値が小さい方、降順の場合は値が大きい方)という部分的なソート
1407| 状態になります。ポップすると最も優先順位の高いものが取り出されます。
1408| つまり、すべての要素をプッシュ(ArrX_Sort_pushPQ)した後、ポップ(
1409| ArrX_Sort_popPQ)していくと、ソートされたデータを最初から取り出すことが
1410| 出来るということです。
1411|【参考】
1412|・C++ STL のプライオリティキューによるハフマンツリーの実装
1413| - Mark R.Nelson - DDJ Japan May.1996 p30
1414|***************************************************************************/
1415|#ifdef USES_OFFSET
1416|void ArrX_Sort_pushPQ( ArrX_Sort* m, void* plus )
1417|{
1418| int i, iParent; /* 処理中の配列番号と、その親ノード(ルート方向) */
1419| void **p, **pParent; /* 処理中の要素のアドレスと、その親ノード */
1420| void* sp;
1421|
1422| ASSERT( ArrX_Sort_chk( m ) );
1423|
1424| /* 配列が満杯なら、追加しない */
1425| if ( m->last == m->bufLast ) {
1426| #ifdef _CHECKER
1427| error();
1428| #endif
1429| return;
1430| }
1431|
1432| /* 要素を配列の最後に追加 */
1433| *m->last = plus;
1434| m->last ++;
1435|
1436| /*「正規化」すべてのノードを、子ノードより優先順位を高くする */
1437| i = m->last - m->first - 1;
1438| p = m->last - 1;
1439| while ( i > 0 ) {
1440| iParent = (i-1) / 2;
1441| pParent = m->first + iParent;
1442|
1443| /* あるノードを親ノードより優先順位を低くする */
1444| if ( Offset_Key_cmp( m->key, *p, *pParent ) > 0 ) {
1445|
1446| /* 親ノードと入れ替える */
1447| sp = *p; *p = *pParent; *pParent = sp;
1448| i = iParent; p = pParent;
1449| }
1450| else {
1451| /* 正規化された */
1452| break;
1453| }
1454| }
1455|
1456| ASSERT( ArrX_Sort_chk( m ) );
1457|}
1458|#endif
1459|
1460|
1461|/**************************************************************************
1462| 7-5. <<< [ArrX_Sort_popPQ] プライオリティ・キューとしてバッファから取り出す >>>
1463|【引数】
1464| ・void* 返り値; 最も優先順位の高い要素のアドレス
1465|【補足】
1466|・返り値として返されたポインタは、配列から取り除かれます。
1467|・キューが空の場合は、エラーになるので、ArrX_Sort_isEmpty 関数で調べて
1468| からこの関数を呼び出してください。
1469|***************************************************************************/
1470|#ifdef USES_OFFSET
1471|void* ArrX_Sort_popPQ( ArrX_Sort* m )
1472|{
1473| int i, iChild; /* 処理中の配列番号と、その子ノードの配列番号の小さい方 */
1474| void **p, **pChild; /* 要素番号 i の要素のアドレスと、同 iChild */
1475| int iLast; /* 最後の配列番号 */
1476| void* ret;
1477| void* sp;
1478|
1479| ASSERT( ArrX_Sort_chk( m ) );
1480|
1481| /* 空の場合 NULL を返す */
1482| ASSERT( m->first != m->last );
1483|
1484| /* 優先順位のいちばん高いノードを ret に格納し、配列から取り除く */
1485| ret = *m->first;
1486| m->last --;
1487| *m->first = *m->last;
1488| iLast = m->last - m->first - 1;
1489|
1490| /*「正規化」すべてのノードを、子ノードより優先順位を高くする */
1491| i = 0; iChild = 1;
1492| p = m->first; pChild = p + 1;
1493| while ( iChild < iLast ) {
1494|
1495| /* 2つの子ノードのうち優先順位の高いものを iChild にする */
1496| if ( Offset_Key_cmp( m->key, *(pChild + 1), *pChild ) > 0 ) {
1497| iChild++; pChild++;
1498| }
1499|
1500| /* あるノードを子ノードより優先順位を高くする */
1501| if ( Offset_Key_cmp( m->key, *p, *pChild ) < 0 ) {
1502|
1503| /* 子ノードと入れ替える */
1504| sp = *p; *p = *pChild; *pChild = sp;
1505| i = iChild; p = pChild;
1506| iChild = i * 2 + 1; pChild = m->first + iChild;
1507| }
1508| else {
1509| /* 正規化された */
1510| ASSERT( ArrX_Sort_chk( m ) );
1511| return ret;
1512| }
1513| }
1514| if ( iChild == iLast ) { /* 子ノードが片方しか無い場合 */
1515| if ( Offset_Key_cmp( m->key, *p, *pChild ) < 0 ) {
1516| /* 子ノードと入れ替える */
1517| sp = *p; *p = *pChild; *pChild = sp;
1518| }
1519| }
1520| ASSERT( ArrX_Sort_chk( m ) );
1521| return ret;
1522|}
1523|#endif
1524|
1525|#endif /* USES_OFFSET */
1526|
1527|/*-------------------------------------------------------------------------*/
1528|/* ◆8. <<<< ハッシュテーブルを用いた辞書 (ArrX_Dic) >>>> */
1529|/*-------------------------------------------------------------------------*/
1530|
1531|#if defined(USES_OFFSET) && defined(USES_STRX)
1532|
1533|/**************************************************************************
1534| 8-1. <<< [ArrX_Dic_init] 初期化する >>>
1535|【引数】
1536| ・int width; ハッシュテーブルの幅
1537| ・ArrX_Buf* subDics; ArrX_Buf 型の配列の先頭アドレス
1538| ・int subDics_sizeof; subDics のメモリサイズ
1539| ・Offset_Key* key; キー、(ワードの位置)
1540| ・void* elems; 配列(辞書要素)の先頭アドレス
1541| ・int elems_sizeof; 配列(辞書要素)のメモリサイズ
1542|***************************************************************************/
1543|void ArrX_Dic_init( ArrX_Dic* m,
1544| int width, ArrX_Buf* subDics, int subDics_sizeof,
1545| Offset_Key* key, void* elems, int elems_sizeof )
1546|{
1547| int i;
1548| void* pElem;
1549| int elem_sizeof = elems_sizeof / width;
1550|
1551| ASSERT( subDics_sizeof / sizeof(ArrX_Buf) == (unsigned int)width );
1552| ASSERT( elems_sizeof >= width );
1553|
1554| /* subDics を初期化する */
1555| m->subDics = subDics;
1556| pElem = elems;
1557| for ( i = 0; i < width; i++ ) {
1558| ArrX_Buf_init( &m->subDics[i], pElem, elem_sizeof );
1559| pElem = (char*)pElem + elem_sizeof;
1560| }
1561|
1562| /* その他の属性を初期化する */
1563| m->width = width;
1564| m->key = key;
1565|}
1566|
1567|
1568|/**************************************************************************
1569| 8-2. <<< [ArrX_Dic_search_imp] 検索する >>>
1570|【引数】
1571| ・char* word; ワード
1572| ・int elem_sizeof; 検索する要素のサイズ
1573| ・void* 返り値; 検索された領域のアドレス、または NULL
1574|【補足】
1575|・指定したワードが辞書に登録されていない場合、NULL を返します。
1576|・この関数は、ArrX_Dic_search マクロの実装部です。
1577|***************************************************************************/
1578|void* ArrX_Dic_search_imp( ArrX_Dic* m, const char* word,
1579| int elem_sizeof )
1580|{
1581| int hash = StrX_getHash( word, m->width );
1582|
1583| return ArrX_Buf_search_s_imp( &m->subDics[hash], m->subDics[hash].first,
1584| m->key, word, elem_sizeof );
1585|}
1586|
1587|
1588|/**************************************************************************
1589| 8-3. <<< [ArrX_Dic_searchNext_imp] ArrX_Dic_searchNext マクロの実装部 >>>
1590|***************************************************************************/
1591|void* ArrX_Dic_searchNext_imp( ArrX_Dic* m, const void* prev,
1592| int elem_sizeof )
1593|{
1594| char* word = Offset_Key_getCharPtr( m->key, (void*)prev );
1595| int hash = StrX_getHash( word, m->width );
1596|
1597| ASSERT( word != NULL );
1598|
1599| return ArrX_Buf_search_s_imp( &m->subDics[hash], (char*)prev + elem_sizeof,
1600| m->key, word, elem_sizeof );
1601|}
1602|
1603|
1604|/**************************************************************************
1605| 8-4. <<< [ArrX_Dic_alloc_imp] ArrX_Dic_alloc マクロの実装部 >>>
1606|***************************************************************************/
1607|void* ArrX_Dic_alloc_imp( ArrX_Dic* m, const char* word,
1608| int alloc_sizeof )
1609|{
1610| int hash = StrX_getHash( word, m->width );
1611|
1612| if ( ArrX_Buf_search_s_imp( &m->subDics[hash], m->subDics[hash].first,
1613| m->key, word, alloc_sizeof ) == NULL ) {
1614| return ArrX_Buf_alloc_imp( &m->subDics[hash], alloc_sizeof );
1615| }
1616| else
1617| return NULL; /* すでに登録されている */
1618|}
1619|
1620|
1621|/**************************************************************************
1622| 8-5. <<< [ArrX_Dic_allocDup_imp] ArrX_Dic_allocDup マクロの実装部 >>>
1623|***************************************************************************/
1624|void* ArrX_Dic_allocDup_imp( ArrX_Dic* m, const char* word,
1625| int alloc_sizeof )
1626|{
1627| int hash = StrX_getHash( word, m->width );
1628|
1629| return ArrX_Buf_alloc_imp( &m->subDics[hash], alloc_sizeof );
1630|}
1631|
1632|
1633|/***********************************************************************
1634| 8-6. <<< [ArrX_Dic_allocFromFile] ファイルから登録する >>>
1635|【引数】
1636| ・ArrX_Dic* m; 辞書
1637| ・char* path; 登録する文字列が書かれたファイル
1638| ・StrX_Mem* mem; 文字列記憶領域
1639|【補足】
1640|・文字列型(char*型)の配列をハッシュテーブルに登録します。
1641|・ファイルのフォーマットは、文字列をスペース系文字(' ','\t','\n')で
1642| 区切るものです。(fscanf と同様)
1643|・テーブルの要素は、構造体ではなく char* 型の固定です。
1644| ですから、キーワードが存在するかどうかの判定しか用途がありません。
1645|・word_size - 1 文字より大きい文字列は、それ以降を切り捨てて登録します。
1646|************************************************************************/
1647|#if defined(USES_FILEX)
1648|#ifndef FOR_WINCE
1649|void ArrX_Dic_allocFromFile( ArrX_Dic* m,
1650| const char* path, StrX_Mem* mem )
1651|{
1652| enum { word_size = 256 };
1653| char word[256];
1654| FILE* file;
1655| char** data;
1656|
1657| file = FileX_open( path, "rt" );
1658|
1659| for (;;) {
1660| fscanf( file, "%s", word );
1661| if ( feof( file ) ) break;
1662| data = ArrX_Dic_alloc( m, word, char* );
1663| if ( data != NULL ) {
1664| *data = StrX_Mem_alloc( mem );
1665| strcpy( *data, word );
1666| }
1667| }
1668| fclose( file );
1669|}
1670|#endif
1671|#endif
1672|
1673|
1674|
1675|/***********************************************************************
1676| 8-7. <<< [ArrX_Dic_print] デバッグ表示する >>>
1677|【引数】
1678| ・int elem_size; 辞書要素のメモリサイズ
1679| ・print; 辞書要素のデバッグ表示をする関数
1680|【補足】
1681|・print は、第1引数が要素へのポインタ、第2引数が title です。
1682|************************************************************************/
1683|#ifndef ERRORS_CUT_DEBUG_TOOL
1684|void ArrX_Dic_print( ArrX_Dic* m, const char* title, int elem_size,
1685| void (*elem_print)(void*,const char*) )
1686|{
1687| ArrX_Buf* buf;
1688| ArrX_Buf* buf_over;
1689| void* pElem;
1690|
1691| Errors_printf( "%sArrX_Dic[%p] width=%d", title, m, m->width );
1692| Offset_Key_print( m->key, title );
1693|
1694| /* 配列要素をデバッグ表示する */
1695| for ( buf = m->subDics, buf_over = m->subDics + m->width;
1696| buf < buf_over; buf++ ) {
1697| Errors_printf( "%s [%d] = %d", title, buf - m->subDics,
1698| ArrX_Buf_getN_imp( buf, elem_size ) );
1699| }
1700|
1701| /* 配列要素をデバッグ表示する */
1702| for ( buf = m->subDics, buf_over = m->subDics + m->width;
1703| buf < buf_over; buf++ ) {
1704| Errors_printf( "%s[%d] = %d ------------------------------",
1705| title, buf - m->subDics,
1706| ArrX_Buf_getN_imp( buf, elem_size ) );
1707| for ( ArrX_Buf_forEach_imp( buf, &pElem, elem_size ) ) {
1708| (*elem_print)( pElem, title );
1709| }
1710| }
1711|}
1712|#endif
1713|
1714|/***********************************************************************
1715| 8-8. <<< [ArrX_Dic_forEachDup_imp] ArrX_Dic_forEachDup の実装部 >>>
1716|************************************************************************/
1717|void* ArrX_Dic_forEach_Dup_next( ArrX_Dic* m, ArrX_DicDupIter* dup,
1718| int elem_size, void* key_elem );
1719|
1720|
1721|bool ArrX_Dic_forEachDup_imp( ArrX_Dic* m, ArrX_DicDupIter* dup, int elem_size )
1722|{
1723| void* key_elem; /* 重複候補の辞書要素 */
1724| char* kword;
1725| void* dup_elem;
1726|
1727| /* 重複キーの候補を key_elem に設定する */
1728| if ( dup->first == NULL ) {
1729| dup->dic = m;
1730| dup->pSubDic = m->subDics;
1731| key_elem = ArrX_Dic_forEach_Dup_next( m, dup, elem_size,
1732| dup->pSubDic->first );
1733| if ( key_elem == NULL ) return false;
1734| }
1735| else {
1736| key_elem = ArrX_Dic_forEach_Dup_next( m, dup, elem_size,
1737| (void*)( (char*)dup->first + elem_size ) );
1738| if ( key_elem == NULL ) return false;
1739| }
1740|
1741| /* 候補 key_elem のキーに一致する要素を検索する */
1742| for (;;) {
1743|
1744| /* dup->pSubDic の中から、キーが候補と一致する要素を検索する */
1745| kword = Offset_Key_getCharPtr( m->key, key_elem );
1746| ASSERT( kword != NULL );
1747|
1748| dup_elem = ArrX_Buf_search_s_imp( dup->pSubDic,
1749| (char*)key_elem + elem_size, /* 候補の次の要素から検索する */
1750| m->key, kword, elem_size );
1751|
1752| /* 見つかったら、それを採用する */
1753| if ( dup_elem != NULL ) {
1754| dup->first = key_elem;
1755| dup->p = NULL;
1756|
1757| return true;
1758| }
1759|
1760| /* 見つからなかったら、次の候補を key_elem に設定する */
1761| key_elem = ArrX_Dic_forEach_Dup_next( m, dup, elem_size,
1762| (void*)( (char*)key_elem + elem_size ) );
1763| if ( key_elem == NULL ) return false;
1764| }
1765|}
1766|
1767|
1768|
1769|/***********************************************************************
1770| 8-9. <<< [ArrX_Dic_forEach_Dup_next] 以前候補になっていない次の重複要素の候補を返す >>>
1771|【引数】
1772| ・void* key_elem; 以前候補になったか分らかない次の重複要素の候補
1773| ・void* 返り値; 以前候補になっていない次の重複要素の候補(NULL=次はない)
1774|************************************************************************/
1775|void* ArrX_Dic_forEach_Dup_next( ArrX_Dic* m, ArrX_DicDupIter* dup,
1776| int elem_size, void* key_elem )
1777|{
1778| char* kword;
1779| void* dup_elem;
1780|
1781| for (;;) {
1782|
1783| if ( key_elem >= dup->pSubDic->last ) {
1784| do {
1785| dup->pSubDic ++;
1786| if ( dup->pSubDic >= m->subDics + m->width ) return NULL;
1787| key_elem = dup->pSubDic->first;
1788| } while ( key_elem >= dup->pSubDic->last );
1789|
1790| return key_elem;
1791| }
1792|
1793| if ( dup->first == NULL ||
1794| strcmp( Offset_Key_getCharPtr( m->key, key_elem ),
1795| Offset_Key_getCharPtr( m->key, dup->first ) ) != 0 ) {
1796|
1797| /* すでに候補に挙がったものでなければ採用する */
1798| kword = Offset_Key_getCharPtr( m->key, key_elem );
1799| ASSERT( kword != NULL );
1800| for ( dup_elem = dup->pSubDic->first;
1801| dup_elem < key_elem;
1802| dup_elem = (void*)( (char*)dup_elem + elem_size ) ) {
1803| if ( strcmp( Offset_Key_getCharPtr( m->key, dup_elem ), kword ) == 0 )
1804| break;
1805| }
1806| if ( dup_elem == key_elem )
1807| return key_elem;
1808| }
1809| key_elem = (void*)( (char*)key_elem + elem_size );
1810| }
1811|}
1812|
1813|/***********************************************************************
1814| 8-10. <<< [ArrX_DicDupIter_forEach_imp] ArrX_DicDupIter_forEach の実装部 >>>
1815|************************************************************************/
1816|bool ArrX_DicDupIter_forEach_imp( ArrX_DicDupIter* dup, int elem_size )
1817|{
1818| char* kword;
1819| void* elem;
1820|
1821| if ( dup->p == NULL )
1822| { dup->p = dup->first; return true; }
1823| else
1824| elem = dup->p;
1825|
1826| kword = Offset_Key_getCharPtr( dup->dic->key, dup->first );
1827| ASSERT( kword != NULL );
1828|
1829| elem = ArrX_Buf_search_s_imp( dup->pSubDic, (char*) elem + elem_size,
1830| dup->dic->key, kword, elem_size );
1831| dup->p = elem;
1832|
1833| return ( elem != NULL );
1834|}
1835|
1836|
1837|#endif /* USES_OFFSET */
1838|
1839|/*-------------------------------------------------------------------------*/
1840|/* ◆9. <<<< ハッシュテーブルを用いた辞書の走査子 (ArrX_DicIter) >>>> */
1841|/*-------------------------------------------------------------------------*/
1842|
1843|
1844|
1845|/**************************************************************************
1846| 9-1. <<< [ArrX_DicIter_init_imp] 走査子を初期化する >>>
1847|【補足】
1848|・この関数は、ArrX_DicIter_init マクロの実装です。
1849|***************************************************************************/
1850|#ifdef USES_STRX
1851|void ArrX_DicIter_init_imp( ArrX_DicIter* m, ArrX_Dic* dic, int size )
1852|{
1853| m->dic = dic;
1854| m->curBuf = dic->subDics;
1855| m->curData = (void*)((char*)m->curBuf->first - size);
1856| m->iBuf = 0;
1857| m->size = size;
1858|}
1859|
1860|#endif /* USES_STRX */
1861|
1862|
1863|
1864|/**************************************************************************
1865| 9-2. <<< [ArrX_DicIter_next_imp] 走査子を次の辞書要素に移動する >>>
1866|【引数】
1867| ・int size; 辞書要素のサイズ
1868| ・int 返り値; 0=正常、1=次の辞書要素は無い
1869|***************************************************************************/
1870|#ifdef USES_STRX
1871|int ArrX_DicIter_next( ArrX_DicIter* m )
1872|{
1873| /* 現在のバッファ curBuf に次の辞書要素が有れば、それを指す */
1874| m->curData = (void*)((char*)m->curData + m->size);
1875| if ( m->curData < m->curBuf->last ) {
1876| return 0;
1877| }
1878|
1879| /* 次の辞書要素が無ければ、辞書要素を持っている次のバッファを指す */
1880| else {
1881| do {
1882| m->curBuf ++;
1883| m->iBuf ++;
1884| if ( m->iBuf == m->dic->width ) return 1;
1885| } while ( m->curBuf->first == m->curBuf->last );
1886| m->curData = m->curBuf->first;
1887| return 0;
1888| }
1889|}
1890|
1891|#endif /* USES_STRX */
1892|
1893|
1894|
1895|/*---------------------------------------------------------------------*/
1896|/* ◆10. <<<< はしごポインタ (ArrX_ArrsPtrI) >>>> */
1897|/*---------------------------------------------------------------------*/
1898|
1899|/***********************************************************************
1900| 10-1. <<< [ArrX_ArrsPtrI_init] 初期化する >>>
1901|【引数】
1902| ・int* arr[]; それぞれの配列のアドレスの配列
1903| ・int arr_n[]; それぞれの配列の要素数の配列
1904| ・int nArr; arr の要素数
1905| ・int iArr; ポインタの初期値(1)(arr の配列番号)
1906| ・int p; ポインタの初期値(2)(arr[iArr] の先頭を0としたアドレス)
1907|************************************************************************/
1908|void ArrX_ArrsPtrI_init( ArrX_ArrsPtrI* m, int* arr[], int arr_n[], int nArr,
1909| int iArr, int p )
1910|{
1911| m->arr = arr; m->arr_n = arr_n; m->nArr = nArr;
1912| ArrX_ArrsPtrI_set( m, iArr, p );
1913|}
1914|
1915|
1916|
1917|/***********************************************************************
1918| 10-2. <<< [ArrX_ArrsPtrI_set] ポインタの値を設定する(ランダム指定)>>>
1919|【引数】
1920| ・int iArr; 配列の番号(要素番号ではない)
1921| ・int p; 配列番号(iArr の先頭を基準とする)
1922|************************************************************************/
1923|void ArrX_ArrsPtrI_set( ArrX_ArrsPtrI* m, int iArr, int p )
1924|{
1925| m->p = m->arr[iArr];
1926| m->iArr = iArr;
1927| m->pOver = m->arr[iArr] + m->arr_n[iArr];
1928|
1929| ArrX_ArrsPtrI_plus( m, p );
1930|}
1931|
1932|
1933|
1934|/***********************************************************************
1935| 10-3. <<< [ArrX_ArrsPtrI_plus] ポインタの演算をする >>>
1936|【引数】
1937| ・int p; 配列番号の増分(正の数のみ)
1938|************************************************************************/
1939|void ArrX_ArrsPtrI_plus( ArrX_ArrsPtrI* m, unsigned int plus )
1940|{
1941| m->p += plus;
1942|
1943| while ( m->p >= m->pOver ) {
1944| m->iArr ++;
1945| m->p = m->arr[m->iArr] + ( m->p - m->pOver );
1946| m->pOver = m->arr[m->iArr] + m->arr_n[m->iArr];
1947| }
1948|}
1949|
1950|
1951|
1952|/*-------------------------------------------------------------------------*/
1953|/* ◆11. <<<< 実装 (ArrX_Imp) >>>> */
1954|/*-------------------------------------------------------------------------*/
1955|
1956|
1957|
1958|/**************************************************************************
1959| 11-1. <<< [ArrX_Imp_linearSearch] 線形検索する(1) >>>
1960|【引数】
1961| ・void* start; 配列の先頭アドレス
1962| ・void* last; 配列の末尾の次のアドレス
1963| ・int elem_size; 要素のサイズ
1964| ・void* key; キーのアドレス
1965| ・int key_offset; 要素中のキーのオフセット
1966| ・int key_type; キーのタイプ(補足を参照)
1967| ・int key_size; キーのサイズ(補足を参照)
1968| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない
1969|【補足】
1970|・key_type は、0=バイナリ か 1=ポインタのどちらかを指定します。
1971|・key_size を -1 にすると、'\0'付き文字列として比較します。
1972|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった
1973| 要素の次の要素のアドレスを指定します。例:(type*)p + 1
1974|***************************************************************************/
1975|void* ArrX_Imp_linearSearch( void* start, void* last, int elem_size,
1976| const void* key, int key_offset, int key_type, int key_size )
1977|{
1978| int flag; /* 比較結果, memcmp 関数と同じ返り値 */
1979| void* elem_key; /* 要素中のキーのアドレス */
1980|
1981| if ( key_type == 0 ) {
1982| if ( key_size >= 0 ) {
1983| while ( start < last ) {
1984| elem_key = ((char*)start + key_offset);
1985| flag = memcmp( elem_key, key, key_size );
1986| if ( flag == 0 ) return start;
1987| start = (char*)start + elem_size;
1988| }
1989| }
1990| else {
1991| while ( start < last ) {
1992| elem_key = ((char*)start + key_offset);
1993| flag = strcmp( (char*)elem_key, (char*)key );
1994| if ( flag == 0 ) return start;
1995| start = (char*)start + elem_size;
1996| }
1997| }
1998| }
1999| else {
2000| if ( key_size >= 0 ) {
2001| while ( start < last ) {
2002| elem_key = *((void**)((char*)start + key_offset));
2003| flag = memcmp( elem_key, key, key_size );
2004| if ( flag == 0 ) return start;
2005| start = (char*)start + elem_size;
2006| }
2007| }
2008| else {
2009| while ( start < last ) {
2010| elem_key = *((void**)((char*)start + key_offset));
2011| flag = strcmp( (char*)elem_key, (char*)key );
2012| if ( flag == 0 ) return start;
2013| start = (char*)start + elem_size;
2014| }
2015| }
2016| }
2017|
2018| return NULL;
2019|}
2020|
2021|
2022|
2023|/**************************************************************************
2024| 11-2. <<< [ArrX_Imp_linearSearchF] 線形検索する(2) >>>
2025|【引数】
2026| ・void* start; 配列の先頭アドレス
2027| ・void* last; 配列の末尾の次のアドレス
2028| ・int elem_size; 要素のサイズ
2029| ・void* key; キーのアドレス
2030| ・int key_offset; 要素中のキーのオフセット
2031| ・void* param; 判定関数に渡す任意のパラメータのアドレス
2032| ・ArrX_CmpF func; 判定関数のアドレス
2033| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない
2034|【補足】
2035|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった
2036| 要素の次の要素のアドレスを指定します。例:(type*)p + 1
2037|***************************************************************************/
2038|void* ArrX_Imp_linearSearchF( void* start, void* last, int elem_size,
2039| const void* key, int key_offset, void* param, ArrX_CmpF func )
2040|{
2041| int flag; /* 比較結果, memcmp 関数と同じ返り値 */
2042| void* elem_key; /* 要素中のキーのアドレス */
2043|
2044| while ( start < last ) {
2045| elem_key = ((char*)start + key_offset);
2046| flag = (*func)( elem_key, (void*)key, param );
2047| if ( flag == 0 ) return start;
2048| start = (char*)start + elem_size;
2049| }
2050| return NULL;
2051|}
2052|
2053|
2054|
2055|/**************************************************************************
2056| 11-3. <<< [ArrX_Imp_linearSearchP] ポインタ配列を線形検索する(1) >>>
2057|【引数】
2058| ・void** start; ポインタ配列の先頭アドレス
2059| ・void** last; ポインタ配列の末尾の次のアドレス
2060| ・void* key; キーのアドレス
2061| ・int key_offset; 要素中のキーのオフセット
2062| ・int key_type; キーのタイプ(補足を参照)
2063| ・int key_size; キーのサイズ(補足を参照)
2064| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない
2065|【補足】
2066|・key_type は、0=バイナリ か 1=ポインタのどちらかを指定します。
2067|・key_size を -1 にすると、'\0'付き文字列として比較します。
2068|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった
2069| 要素の次の要素のアドレスを指定します。例:(type*)p + 1
2070|***************************************************************************/
2071|void* ArrX_Imp_linearSearchP( void** start, void** last,
2072| const void* key, int key_offset, int key_type, int key_size )
2073|{
2074| int flag; /* 比較結果, memcmp 関数と同じ返り値 */
2075| void* elem_key; /* 要素中のキーのアドレス */
2076|
2077| if ( key_type == 0 ) {
2078| if ( key_size >= 0 ) {
2079| while ( start < last ) {
2080| elem_key = ((char*)*start + key_offset);
2081| flag = memcmp( elem_key, key, key_size );
2082| if ( flag == 0 ) return start;
2083| start ++;
2084| }
2085| }
2086| else {
2087| while ( start < last ) {
2088| elem_key = ((char*)*start + key_offset);
2089| flag = strcmp( (char*)elem_key, (char*)key );
2090| if ( flag == 0 ) return start;
2091| start ++;
2092| }
2093| }
2094| }
2095| else {
2096| if ( key_size >= 0 ) {
2097| while ( start < last ) {
2098| elem_key = *((void**)((char*)*start + key_offset));
2099| flag = memcmp( elem_key, key, key_size );
2100| if ( flag == 0 ) return start;
2101| start ++;
2102| }
2103| }
2104| else {
2105| while ( start < last ) {
2106| elem_key = *((void**)((char*)*start + key_offset));
2107| flag = strcmp( (char*)elem_key, (char*)key );
2108| if ( flag == 0 ) return start;
2109| start ++;
2110| }
2111| }
2112| }
2113|
2114| return NULL;
2115|}
2116|
2117|
2118|
2119|/**************************************************************************
2120| 11-4. <<< [ArrX_Imp_linearSearchPF] ポインタ配列を線形検索する(2) >>>
2121|【引数】
2122| ・void** start; ポインタ配列の先頭アドレス
2123| ・void** last; ポインタ配列の末尾の次のアドレス
2124| ・void* key; キーのアドレス
2125| ・int key_offset; 要素中のキーのオフセット
2126| ・void* param; 判定関数に渡す任意のパラメータのアドレス
2127| ・ArrX_CmpF func; 判定関数のアドレス
2128| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない
2129|【補足】
2130|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった
2131| 要素の次の要素のアドレスを指定します。例:(type*)p + 1
2132|***************************************************************************/
2133|void* ArrX_Imp_linearSearchPF( void** start, void** last,
2134| const void* key, int key_offset, void* param, ArrX_CmpF func )
2135|{
2136| int flag; /* 比較結果, memcmp 関数と同じ返り値 */
2137| void* elem_key; /* 要素中のキーのアドレス */
2138|
2139| while ( start < last ) {
2140| elem_key = ((char*)*start + key_offset);
2141| flag = (*func)( elem_key, (void*)key, param );
2142| if ( flag == 0 ) return start;
2143| start ++;
2144| }
2145| return NULL;
2146|}
2147|
2148|
2149|
2150|/**************************************************************************
2151| 11-5. <<< [ArrX_Imp_cmpMatchMask] ワイルドカードによる文字列比較 >>>
2152|【補足】
2153|・StrX_cmpWild 関数を ArrX_Imp_linearSearchF 関数で用いるための
2154| ラッパーです。
2155|***************************************************************************/
2156|#ifdef USES_STRX
2157|int ArrX_Imp_cmpMatchMask( char** a, char* b, void* dummy )
2158|{
2159| return StrX_cmpWild( *a, b );
2160|}
2161|#endif /* USES_STRX */
2162|
2163|/**************************************************************************
2164| 11-6. <<< [ArrX_Imp_cmpIStr] 大文字小文字を区別しない文字列比較 >>>
2165|【補足】
2166|・stricmp 関数を ArrX_Imp_linearSearchF 関数で用いるための
2167|s ラッパーです。
2168|***************************************************************************/
2169|#ifndef ARRX_NO_STRICMP
2170|int ArrX_Imp_cmpIStr( char** a, char* b, void* dummy )
2171|{
2172| return stricmp( *a, b );
2173|}
2174|#endif
2175|
2176|