Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: native_client_sdk/src/examples/demo/nacl_io/hello_nacl_io.c

Issue 14607005: [NaCl SDK] Cleanup examples. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: feedback Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include "hello_nacl_io.h"
7
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <pthread.h>
13
14 #include "ppapi/c/pp_errors.h"
15 #include "ppapi/c/pp_module.h"
16 #include "ppapi/c/ppb.h"
17 #include "ppapi/c/ppb_instance.h"
18 #include "ppapi/c/ppb_messaging.h"
19 #include "ppapi/c/ppb_var.h"
20 #include "ppapi/c/ppp.h"
21 #include "ppapi/c/ppp_instance.h"
22 #include "ppapi/c/ppp_messaging.h"
23 #include "nacl_io/nacl_io.h"
24
25 #include "handlers.h"
26 #include "queue.h"
27
28 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
29
30 #if defined(WIN32)
31 #define va_copy(d, s) ((d) = (s))
32 #endif
33
34 typedef struct {
35 const char* name;
36 HandleFunc function;
37 } FuncNameMapping;
38
39 static PP_Instance g_instance = 0;
40 static PPB_GetInterface get_browser_interface = NULL;
41 static PPB_Messaging* ppb_messaging_interface = NULL;
42 static PPB_Var* ppb_var_interface = NULL;
43
44 static FuncNameMapping g_function_map[] = {
45 { "fopen", HandleFopen },
46 { "fwrite", HandleFwrite },
47 { "fread", HandleFread },
48 { "fseek", HandleFseek },
49 { "fclose", HandleFclose },
50 { "stat", HandleStat },
51 { NULL, NULL },
52 };
53
54 /** A handle to the thread the handles messages. */
55 static pthread_t g_handle_message_thread;
56
57 /**
58 * Create a new PP_Var from a C string.
59 * @param[in] str The string to convert.
60 * @return A new PP_Var with the contents of |str|. */
61 struct PP_Var CStrToVar(const char* str) {
62 if (ppb_var_interface != NULL) {
63 return ppb_var_interface->VarFromUtf8(str, strlen(str));
64 }
65 return PP_MakeUndefined();
66 }
67
68 /**
69 * Printf to a newly allocated C string.
70 * @param[in] format A printf format string.
71 * @param[in] args The printf arguments.
72 * @return The newly constructed string. Caller takes ownership. */
73 char* VprintfToNewString(const char* format, va_list args) {
74 va_list args_copy;
75 int length;
76 char* buffer;
77 int result;
78
79 va_copy(args_copy, args);
80 length = vsnprintf(NULL, 0, format, args);
81 buffer = (char*)malloc(length + 1); /* +1 for NULL-terminator. */
82 result = vsnprintf(&buffer[0], length + 1, format, args_copy);
83 assert(result == length);
84 return buffer;
85 }
86
87 /**
88 * Printf to a newly allocated C string.
89 * @param[in] format A print format string.
90 * @param[in] ... The printf arguments.
91 * @return The newly constructed string. Caller takes ownership. */
92 char* PrintfToNewString(const char* format, ...) {
93 va_list args;
94 char* result;
95 va_start(args, format);
96 result = VprintfToNewString(format, args);
97 va_end(args);
98 return result;
99 }
100
101 /**
102 * Printf to a new PP_Var.
103 * @param[in] format A print format string.
104 * @param[in] ... The printf arguments.
105 * @return A new PP_Var. */
106 struct PP_Var PrintfToVar(const char* format, ...) {
107 if (ppb_var_interface != NULL) {
108 char* string;
109 va_list args;
110 struct PP_Var var;
111
112 va_start(args, format);
113 string = VprintfToNewString(format, args);
114 va_end(args);
115
116 var = ppb_var_interface->VarFromUtf8(string, strlen(string));
117 free(string);
118
119 return var;
120 }
121
122 return PP_MakeUndefined();
123 }
124
125 /**
126 * Convert a PP_Var to a C string, given a buffer.
127 * @param[in] var The PP_Var to convert.
128 * @param[out] buffer The buffer to write to.
129 * @param[in] length The length of |buffer|.
130 * @return The number of characters written. */
131 uint32_t VarToCStr(struct PP_Var var, char* buffer, uint32_t length) {
132 if (ppb_var_interface != NULL) {
133 uint32_t var_length;
134 const char* str = ppb_var_interface->VarToUtf8(var, &var_length);
135 /* str is NOT NULL-terminated. Copy using memcpy. */
136 uint32_t min_length = MIN(var_length, length - 1);
137 memcpy(buffer, str, min_length);
138 buffer[min_length] = 0;
139
140 return min_length;
141 }
142
143 return 0;
144 }
145
146 /**
147 * Given a message from JavaScript, parse it for functions and parameters.
148 *
149 * The format of the message is:
150 * function, param1, param2, param3, etc.
151 * where each element is separated by the \1 character.
152 *
153 * e.g.
154 * "function\1first parameter\1second parameter"
155 *
156 * How to use:
157 * char* function;
158 * char* params[4];
159 * int num_params = ParseMessage(msg, &function, &params, 4);
160 *
161 * @param[in, out] message The message to parse. This string is modified
162 * in-place.
163 * @param[out] out_function The function name.
164 * @param[out] out_params An array of strings, one for each parameter parsed.
165 * @param[in] max_params The maximum number of parameters to parse.
166 * @return The number of parameters parsed. */
167 static size_t ParseMessage(char* message,
168 char** out_function,
169 char** out_params,
170 size_t max_params) {
171 char* separator;
172 char* param_start;
173 size_t num_params = 0;
174
175 /* Parse the message: function\1param1\1param2\1param3,... */
176 *out_function = &message[0];
177
178 separator = strchr(message, 1);
179 if (!separator) {
180 return num_params;
181 }
182
183 *separator = 0; /* NULL-terminate function. */
184
185 while (separator && num_params < max_params) {
186 param_start = separator + 1;
187 separator = strchr(param_start, 1);
188 if (separator) {
189 *separator = 0;
190 out_params[num_params++] = param_start;
191 }
192 }
193
194 out_params[num_params++] = param_start;
195
196 return num_params;
197 }
198
199 /**
200 * Given a function name, look up its handler function.
201 * @param[in] function_name The function name to look up.
202 * @return The handler function mapped to |function_name|. */
203 static HandleFunc GetFunctionByName(const char* function_name) {
204 FuncNameMapping* map_iter = g_function_map;
205 for (; map_iter->name; ++map_iter) {
206 if (strcmp(map_iter->name, function_name) == 0) {
207 return map_iter->function;
208 }
209 }
210
211 return NULL;
212 }
213
214 /** Handle as message from JavaScript on the worker thread.
215 *
216 * @param[in] message The message to parse and handle. */
217 static void HandleMessage(char* message) {
218 char* function_name;
219 char* params[MAX_PARAMS];
220 size_t num_params;
221 char* output = NULL;
222 int result;
223 HandleFunc function;
224
225 num_params = ParseMessage(message, &function_name, &params[0], MAX_PARAMS);
226
227 function = GetFunctionByName(function_name);
228 if (!function) {
229 /* Function name wasn't found. Error. */
230 ppb_messaging_interface->PostMessage(
231 g_instance, PrintfToVar("Error: Unknown function \"%s\"", function));
232 }
233
234 /* Function name was found, call it. */
235 result = (*function)(num_params, &params[0], &output);
236 if (result != 0) {
237 /* Error. */
238 struct PP_Var var;
239 if (output != NULL) {
240 var = PrintfToVar("Error: Function \"%s\" returned error %d. "
241 "Additional output: %s",
242 function_name,
243 result,
244 output);
245 free(output);
246 } else {
247 var = PrintfToVar(
248 "Error: Function \"%s\" returned error %d.", function_name, result);
249 }
250
251 /* Post the error to JavaScript, so the user can see it. */
252 ppb_messaging_interface->PostMessage(g_instance, var);
253 return;
254 }
255
256 if (output != NULL) {
257 /* Function returned an output string. Send it to JavaScript. */
258 ppb_messaging_interface->PostMessage(g_instance, CStrToVar(output));
259 free(output);
260 }
261 }
262
263 /** A worker thread that handles messages from JavaScript.
264 * @param[in] user_data Unused.
265 * @return unused. */
266 void* HandleMessageThread(void* user_data) {
267 while (1) {
268 char* message = DequeueMessage();
269 HandleMessage(message);
270 free(message);
271 }
272 }
273
274 static PP_Bool Instance_DidCreate(PP_Instance instance,
275 uint32_t argc,
276 const char* argn[],
277 const char* argv[]) {
278 g_instance = instance;
279 nacl_io_init_ppapi(instance, get_browser_interface);
280
281 // By default, nacl_io mounts / to pass through to the original NaCl
282 // filesystem (which doesn't do much). Let's remount it to a memfs
283 // filesystem.
284 umount("/");
285 mount("", "/", "memfs", 0, "");
286
287 mount("", /* source */
288 "/persistent", /* target */
289 "html5fs", /* filesystemtype */
290 0, /* mountflags */
291 "type=PERSISTENT,expected_size=1048576"); /* data */
292
293 mount("", /* source. Use relative URL */
294 "/http", /* target */
295 "httpfs", /* filesystemtype */
296 0, /* mountflags */
297 ""); /* data */
298
299 pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL);
300 InitializeMessageQueue();
301
302 return PP_TRUE;
303 }
304
305 static void Instance_DidDestroy(PP_Instance instance) {}
306
307 static void Instance_DidChangeView(PP_Instance instance,
308 PP_Resource view_resource) {}
309
310 static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
311
312 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
313 PP_Resource url_loader) {
314 /* NaCl modules do not need to handle the document load function. */
315 return PP_FALSE;
316 }
317
318 static void Messaging_HandleMessage(PP_Instance instance,
319 struct PP_Var message) {
320 char buffer[1024];
321 VarToCStr(message, &buffer[0], 1024);
322 if (!EnqueueMessage(strdup(buffer))) {
323 struct PP_Var var;
324 var = PrintfToVar(
325 "Warning: dropped message \"%s\" because the queue was full.", message);
326 ppb_messaging_interface->PostMessage(g_instance, var);
327 }
328 }
329
330 PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
331 PPB_GetInterface get_browser) {
332 get_browser_interface = get_browser;
333 ppb_messaging_interface =
334 (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
335 ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
336 return PP_OK;
337 }
338
339 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
340 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
341 static PPP_Instance instance_interface = {
342 &Instance_DidCreate,
343 &Instance_DidDestroy,
344 &Instance_DidChangeView,
345 &Instance_DidChangeFocus,
346 &Instance_HandleDocumentLoad,
347 };
348 return &instance_interface;
349 } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
350 static PPP_Messaging messaging_interface = {
351 &Messaging_HandleMessage,
352 };
353 return &messaging_interface;
354 }
355 return NULL;
356 }
357
358 PP_EXPORT void PPP_ShutdownModule() {}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698