* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Memory.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Memory.c\r
79 // メモリ管理プログラム\r
80 \r
81 #include <stdio.h>\r
82 #include <stdlib.h>\r
83 #include <string.h>\r
84 #include <wchar.h>\r
85 #include <stdarg.h>\r
86 #include <time.h>\r
87 #include <errno.h>\r
88 #include <zlib/zlib.h>\r
89 #include <Mayaqua/Mayaqua.h>\r
90 \r
91 #define MEMORY_SLEEP_TIME               150\r
92 #define MEMORY_MAX_RETRY                30\r
93 #define INIT_BUF_SIZE                   10240\r
94 \r
95 #define FIFO_INIT_MEM_SIZE              4096\r
96 #define FIFO_REALLOC_MEM_SIZE   (65536 * 10)    // 絶妙な値\r
97 #define FIFO_REALLOC_MEM_SIZE_SMALL     65536\r
98 \r
99 #define INIT_NUM_RESERVED               32\r
100 static UINT fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;\r
101 \r
102 // バイナリを検索\r
103 UINT SearchBin(void *data, UINT data_start, UINT data_size, void *key, UINT key_size)\r
104 {\r
105         UINT i;\r
106         // 引数チェック\r
107         if (data == NULL || key == NULL || key_size == 0 || data_size == 0 ||\r
108                 (data_start >= data_size) || (data_start + key_size > data_size))\r
109         {\r
110                 return INFINITE;\r
111         }\r
112 \r
113         for (i = data_start;i < (data_size - key_size + 1);i++)\r
114         {\r
115                 UCHAR *p = ((UCHAR *)data) + i;\r
116 \r
117                 if (Cmp(p, key, key_size) == 0)\r
118                 {\r
119                         return i;\r
120                 }\r
121         }\r
122 \r
123         return INFINITE;\r
124 }\r
125 \r
126 // すぐにクラッシュする\r
127 void CrashNow()\r
128 {\r
129         // これでとりあえずどのような OS 上でもプロセスは落ちるはずである\r
130         while (true)\r
131         {\r
132                 UINT r = Rand32();\r
133                 UCHAR *c = (UCHAR *)r;\r
134 \r
135                 *c = Rand8();\r
136         }\r
137 }\r
138 \r
139 // バッファを候補に変換\r
140 LIST *BufToCandidate(BUF *b)\r
141 {\r
142         LIST *o;\r
143         UINT i;\r
144         UINT num;\r
145         // 引数チェック\r
146         if (b == NULL)\r
147         {\r
148                 return NULL;\r
149         }\r
150 \r
151         num = ReadBufInt(b);\r
152         o = NewCandidateList();\r
153 \r
154         for (i = 0;i < num;i++)\r
155         {\r
156                 CANDIDATE *c;\r
157                 wchar_t *s;\r
158                 UINT64 sec64;\r
159                 UINT len, size;\r
160                 sec64 = ReadBufInt64(b);\r
161                 len = ReadBufInt(b);\r
162                 if (len >= 65536)\r
163                 {\r
164                         break;\r
165                 }\r
166                 size = (len + 1) * 2;\r
167                 s = ZeroMalloc(size);\r
168                 if (ReadBuf(b, s, size) != size)\r
169                 {\r
170                         Free(s);\r
171                         break;\r
172                 }\r
173                 else\r
174                 {\r
175                         c = ZeroMalloc(sizeof(CANDIDATE));\r
176                         c->LastSelectedTime = sec64;\r
177                         c->Str = s;\r
178                         Add(o, c);\r
179                 }\r
180         }\r
181 \r
182         Sort(o);\r
183         return o;\r
184 }\r
185 \r
186 // 候補をバッファに変換\r
187 BUF *CandidateToBuf(LIST *o)\r
188 {\r
189         BUF *b;\r
190         UINT i;\r
191         // 引数チェック\r
192         if (o == NULL)\r
193         {\r
194                 return NULL;\r
195         }\r
196 \r
197         b = NewBuf();\r
198         WriteBufInt(b, LIST_NUM(o));\r
199         for (i = 0;i < LIST_NUM(o);i++)\r
200         {\r
201                 CANDIDATE *c = LIST_DATA(o, i);\r
202                 WriteBufInt64(b, c->LastSelectedTime);\r
203                 WriteBufInt(b, UniStrLen(c->Str));\r
204                 WriteBuf(b, c->Str, UniStrSize(c->Str));\r
205         }\r
206 \r
207         SeekBuf(b, 0, 0);\r
208 \r
209         return b;\r
210 }\r
211 \r
212 // 候補の追加\r
213 void AddCandidate(LIST *o, wchar_t *str, UINT num_max)\r
214 {\r
215         UINT i;\r
216         bool exists;\r
217         // 引数チェック\r
218         if (o == NULL || str == NULL)\r
219         {\r
220                 return;\r
221         }\r
222         if (num_max == 0)\r
223         {\r
224                 num_max = 0x7fffffff;\r
225         }\r
226 \r
227         // 文字列コピー\r
228         str = UniCopyStr(str);\r
229         UniTrim(str);\r
230 \r
231         exists = false;\r
232         for (i = 0;i < LIST_NUM(o);i++)\r
233         {\r
234                 CANDIDATE *c = LIST_DATA(o, i);\r
235                 if (UniStrCmpi(c->Str, str) == 0)\r
236                 {\r
237                         // 既存のものを発見したので時刻を更新する\r
238                         c->LastSelectedTime = SystemTime64();\r
239                         exists = true;\r
240                         break;\r
241                 }\r
242         }\r
243 \r
244         if (exists == false)\r
245         {\r
246                 // 新しく挿入する\r
247                 CANDIDATE *c = ZeroMalloc(sizeof(CANDIDATE));\r
248                 c->LastSelectedTime = SystemTime64();\r
249                 c->Str = UniCopyStr(str);\r
250                 Insert(o, c);\r
251         }\r
252 \r
253         // 文字列解放\r
254         Free(str);\r
255 \r
256         // 現在の候補数を調べて、num_max より多ければ\r
257         // 古いものから順に削除する\r
258         if (LIST_NUM(o) > num_max)\r
259         {\r
260                 while (LIST_NUM(o) > num_max)\r
261                 {\r
262                         UINT index = LIST_NUM(o) - 1;\r
263                         CANDIDATE *c = LIST_DATA(o, index);\r
264                         Delete(o, c);\r
265                         Free(c->Str);\r
266                         Free(c);\r
267                 }\r
268         }\r
269 }\r
270 \r
271 // 候補の比較\r
272 int ComapreCandidate(void *p1, void *p2)\r
273 {\r
274         CANDIDATE *c1, *c2;\r
275         if (p1 == NULL || p2 == NULL)\r
276         {\r
277                 return 0;\r
278         }\r
279         c1 = *(CANDIDATE **)p1;\r
280         c2 = *(CANDIDATE **)p2;\r
281         if (c1 == NULL || c2 == NULL)\r
282         {\r
283                 return 0;\r
284         }\r
285         if (c1->LastSelectedTime > c2->LastSelectedTime)\r
286         {\r
287                 return -1;\r
288         }\r
289         else if (c1->LastSelectedTime < c2->LastSelectedTime)\r
290         {\r
291                 return 1;\r
292         }\r
293         else\r
294         {\r
295                 return UniStrCmpi(c1->Str, c2->Str);\r
296         }\r
297 }\r
298 \r
299 // 候補リストの解放\r
300 void FreeCandidateList(LIST *o)\r
301 {\r
302         UINT i;\r
303         // 引数チェック\r
304         if (o == NULL)\r
305         {\r
306                 return;\r
307         }\r
308 \r
309         for (i = 0;i < LIST_NUM(o);i++)\r
310         {\r
311                 CANDIDATE *c = LIST_DATA(o, i);\r
312                 Free(c->Str);\r
313                 Free(c);\r
314         }\r
315 \r
316         ReleaseList(o);\r
317 }\r
318 \r
319 // 新しい候補リストの作成\r
320 LIST *NewCandidateList()\r
321 {\r
322         return NewList(ComapreCandidate);\r
323 }\r
324 \r
325 // 指定したアドレスがすべてゼロかどうか調べる\r
326 bool IsZero(void *data, UINT size)\r
327 {\r
328         UINT i;\r
329         UCHAR *c = (UCHAR *)data;\r
330         // 引数チェック\r
331         if (data == NULL || size == 0)\r
332         {\r
333                 return true;\r
334         }\r
335 \r
336         for (i = 0;i < size;i++)\r
337         {\r
338                 if (c[i] != 0)\r
339                 {\r
340                         return false;\r
341                 }\r
342         }\r
343 \r
344         return true;\r
345 }\r
346 \r
347 // データを展開する\r
348 UINT Uncompress(void *dst, UINT dst_size, void *src, UINT src_size)\r
349 {\r
350         unsigned long dst_size_long = dst_size;\r
351         // 引数チェック\r
352         if (dst == NULL || dst_size_long == 0 || src == NULL)\r
353         {\r
354                 return 0;\r
355         }\r
356 \r
357         if (uncompress(dst, &dst_size_long, src, src_size) != Z_OK)\r
358         {\r
359                 return 0;\r
360         }\r
361 \r
362         return (UINT)dst_size_long;\r
363 }\r
364 \r
365 // データを圧縮する\r
366 UINT Compress(void *dst, UINT dst_size, void *src, UINT src_size)\r
367 {\r
368         return CompressEx(dst, dst_size, src, src_size, Z_DEFAULT_COMPRESSION);\r
369 }\r
370 \r
371 // データをオプション付きで圧縮する\r
372 UINT CompressEx(void *dst, UINT dst_size, void *src, UINT src_size, UINT level)\r
373 {\r
374         unsigned long dst_size_long = dst_size;\r
375         // 引数チェック\r
376         if (dst == NULL || dst_size_long == 0 || src == NULL)\r
377         {\r
378                 return 0;\r
379         }\r
380 \r
381         if (compress2(dst, &dst_size_long, src, src_size, (int)level) != Z_OK)\r
382         {\r
383                 return 0;\r
384         }\r
385 \r
386         return dst_size_long;\r
387 }\r
388 \r
389 // src_size データを圧縮した場合の最大サイズを取得する\r
390 UINT CalcCompress(UINT src_size)\r
391 {\r
392         // あっ これは いい加減!\r
393         return src_size * 2 + 100;\r
394 }\r
395 \r
396 // スタックの作成\r
397 SK *NewSk()\r
398 {\r
399         return NewSkEx(false);\r
400 }\r
401 SK *NewSkEx(bool no_compact)\r
402 {\r
403         SK *s;\r
404 \r
405         s = Malloc(sizeof(SK));\r
406         s->lock = NewLock();\r
407         s->ref = NewRef();\r
408         s->num_item = 0;\r
409         s->num_reserved = INIT_NUM_RESERVED;\r
410         s->p = Malloc(sizeof(void *) * s->num_reserved);\r
411         s->no_compact = no_compact;\r
412 \r
413 #ifndef DONT_USE_KERNEL_STATUS\r
414         TrackNewObj(POINTER_TO_UINT64(s), "SK", 0);\r
415 #endif  // DONT_USE_KERNEL_STATUS\r
416 \r
417         // KS\r
418         KS_INC(KS_NEWSK_COUNT);\r
419 \r
420         return s;\r
421 }\r
422 \r
423 // スタックの解放\r
424 void ReleaseSk(SK *s)\r
425 {\r
426         // 引数チェック\r
427         if (s == NULL)\r
428         {\r
429                 return;\r
430         }\r
431 \r
432         if (Release(s->ref) == 0)\r
433         {\r
434                 CleanupSk(s);\r
435         }\r
436 }\r
437 \r
438 // スタックのクリーンアップ\r
439 void CleanupSk(SK *s)\r
440 {\r
441         // 引数チェック\r
442         if (s == NULL)\r
443         {\r
444                 return;\r
445         }\r
446 \r
447         // メモリ解放\r
448         Free(s->p);\r
449         DeleteLock(s->lock);\r
450         Free(s);\r
451 \r
452 #ifndef DONT_USE_KERNEL_STATUS\r
453         TrackDeleteObj(POINTER_TO_UINT64(s));\r
454 #endif  // DONT_USE_KERNEL_STATUS\r
455 \r
456         // KS\r
457         KS_INC(KS_FREESK_COUNT);\r
458 }\r
459 \r
460 // スタックのロック\r
461 void LockSk(SK *s)\r
462 {\r
463         // 引数チェック\r
464         if (s == NULL)\r
465         {\r
466                 return;\r
467         }\r
468 \r
469         Lock(s->lock);\r
470 }\r
471 \r
472 // スタックのロック解除\r
473 void UnlockSk(SK *s)\r
474 {\r
475         // 引数チェック\r
476         if (s == NULL)\r
477         {\r
478                 return;\r
479         }\r
480 \r
481         Unlock(s->lock);\r
482 }\r
483 \r
484 // スタックの Push\r
485 void Push(SK *s, void *p)\r
486 {\r
487         UINT i;\r
488         // 引数チェック\r
489         if (s == NULL || p == NULL)\r
490         {\r
491                 return;\r
492         }\r
493 \r
494         i = s->num_item;\r
495         s->num_item++;\r
496 \r
497         // サイズ拡大\r
498         if (s->num_item > s->num_reserved)\r
499         {\r
500                 s->num_reserved = s->num_reserved * 2;\r
501                 s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);\r
502         }\r
503         s->p[i] = p;\r
504 \r
505         // KS\r
506         KS_INC(KS_PUSH_COUNT);\r
507 }\r
508 \r
509 // スタックの Pop\r
510 void *Pop(SK *s)\r
511 {\r
512         void *ret;\r
513         // 引数チェック\r
514         if (s == NULL)\r
515         {\r
516                 return NULL;\r
517         }\r
518         if (s->num_item == 0)\r
519         {\r
520                 return NULL;\r
521         }\r
522         ret = s->p[s->num_item - 1];\r
523         s->num_item--;\r
524 \r
525         // サイズ縮小\r
526         if (s->no_compact == false)\r
527         {\r
528                 // no_compact が true の場合は縮小しない\r
529                 if ((s->num_item * 2) <= s->num_reserved)\r
530                 {\r
531                         if (s->num_reserved >= (INIT_NUM_RESERVED * 2))\r
532                         {\r
533                                 s->num_reserved = s->num_reserved / 2;\r
534                                 s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);\r
535                         }\r
536                 }\r
537         }\r
538 \r
539         // KS\r
540         KS_INC(KS_POP_COUNT);\r
541 \r
542         return ret;\r
543 }\r
544 \r
545 // 1 つ取得\r
546 void *GetNext(QUEUE *q)\r
547 {\r
548         void *p = NULL;\r
549         // 引数チェック\r
550         if (q == NULL)\r
551         {\r
552                 return NULL;\r
553         }\r
554 \r
555         if (q->num_item == 0)\r
556         {\r
557                 // アイテム無し\r
558                 return NULL;\r
559         }\r
560 \r
561         // FIFO から読み込む\r
562         ReadFifo(q->fifo, &p, sizeof(void *));\r
563         q->num_item--;\r
564 \r
565         // KS\r
566         KS_INC(KS_GETNEXT_COUNT);\r
567 \r
568         return p;\r
569 }\r
570 \r
571 // キューに Int 型を挿入\r
572 void InsertQueueInt(QUEUE *q, UINT value)\r
573 {\r
574         UINT *p;\r
575         // 引数チェック\r
576         if (q == NULL)\r
577         {\r
578                 return;\r
579         }\r
580 \r
581         p = Clone(&value, sizeof(UINT));\r
582 \r
583         InsertQueue(q, p);\r
584 }\r
585 \r
586 // キューに挿入\r
587 void InsertQueue(QUEUE *q, void *p)\r
588 {\r
589         // 引数チェック\r
590         if (q == NULL || p == NULL)\r
591         {\r
592                 return;\r
593         }\r
594 \r
595         // FIFO に書き込む\r
596         WriteFifo(q->fifo, &p, sizeof(void *));\r
597 \r
598         q->num_item++;\r
599 \r
600         // KS\r
601         KS_INC(KS_INSERT_QUEUE_COUNT);\r
602 }\r
603 \r
604 // キューのロック\r
605 void LockQueue(QUEUE *q)\r
606 {\r
607         // 引数チェック\r
608         if (q == NULL)\r
609         {\r
610                 return;\r
611         }\r
612 \r
613         Lock(q->lock);\r
614 }\r
615 \r
616 // キューのロック解除\r
617 void UnlockQueue(QUEUE *q)\r
618 {\r
619         // 引数チェック\r
620         if (q == NULL)\r
621         {\r
622                 return;\r
623         }\r
624 \r
625         Unlock(q->lock);\r
626 }\r
627 \r
628 // キューの解放\r
629 void ReleaseQueue(QUEUE *q)\r
630 {\r
631         // 引数チェック\r
632         if (q == NULL)\r
633         {\r
634                 return;\r
635         }\r
636 \r
637         if (q->ref == NULL || Release(q->ref) == 0)\r
638         {\r
639                 CleanupQueue(q);\r
640         }\r
641 }\r
642 \r
643 // キューのクリーンアップ\r
644 void CleanupQueue(QUEUE *q)\r
645 {\r
646         // 引数チェック\r
647         if (q == NULL)\r
648         {\r
649                 return;\r
650         }\r
651 \r
652         // メモリ解放\r
653         ReleaseFifo(q->fifo);\r
654         DeleteLock(q->lock);\r
655         Free(q);\r
656 \r
657 #ifndef DONT_USE_KERNEL_STATUS\r
658         TrackDeleteObj(POINTER_TO_UINT64(q));\r
659 #endif  // DONT_USE_KERNEL_STATUS\r
660 \r
661         // KS\r
662         KS_INC(KS_FREEQUEUE_COUNT);\r
663 }\r
664 \r
665 // キューの作成\r
666 QUEUE *NewQueue()\r
667 {\r
668         QUEUE *q;\r
669 \r
670         q = ZeroMalloc(sizeof(QUEUE));\r
671         q->lock = NewLock();\r
672         q->ref = NewRef();\r
673         q->num_item = 0;\r
674         q->fifo = NewFifo();\r
675 \r
676 #ifndef DONT_USE_KERNEL_STATUS\r
677         TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);\r
678 #endif  // DONT_USE_KERNEL_STATUS\r
679 \r
680         // KS\r
681         KS_INC(KS_NEWQUEUE_COUNT);\r
682 \r
683         return q;\r
684 }\r
685 QUEUE *NewQueueFast()\r
686 {\r
687         QUEUE *q;\r
688 \r
689         q = ZeroMalloc(sizeof(QUEUE));\r
690         q->lock = NULL;\r
691         q->ref = NULL;\r
692         q->num_item = 0;\r
693         q->fifo = NewFifoFast();\r
694 \r
695 #ifndef DONT_USE_KERNEL_STATUS\r
696         TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);\r
697 #endif  // DONT_USE_KERNEL_STATUS\r
698 \r
699         // KS\r
700         KS_INC(KS_NEWQUEUE_COUNT);\r
701 \r
702         return q;\r
703 }\r
704 \r
705 // リストに比較関数をセットする\r
706 void SetCmp(LIST *o, COMPARE *cmp)\r
707 {\r
708         // 引数チェック\r
709         if (o == NULL || cmp == NULL)\r
710         {\r
711                 return;\r
712         }\r
713 \r
714         if (o->cmp != cmp)\r
715         {\r
716                 o->cmp = cmp;\r
717                 o->sorted = false;\r
718         }\r
719 }\r
720 \r
721 // リストのクローン\r
722 LIST *CloneList(LIST *o)\r
723 {\r
724         LIST *n = NewList(o->cmp);\r
725 \r
726         // メモリ再確保\r
727         Free(n->p);\r
728         n->p = ToArray(o);\r
729         n->num_item = n->num_reserved = LIST_NUM(o);\r
730         n->sorted = o->sorted;\r
731 \r
732         return n;\r
733 }\r
734 \r
735 // リストを配列にコピー\r
736 void CopyToArray(LIST *o, void *p)\r
737 {\r
738         // 引数チェック\r
739         if (o == NULL || p == NULL)\r
740         {\r
741                 return;\r
742         }\r
743 \r
744         // KS\r
745         KS_INC(KS_TOARRAY_COUNT);\r
746 \r
747         Copy(p, o->p, sizeof(void *) * o->num_item);\r
748 }\r
749 \r
750 // リストを配列化する\r
751 void *ToArray(LIST *o)\r
752 {\r
753         return ToArrayEx(o, false);\r
754 }\r
755 void *ToArrayEx(LIST *o, bool fast)\r
756 {\r
757         void *p;\r
758         // 引数チェック\r
759         if (o == NULL)\r
760         {\r
761                 return NULL;\r
762         }\r
763 \r
764         // メモリ確保\r
765         if (fast == false)\r
766         {\r
767                 p = Malloc(sizeof(void *) * LIST_NUM(o));\r
768         }\r
769         else\r
770         {\r
771                 p = MallocFast(sizeof(void *) * LIST_NUM(o));\r
772         }\r
773         // コピー\r
774         CopyToArray(o, p);\r
775 \r
776         return p;\r
777 }\r
778 \r
779 // リストのサーチ\r
780 void *Search(LIST *o, void *target)\r
781 {\r
782         void **ret;\r
783         // 引数チェック\r
784         if (o == NULL || target == NULL)\r
785         {\r
786                 return NULL;\r
787         }\r
788         if (o->cmp == NULL)\r
789         {\r
790                 return NULL;\r
791         }\r
792 \r
793         // ソートのチェック\r
794         if (o->sorted == false)\r
795         {\r
796                 // 未ソートなのでソートを行う\r
797                 Sort(o);\r
798         }\r
799 \r
800         // なんだ C ライブラリのバイナリサーチ関数を呼んでいるだけか\r
801         ret = (void **)bsearch(&target, o->p, o->num_item, sizeof(void *),\r
802                 (int(*)(const void *, const void *))o->cmp);\r
803 \r
804         // KS\r
805         KS_INC(KS_SEARCH_COUNT);\r
806 \r
807         if (ret != NULL)\r
808         {\r
809                 return *ret;\r
810         }\r
811         else\r
812         {\r
813                 return NULL;\r
814         }\r
815 }\r
816 \r
817 // リストに項目を挿入\r
818 // 本当はもうちょっとましなデータ構造 & アルゴリズムにするべき\r
819 void Insert(LIST *o, void *p)\r
820 {\r
821         int low, high, middle;\r
822         UINT pos;\r
823         int i;\r
824         // 引数チェック\r
825         if (o == NULL || p == NULL)\r
826         {\r
827                 return;\r
828         }\r
829 \r
830         if (o->cmp == NULL)\r
831         {\r
832                 // ソート関数が無い場合は単純に追加する\r
833                 Add(o, p);\r
834                 return;\r
835         }\r
836 \r
837         // ソートされていない場合は直ちにソートする\r
838         if (o->sorted == false)\r
839         {\r
840                 Sort(o);\r
841         }\r
842 \r
843         low = 0;\r
844         high = LIST_NUM(o) - 1;\r
845 \r
846         pos = INFINITE;\r
847 \r
848         while (low <= high)\r
849         {\r
850                 int ret;\r
851 \r
852                 middle = (low + high) / 2;\r
853                 ret = o->cmp(&(o->p[middle]), &p);\r
854 \r
855                 if (ret == 0)\r
856                 {\r
857                         pos = middle;\r
858                         break;\r
859                 }\r
860                 else if (ret > 0)\r
861                 {\r
862                         high = middle - 1;\r
863                 }\r
864                 else\r
865                 {\r
866                         low = middle + 1;\r
867                 }\r
868         }\r
869 \r
870         if (pos == INFINITE)\r
871         {\r
872                 pos = low;\r
873         }\r
874 \r
875         o->num_item++;\r
876         if (o->num_item > o->num_reserved)\r
877         {\r
878                 o->num_reserved *= 2;\r
879                 o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);\r
880         }\r
881 \r
882         if (LIST_NUM(o) >= 2)\r
883         {\r
884                 for (i = (LIST_NUM(o) - 2);i >= (int)pos;i--)\r
885                 {\r
886                         o->p[i + 1] = o->p[i];\r
887                 }\r
888         }\r
889 \r
890         o->p[pos] = p;\r
891 \r
892         // KS\r
893         KS_INC(KS_INSERT_COUNT);\r
894 }\r
895 \r
896 // ソートフラグの設定\r
897 void SetSortFlag(LIST *o, bool sorted)\r
898 {\r
899         // 引数チェック\r
900         if (o == NULL)\r
901         {\r
902                 return;\r
903         }\r
904 \r
905         o->sorted = sorted;\r
906 }\r
907 \r
908 // リストのソート\r
909 void Sort(LIST *o)\r
910 {\r
911         // 引数チェック\r
912         if (o == NULL || o->cmp == NULL)\r
913         {\r
914                 return;\r
915         }\r
916 \r
917         qsort(o->p, o->num_item, sizeof(void *), (int(*)(const void *, const void *))o->cmp);\r
918         o->sorted = true;\r
919 \r
920         // KS\r
921         KS_INC(KS_SORT_COUNT);\r
922 }\r
923 \r
924 // ある文字列項目がリスト内に存在しているかどうか調べる (Unicode 版)\r
925 bool IsInListUniStr(LIST *o, wchar_t *str)\r
926 {\r
927         UINT i;\r
928         // 引数チェック\r
929         if (o == NULL || str == NULL)\r
930         {\r
931                 return false;\r
932         }\r
933 \r
934         for (i = 0;i < LIST_NUM(o);i++)\r
935         {\r
936                 wchar_t *s = LIST_DATA(o, i);\r
937 \r
938                 if (UniStrCmpi(s, str) == 0)\r
939                 {\r
940                         return true;\r
941                 }\r
942         }\r
943 \r
944         return false;\r
945 }\r
946 \r
947 // リスト内のポインタを置換する\r
948 bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr)\r
949 {\r
950         UINT i;\r
951         // 引数チェック\r
952         if (o == NULL || oldptr == NULL || newptr == NULL)\r
953         {\r
954                 return false;\r
955         }\r
956 \r
957         for (i = 0;i < LIST_NUM(o);i++)\r
958         {\r
959                 void *p = LIST_DATA(o, i);\r
960 \r
961                 if (p == oldptr)\r
962                 {\r
963                         o->p[i] = newptr;\r
964                         return true;\r
965                 }\r
966         }\r
967 \r
968         return false;\r
969 }\r
970 \r
971 // ある文字列項目がリスト内に存在しているかどうか調べる\r
972 bool IsInListStr(LIST *o, char *str)\r
973 {\r
974         UINT i;\r
975         // 引数チェック\r
976         if (o == NULL || str == NULL)\r
977         {\r
978                 return false;\r
979         }\r
980 \r
981         for (i = 0;i < LIST_NUM(o);i++)\r
982         {\r
983                 char *s = LIST_DATA(o, i);\r
984 \r
985                 if (StrCmpi(s, str) == 0)\r
986                 {\r
987                         return true;\r
988                 }\r
989         }\r
990 \r
991         return false;\r
992 }\r
993 \r
994 // リスト内を UINT 形式のポインタで走査してポインタを取得する\r
995 void *ListKeyToPointer(LIST *o, UINT key)\r
996 {\r
997         UINT i;\r
998         // 引数チェック\r
999         if (o == NULL || key == 0)\r
1000         {\r
1001                 return NULL;\r
1002         }\r
1003 \r
1004         for (i = 0;i < LIST_NUM(o);i++)\r
1005         {\r
1006                 void *p = LIST_DATA(o, i);\r
1007 \r
1008                 if (POINTER_TO_KEY(p) == key)\r
1009                 {\r
1010                         return p;\r
1011                 }\r
1012         }\r
1013 \r
1014         return NULL;\r
1015 }\r
1016 \r
1017 // あるキーがリスト内に存在するかどうか調べる\r
1018 bool IsInListKey(LIST *o, UINT key)\r
1019 {\r
1020         void *p;\r
1021         // 引数チェック\r
1022         if (o == NULL || key == 0)\r
1023         {\r
1024                 return false;\r
1025         }\r
1026 \r
1027         p = ListKeyToPointer(o, key);\r
1028         if (p == NULL)\r
1029         {\r
1030                 return false;\r
1031         }\r
1032 \r
1033         return true;\r
1034 }\r
1035 \r
1036 // ある項目がリスト内に存在するかどうか調べる\r
1037 bool IsInList(LIST *o, void *p)\r
1038 {\r
1039         UINT i;\r
1040         // 引数チェック\r
1041         if (o == NULL || p == NULL)\r
1042         {\r
1043                 return false;\r
1044         }\r
1045 \r
1046         for (i = 0;i < LIST_NUM(o);i++)\r
1047         {\r
1048                 void *q = LIST_DATA(o, i);\r
1049                 if (p == q)\r
1050                 {\r
1051                         return true;\r
1052                 }\r
1053         }\r
1054 \r
1055         return false;\r
1056 }\r
1057 \r
1058 // リストへの要素の追加\r
1059 void Add(LIST *o, void *p)\r
1060 {\r
1061         UINT i;\r
1062         // 引数チェック\r
1063         if (o == NULL || p == NULL)\r
1064         {\r
1065                 return;\r
1066         }\r
1067 \r
1068         i = o->num_item;\r
1069         o->num_item++;\r
1070 \r
1071         if (o->num_item > o->num_reserved)\r
1072         {\r
1073                 o->num_reserved = o->num_reserved * 2;\r
1074                 o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);\r
1075         }\r
1076 \r
1077         o->p[i] = p;\r
1078         o->sorted = false;\r
1079 \r
1080         // KS\r
1081         KS_INC(KS_INSERT_COUNT);\r
1082 }\r
1083 \r
1084 // リストからキーで指定した要素の削除\r
1085 bool DeleteKey(LIST *o, UINT key)\r
1086 {\r
1087         void *p;\r
1088         // 引数チェック\r
1089         if (o == NULL || key == 0)\r
1090         {\r
1091                 return false;\r
1092         }\r
1093 \r
1094         p = ListKeyToPointer(o, key);\r
1095         if (p == NULL)\r
1096         {\r
1097                 return false;\r
1098         }\r
1099 \r
1100         return Delete(o, p);\r
1101 }\r
1102 \r
1103 // リストから要素の削除\r
1104 bool Delete(LIST *o, void *p)\r
1105 {\r
1106         UINT i, n;\r
1107         // 引数チェック\r
1108         if (o == NULL || p == NULL)\r
1109         {\r
1110                 return false;\r
1111         }\r
1112 \r
1113         for (i = 0;i < o->num_item;i++)\r
1114         {\r
1115                 if (o->p[i] == p)\r
1116                 {\r
1117                         break;\r
1118                 }\r
1119         }\r
1120         if (i == o->num_item)\r
1121         {\r
1122                 return false;\r
1123         }\r
1124 \r
1125         n = i;\r
1126         for (i = n;i < (o->num_item - 1);i++)\r
1127         {\r
1128                 o->p[i] = o->p[i + 1];\r
1129         }\r
1130         o->num_item--;\r
1131         if ((o->num_item * 2) <= o->num_reserved)\r
1132         {\r
1133                 if (o->num_reserved > (INIT_NUM_RESERVED * 2))\r
1134                 {\r
1135                         o->num_reserved = o->num_reserved / 2;\r
1136                         o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);\r
1137                 }\r
1138         }\r
1139 \r
1140         // KS\r
1141         KS_INC(KS_DELETE_COUNT);\r
1142 \r
1143         return true;\r
1144 }\r
1145 \r
1146 // リストからすべての要素の削除\r
1147 void DeleteAll(LIST *o)\r
1148 {\r
1149         // 引数チェック\r
1150         if (o == NULL)\r
1151         {\r
1152                 return;\r
1153         }\r
1154 \r
1155         o->num_item = 0;\r
1156         o->num_reserved = INIT_NUM_RESERVED;\r
1157         o->p = ReAlloc(o->p, sizeof(void *) * INIT_NUM_RESERVED);\r
1158 }\r
1159 \r
1160 // リストのロック\r
1161 void LockList(LIST *o)\r
1162 {\r
1163         // 引数チェック\r
1164         if (o == NULL)\r
1165         {\r
1166                 return;\r
1167         }\r
1168 \r
1169         Lock(o->lock);\r
1170 }\r
1171 \r
1172 // リストのロック解除\r
1173 void UnlockList(LIST *o)\r
1174 {\r
1175         // 引数チェック\r
1176         if (o == NULL)\r
1177         {\r
1178                 return;\r
1179         }\r
1180 \r
1181         Unlock(o->lock);\r
1182 }\r
1183 \r
1184 // リストの解放\r
1185 void ReleaseList(LIST *o)\r
1186 {\r
1187         // 引数チェック\r
1188         if (o == NULL)\r
1189         {\r
1190                 return;\r
1191         }\r
1192 \r
1193         if (o->ref == NULL || Release(o->ref) == 0)\r
1194         {\r
1195                 CleanupList(o);\r
1196         }\r
1197 }\r
1198 \r
1199 // リストのクリーンアップ\r
1200 void CleanupList(LIST *o)\r
1201 {\r
1202         // 引数チェック\r
1203         if (o == NULL)\r
1204         {\r
1205                 return;\r
1206         }\r
1207 \r
1208         Free(o->p);\r
1209         if (o->lock != NULL)\r
1210         {\r
1211                 DeleteLock(o->lock);\r
1212         }\r
1213         Free(o);\r
1214 \r
1215         // KS\r
1216         KS_INC(KS_FREELIST_COUNT);\r
1217 \r
1218 #ifndef DONT_USE_KERNEL_STATUS\r
1219         TrackDeleteObj(POINTER_TO_UINT64(o));\r
1220 #endif  // DONT_USE_KERNEL_STATUS\r
1221 }\r
1222 \r
1223 // 文字列比較関数 (Unicode)\r
1224 int CompareUniStr(void *p1, void *p2)\r
1225 {\r
1226         wchar_t *s1, *s2;\r
1227         if (p1 == NULL || p2 == NULL)\r
1228         {\r
1229                 return 0;\r
1230         }\r
1231         s1 = *(wchar_t **)p1;\r
1232         s2 = *(wchar_t **)p2;\r
1233 \r
1234         return UniStrCmp(s1, s2);\r
1235 }\r
1236 \r
1237 // 文字列をリストに挿入する\r
1238 bool InsertStr(LIST *o, char *str)\r
1239 {\r
1240         // 引数チェック\r
1241         if (o == NULL || str == NULL)\r
1242         {\r
1243                 return false;\r
1244         }\r
1245 \r
1246         if (Search(o, str) == NULL)\r
1247         {\r
1248                 Insert(o, str);\r
1249 \r
1250                 return true;\r
1251         }\r
1252 \r
1253         return false;\r
1254 }\r
1255 \r
1256 // 文字列比較関数\r
1257 int CompareStr(void *p1, void *p2)\r
1258 {\r
1259         char *s1, *s2;\r
1260         if (p1 == NULL || p2 == NULL)\r
1261         {\r
1262                 return 0;\r
1263         }\r
1264         s1 = *(char **)p1;\r
1265         s2 = *(char **)p2;\r
1266 \r
1267         return StrCmpi(s1, s2);\r
1268 }\r
1269 \r
1270 // 高速リスト (ロック無し) の作成\r
1271 LIST *NewListFast(COMPARE *cmp)\r
1272 {\r
1273         return NewListEx(cmp, true);\r
1274 }\r
1275 \r
1276 // リストの作成\r
1277 LIST *NewList(COMPARE *cmp)\r
1278 {\r
1279         return NewListEx(cmp, false);\r
1280 }\r
1281 LIST *NewListEx(COMPARE *cmp, bool fast)\r
1282 {\r
1283         return NewListEx2(cmp, fast, false);\r
1284 }\r
1285 LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc)\r
1286 {\r
1287         LIST *o;\r
1288 \r
1289         if (fast_malloc == false)\r
1290         {\r
1291                 o = Malloc(sizeof(LIST));\r
1292         }\r
1293         else\r
1294         {\r
1295                 o = MallocFast(sizeof(LIST));\r
1296         }\r
1297 \r
1298         if (fast == false)\r
1299         {\r
1300                 o->lock = NewLock();\r
1301                 o->ref = NewRef();\r
1302         }\r
1303         else\r
1304         {\r
1305                 o->lock = NULL;\r
1306                 o->ref = NULL;\r
1307         }\r
1308         o->num_item = 0;\r
1309         o->num_reserved = INIT_NUM_RESERVED;\r
1310 \r
1311         if (fast_malloc == false)\r
1312         {\r
1313                 o->p = Malloc(sizeof(void *) * o->num_reserved);\r
1314         }\r
1315         else\r
1316         {\r
1317                 o->p = MallocFast(sizeof(void *) * o->num_reserved);\r
1318         }\r
1319 \r
1320         o->cmp = cmp;\r
1321         o->sorted = true;\r
1322 \r
1323 #ifndef DONT_USE_KERNEL_STATUS\r
1324         TrackNewObj(POINTER_TO_UINT64(o), "LIST", 0);\r
1325 #endif  //DONT_USE_KERNEL_STATUS\r
1326 \r
1327         // KS\r
1328         KS_INC(KS_NEWLIST_COUNT);\r
1329 \r
1330         return o;\r
1331 }\r
1332 \r
1333 // FIFO から peek する\r
1334 UINT PeekFifo(FIFO *f, void *p, UINT size)\r
1335 {\r
1336         UINT read_size;\r
1337         if (f == NULL || size == 0)\r
1338         {\r
1339                 return 0;\r
1340         }\r
1341 \r
1342         // KS\r
1343         KS_INC(KS_PEEK_FIFO_COUNT);\r
1344 \r
1345         read_size = MIN(size, f->size);\r
1346         if (read_size == 0)\r
1347         {\r
1348                 return 0;\r
1349         }\r
1350 \r
1351         if (p != NULL)\r
1352         {\r
1353                 Copy(p, (UCHAR *)f->p + f->pos, read_size);\r
1354         }\r
1355 \r
1356         return read_size;\r
1357 }\r
1358 \r
1359 // FIFO から読み取る\r
1360 UINT ReadFifo(FIFO *f, void *p, UINT size)\r
1361 {\r
1362         UINT read_size;\r
1363         // 引数チェック\r
1364         if (f == NULL || size == 0)\r
1365         {\r
1366                 return 0;\r
1367         }\r
1368 \r
1369         read_size = MIN(size, f->size);\r
1370         if (read_size == 0)\r
1371         {\r
1372                 return 0;\r
1373         }\r
1374         if (p != NULL)\r
1375         {\r
1376                 Copy(p, (UCHAR *)f->p + f->pos, read_size);\r
1377         }\r
1378         f->pos += read_size;\r
1379         f->size -= read_size;\r
1380 \r
1381         if (f->size == 0)\r
1382         {\r
1383                 f->pos = 0;\r
1384         }\r
1385 \r
1386         // メモリの詰め直し\r
1387         if (f->pos >= FIFO_INIT_MEM_SIZE &&\r
1388                 f->memsize >= f->realloc_mem_size &&\r
1389                 (f->memsize / 2) > f->size)\r
1390         {\r
1391                 void *new_p;\r
1392                 UINT new_size;\r
1393 \r
1394                 new_size = MAX(f->memsize / 2, FIFO_INIT_MEM_SIZE);\r
1395                 new_p = Malloc(new_size);\r
1396                 Copy(new_p, (UCHAR *)f->p + f->pos, f->size);\r
1397 \r
1398                 Free(f->p);\r
1399 \r
1400                 f->memsize = new_size;\r
1401                 f->p = new_p;\r
1402                 f->pos = 0;\r
1403         }\r
1404 \r
1405         // KS\r
1406         KS_INC(KS_READ_FIFO_COUNT);\r
1407 \r
1408         return read_size;\r
1409 }\r
1410 \r
1411 // FIFO に書き込む\r
1412 void WriteFifo(FIFO *f, void *p, UINT size)\r
1413 {\r
1414         UINT i, need_size;\r
1415         bool realloc_flag;\r
1416         // 引数チェック\r
1417         if (f == NULL || size == 0)\r
1418         {\r
1419                 return;\r
1420         }\r
1421 \r
1422         i = f->size;\r
1423         f->size += size;\r
1424         need_size = f->pos + f->size;\r
1425         realloc_flag = false;\r
1426 \r
1427         // メモリ拡張\r
1428         while (need_size > f->memsize)\r
1429         {\r
1430                 f->memsize = MAX(f->memsize, FIFO_INIT_MEM_SIZE) * 3;\r
1431                 realloc_flag = true;\r
1432         }\r
1433 \r
1434         if (realloc_flag)\r
1435         {\r
1436                 f->p = ReAlloc(f->p, f->memsize);\r
1437         }\r
1438 \r
1439         // データ書き込み\r
1440         if (p != NULL)\r
1441         {\r
1442                 Copy((UCHAR *)f->p + f->pos + i, p, size);\r
1443         }\r
1444 \r
1445         // KS\r
1446         KS_INC(KS_WRITE_FIFO_COUNT);\r
1447 }\r
1448 \r
1449 // FIFO のクリア\r
1450 void ClearFifo(FIFO *f)\r
1451 {\r
1452         // 引数チェック\r
1453         if (f == NULL)\r
1454         {\r
1455                 return;\r
1456         }\r
1457 \r
1458         f->size = f->pos = 0;\r
1459         f->memsize = FIFO_INIT_MEM_SIZE;\r
1460         f->p = ReAlloc(f->p, f->memsize);\r
1461 }\r
1462 \r
1463 // FIFO のサイズ取得\r
1464 UINT FifoSize(FIFO *f)\r
1465 {\r
1466         // 引数チェック\r
1467         if (f == NULL)\r
1468         {\r
1469                 return 0;\r
1470         }\r
1471 \r
1472         return f->size;\r
1473 }\r
1474 \r
1475 // FIFO のロック\r
1476 void LockFifo(FIFO *f)\r
1477 {\r
1478         // 引数チェック\r
1479         if (f == NULL)\r
1480         {\r
1481                 return;\r
1482         }\r
1483 \r
1484         Lock(f->lock);\r
1485 }\r
1486 \r
1487 // FIFO のロック解除\r
1488 void UnlockFifo(FIFO *f)\r
1489 {\r
1490         // 引数チェック\r
1491         if (f == NULL)\r
1492         {\r
1493                 return;\r
1494         }\r
1495 \r
1496         Unlock(f->lock);\r
1497 }\r
1498 \r
1499 // FIFO の解放\r
1500 void ReleaseFifo(FIFO *f)\r
1501 {\r
1502         // 引数チェック\r
1503         if (f == NULL)\r
1504         {\r
1505                 return;\r
1506         }\r
1507 \r
1508         if (f->ref == NULL || Release(f->ref) == 0)\r
1509         {\r
1510                 CleanupFifo(f);\r
1511         }\r
1512 }\r
1513 \r
1514 // FIFO のクリーンアップ\r
1515 void CleanupFifo(FIFO *f)\r
1516 {\r
1517         // 引数チェック\r
1518         if (f == NULL)\r
1519         {\r
1520                 return;\r
1521         }\r
1522 \r
1523         DeleteLock(f->lock);\r
1524         Free(f->p);\r
1525         Free(f);\r
1526 \r
1527 #ifndef DONT_USE_KERNEL_STATUS\r
1528         TrackDeleteObj(POINTER_TO_UINT64(f));\r
1529 #endif  //DONT_USE_KERNEL_STATUS\r
1530 \r
1531         // KS\r
1532         KS_INC(KS_FREEFIFO_COUNT);\r
1533 }\r
1534 \r
1535 // FIFO システムの初期化\r
1536 void InitFifo()\r
1537 {\r
1538         fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;\r
1539 }\r
1540 \r
1541 // FIFO の作成\r
1542 FIFO *NewFifo()\r
1543 {\r
1544         return NewFifoEx(0, false);\r
1545 }\r
1546 FIFO *NewFifoFast()\r
1547 {\r
1548         return NewFifoEx(0, true);\r
1549 }\r
1550 FIFO *NewFifoEx(UINT realloc_mem_size, bool fast)\r
1551 {\r
1552         FIFO *f;\r
1553 \r
1554         // メモリ確保\r
1555         f = Malloc(sizeof(FIFO));\r
1556 \r
1557         if (fast == false)\r
1558         {\r
1559                 f->lock = NewLock();\r
1560                 f->ref = NewRef();\r
1561         }\r
1562         else\r
1563         {\r
1564                 f->lock = NULL;\r
1565                 f->ref = NULL;\r
1566         }\r
1567 \r
1568         f->size = f->pos = 0;\r
1569         f->memsize = FIFO_INIT_MEM_SIZE;\r
1570         f->p = Malloc(FIFO_INIT_MEM_SIZE);\r
1571 \r
1572         if (realloc_mem_size == 0)\r
1573         {\r
1574                 realloc_mem_size = fifo_default_realloc_mem_size;\r
1575         }\r
1576 \r
1577         f->realloc_mem_size = realloc_mem_size;\r
1578 \r
1579 #ifndef DONT_USE_KERNEL_STATUS\r
1580         TrackNewObj(POINTER_TO_UINT64(f), "FIFO", 0);\r
1581 #endif  // DONT_USE_KERNEL_STATUS\r
1582 \r
1583         // KS\r
1584         KS_INC(KS_NEWFIFO_COUNT);\r
1585 \r
1586         return f;\r
1587 }\r
1588 \r
1589 // FIFO のデフォルトのメモリ再確保サイズを取得する\r
1590 UINT GetFifoDefaultReallocMemSize()\r
1591 {\r
1592         return fifo_default_realloc_mem_size;\r
1593 }\r
1594 \r
1595 // FIFO のデフォルトのメモリ再確保サイズを設定する\r
1596 void SetFifoDefaultReallocMemSize(UINT size)\r
1597 {\r
1598         if (size == 0)\r
1599         {\r
1600                 size = FIFO_REALLOC_MEM_SIZE;\r
1601         }\r
1602 \r
1603         fifo_default_realloc_mem_size = size;\r
1604 }\r
1605 \r
1606 // バッファをファイルから読み込む\r
1607 BUF *FileToBuf(IO *o)\r
1608 {\r
1609         UCHAR hash1[MD5_SIZE], hash2[MD5_SIZE];\r
1610         UINT size;\r
1611         void *buf;\r
1612         BUF *b;\r
1613 \r
1614         // 引数チェック\r
1615         if (o == NULL)\r
1616         {\r
1617                 return NULL;\r
1618         }\r
1619 \r
1620         // サイズを読み込む\r
1621         if (FileRead(o, &size, sizeof(size)) == false)\r
1622         {\r
1623                 return NULL;\r
1624         }\r
1625         size = Endian32(size);\r
1626 \r
1627         if (size > FileSize(o))\r
1628         {\r
1629                 return NULL;\r
1630         }\r
1631 \r
1632         // ハッシュを読み込む\r
1633         if (FileRead(o, hash1, sizeof(hash1)) == false)\r
1634         {\r
1635                 return NULL;\r
1636         }\r
1637 \r
1638         // バッファを読み込む\r
1639         buf = Malloc(size);\r
1640         if (FileRead(o, buf, size) == false)\r
1641         {\r
1642                 Free(buf);\r
1643                 return NULL;\r
1644         }\r
1645 \r
1646         // ハッシュをとる\r
1647         Hash(hash2, buf, size, false);\r
1648 \r
1649         // ハッシュを比較する\r
1650         if (Cmp(hash1, hash2, sizeof(hash1)) != 0)\r
1651         {\r
1652                 // ハッシュが異なる\r
1653                 Free(buf);\r
1654                 return NULL;\r
1655         }\r
1656 \r
1657         // バッファを作成する\r
1658         b = NewBuf();\r
1659         WriteBuf(b, buf, size);\r
1660         Free(buf);\r
1661         b->Current = 0;\r
1662 \r
1663         return b;\r
1664 }\r
1665 \r
1666 // ダンプファイルをバッファに読み込む\r
1667 BUF *ReadDump(char *filename)\r
1668 {\r
1669         IO *o;\r
1670         BUF *b;\r
1671         UINT size;\r
1672         void *data;\r
1673         // 引数チェック\r
1674         if (filename == NULL)\r
1675         {\r
1676                 return NULL;\r
1677         }\r
1678 \r
1679         o = FileOpen(filename, false);\r
1680         if (o == NULL)\r
1681         {\r
1682                 return NULL;\r
1683         }\r
1684 \r
1685         size = FileSize(o);\r
1686         data = Malloc(size);\r
1687         FileRead(o, data, size);\r
1688         FileClose(o);\r
1689 \r
1690         b = NewBuf();\r
1691         WriteBuf(b, data, size);\r
1692         b->Current = 0;\r
1693         Free(data);\r
1694 \r
1695         return b;\r
1696 }\r
1697 BUF *ReadDumpW(wchar_t *filename)\r
1698 {\r
1699         IO *o;\r
1700         BUF *b;\r
1701         UINT size;\r
1702         void *data;\r
1703         // 引数チェック\r
1704         if (filename == NULL)\r
1705         {\r
1706                 return NULL;\r
1707         }\r
1708 \r
1709         o = FileOpenW(filename, false);\r
1710         if (o == NULL)\r
1711         {\r
1712                 return NULL;\r
1713         }\r
1714 \r
1715         size = FileSize(o);\r
1716         data = Malloc(size);\r
1717         FileRead(o, data, size);\r
1718         FileClose(o);\r
1719 \r
1720         b = NewBuf();\r
1721         WriteBuf(b, data, size);\r
1722         b->Current = 0;\r
1723         Free(data);\r
1724 \r
1725         return b;\r
1726 }\r
1727 \r
1728 // バッファ内容をファイルにダンプする\r
1729 bool DumpBuf(BUF *b, char *filename)\r
1730 {\r
1731         IO *o;\r
1732         // 引数チェック\r
1733         if (b == NULL || filename == NULL)\r
1734         {\r
1735                 return false;\r
1736         }\r
1737 \r
1738         o = FileCreate(filename);\r
1739         if (o == NULL)\r
1740         {\r
1741                 return false;\r
1742         }\r
1743         FileWrite(o, b->Buf, b->Size);\r
1744         FileClose(o);\r
1745 \r
1746         return true;\r
1747 }\r
1748 bool DumpBufW(BUF *b, wchar_t *filename)\r
1749 {\r
1750         IO *o;\r
1751         // 引数チェック\r
1752         if (b == NULL || filename == NULL)\r
1753         {\r
1754                 return false;\r
1755         }\r
1756 \r
1757         o = FileCreateW(filename);\r
1758         if (o == NULL)\r
1759         {\r
1760                 return false;\r
1761         }\r
1762         FileWrite(o, b->Buf, b->Size);\r
1763         FileClose(o);\r
1764 \r
1765         return true;\r
1766 }\r
1767 \r
1768 // バッファをファイルに書き込む\r
1769 bool BufToFile(IO *o, BUF *b)\r
1770 {\r
1771         UCHAR hash[MD5_SIZE];\r
1772         UINT size;\r
1773 \r
1774         // 引数チェック\r
1775         if (o == NULL || b == NULL)\r
1776         {\r
1777                 return false;\r
1778         }\r
1779 \r
1780         // データをハッシュする\r
1781         Hash(hash, b->Buf, b->Size, false);\r
1782 \r
1783         size = Endian32(b->Size);\r
1784 \r
1785         // サイズを書き込む\r
1786         if (FileWrite(o, &size, sizeof(size)) == false)\r
1787         {\r
1788                 return false;\r
1789         }\r
1790 \r
1791         // ハッシュを書き込む\r
1792         if (FileWrite(o, hash, sizeof(hash)) == false)\r
1793         {\r
1794                 return false;\r
1795         }\r
1796 \r
1797         // データを書き込む\r
1798         if (FileWrite(o, b->Buf, b->Size) == false)\r
1799         {\r
1800                 return false;\r
1801         }\r
1802 \r
1803         return true;\r
1804 }\r
1805 \r
1806 // バッファの作成\r
1807 BUF *NewBuf()\r
1808 {\r
1809         BUF *b;\r
1810 \r
1811         // メモリ確保\r
1812         b = Malloc(sizeof(BUF));\r
1813         b->Buf = Malloc(INIT_BUF_SIZE);\r
1814         b->Size = 0;\r
1815         b->Current = 0;\r
1816         b->SizeReserved = INIT_BUF_SIZE;\r
1817 \r
1818 #ifndef DONT_USE_KERNEL_STATUS\r
1819         TrackNewObj(POINTER_TO_UINT64(b), "BUF", 0);\r
1820 #endif  // DONT_USE_KERNEL_STATUS\r
1821 \r
1822         // KS\r
1823         KS_INC(KS_NEWBUF_COUNT);\r
1824         KS_INC(KS_CURRENT_BUF_COUNT);\r
1825 \r
1826         return b;\r
1827 }\r
1828 \r
1829 // バッファのクリア\r
1830 void ClearBuf(BUF *b)\r
1831 {\r
1832         // 引数チェック\r
1833         if (b == NULL)\r
1834         {\r
1835                 return;\r
1836         }\r
1837 \r
1838         b->Size = 0;\r
1839         b->Current = 0;\r
1840 }\r
1841 \r
1842 // バッファへ書き込み\r
1843 void WriteBuf(BUF *b, void *buf, UINT size)\r
1844 {\r
1845         UINT new_size;\r
1846         // 引数チェック\r
1847         if (b == NULL || buf == NULL || size == 0)\r
1848         {\r
1849                 return;\r
1850         }\r
1851 \r
1852         new_size = b->Current + size;\r
1853         if (new_size > b->Size)\r
1854         {\r
1855                 // サイズを調整する\r
1856                 AdjustBufSize(b, new_size);\r
1857         }\r
1858         if (b->Buf != NULL)\r
1859         {\r
1860                 Copy((UCHAR *)b->Buf + b->Current, buf, size);\r
1861         }\r
1862         b->Current += size;\r
1863         b->Size = new_size;\r
1864 \r
1865         // KS\r
1866         KS_INC(KS_WRITE_BUF_COUNT);\r
1867 }\r
1868 \r
1869 // バッファに文字列を追記\r
1870 void AddBufStr(BUF *b, char *str)\r
1871 {\r
1872         // 引数チェック\r
1873         if (b == NULL || str == NULL)\r
1874         {\r
1875                 return;\r
1876         }\r
1877 \r
1878         WriteBuf(b, str, StrLen(str));\r
1879 }\r
1880 \r
1881 // バッファに 1 行書き込む\r
1882 void WriteBufLine(BUF *b, char *str)\r
1883 {\r
1884         char *crlf = "\r\n";\r
1885         // 引数チェック\r
1886         if (b == NULL || str == NULL)\r
1887         {\r
1888                 return;\r
1889         }\r
1890 \r
1891         WriteBuf(b, str, StrLen(str));\r
1892         WriteBuf(b, crlf, StrLen(crlf));\r
1893 }\r
1894 \r
1895 // バッファに文字列を書き込む\r
1896 bool WriteBufStr(BUF *b, char *str)\r
1897 {\r
1898         UINT len;\r
1899         // 引数チェック\r
1900         if (b == NULL || str == NULL)\r
1901         {\r
1902                 return false;\r
1903         }\r
1904 \r
1905         // 文字列長\r
1906         len = StrLen(str);\r
1907         if (WriteBufInt(b, len + 1) == false)\r
1908         {\r
1909                 return false;\r
1910         }\r
1911 \r
1912         // 文字列本体\r
1913         WriteBuf(b, str, len);\r
1914 \r
1915         return true;\r
1916 }\r
1917 \r
1918 // バッファから文字列を読み込む\r
1919 bool ReadBufStr(BUF *b, char *str, UINT size)\r
1920 {\r
1921         UINT len;\r
1922         UINT read_size;\r
1923         // 引数チェック\r
1924         if (b == NULL || str == NULL || size == 0)\r
1925         {\r
1926                 return false;\r
1927         }\r
1928 \r
1929         // 文字列長を読み込む\r
1930         len = ReadBufInt(b);\r
1931         if (len == 0)\r
1932         {\r
1933                 return false;\r
1934         }\r
1935         len--;\r
1936         if (len <= (size - 1))\r
1937         {\r
1938                 size = len + 1;\r
1939         }\r
1940 \r
1941         read_size = MIN(len, (size - 1));\r
1942 \r
1943         // 文字列本体を読み込む\r
1944         if (ReadBuf(b, str, read_size) != read_size)\r
1945         {\r
1946                 return false;\r
1947         }\r
1948         if (read_size < len)\r
1949         {\r
1950                 ReadBuf(b, NULL, len - read_size);\r
1951         }\r
1952         str[read_size] = 0;\r
1953 \r
1954         return true;\r
1955 }\r
1956 \r
1957 // バッファに 64 bit 整数を書き込む\r
1958 bool WriteBufInt64(BUF *b, UINT64 value)\r
1959 {\r
1960         // 引数チェック\r
1961         if (b == NULL)\r
1962         {\r
1963                 return false;\r
1964         }\r
1965 \r
1966         value = Endian64(value);\r
1967 \r
1968         WriteBuf(b, &value, sizeof(UINT64));\r
1969         return true;\r
1970 }\r
1971 \r
1972 // バッファに整数を書き込む\r
1973 bool WriteBufInt(BUF *b, UINT value)\r
1974 {\r
1975         // 引数チェック\r
1976         if (b == NULL)\r
1977         {\r
1978                 return false;\r
1979         }\r
1980 \r
1981         value = Endian32(value);\r
1982 \r
1983         WriteBuf(b, &value, sizeof(UINT));\r
1984         return true;\r
1985 }\r
1986 \r
1987 // バッファから 64bit 整数を読み込む\r
1988 UINT64 ReadBufInt64(BUF *b)\r
1989 {\r
1990         UINT64 value;\r
1991         // 引数チェック\r
1992         if (b == NULL)\r
1993         {\r
1994                 return 0;\r
1995         }\r
1996 \r
1997         if (ReadBuf(b, &value, sizeof(UINT64)) != sizeof(UINT64))\r
1998         {\r
1999                 return 0;\r
2000         }\r
2001         return Endian64(value);\r
2002 }\r
2003 \r
2004 // バッファから整数を読み込む\r
2005 UINT ReadBufInt(BUF *b)\r
2006 {\r
2007         UINT value;\r
2008         // 引数チェック\r
2009         if (b == NULL)\r
2010         {\r
2011                 return 0;\r
2012         }\r
2013 \r
2014         if (ReadBuf(b, &value, sizeof(UINT)) != sizeof(UINT))\r
2015         {\r
2016                 return 0;\r
2017         }\r
2018         return Endian32(value);\r
2019 }\r
2020 \r
2021 // バッファにバッファを書き込み\r
2022 void WriteBufBuf(BUF *b, BUF *bb)\r
2023 {\r
2024         // 引数チェック\r
2025         if (b == NULL || bb == NULL)\r
2026         {\r
2027                 return;\r
2028         }\r
2029 \r
2030         WriteBuf(b, bb->Buf, bb->Size);\r
2031 }\r
2032 \r
2033 // バッファからバッファを読み込み\r
2034 BUF *ReadBufFromBuf(BUF *b, UINT size)\r
2035 {\r
2036         BUF *ret;\r
2037         UCHAR *data;\r
2038         // 引数チェック\r
2039         if (b == NULL)\r
2040         {\r
2041                 return NULL;\r
2042         }\r
2043 \r
2044         data = Malloc(size);\r
2045         if (ReadBuf(b, data, size) != size)\r
2046         {\r
2047                 Free(data);\r
2048                 return NULL;\r
2049         }\r
2050 \r
2051         ret = NewBuf();\r
2052         WriteBuf(ret, data, size);\r
2053         SeekBuf(ret, 0, 0);\r
2054 \r
2055         Free(data);\r
2056 \r
2057         return ret;\r
2058 }\r
2059 \r
2060 // バッファから読み込み\r
2061 UINT ReadBuf(BUF *b, void *buf, UINT size)\r
2062 {\r
2063         UINT size_read;\r
2064         // 引数チェック\r
2065         if (b == NULL || size == 0)\r
2066         {\r
2067                 return 0;\r
2068         }\r
2069 \r
2070         if (b->Buf == NULL)\r
2071         {\r
2072                 Zero(buf, size);\r
2073                 return 0;\r
2074         }\r
2075         size_read = size;\r
2076         if ((b->Current + size) >= b->Size)\r
2077         {\r
2078                 size_read = b->Size - b->Current;\r
2079                 if (buf != NULL)\r
2080                 {\r
2081                         Zero((UCHAR *)buf + size_read, size - size_read);\r
2082                 }\r
2083         }\r
2084 \r
2085         if (buf != NULL)\r
2086         {\r
2087                 Copy(buf, (UCHAR *)b->Buf + b->Current, size_read);\r
2088         }\r
2089 \r
2090         b->Current += size_read;\r
2091 \r
2092         // KS\r
2093         KS_INC(KS_READ_BUF_COUNT);\r
2094 \r
2095         return size_read;\r
2096 }\r
2097 \r
2098 // バッファサイズの調整\r
2099 void AdjustBufSize(BUF *b, UINT new_size)\r
2100 {\r
2101         // 引数チェック\r
2102         if (b == NULL)\r
2103         {\r
2104                 return;\r
2105         }\r
2106 \r
2107         if (b->SizeReserved >= new_size)\r
2108         {\r
2109                 return;\r
2110         }\r
2111 \r
2112         while (b->SizeReserved < new_size)\r
2113         {\r
2114                 b->SizeReserved = b->SizeReserved * 2;\r
2115         }\r
2116         b->Buf = ReAlloc(b->Buf, b->SizeReserved);\r
2117 \r
2118         // KS\r
2119         KS_INC(KS_ADJUST_BUFSIZE_COUNT);\r
2120 }\r
2121 \r
2122 // バッファのシーク\r
2123 void SeekBuf(BUF *b, UINT offset, int mode)\r
2124 {\r
2125         UINT new_pos;\r
2126         // 引数チェック\r
2127         if (b == NULL)\r
2128         {\r
2129                 return;\r
2130         }\r
2131 \r
2132         if (mode == 0)\r
2133         {\r
2134                 // 絶対位置\r
2135                 new_pos = offset;\r
2136         }\r
2137         else\r
2138         {\r
2139                 if (mode > 0)\r
2140                 {\r
2141                         // 右へ移動\r
2142                         new_pos = b->Current + offset;\r
2143                 }\r
2144                 else\r
2145                 {\r
2146                         // 左へ移動\r
2147                         if (b->Current >= offset)\r
2148                         {\r
2149                                 new_pos = b->Current - offset;\r
2150                         }\r
2151                         else\r
2152                         {\r
2153                                 new_pos = 0;\r
2154                         }\r
2155                 }\r
2156         }\r
2157         b->Current = MAKESURE(new_pos, 0, b->Size);\r
2158 \r
2159         KS_INC(KS_SEEK_BUF_COUNT);\r
2160 }\r
2161 \r
2162 // バッファの解放\r
2163 void FreeBuf(BUF *b)\r
2164 {\r
2165         // 引数チェック\r
2166         if (b == NULL)\r
2167         {\r
2168                 return;\r
2169         }\r
2170 \r
2171         // メモリ解放\r
2172         Free(b->Buf);\r
2173         Free(b);\r
2174 \r
2175         // KS\r
2176         KS_INC(KS_FREEBUF_COUNT);\r
2177         KS_DEC(KS_CURRENT_BUF_COUNT);\r
2178 \r
2179 #ifndef DONT_USE_KERNEL_STATUS\r
2180         TrackDeleteObj(POINTER_TO_UINT64(b));\r
2181 #endif  // DONT_USE_KERNEL_STATUS\r
2182 }\r
2183 \r
2184 // Unicode 文字列のエンディアン変換\r
2185 void EndianUnicode(wchar_t *str)\r
2186 {\r
2187         UINT i, len;\r
2188         // 引数チェック\r
2189         if (str == NULL)\r
2190         {\r
2191                 return;\r
2192         }\r
2193         len = UniStrLen(str);\r
2194 \r
2195         for (i = 0;i < len;i++)\r
2196         {\r
2197                 str[i] = Endian16(str[i]);\r
2198         }\r
2199 }\r
2200 \r
2201 // エンディアン変換 16bit\r
2202 USHORT Endian16(USHORT src)\r
2203 {\r
2204         int x = 1;\r
2205         if (*((char *)&x))\r
2206         {\r
2207                 return Swap16(src);\r
2208         }\r
2209         else\r
2210         {\r
2211                 return src;\r
2212         }\r
2213 }\r
2214 \r
2215 // エンディアン変換 32bit\r
2216 UINT Endian32(UINT src)\r
2217 {\r
2218         int x = 1;\r
2219         if (*((char *)&x))\r
2220         {\r
2221                 return Swap32(src);\r
2222         }\r
2223         else\r
2224         {\r
2225                 return src;\r
2226         }\r
2227 }\r
2228 \r
2229 // エンディアン変換 64bit\r
2230 UINT64 Endian64(UINT64 src)\r
2231 {\r
2232         int x = 1;\r
2233         if (*((char *)&x))\r
2234         {\r
2235                 return Swap64(src);\r
2236         }\r
2237         else\r
2238         {\r
2239                 return src;\r
2240         }\r
2241 }\r
2242 \r
2243 // 任意のデータのスワップ\r
2244 void Swap(void *buf, UINT size)\r
2245 {\r
2246         UCHAR *tmp, *src;\r
2247         UINT i;\r
2248         // 引数チェック\r
2249         if (buf == NULL || size == 0)\r
2250         {\r
2251                 return;\r
2252         }\r
2253 \r
2254         src = (UCHAR *)buf;\r
2255         tmp = Malloc(size);\r
2256         for (i = 0;i < size;i++)\r
2257         {\r
2258                 tmp[size - i - 1] = src[i];\r
2259         }\r
2260 \r
2261         Copy(buf, tmp, size);\r
2262         Free(buf);\r
2263 }\r
2264 \r
2265 // 16bit スワップ\r
2266 USHORT Swap16(USHORT value)\r
2267 {\r
2268         USHORT r;\r
2269         // 汚いコード\r
2270         ((BYTE *)&r)[0] = ((BYTE *)&value)[1];\r
2271         ((BYTE *)&r)[1] = ((BYTE *)&value)[0];\r
2272         return r;\r
2273 }\r
2274 \r
2275 // 32bit スワップ\r
2276 UINT Swap32(UINT value)\r
2277 {\r
2278         UINT r;\r
2279         // 汚いコード\r
2280         ((BYTE *)&r)[0] = ((BYTE *)&value)[3];\r
2281         ((BYTE *)&r)[1] = ((BYTE *)&value)[2];\r
2282         ((BYTE *)&r)[2] = ((BYTE *)&value)[1];\r
2283         ((BYTE *)&r)[3] = ((BYTE *)&value)[0];\r
2284         return r;\r
2285 }\r
2286 \r
2287 // 64bit スワップ\r
2288 UINT64 Swap64(UINT64 value)\r
2289 {\r
2290         UINT64 r;\r
2291         // 汚いコード\r
2292         ((BYTE *)&r)[0] = ((BYTE *)&value)[7];\r
2293         ((BYTE *)&r)[1] = ((BYTE *)&value)[6];\r
2294         ((BYTE *)&r)[2] = ((BYTE *)&value)[5];\r
2295         ((BYTE *)&r)[3] = ((BYTE *)&value)[4];\r
2296         ((BYTE *)&r)[4] = ((BYTE *)&value)[3];\r
2297         ((BYTE *)&r)[5] = ((BYTE *)&value)[2];\r
2298         ((BYTE *)&r)[6] = ((BYTE *)&value)[1];\r
2299         ((BYTE *)&r)[7] = ((BYTE *)&value)[0];\r
2300         return r;\r
2301 }\r
2302 \r
2303 // Base64 エンコード\r
2304 UINT Encode64(char *dst, char *src)\r
2305 {\r
2306         // 引数チェック\r
2307         if (dst == NULL || src == NULL)\r
2308         {\r
2309                 return 0;\r
2310         }\r
2311 \r
2312         return B64_Encode(dst, src, StrLen(src));\r
2313 }\r
2314 \r
2315 // Base64 デコード\r
2316 UINT Decode64(char *dst, char *src)\r
2317 {\r
2318         // 引数チェック\r
2319         if (dst == NULL || src == NULL)\r
2320         {\r
2321                 return 0;\r
2322         }\r
2323 \r
2324         return B64_Decode(dst, src, StrLen(src));\r
2325 }\r
2326 \r
2327 // Base64 エンコード\r
2328 int B64_Encode(char *set, char *source, int len)\r
2329 {\r
2330         BYTE *src;\r
2331         int i,j;\r
2332         src = (BYTE *)source;\r
2333         j = 0;\r
2334         i = 0;\r
2335         if (!len)\r
2336         {\r
2337                 return 0;\r
2338         }\r
2339         while (TRUE)\r
2340         {\r
2341                 if (i >= len)\r
2342                 {\r
2343                         return j;\r
2344                 }\r
2345                 if (set)\r
2346                 {\r
2347                         set[j] = B64_CodeToChar((src[i]) >> 2);\r
2348                 }\r
2349                 if (i + 1 >= len)\r
2350                 {\r
2351                         if (set)\r
2352                         {\r
2353                                 set[j + 1] = B64_CodeToChar((src[i] & 0x03) << 4);\r
2354                                 set[j + 2] = '=';\r
2355                                 set[j + 3] = '=';\r
2356                         }\r
2357                         return j + 4;\r
2358                 }\r
2359                 if (set)\r
2360                 {\r
2361                         set[j + 1] = B64_CodeToChar(((src[i] & 0x03) << 4) + ((src[i + 1] >> 4)));\r
2362                 }\r
2363                 if (i + 2 >= len)\r
2364                 {\r
2365                         if (set)\r
2366                         {\r
2367                                 set[j + 2] = B64_CodeToChar((src[i + 1] & 0x0f) << 2);\r
2368                                 set[j + 3] = '=';\r
2369                         }\r
2370                         return j + 4;\r
2371                 }\r
2372                 if (set)\r
2373                 {\r
2374                         set[j + 2] = B64_CodeToChar(((src[i + 1] & 0x0f) << 2) + ((src[i + 2] >> 6)));\r
2375                         set[j + 3] = B64_CodeToChar(src[i + 2] & 0x3f);\r
2376                 }\r
2377                 i += 3;\r
2378                 j += 4;\r
2379         }\r
2380 }\r
2381 \r
2382 // Base64 デコード\r
2383 int B64_Decode(char *set, char *source, int len)\r
2384 {\r
2385         int i,j;\r
2386         char a1,a2,a3,a4;\r
2387         char *src;\r
2388         int f1,f2,f3,f4;\r
2389         src = source;\r
2390         i = 0;\r
2391         j = 0;\r
2392         while (TRUE)\r
2393         {\r
2394                 f1 = f2 = f3 = f4 = 0;\r
2395                 if (i >= len)\r
2396                 {\r
2397                         break;\r
2398                 }\r
2399                 f1 = 1;\r
2400                 a1 = B64_CharToCode(src[i]);\r
2401                 if (a1 == -1)\r
2402                 {\r
2403                         f1 = 0;\r
2404                 }\r
2405                 if (i >= len + 1)\r
2406                 {\r
2407                         a2 = 0;\r
2408                 }\r
2409                 else\r
2410                 {\r
2411                         a2 = B64_CharToCode(src[i + 1]);\r
2412                         f2 = 1;\r
2413                         if (a2 == -1)\r
2414                         {\r
2415                                 f2 = 0;\r
2416                         }\r
2417                 }\r
2418                 if (i >= len + 2)\r
2419                 {\r
2420                         a3 = 0;\r
2421                 }\r
2422                 else\r
2423                 {\r
2424                         a3 = B64_CharToCode(src[i + 2]);\r
2425                         f3 = 1;\r
2426                         if (a3 == -1)\r
2427                         {\r
2428                                 f3 = 0;\r
2429                         }\r
2430                 }\r
2431                 if (i >= len + 3)\r
2432                 {\r
2433                         a4 = 0;\r
2434                 }\r
2435                 else\r
2436                 {\r
2437                         a4 = B64_CharToCode(src[i + 3]);\r
2438                         f4 = 1;\r
2439                         if (a4 == -1)\r
2440                         {\r
2441                                 f4 = 0;\r
2442                         }\r
2443                 }\r
2444                 if (f1 && f2)\r
2445                 {\r
2446                         if (set)\r
2447                         {\r
2448                                 set[j] = (a1 << 2) + (a2 >> 4);\r
2449                         }\r
2450                         j++;\r
2451                 }\r
2452                 if (f2 && f3)\r
2453                 {\r
2454                         if (set)\r
2455                         {\r
2456                                 set[j] = (a2 << 4) + (a3 >> 2);\r
2457                         }\r
2458                         j++;\r
2459                 }\r
2460                 if (f3 && f4)\r
2461                 {\r
2462                         if (set)\r
2463                         {\r
2464                                 set[j] = (a3 << 6) + a4;\r
2465                         }\r
2466                         j++;\r
2467                 }\r
2468                 i += 4;\r
2469         }\r
2470         return j;\r
2471 }\r
2472 \r
2473 // Base64 - コードを文字に変換\r
2474 char B64_CodeToChar(BYTE c)\r
2475 {\r
2476         BYTE r;\r
2477         r = '=';\r
2478         if (c <= 0x19)\r
2479         {\r
2480                 r = c + 'A';\r
2481         }\r
2482         if (c >= 0x1a && c <= 0x33)\r
2483         {\r
2484                 r = c - 0x1a + 'a';\r
2485         }\r
2486         if (c >= 0x34 && c <= 0x3d)\r
2487         {\r
2488                 r = c - 0x34 + '0';\r
2489         }\r
2490         if (c == 0x3e)\r
2491         {\r
2492                 r = '+';\r
2493         }\r
2494         if (c == 0x3f)\r
2495         {\r
2496                 r = '/';\r
2497         }\r
2498         return r;\r
2499 }\r
2500 \r
2501 // Base64 - 文字をコードに変換\r
2502 char B64_CharToCode(char c)\r
2503 {\r
2504         if (c >= 'A' && c <= 'Z')\r
2505         {\r
2506                 return c - 'A';\r
2507         }\r
2508         if (c >= 'a' && c <= 'z')\r
2509         {\r
2510                 return c - 'a' + 0x1a;\r
2511         }\r
2512         if (c >= '0' && c <= '9')\r
2513         {\r
2514                 return c - '0' + 0x34;\r
2515         }\r
2516         if (c == '+')\r
2517         {\r
2518                 return 0x3e;\r
2519         }\r
2520         if (c == '/')\r
2521         {\r
2522                 return 0x3f;\r
2523         }\r
2524         if (c == '=')\r
2525         {\r
2526                 return -1;\r
2527         }\r
2528         return 0;\r
2529 }\r
2530 \r
2531 // 高速な Malloc (現在未実装)\r
2532 // 実は小さなバッファをたくさんまとめておいてそれを動的に割り当てるコードを昔\r
2533 // 書いたのだが、Windows, Linux, Solaris で試しても普通の malloc() と比べて\r
2534 // ほとんど速度に影響がなかったので、やめにした。\r
2535 void *MallocFast(UINT size)\r
2536 {\r
2537         return Malloc(size);\r
2538 }\r
2539 \r
2540 // Malloc\r
2541 void *Malloc(UINT size)\r
2542 {\r
2543         return MallocEx(size, false);\r
2544 }\r
2545 void *MallocEx(UINT size, bool zero_clear_when_free)\r
2546 {\r
2547         MEMTAG *tag;\r
2548         UINT real_size;\r
2549 \r
2550         real_size = CALC_MALLOCSIZE(size);\r
2551 \r
2552         tag = InternalMalloc(real_size);\r
2553 \r
2554         Zero(tag, sizeof(MEMTAG));\r
2555         tag->Magic = MEMTAG_MAGIC;\r
2556         tag->Size = size;\r
2557         tag->ZeroFree = zero_clear_when_free;\r
2558 \r
2559         return MEMTAG_TO_POINTER(tag);\r
2560 }\r
2561 \r
2562 // ReAlloc\r
2563 void *ReAlloc(void *addr, UINT size)\r
2564 {\r
2565         MEMTAG *tag;\r
2566         bool zerofree;\r
2567         // 引数チェック\r
2568         if (IS_NULL_POINTER(addr))\r
2569         {\r
2570                 return NULL;\r
2571         }\r
2572 \r
2573         tag = POINTER_TO_MEMTAG(addr);\r
2574         CheckMemTag(tag);\r
2575 \r
2576         zerofree = tag->ZeroFree;\r
2577 \r
2578         if (tag->Size == size)\r
2579         {\r
2580                 // サイズ変更無し\r
2581                 return addr;\r
2582         }\r
2583         else\r
2584         {\r
2585                 if (zerofree)\r
2586                 {\r
2587                         // サイズ変更有り (ゼロクリア必須)\r
2588                         void *new_p = MallocEx(size, true);\r
2589 \r
2590                         if (tag->Size <= size)\r
2591                         {\r
2592                                 // サイズ拡大\r
2593                                 Copy(new_p, addr, tag->Size);\r
2594                         }\r
2595                         else\r
2596                         {\r
2597                                 // サイズ縮小\r
2598                                 Copy(new_p, addr, size);\r
2599                         }\r
2600 \r
2601                         // 古いブロックの解放\r
2602                         Free(addr);\r
2603 \r
2604                         return new_p;\r
2605                 }\r
2606                 else\r
2607                 {\r
2608                         // サイズ変更有り\r
2609                         MEMTAG *tag2 = InternalReAlloc(tag, CALC_MALLOCSIZE(size));\r
2610 \r
2611                         Zero(tag2, sizeof(MEMTAG));\r
2612                         tag2->Magic = MEMTAG_MAGIC;\r
2613                         tag2->Size = size;\r
2614 \r
2615                         return MEMTAG_TO_POINTER(tag2);\r
2616                 }\r
2617         }\r
2618 }\r
2619 \r
2620 // Free\r
2621 void Free(void *addr)\r
2622 {\r
2623         MEMTAG *tag;\r
2624         // 引数チェック\r
2625         if (IS_NULL_POINTER(addr))\r
2626         {\r
2627                 return;\r
2628         }\r
2629 \r
2630         tag = POINTER_TO_MEMTAG(addr);\r
2631         CheckMemTag(tag);\r
2632 \r
2633         if (tag->ZeroFree)\r
2634         {\r
2635                 // ゼロクリア\r
2636                 Zero(addr, tag->Size);\r
2637         }\r
2638 \r
2639         // メモリ解放\r
2640         tag->Magic = 0;\r
2641         InternalFree(tag);\r
2642 }\r
2643 \r
2644 // memtag をチェック\r
2645 void CheckMemTag(MEMTAG *tag)\r
2646 {\r
2647 #ifndef DONT_CHECK_HEAP\r
2648         // 引数チェック\r
2649         if (tag == NULL)\r
2650         {\r
2651                 AbortExitEx("CheckMemTag: tag == NULL");\r
2652                 return;\r
2653         }\r
2654 \r
2655         if (tag->Magic != MEMTAG_MAGIC)\r
2656         {\r
2657                 AbortExitEx("CheckMemTag: tag->Magic != MEMTAG_MAGIC");\r
2658                 return;\r
2659         }\r
2660 #endif  // DONT_CHECK_HEAP\r
2661 }\r
2662 \r
2663 // ZeroMalloc\r
2664 void *ZeroMalloc(UINT size)\r
2665 {\r
2666         return ZeroMallocEx(size, false);\r
2667 }\r
2668 void *ZeroMallocEx(UINT size, bool zero_clear_when_free)\r
2669 {\r
2670         void *p = MallocEx(size, zero_clear_when_free);\r
2671         Zero(p, size);\r
2672         return p;\r
2673 }\r
2674 void *ZeroMallocFast(UINT size)\r
2675 {\r
2676         void *p = MallocFast(size);\r
2677         Zero(p, size);\r
2678         return p;\r
2679 }\r
2680 \r
2681 // メモリ確保\r
2682 void *InternalMalloc(UINT size)\r
2683 {\r
2684         void *addr;\r
2685         UINT retry = 0;\r
2686         size = MORE(size, 1);\r
2687 \r
2688         // KS\r
2689         KS_INC(KS_MALLOC_COUNT);\r
2690         KS_INC(KS_TOTAL_MEM_COUNT);\r
2691         KS_ADD(KS_TOTAL_MEM_SIZE, size);\r
2692         KS_INC(KS_CURRENT_MEM_COUNT);\r
2693 \r
2694         // メモリが確保されるまで試行する\r
2695         while (true)\r
2696         {\r
2697                 if ((retry++) > MEMORY_MAX_RETRY)\r
2698                 {\r
2699                         AbortExitEx("InternalMalloc: error: malloc() failed.\n\n");\r
2700                 }\r
2701                 addr = OSMemoryAlloc(size);\r
2702                 if (addr != NULL)\r
2703                 {\r
2704                         break;\r
2705                 }\r
2706 \r
2707                 OSSleep(MEMORY_SLEEP_TIME);\r
2708         }\r
2709 \r
2710 #ifndef DONT_USE_KERNEL_STATUS\r
2711         TrackNewObj(POINTER_TO_UINT64(addr), "MEM", size);\r
2712 #endif  //DONT_USE_KERNEL_STATUS\r
2713 \r
2714         return addr;\r
2715 }\r
2716 \r
2717 // メモリ解放\r
2718 void InternalFree(void *addr)\r
2719 {\r
2720         // 引数チェック\r
2721         if (addr == NULL)\r
2722         {\r
2723                 return;\r
2724         }\r
2725 \r
2726         // KS\r
2727         KS_DEC(KS_CURRENT_MEM_COUNT);\r
2728         KS_INC(KS_FREE_COUNT);\r
2729 \r
2730 #ifndef DONT_USE_KERNEL_STATUS\r
2731         TrackDeleteObj(POINTER_TO_UINT64(addr));\r
2732 #endif  // DONT_USE_KERNEL_STATUS\r
2733 \r
2734         // メモリ解放\r
2735         OSMemoryFree(addr);\r
2736 }\r
2737 \r
2738 // メモリ再確保\r
2739 void *InternalReAlloc(void *addr, UINT size)\r
2740 {\r
2741         void *new_addr;\r
2742         UINT retry = 0;\r
2743         size = MORE(size, 1);\r
2744 \r
2745         // KS\r
2746         KS_INC(KS_REALLOC_COUNT);\r
2747         KS_ADD(KS_TOTAL_MEM_SIZE, size);\r
2748 \r
2749         // メモリが確保されるまで試行する\r
2750         while (true)\r
2751         {\r
2752                 if ((retry++) > MEMORY_MAX_RETRY)\r
2753                 {\r
2754                         AbortExitEx("InternalReAlloc: error: realloc() failed.\n\n");\r
2755                 }\r
2756                 new_addr = OSMemoryReAlloc(addr, size);\r
2757                 if (new_addr != NULL)\r
2758                 {\r
2759                         break;\r
2760                 }\r
2761 \r
2762                 OSSleep(MEMORY_SLEEP_TIME);\r
2763         }\r
2764 \r
2765 #ifndef DONT_USE_KERNEL_STATUS\r
2766         TrackChangeObjSize((DWORD)addr, size, (DWORD)new_addr);\r
2767 #endif  // DONT_USE_KERNEL_STATUS\r
2768 \r
2769         return new_addr;\r
2770 }\r
2771 \r
2772 // メモリ領域のクローン\r
2773 void *Clone(void *addr, UINT size)\r
2774 {\r
2775         void *ret;\r
2776         // 引数チェック\r
2777         if (addr == NULL)\r
2778         {\r
2779                 return NULL;\r
2780         }\r
2781 \r
2782         ret = Malloc(size);\r
2783         Copy(ret, addr, size);\r
2784 \r
2785         return ret;\r
2786 }\r
2787 \r
2788 // メモリコピー\r
2789 void Copy(void *dst, void *src, UINT size)\r
2790 {\r
2791         // 引数チェック\r
2792         if (dst == NULL || src == NULL || size == 0 || dst == src)\r
2793         {\r
2794                 return;\r
2795         }\r
2796 \r
2797         // KS\r
2798         KS_INC(KS_COPY_COUNT);\r
2799 \r
2800         memcpy(dst, src, size);\r
2801 }\r
2802 \r
2803 // メモリ比較\r
2804 int Cmp(void *p1, void *p2, UINT size)\r
2805 {\r
2806         // 引数チェック\r
2807         if (p1 == NULL || p2 == NULL || size == 0)\r
2808         {\r
2809                 return 0;\r
2810         }\r
2811 \r
2812         return memcmp(p1, p2, (size_t)size);\r
2813 }\r
2814 \r
2815 // メモリのゼロクリア\r
2816 void Zero(void *addr, UINT size)\r
2817 {\r
2818         ZeroMem(addr, size);\r
2819 }\r
2820 void ZeroMem(void *addr, UINT size)\r
2821 {\r
2822         // 引数チェック\r
2823         if (addr == NULL || size == 0)\r
2824         {\r
2825                 return;\r
2826         }\r
2827 \r
2828         // KS\r
2829         KS_INC(KS_ZERO_COUNT);\r
2830 \r
2831         memset(addr, 0, size);\r
2832 }\r
2833 \r
2834 // 文字列マップエントリの比較\r
2835 int StrMapCmp(void *p1, void *p2)\r
2836 {\r
2837         STRMAP_ENTRY *s1, *s2;\r
2838         if (p1 == NULL || p2 == NULL)\r
2839         {\r
2840                 return 0;\r
2841         }\r
2842         s1 = *(STRMAP_ENTRY **)p1;\r
2843         s2 = *(STRMAP_ENTRY **)p2;\r
2844         if (s1 == NULL || s2 == NULL)\r
2845         {\r
2846                 return 0;\r
2847         }\r
2848         return StrCmpi(s1->Name, s2->Name);\r
2849 }\r
2850 \r
2851 // 文字列マップ(文字列で検索できるデータ)の作成\r
2852 LIST *NewStrMap()\r
2853 {\r
2854         return NewList(StrMapCmp);\r
2855 }\r
2856 \r
2857 // 文字列マップの検索\r
2858 void *StrMapSearch(LIST *map, char *key)\r
2859 {\r
2860         STRMAP_ENTRY tmp, *result;\r
2861         tmp.Name = key;\r
2862         result = (STRMAP_ENTRY*)Search(map, &tmp);\r
2863         if(result != NULL)\r
2864         {\r
2865                 return result->Value;\r
2866         }\r
2867         return NULL;\r
2868 }\r