Skip to content

Commit

Permalink
Merge pull request #9 from BusyStudent/master
Browse files Browse the repository at this point in the history
Add Linux Port
  • Loading branch information
MolecularMatters committed Oct 18, 2021
2 parents 91643c3 + 9166202 commit 4768e60
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -427,3 +427,7 @@ fastlane/test_output
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/

# Scons
*.o
.sconsign.dblite
20 changes: 20 additions & 0 deletions build/Linux/SConstruct
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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)

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","-g"])
166 changes: 166 additions & 0 deletions src/Psd/PsdNativeFile_Linux.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@

#include "PsdPch.h"

#include "PsdLog.h"
#include "PsdFile.h"
#include "PsdAllocator.h"
#include "PsdNamespace.h"
#include "PsdMemoryUtil.h"
#include "PsdStringUtil.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>


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

if(ret == -1)
{
PSD_ERROR("NativeFile","aio_error() %d => %s",errcode,strerror(errcode));
}
_Psd::memoryUtil::Free(alloc,operation);
return ret != -1;
}
}


PSD_NAMESPACE_BEGIN

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

}

//Convert wchar to char and open
bool NativeFile::DoOpenRead(const wchar_t* filename)
{
char *name = stringUtil::ConvertWString(filename,m_allocator);
m_fd = open(name,O_RDONLY);
if(m_fd == -1)
{
PSD_ERROR("NativeFile","open(%s) => %s",name,strerror(errno));
m_allocator->Free(name);
return false;
}
m_allocator->Free(name);
return true;
}
bool NativeFile::DoOpenWrite(const wchar_t* filename){
char *name = stringUtil::ConvertWString(filename,m_allocator);
//Create a new file
m_fd = open(name,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR);
if(m_fd == -1)
{
PSD_ERROR("NativeFile","open(%s) => %s",name,strerror(errno));
m_allocator->Free(name);
return false;
}
m_allocator->Free(name);
return true;
}
bool NativeFile::DoClose()
{
int ret = close(m_fd);
m_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 = m_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(m_fd:%d) => %s",m_fd,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 = m_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_write(operation) == -1)
{
//Has Error
PSD_ERROR("NativeFile","On DoWrite aio_write(m_fd:%d) => %s",m_fd,strerror(errno));
memoryUtil::Free(m_allocator,operation);
return nullptr;
}
return operation;
}


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(m_fd,&s) == -1){
PSD_ERROR("NativeFile","fstat(%d) => %s",m_fd,strerror(errno));
//Emm,return 0 on error
return 0;
}
return s.st_size;
}

PSD_NAMESPACE_END
38 changes: 38 additions & 0 deletions src/Psd/PsdNativeFile_Linux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//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 m_fd;
};


PSD_NAMESPACE_END

33 changes: 33 additions & 0 deletions src/Psd/PsdStringUtil.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "PsdPch.h"

#include "PsdStringUtil.h"
#include "PsdMemoryUtil.h"

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

PSD_NAMESPACE_BEGIN

namespace stringUtil
{
char *ConvertWString(const wchar_t* ws, Allocator* alloc)
{
if(ws == nullptr)
{
return nullptr;
}
char *buffer;
size_t n = std::wcslen(ws) * 4 + 1;
buffer = static_cast<char*>(memoryUtil::AllocateArray<char>(alloc,n));
std::memset(buffer,0,n);
if(buffer == nullptr)
{
return nullptr;
}
std::wcstombs(buffer,ws,n);
return buffer;
}
}

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

#include "PsdNamespace.h"
#include "PsdAllocator.h"

PSD_NAMESPACE_BEGIN

namespace stringUtil
{
///
/// \brief Convert wchar_t * to char *
///
/// \param ws The wide string
/// \param alloc The mem allocator
/// \return char* nullptr on error
///
char *ConvertWString(const wchar_t* ws, Allocator* alloc);
}

PSD_NAMESPACE_END
10 changes: 10 additions & 0 deletions src/Samples/PsdDebug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#ifdef __linux
#define OutputDebugStringA(S) fputs(S,stderr)
#elif defined(__APPLE__)
void OutputDebugStringA(const char *message)
{
fprintf(stderr, "%s", message);
}
#endif
58 changes: 58 additions & 0 deletions src/Samples/PsdSamples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "../Psd/PsdExportDocument.h"

#include "PsdTgaExporter.h"
#include "PsdDebug.h"

PSD_PUSH_WARNING_LEVEL(0)
// disable annoying warning caused by xlocale(337): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
Expand All @@ -46,6 +47,11 @@ PSD_POP_WARNING_LEVEL
PSD_USING_NAMESPACE;


#ifdef __linux
#include <climits>
#include <cstring>
#endif

// helpers for reading PSDs
namespace
{
Expand Down Expand Up @@ -358,7 +364,59 @@ int SampleReadPsd(void)
std::wstringstream layerName;
if (layer->utf16Name)
{
#ifdef _WIN32
//In Windows wchar_t is utf16
static_assert(sizeof(wchar_t) == sizeof(uint16_t));
layerName << reinterpret_cast<wchar_t*>(layer->utf16Name);
#else
//In Linux, wchar_t is utf32
//Convert code from https://stackoverflow.com/questions/23919515/how-to-convert-from-utf-16-to-utf-32-on-linux-with-std-library#comment95663809_23920015
auto is_surrogate = [](uint16_t uc) -> bool
{
return ((uc - 0xd800u) < 2048u );
};
auto is_high_surrogate = [](uint16_t uc) -> bool
{
return ((uc & 0xfffffc00) == 0xd800 );
};
auto is_low_surrogate = [](uint16_t uc ) -> bool
{
return ((uc & 0xfffffc00) == 0xdc00 );
};
auto surrogate_to_utf32 = [](uint16_t high,uint16_t low) -> wchar_t
{
return ((high << 10) + low - 0x35fdc00);
};
static_assert(sizeof(wchar_t) == sizeof(uint32_t));

//Begin convert
size_t u16len = 0;
const uint16_t * cur = layer->utf16Name;
while(*cur != uint16_t('\0')){
cur++;
u16len++;
}
//Len it

const uint16_t * const end = layer->utf16Name + u16len;
const uint16_t * input = layer->utf16Name;
while (input < end) {
const uint16_t uc = *input++;
if (!is_surrogate(uc)) {
layerName << wchar_t(uc);
}
else {
if (is_high_surrogate(uc) && input < end && is_low_surrogate(*input)){
layerName << wchar_t(surrogate_to_utf32(uc, *input++));
}
else{
// Error
// Impossible
std::abort();
}
}
}
#endif
}
else
{
Expand Down
Loading

0 comments on commit 4768e60

Please sign in to comment.