Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / examples / demo / nacl_io / nacl_io_demo.c
index eed1721..6a08cd2 100644 (file)
@@ -18,6 +18,8 @@
 #include "ppapi/c/ppb_instance.h"
 #include "ppapi/c/ppb_messaging.h"
 #include "ppapi/c/ppb_var.h"
+#include "ppapi/c/ppb_var_array.h"
+#include "ppapi/c/ppb_var_dictionary.h"
 #include "ppapi/c/ppp.h"
 #include "ppapi/c/ppp_instance.h"
 #include "ppapi/c/ppp_messaging.h"
@@ -26,8 +28,6 @@
 #include "handlers.h"
 #include "queue.h"
 
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
 #if defined(WIN32)
 #define va_copy(d, s) ((d) = (s))
 #endif
@@ -37,31 +37,35 @@ typedef struct {
   HandleFunc function;
 } FuncNameMapping;
 
-static PP_Instance g_instance = 0;
-static PPB_GetInterface get_browser_interface = NULL;
-static PPB_Messaging* ppb_messaging_interface = NULL;
-static PPB_Var* ppb_var_interface = NULL;
+PP_Instance g_instance = 0;
+PPB_GetInterface g_get_browser_interface = NULL;
+PPB_Messaging* g_ppb_messaging = NULL;
+PPB_Var* g_ppb_var = NULL;
+PPB_VarArray* g_ppb_var_array = NULL;
+PPB_VarDictionary* g_ppb_var_dictionary = NULL;
 
 static FuncNameMapping g_function_map[] = {
-  {"fopen", HandleFopen},
-  {"fwrite", HandleFwrite},
-  {"fread", HandleFread},
-  {"fseek", HandleFseek},
-  {"fclose", HandleFclose},
-  {"stat", HandleStat},
-  {"opendir", HandleOpendir},
-  {"readdir", HandleReaddir},
-  {"closedir", HandleClosedir},
-  {"mkdir", HandleMkdir},
-  {"rmdir", HandleRmdir},
-  {"chdir", HandleChdir},
-  {"getcwd", HandleGetcwd},
-  {"gethostbyname", HandleGethostbyname},
-  {"connect", HandleConnect},
-  {"send", HandleSend},
-  {"recv", HandleRecv},
-  {"close", HandleClose},
-  {NULL, NULL},
+    {"fopen", HandleFopen},
+    {"fwrite", HandleFwrite},
+    {"fread", HandleFread},
+    {"fseek", HandleFseek},
+    {"fclose", HandleFclose},
+    {"fflush", HandleFflush},
+    {"stat", HandleStat},
+    {"opendir", HandleOpendir},
+    {"readdir", HandleReaddir},
+    {"closedir", HandleClosedir},
+    {"mkdir", HandleMkdir},
+    {"rmdir", HandleRmdir},
+    {"chdir", HandleChdir},
+    {"getcwd", HandleGetcwd},
+    {"getaddrinfo", HandleGetaddrinfo},
+    {"gethostbyname", HandleGethostbyname},
+    {"connect", HandleConnect},
+    {"send", HandleSend},
+    {"recv", HandleRecv},
+    {"close", HandleClose},
+    {NULL, NULL},
 };
 
 /** A handle to the thread the handles messages. */
@@ -73,10 +77,7 @@ static pthread_t g_handle_message_thread;
  * @return A new PP_Var with the contents of |str|.
  */
 struct PP_Var CStrToVar(const char* str) {
-  if (ppb_var_interface != NULL) {
-    return ppb_var_interface->VarFromUtf8(str, strlen(str));
-  }
-  return PP_MakeUndefined();
+  return g_ppb_var->VarFromUtf8(str, strlen(str));
 }
 
 /**
@@ -123,22 +124,18 @@ char* PrintfToNewString(const char* format, ...) {
  * @return A new PP_Var.
  */
 struct PP_Var PrintfToVar(const char* format, ...) {
-  if (ppb_var_interface != NULL) {
-    char* string;
-    va_list args;
-    struct PP_Var var;
-
-    va_start(args, format);
-    string = VprintfToNewString(format, args);
-    va_end(args);
+  char* string;
+  va_list args;
+  struct PP_Var var;
 
-    var = ppb_var_interface->VarFromUtf8(string, strlen(string));
-    free(string);
+  va_start(args, format);
+  string = VprintfToNewString(format, args);
+  va_end(args);
 
-    return var;
-  }
+  var = g_ppb_var->VarFromUtf8(string, strlen(string));
+  free(string);
 
-  return PP_MakeUndefined();
+  return var;
 }
 
 /**
@@ -148,73 +145,77 @@ struct PP_Var PrintfToVar(const char* format, ...) {
  * @param[in] length The length of |buffer|.
  * @return The number of characters written.
  */
