File Coverage

blib/lib/AutoXS/Header.pm
Criterion Covered Total %
statement 15 16 93.7
branch 4 6 66.6
condition 2 3 66.6
subroutine 4 4 100.0
pod 0 1 0.0
total 25 30 83.3


line stmt bran cond sub pod time code
1             package AutoXS::Header;
2              
3 1     1   34033 use 5.006;
  1         4  
  1         53  
4 1     1   7 use strict;
  1         1  
  1         37  
5 1     1   23 use warnings;
  1         7  
  1         244  
6              
7             our $VERSION = '1.02';
8              
9             sub WriteAutoXSHeader {
10 2     2 0 573 my $filename = shift;
11 2 50 66     14 if (defined $filename and $filename eq 'AutoXS::Header') {
12 0         0 $filename = shift;
13             }
14 2 100       12 $filename = 'AutoXS.h' if not defined $filename;
15 2 50       184 open my $fh, '>', $filename
16             or die "Could not open '$filename' for writing: $!";
17 2         32 print $fh "/* AutoXS::Header version '$VERSION' */\n";
18 2         100 print $fh <<'AUTOXSHEADERHEREDOC';
19             typedef struct {
20             U32 hash;
21             SV* key;
22             } autoxs_hashkey;
23              
24             /* prototype section */
25              
26             I32 get_hashkey_index(const char* key, const I32 len);
27             I32 _new_hashkey();
28             void _resize_array(I32** array, unsigned int* len, unsigned int newlen);
29             void _resize_array_init(I32** array, unsigned int* len, unsigned int newlen, I32 init);
30             I32 _new_internal_arrayindex();
31             I32 get_internal_array_index(I32 object_ary_idx);
32              
33             /* initialization section */
34              
35             unsigned int AutoXS_no_hashkeys = 0;
36             unsigned int AutoXS_free_hashkey_no = 0;
37             autoxs_hashkey* AutoXS_hashkeys = NULL;
38             HV* AutoXS_reverse_hashkeys = NULL;
39              
40             unsigned int AutoXS_no_arrayindices = 0;
41             unsigned int AutoXS_free_arrayindices_no = 0;
42             I32* AutoXS_arrayindices = NULL;
43              
44             unsigned int AutoXS_reverse_arrayindices_length = 0;
45             I32* AutoXS_reverse_arrayindices = NULL;
46              
47              
48             /* implementation section */
49              
50             I32 get_hashkey_index(const char* key, const I32 len) {
51             I32 index;
52              
53             /* init */
54             if (AutoXS_reverse_hashkeys == NULL)
55             AutoXS_reverse_hashkeys = newHV();
56              
57             index = 0;
58             if ( hv_exists(AutoXS_reverse_hashkeys, key, len) ) {
59             SV** index_sv = hv_fetch(AutoXS_reverse_hashkeys, key, len, 0);
60              
61             /* simply return the index that corresponds to an earlier
62             * use with the same hash key name */
63              
64             if ( (index_sv == NULL) || (!SvIOK(*index_sv)) ) {
65             /* shouldn't happen */
66             index = _new_hashkey();
67             }
68             else /* Note to self: Check that this I32 cast is sane */
69             return (I32)SvIVX(*index_sv);
70             }
71             else /* does not exist */
72             index = _new_hashkey();
73              
74             /* store the new hash key in the reverse lookup table */
75             hv_store(AutoXS_reverse_hashkeys, key, len, newSViv(index), 0);
76             return index;
77             }
78              
79             /* this is private, call get_hashkey_index instead */
80             I32 _new_hashkey() {
81             if (AutoXS_no_hashkeys == AutoXS_free_hashkey_no) {
82             unsigned int extend = 1 + AutoXS_no_hashkeys * 2;
83             /*printf("extending hashkey storage by %u\n", extend);*/
84             unsigned int oldsize = AutoXS_no_hashkeys * sizeof(autoxs_hashkey);
85             /*printf("previous data size %u\n", oldsize);*/
86             autoxs_hashkey* tmphashkeys =
87             (autoxs_hashkey*) malloc( oldsize + extend * sizeof(autoxs_hashkey) );
88             memcpy(tmphashkeys, AutoXS_hashkeys, oldsize);
89             free(AutoXS_hashkeys);
90             AutoXS_hashkeys = tmphashkeys;
91             AutoXS_no_hashkeys += extend;
92             }
93             return AutoXS_free_hashkey_no++;
94             }
95              
96              
97             void _resize_array(I32** array, unsigned int* len, unsigned int newlen) {
98             unsigned int oldsize = *len * sizeof(I32);
99             I32* tmparraymap = (I32*) malloc( newlen * sizeof(I32) );
100             memcpy(tmparraymap, *array, oldsize);
101             free(*array);
102             *array = tmparraymap;
103             *len = newlen;
104             }
105              
106             void _resize_array_init(I32** array, unsigned int* len, unsigned int newlen, I32 init) {
107             unsigned int i;
108             unsigned int oldsize = *len * sizeof(I32);
109             I32* tmparraymap = (I32*) malloc( newlen * sizeof(I32) );
110             memcpy(tmparraymap, *array, oldsize);
111             free(*array);
112             *array = tmparraymap;
113             for (i = *len; i < newlen; ++i)
114             (*array)[i] = init;
115             *len = newlen;
116             }
117              
118              
119             /* this is private, call get_array_index instead */
120             I32 _new_internal_arrayindex() {
121             if (AutoXS_no_arrayindices == AutoXS_free_arrayindices_no) {
122             unsigned int extend = 2 + AutoXS_no_arrayindices * 2;
123             /*printf("extending array index storage by %u\n", extend);*/
124             /*printf("previous data size %u\n", oldsize);*/
125             _resize_array(&AutoXS_arrayindices, &AutoXS_no_arrayindices, extend);
126             }
127             return AutoXS_free_arrayindices_no++;
128             }
129              
130             I32 get_internal_array_index(I32 object_ary_idx) {
131             I32 new_index;
132              
133             if (AutoXS_reverse_arrayindices_length <= (unsigned int)object_ary_idx)
134             _resize_array_init( &AutoXS_reverse_arrayindices,
135             &AutoXS_reverse_arrayindices_length,
136             object_ary_idx+1, -1 );
137              
138             /* -1 == "undef" */
139             if (AutoXS_reverse_arrayindices[object_ary_idx] > -1)
140             return AutoXS_reverse_arrayindices[object_ary_idx];
141              
142             new_index = _new_internal_arrayindex();
143             AutoXS_reverse_arrayindices[object_ary_idx] = new_index;
144             return new_index;
145             }
146             AUTOXSHEADERHEREDOC
147             }
148              
149             1;
150             __END__