Android: Add content provider support to File::OpenFStream
This commit is contained in:
parent
64afe97491
commit
99ffee9a0a
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||
|
||||
#include <ios>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
@ -66,6 +67,28 @@ std::string OpenModeToAndroid(std::string mode)
|
|||
return mode;
|
||||
}
|
||||
|
||||
std::string OpenModeToAndroid(std::ios_base::openmode mode)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
if (mode & std::ios_base::in)
|
||||
result += 'r';
|
||||
|
||||
if (mode & (std::ios_base::out | std::ios_base::app))
|
||||
result += 'w';
|
||||
|
||||
if (mode & std::ios_base::app)
|
||||
result += 'a';
|
||||
|
||||
constexpr std::ios_base::openmode t = std::ios_base::in | std::ios_base::trunc;
|
||||
if ((mode & t) == t)
|
||||
result += 't';
|
||||
|
||||
// The 'b' specifier is not supported. Since we're on POSIX, it's fine to just skip it.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int OpenAndroidContent(const std::string& uri, const std::string& mode)
|
||||
{
|
||||
JNIEnv* env = IDCache::GetEnvForThread();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <ios>
|
||||
#include <string>
|
||||
|
||||
#include <jni.h>
|
||||
|
@ -17,6 +18,7 @@ bool IsPathAndroidContent(const std::string& uri);
|
|||
|
||||
// Turns a C/C++ style mode (e.g. "rb") into one which can be used with OpenAndroidContent.
|
||||
std::string OpenModeToAndroid(std::string mode);
|
||||
std::string OpenModeToAndroid(std::ios_base::openmode mode);
|
||||
|
||||
// Opens a given file and returns a file descriptor.
|
||||
int OpenAndroidContent(const std::string& uri, const std::string& mode);
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
#include "Common/StringUtil.h"
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "Common/StringUtil.h"
|
||||
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||
#endif
|
||||
|
||||
// User directory indices for GetUserPath
|
||||
enum
|
||||
{
|
||||
|
@ -213,14 +218,20 @@ std::string GetExeDirectory();
|
|||
bool WriteStringToFile(const std::string& filename, std::string_view str);
|
||||
bool ReadFileToString(const std::string& filename, std::string& str);
|
||||
|
||||
// To deal with Windows being dumb at unicode:
|
||||
// To deal with Windows not fully supporting UTF-8 and Android not fully supporting paths.
|
||||
template <typename T>
|
||||
void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fstream.open(UTF8ToTStr(filename).c_str(), openmode);
|
||||
#else
|
||||
fstream.open(filename.c_str(), openmode);
|
||||
#ifdef ANDROID
|
||||
// Unfortunately it seems like the non-standard __open is the only way to use a file descriptor
|
||||
if (IsPathAndroidContent(filename))
|
||||
fstream.__open(OpenAndroidContent(filename, OpenModeToAndroid(openmode)), openmode);
|
||||
else
|
||||
#endif
|
||||
fstream.open(filename.c_str(), openmode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue