import Devel-Size 0.02 from CPAN
[p5sagit/Devel-Size.git] / Size.xs
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #if !defined(NV)
6 #define NV double
7 #endif
8
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:
61     croak("Not yet");
62     break;
63   case SVt_PVBM:
64     croak("Not yet");
65     break;
66   case SVt_PVLV:
67     croak("Not yet");
68     break;
69     /* How much space is dedicated to the array? Not counting the
70        elements in the array, mind, just the array itself */
71   case SVt_PVAV:
72     total_size += sizeof(XPVAV);
73     /* Is there anything in the array? */
74     if (AvMAX(thing) != -1) {
75       total_size += sizeof(SV *) * AvMAX(thing);
76     }
77     /* Add in the bits on the other side of the beginning */
78     total_size += (sizeof(SV *) * (AvARRAY(thing) - AvALLOC(thing)));
79     /* Is there something hanging off the arylen element? */
80     if (AvARYLEN(thing)) {
81       total_size += thing_size(AvARYLEN(thing));
82     }
83     break;
84   case SVt_PVHV:
85     /* First the base struct */
86     total_size += sizeof(XPVHV);
87     /* Now the array of buckets */
88     total_size += (sizeof(HE *) * (HvMAX(thing) + 1));
89     /* Now walk the bucket chain */
90     {
91       HE *cur_entry;
92       IV cur_bucket = 0;
93       puts("Foo!");
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     }
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
128 IV
129 size(orig_thing)
130      SV *orig_thing
131 CODE:
132 {
133   RETVAL = thing_size(orig_thing);
134 }
135 OUTPUT:
136   RETVAL