Native Client(NaCl)をやってみる (8) - pp::FileSystem -

2012-10-28T00:00:00+00:00 C++ Native Client

タイトル通り、今まで同様にサンプル(今回はfile_io)にあるソースを読んでやってみてる。File IOなAPIを使ってストレージサービス(Webサービスでは無い)なところにデータを読み書きしてみる

sample.cc

#include <iostream>
#include <sstream>
#include <time.h>

#include "ppapi/c/ppb_file_io.h"

#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/file_system.h"
#include "ppapi/cpp/file_ref.h"
#include "ppapi/cpp/file_io.h"
#include "ppapi/utility/completion_callback_factory.h"

using namespace std;

const string filename = "/sample.txt";

class SampleInstance : public pp::Instance {
  public:
    explicit SampleInstance(PP_Instance instance) :
      pp::Instance(instance),
      fs_(this, PP_FILESYSTEMTYPE_LOCALPERSISTENT),
      factory_(this) {
    }

    virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
      pp::CompletionCallback callback = factory_.NewCallback(
        &SampleInstance::OnFileSystemOpen
      );

      int32_t rv = fs_.Open(1024 * 1024, callback);

      if (rv != PP_OK_COMPLETIONPENDING) {
        callback.Run(rv);

        return false;
      }

      return true;
    }

    virtual void HandleMessage(const pp::Var& message) {
      string s = message.AsString();

      if (s.compare("load") == 0) {
        Load();
      } else if (s.compare("save") == 0) {
        Save();
      } else {
        PostMessage("Unknown Command");
      }
    }

  private:
    pp::FileSystem fs_;
    pp::CompletionCallbackFactory<SampleInstance> factory_;

    struct RequestFileInfo {
      pp::FileIO file;
      pp::FileRef ref;
      PP_FileInfo stat;
      string data;
    };

    long getTime() {
      time_t timer;
      time(&timer);

      long t = timer;

      return t;
    }

    void OnFileSystemOpen(int32_t result) {
      if (result != PP_OK) {
        return;
      }

      PostMessage("OnFileSystemOpen");
    }

    void Load() {
      SampleInstance::RequestFileInfo* info;
      info = new SampleInstance::RequestFileInfo();

      info->file = pp::FileIO(this);
      info->ref = pp::FileRef(fs_, filename.c_str());


      pp::CompletionCallback callback = factory_.NewCallback(
        &SampleInstance::OnLoad,
        info
      );

      int32_t rv = info->file.Open(info->ref, PP_FILEOPENFLAG_READ, callback);

      if (rv != PP_OK_COMPLETIONPENDING) {
        callback.Run(rv);
      }

      PostMessage("Load");
    }

    void OnLoad(int32_t result, SampleInstance::RequestFileInfo* info) {
      if (result != PP_OK) {
        if (result == PP_ERROR_FILENOTFOUND) {
          PostMessage("404");
        }

        delete info;

        return;
      }

      pp::CompletionCallback callback = factory_.NewCallback(
        &SampleInstance::OnQuery,
        info
      );

      int32_t rv = info->file.Query(&info->stat, callback);

      if (rv != PP_OK_COMPLETIONPENDING) {
        callback.Run(rv);
      }

      PostMessage("OnLoad");
    }

    void OnQuery(int32_t result, SampleInstance::RequestFileInfo* info) {
      if (result != PP_OK) {
        delete info;

        return;
      }

      info->data.resize(info->stat.size, "");

      pp::CompletionCallback callback = factory_.NewCallback(
        &SampleInstance::OnRead,
        info
      );

      int32_t rv = info->file.Read(
        0,
        &info->data[0],
        info->data.length(),
        callback
      );

      if (rv != PP_OK_COMPLETIONPENDING) {
        callback.Run(rv);
      }

      PostMessage("OnQuery");
    }

    void OnRead(int32_t result, SampleInstance::RequestFileInfo* info) {
      PostMessage("OnRead");
      PostMessage("data: " + info->data);

      delete info;
    }

    void Save() {
      SampleInstance::RequestFileInfo* info;
      info = new SampleInstance::RequestFileInfo();

      info->file = pp::FileIO(this);
      info->ref = pp::FileRef(fs_, filename.c_str());

      pp::CompletionCallback callback = factory_.NewCallback(
        &SampleInstance::OnSave,
        info
      );

      int32_t rv = info->file.Open(
        info->ref,
        PP_FILEOPENFLAG_WRITE|PP_FILEOPENFLAG_CREATE|PP_FILEOPENFLAG_TRUNCATE,
        callback
      );

      if (rv != PP_OK_COMPLETIONPENDING) {
        callback.Run(rv);
      }
    }

    void OnSave(int32_t result, SampleInstance::RequestFileInfo* info) {
      if (result != PP_OK) {
        delete info;

        return;
      }

      pp::CompletionCallback callback = factory_.NewCallback(
        &SampleInstance::OnWrite,
        info
      );

      long t = getTime();

      stringstream s;
      s << t;

      const string tStr = s.str();

      int32_t rv = info->file.Write(0, tStr.c_str(), tStr.length(), callback);

      if (rv != PP_OK_COMPLETIONPENDING) {
        callback.Run(rv);
      }

      PostMessage("OnSave");
    }

    void OnWrite(int32_t result, SampleInstance::RequestFileInfo* info) {
      pp::CompletionCallback callback = factory_.NewCallback(
        &SampleInstance::OnFlush
      );

      int32_t rv = info->file.Flush(callback);

      if (rv != PP_OK_COMPLETIONPENDING) {
        callback.Run(rv);
      }

      PostMessage("OnWrite");

      delete info;
    }

    void OnFlush(int32_t result) {
      if (result != PP_OK) {
        return;
      }

      PostMessage("OnFlush");
    }
};

class SampleModule : public pp::Module {
  public:
    SampleModule() : pp::Module() {
    }

    virtual pp::Instance* CreateInstance(PP_Instance instance) {
      return new SampleInstance(instance);
    }
};

namespace pp {
  Module* CreateModule() {
    return new SampleModule();
  }
}

とりあえず適当に現時点のタイムを書きこんでそれを読み込むだけ

index.html

<!DOCTYPE>
<html>
  <head>
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="-1" />
  </head>
  <body>
    <button id="btn1">load</button>
    <button id="btn2">save</button>
    <embed id="plugin" width="0" height="0" src="/sample.nmf" type="application/x-nacl" style="display: none" />

    <script type="text/javascript">
(function(undefined) {
  webkitStorageInfo.requestQuota(PERSISTENT, 1024 * 1024, function() {
    var plugin = document.querySelector("#plugin");
    plugin.style.display = "block";

    plugin.addEventListener("message", function(msg) {
      console.log(msg.data);
    });

    document.querySelector("#btn1").addEventListener("click", function() {
      plugin.postMessage("load");
    });

    document.querySelector("#btn2").addEventListener("click", function() {
      plugin.postMessage("save");
    });
  });
})();
    </script>
  <body>
</html>

fluentdを使ってみる Native Client(NaCl)をやってみる (7) - pp::WebSocket -