-uint32_t VarToCStr(struct PP_Var var, char* buffer, uint32_t length) {
-  if (ppb_var_interface != NULL) {
-    uint32_t var_length;
-    const char* str = ppb_var_interface->VarToUtf8(var, &var_length);
-    /* str is NOT NULL-terminated. Copy using memcpy. */
-    uint32_t min_length = MIN(var_length, length - 1);
-    memcpy(buffer, str, min_length);
-    buffer[min_length] = 0;
-
-    return min_length;
+const char* VarToCStr(struct PP_Var var) {
+  uint32_t length;
+  const char* str = g_ppb_var->VarToUtf8(var, &length);
+  if (str == NULL) {
+    return NULL;
   }
 
-  return 0;
+  /* str is NOT NULL-terminated. Copy using memcpy. */
+  char* new_str = (char*)malloc(length + 1);
+  memcpy(new_str, str, length);
+  new_str[length] = 0;
+  return new_str;
+}
+
+/**
+ * Get a value from a Dictionary, given a string key.
+ * @param[in] dict The dictionary to look in.
+ * @param[in] key The key to look up.
+ * @return PP_Var The value at |key| in the |dict|. If the key doesn't exist,
+ *     return a PP_Var with the undefined value.
+ */
+struct PP_Var GetDictVar(struct PP_Var dict, const char* key) {
+  struct PP_Var key_var = CStrToVar(key);
+  struct PP_Var value = g_ppb_var_dictionary->Get(dict, key_var);
+  g_ppb_var->Release(key_var);
+  return value;
+}
+
+/**
+ * Send a newly-created PP_Var to JavaScript, then release it.
+ * @param[in] var The PP_Var to send.
+ */
+static void PostMessageVar(struct PP_Var var) {
+  g_ppb_messaging->PostMessage(g_instance, var);
+  g_ppb_var->Release(var);
 }
 
 /**
  * Given a message from JavaScript, parse it for functions and parameters.
  *
  * The format of the message is:
- *   function, param1, param2, param3, etc.
- * where each element is separated by the \1 character.
- *
- * e.g.
- *   "function\1first parameter\1second parameter"
+ * {
+ *  "cmd": <function name>,
+ *  "args": [<arg0>, <arg1>, ...]
+ * }
  *
- * How to use:
- *   char* function;
- *   char* params[4];
- *   int num_params = ParseMessage(msg, &function, &params, 4);
- *
- * @param[in, out] message The message to parse. This string is modified
- *     in-place.
+ * @param[in] message The message to parse.
  * @param[out] out_function The function name.
- * @param[out] out_params An array of strings, one for each parameter parsed.
- * @param[in] max_params The maximum number of parameters to parse.
- * @return The number of parameters parsed.
+ * @param[out] out_params A PP_Var array.
+ * @return 0 if successful, otherwise 1.
  */
-static size_t ParseMessage(char* message,
-                           char** out_function,
-                           char** out_params,
-                           size_t max_params) {
-  char* separator;
-  char* param_start;
-  size_t num_params = 0;
-
-  /* Parse the message: function\1param1\1param2\1param3,... */
-  *out_function = &message[0];
-
-  separator = strchr(message, 1);
-  if (!separator) {
-    return num_params;
+static int ParseMessage(struct PP_Var message,
+                        const char** out_function,
+                        struct PP_Var* out_params) {
+  if (message.type != PP_VARTYPE_DICTIONARY) {
+    return 1;
   }
 
-  *separator = 0; /* NULL-terminate function. */
-
-  while (separator && num_params < max_params) {
-    param_start = separator + 1;
-    separator = strchr(param_start, 1);
-    if (separator) {
-      *separator = 0;
-      out_params[num_params++] = param_start;
-    }
+  struct PP_Var cmd_value = GetDictVar(message, "cmd");
+  *out_function = VarToCStr(cmd_value);
+  g_ppb_var->Release(cmd_value);
+  if (cmd_value.type != PP_VARTYPE_STRING) {
+    return 1;
   }
 
-  out_params[num_params++] = param_start;
+  *out_params = GetDictVar(message, "args");
+  if (out_params->type != PP_VARTYPE_ARRAY) {
+    return 1;
+  }
 
-  return num_params;
+  return 0;
 }
 
 /**
@@ -238,49 +239,44 @@ static HandleFunc GetFunctionByName(const char* function_name) {
  *
  * @param[in] message The message to parse and handle.
  */
-static void HandleMessage(char* message) {
-  char* function_name;
-  char* params[MAX_PARAMS];
-  size_t num_params;
-  char* output = NULL;
-  int result;
-  HandleFunc function;
-
-  num_params = ParseMessage(message, &function_name, &params[0], MAX_PARAMS);
+static void HandleMessage(struct PP_Var message) {
+  const char* function_name;
+  struct PP_Var params;
+  if (ParseMessage(message, &function_name, &params)) {
+    PostMessageVar(CStrToVar("Error: Unable to parse message"));
+    return;
+  }
 
-  function = GetFunctionByName(function_name);
+  HandleFunc function = GetFunctionByName(function_name);
   if (!function) {
     /* Function name wasn't found. Error. */
-    ppb_messaging_interface->PostMessage(
-        g_instance,
+    PostMessageVar(
         PrintfToVar("Error: Unknown function \"%s\"", function_name));
     return;
   }
 
   /* Function name was found, call it. */
-  result = (*function)(num_params, &params[0], &output);
+  struct PP_Var result_var;
+  const char* error;
+  int result = (*function)(params, &result_var, &error);
   if (result != 0) {
     /* Error. */
     struct PP_Var var;
-    if (output != NULL) {
-      var = PrintfToVar("Error: \"%s\" failed: %d: %s.", function_name,
-                        result, output);
-      free(output);
+    if (error != NULL) {
+      var = PrintfToVar("Error: \"%s\" failed: %s.", function_name, error);
+      free((void*)error);
     } else {
-      var = PrintfToVar(
-          "Error: \"%s\" failed: %d.", function_name, result);
+      var = PrintfToVar("Error: \"%s\" failed.", function_name);
     }
 
     /* Post the error to JavaScript, so the user can see it. */
-    ppb_messaging_interface->PostMessage(g_instance, var);
+    PostMessageVar(var);
     return;
   }
 
-  if (output != NULL) {
-    /* Function returned an output string. Send it to JavaScript. */
-    ppb_messaging_interface->PostMessage(g_instance, CStrToVar(output));
-    free(output);
-  }
+  /* Function returned an output dictionary. Send it to JavaScript. */
+  PostMessageVar(result_var);
+  g_ppb_var->Release(result_var);
 }
 
 /**
@@ -290,9 +286,9 @@ static void HandleMessage(char* message) {
  */
 void* HandleMessageThread(void* user_data) {
   while (1) {
-    char* message = DequeueMessage();
+    struct PP_Var message = DequeueMessage();
     HandleMessage(message);
-    free(message);
+    g_ppb_var->Release(message);
   }
 }
 
@@ -301,7 +297,7 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
                                   const char* argn[],
                                   const char* argv[]) {
   g_instance = instance;
-  nacl_io_init_ppapi(instance, get_browser_interface);
+  nacl_io_init_ppapi(instance, g_get_browser_interface);
 
   // By default, nacl_io mounts / to pass through to the original NaCl
   // filesystem (which doesn't do much). Let's remount it to a memfs
@@ -327,12 +323,15 @@ static PP_Bool Instance_DidCreate(PP_Instance instance,
   return PP_TRUE;
 }
 
-static void Instance_DidDestroy(PP_Instance instance) {}
+static void Instance_DidDestroy(PP_Instance instance) {
+}
 
 static void Instance_DidChangeView(PP_Instance instance,
-                                   PP_Resource view_resource) {}
+                                   PP_Resource view_resource) {
+}
 
-static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {}
+static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
+}
 
 static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
                                            PP_Resource url_loader) {
@@ -342,42 +341,50 @@ static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
 
 static void Messaging_HandleMessage(PP_Instance instance,
                                     struct PP_Var message) {
-  char buffer[1024];
-  VarToCStr(message, &buffer[0], 1024);
-  if (!EnqueueMessage(strdup(buffer))) {
-    struct PP_Var var;
-    var = PrintfToVar(
-        "Warning: dropped message \"%s\" because the queue was full.", message);
-    ppb_messaging_interface->PostMessage(g_instance, var);
+  g_ppb_var->AddRef(message);
+  if (!EnqueueMessage(message)) {
+    g_ppb_var->Release(message);
+    PostMessageVar(
+        PrintfToVar("Warning: dropped message because the queue was full."));
   }
 }
 
+#define GET_INTERFACE(var, type, name)            \
+  var = (type*)(get_browser(name));               \
+  if (!var) {                                     \
+    printf("Unable to get interface " name "\n"); \
+    return PP_ERROR_FAILED;                       \
+  }
+
 PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
                                        PPB_GetInterface get_browser) {
-  get_browser_interface = get_browser;
-  ppb_messaging_interface =
-      (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
-  ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
+  g_get_browser_interface = get_browser;
+  GET_INTERFACE(g_ppb_messaging, PPB_Messaging, PPB_MESSAGING_INTERFACE);
+  GET_INTERFACE(g_ppb_var, PPB_Var, PPB_VAR_INTERFACE);
+  GET_INTERFACE(g_ppb_var_array, PPB_VarArray, PPB_VAR_ARRAY_INTERFACE);
+  GET_INTERFACE(
+      g_ppb_var_dictionary, PPB_VarDictionary, PPB_VAR_DICTIONARY_INTERFACE);
   return PP_OK;
 }
 
 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
   if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
     static PPP_Instance instance_interface = {
-      &Instance_DidCreate,
-      &Instance_DidDestroy,
-      &Instance_DidChangeView,
-      &Instance_DidChangeFocus,
-      &Instance_HandleDocumentLoad,
+        &Instance_DidCreate,
+        &Instance_DidDestroy,
+        &Instance_DidChangeView,
+        &Instance_DidChangeFocus,
+        &Instance_HandleDocumentLoad,
     };
     return &instance_interface;
   } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
     static PPP_Messaging messaging_interface = {
-      &Messaging_HandleMessage,
+        &Messaging_HandleMessage,
     };
     return &messaging_interface;
   }
   return NULL;
 }
 
-PP_EXPORT void PPP_ShutdownModule() {}
+PP_EXPORT void PPP_ShutdownModule() {
+}