Add a class for accessing applications assets
authorMikko Rasa <tdb@tdb.fi>
Sun, 19 Oct 2014 22:34:17 +0000 (01:34 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 19 Oct 2014 22:34:17 +0000 (01:34 +0300)
source/io/android/asset.cpp [new file with mode: 0644]
source/io/asset.cpp [new file with mode: 0644]
source/io/asset.h [new file with mode: 0644]
source/io/unix/asset.cpp [new file with mode: 0644]

diff --git a/source/io/android/asset.cpp b/source/io/android/asset.cpp
new file mode 100644 (file)
index 0000000..1b97eae
--- /dev/null
@@ -0,0 +1,66 @@
+#include <stdexcept>
+#include <msp/core/application.h>
+#include <msp/core/mainthread.h>
+#include <android/asset_manager.h>
+#include "asset.h"
+#include "file.h"
+
+using namespace std;
+
+namespace Msp {
+namespace IO {
+
+struct Asset::Private
+{
+       AAsset *asset;
+};
+
+Asset::Asset(const string &name)
+{
+       AAssetManager *asset_manager = reinterpret_cast<Android::MainThread *>(Application::get_data())->get_asset_manager();
+       AAsset *asset = AAssetManager_open(asset_manager, name.c_str(), AASSET_MODE_RANDOM);
+       if(!asset)
+               throw file_not_found(name);
+
+       priv = new Private;
+       priv->asset = asset;
+
+       mode = M_READ;
+}
+
+Asset::~Asset()
+{
+       AAsset_close(priv->asset);
+       delete priv;
+}
+
+unsigned Asset::do_read(char *buf, unsigned size)
+{
+       int ret = AAsset_read(priv->asset, buf, size);
+       if(ret<0)
+               throw runtime_error("Asset::do_read");
+       else if(ret==0)
+               set_eof();
+
+       return ret;
+}
+
+SeekOffset Asset::seek(SeekOffset off, SeekType type)
+{
+       signal_flush_required.emit();
+       off = AAsset_seek(priv->asset, off, type);
+       if(off<0)
+               throw runtime_error("Asset::seek");
+       return off;
+}
+
+SeekOffset Asset::tell() const
+{
+       SeekOffset off = AAsset_seek(priv->asset, 0, S_CUR);
+       if(off<0)
+               throw runtime_error("Asset::tell");
+       return off;
+}
+
+} // namespace IO
+} // namespace Msp
diff --git a/source/io/asset.cpp b/source/io/asset.cpp
new file mode 100644 (file)
index 0000000..a5ce175
--- /dev/null
@@ -0,0 +1,12 @@
+#include "asset.h"
+
+namespace Msp {
+namespace IO {
+
+unsigned Asset::do_write(const char *, unsigned)
+{
+       throw invalid_access(M_WRITE);
+}
+
+} // namespace IO
+} // namespace Msp
diff --git a/source/io/asset.h b/source/io/asset.h
new file mode 100644 (file)
index 0000000..d1d63b5
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef MSP_IO_ASSET_H_
+#define MSP_IO_ASSET_H_
+
+#include "seekable.h"
+
+namespace Msp {
+namespace IO {
+
+/**
+Opens a file from the application's assets.  On Android, this means the assets
+contained within the APK.  On other platfoms, assets are located in the
+directory indicated by FS::get_sys_data_dir().  Assets are always read-only.
+*/
+class Asset: public Seekable
+{
+private:
+       struct Private;
+
+       Private *priv;
+
+public:
+       Asset(const std::string &);
+       ~Asset();
+
+private:
+       virtual unsigned do_write(const char *, unsigned);
+       virtual unsigned do_read(char *, unsigned);
+
+public:
+       virtual SeekOffset seek(SeekOffset, SeekType);
+       virtual SeekOffset tell() const;
+};
+
+} // namespace IO
+} // namespace Msp
+
+#endif
diff --git a/source/io/unix/asset.cpp b/source/io/unix/asset.cpp
new file mode 100644 (file)
index 0000000..7971f1b
--- /dev/null
@@ -0,0 +1,47 @@
+#include <msp/fs/dir.h>
+#include "asset.h"
+#include "file.h"
+
+using namespace std;
+
+namespace Msp {
+namespace IO {
+
+struct Asset::Private
+{
+       Seekable *file;
+};
+
+Asset::Asset(const string &name)
+{
+       Seekable *file = new BufferedFile((FS::get_sys_data_dir()/name).str());
+
+       priv = new Private;
+       priv->file = file;
+
+       priv->file->signal_flush_required.connect(signal_flush_required);
+}
+
+Asset::~Asset()
+{
+       delete priv->file;
+       delete priv;
+}
+
+unsigned Asset::do_read(char *buf, unsigned size)
+{
+       return priv->file->read(buf, size);
+}
+
+SeekOffset Asset::seek(SeekOffset off, SeekType type)
+{
+       return priv->file->seek(off, type);
+}
+
+SeekOffset Asset::tell() const
+{
+       return priv->file->tell();
+}
+
+} // namespace IO
+} // namespace Msp