Commit | Line | Data |
e98cedbf |
1 | #include "EXTERN.h" |
2 | #include "perl.h" |
3 | #include "XSUB.h" |
4 | |
a6ea0805 |
5 | #if !defined(NV) |
6 | #define NV double |
7 | #endif |
8 | |
e98cedbf |
9 | UV thing_size(SV *orig_thing) { |
10 | SV *thing = orig_thing; |
11 | UV total_size = sizeof(SV); |
12 | |
13 | /* If they passed us a reference then dereference it. This is the |
14 | only way we can check the sizes of arrays and hashes */ |
15 | if (SvOK(thing) && SvROK(thing)) { |
16 | thing = SvRV(thing); |
17 | } |
18 | |
19 | switch (SvTYPE(thing)) { |
20 | /* Is it undef? */ |
21 | case SVt_NULL: |
22 | break; |
23 | /* Just a plain integer. This will be differently sized depending |
24 | on whether purify's been compiled in */ |
25 | case SVt_IV: |
26 | #ifdef PURIFY |
27 | total_size += sizeof(sizeof(XPVIV)); |
28 | #else |
29 | total_size += sizeof(IV); |
30 | #endif |
31 | break; |
32 | /* Is it a float? Like the int, it depends on purify */ |
33 | case SVt_NV: |
34 | #ifdef PURIFY |
35 | total_size += sizeof(sizeof(XPVNV)); |
36 | #else |
37 | total_size += sizeof(NV); |
38 | #endif |
39 | break; |
40 | /* Is it a reference? */ |
41 | case SVt_RV: |
42 | total_size += sizeof(XRV); |
43 | break; |
44 | /* How about a plain string? In which case we need to add in how |
45 | much has been allocated */ |
46 | case SVt_PV: |
47 | total_size += sizeof(XPV); |
48 | total_size += SvLEN(thing); |
49 | break; |
50 | /* A string with an integer part? */ |
51 | case SVt_PVIV: |
52 | total_size += sizeof(XPVIV); |
53 | total_size += SvLEN(thing); |
54 | break; |
55 | /* A string with a float part? */ |
56 | case SVt_PVNV: |
57 | total_size += sizeof(XPVNV); |
58 | total_size += SvLEN(thing); |
59 | break; |
60 | case SVt_PVMG: |
4ab42718 |
61 | total_size += sizeof(XPVMG); |
62 | total_size += SvLEN(thing); |
e98cedbf |
63 | break; |
64 | case SVt_PVBM: |
65 | croak("Not yet"); |
66 | break; |
67 | case SVt_PVLV: |
68 | croak("Not yet"); |
69 | break; |
70 | /* How much space is dedicated to the array? Not counting the |
71 | elements in the array, mind, just the array itself */ |
72 | case SVt_PVAV: |
73 | total_size += sizeof(XPVAV); |
74 | /* Is there anything in the array? */ |
75 | if (AvMAX(thing) != -1) { |
76 | total_size += sizeof(SV *) * AvMAX(thing); |
77 | } |
78 | /* Add in the bits on the other side of the beginning */ |
79 | total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing))); |
80 | /* Is there something hanging off the arylen element? */ |
81 | if (AvARYLEN(thing)) { |
82 | total_size += thing_size(AvARYLEN(thing)); |
83 | } |
84 | break; |
85 | case SVt_PVHV: |
a6ea0805 |
86 | /* First the base struct */ |
87 | total_size += sizeof(XPVHV); |
88 | /* Now the array of buckets */ |
89 | total_size += (sizeof(HE *) * (HvMAX(thing) + 1)); |
90 | /* Now walk the bucket chain */ |
91 | { |
92 | HE *cur_entry; |
93 | IV cur_bucket = 0; |
a6ea0805 |
94 | for (cur_bucket = 0; cur_bucket <= HvMAX(thing); cur_bucket++) { |
95 | cur_entry = *(HvARRAY(thing) + cur_bucket); |
96 | while (cur_entry) { |
97 | total_size += sizeof(HE); |
98 | if (cur_entry->hent_hek) { |
99 | total_size += sizeof(HEK); |
100 | total_size += cur_entry->hent_hek->hek_len - 1; |
101 | } |
102 | cur_entry = cur_entry->hent_next; |
103 | } |
104 | } |
105 | } |
e98cedbf |
106 | break; |
107 | case SVt_PVCV: |
108 | croak("Not yet"); |
109 | break; |
110 | case SVt_PVGV: |
111 | croak("Not yet"); |
112 | break; |
113 | case SVt_PVFM: |
114 | croak("Not yet"); |
115 | break; |
116 | case SVt_PVIO: |
117 | croak("Not yet"); |
118 | break; |
119 | default: |
120 | croak("Unknown variable type"); |
121 | } |
122 | return total_size; |
123 | } |
124 | |
125 | |
126 | MODULE = Devel::Size PACKAGE = Devel::Size |
127 | |
a6ea0805 |
128 | IV |
129 | size(orig_thing) |
130 | SV *orig_thing |
e98cedbf |
131 | CODE: |
132 | { |
133 | RETVAL = thing_size(orig_thing); |
134 | } |
135 | OUTPUT: |
136 | RETVAL |