| 1 | /* |
|---|
| 2 | Copyright (C) 2010, Parrot Foundation. |
|---|
| 3 | $Id$ |
|---|
| 4 | |
|---|
| 5 | =head1 |
|---|
| 6 | |
|---|
| 7 | src/pmc/pasmserializer - PASM Object Serializer |
|---|
| 8 | |
|---|
| 9 | =head1 DESCRIPTION |
|---|
| 10 | |
|---|
| 11 | Freezes and thaws PMCs using a text format suitable for use in PASM. |
|---|
| 12 | |
|---|
| 13 | =head2 Vtables |
|---|
| 14 | |
|---|
| 15 | =over 4 |
|---|
| 16 | |
|---|
| 17 | =cut |
|---|
| 18 | |
|---|
| 19 | */ |
|---|
| 20 | |
|---|
| 21 | /* HEADERIZER HFILE: none */ |
|---|
| 22 | |
|---|
| 23 | pmclass PASMSerializer auto_attrs { |
|---|
| 24 | ATTR PMC *buffer; |
|---|
| 25 | ATTR PMC *seen; |
|---|
| 26 | ATTR PMC *todo; |
|---|
| 27 | ATTR UINTVAL id; |
|---|
| 28 | ATTR INTVAL action; |
|---|
| 29 | |
|---|
| 30 | /* |
|---|
| 31 | |
|---|
| 32 | =item C<void init()> |
|---|
| 33 | |
|---|
| 34 | Initialize the serializer. |
|---|
| 35 | |
|---|
| 36 | =cut |
|---|
| 37 | |
|---|
| 38 | */ |
|---|
| 39 | |
|---|
| 40 | VTABLE void init() { |
|---|
| 41 | PARROT_PASMSERIALIZER(SELF)->buffer = PMCNULL; |
|---|
| 42 | PARROT_PASMSERIALIZER(SELF)->todo = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray); |
|---|
| 43 | PARROT_PASMSERIALIZER(SELF)->seen = PMCNULL; |
|---|
| 44 | PARROT_PASMSERIALIZER(SELF)->id = 0; |
|---|
| 45 | |
|---|
| 46 | PObj_custom_mark_SET(SELF); |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | /* |
|---|
| 50 | |
|---|
| 51 | =item C<void mark()> |
|---|
| 52 | |
|---|
| 53 | Mark the PMC as alive. |
|---|
| 54 | |
|---|
| 55 | =cut |
|---|
| 56 | |
|---|
| 57 | */ |
|---|
| 58 | |
|---|
| 59 | VTABLE void mark() { |
|---|
| 60 | Parrot_gc_mark_PMC_alive(INTERP, PARROT_PASMSERIALIZER(SELF)->buffer); |
|---|
| 61 | Parrot_gc_mark_PMC_alive(INTERP, PARROT_PASMSERIALIZER(SELF)->todo); |
|---|
| 62 | Parrot_gc_mark_PMC_alive(INTERP, PARROT_PASMSERIALIZER(SELF)->seen); |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | /* |
|---|
| 66 | |
|---|
| 67 | =item C<PMC *get_iter()> |
|---|
| 68 | |
|---|
| 69 | Get the C<todo> list for this freeze/thaw for iterating over. |
|---|
| 70 | |
|---|
| 71 | =cut |
|---|
| 72 | |
|---|
| 73 | */ |
|---|
| 74 | |
|---|
| 75 | VTABLE PMC *get_iter() { |
|---|
| 76 | return PARROT_PASMSERIALIZER(SELF)->todo; |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | /* |
|---|
| 80 | |
|---|
| 81 | =item C<INTVAL get_integer()> |
|---|
| 82 | |
|---|
| 83 | Get the flags describing this visit action |
|---|
| 84 | |
|---|
| 85 | =cut |
|---|
| 86 | |
|---|
| 87 | */ |
|---|
| 88 | |
|---|
| 89 | VTABLE INTVAL get_integer() { |
|---|
| 90 | return PARROT_PASMSERIALIZER(SELF)->action; |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | /* |
|---|
| 94 | |
|---|
| 95 | =item C<void push_integer(INTVAL v)> |
|---|
| 96 | |
|---|
| 97 | =item C<void push_float(FLOATVAL v)> |
|---|
| 98 | |
|---|
| 99 | =item C<void push_string(STRING *v)> |
|---|
| 100 | |
|---|
| 101 | =item C<void push_pmc(PMC *v)> |
|---|
| 102 | |
|---|
| 103 | Push data item C<v> onto the end of the image being frozen. |
|---|
| 104 | |
|---|
| 105 | =cut |
|---|
| 106 | |
|---|
| 107 | */ |
|---|
| 108 | |
|---|
| 109 | VTABLE void push_integer(INTVAL v) { |
|---|
| 110 | PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer; |
|---|
| 111 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 112 | VTABLE_push_string(INTERP, buf, Parrot_str_from_int(INTERP, v)); |
|---|
| 113 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | VTABLE void push_float(FLOATVAL v) { |
|---|
| 117 | PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer; |
|---|
| 118 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 119 | VTABLE_push_string(INTERP, buf, Parrot_str_from_num(INTERP, v)); |
|---|
| 120 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | VTABLE void push_string(STRING *v) { |
|---|
| 124 | PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer; |
|---|
| 125 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 126 | if (STRING_IS_NULL(v)) { |
|---|
| 127 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "STRINGNULL")); |
|---|
| 128 | } |
|---|
| 129 | else { |
|---|
| 130 | VTABLE_push_string(INTERP, buf, |
|---|
| 131 | Parrot_encoding_name(INTERP, Parrot_encoding_number_of_str(INTERP, v))); |
|---|
| 132 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":")); |
|---|
| 133 | VTABLE_push_string(INTERP, buf, |
|---|
| 134 | Parrot_charset_name(INTERP, Parrot_charset_number_of_str(INTERP, v))); |
|---|
| 135 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":\"")); |
|---|
| 136 | VTABLE_push_string(INTERP, buf, Parrot_str_escape(INTERP, v)); |
|---|
| 137 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "\"")); |
|---|
| 138 | } |
|---|
| 139 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | VTABLE void push_pmc(PMC *v) { |
|---|
| 143 | PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer; |
|---|
| 144 | PMC *seen = PARROT_PASMSERIALIZER(SELF)->seen; |
|---|
| 145 | INTVAL id; |
|---|
| 146 | INTVAL was_seen; |
|---|
| 147 | |
|---|
| 148 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 149 | |
|---|
| 150 | if (PMC_IS_NULL(v)) { |
|---|
| 151 | id = 0; |
|---|
| 152 | was_seen = 1; |
|---|
| 153 | } |
|---|
| 154 | else { |
|---|
| 155 | was_seen = VTABLE_exists_keyed(INTERP, seen, v); |
|---|
| 156 | if (was_seen) |
|---|
| 157 | id = VTABLE_get_integer_keyed(INTERP, seen, v); |
|---|
| 158 | else |
|---|
| 159 | id = ++PARROT_PASMSERIALIZER(SELF)->id; |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "$")); |
|---|
| 163 | VTABLE_push_string(INTERP, buf, Parrot_str_from_int(INTERP, id)); |
|---|
| 164 | |
|---|
| 165 | if (!was_seen) { |
|---|
| 166 | VTABLE_set_integer_keyed(INTERP, seen, v, id); |
|---|
| 167 | VTABLE_push_pmc(INTERP, PARROT_PASMSERIALIZER(SELF)->todo, v); |
|---|
| 168 | |
|---|
| 169 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":")); |
|---|
| 170 | VTABLE_push_string(INTERP, buf, VTABLE_name(INTERP, v)); |
|---|
| 171 | |
|---|
| 172 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "{")); |
|---|
| 173 | VTABLE_freeze(INTERP, v, SELF); |
|---|
| 174 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "}")); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, " ")); |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | /* |
|---|
| 181 | |
|---|
| 182 | =item C<STRING *get_string()> |
|---|
| 183 | |
|---|
| 184 | Get the serialized image as a string (after freezing). |
|---|
| 185 | |
|---|
| 186 | =cut |
|---|
| 187 | |
|---|
| 188 | */ |
|---|
| 189 | |
|---|
| 190 | VTABLE STRING *get_string() { |
|---|
| 191 | return VTABLE_get_string(INTERP, PARROT_PASMSERIALIZER(SELF)->buffer); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | /* |
|---|
| 195 | |
|---|
| 196 | =item C<void set_pmc(PMC *p)> |
|---|
| 197 | |
|---|
| 198 | Freeze the PMC C<p> into the buffer. |
|---|
| 199 | |
|---|
| 200 | =cut |
|---|
| 201 | |
|---|
| 202 | */ |
|---|
| 203 | |
|---|
| 204 | VTABLE void set_pmc(PMC *p) { |
|---|
| 205 | PARROT_PASMSERIALIZER(SELF)->action = VISIT_FREEZE_NORMAL; |
|---|
| 206 | PARROT_PASMSERIALIZER(SELF)->buffer = Parrot_pmc_new(INTERP, enum_class_StringBuilder); |
|---|
| 207 | PARROT_PASMSERIALIZER(SELF)->seen = Parrot_pmc_new(INTERP, enum_class_Hash); |
|---|
| 208 | VTABLE_set_pointer(INTERP, PARROT_PASMSERIALIZER(SELF)->seen, |
|---|
| 209 | parrot_new_intval_hash(INTERP)); |
|---|
| 210 | SELF.push_pmc(p); |
|---|
| 211 | |
|---|
| 212 | // Parrot_visit_loop_visit(INTERP, SELF); |
|---|
| 213 | { |
|---|
| 214 | INTVAL i; |
|---|
| 215 | PMC *buf = PARROT_PASMSERIALIZER(SELF)->buffer; |
|---|
| 216 | PMC *todo = VTABLE_get_iter(INTERP, SELF); |
|---|
| 217 | for (i = 0; i < VTABLE_elements(INTERP, todo); i++) { |
|---|
| 218 | PMC *current = VTABLE_get_pmc_keyed_int(INTERP, todo, i); |
|---|
| 219 | |
|---|
| 220 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "\n$")); |
|---|
| 221 | VTABLE_push_string(INTERP, buf, Parrot_str_from_int(INTERP, i + 1)); |
|---|
| 222 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, ":[")); |
|---|
| 223 | |
|---|
| 224 | VTABLE_visit(INTERP, current, SELF); |
|---|
| 225 | VISIT_PMC(INTERP, SELF, PMC_metadata(current)); |
|---|
| 226 | |
|---|
| 227 | VTABLE_push_string(INTERP, buf, CONST_STRING(INTERP, "]")); |
|---|
| 228 | } |
|---|
| 229 | } |
|---|
| 230 | } |
|---|
| 231 | } |
|---|
| 232 | |
|---|
| 233 | /* |
|---|
| 234 | |
|---|
| 235 | =back |
|---|
| 236 | |
|---|
| 237 | =cut |
|---|
| 238 | |
|---|
| 239 | */ |
|---|
| 240 | |
|---|
| 241 | /* |
|---|
| 242 | * Local variables: |
|---|
| 243 | * c-file-style: "parrot" |
|---|
| 244 | * End: |
|---|
| 245 | * vim: expandtab shiftwidth=4: |
|---|
| 246 | */ |
|---|