mirror of https://github.com/axmolengine/axmol.git
Merge pull request #340 from rh101/vfs-support
Enhance FileStream support to allow usage of virtual file systems
This commit is contained in:
commit
dd69c21c0e
|
@ -68,8 +68,8 @@ static unsigned long ft_stream_read_callback(FT_Stream stream, unsigned long off
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ft_stream_close_callback(FT_Stream stream) {
|
static void ft_stream_close_callback(FT_Stream stream) {
|
||||||
auto fd = (FileStream*)stream->descriptor.pointer;
|
const auto* fd = (FileStream*)stream->descriptor.pointer;
|
||||||
if (fd) delete fd;
|
delete fd;
|
||||||
stream->size = 0;
|
stream->size = 0;
|
||||||
stream->descriptor.pointer = nullptr;
|
stream->descriptor.pointer = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -174,21 +174,23 @@ bool FontFreeType::createFontObject(const std::string &fontName, float fontSize)
|
||||||
auto fullPath = FileUtils::getInstance()->fullPathForFilename(fontName);
|
auto fullPath = FileUtils::getInstance()->fullPathForFilename(fontName);
|
||||||
if (fullPath.empty()) return false;
|
if (fullPath.empty()) return false;
|
||||||
|
|
||||||
FileStream fs;
|
FileStream* fs = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
|
||||||
if (!fs.open(fullPath, FileStream::Mode::READ))
|
if (!fs)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<FT_StreamRec> fts(new FT_StreamRec());
|
std::unique_ptr<FT_StreamRec> fts(new FT_StreamRec());
|
||||||
fts->read = ft_stream_read_callback;
|
fts->read = ft_stream_read_callback;
|
||||||
fts->close = ft_stream_close_callback;
|
fts->close = ft_stream_close_callback;
|
||||||
fts->size = fs.seek(0, SEEK_END);
|
fts->size = fs->seek(0, SEEK_END);
|
||||||
fs.seek(0, SEEK_SET);
|
fs->seek(0, SEEK_SET);
|
||||||
|
|
||||||
fts->descriptor.pointer = new FileStream(std::move(fs));
|
fts->descriptor.pointer = fs;
|
||||||
|
|
||||||
FT_Open_Args args = { 0 };
|
FT_Open_Args args = { 0 };
|
||||||
args.flags = FT_OPEN_STREAM;
|
args.flags = FT_OPEN_STREAM;
|
||||||
args.stream = fts.get();;
|
args.stream = fts.get();
|
||||||
|
|
||||||
if (FT_Open_Face(getFTLibrary(), &args, 0, &face))
|
if (FT_Open_Face(getFTLibrary(), &args, 0, &face))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -80,7 +80,7 @@ protected:
|
||||||
static bool lazyInit();
|
static bool lazyInit();
|
||||||
static void destroy();
|
static void destroy();
|
||||||
|
|
||||||
FileStream _fileStream;
|
FileStream* _fileStream = nullptr;
|
||||||
mp3dec_handle_t _handle;
|
mp3dec_handle_t _handle;
|
||||||
|
|
||||||
friend class AudioDecoderManager;
|
friend class AudioDecoderManager;
|
||||||
|
|
|
@ -68,7 +68,7 @@ protected:
|
||||||
AudioDecoderOgg();
|
AudioDecoderOgg();
|
||||||
~AudioDecoderOgg();
|
~AudioDecoderOgg();
|
||||||
|
|
||||||
FileStream _fileStream;
|
FileStream* _fileStream;
|
||||||
OggVorbis_File _vf;
|
OggVorbis_File _vf;
|
||||||
|
|
||||||
friend class AudioDecoderManager;
|
friend class AudioDecoderManager;
|
||||||
|
|
|
@ -106,7 +106,7 @@ struct WAV_FILE
|
||||||
WAV_FILE_HEADER FileHeader;
|
WAV_FILE_HEADER FileHeader;
|
||||||
AUDIO_SOURCE_FORMAT SourceFormat;
|
AUDIO_SOURCE_FORMAT SourceFormat;
|
||||||
uint32_t PcmDataOffset;
|
uint32_t PcmDataOffset;
|
||||||
cocos2d::FileStream Stream;
|
cocos2d::FileStream* Stream = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,9 @@ namespace cocos2d {
|
||||||
#if !CC_USE_MPG123
|
#if !CC_USE_MPG123
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!_fileStream.open(fullPath, FileStream::Mode::READ))
|
delete _fileStream;
|
||||||
|
_fileStream = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
|
||||||
|
if (!_fileStream)
|
||||||
{
|
{
|
||||||
ALOGE("Trouble with minimp3(1): %s\n", strerror(errno));
|
ALOGE("Trouble with minimp3(1): %s\n", strerror(errno));
|
||||||
break;
|
break;
|
||||||
|
@ -138,7 +140,7 @@ namespace cocos2d {
|
||||||
|
|
||||||
handle->_decIO.read = minimp3_read_r;
|
handle->_decIO.read = minimp3_read_r;
|
||||||
handle->_decIO.seek = minimp3_seek_r;
|
handle->_decIO.seek = minimp3_seek_r;
|
||||||
handle->_decIO.read_data = handle->_decIO.seek_data = &_fileStream;
|
handle->_decIO.read_data = handle->_decIO.seek_data = _fileStream;
|
||||||
|
|
||||||
if (mp3dec_ex_open_cb(&handle->_dec, &handle->_decIO, MP3D_SEEK_TO_SAMPLE) != 0)
|
if (mp3dec_ex_open_cb(&handle->_dec, &handle->_decIO, MP3D_SEEK_TO_SAMPLE) != 0)
|
||||||
{
|
{
|
||||||
|
@ -189,7 +191,7 @@ namespace cocos2d {
|
||||||
|
|
||||||
mpg123_replace_reader_handle(_handle, mpg123_read_r, mpg123_lseek_r, mpg123_close_r);
|
mpg123_replace_reader_handle(_handle, mpg123_read_r, mpg123_lseek_r, mpg123_close_r);
|
||||||
|
|
||||||
if (mpg123_open_handle(_handle, &_fileStream) != MPG123_OK
|
if (mpg123_open_handle(_handle, _fileStream) != MPG123_OK
|
||||||
|| mpg123_getformat(_handle, &rate, &channel, &mp3Encoding) != MPG123_OK)
|
|| mpg123_getformat(_handle, &rate, &channel, &mp3Encoding) != MPG123_OK)
|
||||||
{
|
{
|
||||||
ALOGE("Trouble with mpg123(2): %s\n", mpg123_strerror(_handle));
|
ALOGE("Trouble with mpg123(2): %s\n", mpg123_strerror(_handle));
|
||||||
|
@ -248,7 +250,8 @@ namespace cocos2d {
|
||||||
delete _handle;
|
delete _handle;
|
||||||
_handle = nullptr;
|
_handle = nullptr;
|
||||||
|
|
||||||
_fileStream.close();
|
delete _fileStream;
|
||||||
|
_fileStream = nullptr;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (_handle != nullptr)
|
if (_handle != nullptr)
|
||||||
|
@ -256,6 +259,9 @@ namespace cocos2d {
|
||||||
mpg123_close(_handle);
|
mpg123_close(_handle);
|
||||||
mpg123_delete(_handle);
|
mpg123_delete(_handle);
|
||||||
_handle = nullptr;
|
_handle = nullptr;
|
||||||
|
|
||||||
|
delete _fileStream;
|
||||||
|
_fileStream = nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_isOpened = false;
|
_isOpened = false;
|
||||||
|
|
|
@ -69,7 +69,8 @@ namespace cocos2d {
|
||||||
|
|
||||||
bool AudioDecoderOgg::open(const std::string& fullPath)
|
bool AudioDecoderOgg::open(const std::string& fullPath)
|
||||||
{
|
{
|
||||||
if (!_fileStream.open(fullPath, FileStream::Mode::READ))
|
_fileStream = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
|
||||||
|
if (!_fileStream)
|
||||||
{
|
{
|
||||||
ALOGE("Trouble with ogg(1): %s\n", strerror(errno));
|
ALOGE("Trouble with ogg(1): %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -52,23 +52,23 @@ namespace cocos2d {
|
||||||
static bool wav_scan_chunk(WAV_FILE* wavf, uint32_t chunkID, void* header, void* body, uint32_t bodySize) {
|
static bool wav_scan_chunk(WAV_FILE* wavf, uint32_t chunkID, void* header, void* body, uint32_t bodySize) {
|
||||||
auto& fs = wavf->Stream;
|
auto& fs = wavf->Stream;
|
||||||
auto h = (WAV_CHUNK_HEADER*)header;
|
auto h = (WAV_CHUNK_HEADER*)header;
|
||||||
for (; fs.read(h, WAV_HEADER_SIZE) == WAV_HEADER_SIZE; ) {
|
for (; fs->read(h, WAV_HEADER_SIZE) == WAV_HEADER_SIZE; ) {
|
||||||
wavf->PcmDataOffset += WAV_HEADER_SIZE;
|
wavf->PcmDataOffset += WAV_HEADER_SIZE;
|
||||||
if (h->ChunkID == chunkID)
|
if (h->ChunkID == chunkID)
|
||||||
{ // chunk found
|
{ // chunk found
|
||||||
if (body)
|
if (body)
|
||||||
{ // require read body?
|
{ // require read body?
|
||||||
auto readsize = (std::min)(bodySize, h->ChunkSize);
|
auto readsize = (std::min)(bodySize, h->ChunkSize);
|
||||||
fs.read(body, readsize);
|
fs->read(body, readsize);
|
||||||
if (h->ChunkSize > bodySize)
|
if (h->ChunkSize > bodySize)
|
||||||
fs.seek(h->ChunkSize - bodySize, SEEK_CUR);
|
fs->seek(h->ChunkSize - bodySize, SEEK_CUR);
|
||||||
wavf->PcmDataOffset += h->ChunkSize;
|
wavf->PcmDataOffset += h->ChunkSize;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Skip other non specified chunk
|
// Skip other non specified chunk
|
||||||
fs.seek(h->ChunkSize, SEEK_CUR);
|
fs->seek(h->ChunkSize, SEEK_CUR);
|
||||||
wavf->PcmDataOffset += h->ChunkSize;
|
wavf->PcmDataOffset += h->ChunkSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,15 +76,16 @@ namespace cocos2d {
|
||||||
}
|
}
|
||||||
static bool wav_open(const std::string& fullPath, WAV_FILE* wavf)
|
static bool wav_open(const std::string& fullPath, WAV_FILE* wavf)
|
||||||
{
|
{
|
||||||
bool succeed = wavf->Stream.open(fullPath, FileStream::Mode::READ);
|
delete wavf->Stream;
|
||||||
if (!succeed)
|
wavf->Stream = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
|
||||||
|
if (!wavf->Stream)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto& fileStream = wavf->Stream;
|
auto& fileStream = wavf->Stream;
|
||||||
wavf->PcmDataOffset = 0;
|
wavf->PcmDataOffset = 0;
|
||||||
|
|
||||||
// Parsing RIFF chunk
|
// Parsing RIFF chunk
|
||||||
fileStream.read(&wavf->FileHeader, WAV_RIFF_SIZE);
|
fileStream->read(&wavf->FileHeader, WAV_RIFF_SIZE);
|
||||||
wavf->PcmDataOffset += WAV_RIFF_SIZE;
|
wavf->PcmDataOffset += WAV_RIFF_SIZE;
|
||||||
|
|
||||||
if (wavf->FileHeader.Riff.Format != WAV_SIGN_ID)
|
if (wavf->FileHeader.Riff.Format != WAV_SIGN_ID)
|
||||||
|
@ -132,13 +133,13 @@ namespace cocos2d {
|
||||||
if (!IsEqualGUID(fmtInfo.ExtParams.SubFormat, WAV_SUBTYPE_PCM)
|
if (!IsEqualGUID(fmtInfo.ExtParams.SubFormat, WAV_SUBTYPE_PCM)
|
||||||
&& !IsEqualGUID(fmtInfo.ExtParams.SubFormat, WAV_SUBTYPE_IEEE_FLOAT))
|
&& !IsEqualGUID(fmtInfo.ExtParams.SubFormat, WAV_SUBTYPE_IEEE_FLOAT))
|
||||||
{
|
{
|
||||||
fileStream.close();
|
fileStream->close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ALOGW("The wav format %d doesn't supported currently!", (int)fmtInfo.AudioFormat);
|
ALOGW("The wav format %d doesn't supported currently!", (int)fmtInfo.AudioFormat);
|
||||||
fileStream.close();
|
fileStream->close();
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;;
|
return false;;
|
||||||
}
|
}
|
||||||
|
@ -148,18 +149,21 @@ namespace cocos2d {
|
||||||
|
|
||||||
static int wav_read(WAV_FILE* wavf, char* pcmBuf, uint32_t bytesToRead)
|
static int wav_read(WAV_FILE* wavf, char* pcmBuf, uint32_t bytesToRead)
|
||||||
{
|
{
|
||||||
return wavf->Stream.read(pcmBuf, bytesToRead);
|
return wavf->Stream->read(pcmBuf, bytesToRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wav_seek(WAV_FILE* wavf, int offset)
|
static int wav_seek(WAV_FILE* wavf, int offset)
|
||||||
{
|
{
|
||||||
auto newOffset = wavf->Stream.seek(wavf->PcmDataOffset + offset, SEEK_SET);
|
auto newOffset = wavf->Stream->seek(wavf->PcmDataOffset + offset, SEEK_SET);
|
||||||
return newOffset >= wavf->PcmDataOffset ? newOffset - wavf->PcmDataOffset : -1;
|
return newOffset >= wavf->PcmDataOffset ? newOffset - wavf->PcmDataOffset : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wav_close(WAV_FILE* wavf)
|
static int wav_close(WAV_FILE* wavf)
|
||||||
{
|
{
|
||||||
return wavf->Stream.close();
|
const auto result = wavf->Stream->close();
|
||||||
|
delete wavf->Stream;
|
||||||
|
wavf->Stream = nullptr;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDecoderWav::AudioDecoderWav()
|
AudioDecoderWav::AudioDecoderWav()
|
||||||
|
|
|
@ -35,6 +35,7 @@ THE SOFTWARE.
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "openssl/aes.h"
|
#include "openssl/aes.h"
|
||||||
#include "openssl/modes.h"
|
#include "openssl/modes.h"
|
||||||
|
@ -51,7 +52,7 @@ THE SOFTWARE.
|
||||||
#include "yasio/obstream.hpp"
|
#include "yasio/obstream.hpp"
|
||||||
#include "yasio/detail/sz.hpp"
|
#include "yasio/detail/sz.hpp"
|
||||||
|
|
||||||
#include "CCFileStream.h"
|
#include "CCPosixFileStream.h"
|
||||||
|
|
||||||
#define USER_DEFAULT_PLAIN_MODE 0
|
#define USER_DEFAULT_PLAIN_MODE 0
|
||||||
|
|
||||||
|
@ -132,10 +133,12 @@ UserDefault::UserDefault()
|
||||||
void UserDefault::closeFileMapping()
|
void UserDefault::closeFileMapping()
|
||||||
{
|
{
|
||||||
_rwmmap.reset();
|
_rwmmap.reset();
|
||||||
|
#if !USER_DEFAULT_PLAIN_MODE
|
||||||
if (_fd != -1) {
|
if (_fd != -1) {
|
||||||
posix_close(_fd);
|
posix_close(_fd);
|
||||||
_fd = -1;
|
_fd = -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserDefault::getBoolForKey(const char* pKey)
|
bool UserDefault::getBoolForKey(const char* pKey)
|
||||||
|
@ -369,9 +372,9 @@ void UserDefault::lazyInit()
|
||||||
{
|
{
|
||||||
if (_initialized) return;
|
if (_initialized) return;
|
||||||
|
|
||||||
_filePath = FileUtils::getInstance()->getWritablePath() + USER_DEFAULT_FILENAME;
|
|
||||||
|
|
||||||
#if !USER_DEFAULT_PLAIN_MODE
|
#if !USER_DEFAULT_PLAIN_MODE
|
||||||
|
_filePath = FileUtils::getInstance()->getNativeWritableAbsolutePath() + USER_DEFAULT_FILENAME;
|
||||||
|
|
||||||
// construct file mapping
|
// construct file mapping
|
||||||
_fd = posix_open(_filePath.c_str(), O_OVERLAP_FLAGS);
|
_fd = posix_open(_filePath.c_str(), O_OVERLAP_FLAGS);
|
||||||
if (_fd == -1) {
|
if (_fd == -1) {
|
||||||
|
@ -415,14 +418,22 @@ void UserDefault::lazyInit()
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result ret = doc.load_file(_filePath.c_str());
|
|
||||||
if (ret) {
|
_filePath = FileUtils::getInstance()->getWritablePath() + USER_DEFAULT_FILENAME;
|
||||||
for (auto& elem : doc.document_element())
|
|
||||||
updateValueForKey(elem.name(), elem.text().as_string());
|
if (FileUtils::getInstance()->isFileExist(_filePath))
|
||||||
}
|
{
|
||||||
else {
|
auto data = FileUtils::getInstance()->getDataFromFile(_filePath);
|
||||||
log("UserDefault::init load xml file: %s failed, %s", _filePath.c_str(), ret.description());
|
pugi::xml_parse_result ret = doc.load_buffer_inplace(data.getBytes(), data.getSize());
|
||||||
|
if (ret) {
|
||||||
|
for (auto& elem : doc.document_element())
|
||||||
|
updateValueForKey(elem.name(), elem.text().as_string());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log("UserDefault::init load xml file: %s failed, %s", _filePath.c_str(), ret.description());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
@ -474,7 +485,10 @@ void UserDefault::flush()
|
||||||
r.append_child(kv.first.c_str())
|
r.append_child(kv.first.c_str())
|
||||||
.append_child(pugi::xml_node_type::node_pcdata)
|
.append_child(pugi::xml_node_type::node_pcdata)
|
||||||
.set_value(kv.second.c_str());
|
.set_value(kv.second.c_str());
|
||||||
doc.save_file(_filePath.c_str(), " ");
|
|
||||||
|
std::stringstream ss;
|
||||||
|
doc.save(ss, " ");
|
||||||
|
FileUtils::getInstance()->writeStringToFile(ss.str(), _filePath);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "network/CCDownloader-curl.h"
|
#include "network/CCDownloader-curl.h"
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
@ -38,7 +39,6 @@
|
||||||
#include "platform/CCFileStream.h"
|
#include "platform/CCFileStream.h"
|
||||||
#include "md5/md5.h"
|
#include "md5/md5.h"
|
||||||
#include "yasio/xxsocket.hpp"
|
#include "yasio/xxsocket.hpp"
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
// **NOTE**
|
// **NOTE**
|
||||||
// In the file:
|
// In the file:
|
||||||
|
@ -87,11 +87,8 @@ namespace cocos2d { namespace network {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_fs)
|
delete _fs;
|
||||||
_fs.close();
|
delete _fsMd5;
|
||||||
|
|
||||||
if (_fsMd5)
|
|
||||||
_fsMd5.close();
|
|
||||||
|
|
||||||
if (_requestHeaders)
|
if (_requestHeaders)
|
||||||
curl_slist_free_all(_requestHeaders);
|
curl_slist_free_all(_requestHeaders);
|
||||||
|
@ -152,7 +149,7 @@ namespace cocos2d { namespace network {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// open file
|
// open file
|
||||||
_fs.open(_tempFileName, FileStream::Mode::APPEND);
|
_fs = FileUtils::getInstance()->openFileStream(_tempFileName, FileStream::Mode::APPEND);
|
||||||
if (!_fs)
|
if (!_fs)
|
||||||
{
|
{
|
||||||
_errCode = DownloadTask::ERROR_OPEN_FILE_FAILED;
|
_errCode = DownloadTask::ERROR_OPEN_FILE_FAILED;
|
||||||
|
@ -164,13 +161,14 @@ namespace cocos2d { namespace network {
|
||||||
|
|
||||||
// init md5 state
|
// init md5 state
|
||||||
_checksumFileName = filename + ".chksum";
|
_checksumFileName = filename + ".chksum";
|
||||||
_fsMd5.open(_checksumFileName.c_str(), FileStream::Mode::WRITE);
|
|
||||||
if (_fsMd5.seek(0, SEEK_END) != sizeof(md5_state_s)) {
|
_fsMd5 = FileUtils::getInstance()->openFileStream(_checksumFileName, FileStream::Mode::WRITE);
|
||||||
|
if (_fsMd5->seek(0, SEEK_END) != sizeof(md5_state_s)) {
|
||||||
md5_init(&_md5State);
|
md5_init(&_md5State);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_fsMd5.seek(0, SEEK_SET);
|
_fsMd5->seek(0, SEEK_SET);
|
||||||
_fsMd5.read(&_md5State, sizeof(md5_state_s));
|
_fsMd5->read(&_md5State, sizeof(md5_state_s));
|
||||||
}
|
}
|
||||||
ret = true;
|
ret = true;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
@ -242,9 +240,9 @@ namespace cocos2d { namespace network {
|
||||||
|
|
||||||
auto bytes_transferred = size * count;
|
auto bytes_transferred = size * count;
|
||||||
|
|
||||||
if (_fs)
|
if (_fs->isOpen())
|
||||||
{
|
{
|
||||||
ret = _fs.write(buffer, bytes_transferred);// fwrite(buffer, size, count, _fp);
|
ret = _fs->write(buffer, bytes_transferred);// fwrite(buffer, size, count, _fp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -263,8 +261,8 @@ namespace cocos2d { namespace network {
|
||||||
_totalBytesReceived += ret;
|
_totalBytesReceived += ret;
|
||||||
|
|
||||||
::md5_append(&_md5State, buffer, bytes_transferred);
|
::md5_append(&_md5State, buffer, bytes_transferred);
|
||||||
_fsMd5.seek(0, SEEK_SET);
|
_fsMd5->seek(0, SEEK_SET);
|
||||||
_fsMd5.write(&_md5State, sizeof(_md5State));
|
_fsMd5->write(&_md5State, sizeof(_md5State));
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_easy_getinfo(_curl, CURLINFO_SPEED_DOWNLOAD, &_speed);
|
curl_easy_getinfo(_curl, CURLINFO_SPEED_DOWNLOAD, &_speed);
|
||||||
|
@ -306,10 +304,10 @@ namespace cocos2d { namespace network {
|
||||||
string _tempFileName;
|
string _tempFileName;
|
||||||
std::string _checksumFileName;
|
std::string _checksumFileName;
|
||||||
vector<unsigned char> _buf;
|
vector<unsigned char> _buf;
|
||||||
FileStream _fs;
|
FileStream* _fs;
|
||||||
|
|
||||||
// calculate md5 in downloading time support
|
// calculate md5 in downloading time support
|
||||||
FileStream _fsMd5; // store md5 state realtime
|
FileStream* _fsMd5; // store md5 state realtime
|
||||||
md5_state_s _md5State;
|
md5_state_s _md5State;
|
||||||
|
|
||||||
|
|
||||||
|
@ -887,8 +885,7 @@ public:
|
||||||
task.progressInfo.totalBytesReceived = coTask._totalBytesReceived;
|
task.progressInfo.totalBytesReceived = coTask._totalBytesReceived;
|
||||||
task.progressInfo.totalBytesExpected = coTask._totalBytesExpected;
|
task.progressInfo.totalBytesExpected = coTask._totalBytesExpected;
|
||||||
task.progressInfo.speedInBytes = coTask._speed;
|
task.progressInfo.speedInBytes = coTask._speed;
|
||||||
onTaskProgress(task,
|
onTaskProgress(task, _transferDataToBuffer);
|
||||||
_transferDataToBuffer);
|
|
||||||
coTask._bytesReceived = 0;
|
coTask._bytesReceived = 0;
|
||||||
_currTask = nullptr;
|
_currTask = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -899,14 +896,14 @@ public:
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto pFileUtils = FileUtils::getInstance();
|
auto pFileUtils = FileUtils::getInstance();
|
||||||
coTask._fs.close();
|
coTask._fs->close();
|
||||||
coTask._fsMd5.close();
|
coTask._fsMd5->close();
|
||||||
|
|
||||||
if (checkState & kCheckSumStateSucceed) // No need download
|
if (checkState & kCheckSumStateSucceed) // No need download
|
||||||
{
|
{
|
||||||
FileStream fsOrigin;
|
FileStream* fsOrigin = FileUtils::getInstance()->openFileStream(coTask._fileName, FileStream::Mode::READ);
|
||||||
if (fsOrigin.open(coTask._fileName, FileStream::Mode::READ)) {
|
if (fsOrigin) {
|
||||||
task.progressInfo.totalBytesExpected = fsOrigin.seek(0, SEEK_END);
|
task.progressInfo.totalBytesExpected = fsOrigin->seek(0, SEEK_END);
|
||||||
task.progressInfo.bytesReceived = task.progressInfo.totalBytesExpected;
|
task.progressInfo.bytesReceived = task.progressInfo.totalBytesExpected;
|
||||||
task.progressInfo.totalBytesReceived = task.progressInfo.totalBytesExpected;
|
task.progressInfo.totalBytesReceived = task.progressInfo.totalBytesExpected;
|
||||||
task.progressInfo.speedInBytes = task.progressInfo.totalBytesExpected;
|
task.progressInfo.speedInBytes = task.progressInfo.totalBytesExpected;
|
||||||
|
@ -916,8 +913,10 @@ public:
|
||||||
|
|
||||||
pFileUtils->removeFile(coTask._tempFileName);
|
pFileUtils->removeFile(coTask._tempFileName);
|
||||||
|
|
||||||
onTaskProgress(task,
|
onTaskProgress(task,_transferDataToBuffer);
|
||||||
_transferDataToBuffer);
|
|
||||||
|
delete fsOrigin;
|
||||||
|
fsOrigin = nullptr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
coTask._errCode = DownloadTask::ERROR_ORIGIN_FILE_MISSING;
|
coTask._errCode = DownloadTask::ERROR_ORIGIN_FILE_MISSING;
|
||||||
|
@ -926,6 +925,7 @@ public:
|
||||||
pFileUtils->removeFile(coTask._checksumFileName);
|
pFileUtils->removeFile(coTask._checksumFileName);
|
||||||
pFileUtils->removeFile(coTask._tempFileName);
|
pFileUtils->removeFile(coTask._tempFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,199 +2,6 @@
|
||||||
// Copyright (c) 2020 c4games.com
|
// Copyright (c) 2020 c4games.com
|
||||||
#include "platform/CCFileStream.h"
|
#include "platform/CCFileStream.h"
|
||||||
|
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
|
||||||
#include "base/ZipUtils.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
struct PXIoF {
|
|
||||||
int(*read)(PXFileHandle& handle, void*, unsigned int);
|
|
||||||
long(*seek)(PXFileHandle& handle, long, int);
|
|
||||||
int(*close)(PXFileHandle& handle);
|
|
||||||
};
|
|
||||||
|
|
||||||
static int pfs_posix_open(const std::string& path, FileStream::Mode mode, PXFileHandle& handle)
|
|
||||||
{
|
|
||||||
switch (mode) {
|
|
||||||
case FileStream::Mode::READ:
|
|
||||||
handle._fd = posix_open(path.c_str(), O_READ_FLAGS);
|
|
||||||
break;
|
|
||||||
case FileStream::Mode::WRITE:
|
|
||||||
handle._fd = posix_open(path.c_str(), O_WRITE_FLAGS);
|
|
||||||
break;
|
|
||||||
case FileStream::Mode::APPEND:
|
|
||||||
handle._fd = posix_open(path.c_str(), O_APPEND_FLAGS);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
handle._fd = -1;
|
|
||||||
}
|
|
||||||
return handle._fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// posix standard wrappers
|
|
||||||
static int pfs_posix_read(PXFileHandle& handle, void* buf, unsigned int size) { return static_cast<int>(posix_read(handle._fd, buf, size)); }
|
|
||||||
static long pfs_posix_seek(PXFileHandle& handle, long offst, int origin) { return posix_lseek(handle._fd, offst, origin); }
|
|
||||||
static int pfs_posix_close(PXFileHandle& handle) {
|
|
||||||
int fd = handle._fd;
|
|
||||||
if (fd != -1) {
|
|
||||||
handle._fd = -1;
|
|
||||||
return posix_close(fd);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static PXIoF pfs_posix_iof = {
|
|
||||||
pfs_posix_read,
|
|
||||||
pfs_posix_seek,
|
|
||||||
pfs_posix_close
|
|
||||||
};
|
|
||||||
|
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
|
||||||
// android AssetManager wrappers
|
|
||||||
static int pfs_asset_read(PXFileHandle& handle, void* buf, unsigned int size) { return AAsset_read(handle._asset, buf, size); }
|
|
||||||
static long pfs_asset_seek(PXFileHandle& handle, long offst, int origin) { return AAsset_seek(handle._asset, offst, origin); }
|
|
||||||
static int pfs_asset_close(PXFileHandle& handle) {
|
|
||||||
if (handle._asset != nullptr) {
|
|
||||||
AAsset_close(handle._asset);
|
|
||||||
handle._asset = nullptr;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static PXIoF pfs_asset_iof = {
|
|
||||||
pfs_asset_read,
|
|
||||||
pfs_asset_seek,
|
|
||||||
pfs_asset_close
|
|
||||||
};
|
|
||||||
|
|
||||||
// android obb
|
|
||||||
static int pfs_obb_read(PXFileHandle& handle, void* buf, unsigned int size) { return FileUtilsAndroid::getObbFile()->zfread(&handle._zfs, buf, size); }
|
|
||||||
static long pfs_obb_seek(PXFileHandle& handle, long offset, int origin) { return FileUtilsAndroid::getObbFile()->zfseek(&handle._zfs, offset, origin); }
|
|
||||||
static int pfs_obb_close(PXFileHandle& handle) {
|
|
||||||
FileUtilsAndroid::getObbFile()->zfclose(&handle._zfs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static PXIoF pfs_obb_iof = {
|
|
||||||
pfs_obb_read,
|
|
||||||
pfs_obb_seek,
|
|
||||||
pfs_obb_close
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FileStream::FileStream()
|
|
||||||
{
|
|
||||||
zeroset();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileStream::~FileStream()
|
|
||||||
{
|
|
||||||
this->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileStream::FileStream(FileStream&& rhs)
|
|
||||||
{
|
|
||||||
zeroset();
|
|
||||||
assign(std::forward<FileStream>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
FileStream& FileStream::operator=(FileStream&& rhs)
|
|
||||||
{
|
|
||||||
assign(std::forward<FileStream>(rhs));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileStream::zeroset()
|
|
||||||
{
|
|
||||||
memset(this, 0, sizeof(FileStream));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileStream::assign(FileStream&& rhs)
|
|
||||||
{
|
|
||||||
this->close();
|
|
||||||
memcpy(this, &rhs, sizeof(FileStream));
|
|
||||||
rhs.zeroset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileStream::open(const std::string& path, FileStream::Mode mode)
|
|
||||||
{
|
|
||||||
bool ok = false;
|
|
||||||
#if CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
|
|
||||||
ok = pfs_posix_open(path, mode, _handle) != -1;
|
|
||||||
#else // Android
|
|
||||||
if (path[0] != '/') { // from package, always readonly
|
|
||||||
std::string relativePath;
|
|
||||||
size_t position = path.find("assets/");
|
|
||||||
if (0 == position)
|
|
||||||
{
|
|
||||||
// "assets/" is at the beginning of the path and we don't want it
|
|
||||||
relativePath = path.substr(sizeof("assets/") - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
relativePath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto obb = FileUtilsAndroid::getObbFile();
|
|
||||||
ok = obb != nullptr && obb->zfopen(relativePath, &_handle._zfs);
|
|
||||||
if (ok) {
|
|
||||||
this->_iof = &pfs_obb_iof;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
AAssetManager* asMgr = FileUtilsAndroid::getAssetManager();
|
|
||||||
AAsset* asset = AAssetManager_open(asMgr, relativePath.c_str(), AASSET_MODE_UNKNOWN);
|
|
||||||
ok = !!asset;
|
|
||||||
if (ok) {
|
|
||||||
_handle._asset = asset;
|
|
||||||
// setup file read/seek/close at here
|
|
||||||
this->_iof = &pfs_asset_iof;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // otherwise, as a absolutely path
|
|
||||||
ok = pfs_posix_open(path, mode, _handle) != -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ok && !_iof)
|
|
||||||
_iof = &pfs_posix_iof;
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileStream::operator bool() const
|
|
||||||
{
|
|
||||||
#if CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
|
|
||||||
return _handle._fd != -1;
|
|
||||||
#else
|
|
||||||
return _handle._fd != -1 && _handle._asset != nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileStream::close()
|
|
||||||
{
|
|
||||||
if (_iof) {
|
|
||||||
int ret = _iof->close(_handle);
|
|
||||||
_iof = nullptr;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileStream::seek(long offset, int origin)
|
|
||||||
{
|
|
||||||
return static_cast<int>(_iof->seek(_handle, offset, origin));
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileStream::read(void* buf, unsigned int size)
|
|
||||||
{
|
|
||||||
return _iof->read(_handle, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileStream::write(const void* buf, unsigned int size)
|
|
||||||
{
|
|
||||||
return static_cast<int>(posix_write(_handle._fd, buf, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_CC_END
|
NS_CC_END
|
||||||
|
|
|
@ -2,78 +2,16 @@
|
||||||
// Copyright (c) 2020 c4games.com
|
// Copyright (c) 2020 c4games.com
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "platform/CCPlatformConfig.h"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
|
||||||
#include <io.h>
|
|
||||||
#include <direct.h>
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
|
#include "platform/CCPlatformConfig.h"
|
||||||
#include "platform/CCPlatformMacros.h"
|
#include "platform/CCPlatformMacros.h"
|
||||||
|
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
|
||||||
#include "platform/android/CCFileUtils-android.h"
|
|
||||||
#include <jni.h>
|
|
||||||
#include <android/asset_manager.h>
|
|
||||||
#include <android/asset_manager_jni.h>
|
|
||||||
#include "base/ZipUtils.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#define O_READ_FLAGS O_BINARY | O_RDONLY, S_IREAD
|
|
||||||
#define O_WRITE_FLAGS O_CREAT | O_RDWR | O_BINARY | O_TRUNC, S_IWRITE | S_IREAD
|
|
||||||
#define O_APPEND_FLAGS O_APPEND | O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD
|
|
||||||
|
|
||||||
#define O_OVERLAP_FLAGS O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD
|
|
||||||
|
|
||||||
#define posix_open ::_open
|
|
||||||
#define posix_close ::_close
|
|
||||||
#define posix_lseek ::_lseek
|
|
||||||
#define posix_read ::_read
|
|
||||||
#define posix_write ::_write
|
|
||||||
#define posix_fd2fh(fd) reinterpret_cast<HANDLE>(_get_osfhandle(fd))
|
|
||||||
#define posix_fsetsize(fd, size) ::_chsize(fd, size)
|
|
||||||
#else
|
|
||||||
#define O_READ_FLAGS O_RDONLY, S_IRUSR
|
|
||||||
#define O_WRITE_FLAGS O_CREAT | O_RDWR | O_TRUNC, S_IRWXU
|
|
||||||
#define O_APPEND_FLAGS O_APPEND | O_CREAT | O_RDWR, S_IRWXU
|
|
||||||
|
|
||||||
#define O_OVERLAP_FLAGS O_CREAT | O_RDWR, S_IRWXU
|
|
||||||
|
|
||||||
#define posix_open ::open
|
|
||||||
#define posix_close ::close
|
|
||||||
#define posix_lseek ::lseek
|
|
||||||
#define posix_read ::read
|
|
||||||
#define posix_write ::write
|
|
||||||
#define posix_fd2fh(fd) (fd)
|
|
||||||
#define posix_fsetsize(fd, size) ::ftruncate(fd, size); ::lseek(fd, 0, SEEK_SET)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
struct UnzFileStream;
|
|
||||||
union PXFileHandle {
|
|
||||||
int _fd = -1;
|
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
|
||||||
AAsset* _asset;
|
|
||||||
ZipFileStream _zfs;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PXIoF;
|
|
||||||
|
|
||||||
class CC_DLL FileStream {
|
class CC_DLL FileStream {
|
||||||
public:
|
public:
|
||||||
FileStream();
|
virtual ~FileStream() = default;
|
||||||
~FileStream();
|
|
||||||
|
|
||||||
FileStream(FileStream&& rhs);
|
|
||||||
FileStream& operator=(FileStream&& rhs);
|
|
||||||
|
|
||||||
enum class Mode {
|
enum class Mode {
|
||||||
READ,
|
READ,
|
||||||
|
@ -81,22 +19,20 @@ public:
|
||||||
APPEND,
|
APPEND,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool open(const std::string& path, Mode mode);
|
virtual bool open(const std::string& path, FileStream::Mode mode) = 0;
|
||||||
int close();
|
virtual int close() = 0;
|
||||||
|
|
||||||
int seek(long offset, int origin);
|
virtual int seek(long offset, int origin) = 0;
|
||||||
int read(void* buf, unsigned int size);
|
virtual int read(void* buf, unsigned int size) = 0;
|
||||||
|
|
||||||
int write(const void* buf, unsigned int size);
|
virtual int write(const void* buf, unsigned int size) = 0;
|
||||||
|
virtual int tell() = 0;
|
||||||
|
virtual bool isOpen() const = 0;
|
||||||
|
|
||||||
operator bool() const;
|
virtual operator bool() const { return isOpen(); }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void zeroset();
|
FileStream() = default;
|
||||||
void assign(FileStream&& rhs);
|
|
||||||
|
|
||||||
PXFileHandle _handle;
|
|
||||||
const PXIoF* _iof;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_CC_END
|
NS_CC_END
|
|
@ -27,12 +27,14 @@ THE SOFTWARE.
|
||||||
#include "platform/CCFileUtils.h"
|
#include "platform/CCFileUtils.h"
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "base/CCData.h"
|
#include "base/CCData.h"
|
||||||
#include "base/ccMacros.h"
|
#include "base/ccMacros.h"
|
||||||
#include "base/CCDirector.h"
|
#include "base/CCDirector.h"
|
||||||
#include "platform/CCSAXParser.h"
|
#include "platform/CCSAXParser.h"
|
||||||
//#include "base/ccUtils.h"
|
//#include "base/ccUtils.h"
|
||||||
|
#include "platform/CCPosixFileStream.h"
|
||||||
|
|
||||||
#ifdef MINIZIP_FROM_SYSTEM
|
#ifdef MINIZIP_FROM_SYSTEM
|
||||||
#include <minizip/unzip.h>
|
#include <minizip/unzip.h>
|
||||||
|
@ -370,8 +372,9 @@ bool FileUtils::writeValueMapToFile(const ValueMap& dict, const std::string& ful
|
||||||
auto rootEle = doc.document_element();
|
auto rootEle = doc.document_element();
|
||||||
|
|
||||||
generateElementForDict(dict, rootEle);
|
generateElementForDict(dict, rootEle);
|
||||||
|
std::stringstream ss;
|
||||||
return doc.save_file(fullPath.c_str());
|
doc.save(ss, " ");
|
||||||
|
return writeStringToFile(ss.str(), fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileUtils::writeValueVectorToFile(const ValueVector& vecData, const std::string& fullPath) const
|
bool FileUtils::writeValueVectorToFile(const ValueVector& vecData, const std::string& fullPath) const
|
||||||
|
@ -383,8 +386,9 @@ bool FileUtils::writeValueVectorToFile(const ValueVector& vecData, const std::st
|
||||||
|
|
||||||
auto rootEle = doc.document_element();
|
auto rootEle = doc.document_element();
|
||||||
generateElementForArray(vecData, rootEle);
|
generateElementForArray(vecData, rootEle);
|
||||||
|
std::stringstream ss;
|
||||||
return doc.save_file(fullPath.c_str());
|
doc.save(ss, " ");
|
||||||
|
return writeStringToFile(ss.str(), fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generateElementForObject(const Value& value, pugi::xml_node& parent)
|
static void generateElementForObject(const Value& value, pugi::xml_node& parent)
|
||||||
|
@ -1101,6 +1105,18 @@ void FileUtils::listFilesRecursivelyAsync(const std::string& dirPath, std::funct
|
||||||
}, std::move(callback));
|
}, std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileStream* FileUtils::openFileStream(const std::string& filePath, FileStream::Mode mode)
|
||||||
|
{
|
||||||
|
PosixFileStream fs;
|
||||||
|
|
||||||
|
if (fs.open(filePath, mode))
|
||||||
|
{
|
||||||
|
return new PosixFileStream(std::move(fs)); // PosixFileStream is the default implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||||
// windows os implement should override in platform specific FileUtiles class
|
// windows os implement should override in platform specific FileUtiles class
|
||||||
bool FileUtils::isDirectoryExistInternal(const std::string& dirPath) const
|
bool FileUtils::isDirectoryExistInternal(const std::string& dirPath) const
|
||||||
|
|
|
@ -32,6 +32,7 @@ THE SOFTWARE.
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "platform/CCFileStream.h"
|
||||||
#include "platform/CCPlatformMacros.h"
|
#include "platform/CCPlatformMacros.h"
|
||||||
#include "base/ccTypes.h"
|
#include "base/ccTypes.h"
|
||||||
#include "base/CCValue.h"
|
#include "base/CCValue.h"
|
||||||
|
@ -449,11 +450,19 @@ public:
|
||||||
virtual const std::vector<std::string> getOriginalSearchPaths() const;
|
virtual const std::vector<std::string> getOriginalSearchPaths() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the writable path.
|
* Gets the writable path that may not be in the format of an absolute path
|
||||||
* @return The path that can be write/read a file in
|
* @return The path that can be write/read a file in
|
||||||
|
* @note This may return the same value as getNativeWritableAbsolutePath(). If you require the absolute path
|
||||||
|
* to the underlying file system, then call getNativeWritableAbsolutePath() instead.
|
||||||
*/
|
*/
|
||||||
virtual std::string getWritablePath() const = 0;
|
virtual std::string getWritablePath() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the writable path in the native file-system format
|
||||||
|
* @return The path that can be write/read a file in
|
||||||
|
*/
|
||||||
|
virtual std::string getNativeWritableAbsolutePath() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets writable path.
|
* Sets writable path.
|
||||||
*/
|
*/
|
||||||
|
@ -839,6 +848,14 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool isDirectoryExistInternal(const std::string& dirPath) const;
|
virtual bool isDirectoryExistInternal(const std::string& dirPath) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a FileStream based on the implementation provided in openFileStream or its overrides
|
||||||
|
* @param filePath The path to the file
|
||||||
|
* @param mode The mode to open the file in, being READ | WRITE | APPEND
|
||||||
|
* @return Returns a pointer to the file stream
|
||||||
|
*/
|
||||||
|
virtual FileStream* openFileStream(const std::string& filePath, FileStream::Mode mode);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* The default constructor.
|
* The default constructor.
|
||||||
|
|
|
@ -471,6 +471,19 @@ namespace
|
||||||
}tImageSource;
|
}tImageSource;
|
||||||
|
|
||||||
#if CC_USE_PNG
|
#if CC_USE_PNG
|
||||||
|
void pngWriteCallback(png_structp png_ptr, png_bytep data, size_t length)
|
||||||
|
{
|
||||||
|
if (png_ptr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FileStream* fileStream = (FileStream*)png_get_io_ptr(png_ptr);
|
||||||
|
|
||||||
|
const auto check = fileStream->write(data, length);
|
||||||
|
|
||||||
|
if (check != length)
|
||||||
|
png_error(png_ptr, "Write Error");
|
||||||
|
}
|
||||||
|
|
||||||
static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
|
static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
{
|
{
|
||||||
tImageSource* isource = (tImageSource*)png_get_io_ptr(png_ptr);
|
tImageSource* isource = (tImageSource*)png_get_io_ptr(png_ptr);
|
||||||
|
@ -2161,36 +2174,38 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
FILE *fp;
|
|
||||||
png_structp png_ptr;
|
png_structp png_ptr;
|
||||||
png_infop info_ptr;
|
png_infop info_ptr;
|
||||||
png_bytep *row_pointers;
|
png_bytep *row_pointers;
|
||||||
|
|
||||||
|
auto* outStream = FileUtils::getInstance()->openFileStream(filePath, FileStream::Mode::WRITE);
|
||||||
|
|
||||||
fp = fopen(filePath.c_str(), "wb");
|
CC_BREAK_IF(nullptr == outStream);
|
||||||
CC_BREAK_IF(nullptr == fp);
|
|
||||||
|
|
||||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
if (nullptr == png_ptr)
|
if (nullptr == png_ptr)
|
||||||
{
|
{
|
||||||
fclose(fp);
|
delete outStream;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
if (nullptr == info_ptr)
|
if (nullptr == info_ptr)
|
||||||
{
|
{
|
||||||
fclose(fp);
|
delete outStream;
|
||||||
png_destroy_write_struct(&png_ptr, nullptr);
|
png_destroy_write_struct(&png_ptr, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (setjmp(png_jmpbuf(png_ptr)))
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
{
|
{
|
||||||
fclose(fp);
|
delete outStream;
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
png_init_io(png_ptr, fp);
|
|
||||||
|
//png_init_io(png_ptr, outStream);
|
||||||
|
png_set_write_fn(png_ptr, outStream, pngWriteCallback, nullptr);
|
||||||
|
|
||||||
if (!isToRGB && hasAlpha())
|
if (!isToRGB && hasAlpha())
|
||||||
{
|
{
|
||||||
|
@ -2210,7 +2225,7 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
|
||||||
row_pointers = (png_bytep *)malloc(_height * sizeof(png_bytep));
|
row_pointers = (png_bytep *)malloc(_height * sizeof(png_bytep));
|
||||||
if(row_pointers == nullptr)
|
if(row_pointers == nullptr)
|
||||||
{
|
{
|
||||||
fclose(fp);
|
delete outStream;
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2234,7 +2249,7 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
|
||||||
uint8_t *tempData = static_cast<uint8_t*>(malloc(_width * _height * 3));
|
uint8_t *tempData = static_cast<uint8_t*>(malloc(_width * _height * 3));
|
||||||
if (nullptr == tempData)
|
if (nullptr == tempData)
|
||||||
{
|
{
|
||||||
fclose(fp);
|
delete outStream;
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
|
||||||
free(row_pointers);
|
free(row_pointers);
|
||||||
|
@ -2285,7 +2300,7 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
|
||||||
|
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
|
||||||
fclose(fp);
|
delete outStream;
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
@ -2304,7 +2319,7 @@ bool Image::saveImageToJPG(const std::string& filePath)
|
||||||
{
|
{
|
||||||
struct jpeg_compress_struct cinfo;
|
struct jpeg_compress_struct cinfo;
|
||||||
struct jpeg_error_mgr jerr;
|
struct jpeg_error_mgr jerr;
|
||||||
FILE * outfile; /* target file */
|
FileStream * outfile; /* target file */
|
||||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||||
int row_stride; /* physical row width in image buffer */
|
int row_stride; /* physical row width in image buffer */
|
||||||
|
|
||||||
|
@ -2312,9 +2327,12 @@ bool Image::saveImageToJPG(const std::string& filePath)
|
||||||
/* Now we can initialize the JPEG compression object. */
|
/* Now we can initialize the JPEG compression object. */
|
||||||
jpeg_create_compress(&cinfo);
|
jpeg_create_compress(&cinfo);
|
||||||
|
|
||||||
CC_BREAK_IF((outfile = fopen(filePath.c_str(), "wb")) == nullptr);
|
outfile = FileUtils::getInstance()->openFileStream(filePath, FileStream::Mode::WRITE);
|
||||||
|
CC_BREAK_IF(nullptr == outfile);
|
||||||
jpeg_stdio_dest(&cinfo, outfile);
|
|
||||||
|
unsigned char* outputBuffer = nullptr;
|
||||||
|
unsigned long outputSize = 0;
|
||||||
|
jpeg_mem_dest(&cinfo, &outputBuffer, &outputSize);
|
||||||
|
|
||||||
cinfo.image_width = _width; /* image width and height, in pixels */
|
cinfo.image_width = _width; /* image width and height, in pixels */
|
||||||
cinfo.image_height = _height;
|
cinfo.image_height = _height;
|
||||||
|
@ -2335,7 +2353,14 @@ bool Image::saveImageToJPG(const std::string& filePath)
|
||||||
{
|
{
|
||||||
jpeg_finish_compress(&cinfo);
|
jpeg_finish_compress(&cinfo);
|
||||||
jpeg_destroy_compress(&cinfo);
|
jpeg_destroy_compress(&cinfo);
|
||||||
fclose(outfile);
|
|
||||||
|
delete outfile;
|
||||||
|
outfile = nullptr;
|
||||||
|
if (outputBuffer)
|
||||||
|
{
|
||||||
|
free(outputBuffer);
|
||||||
|
outputBuffer = nullptr;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2370,7 +2395,16 @@ bool Image::saveImageToJPG(const std::string& filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_finish_compress(&cinfo);
|
jpeg_finish_compress(&cinfo);
|
||||||
fclose(outfile);
|
|
||||||
|
outfile->write(outputBuffer, outputSize);
|
||||||
|
delete outfile; // closes FileStream automatically
|
||||||
|
outfile = nullptr;
|
||||||
|
if (outputBuffer)
|
||||||
|
{
|
||||||
|
free(outputBuffer);
|
||||||
|
outputBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
jpeg_destroy_compress(&cinfo);
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
// Copyright (c) 2018-2019 HALX99.
|
||||||
|
// Copyright (c) 2020 c4games.com
|
||||||
|
#include "platform/CCPosixFileStream.h"
|
||||||
|
|
||||||
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||||
|
#include "base/ZipUtils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
struct PXIoF {
|
||||||
|
int(*read)(PXFileHandle& handle, void*, unsigned int);
|
||||||
|
long(*seek)(PXFileHandle& handle, long, int);
|
||||||
|
int(*close)(PXFileHandle& handle);
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pfs_posix_open(const std::string& path, FileStream::Mode mode, PXFileHandle& handle)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case FileStream::Mode::READ:
|
||||||
|
handle._fd = posix_open(path.c_str(), O_READ_FLAGS);
|
||||||
|
break;
|
||||||
|
case FileStream::Mode::WRITE:
|
||||||
|
handle._fd = posix_open(path.c_str(), O_WRITE_FLAGS);
|
||||||
|
break;
|
||||||
|
case FileStream::Mode::APPEND:
|
||||||
|
handle._fd = posix_open(path.c_str(), O_APPEND_FLAGS);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handle._fd = -1;
|
||||||
|
}
|
||||||
|
return handle._fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// posix standard wrappers
|
||||||
|
static int pfs_posix_read(PXFileHandle& handle, void* buf, unsigned int size) { return static_cast<int>(posix_read(handle._fd, buf, size)); }
|
||||||
|
static long pfs_posix_seek(PXFileHandle& handle, long offst, int origin) { return posix_lseek(handle._fd, offst, origin); }
|
||||||
|
static int pfs_posix_close(PXFileHandle& handle) {
|
||||||
|
int fd = handle._fd;
|
||||||
|
if (fd != -1) {
|
||||||
|
handle._fd = -1;
|
||||||
|
return posix_close(fd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static PXIoF pfs_posix_iof = {
|
||||||
|
pfs_posix_read,
|
||||||
|
pfs_posix_seek,
|
||||||
|
pfs_posix_close
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||||
|
// android AssetManager wrappers
|
||||||
|
static int pfs_asset_read(PXFileHandle& handle, void* buf, unsigned int size) { return AAsset_read(handle._asset, buf, size); }
|
||||||
|
static long pfs_asset_seek(PXFileHandle& handle, long offst, int origin) { return AAsset_seek(handle._asset, offst, origin); }
|
||||||
|
static int pfs_asset_close(PXFileHandle& handle) {
|
||||||
|
if (handle._asset != nullptr) {
|
||||||
|
AAsset_close(handle._asset);
|
||||||
|
handle._asset = nullptr;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static PXIoF pfs_asset_iof = {
|
||||||
|
pfs_asset_read,
|
||||||
|
pfs_asset_seek,
|
||||||
|
pfs_asset_close
|
||||||
|
};
|
||||||
|
|
||||||
|
// android obb
|
||||||
|
static int pfs_obb_read(PXFileHandle& handle, void* buf, unsigned int size) { return FileUtilsAndroid::getObbFile()->zfread(&handle._zfs, buf, size); }
|
||||||
|
static long pfs_obb_seek(PXFileHandle& handle, long offset, int origin) { return FileUtilsAndroid::getObbFile()->zfseek(&handle._zfs, offset, origin); }
|
||||||
|
static int pfs_obb_close(PXFileHandle& handle) {
|
||||||
|
FileUtilsAndroid::getObbFile()->zfclose(&handle._zfs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static PXIoF pfs_obb_iof = {
|
||||||
|
pfs_obb_read,
|
||||||
|
pfs_obb_seek,
|
||||||
|
pfs_obb_close
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PosixFileStream::~PosixFileStream()
|
||||||
|
{
|
||||||
|
internalClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixFileStream::open(const std::string& path, FileStream::Mode mode)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
#if CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
|
||||||
|
ok = pfs_posix_open(path, mode, _handle) != -1;
|
||||||
|
#else // Android
|
||||||
|
if (path[0] != '/') { // from package, always readonly
|
||||||
|
std::string relativePath;
|
||||||
|
size_t position = path.find("assets/");
|
||||||
|
if (0 == position)
|
||||||
|
{
|
||||||
|
// "assets/" is at the beginning of the path and we don't want it
|
||||||
|
relativePath = path.substr(sizeof("assets/") - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
relativePath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto obb = FileUtilsAndroid::getObbFile();
|
||||||
|
ok = obb != nullptr && obb->zfopen(relativePath, &_handle._zfs);
|
||||||
|
if (ok) {
|
||||||
|
this->_iof = &pfs_obb_iof;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AAssetManager* asMgr = FileUtilsAndroid::getAssetManager();
|
||||||
|
AAsset* asset = AAssetManager_open(asMgr, relativePath.c_str(), AASSET_MODE_UNKNOWN);
|
||||||
|
ok = !!asset;
|
||||||
|
if (ok) {
|
||||||
|
_handle._asset = asset;
|
||||||
|
// setup file read/seek/close at here
|
||||||
|
this->_iof = &pfs_asset_iof;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // otherwise, as a absolutely path
|
||||||
|
ok = pfs_posix_open(path, mode, _handle) != -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ok && !_iof)
|
||||||
|
_iof = &pfs_posix_iof;
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PosixFileStream::internalClose()
|
||||||
|
{
|
||||||
|
if (_iof) {
|
||||||
|
int ret = _iof->close(_handle);
|
||||||
|
reset();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PosixFileStream::close()
|
||||||
|
{
|
||||||
|
return internalClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PosixFileStream::seek(long offset, int origin)
|
||||||
|
{
|
||||||
|
return static_cast<int>(_iof->seek(_handle, offset, origin));
|
||||||
|
}
|
||||||
|
|
||||||
|
int PosixFileStream::read(void* buf, unsigned int size)
|
||||||
|
{
|
||||||
|
return _iof->read(_handle, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PosixFileStream::write(const void* buf, unsigned int size)
|
||||||
|
{
|
||||||
|
return static_cast<int>(posix_write(_handle._fd, buf, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
int PosixFileStream::tell()
|
||||||
|
{
|
||||||
|
return static_cast<int>(_iof->seek(_handle, 0, SEEK_CUR));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixFileStream::isOpen() const
|
||||||
|
{
|
||||||
|
#if CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
|
||||||
|
return _handle._fd != -1;
|
||||||
|
#else
|
||||||
|
return _handle._fd != -1 && _handle._asset != nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixFileStream::reset()
|
||||||
|
{
|
||||||
|
memset(&_handle, 0, sizeof(_handle));
|
||||||
|
_handle._fd = -1;
|
||||||
|
_iof = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_CC_END
|
|
@ -0,0 +1,125 @@
|
||||||
|
// Copyright (c) 2018-2019 HALX99
|
||||||
|
// Copyright (c) 2020 c4games.com
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "platform/CCFileStream.h"
|
||||||
|
#include "platform/CCPlatformConfig.h"
|
||||||
|
#include <string>
|
||||||
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "platform/CCPlatformMacros.h"
|
||||||
|
|
||||||
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||||
|
#include "platform/android/CCFileUtils-android.h"
|
||||||
|
#include <jni.h>
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#include <android/asset_manager_jni.h>
|
||||||
|
#include "base/ZipUtils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define O_READ_FLAGS O_BINARY | O_RDONLY, S_IREAD
|
||||||
|
#define O_WRITE_FLAGS O_CREAT | O_RDWR | O_BINARY | O_TRUNC, S_IWRITE | S_IREAD
|
||||||
|
#define O_APPEND_FLAGS O_APPEND | O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD
|
||||||
|
|
||||||
|
#define O_OVERLAP_FLAGS O_CREAT | O_RDWR | O_BINARY, S_IWRITE | S_IREAD
|
||||||
|
|
||||||
|
#define posix_open ::_open
|
||||||
|
#define posix_close ::_close
|
||||||
|
#define posix_lseek ::_lseek
|
||||||
|
#define posix_read ::_read
|
||||||
|
#define posix_write ::_write
|
||||||
|
#define posix_fd2fh(fd) reinterpret_cast<HANDLE>(_get_osfhandle(fd))
|
||||||
|
#define posix_fsetsize(fd, size) ::_chsize(fd, size)
|
||||||
|
#else
|
||||||
|
#define O_READ_FLAGS O_RDONLY, S_IRUSR
|
||||||
|
#define O_WRITE_FLAGS O_CREAT | O_RDWR | O_TRUNC, S_IRWXU
|
||||||
|
#define O_APPEND_FLAGS O_APPEND | O_CREAT | O_RDWR, S_IRWXU
|
||||||
|
|
||||||
|
#define O_OVERLAP_FLAGS O_CREAT | O_RDWR, S_IRWXU
|
||||||
|
|
||||||
|
#define posix_open ::open
|
||||||
|
#define posix_close ::close
|
||||||
|
#define posix_lseek ::lseek
|
||||||
|
#define posix_read ::read
|
||||||
|
#define posix_write ::write
|
||||||
|
#define posix_fd2fh(fd) (fd)
|
||||||
|
#define posix_fsetsize(fd, size) ::ftruncate(fd, size); ::lseek(fd, 0, SEEK_SET)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
struct UnzFileStream;
|
||||||
|
union PXFileHandle {
|
||||||
|
int _fd = -1;
|
||||||
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
|
||||||
|
AAsset* _asset;
|
||||||
|
ZipFileStream _zfs;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PXIoF;
|
||||||
|
|
||||||
|
class CC_DLL PosixFileStream : public FileStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PosixFileStream() = default;
|
||||||
|
virtual ~PosixFileStream();
|
||||||
|
|
||||||
|
PosixFileStream(const PosixFileStream& other) = delete;
|
||||||
|
|
||||||
|
PosixFileStream(PosixFileStream&& other) noexcept
|
||||||
|
: FileStream(std::move(other)),
|
||||||
|
_handle(std::move(other._handle)),
|
||||||
|
_iof(other._iof)
|
||||||
|
{
|
||||||
|
other.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixFileStream& operator=(const PosixFileStream& other) = delete;
|
||||||
|
|
||||||
|
PosixFileStream& operator=(PosixFileStream&& other) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
FileStream::operator =(std::move(other));
|
||||||
|
_handle = std::move(other._handle);
|
||||||
|
_iof = other._iof;
|
||||||
|
|
||||||
|
other.reset();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
READ,
|
||||||
|
WRITE,
|
||||||
|
APPEND,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool open(const std::string& path, FileStream::Mode mode) override;
|
||||||
|
int close() override;
|
||||||
|
|
||||||
|
int seek(long offset, int origin) override;
|
||||||
|
int read(void* buf, unsigned int size) override;
|
||||||
|
int write(const void* buf, unsigned int size) override;
|
||||||
|
int tell() override;
|
||||||
|
bool isOpen() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int internalClose();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
PXFileHandle _handle;
|
||||||
|
const PXIoF* _iof;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_CC_END
|
|
@ -160,6 +160,7 @@ set(COCOS_PLATFORM_HEADER
|
||||||
platform/CCSAXParser.h
|
platform/CCSAXParser.h
|
||||||
platform/CCStdC.h
|
platform/CCStdC.h
|
||||||
platform/CCFileStream.h
|
platform/CCFileStream.h
|
||||||
|
platform/CCPosixFileStream.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(COCOS_PLATFORM_SRC
|
set(COCOS_PLATFORM_SRC
|
||||||
|
@ -169,4 +170,5 @@ set(COCOS_PLATFORM_SRC
|
||||||
platform/CCFileUtils.cpp
|
platform/CCFileUtils.cpp
|
||||||
platform/CCImage.cpp
|
platform/CCImage.cpp
|
||||||
platform/CCFileStream.cpp
|
platform/CCFileStream.cpp
|
||||||
|
platform/CCPosixFileStream.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -388,13 +388,18 @@ FileUtils::Status FileUtilsAndroid::getContents(const std::string& filename, Res
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FileUtilsAndroid::getWritablePath() const
|
std::string FileUtilsAndroid::getWritablePath() const
|
||||||
|
{
|
||||||
|
return getNativeWritableAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FileUtilsAndroid::getNativeWritableAbsolutePath() const
|
||||||
{
|
{
|
||||||
// Fix for Nexus 10 (Android 4.2 multi-user environment)
|
// Fix for Nexus 10 (Android 4.2 multi-user environment)
|
||||||
// the path is retrieved through Java Context.getCacheDir() method
|
// the path is retrieved through Java Context.getCacheDir() method
|
||||||
std::string path = JniHelper::callStaticStringMethod("org.cocos2dx.lib.Cocos2dxHelper", "getCocos2dxWritablePath");
|
std::string path = JniHelper::callStaticStringMethod("org.cocos2dx.lib.Cocos2dxHelper", "getCocos2dxWritablePath");
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
path.append("/");
|
path.append("/");
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
virtual FileUtils::Status getContents(const std::string& filename, ResizableBuffer* buffer) const override;
|
virtual FileUtils::Status getContents(const std::string& filename, ResizableBuffer* buffer) const override;
|
||||||
|
|
||||||
virtual std::string getWritablePath() const override;
|
virtual std::string getWritablePath() const override;
|
||||||
|
std::string getNativeWritableAbsolutePath() const override;
|
||||||
virtual bool isAbsolutePath(const std::string& strPath) const override;
|
virtual bool isAbsolutePath(const std::string& strPath) const override;
|
||||||
|
|
||||||
virtual int64_t getFileSize(const std::string& filepath) const override;
|
virtual int64_t getFileSize(const std::string& filepath) const override;
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
virtual ~FileUtilsApple();
|
virtual ~FileUtilsApple();
|
||||||
/* override functions */
|
/* override functions */
|
||||||
virtual std::string getWritablePath() const override;
|
virtual std::string getWritablePath() const override;
|
||||||
|
virtual std::string getNativeWritableAbsolutePath() const override;
|
||||||
virtual std::string getFullPathForFilenameWithinDirectory(const std::string& directory, const std::string& filename) const override;
|
virtual std::string getFullPathForFilenameWithinDirectory(const std::string& directory, const std::string& filename) const override;
|
||||||
|
|
||||||
#if CC_FILEUTILS_APPLE_ENABLE_OBJC
|
#if CC_FILEUTILS_APPLE_ENABLE_OBJC
|
||||||
|
|
|
@ -84,6 +84,12 @@ FileUtils* FileUtils::getInstance()
|
||||||
|
|
||||||
|
|
||||||
std::string FileUtilsApple::getWritablePath() const
|
std::string FileUtilsApple::getWritablePath() const
|
||||||
|
{
|
||||||
|
DECLARE_GUARD;
|
||||||
|
return getNativeWritableAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FileUtilsApple::getNativeWritableAbsolutePath() const
|
||||||
{
|
{
|
||||||
DECLARE_GUARD;
|
DECLARE_GUARD;
|
||||||
if (_writablePath.length())
|
if (_writablePath.length())
|
||||||
|
|
|
@ -94,6 +94,12 @@ bool FileUtilsLinux::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
string FileUtilsLinux::getWritablePath() const
|
string FileUtilsLinux::getWritablePath() const
|
||||||
|
{
|
||||||
|
DECLARE_GUARD;
|
||||||
|
return getNativeWritableAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FileUtilsLinux::getNativeWritableAbsolutePath() const
|
||||||
{
|
{
|
||||||
DECLARE_GUARD;
|
DECLARE_GUARD;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
|
@ -50,6 +50,8 @@ public:
|
||||||
/* override functions */
|
/* override functions */
|
||||||
bool init() override;
|
bool init() override;
|
||||||
virtual std::string getWritablePath() const override;
|
virtual std::string getWritablePath() const override;
|
||||||
|
std::string getNativeWritableAbsolutePath() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool isFileExistInternal(const std::string& strFilePath) const override;
|
virtual bool isFileExistInternal(const std::string& strFilePath) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -299,6 +299,12 @@ std::vector<std::string> FileUtilsWin32::listFiles(const std::string& dirPath) c
|
||||||
}
|
}
|
||||||
|
|
||||||
string FileUtilsWin32::getWritablePath() const
|
string FileUtilsWin32::getWritablePath() const
|
||||||
|
{
|
||||||
|
DECLARE_GUARD;
|
||||||
|
return getNativeWritableAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FileUtilsWin32::getNativeWritableAbsolutePath() const
|
||||||
{
|
{
|
||||||
DECLARE_GUARD;
|
DECLARE_GUARD;
|
||||||
if (_writablePath.length())
|
if (_writablePath.length())
|
||||||
|
@ -313,9 +319,9 @@ string FileUtilsWin32::getWritablePath() const
|
||||||
// Debug app uses executable directory; Non-debug app uses local app data directory
|
// Debug app uses executable directory; Non-debug app uses local app data directory
|
||||||
//#ifndef _DEBUG
|
//#ifndef _DEBUG
|
||||||
// Get filename of executable only, e.g. MyGame.exe
|
// Get filename of executable only, e.g. MyGame.exe
|
||||||
WCHAR *base_name = wcsrchr(full_path, '\\');
|
WCHAR* base_name = wcsrchr(full_path, '\\');
|
||||||
wstring retPath;
|
wstring retPath;
|
||||||
if(base_name)
|
if (base_name)
|
||||||
{
|
{
|
||||||
WCHAR app_data_path[CC_MAX_PATH + 1];
|
WCHAR app_data_path[CC_MAX_PATH + 1];
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,9 @@ protected:
|
||||||
FileUtilsWin32();
|
FileUtilsWin32();
|
||||||
public:
|
public:
|
||||||
/* override functions */
|
/* override functions */
|
||||||
bool init();
|
bool init() override;
|
||||||
virtual std::string getWritablePath() const override;
|
virtual std::string getWritablePath() const override;
|
||||||
|
virtual std::string getNativeWritableAbsolutePath() const override;
|
||||||
virtual bool isAbsolutePath(const std::string& strPath) const override;
|
virtual bool isAbsolutePath(const std::string& strPath) const override;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue