3 * Copyright (C) 2006-2008, The Perl Foundation.
6 /* .NET CLI Signature PMC */
9 #include "parrot/extend.h"
10 #include "tableinfo.h"
11 #include "structures.h"
14 pmclass DotNetSignature dynpmc group dotnet {
16 /* Instance initialization. We need a custom destroy. */
19 PObj_active_destroy_SET(SELF);
20 PMC_struct_val(SELF) = NULL;
27 /* Cleanup any memory we're using. */
28 if (PMC_struct_val(SELF)) {
29 dotnet_signature *sig = (dotnet_signature *)PMC_struct_val(SELF);
32 mem_sys_free(sig->data);
35 PMC_struct_val(SELF) = NULL;
40 /* set_string_native copies the data held in the string to the internal
41 blob data buffer so we can easily walk over it. */
42 void set_string_native(STRING* s)
44 dotnet_signature *sig = (dotnet_signature *)PMC_struct_val(SELF);
46 /* Do we have a struct already allocated? */
49 /* Yes; free up old string. */
55 /* No; need to allocate a new structure. */
56 sig = mem_allocate_zeroed_typed(dotnet_signature);
57 PMC_struct_val(SELF) = sig;
60 /* Get blob data and its size and reset current position. */
61 sig->data = string_to_cstring(INTERP, s);
62 sig->data_size = string_length(INTERP, s);
67 /* Read an unsigned 8-bit integer. */
68 METHOD INTVAL read_uint8()
70 dotnet_signature *sig = (dotnet_signature *)PMC_struct_val(SELF);
73 /* Handle cases where we've an invalid PMC. */
74 if (!sig || !sig->data)
75 real_exception(INTERP, NULL, E_StandardError,
76 "Invalid DotNetSignature PMC");
78 /* Ensure we won't read past the end. */
79 if (sig->cur_pos >= sig->data_size)
80 real_exception(INTERP, NULL, E_StandardError,
81 "Read past end of signature");
83 /* Otherwise read the value. */
84 result = (INTVAL)sig->data[sig->cur_pos];
86 RETURN(INTVAL result);
90 /* Read a compressed integer. */
91 METHOD INTVAL read_compressed()
93 dotnet_signature *sig = (dotnet_signature *)PMC_struct_val(SELF);
95 unsigned char b1, b2, b3, b4;
97 /* Handle cases where we've an invalid PMC. */
98 if (!sig || !sig->data)
99 real_exception(INTERP, NULL, E_StandardError,
100 "Invalid DotNetSignature PMC");
102 /* Check first byte read is OK. */
103 if (sig->cur_pos >= sig->data_size)
104 real_exception(INTERP, NULL, E_StandardError,
105 "Read past end of signature");
107 /* Read first byte and decide if it's a single encoded byte (top bit
109 b1 = sig->data[sig->cur_pos];
111 if ((b1 & 0x80) == 0)
117 /* Is it a 2 byte integer (top bits 10)? */
118 else if ((b1 & 0x80) != 0 && (b1 & 0x40) == 0)
120 /* Check we can read 2 bytes. */
121 if (sig->cur_pos + 1 >= sig->data_size)
122 real_exception(INTERP, NULL, E_StandardError,
123 "Read past end of signature");
125 /* Read second byte and make value. */
126 b2 = sig->data[sig->cur_pos + 1];
127 val = ((b1 & 0x3F) << 8) | b2;
131 /* Is it a 4 byte integer? (top bits 110)? */
132 else if ((b1 & 0x80) != 0 && (b1 & 0x40) != 0 && (b1 & 0x20) == 0) {
133 /* Check we can read 4 bytes. */
134 if (sig->cur_pos + 3 >= sig->data_size)
135 real_exception(INTERP, NULL, E_StandardError,
136 "Read past end of signature");
138 /* Read remaining bytes and make value. */
139 b2 = sig->data[sig->cur_pos + 1];
140 b3 = sig->data[sig->cur_pos + 2];
141 b4 = sig->data[sig->cur_pos + 3];
142 val = ((b1 & 0x1F) << 24) | (b2 << 16) | (b3 << 8) | b4;
146 /* Otherwise, it's a null byte. RT #48128 Need special handling? */
152 /* Return the value. */
160 * c-file-style: "parrot"
162 * vim: expandtab shiftwidth=4: