Skip to content

Commit

Permalink
Add Linux Port
Browse files Browse the repository at this point in the history
  • Loading branch information
BusyStudent committed Sep 22, 2021
1 parent cf31843 commit 3cbd4ab
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 1 deletion.
21 changes: 21 additions & 0 deletions build/Linux/SConstruct
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import os
#Import posix asio
env = Environment(LIBS=['rt'],CC='g++',CXXFLAGS = ["-g"])

source = []
for i in os.listdir("../../src/Psd/"):
#Remove win32 source
if i.endswith(".cpp") and i != "PsdNativeFile.cpp":
source.append("../../src/Psd/" + i)
print(source)

source.append("../../src/Psd/Psdminiz.c")

test_source = [
"../../src/Samples/PsdSamples.cpp",
"../../src/Samples/PsdTgaExporter.cpp",
"./libpsd.a"
]

env.StaticLibrary("psd",source)
env.Program("samples",test_source,CXXFLAGS = ["-std=c++11"])
158 changes: 158 additions & 0 deletions src/Psd/PsdNativeFile_Linux.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@

#include "PsdPch.h"

#include "PsdLog.h"
#include "PsdFile.h"
#include "PsdAllocator.h"
#include "PsdNamespace.h"
#include "PsdMemoryUtil.h"
#include "PsdNativeFile_Linux.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <aio.h>

#include <cstring>
#include <cstdlib>
#include <cwchar>
#include <string>



PSD_NAMESPACE_BEGIN
/**
* @brief Convert wchar_t * to char *
*
* @param ws
* @return char *
*/
static char *convert_ws(const wchar_t *ws){
char *buffer;
size_t n = std::wcslen(ws) * 4 + 1;
buffer = static_cast<char*>(std::malloc(n));
std::memset(buffer,0,n);
if(buffer == nullptr){
return nullptr;
}
std::wcstombs(buffer,ws,n);
return buffer;
}

NativeFile::NativeFile(Allocator *alloc):
File(alloc),
fd(-1){}

//Convert wchar to char and open

bool NativeFile::DoOpenRead(const wchar_t* filename){
char *name = convert_ws(filename);
fd = open(name,O_RDONLY);
if(fd == -1){
PSD_ERROR("NativeFile","open(%s) => %s",name,strerror(errno));
std::free(name);
return false;
}
std::free(name);
return true;
}
bool NativeFile::DoOpenWrite(const wchar_t* filename){
char *name = convert_ws(filename);
//Create a new file
fd = open(name,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR);
if(fd == -1){
PSD_ERROR("NativeFile","open(%s) => %s",name,strerror(errno));
std::free(name);
return false;
}
std::free(name);
return true;
}
bool NativeFile::DoClose(){
int ret = close(fd);
fd = -1;
return ret == 0;
}

//Wrtie / Read

File::ReadOperation NativeFile::DoRead(void* buffer, uint32_t count, uint64_t position){
aiocb *operation = memoryUtil::Allocate<aiocb>(m_allocator);
std::memset(operation,0,sizeof(aiocb));

operation->aio_buf = buffer;
operation->aio_fildes = fd;
operation->aio_lio_opcode = LIO_READ;//Do read
operation->aio_nbytes = count;
operation->aio_offset = position;
operation->aio_reqprio = 0;
operation->aio_sigevent.sigev_notify = SIGEV_NONE;//No signal will be send

//OK Execute it
if(aio_read(operation) == -1){
//Has Error
PSD_ERROR("NativeFile","On DoRead aio_read() => %s",strerror(errno));
memoryUtil::Free(m_allocator,operation);
return nullptr;
}
return operation;
}
File::ReadOperation NativeFile::DoWrite(const void* buffer, uint32_t count, uint64_t position){
aiocb *operation = memoryUtil::Allocate<aiocb>(m_allocator);
std::memset(operation,0,sizeof(aiocb));

operation->aio_buf = const_cast<void*>(buffer);
operation->aio_fildes = fd;
operation->aio_lio_opcode = LIO_WRITE;//Do Write
operation->aio_nbytes = count;
operation->aio_offset = position;
operation->aio_reqprio = 0;
operation->aio_sigevent.sigev_notify = SIGEV_NONE;//No signal will be send

//OK Execute it
if(aio_read(operation) == -1){
//Has Error
PSD_ERROR("NativeFile","On DoWrite aio_read() => %s",strerror(errno));
memoryUtil::Free(m_allocator,operation);
return nullptr;
}
return operation;
}

