1 #include "common.h"
2 #include "bytecode.h"
3 #include "vm.h"
4
5
6 /******************************************************************************
7 * Summary: This file provides functionality for memory management.
8 ******************************************************************************/
9
10
11
12 /*** Locale functions ***/
13
14 uint STDCALL _mem_heapalloc( pvmEngine pThis, uint id )
15 {
16 uint size;
17 pheap p_heap;
18
19 size = ( MEM_HEAPSIZE << ( id >> 5 ));
20
21 p_heap = pThis->_memory.heaps + id;
22
23 p_heap->ptr = os_alloc( size + MAX_BYTE * sizeof( uint ));
24 if ( !p_heap->ptr )
25 return FALSE;
26 p_heap->chain = p_heap->ptr;
27 p_heap->size = size;
28 p_heap->remain = size;
29 p_heap->free = 0;
30 mem_zeroui( pThis, p_heap->chain, MAX_BYTE );
31
32 return TRUE;
33 }
34
35 //--------------------------------------------------------------------------
36
37 uint STDCALL _mem_heapfree( pvmEngine pThis, uint id )
38 {
39 pheap p_heap;
40
41 p_heap = pThis->_memory.heaps + id;
42 if ( p_heap->ptr )
43 // VirtualFree( p_heap->ptr, 0, MEM_RELEASE );
44 os_free( p_heap->ptr );
45 p_heap->ptr = 0;
46
47 return TRUE;
48 }
49
50 //--------------------------------------------------------------------------
51
52 uint STDCALL _mem_size2sid( pvmEngine pThis, uint size )
53 {
54 uint middle, right = 255;
55 uint left = 0;
56
57 while ( right > left )
58 {
59 middle = ( right + left ) >> 1;
60 if ( size > pThis->_memory.sid[ middle ] )
61 left = middle + 1;
62 else
63 right = middle;
64 }
65 return left;
66 }
67
68 /*--------------------------------------------------------------------------
69 *
70 * Public functions
71 *
72 */
73
74 /*--------------------------------------------------------------------------
75 * Description
76 * Allocate the memory.
77 *
78 * Parameters
79 * uint size, The required size.
80 *
81 * Result
82 * uint, The pointer to the memory or 0.
83 *
84 */
85
86 pvoid STDCALL mem_alloc( pvmEngine pThis, uint size )
87 {
88 uint sid, ih;
89 pvoid result = 0;
90 pheap p_heap;
91
92 os_crlsection_enter( &pThis->_crlmem );
93 if ( size > MEM_EDGE )
94 {
95 result = ( pubyte )os_alloc( size + 8 ) + 2;
96 *(( pubyte )result + 5 ) = MAX_BYTE;
97 *( puint )result = size;
98 result = ( pubyte )result + 6;
99 goto end;
100 }
101 sid = _mem_size2sid( pThis, size );
102
103 ih = pThis->_memory.last;
104 size = pThis->_memory.sid[ sid ] + 2;
105
106 again:
107 p_heap = pThis->_memory.heaps + ih;
108 if ( !p_heap->ptr && !_mem_heapalloc( pThis, ih ))
109 {
110 result = 0;
111 goto end;
112 }
113 if ( p_heap->chain[ sid ] )
114 {
115 p_heap->free -= size;
116 result = ( pvoid )p_heap->chain[ sid ];
117 p_heap->chain[ sid ] = *( puint )result;
118 }
119 else
120 {
121 if ( size <= p_heap->remain )
122 {
123 result = ( pubyte )p_heap->ptr + MAX_BYTE * sizeof( uint ) +
124 p_heap->size - p_heap->remain;
125 *(( pubyte )result)++ = ( byte )ih;
126 *(( pubyte )result)++ = ( byte )sid;
127 p_heap->remain -= size;
128 }
129 else
130 {
131 if ( pThis->_memory.last )
132 {
133 pThis->_memory.last = 0;
134 ih = 0;
135 }
136 else
137 ih++;
138 goto again;
139 }
140 }
141 pThis->_memory.last = ih;
142
143 end:
144 os_crlsection_leave( &pThis->_crlmem );
145 mem_zero( pThis, result, size );
146 return result;
147 }
148
149 //--------------------------------------------------------------------------
150
151 pvoid STDCALL mem_copy( pvmEngine pThis, pvoid dest, pvoid src, uint len )
152 {
153 puint psrc = ( puint )src;
154 puint pdest = ( puint )dest;
155 uint ilen = len >> 2;
156
157 while ( ilen-- )
158 *pdest++ = *psrc++;
159
160 len &= 0x3;
161 while ( len-- )
162 *((pubyte)pdest)++ = *((pubyte)psrc)++;
163
164 return dest;
165 }
166
167 //--------------------------------------------------------------------------
168
169 uint STDCALL mem_deinit( pvmEngine pThis )
170 {
171 uint i;
172
173 for ( i = 0; i <= MAX_BYTE; i++ )
174 _mem_heapfree( pThis, i );
175
176 os_free( pThis->_memory.sid );
177 os_free( pThis->_memory.heaps );
178
179 os_crlsection_delete( &pThis->_crlmem );
180
181 return TRUE;
182 }
183
184 //--------------------------------------------------------------------------
185
186 uint STDCALL mem_free( pvmEngine pThis, pvoid ptr )
187 {
188 pubyte p_id;
189 uint sid;
190 pheap p_heap;
191
192 if ( !ptr ) return TRUE;
193
194 os_crlsection_enter( &pThis->_crlmem );
195
196 sid = *(( pubyte )ptr - 1 );
197 p_id = ( pubyte )ptr - 2;
198
199 if ( sid == MAX_BYTE )
200 {
201 os_free( ( pubyte )ptr - 8 );
202 goto end;
203 }
204 p_heap = pThis->_memory.heaps + *p_id;
205 *( puint )ptr = p_heap->chain[ sid ];
206 p_heap->chain[ sid ] = ( uint )ptr;
207
208 p_heap->free += pThis->_memory.sid[ sid ] + 2;
209
210 if ( p_heap->free + p_heap->remain == p_heap->size )
211 _mem_heapfree( pThis, *p_id );
212
213 end:
214 os_crlsection_leave( &pThis->_crlmem );
215
216 return TRUE;
217 }
218
219 //--------------------------------------------------------------------------
220
221 uint STDCALL mem_getsize( pvmEngine pThis, pvoid ptr )
222 {
223 uint sid;
224
225 if (( sid = *((pubyte)ptr - 1 )) == MAX_BYTE )
226 return *( puint )((pubyte)ptr - 8 );
227 return pThis->_memory.sid[ sid ];
228 }
229
230 //--------------------------------------------------------------------------
231
232 uint STDCALL mem_init( pvmEngine pThis )
233 {
234 uint i, size, step = 8;
235
236 pThis->_memory.sid = os_alloc(( MAX_BYTE + 1 ) * sizeof( uint ));
237 pThis->_memory.sid[ 0 ] = step;
238
239 for ( i = 1; i < MAX_BYTE - 1; i++ )
240 {
241 if ( !( i & 0xF ))
242 step <<= 1;
243 pThis->_memory.sid[ i ] = pThis->_memory.sid[ i - 1 ] + step;
244 }
245 pThis->_memory.sid[ MAX_BYTE ] = MAX_UINT;
246
247 pThis->_memory.heaps = os_alloc( size = (MAX_BYTE + 1) * sizeof( heap ));
248 mem_zero( pThis, pThis->_memory.heaps, size );
249
250 os_crlsection_init( &pThis->_crlmem );
251 pThis->_memory.last = 0;
252
253 return TRUE;
254 }
255
256 //--------------------------------------------------------------------------
257
258 uint STDCALL mem_len( pvmEngine pThis, pvoid data )
259 {
260 pubyte temp = ( pubyte )data;
261
262 while ( *temp++ );
263
264 return ( uint )( temp - ( pubyte )data - 1 );
265 }
266
267 //--------------------------------------------------------------------------
268
269 //--------------------------------------------------------------------------
270
271 void STDCALL mem_move( pvmEngine pThis, pvoid dest, pvoid src, uint len )
272 {
273 puint psrc;
274 puint pdest;
275 uint ilen;
276
277 if ( ( pubyte )dest <= ( pubyte )src ||
278 ( pubyte )dest >= ( pubyte )src + len )
279 mem_copy( pThis, dest, src, len );
280 else
281 {
282 ilen = len >> 2;
283 // области памяти пересекаются и надо копировать с конца
284 pdest = ( puint )( ( pubyte )dest + len - sizeof( uint ));
285 psrc = ( puint )(( pubyte )src + len - sizeof( uint ));
286 while ( ilen-- )
287 *pdest-- = *psrc--;
288
289 len &= 0x3;
290 while ( len-- )
291 *( ( pubyte )dest + len ) = *( ( pubyte )src + len );
292 }
293 }
294
295 //--------------------------------------------------------------------------
296
297 pvoid STDCALL mem_zero( pvmEngine pThis, pvoid dest, uint len )
298 {
299 puint p_dest = ( puint )dest;
300 uint ilen = len >> 2;
301
302 while ( ilen-- )
303 *p_dest++ = 0;
304
305 len &= 0x3;
306 while ( len-- )
307 *((pubyte)p_dest)++ = 0;
308
309 return dest;
310 }
311
312 //--------------------------------------------------------------------------
313
314 int STDCALL mem_cmp( pvmEngine pThis, pvoid dest, pvoid src, uint len )
315 {
316 puint dsrc = ( puint )src;
317 puint ddest = ( puint )dest;
318 uint ilen = len >> 2;
319 int i;
320
321 while ( ilen-- )
322 if ( *ddest++ != *dsrc++ )
323 {
324 ddest--;
325 dsrc--;
326 for ( i = 0; i < 4; i++ )
327 {
328 if ( *((pubyte)ddest) > *((pubyte)dsrc) )
329 return 1;
330 if ( *((pubyte)ddest)++ < *((pubyte)dsrc)++ )
331 return -1;
332 }
333 }
334
335 len &= 0x3;
336 while ( len-- )
337 {
338 if ( *((pubyte)ddest) > *((pubyte)dsrc) )
339 return 1;
340 if ( *((pubyte)ddest)++ < *((pubyte)dsrc)++ )
341 return -1;
342 }
343
344 return 0;
345 }
346
347
348 //--------------------------------------------------------------------------
349
350 void STDCALL mem_zeroui( pvmEngine pThis, puint dest, uint len )
351 {
352 while ( len-- )
353 *dest++ = 0;
354 }
355
356
357
358 //--------------------------------------------------------------------------
359
360 uint STDCALL mem_copyuntilzero( pvmEngine pThis, pubyte dest, pubyte src )
361 {
362 pubyte temp = dest;
363
364 while ( *src )
365 *temp++ = *src++;
366 *temp = 0;
367 return ( uint )( temp - dest + 1 );
368 }
369
370
371 /******************************************************************************
372 *
373 * Summary: This file provides functionality for 'buf' type.
374 *
375 ******************************************************************************/
376
377
378 pbuf STDCALL buf_alloc( pvmEngine pThis, pbuf pb, uint size )
379 {
380 mem_free( pThis, pb->data );
381
382 pb->data = mem_alloc( pThis, size );
383 pb->size = mem_getsize( pThis, pb->data );
384 pb->use = 0;
385
386 return pb;
387 }
388
389
390 /*-----------------------------------------------------------------------------
391 *
392 * ID: buf_appendch 19.10.06 0.0.A.
393 *
394 * Summary: Append a ubyte to buf
395 *
396 -----------------------------------------------------------------------------*/
397
398 pbuf STDCALL buf_append( pvmEngine pThis, pbuf pb, pubyte src, uint size )
399 {
400 buf_expand( pThis, pb, size + 1 );
401 mem_copy( pThis, pb->data + pb->use, src, size );
402 pb->use += size;
403
404 return pb;
405 }
406
407 pbuf STDCALL buf_appendch( pvmEngine pThis, pbuf pb, ubyte val )
408 {
409 buf_expand( pThis, pb, 1 );
410 *( pb->data + pb->use ) = val;
411 pb->use++;
412 return pb;
413 }
414
415 pbuf STDCALL buf_appenduint( pvmEngine pThis, pbuf pb, uint val )
416 {
417 buf_expand( pThis, pb, sizeof( uint ));
418 *( pint )( pb->data + pb->use ) = val;
419 pb->use += sizeof( uint );
420
421 return pb;
422 }
423
424
425 pbuf STDCALL buf_appendushort( pvmEngine pThis, pbuf pb, ushort val )
426 {
427 buf_expand( pThis, pb, sizeof( ushort ));
428 *( pushort )( pb->data + pb->use ) = val;
429 pb->use += sizeof( ushort );
430
431 return pb;
432 }
433
434 pbuf STDCALL buf_copy( pvmEngine pThis, pbuf pb, pubyte src, uint size )
435 {
436 pb->use = 0;
437 buf_reserve( pThis, pb, size + 1 );
438 mem_copy( pThis, pb->data, src, size );
439 pb->use = size;
440
441 return pb;
442 }
443
444
445 //--------------------------------------------------------------------------
446
447 pbuf STDCALL buf_copyzero( pvmEngine pThis, pbuf pb, pubyte src )
448 {
449 return buf_copy( pThis, pb, src, mem_len( pThis, src ) + 1 );
450 }
451
452 //--------------------------------------------------------------------------
453
454 void STDCALL buf_delete( pvmEngine pThis, pbuf pb )
455 {
456 mem_free( pThis, pb->data );
457 pb->data = NULL;
458 }
459
460 //--------------------------------------------------------------------------
461
462 pbuf STDCALL buf_init( pvmEngine pThis, pbuf pb )
463 {
464 mem_zero( pThis, pb, sizeof( buf ));
465 return pb;
466 }
467
468 //--------------------------------------------------------------------------
469
470 pbuf STDCALL buf_insert( pvmEngine pThis, pbuf pb, uint off, pubyte data, uint size )
471 {
472 if ( off > pb->use )
473 off = pb->use;
474
475 buf_expand( pThis, pb, size );
476 mem_move( pThis, pb->data + off + size, pb->data + off, pb->use - off );
477 if ( data )
478 mem_copy( pThis, pb->data + off, data, size );
479 pb->use += size;
480
481 return pb;
482 }
483
484 uint STDCALL buf_len( pvmEngine pThis, pbuf pb )
485 {
486 return pb->use;
487 }
488
489 pubyte STDCALL buf_ptr( pvmEngine pThis, pbuf pb )
490 {
491 return pb->data;
492 }
493
494 //--------------------------------------------------------------------------
495 // size - the additional size
496
497 pbuf STDCALL buf_expand( pvmEngine pThis, pbuf pb, uint size )
498 {
499 uint tmp;
500 pubyte old = pb->data;
501 uint use = pb->use;
502
503 size += use; // only size is additional size
504 if ( size <= pb->size )
505 return pb;
506
507 if ( !pb->step )
508 pb->step = max( size/2, 32 );
509 else
510 if ( pb->step < pb->size / 2 )
511 pb->step = pb->size / 2;
512
513 tmp = pb->size + pb->step;
514 if ( size < tmp )
515 size = tmp;
516 pb->data = 0;
517 buf_alloc( pThis, pb, size );
518 if ( old )
519 {
520 mem_copy( pThis, pb->data, old, use );
521 pb->use = use;
522 mem_free( pThis, old );
523 }
524
525 return pb;
526 }
527
528
529 //--------------------------------------------------------------------------
530 // size - the full required size
531
532 pbuf STDCALL buf_reserve( pvmEngine pThis, pbuf pb, uint size )
533 {
534 if ( size <= pb->size )
535 return pb;
536
537 return buf_expand( pThis, pb, size - pb->use );
538 }
539
540 /*-----------------------------------------------------------------------------
541 *
542 * ID: buf_setlen 19.10.06 0.0.A.
543 *
544 * Summary: Set the length of the buffer
545 *
546 -----------------------------------------------------------------------------*/
547
548 pbuf STDCALL buf_setlen( pvmEngine pThis, pbuf pb, uint len )
549 {
550 pb->use = len > pb->size ? pb->size : len ;
551
552 return pb;
553 }
554
555
556
557 /******************************************************************************
558 *
559 *
560 ******************************************************************************/
561
562
563 //--------------------------------------------------------------------------
564 // Возвращается указатель на добавленный элемент
565
566 pvoid STDCALL arr_append( pvmEngine pThis, parr pa )
567 {
568 arr_reserve( pThis, pa, 1 );
569
570 mem_zero( pThis, buf_ptr( pThis, &pa->data ) + pa->data.use, pa->isize );
571 pa->data.use += pa->isize;
572
573 return buf_ptr( pThis, &pa->data ) + pa->data.use - pa->isize;
574 }
575
576 //--------------------------------------------------------------------------
577
578 uint STDCALL arr_appenditems( pvmEngine pThis, parr pa, uint count )
579 {
580 uint size = count * pa->isize;
581
582 arr_reserve( pThis, pa, count );
583
584 mem_zero( pThis, buf_ptr( pThis, &pa->data ) + pa->data.use, size );
585 pa->data.use += size;
586
587 // printf("Append %i size=%i\n", pa->data.use, pa->data.size );
588 return pa->data.use / pa->isize;
589 }
590
591 //--------------------------------------------------------------------------
592
593 void STDCALL arr_appendnum( pvmEngine pThis, parr pa, uint val )
594 {
595 *( puint )arr_append( pThis, pa ) = val;
596 }
597
598 //--------------------------------------------------------------------------
599
600
601 //--------------------------------------------------------------------------
602
603 uint STDCALL arr_count( pvmEngine pThis, parr pa )
604 {
605 return buf_len( pThis, &pa->data ) / pa->isize;
606 }
607
608 //--------------------------------------------------------------------------
609
610 void STDCALL arr_delete( pvmEngine pThis, parr pa )
611 {
612 puint ptr, end;
613
614 if ( pa->isobj )
615 {
616 ptr = ( puint )buf_ptr( pThis, &pa->data );
617 end = ( puint )(( pubyte )ptr + buf_len( pThis, &pa->data ));
618 while ( ptr < end )
619 {
620 mem_free( pThis, ( pvoid )*ptr );
621 ptr++;
622 }
623 }
624 buf_delete( pThis, &pa->data );
625 }
626
627 //--------------------------------------------------------------------------
628
629 uint STDCALL arr_getuint( pvmEngine pThis, parr pa, uint num )
630 {
631 return *( puint )( buf_ptr( pThis, &pa->data ) + num * pa->isize );
632 }
633
634 //--------------------------------------------------------------------------
635
636 void STDCALL arr_init( pvmEngine pThis, parr pa, uint size )
637 {
638 buf_init( pThis, &pa->data );
639
640 pa->isobj = 0;
641 if ( !size )
642 {
643 size = sizeof( uint );
644 pa->isobj = 1;
645 }
646 pa->isize = size;
647 }
648
649 //--------------------------------------------------------------------------
650
651 pvoid STDCALL arr_ptr( pvmEngine pThis, parr pa, uint num )
652 {
653 return buf_ptr( pThis, &pa->data ) + num * pa->isize;
654 }
655
656
657 //--------------------------------------------------------------------------
658 // count - количество резервируемых элементов
659
660 void STDCALL arr_reserve( pvmEngine pThis, parr pa, uint count )
661 {
662 buf_expand( pThis, &pa->data, count * pa->isize );
663 }
664
665 //--------------------------------------------------------------------------
666
667 void STDCALL arr_setuint( pvmEngine pThis, parr pa, uint num, uint value )
668 {
669 *( puint )( buf_ptr( pThis, &pa->data ) + num * pa->isize ) = value;
670 }
671
672 //--------------------------------------------------------------------------
673 // count - количество резервируемых элементов
674
675 void STDCALL arr_step( pvmEngine pThis, parr pa, uint count )
676 {
677 pa->data.step = count * pa->isize;
678 }
679
680
681 /******************************************************************************
682 * Summary: This file provides functionality for 'str' type.
683 *
684 ******************************************************************************/
685
686
687 /*-----------------------------------------------------------------------------
688 *
689 * ID: str_copy 19.10.06 0.0.A.
690 *
691 * Summary: Copy the string
692 *
693 -----------------------------------------------------------------------------*/
694
695 pstr STDCALL str_copy( pvmEngine pThis, pstr dest, pstr src )
696 {
697 return buf_copy( pThis, ( pbuf )dest, str_ptr( src ), src->use );
698 }
699
700 //--------------------------------------------------------------------------
701
702 pstr STDCALL str_copyzero( pvmEngine pThis, pstr ps, pubyte src )
703 {
704 ps->use--;
705 buf_copyzero( pThis, ps, src );
706 return ps;
707 }
708
709
710 pstr STDCALL str_init( pvmEngine pThis, pstr ps )
711 {
712 mem_zero( pThis, ps, sizeof( str ));
713
714 buf_alloc( pThis, ps, 32 );
715 ps->data[0] = 0;
716 ps->use = 1;
717 // print("String Init %x\n", ps );
718 return ps;
719 }
720
721
722 uint STDCALL str_len( pvmEngine pThis, pstr ps )
723 {
724 return ps->use - 1;
725 }
726
727
728
729 /*-----------------------------------------------------------------------------
730 *
731 * ID: str_setlen 19.10.06 0.0.A.
732 *
733 * Summary: Reserve string space
734 *
735 * Params: len - additional required size
736 *
737 -----------------------------------------------------------------------------*/
738
739 pstr STDCALL str_setlen( pvmEngine pThis, pstr ps, uint len )
740 {
741 if ( len >= ps->size )
742 len = 0;
743
744 ps->use = len + 1;
745 ps->data[ len ] = 0;
746
747 return ps;
748 }
749
750 /*-----------------------------------------------------------------------------
751 *
752 * ID: str_new 19.10.06 0.0.A.
753 *
754 * Summary: Create str object.
755 *
756 -----------------------------------------------------------------------------*/
757
758 pstr STDCALL str_new( pvmEngine pThis, pubyte ptr )
759 {
760 pstr ret = mem_alloc( pThis, sizeof( str ));
761
762 str_init( pThis, ret );
763 if ( ptr )
764 str_copyzero( pThis, ret, ptr );
765
766 return ret;
767 }
768
769
770
771 /******************************************************************************
772 *
773 ******************************************************************************/
774
775
776 //--------------------------------------------------------------------------
777
778 puint STDCALL collect_add( pvmEngine pThis, pcollect pclt, puint input, uint type )
779 {
780 // uint value;
781
782 pclt->count++;
783 buf_appenduint( pThis, ( pbuf )pclt, type );
784 if ( (( povmtype )PCMD( type ))->stsize == 2 )
785 {
786 pclt->flag |= 0x01;
787 buf_append( pThis, ( pbuf )pclt, ( pubyte )input, sizeof( long64 ));
788 return input + 2;
789 }
790 else
791 {
792 buf_appenduint( pThis, ( pbuf )pclt, *input );
793 }
794 return input + 1;
795 }
796
797 pubyte STDCALL collect_addptr( pvmEngine pThis, pcollect pclt, pubyte ptr )
798 {
799 pstr ps = str_new( pThis, ptr );
800
801 collect_add( pThis, pclt, ( puint )&ps, TStr );
802 return ptr + mem_len( pThis, ptr ) + 1;
803 }
804
805 pubyte STDCALL collect_index( pvmEngine pThis, pcollect pclt, uint index )
806 {
807 uint i;
808 uint off = 0;
809
810 if ( index >= pclt->count )
811 return 0;
812
813 if ( pclt->flag & 0x01 )
814 {
815 for( i = 0; i < index; i++ )
816 {
817 off += sizeof( uint ) + ((( povmtype )PCMD( *( puint )(
818 buf_ptr( pThis, ( pbuf )pclt ) + off ) ))->stsize << 2 );
819 }
820 }
821 else
822 off = ( index << 3 );
823 return buf_ptr( pThis, ( pbuf )pclt ) + off + sizeof( uint );
824 }
825
826 uint STDCALL collect_gettype( pvmEngine pThis, pcollect pclt, uint index )
827 {
828 if ( index < pclt->count )
829 return *(( puint )collect_index( pThis, pclt, index ) - 1 );
830 return 0;
831 }
832
833
834 uint STDCALL collect_count( pvmEngine pThis, pcollect pclt )
835 {
836 return pclt->count;
837 }
838
839 void STDCALL collect_delete( pvmEngine pThis, pcollect pclt )
840 {
841 // !!! сделать collect_delete() с учетом поля owner. Добавить поле.
842 }
843
844
845 /******************************************************************************
846 *
847 *
848 ******************************************************************************/
849
850
851 void STDCALL hash_delete( pvmEngine pThis, phash ph )
852 {
853 arr_delete( pThis, &ph->values );
854 arr_delete( pThis, &ph->names );
855 }
856
857 //--------------------------------------------------------------------------
858
859 phashitem STDCALL _hash_find( pvmEngine pThis, phash ph, pubyte name, uint create )
860 {
861 pubyte ptr = name;
862 ushort val = 0;
863 uint len = 0;
864 ubyte shift = 0;
865 ushort nameoff;
866 phashitem phi = 0, prev = 0;
867
868 // Вычисляем хэш-значение строки
869 while ( *ptr )
870 {
871 val += (( ushort )*ptr++ ) << shift;
872 if ( ++shift > 7 )
873 shift = 0;
874 len++;
875 }
876 // получаем номер в хэш-таблице
877 val &= HASH_SIZE - 1;
878 phi = prev = ( phashitem )arr_getuint( pThis, &ph->values, val );
879 nameoff = sizeof( hashitem ) + ph->isize;
880 while ( phi )
881 {
882 if ( len == phi->len && !(/* ph->ignore ?
883 mem_cmpign( pThis, name, ( pubyte )phi + nameoff, len ) : */
884 mem_cmp( pThis, name, ( pubyte )phi + nameoff, len )))
885 // нашли совпадение
886 return phi;
887 phi = ( phashitem )phi->next;
888 }
889 if ( create )
890 {
891 // Будем добавлять элемент в таблицу имен
892 phi = ( phashitem )mem_alloc( pThis, nameoff + len + 1 );
893 phi->len = ( ushort )len;
894 phi->next = ( pvoid )prev;
895 phi->id = arr_count( pThis, &ph->names );
896 mem_zero( pThis, ( pubyte )phi + sizeof( hashitem ), ph->isize );
897 mem_copy( pThis, ( pubyte )phi + nameoff, name, len + 1 );
898 arr_appendnum( pThis, &ph->names, ( uint )phi );
899 arr_setuint( pThis, &ph->values, val, ( uint )phi );
900 }
901 return phi;
902 }
903
904 //--------------------------------------------------------------------------
905
906 phashitem STDCALL hash_find( pvmEngine pThis, phash ph, pubyte name )
907 {
908 return _hash_find( pThis, ph, name, 0 );
909 }
910
911 //--------------------------------------------------------------------------
912
913 void STDCALL hash_init( pvmEngine pThis, phash ph, uint isize )
914 {
915 arr_init( pThis, &ph->values, sizeof( uint ));
916 arr_appenditems( pThis, &ph->values, HASH_SIZE );
917
918 arr_init( pThis, &ph->names, 0 );
919 arr_step( pThis, &ph->names, 512 );
920 ph->isize = isize;
921 ph->ignore = 0;
922 }
923
924 //--------------------------------------------------------------------------
925
926 phashitem STDCALL hash_create( pvmEngine pThis, phash ph, pubyte name )
927 {
928 return _hash_find( pThis, ph, name, 1 );
929 }
930
931 //--------------------------------------------------------------------------
932
933
934
935 /******************************************************************************
936 *
937 * Summary: This file provides calculating CRC32.
938 *
939 ******************************************************************************/
940
941
942 //--------------------------------------------------------------------------
943
944 void STDCALL crc_init( pvmEngine pThis )
945 {
946 uint reg, polinom, i, ib;
947
948 polinom = 0xEDB88320;
949 pThis->_crctbl[ 0 ] = 0;
950
951 for ( i = 1; i < 256; i++ )
952 {
953 reg = 0;
954 for ( ib = i | 256; ib != 1; ib >>= 1 )
955 {
956 reg = ( reg & 1 ? (reg >> 1) ^ polinom : reg >> 1 );
957 if ( ib & 1 )
958 reg ^= polinom;
959 }
960 pThis->_crctbl[ i ] = reg;
961 }
962 }
963
964 //--------------------------------------------------------------------------
965 // seed must be 0xFFFFFFFF in the first calling
966
967 uint STDCALL crc( pvmEngine pThis, pubyte data, uint size, uint seed )
968 {
969 while ( size-- )
970 seed = pThis->_crctbl[((ushort)seed ^ ( *data++ )) & 0xFF ] ^ ( seed >> 8 );
971
972 return seed;
973 }
974
975 //--------------------------------------------------------------------------
976
977
978 /*-----------------------------------------------------------------------------
979 *
980 * ID: file2buf 23.10.06 0.0.A.
981 *
982 * Summary: Read file to buf. Result must be destroy later. name is converted
983 into the full name.
984 *
985 -----------------------------------------------------------------------------*/
986
987 pbuf STDCALL file2buf( pvmEngine pThis, pstr name, pbuf ret, uint pos )
988 {
989 str filename;
990 uint search = 0;
991 uint handle, size;
992 // parrdata pad;
993
994 str_init( pThis, &filename );
995 os_filefullname( pThis, name, &filename );
996
997 handle = os_fileopen( &filename, FOP_READONLY );
998 if ( !handle )
999 {
1000 longjmp( pThis->stack_state, -1 );//msg( pThis, MFileopen | MSG_STR | MSG_EXIT | MSG_POS, &filename, pos );
1001 }
1002 size = ( uint )os_filesize( handle );
1003 buf_reserve( pThis, ret, size );
1004
1005 if ( size && !os_fileread( handle, buf_ptr( pThis, ret ), size ))
1006 longjmp( pThis->stack_state, -1 );//msg( pThis, MFileread | MSG_STR | MSG_EXIT | MSG_POS, &filename, pos );
1007
1008 buf_setlen( pThis, ret, size );
1009 os_fileclose( handle );
1010
1011 str_copy( pThis, name, &filename );
1012
1013 str_delete( pThis, &filename );
1014
1015 return ret;
1016 }
1017
1018 uint STDCALL buf2file( pvmEngine pThis, pstr name, pbuf out )
1019 {
1020 str filename;
1021 uint handle;
1022
1023 str_init( pThis, &filename );
1024 str_reserve( pThis, &filename, 512 );
1025 str_reserve( pThis, &filename, 512 );
1026 os_filefullname( pThis, name, &filename );
1027
1028 handle = os_fileopen( &filename, FOP_CREATE );
1029 if ( !handle )
1030 longjmp( pThis->stack_state, -1 );//msg( pThis, MFileopen | MSG_STR | MSG_EXIT, &filename );
1031
1032 if ( !os_filewrite( handle, buf_ptr( pThis, out ), buf_len( pThis, out ) ))
1033 longjmp( pThis->stack_state, -1 );//msg( pThis, MFileread | MSG_STR | MSG_EXIT, &filename );
1034
1035 os_fileclose( handle );
1036
1037 str_copy( pThis, name, &filename );
1038 str_delete( pThis, &filename );
1039
1040 return 1;
1041 }
1042
1043
1044 /*-----------------------------------------------------------------------------
1045 * Summary: Close the file
1046 -----------------------------------------------------------------------------*/
1047
1048 uint STDCALL os_fileclose( uint handle )
1049 {
1050 return CloseHandle(( pvoid )handle );
1051 }
1052
1053 /*-----------------------------------------------------------------------------
1054 * Summary: Get the full name of the file
1055 -----------------------------------------------------------------------------*/
1056
1057 pstr STDCALL os_filefullname( pvmEngine pThis, pstr filename, pstr result )
1058 {
1059 uint len;
1060 pubyte ptr;
1061
1062 str_reserve( pThis, result, 512 );
1063 len = GetFullPathName( str_ptr( filename ), 512, str_ptr( result ), &ptr );
1064 str_setlen( pThis, result, len );
1065 return result;
1066 }
1067
1068
1069 uint STDCALL os_fileopen( pstr name, uint flag )
1070 {
1071 uint ret;
1072
1073 ret = ( uint )CreateFile( str_ptr( name ), ( flag & FOP_READONLY ? GENERIC_READ :
1074 GENERIC_READ | GENERIC_WRITE ), ( flag & FOP_EXCLUSIVE ? 0 :
1075 FILE_SHARE_READ | FILE_SHARE_WRITE ), NULL,
1076 ( flag & FOP_CREATE ? CREATE_ALWAYS :
1077 ( flag & FOP_IFCREATE ? OPEN_ALWAYS : OPEN_EXISTING )),
1078 0, NULL );
1079 return ret == ( uint )INVALID_HANDLE_VALUE ? 0 : ret ;
1080 }
1081
1082
1083 uint STDCALL os_fileread( uint handle, pubyte data, uint size )
1084 {
1085 uint read;
1086
1087 if ( !ReadFile( (pvoid)handle, data, size, &read, NULL ) || read != size )
1088 return FALSE;
1089 return read;
1090 }
1091
1092 ulong64 STDCALL os_filesize( uint handle )
1093 {
1094 LARGE_INTEGER li;
1095
1096 li.LowPart = GetFileSize( ( pvoid )handle, &li.HighPart );
1097
1098 if ( li.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR )
1099 return -1L;
1100
1101 return li.QuadPart;
1102 }
1103
1104 //--------------------------------------------------------------------------
1105
1106 uint STDCALL os_filewrite( uint handle, pubyte data, uint size )
1107 {
1108 uint write;
1109
1110 if ( !WriteFile( ( pvoid )handle, data, size, &write, NULL ) || write != size )
1111 return FALSE;
1112 return write;
1113 }
1114
1115
1116