OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #include <assert.h> |
| 6 #include <errno.h> |
| 7 #include <stdlib.h> |
| 8 |
| 9 #include "dart_archive.h" |
| 10 #include "messaging.h" |
| 11 |
| 12 /** The enumeration of request types for communicating with Dart. */ |
| 13 enum RequestType { |
| 14 kArchiveReadNew = 0, |
| 15 kArchiveReadSupportFilterAll, |
| 16 kArchiveReadSupportFilterBzip2, |
| 17 kArchiveReadSupportFilterCompress, |
| 18 kArchiveReadSupportFilterGzip, |
| 19 kArchiveReadSupportFilterLzma, |
| 20 kArchiveReadSupportFilterXz, |
| 21 kArchiveReadSupportFilterProgram, |
| 22 kArchiveReadSupportFilterProgramSignature, |
| 23 kArchiveReadSupportFormatAll, |
| 24 kArchiveReadSupportFormatAr, |
| 25 kArchiveReadSupportFormatCpio, |
| 26 kArchiveReadSupportFormatEmpty, |
| 27 kArchiveReadSupportFormatIso9660, |
| 28 kArchiveReadSupportFormatMtree, |
| 29 kArchiveReadSupportFormatRaw, |
| 30 kArchiveReadSupportFormatTar, |
| 31 kArchiveReadSupportFormatZip, |
| 32 kArchiveReadSetFilterOptions, |
| 33 kArchiveReadSetFormatOptions, |
| 34 kArchiveReadSetOptions, |
| 35 kArchiveReadOpenFilename, |
| 36 kArchiveReadOpenMemory, |
| 37 kArchiveReadNextHeader, |
| 38 kArchiveReadDataBlock, |
| 39 kArchiveReadDataSkip, |
| 40 kArchiveReadClose, |
| 41 kArchiveReadFree, |
| 42 kNumberOfRequestTypes |
| 43 }; |
| 44 |
| 45 /** |
| 46 * Dispatches a message from Dart to its native function equivalent. |
| 47 * |
| 48 * In addition to matching up a message with its respective function, this |
| 49 * parses out the standard archive struct argument from the message and resolves |
| 50 * it to an actual pointer to an archive struct. |
| 51 */ |
| 52 static void archiveDispatch(Dart_Port dest_port_id, |
| 53 Dart_Port reply_port_id, |
| 54 Dart_CObject* message) { |
| 55 if (message->type != kArray) { |
| 56 postInvalidArgument(reply_port_id, "Message was not an array."); |
| 57 return; |
| 58 } else if (message->value.as_array.length < 2) { |
| 59 postInvalidArgument(reply_port_id, "Message array had %d elements, " \ |
| 60 "expected at least 2.", message->value.as_array.length); |
| 61 return; |
| 62 } |
| 63 |
| 64 Dart_CObject* wrapped_request_type = message->value.as_array.values[0]; |
| 65 if (wrapped_request_type->type != kInt32) { |
| 66 postInvalidArgument(reply_port_id, "Invalid request type %d.", |
| 67 wrapped_request_type->type); |
| 68 return; |
| 69 } |
| 70 enum RequestType request_type = wrapped_request_type->value.as_int32; |
| 71 |
| 72 Dart_CObject* archive_id = message->value.as_array.values[1]; |
| 73 struct archive* archive; |
| 74 if (archive_id->type == kNull) { |
| 75 archive = NULL; |
| 76 } else if (archive_id->type == kInt64 || archive_id->type == kInt32) { |
| 77 archive = (struct archive*) (intptr_t) getInteger(archive_id); |
| 78 } else { |
| 79 postInvalidArgument(reply_port_id, "Invalid archive id type %d.", |
| 80 archive_id->type); |
| 81 return; |
| 82 } |
| 83 |
| 84 switch (request_type) { |
| 85 case kArchiveReadNew: |
| 86 archiveReadNew(reply_port_id); |
| 87 break; |
| 88 case kArchiveReadSupportFilterAll: |
| 89 archiveReadSupportFilterAll(reply_port_id, archive); |
| 90 break; |
| 91 case kArchiveReadSupportFilterBzip2: |
| 92 archiveReadSupportFilterBzip2(reply_port_id, archive); |
| 93 break; |
| 94 case kArchiveReadSupportFilterCompress: |
| 95 archiveReadSupportFilterCompress(reply_port_id, archive); |
| 96 break; |
| 97 case kArchiveReadSupportFilterGzip: |
| 98 archiveReadSupportFilterGzip(reply_port_id, archive); |
| 99 break; |
| 100 case kArchiveReadSupportFilterLzma: |
| 101 archiveReadSupportFilterLzma(reply_port_id, archive); |
| 102 break; |
| 103 case kArchiveReadSupportFilterXz: |
| 104 archiveReadSupportFilterXz(reply_port_id, archive); |
| 105 break; |
| 106 case kArchiveReadSupportFilterProgram: |
| 107 archiveReadSupportFilterProgram(reply_port_id, archive, message); |
| 108 break; |
| 109 case kArchiveReadSupportFilterProgramSignature: |
| 110 archiveReadSupportFilterProgramSignature( |
| 111 reply_port_id, archive, message); |
| 112 break; |
| 113 case kArchiveReadSupportFormatAll: |
| 114 archiveReadSupportFormatAll(reply_port_id, archive); |
| 115 break; |
| 116 case kArchiveReadSupportFormatAr: |
| 117 archiveReadSupportFormatAr(reply_port_id, archive); |
| 118 break; |
| 119 case kArchiveReadSupportFormatCpio: |
| 120 archiveReadSupportFormatCpio(reply_port_id, archive); |
| 121 break; |
| 122 case kArchiveReadSupportFormatEmpty: |
| 123 archiveReadSupportFormatEmpty(reply_port_id, archive); |
| 124 break; |
| 125 case kArchiveReadSupportFormatIso9660: |
| 126 archiveReadSupportFormatIso9660(reply_port_id, archive); |
| 127 break; |
| 128 case kArchiveReadSupportFormatMtree: |
| 129 archiveReadSupportFormatMtree(reply_port_id, archive); |
| 130 break; |
| 131 case kArchiveReadSupportFormatRaw: |
| 132 archiveReadSupportFormatRaw(reply_port_id, archive); |
| 133 break; |
| 134 case kArchiveReadSupportFormatTar: |
| 135 archiveReadSupportFormatTar(reply_port_id, archive); |
| 136 break; |
| 137 case kArchiveReadSupportFormatZip: |
| 138 archiveReadSupportFormatZip(reply_port_id, archive); |
| 139 break; |
| 140 case kArchiveReadSetFilterOptions: |
| 141 archiveReadSetFilterOptions(reply_port_id, archive, message); |
| 142 break; |
| 143 case kArchiveReadSetFormatOptions: |
| 144 archiveReadSetFormatOptions(reply_port_id, archive, message); |
| 145 break; |
| 146 case kArchiveReadSetOptions: |
| 147 archiveReadSetOptions(reply_port_id, archive, message); |
| 148 break; |
| 149 case kArchiveReadOpenFilename: |
| 150 archiveReadOpenFilename(reply_port_id, archive, message); |
| 151 break; |
| 152 case kArchiveReadOpenMemory: |
| 153 archiveReadOpenMemory(reply_port_id, archive, message); |
| 154 break; |
| 155 case kArchiveReadNextHeader: |
| 156 archiveReadNextHeader(reply_port_id, archive); |
| 157 break; |
| 158 case kArchiveReadDataBlock: |
| 159 archiveReadDataBlock(reply_port_id, archive); |
| 160 break; |
| 161 case kArchiveReadDataSkip: |
| 162 archiveReadDataSkip(reply_port_id, archive); |
| 163 break; |
| 164 case kArchiveReadClose: |
| 165 archiveReadClose(reply_port_id, archive); |
| 166 break; |
| 167 case kArchiveReadFree: |
| 168 archiveReadFree(reply_port_id, archive); |
| 169 break; |
| 170 default: |
| 171 postInvalidArgument(reply_port_id, "Invalid request id %d.", request_type); |
| 172 break; |
| 173 } |
| 174 } |
| 175 |
| 176 /** |
| 177 * Checks if [handle] represents an error and, if so, propagates it to Dart. |
| 178 * Otherwise, returns [handle]. |
| 179 */ |
| 180 static Dart_Handle handleError(Dart_Handle handle) { |
| 181 if (Dart_IsError(handle)) Dart_PropagateError(handle); |
| 182 return handle; |
| 183 } |
| 184 |
| 185 /** |
| 186 * A function exposed to Dart that creates a [ServicePort] for two-way |
| 187 * communication between Dart and C. |
| 188 * |
| 189 * Takes no arguments and returns a [ServicePort]. |
| 190 */ |
| 191 static void archiveServicePort(Dart_NativeArguments arguments) { |
| 192 Dart_EnterScope(); |
| 193 Dart_SetReturnValue(arguments, Dart_Null()); |
| 194 Dart_Port service_port = |
| 195 Dart_NewNativePort("ArchiveService", archiveDispatch, false); |
| 196 if (service_port != ILLEGAL_PORT) { |
| 197 Dart_Handle send_port = handleError(Dart_NewSendPort(service_port)); |
| 198 Dart_SetReturnValue(arguments, send_port); |
| 199 } |
| 200 Dart_ExitScope(); |
| 201 } |
| 202 |
| 203 /** |
| 204 * A struct representing a function exposed to Dart and the name under which it |
| 205 * can be looked up. |
| 206 */ |
| 207 struct FunctionLookup { |
| 208 const char* name; |
| 209 Dart_NativeFunction function; |
| 210 }; |
| 211 |
| 212 /** The list of functions exposed to Dart. */ |
| 213 struct FunctionLookup function_list[] = { |
| 214 {"Archive_ServicePort", archiveServicePort}, |
| 215 {NULL, NULL} |
| 216 }; |
| 217 |
| 218 /** |
| 219 * Resolves a Dart name as provided in a `native` declaration and returns the |
| 220 * C function that should be invoked for that name. |
| 221 */ |
| 222 static Dart_NativeFunction resolveName(Dart_Handle name, int argc) { |
| 223 if (!Dart_IsString8(name)) return NULL; |
| 224 Dart_EnterScope(); |
| 225 const char* cname; |
| 226 handleError(Dart_StringToCString(name, &cname)); |
| 227 |
| 228 Dart_NativeFunction result = NULL; |
| 229 int i; |
| 230 for (i = 0; function_list[i].name != NULL; ++i) { |
| 231 if (strcmp(function_list[i].name, cname) == 0) { |
| 232 result = function_list[i].function; |
| 233 break; |
| 234 } |
| 235 } |
| 236 Dart_ExitScope(); |
| 237 return result; |
| 238 } |
| 239 |
| 240 /** Initializes the C extension. */ |
| 241 DART_EXPORT Dart_Handle dart_archive_Init(Dart_Handle parent_library) { |
| 242 if (Dart_IsError(parent_library)) return parent_library; |
| 243 |
| 244 Dart_Handle result_code = Dart_SetNativeResolver(parent_library, resolveName); |
| 245 if (Dart_IsError(result_code)) return result_code; |
| 246 |
| 247 return Dart_Null(); |
| 248 } |
OLD | NEW |