//Wait for R/W

static bool generic_wait(aiocb *operation,Allocator *alloc){
//Wait for it
if(aio_suspend(&operation,1,nullptr) == -1){
PSD_ERROR("NativeFile","aio_suspend() => %s",strerror(errno));
memoryUtil::Free(alloc,operation);
return false;
}
//Get status
ssize_t ret = aio_return(operation);
memoryUtil::Free(alloc,operation);
return ret != -1;
}

bool NativeFile::DoWaitForRead(ReadOperation &_operation){
aiocb *operation = static_cast<aiocb*>(_operation);
return generic_wait(operation,m_allocator);
}
bool NativeFile::DoWaitForWrite(ReadOperation &_operation){
aiocb *operation = static_cast<aiocb*>(_operation);
return generic_wait(operation,m_allocator);
}


uint64_t NativeFile::DoGetSize() const{
struct stat s;
if(fstat(fd,&s) == -1){
PSD_ERROR("NativeFile","lstat() => %s",strerror(errno));
//Emm,return 0 on error
return 0;
}
return s.st_size;
}

PSD_NAMESPACE_END
37 changes: 37 additions & 0 deletions src/Psd/PsdNativeFile_Linux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//Linux
#pragma once

#include "PsdPch.h"
#include "PsdAllocator.h"
#include "PsdFile.h"
#include "PsdNamespace.h"

PSD_NAMESPACE_BEGIN

/// \ingroup Files
/// \brief Simple file implementation that uses Posix asio internally.
/// \sa File
class NativeFile : public File
{
public:
/// Constructor.
explicit NativeFile(Allocator* allocator);
private:
virtual bool DoOpenRead(const wchar_t* filename) PSD_OVERRIDE;
virtual bool DoOpenWrite(const wchar_t* filename) PSD_OVERRIDE;
virtual bool DoClose(void) PSD_OVERRIDE;

virtual File::ReadOperation DoRead(void* buffer, uint32_t count, uint64_t position) PSD_OVERRIDE;
virtual bool DoWaitForRead(File::ReadOperation& operation) PSD_OVERRIDE;

virtual File::WriteOperation DoWrite(const void* buffer, uint32_t count, uint64_t position) PSD_OVERRIDE;
virtual bool DoWaitForWrite(File::WriteOperation& operation) PSD_OVERRIDE;

virtual uint64_t DoGetSize(void) const PSD_OVERRIDE;

int fd;
};


PSD_NAMESPACE_END

6 changes: 6 additions & 0 deletions src/Samples/PsdSamples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ PSD_POP_WARNING_LEVEL
PSD_USING_NAMESPACE;


#ifdef __linux
#define OutputDebugStringA(S) fputs(S,stderr)
#include <climits>
#include <cstring>
#endif

// helpers for reading PSDs
namespace
{
Expand Down
19 changes: 18 additions & 1 deletion src/Samples/PsdTgaExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ void OutputDebugStringA(const char *message)
}
#endif

#ifdef __linux
#include <cwchar>
#include <cstring>
#include <cstdlib>
#define OutputDebugStringA(S) fputs(S,stderr)
#endif

namespace
{
struct TgaType
Expand Down Expand Up @@ -80,12 +87,22 @@ namespace tgaExporter
#if PSD_USE_MSVC
const errno_t success = _wfopen_s(&file, filename, L"wb");
if (success != 0)
#else
#elif defined(__APPLE__)
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert;
std::string s = convert.to_bytes(filename);
char const *cs = s.c_str();
file = fopen(cs, "wb");
if (file == NULL)
#else
//In Linux
char *buffer;
size_t n = std::wcslen(filename) * 4 + 1;
buffer = static_cast<char*>(std::malloc(n));
std::memset(buffer,0,n);
std::wcstombs(buffer,filename,n);
file = fopen(buffer,"wb");
std::free(buffer);
if (file == NULL)
#endif
{
OutputDebugStringA("Cannot create file for writing.");
Expand Down

0 comments on commit 3cbd4ab

Please sign in to comment.