ARRAYU3.C
[目次 | 関数 | マクロ]
1|/**************************************************************************
2|* 1. <<< 配列使用管理・メモリ領域 (ArrayU3) >>>
3|***************************************************************************/
4|
5|#include "mixer_precomp.h"
6|// #pragma hdrstop ("mixer_precomp")
7|
8|#ifdef USES_MXP_AUTOINC
9|#include <ArrayU3.ah> /* Auto include header, Look at mixer-... folder */
10|#endif
11|
12|#define i_check /* 配列番号チェッカー */
13|
14|
15|
16|/**************************************************************************
17|* 2. <<< [ArrayU3_init] 初期化する >>>
18|*【引数】
19|* ・ArrayU3* m; 「配列使用管理」のアドレス
20|* ・char* p; 「管理配列」の先頭アドレス
21|* ・int elem_size; 配列に含まれる1つの要素(データ)のサイズ
22|* ・int nElem; 配列要素数
23|*【補足】
24|* p に指定する管理配列のサイズは次のように指定します。
25|* 例:
26|* #define elem_size 256
27|* #define nElem 100
28|* char* mem[ ArrayU3_getMemSize( elem_size, nElem ) ];
29|* ArrayU3_init( m, mem, elem_size, nElem );
30|***************************************************************************/
31|void ArrayU3_init( ArrayU3* m, char* p, int elem_size, int nElem )
32|{
33| int i;
34|
35| m->p = p;
36| m->size = elem_size + sizeof(int)*2;
37| m->iUseTop = -1;
38| m->iNoUseTop = 0;
39| m->iNoUseLast = nElem - 1;
40| m->nNoUseButValid = 0;
41|
42| for ( i=0; i < nElem; i++ ) {
43| ((ArrayU3_Elem*) p )->iPrev = i-1;
44| ((ArrayU3_Elem*) p )->iNext = i+1;
45| p += m->size;
46| }
47| ArrayU3_getInElem( m, nElem-1 )->iNext = -1;
48|}
49|
50|
51|
52|/**************************************************************************
53|* 3. <<< [ArrayU3_alloc_imp] 配列要素を確保する >>>
54|*【引数】
55|* ・ArrayU3* m; 「配列使用管理」のアドレス
56|* ・void* 返り値; 確保した配列要素の先頭アドレス
57|***************************************************************************/
58|void* ArrayU3_alloc_imp( ArrayU3* m )
59|{
60| int i;
61|
62| i = ArrayU3_getNoUseTop( m );
63| if ( i == -1 ) error();
64|
65| ArrayU3_use( m, i );
66|
67| return ArrayU3_getElem( m, i, void* );
68|}
69|
70|
71|
72|/**************************************************************************
73|* 4. <<< [ArrayU3_free] 配列要素を解放する >>>
74|*【引数】
75|* ・ArrayU3* m; 「配列使用管理」のアドレス
76|* ・void* elem; 解放する配列要素の先頭アドレス
77|***************************************************************************/
78|void ArrayU3_free( ArrayU3* m, void* elem )
79|{
80| int i;
81|
82| i = ArrayU3_getI( m, (char*)elem );
83| ArrayU3_disuse( m, i );
84|}
85|
86|
87|
88|/**************************************************************************
89|* 5. <<< [ArrayU3_use] 「管理配列要素」を使用状態にする >>>
90|*【引数】
91|* ・ArrayU3* m; 「配列使用管理」のアドレス
92|* ・int i; 使用状態にする「管理配列要素」の番号
93|*【機能】
94|*・「配列使用管理」m の「管理配列要素」(番号 i )を使用状態にします。
95|***************************************************************************/
96|void ArrayU3_use( ArrayU3* m, int i )
97|{
98| /* 使用状態にする「管理配列要素」p を取得する */
99| ArrayU3_Elem* p = ArrayU3_getInElem( m, i );
100|
101| ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
102|
103| /* p が使用状態なら、そのまま関数を抜ける */
104| if ( ArrayU3_isUse( m, i ) ) return;
105|
106| /* p を未使用状態のリストから外す */
107| {
108| /* p がリストの先頭なら、*/
109| /* p の次の「管理配列要素」を未使用状態のリストの先頭にする */
110| if ( p->iPrev == -1 ) m->iNoUseTop = p->iNext;
111|
112| /* p の両隣の「管理配列要素」をつなぐ */
113| else
114| ArrayU3_getInElem( m, p->iPrev ) -> iNext = p->iNext;
115|
116| if ( p->iNext >= 0 )
117| ArrayU3_getInElem( m, p->iNext ) -> iPrev = p->iPrev;
118|
119| /* p の前の「管理配列要素」を未使用状態のリストの末尾にする */
120| else
121| m->iNoUseLast = p->iPrev;
122|
123| /* 未使用状態の「管理配列要素」の数を減らす */
124| m->nNoUseButValid --;
125| }
126|
127| /* p を使用状態のリストに入れる */
128| if ( m->iUseTop != -1 )
129| ArrayU3_getInElem( m, m->iUseTop ) -> iPrev = i;
130| p->iNext = m->iUseTop;
131| p->iPrev = -1;
132| m->iUseTop = i;
133|}
134|
135|
136|
137|/**************************************************************************
138|* 6. <<< [ArrayU3_useTop] 最も古い「管理配列要素」を使用状態にする >>>
139|*【機能】
140|*・最も古い未使用状態の「管理配列要素」を使用状態にします。
141|*【引数】
142|* ・ArrayU3* m; 「配列使用管理」のアドレス
143|*【補足】
144|*・使用条件:未使用要素があること。m->iNoUseTop != -1 ならあります。
145|*・ArrayU3_use 関数より高速です。
146|*・使用状態にする「管理配列要素」は、関数を呼んだ後で知る方法が無いので、
147|* この関数を呼ぶ前に ArrayU3_getTop 関数で取得すること。
148|***************************************************************************/
149|void ArrayU3_useTop( ArrayU3* m )
150|{
151| /* 使用状態にする「管理配列要素」p(番号 i)を取得する */
152| int i = m->iNoUseTop;
153| ArrayU3_Elem* p = ArrayU3_getInElem( m, i );
154|
155| /* p を未使用状態のリストから外す */
156| m->iNoUseTop = p->iNext;
157| if ( p->iNext >= 0 )
158| ArrayU3_getInElem( m, p->iNext ) -> iPrev = -1;
159| else
160| m->iNoUseLast = -1;
161|
162| /* p を使用状態のリストに入れる */
163| if ( m->iUseTop != -1 )
164| ArrayU3_getInElem( m, m->iUseTop ) -> iPrev = i;
165| p->iNext = m->iUseTop;
166| p->iPrev = -1;
167| m->iUseTop = i;
168|}
169|
170|
171|
172|/**************************************************************************
173|* 7. <<< [ArrayU3_disuse]「管理配列要素」を未使用状態にする >>>
174|*【引数】
175|* ・ArrayU3* m; 「配列使用管理」のアドレス
176|* ・int i; 未使用状態にする「管理配列要素」の番号
177|***************************************************************************/
178|void ArrayU3_disuse( ArrayU3* m, int i )
179|{
180| /* 未使用状態にする「管理配列要素」p を取得する */
181| ArrayU3_Elem* p = ArrayU3_getInElem( m, i );
182|
183| ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
184|
185| /* p が未使用状態のなら、そのまま関数を抜ける */
186| if ( ! ArrayU3_isUse( m, i ) ) return;
187|
188| /* p を使用状態のリストから外す */
189| {
190| /* p がリストの先頭なら、*/
191| /* p の次の「管理配列要素」を使用状態のリストの先頭にする */
192| if ( p->iPrev == -1 ) m->iUseTop = p->iNext;
193|
194| /* p の両隣の「管理配列要素」をつなぐ */
195| else
196| ArrayU3_getInElem( m, p->iPrev ) -> iNext = p->iNext;
197|
198| if ( p->iNext >= 0 )
199| ArrayU3_getInElem( m, p->iNext ) -> iPrev = p->iPrev;
200| }
201|
202| /* p を未使用状態のリストの末尾に入れる */
203| if ( m->iNoUseLast == -1 )
204| m->iNoUseTop = i;
205| else
206| ArrayU3_getInElem( m, m->iNoUseLast ) -> iNext = i;
207| p->iPrev = m->iNoUseLast;
208| p->iNext = -1;
209| m->iNoUseLast = i;
210| m->nNoUseButValid ++;
211|}
212|
213|
214|
215|/**************************************************************************
216|* 8. <<< [ArrayU3_getPElem]「配列要素」のアドレスを返す >>>
217|*【補足】
218|*・ユーザは、このアドレスの配列要素にアクセスします。
219|***************************************************************************/
220|char* ArrayU3_getPElem( ArrayU3* m, int i )
221|{
222| ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
223|
224| /*「管理配列要素」に含まれる「配列要素」のアドレスを返す */
225| return (char*)ArrayU3_getInElem(m, i) + 2*sizeof(int);
226|}
227|
228|
229|
230|/**************************************************************************
231|* 9. <<< [ArrayU3_getNext] リストの次の「管理配列要素」の番号を返す >>>
232|*【機能】
233|*・使用状態(または未使用状態)のリストの次の「管理配列要素」の番号を返します。
234|*【引数】
235|* ・ArrayU3* m; 「配列使用管理」のアドレス
236|* ・int i; 基準となる「管理配列要素」の番号
237|* ・int 返り値; 次の「管理配列要素」の番号
238|*【補足】
239|*・次の「管理配列要素」の番号が無い場合は -1 を返します。
240|***************************************************************************/
241|int ArrayU3_getNext( ArrayU3* m, int i )
242|{
243| return ArrayU3_getInElem( m, i ) -> iNext;
244|}
245|
246|
247|
248|/**************************************************************************
249|* 10. <<< [ArrayU3_getPrev] リストの前の「管理配列要素」の番号を返す >>>
250|*【機能】
251|*・使用状態(または未使用状態)のリストの前の「管理配列要素」の番号を返します。
252|*【引数】
253|* ・ArrayU3* m; 「配列使用管理」のアドレス
254|* ・int i; 基準となる「管理配列要素」の番号
255|* ・int 返り値; 前の「管理配列要素」の番号
256|*【補足】
257|*・前の「管理配列要素」の番号が無い場合は -1 を返します。
258|***************************************************************************/
259|int ArrayU3_getPrev( ArrayU3* m, int i )
260|{
261| ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
262|
263| return ArrayU3_getInElem( m, i ) -> iPrev;
264|}
265|
266|
267|
268|/**************************************************************************
269|* 11. <<< [ArrayU3_getI]「配列要素」のアドレスから「配列要素」番号を返す >>>
270|***************************************************************************/
271|int ArrayU3_getI( ArrayU3* m, char* elem )
272|{
273| char* InElem = (char*)elem - 2*sizeof(int); /*「管理配列要素」のアド */
274|
275| return (InElem - m->p) / m->size;
276|}
277|
278|
279|
280|/**************************************************************************
281|* 12. <<< [ArrayU3_isUse]「管理配列要素」が使用状態かどうかを返す >>>
282|*【引数】
283|* ・ArrayU3* m; 「配列使用管理」のアドレス
284|* ・int i; 使用状態を確認する「管理配列要素」の番号
285|* ・bool 返り値; 1=使用状態, 0=未使用状態
286|*【補足】
287|*・リストの先頭までたどっていくので、比較的処理が遅くなります。
288|***************************************************************************/
289|bool ArrayU3_isUse( ArrayU3* m, int i )
290|{
291| /* 使用状態を確認する「管理配列要素」p を取得する */
292| ArrayU3_Elem* p = ArrayU3_getInElem( m, i );
293|
294| ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
295|
296| /* p を使用状態(または未使用状態)のリストの先頭に移動する */
297| while ( p->iPrev != -1 ) {
298| p = ArrayU3_getInElem( m, p->iPrev );
299| }
300|
301| /* p が使用状態のリストの先頭かどうかを返す */
302| return p == ArrayU3_getInElem( m, m->iUseTop );
303|}
304|
305|
306|
307|/**************************************************************************
308|* 13. <<< [ArrayU3_getNElem] 配列要素数を返す >>>
309|***************************************************************************/
310|int ArrayU3_getNElem( ArrayU3* m )
311|{
312| int i;
313|
314| /* n を 0 に初期化する */
315| int n = 0;
316|
317| /* 未使用状態の「管理配列要素」の数を n に加算する */
318| i = ArrayU3_getNoUseTop( m );
319| while ( i != -1 ) {
320| n++;
321| i = ArrayU3_getNext( m, i );
322| }
323|
324| /* 使用状態の「管理配列要素」の数を n に加算する */
325| i = ArrayU3_getUseTop( m );
326| while ( i != -1 ) {
327| n++;
328| i = ArrayU3_getNext( m, i );
329| }
330|
331| return n;
332|}
333|
334|
335|
336|/**************************************************************************
337|* 14. <<< [ArrayU3_watch] ウォッチ(デバッグ用)>>>
338|***************************************************************************/
339|#ifdef USES_WATCH
340|void ArrayU3_watch( ArrayU3* m )
341|{
342| int i;
343| int nElem = ArrayU3_getNElem( m );
344|
345| for ( i = 0; i < nElem; i++ ) {
346|
347| /* 要素番号と使用状態をウォッチ */
348| watch( i, ArrayU3_isUse( m, i ) );
349|
350| /* 配列要素の先頭の4バイトと、そのアドレスをウォッチ */
351| watch( ArrayU3_getElem( m, i, int ),
352| (int)ArrayU3_getPElem( m, i ) );
353| }
354|}
355|#endif /* USES_WATCH */
356|
357|
358|
359|/**************************************************************************
360|* 15. <<< [ArrayU3_print] 表示(デバッグ用)>>>
361|*【機能】
362|*・使用状態と未使用状態のリスト構造をたどり、
363|* 各要素のアドレスを表示します。
364|***************************************************************************/
365|#ifdef FOR_DOS16
366|void ArrayU3_print( ArrayU3* m )
367|{
368| int i;
369|
370| /* 使用状態の「配列要素」のアドレスを先頭から列挙表示する */
371| printf( "status=USE ... " );
372| i = m->iUseTop;
373| while ( i != -1 ) {
374| printf( "%p, ", ArrayU3_getPElem( m, i ) );
375| i = ArrayU3_getNext( m, i );
376| }
377| printf( "\n" );
378|
379| /* 未使用状態の「配列要素」のアドレスを先頭から列挙表示する */
380| printf( "status=NOUSE ... " );
381| i = m->iNoUseTop;
382| while ( i != -1 ) {
383| printf( "%p, ", ArrayU3_getPElem( m, i ) );
384| i = ArrayU3_getNext( m, i );
385| }
386| printf( "\n" );
387|}
388|#endif /* FOR_DOS16 */
389|
390|
391|
392|/**************************************************************************
393|* 16. <<< [ArrayU3_print2] 表示(デバッグ用)>>>
394|*【引数】
395|* ・int n; 要素数、-1 にすると自動的に計算
396|*【機能】
397|*・iUseTop, iNoUseTop, iNoUseLast の値を表示します。
398|*・配列番号 0 から n-1 の要素のアドレスと、前後の番号を表示します。
399|*【補足】
400|*・n を -1 にすると、ArrayU3_getNElem 関数の返り値を n に設定しますが、
401|* その関数が異常なら、1つの要素も表示できないことがあります。
402|***************************************************************************/
403|#ifdef FOR_DOS16
404|void ArrayU3_print2( ArrayU3* m, int n )
405|{
406| int i;
407|
408| /* iUseTop, iNoUseTop, iNoUseLast の値を表示する */
409| printf( "iUseTop = %d, iNoUseTop = %d, iNoUseLast = %d\n",
410| m->iUseTop, m->iNoUseTop, m->iNoUseLast );
411|
412| /* もし n == -1 なら要素数 n を計算する */
413| if ( n == -1 )
414| n = ArrayU3_getNElem( m );
415|
416| /* すべての要素のアドレスと、前後の番号を表示する */
417| for ( i = 0; i < n; i++ ) {
418| ArrayU3_Elem* inElem;
419|
420| printf( " [%d]", i );
421| printf( "%p ", ArrayU3_getPElem( m, i ) );
422|
423| inElem = ArrayU3_getInElem( m, i );
424| printf( "prev=%d ", inElem->iPrev );
425| printf( "next=%d \n", inElem->iNext );
426| }
427| printf( "\n" );
428|}
429|#endif /* FOR_DOS16 */
430|
431|
432|
433|