diff --git a/header/examples/c++/example.cpp b/header/examples/c++/example.cpp index a48c456..9711ced 100644 --- a/header/examples/c++/example.cpp +++ b/header/examples/c++/example.cpp @@ -1,10 +1,11 @@ +#include #include #include "../../libShaderFile.hpp" #if _WIN64 -static const char* LibName = "..\..\..\libShaderFile-x86_64-win64.dll"; +static const char* LibName = "..\\..\\..\\libShaderFile-x86_64-win64.dll"; #elif _WIN32 -static const char* LibName = "..\..\..\libShaderFile-i386-win32.dll"; +static const char* LibName = "..\\..\\..\\libShaderFile-i386-win32.dll"; #elif __linux__ && (__amd64 || __x86_64 || _M_AMD64 || __ppc64__) static const char* LibName = "../../../libShaderFile-x86_64-linux.so"; #elif __linux__ && (__i386 || _X86_) @@ -13,6 +14,19 @@ static const char* LibName = "../../../libShaderFile-i386-linux.so"; # error 'unknown operation system' #endif +class FileReader : public lsf::IFileReader +{ +public: + virtual bool loadStream(const std::string& filename, std::ostream& os) + { + std::ifstream fs(filename.c_str()); + if (!fs) + return false; + os << fs.rdbuf(); + return true; + } +}; + int main(int argc, char **argv) { try @@ -28,7 +42,8 @@ int main(int argc, char **argv) // create and load shader file lsf::ShaderFile shaderFile(lib); - shaderFile.loadFromFile(argv[1]); + FileReader reader; + shaderFile.loadFromFunc(argv[1], reader); const lsf::Library& l = shaderFile.getLibrary(); diff --git a/header/examples/c/example.c b/header/examples/c/example.c index 16ea244..68c1298 100644 --- a/header/examples/c/example.c +++ b/header/examples/c/example.c @@ -2,9 +2,9 @@ #include "../../libShaderFile.h" #if _WIN64 -# define LIB_NAME "..\..\..\libShaderFile-x86_64-win64.dll" +# define LIB_NAME "..\\..\\..\\libShaderFile-x86_64-win64.dll" #elif _WIN32 -# define LIB_NAME "..\..\..\libShaderFile-i386-win32.dll" +# define LIB_NAME "..\\..\\..\\libShaderFile-i386-win32.dll" #elif __linux__ && (__amd64 || __x86_64 || _M_AMD64 || __ppc64__) # define LIB_NAME "../../../libShaderFile-x86_64-linux.so" #elif __linux__ && (__i386 || _X86_) diff --git a/header/examples/delphi/example.dpr b/header/examples/delphi/example.dpr index 944ce58..a279357 100644 --- a/header/examples/delphi/example.dpr +++ b/header/examples/delphi/example.dpr @@ -3,15 +3,34 @@ program example; {$APPTYPE CONSOLE} uses - SysUtils, + SysUtils, Classes, ulibShaderFile; +type + TFileReader = class(TInterfacedObject, IlsfFileReader) + public + function LoadStream(const aFilename: String; const aStream: TStream): Boolean; + end; + var i: Integer; s: String; ShaderFile: TlsfShaderFile; Generator: TlsfGenerator; +function TFileReader.LoadStream(const aFilename: String; const aStream: TStream): Boolean; +var + fs: TFileStream; +begin + fs := TFileStream.Create(aFilename, fmOpenRead); + try + aStream.CopyFrom(fs, fs.Size - fs.Position); + result := true; + finally + FreeAndNil(fs); + end; +end; + begin lsf_init(ExtractFilePath(ParamStr(0)) + '..\..\..\libShaderFile-i386-win32.dll'); try @@ -22,8 +41,8 @@ begin end; ShaderFile := TlsfShaderFile.Create; try - ShaderFile.LoadFromFile(ParamStr(1)); - Generator := TlsfGenerator.Create(ShaderFile, ParamStr(2)); + ShaderFile.LoadFromFunc(ParamStr(1), TFileReader.Create); + Generator := TlsfGenerator.Create(ShaderFile, Trim(ParamStr(2))); try i := 3; while (i < ParamCount) do begin diff --git a/header/examples/fpc/example.lpr b/header/examples/fpc/example.lpr index 6df54e4..f9d10d8 100644 --- a/header/examples/fpc/example.lpr +++ b/header/examples/fpc/example.lpr @@ -1,7 +1,7 @@ program example; uses - sysutils, variants, + sysutils, variants, Classes, ulibShaderFile; const @@ -17,12 +17,31 @@ const {$ERROR 'unknown operation system'} {$IFEND} +type + TFileReader = class(TInterfacedObject, IlsfFileReader) + public + function LoadStream(const aFilename: String; const aStream: TStream): Boolean; + end; + var i: Integer; s: String; ShaderFile: TlsfShaderFile; Generator: TlsfGenerator; +function TFileReader.LoadStream(const aFilename: String; const aStream: TStream): Boolean; +var + fs: TFileStream; +begin + fs := TFileStream.Create(aFilename, fmOpenRead); + try + aStream.CopyFrom(fs, fs.Size - fs.Position); + result := true; + finally + FreeAndNil(fs); + end; +end; + begin lsf_init(ExtractFilePath(ParamStr(0)) + LibName); try @@ -33,7 +52,7 @@ begin end; ShaderFile := TlsfShaderFile.Create; try - ShaderFile.LoadFromFile(ParamStr(1)); + ShaderFile.LoadFromFunc(ParamStr(1), TFileReader.Create); Generator := TlsfGenerator.Create(ShaderFile, ParamStr(2)); try i := 3; diff --git a/header/libShaderFile.h b/header/libShaderFile.h index 865850e..1408c44 100644 --- a/header/libShaderFile.h +++ b/header/libShaderFile.h @@ -2,6 +2,7 @@ #define LIB_SHADER_FILE_H #include +#include /**********************************************************************************************************************************/ /* public interface */ @@ -15,6 +16,7 @@ #define LSF_ERR_NOT_INIT 0x00000001 #define LSF_ERR_INVALID_HANDLE_SHADER_FILE 0x00000010 #define LSF_ERR_INVALID_HANDLE_SHADER_GENERATOR 0x00000011 +#define LSF_ERR_INVALID_HANDLE_STREAM 0x00000012 #define LSF_ERR_INVALID_GENERATOR_NAME 0x00000020 #define LSF_ERR_INVALID_PROPERTY_INDEX 0x00000021 #define LSF_ERR_INVALID_PROPERTY_NAME 0x00000022 @@ -36,6 +38,10 @@ #define LSF_ERR_INVALID_METHOD_NAME 0x00002002 #define LSF_ERR_UNKNOWN 0xFFFFFFFF +#define LSF_SEEK_BEG 0 +#define LSF_SEEK_CUR 1 +#define LSF_SEEK_END 2 + #if __MINGW32__ # define WINAPI __stdcall #else @@ -44,10 +50,30 @@ typedef uint32_t lsf_error_code_t; typedef uint32_t lsf_log_level_t; +typedef uint32_t lsf_seek_origin_t; + typedef void* lsf_shader_file_handle_t; typedef void* lsf_shader_generator_handle_t; +typedef void* lsf_stream_handle_t; + +/** function pointer to write log messages + * @param loglevel log level of current message (see LSF_LOGLEVEL_*) + * @param msg message to log + * @param userargs user defined arguments */ +typedef void (WINAPI *lsf_shader_file_log_callback_t)(const lsf_log_level_t loglevel, const char* msg, const void* userargs); + +/** function pointer to save shader code + * @param filename filename to save shader code to + * @param handle handle to stream data (use lsf_stream_* methods to read/write data) + * @param userargs user defined arguments */ +typedef void (WINAPI *lsf_save_data_callback_t)(const char* filename, const lsf_stream_handle_t handle, const void* userargs); + +/** function pointer to load shader code + * @param filename filename to load shader code from + * @param handle handle to stream data (use lsf_stream_* methods to read/write data) + * @param userargs user defined arguments */ +typedef bool (WINAPI *lsf_load_data_callback_t)(const char* filename, const lsf_stream_handle_t handle, const void* userargs); -typedef void (*lsf_shader_file_log_callback_t)(const lsf_log_level_t loglevel, const char* msg, const void* userargs); /** create a new shader file handle * @returns shader file handle or NULL (check lsf_get_last_error_* for more details) */ @@ -66,12 +92,28 @@ lsf_error_code_t (WINAPI *lsf_shader_file_set_log_callback) (const lsf_shader_fi * @returns error code (see LSF_ERR_*) */ lsf_error_code_t (WINAPI *lsf_shader_file_load_from_file) (const lsf_shader_file_handle_t handle, const char* filename); +/** load shader code from function + * @param handle handle of shader file to load + * @param filename name of the file to load code from (will be passed to callback; can be used as key to identify data to load) + * @param callback function to call to request data + * @param userargs user defined arguments (will be passed to callback) + * @returns error code (see LSF_ERR_) */ +lsf_error_code_t (WINAPI *lsf_shader_file_load_from_func) (const lsf_shader_file_handle_t handle, const char* filename, const lsf_load_data_callback_t callback, const void* userargs); + /** save shader file code to a given file * @param handle handle of shader file to save to file * @param filename file to save shader code to * @returns error code (see LSF_ERR_*) */ lsf_error_code_t (WINAPI *lsf_shader_file_save_to_file) (const lsf_shader_file_handle_t handle, const char* filename); +/** save shader code to function + * @param handle handle of shader file to load + * @param filename name of the file to save code to (will be passed to callback; can be used as key to identify data to save) + * @param callback function to call to save data + * @param userargs user defined arguments (will be passed to callback) + * @returns error code (see LSF_ERR_) */ +lsf_error_code_t (WINAPI *lsf_shader_file_save_to_func) (const lsf_shader_file_handle_t handle, const char* filename, const lsf_load_data_callback_t callback, const void* userargs); + /** generate a list of all code generators in a shader file * @param handle shader file handle to generate list for * @returns list of code generators (seperated by linebreak) or NULL (check lsf_get_last_error_* for more details) */ @@ -111,14 +153,14 @@ const char* (WINAPI *lsf_generator_get_property_by_name) (const lsf_shader_gener * @param handle generator handle * @param index index of the property (see lsf_generator_get_property_names to calculate property index) * @param value new value of the property - * @return property value or NULL (check lsf_get_last_error_* for more details) */ + * @return error code (see LSF_ERR_*) */ lsf_error_code_t (WINAPI *lsf_generator_set_property) (const lsf_shader_generator_handle_t handle, const int index, const char* value); /** set a property value by its name * @param handle generator handle * @param name name of the property * @param value new value of the property - * @return property value or NULL (check lsf_get_last_error_* for more details) */ + * @return error code (see LSF_ERR_*) */ lsf_error_code_t (WINAPI *lsf_generator_set_property_by_name) (const lsf_shader_generator_handle_t handle, const char* name, const char* value); /** generate shader code @@ -132,6 +174,38 @@ const char* (WINAPI *lsf_generator_generate_code) (const lsf_shader_generator_ha lsf_error_code_t (WINAPI *lsf_generator_destroy) (const lsf_shader_generator_handle_t handle); +/** get size of stream + * @param handle stream handle to get size from + * @returns stream size on success, -1 otherwise (check lsf_get_last_error_* for more details) */ +int (WINAPI *lsf_stream_get_size) (const lsf_stream_handle_t handle); + +/** set size of stream + * @param handle stream handle to set size from + * @returns error code (see LSF_ERR_*) */ +lsf_error_code_t (WINAPI *lsf_stream_set_size) (const lsf_stream_handle_t handle, const int size); + +/** seek stream + * @param handle stream handle to seek + * @param offset number of bytes to use as offset + * @param origin seek origin + * @returns new position on success, -1 otherwise (check lsf_get_last_error_* for more details) */ +int (WINAPI *lsf_stream_seek) (const lsf_stream_handle_t handle, const int offset, const lsf_seek_origin_t origin); + +/** read data from stream + * @param handle stream handle to read data from + * @param buffer buffer to copy data into + * @param size number of bytes to read + * @returns number of read bytes on success, -1 otherwise (check lsf_get_last_error_* for more details) */ +int (WINAPI *lsf_stream_read) (const lsf_stream_handle_t handle, const void *buffer, const int size); + +/** write data to stream + * @param handle stream handle to write data to + * @param buffer buffer to copy data from + * @param size number of bytes to write + * @returns number of written bytes on success, -1 otherwise (check lsf_get_last_error_* for more details) */ +int (WINAPI *lsf_stream_write) (const lsf_stream_handle_t handle, const void *buffer, const int size); + + /** get last error code * @return error code of last failed operation */ lsf_error_code_t (WINAPI *lsf_get_last_error_code) (); @@ -242,6 +316,12 @@ int lsf_init(const char* libname) LoadProc(lsf_generator_generate_code, "lsf_Generator_generateCode"); LoadProc(lsf_generator_destroy, "lsf_Generator_destroy"); + LoadProc(lsf_stream_get_size, "lsf_Stream_getSize"); + LoadProc(lsf_stream_set_size, "lsf_Stream_setSize"); + LoadProc(lsf_stream_seek, "lsf_Stream_seek"); + LoadProc(lsf_stream_read, "lsf_Stream_read"); + LoadProc(lsf_stream_write, "lsf_Stream_write"); + LoadProc(lsf_init_intern, "lsf_init"); LoadProc(lsf_get_last_error_code, "lsf_getLastErrorCode"); LoadProc(lsf_get_last_error_msg, "lsf_getLastErrorMsg"); diff --git a/header/libShaderFile.hpp b/header/libShaderFile.hpp index 6d3bf06..57534d1 100644 --- a/header/libShaderFile.hpp +++ b/header/libShaderFile.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -35,6 +36,7 @@ namespace lsf enum ErrorCode { + errUnknown = -1, errNone = 0x00000000, errNotInit = 0x00000001, errInvalidHandleShaderFile = 0x00000010, @@ -58,7 +60,32 @@ namespace lsf errInvalidLibraryName = 0x00002000, errInvalidLibraryHandle = 0x00002001, errInvalidMethodName = 0x00002002, - errUnknown = 0xffffffff, + }; + + enum SeekOrigin + { + soBeg = 0, + soCur = 1, + soEnd = 2, + }; + + class IFileReader + { + public: + /** request to load shader code + * @param filename filename/name to identify data to be load + * @param is input stream to write loaded data into + * @returns TRUE on success, FALSE otherwise */ + virtual bool loadStream(const std::string& filename, std::ostream& os) = 0; + }; + + class IFileWriter + { + public: + /** request to store shader code + * @param filename filename/name to identify data to be saved + * @param os output stream to read saved data from */ + virtual void saveStream(const std::string& filename, std::istream& is) = 0; }; /** class to load and manage shared library */ @@ -135,10 +162,20 @@ namespace lsf * @param filename file to load shader code from */ void loadFromFile(std::string filename); + /** load shader file from function + * @param filename file to load shader code from + * @param reader file reader to use for loading */ + void loadFromFunc(std::string filename, IFileReader& reader); + /** save shader file to a given file * @param filename file to save shader code to */ void saveToFile(std::string filename) const; + /** save shader file to function + * @param filename file to save shader code to + * @param writer file writer to use for saving */ + void saveToFunc(std::string filename, IFileWriter& writer); + /** constructor * @param library library this shader file is attached to */ ShaderFile(const Library& library); @@ -186,7 +223,7 @@ namespace lsf const ShaderFile& getShaderFile() const; /** get a vector of all known properties - * @return vecotr with all known properties */ + * @return vector with all known properties */ const StringVec& getPropertyNames() const; /** get the value of a single property by its name @@ -255,7 +292,6 @@ namespace lsf - /**********************************************************************************************************************************/ /* private implementation */ /**********************************************************************************************************************************/ @@ -288,35 +324,244 @@ int libClose(lsf::Library::Handle handle) /* Library::Impl ******************************************************************************************************************/ struct lsf::Library::Impl { - typedef ShaderFile::Handle (WINAPI *lsf_shader_file_create_t) (); - typedef void (WINAPI *lsf_shader_file_log_callback_t) (const LogLevel loglevel, const char* msg, void* userargs); - typedef ErrorCode (WINAPI *lsf_shader_file_set_log_callback_t) (const ShaderFile::Handle handle, const lsf_shader_file_log_callback_t callback, void* userargs); - typedef ErrorCode (WINAPI *lsf_shader_file_load_from_file_t) (const ShaderFile::Handle handle, const char* filename); - typedef ErrorCode (WINAPI *lsf_shader_file_save_to_file_t) (const ShaderFile::Handle handle, const char* filename); - typedef const char* (WINAPI *lsf_shader_file_get_generator_names_t) (const ShaderFile::Handle handle); - typedef ErrorCode (WINAPI *lsf_shader_file_destroy_t) (const ShaderFile::Handle handle); - - typedef Generator::Handle (WINAPI *lsf_generator_create_t) (const ShaderFile::Handle handle, const char* name); - typedef const char* (WINAPI *lsf_generator_get_property_names_t) (const Generator::Handle handle); - typedef const char* (WINAPI *lsf_generator_get_property_t) (const Generator::Handle handle, const int index); - typedef const char* (WINAPI *lsf_generator_get_property_by_name_t) (const Generator::Handle handle, const char* name); - typedef ErrorCode (WINAPI *lsf_generator_set_property_t) (const Generator::Handle handle, const int index, const char* value); - typedef ErrorCode (WINAPI *lsf_generator_set_property_by_name_t) (const Generator::Handle handle, const char* name, const char* value); - typedef const char* (WINAPI *lsf_generator_generate_code_t) (const Generator::Handle handle); - typedef ErrorCode (WINAPI *lsf_generator_destroy_t) (const Generator::Handle handle); - - typedef ErrorCode (WINAPI *lsf_init_t) (); - typedef ErrorCode (WINAPI *lsf_get_last_error_code_t) (); - typedef const char* (WINAPI *lsf_get_last_error_msg_t) (); - typedef const char* (WINAPI *lsf_get_last_error_trace_t) (); - typedef ErrorCode (WINAPI *lsf_finish_t) (); +public: + typedef void* StreamHandle; + + /* pure callbacks */ + typedef void (WINAPI *lsf_shader_file_log_callback_t) (const LogLevel loglevel, const char* msg, void* userargs); + typedef void (WINAPI *lsf_save_data_callback_t) (const char* filename, const StreamHandle handle, const void* userargs); + typedef bool (WINAPI *lsf_load_data_callback_t) (const char* filename, const StreamHandle handle, const void* userargs); + + /* ShaderFile */ + typedef ShaderFile::Handle (WINAPI *lsf_shader_file_create_t) (); + typedef ErrorCode (WINAPI *lsf_shader_file_set_log_callback_t) (const ShaderFile::Handle handle, const lsf_shader_file_log_callback_t callback, void* userargs); + typedef ErrorCode (WINAPI *lsf_shader_file_load_from_file_t) (const ShaderFile::Handle handle, const char* filename); + typedef ErrorCode (WINAPI *lsf_shader_file_load_from_func_t) (const ShaderFile::Handle handle, const char* filename, const lsf_load_data_callback_t callback, const void* userargs); + typedef ErrorCode (WINAPI *lsf_shader_file_save_to_file_t) (const ShaderFile::Handle handle, const char* filename); + typedef ErrorCode (WINAPI *lsf_shader_file_save_to_func_t) (const ShaderFile::Handle handle, const char* filename, const lsf_save_data_callback_t callback, const void* userargs); + typedef const char* (WINAPI *lsf_shader_file_get_generator_names_t) (const ShaderFile::Handle handle); + typedef ErrorCode (WINAPI *lsf_shader_file_destroy_t) (const ShaderFile::Handle handle); + + /* Generator */ + typedef Generator::Handle (WINAPI *lsf_generator_create_t) (const ShaderFile::Handle handle, const char* name); + typedef const char* (WINAPI *lsf_generator_get_property_names_t) (const Generator::Handle handle); + typedef const char* (WINAPI *lsf_generator_get_property_t) (const Generator::Handle handle, const int index); + typedef const char* (WINAPI *lsf_generator_get_property_by_name_t) (const Generator::Handle handle, const char* name); + typedef ErrorCode (WINAPI *lsf_generator_set_property_t) (const Generator::Handle handle, const int index, const char* value); + typedef ErrorCode (WINAPI *lsf_generator_set_property_by_name_t) (const Generator::Handle handle, const char* name, const char* value); + typedef const char* (WINAPI *lsf_generator_generate_code_t) (const Generator::Handle handle); + typedef ErrorCode (WINAPI *lsf_generator_destroy_t) (const Generator::Handle handle); + + /* Stream */ + typedef int (WINAPI *lsf_stream_get_size_t) (const StreamHandle handle); + typedef ErrorCode (WINAPI *lsf_stream_set_size_t) (const StreamHandle handle, const int size); + typedef int (WINAPI *lsf_stream_seek_t) (const StreamHandle handle, const int offset, const SeekOrigin origin); + typedef int (WINAPI *lsf_stream_read_t) (const StreamHandle handle, void *buffer, const int size); + typedef int (WINAPI *lsf_stream_write_t) (const StreamHandle handle, const void *buffer, const int size); + + /* Library */ + typedef ErrorCode (WINAPI *lsf_init_t) (); + typedef ErrorCode (WINAPI *lsf_get_last_error_code_t) (); + typedef const char* (WINAPI *lsf_get_last_error_msg_t) (); + typedef const char* (WINAPI *lsf_get_last_error_trace_t) (); + typedef ErrorCode (WINAPI *lsf_finish_t) (); + +public: + class InStreamBuf : public std::streambuf + { + private: + const Library::Impl& _impl; + StreamHandle _handle; + const std::streamsize _bufferSize; + const std::streamsize _putBack; + std::vector _buffer; + + void resetBuffer() + { + char* end = &_buffer.front() + _buffer.size(); + setg(end, end, end); + } + protected: + virtual int_type underflow() + { + if (gptr() < egptr()) + return traits_type::to_int_type(*gptr()); + + char *base = &_buffer.front(); + char *start = base; + if (eback() == base) + { + std::memmove(base, egptr() - _putBack, _putBack); + start += _putBack; + } + int n = _impl.lsf_stream_read(_handle, start, _buffer.size() - (start - base)); + if (n < 0) + throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); + if (n == 0) + return traits_type::eof(); + setg(base, start, start + n); + return traits_type::to_int_type(*gptr()); + } + + virtual std::streamsize xsgetn(char* buffer, std::streamsize count) + { + std::streamsize ret = 0; + char* b = buffer; + std::streamsize s = std::min(static_cast(egptr() - gptr()), count); + if (s > 0) + { + memmove(b, gptr(), s); + gbump(s); + b += s; + ret += s; + count -= s; + resetBuffer(); + } + if (count > 0) + { + int n = _impl.lsf_stream_read(_handle, b, count); + if (n < 0) + throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); + ret += n; + } + return ret; + } + + virtual pos_type seekoff(off_type offset, std::ios_base::seekdir dir, std::ios_base::openmode mode) + { + if (mode & std::ios_base::out) + return (std::streampos(-1)); + int pos = 0; + switch(dir) + { + case std::ios::beg: + pos = _impl.lsf_stream_seek(_handle, offset, soBeg); + break; + case std::ios::cur: + pos = _impl.lsf_stream_seek(_handle, offset, soCur); + break; + case std::ios::end: + pos = _impl.lsf_stream_seek(_handle, offset, soEnd); + break; + } + if (pos < 0) + throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); + resetBuffer(); + return pos; + } + + virtual pos_type seekpos(pos_type offset, std::ios_base::openmode mode) + { + return seekoff(offset, std::ios::beg, mode); + } + public: + InStreamBuf(const Impl& impl, StreamHandle handle, std::streamsize bufferSize = 1024, std::streamsize putBack = 32) : + _impl (impl), + _handle (handle), + _bufferSize (bufferSize), + _putBack (putBack), + _buffer (bufferSize) + { + resetBuffer(); + }; + }; + class OutStreamBuf : public std::streambuf + { + private: + const Library::Impl& _impl; + StreamHandle _handle; + const std::streamsize _bufferSize; + std::vector _buffer; + + inline int doWrite(const char* buffer, int size) + { + int ret = _impl.lsf_stream_write(_handle, buffer, size); + if (ret < 0) + throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); + } + + bool doFlush() + { + int n = pptr() - pbase(); + pbump(-n); + int ret = doWrite(pbase(), n); + return (ret == n); + } + protected: + virtual int_type overflow(int_type ch) + { + if (ch != traits_type::eof()) + { + if (pptr() > epptr()) + throw Exception("internal error in OutStreamBuf", errUnknown); + *pptr() = ch; + pbump(1); + if (doFlush()) + return ch; + } + return traits_type::eof(); + } + + virtual int sync() + { + return (doFlush() ? 0 : -1); + } + + virtual std::streamsize xsputn(const char *buffer, std::streamsize count) + { + if (!doFlush()) + return 0; + return doWrite(buffer, count); + } + + virtual pos_type seekoff(off_type offset, std::ios_base::seekdir dir, std::ios_base::openmode mode) + { + if (mode & std::ios_base::in) + return (std::streampos(-1)); + int pos = 0; + switch(dir) + { + case std::ios::beg: + pos = _impl.lsf_stream_seek(_handle, offset, soBeg); + break; + case std::ios::cur: + pos = _impl.lsf_stream_seek(_handle, offset, soCur); + break; + case std::ios::end: + pos = _impl.lsf_stream_seek(_handle, offset, soEnd); + break; + } + if (pos < 0) + throw Exception(_impl.lsf_get_last_error_msg(), _impl.lsf_get_last_error_code()); + return pos; + } + + virtual pos_type seekpos(pos_type offset, std::ios_base::openmode mode) + { + return seekoff(offset, std::ios::beg, mode); + } + public: + OutStreamBuf(const Impl& impl, StreamHandle handle, std::streamsize bufferSize = 1024) : + _impl (impl), + _handle (handle), + _bufferSize (bufferSize), + _buffer (bufferSize) + { + char *base = &_buffer.front(); + setp(base, base + _buffer.size() - 1); + }; + }; + +public: const Library& library; lsf_shader_file_create_t lsf_shader_file_create; lsf_shader_file_set_log_callback_t lsf_shader_file_set_log_callback; lsf_shader_file_load_from_file_t lsf_shader_file_load_from_file; + lsf_shader_file_load_from_func_t lsf_shader_file_load_from_func; lsf_shader_file_save_to_file_t lsf_shader_file_save_to_file; + lsf_shader_file_save_to_func_t lsf_shader_file_save_to_func; lsf_shader_file_get_generator_names_t lsf_shader_file_get_generator_names; lsf_shader_file_destroy_t lsf_shader_file_destroy; @@ -329,6 +574,12 @@ struct lsf::Library::Impl lsf_generator_generate_code_t lsf_generator_generate_code; lsf_generator_destroy_t lsf_generator_destroy; + lsf_stream_get_size_t lsf_stream_get_size; + lsf_stream_set_size_t lsf_stream_set_size; + lsf_stream_seek_t lsf_stream_seek; + lsf_stream_read_t lsf_stream_read; + lsf_stream_write_t lsf_stream_write; + lsf_init_t lsf_init; lsf_get_last_error_code_t lsf_get_last_error_code; lsf_get_last_error_msg_t lsf_get_last_error_msg; @@ -341,7 +592,9 @@ struct lsf::Library::Impl lsf_shader_file_create (NULL), lsf_shader_file_set_log_callback (NULL), lsf_shader_file_load_from_file (NULL), + lsf_shader_file_load_from_func (NULL), lsf_shader_file_save_to_file (NULL), + lsf_shader_file_save_to_func (NULL), lsf_shader_file_get_generator_names (NULL), lsf_shader_file_destroy (NULL), @@ -354,12 +607,51 @@ struct lsf::Library::Impl lsf_generator_generate_code (NULL), lsf_generator_destroy (NULL), + lsf_stream_get_size (NULL), + lsf_stream_set_size (NULL), + lsf_stream_seek (NULL), + lsf_stream_read (NULL), + lsf_stream_write (NULL), + lsf_init (NULL), lsf_get_last_error_code (NULL), lsf_get_last_error_msg (NULL), lsf_get_last_error_trace (NULL), lsf_finish (NULL) { }; + +public: + struct DataCallbackArgs + { + const Impl* impl; + IFileReader* reader; + IFileWriter* writer; + }; + + /** callback method to save data + * @param filename filename to save data to + * @param handle stream handle with data to save + * @param userargs user defined arguments */ + static void WINAPI saveDataCallback(const char* filename, const StreamHandle handle, const void* userargs) + { + const DataCallbackArgs *args = static_cast(userargs); + InStreamBuf buf(*args->impl, handle); + std::istream is(&buf); + args->writer->saveStream(filename, is); + } + + /** callback method to load data + * @param filename filename to load data from + * @param handle stream handle to write loaded data to + * @param userargs user defined arguments + * @returns TRUE on success, FALSE otherwise */ + static bool WINAPI loadDataCallback(const char* filename, const StreamHandle handle, const void* userargs) + { + const DataCallbackArgs *args = static_cast(userargs); + OutStreamBuf buf(*args->impl, handle); + std::ostream os(&buf); + return args->reader->loadStream(filename, os); + } }; /* Library ************************************************************************************************************************/ @@ -390,7 +682,9 @@ lsf::Library::Library(std::string libName) : loadProc(_handle, _impl->lsf_shader_file_create, "lsf_ShaderFile_create"); loadProc(_handle, _impl->lsf_shader_file_set_log_callback, "lsf_ShaderFile_setLogCallback"); loadProc(_handle, _impl->lsf_shader_file_load_from_file, "lsf_ShaderFile_loadFromFile"); + loadProc(_handle, _impl->lsf_shader_file_load_from_func, "lsf_ShaderFile_loadFromFunc"); loadProc(_handle, _impl->lsf_shader_file_save_to_file, "lsf_ShaderFile_saveToFile"); + loadProc(_handle, _impl->lsf_shader_file_save_to_func, "lsf_ShaderFile_saveToFunc"); loadProc(_handle, _impl->lsf_shader_file_get_generator_names, "lsf_ShaderFile_getGeneratorNames"); loadProc(_handle, _impl->lsf_shader_file_destroy, "lsf_ShaderFile_destroy"); @@ -403,6 +697,12 @@ lsf::Library::Library(std::string libName) : loadProc(_handle, _impl->lsf_generator_generate_code, "lsf_Generator_generateCode"); loadProc(_handle, _impl->lsf_generator_destroy, "lsf_Generator_destroy"); + loadProc(_handle, _impl->lsf_stream_get_size, "lsf_Stream_getSize"); + loadProc(_handle, _impl->lsf_stream_set_size, "lsf_Stream_setSize"); + loadProc(_handle, _impl->lsf_stream_seek, "lsf_Stream_seek"); + loadProc(_handle, _impl->lsf_stream_read, "lsf_Stream_read"); + loadProc(_handle, _impl->lsf_stream_write, "lsf_Stream_write"); + loadProc(_handle, _impl->lsf_init, "lsf_init"); loadProc(_handle, _impl->lsf_get_last_error_code, "lsf_getLastErrorCode"); loadProc(_handle, _impl->lsf_get_last_error_msg, "lsf_getLastErrorMsg"); @@ -443,14 +743,34 @@ void lsf::ShaderFile::loadFromFile(std::string filename) { ErrorCode err = _impl.lsf_shader_file_load_from_file(_handle, filename.c_str()); if (err != errNone) - throw Exception("unable to load file", err); + throw Exception(_impl.lsf_get_last_error_msg(), err); +} + +void lsf::ShaderFile::loadFromFunc(std::string filename, IFileReader& reader) +{ + lsf::Library::Impl::DataCallbackArgs args; + args.impl = &_impl; + args.reader = &reader; + ErrorCode err = _impl.lsf_shader_file_load_from_func(_handle, filename.c_str(), &Library::Impl::loadDataCallback, &args); + if (err != errNone) + throw Exception(_impl.lsf_get_last_error_msg(), err); } void lsf::ShaderFile::saveToFile(std::string filename) const { ErrorCode err = _impl.lsf_shader_file_load_from_file(_handle, filename.c_str()); if (err != errNone) - throw Exception("unable to load file", err); + throw Exception(_impl.lsf_get_last_error_msg(), err); +} + +void lsf::ShaderFile::saveToFunc(std::string filename, IFileWriter& writer) +{ + lsf::Library::Impl::DataCallbackArgs args; + args.impl = &_impl; + args.writer = &writer; + ErrorCode err = _impl.lsf_shader_file_save_to_func(_handle, filename.c_str(), &Library::Impl::saveDataCallback, &args); + if (err != errNone) + throw Exception(_impl.lsf_get_last_error_msg(), err); } lsf::ShaderFile::ShaderFile(const Library& library) : @@ -572,3 +892,4 @@ lsf::Exception::~Exception() throw() + diff --git a/header/ulibShaderFile.pas b/header/ulibShaderFile.pas index 8693f5f..025d840 100644 --- a/header/ulibShaderFile.pas +++ b/header/ulibShaderFile.pas @@ -26,6 +26,7 @@ type errNotInit = $00000001, errInvalidHandleShaderFile = $00000010, errInvalidHandleShaderGenerator = $00000011, + errInvalidHandleStream = $00000012, errInvalidGeneratorName = $00000020, errInvalidPropertyIndex = $00000021, errInvalidPropertyName = $00000022, @@ -47,16 +48,28 @@ type errInvalidMethodName = $00002002 ); + {$Z4} + TlsfSeekOrigin = ( + soBeg = 0, + soCur = 1, + soEnd = 2 + ); + TlsfShaderFileHandle = Pointer; TlsfGeneratorHandle = Pointer; + TlsfStreamHandle = Pointer; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TlsfShaderFileLogEvent = procedure(const aLogLevel: TlsfLogLevel; const aMsg: PAnsiChar; const aUserArgs: Pointer); stdcall; + TlsfSaveDataCallback = procedure(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer); stdcall; + TlsfLoadDataCallback = function(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer): Boolean; stdcall; Tlsf_ShaderFile_create = function: TlsfShaderFileHandle; stdcall; Tlsf_ShaderFile_setLogCallback = function(const aHandle: TlsfShaderFileHandle; const aCallback: TlsfShaderFileLogEvent; const aUserArgs: Pointer): TlsfErrorCode; stdcall; Tlsf_ShaderFile_loadFromFile = function(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall; + Tlsf_ShaderFile_loadFromFunc = function(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar; const aCallback: TlsfLoadDataCallback; const aUserArgs: Pointer): TlsfErrorCode; stdcall; Tlsf_ShaderFile_saveToFile = function(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall; + Tlsf_ShaderFile_saveToFunc = function(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar; const aCallback: TlsfSaveDataCallback; const aUserArgs: Pointer): TlsfErrorCode; stdcall; Tlsf_ShaderFile_getGeneratorNames = function(const aHandle: TlsfShaderFileHandle): PAnsiChar; stdcall; Tlsf_ShaderFile_destroy = function(const aHandle: TlsfShaderFileHandle): TlsfErrorCode; stdcall; @@ -69,12 +82,29 @@ type Tlsf_Generator_generateCode = function(const aHandle: TlsfGeneratorHandle): PAnsiChar; stdcall; Tlsf_Generator_destroy = function(const aHandle: TlsfGeneratorHandle): TlsfErrorCode; stdcall; + Tlsf_Stream_getSize = function(const aHandle: TlsfStreamHandle): Integer; stdcall; + Tlsf_Stream_setSize = function(const aHandle: TlsfStreamHandle; const aSize: Integer): TlsfErrorCode; stdcall; + Tlsf_Stream_seek = function(const aHandle: TlsfStreamHandle; const aOffset: Integer; const aOrigin: TlsfSeekOrigin): Integer; stdcall; + Tlsf_Stream_read = function(const aHandle: TlsfStreamHandle; const aBuffer: Pointer; const aSize: Integer): Integer; stdcall; + Tlsf_Stream_write = function(const aHandle: TlsfStreamHandle; const aBuffer: Pointer; const aSize: Integer): Integer; stdcall; + Tlsf_init = function: TlsfErrorCode; stdcall; Tlsf_getLastErrorCode = function: TlsfErrorCode; stdcall; Tlsf_getLastErrorMsg = function: PAnsiChar; stdcall; Tlsf_getLastErrorTrace = function: PAnsiChar; stdcall; Tlsf_finish = function: TlsfErrorCode; stdcall; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + IlsfFileReader = interface + ['{1820220E-0043-491A-B841-19A4B11C6090}'] + function LoadStream(const aFilename: String; const aStream: TStream): Boolean; + end; + + IlsfFileWriter = interface + ['{FEF0760E-402B-4627-9171-273AE215FADB}'] + procedure SaveStream(const aFilename: String; const aStream: TStream); + end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TlsfShaderFile = class(TObject) private @@ -85,7 +115,9 @@ type property Handle: TlsfShaderFileHandle read fHandle; procedure LoadFromFile(const aFilename: String); + procedure LoadFromFunc(const aFilename: String; const aFileReader: IlsfFileReader); procedure SaveToFile(const aFilename: String); + procedure SaveToFunc(const aFilename: String; const aFileWriter: IlsfFileWriter); constructor Create; destructor Destroy; override; @@ -130,7 +162,9 @@ var lsf_ShaderFile_create: Tlsf_ShaderFile_create; lsf_ShaderFile_setLogCallback: Tlsf_ShaderFile_setLogCallback; lsf_ShaderFile_loadFromFile: Tlsf_ShaderFile_loadFromFile; + lsf_ShaderFile_loadFromFunc: Tlsf_ShaderFile_loadFromFunc; lsf_ShaderFile_saveToFile: Tlsf_ShaderFile_saveToFile; + lsf_ShaderFile_saveToFunc: Tlsf_ShaderFile_saveToFunc; lsf_ShaderFile_getGeneratorNames: Tlsf_ShaderFile_getGeneratorNames; lsf_ShaderFile_destroy: Tlsf_ShaderFile_destroy; @@ -143,6 +177,12 @@ var lsf_Generator_generateCode: Tlsf_Generator_generateCode; lsf_Generator_destroy: Tlsf_Generator_destroy; + lsf_Stream_getSize: Tlsf_Stream_getSize; + lsf_Stream_setSize: Tlsf_Stream_setSize; + lsf_Stream_seek: Tlsf_Stream_seek; + lsf_Stream_read: Tlsf_Stream_read; + lsf_Stream_write: Tlsf_Stream_write; + lsf_getLastErrorCode: Tlsf_getLastErrorCode; lsf_getLastErrorMsg: Tlsf_getLastErrorMsg; lsf_getLastErrorTrace: Tlsf_getLastErrorTrace; @@ -218,6 +258,21 @@ var lsf_init_intern: Tlsf_init; lsf_finish_intern: Tlsf_finish; +type + TlsfStream = class(TStream) + private + fHandle: TlsfStreamHandle; + protected + function GetSize: Int64; override; + procedure SetSize(NewSize: Longint); override; {$IFDEF FPC}overload;{$ENDIF} + public + function Seek(Offset: Longint; Origin: Word): Longint; override; {$IFDEF FPC}overload;{$ENDIF} + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + + constructor Create(const aHandle: TlsfStreamHandle); + end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure lsf_init(const aLibName: String); @@ -239,7 +294,9 @@ begin lsf_ShaderFile_create := Tlsf_ShaderFile_create( LoadProc('lsf_ShaderFile_create')); lsf_ShaderFile_setLogCallback := Tlsf_ShaderFile_setLogCallback( LoadProc('lsf_ShaderFile_setLogCallback')); lsf_ShaderFile_loadFromFile := Tlsf_ShaderFile_loadFromFile( LoadProc('lsf_ShaderFile_loadFromFile')); + lsf_ShaderFile_loadFromFunc := Tlsf_ShaderFile_loadFromFunc( LoadProc('lsf_ShaderFile_loadFromFunc')); lsf_ShaderFile_saveToFile := Tlsf_ShaderFile_saveToFile( LoadProc('lsf_ShaderFile_saveToFile')); + lsf_ShaderFile_saveToFunc := Tlsf_ShaderFile_saveToFunc( LoadProc('lsf_ShaderFile_saveToFunc')); lsf_ShaderFile_getGeneratorNames := Tlsf_ShaderFile_getGeneratorNames( LoadProc('lsf_ShaderFile_getGeneratorNames')); lsf_ShaderFile_destroy := Tlsf_ShaderFile_destroy( LoadProc('lsf_ShaderFile_destroy')); @@ -252,6 +309,12 @@ begin lsf_Generator_generateCode := Tlsf_Generator_generateCode( LoadProc('lsf_Generator_generateCode')); lsf_Generator_destroy := Tlsf_Generator_destroy( LoadProc('lsf_Generator_destroy')); + lsf_Stream_getSize := Tlsf_Stream_getSize( LoadProc('lsf_Stream_getSize')); + lsf_Stream_setSize := Tlsf_Stream_setSize( LoadProc('lsf_Stream_setSize')); + lsf_Stream_seek := Tlsf_Stream_seek( LoadProc('lsf_Stream_seek')); + lsf_Stream_read := Tlsf_Stream_read( LoadProc('lsf_Stream_read')); + lsf_Stream_write := Tlsf_Stream_write( LoadProc('lsf_Stream_write')); + lsf_init_intern := Tlsf_init( LoadProc('lsf_init')); lsf_getLastErrorCode := Tlsf_getLastErrorCode( LoadProc('lsf_getLastErrorCode')); lsf_getLastErrorMsg := Tlsf_getLastErrorMsg( LoadProc('lsf_getLastErrorMsg')); @@ -267,27 +330,128 @@ end; procedure lsf_finish; begin lsf_finish_intern(); - lsf_ShaderFile_create := nil; - lsf_ShaderFile_setLogCallback := nil; - lsf_ShaderFile_loadFromFile := nil; - lsf_ShaderFile_saveToFile := nil; - lsf_ShaderFile_getGeneratorNames := nil; - lsf_ShaderFile_destroy := nil; - lsf_getLastErrorCode := nil; - lsf_getLastErrorMsg := nil; - lsf_getLastErrorTrace := nil; + + lsf_ShaderFile_create := nil; + lsf_ShaderFile_setLogCallback := nil; + lsf_ShaderFile_loadFromFile := nil; + lsf_ShaderFile_loadFromFunc := nil; + lsf_ShaderFile_saveToFile := nil; + lsf_ShaderFile_saveToFunc := nil; + lsf_ShaderFile_getGeneratorNames := nil; + lsf_ShaderFile_destroy := nil; + + lsf_Generator_create := nil; + lsf_Generator_getPropertyNames := nil; + lsf_Generator_getProperty := nil; + lsf_Generator_getPropertyByName := nil; + lsf_Generator_setProperty := nil; + lsf_Generator_setPropertyByName := nil; + lsf_Generator_generateCode := nil; + lsf_Generator_destroy := nil; + + lsf_Stream_getSize := nil; + lsf_Stream_setSize := nil; + lsf_Stream_seek := nil; + lsf_Stream_read := nil; + lsf_Stream_write := nil; + + lsf_init_intern := nil; + lsf_getLastErrorCode := nil; + lsf_getLastErrorMsg := nil; + lsf_getLastErrorTrace := nil; + lsf_finish_intern := nil; + if (libHandle <> InvalidLibHandle) then begin LibClose(libHandle); libHandle := InvalidLibHandle; end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Callbacks From Library//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure LogCallback(const aLogLevel: TlsfLogLevel; const aMsg: PAnsiChar; const aUserArgs: Pointer); stdcall; begin TlsfShaderFile(aUserArgs).LogMsg(aLogLevel, String(aMsg)); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure SaveDataCallback(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer); stdcall; +var + s: TlsfStream; +begin + s := TlsfStream.Create(aHandle); + try + IlsfFileWriter(aUserArgs).SaveStream(aFilename, s); + finally + FreeAndNil(s); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function LoadDataCallback(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer): Boolean; stdcall; +var + s: TlsfStream; +begin + s := TlsfStream.Create(aHandle); + try + result := IlsfFileReader(aUserArgs).LoadStream(aFilename, s); + finally + FreeAndNil(s); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TlsfStream//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TlsfStream.GetSize: Int64; +begin + result := lsf_Stream_getSize(fHandle); + if (result < 0) then + raise TlsfException.Create('error in TlsfStream.GetSize: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TlsfStream.SetSize(NewSize: Longint); +var + err: TlsfErrorCode; +begin + err := lsf_Stream_setSize(fHandle, NewSize); + if (err <> errNone) then + raise TlsfException.Create('error in TlsfStream.SetSize: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TlsfStream.Seek(Offset: Longint; Origin: Word): Longint; +begin + result := lsf_Stream_seek(fHandle, Offset, TlsfSeekOrigin(Origin)); + if (result < 0) then + raise TlsfException.Create('error in TlsfStream.Seek: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TlsfStream.Read(var Buffer; Count: Longint): Longint; +begin + result := lsf_Stream_read(fHandle, @Buffer, Count); + if (result < 0) then + raise TlsfException.Create('error in TlsfStream.Read: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TlsfStream.Write(const Buffer; Count: Longint): Longint; +begin + result := lsf_Stream_write(fHandle, @Buffer, Count); + if (result < 0) then + raise TlsfException.Create('error in TlsfStream.Write: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TlsfStream.Create(const aHandle: TlsfStreamHandle); +begin + inherited Create; + fHandle := aHandle; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TlsfShaderFile//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -306,6 +470,18 @@ begin raise TlsfException.Create('error while loading from file: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TlsfShaderFile.LoadFromFunc(const aFilename: String; const aFileReader: IlsfFileReader); +var + err: TlsfErrorCode; +begin + if not Assigned(aFileReader) then + LoadFromFile(aFilename); + err := lsf_ShaderFile_loadFromFunc(fHandle, PAnsiChar(AnsiString(aFilename)), @LoadDataCallback, Pointer(aFileReader)); + if (err <> errNone) then + raise TlsfException.Create('error while loading from function: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TlsfShaderFile.SaveToFile(const aFilename: String); var @@ -316,6 +492,18 @@ begin raise TlsfException.Create('error while saving to file: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TlsfShaderFile.SaveToFunc(const aFilename: String; const aFileWriter: IlsfFileWriter); +var + err: TlsfErrorCode; +begin + if not Assigned(aFileWriter) then + SaveToFile(aFilename); + err := lsf_ShaderFile_saveToFunc(fHandle, PAnsiChar(AnsiString(aFilename)), @SaveDataCallback, Pointer(aFileWriter)); + if (err <> errNone) then + raise TlsfException.Create('error while saving to function: ' + lsf_getLastErrorMsg(), lsf_getLastErrorCode()); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TlsfShaderFile.Create; var diff --git a/libShaderFile.lpr b/libShaderFile.lpr index 98c3f52..103e48e 100644 --- a/libShaderFile.lpr +++ b/libShaderFile.lpr @@ -3,7 +3,7 @@ library libShaderFile; {$mode objfpc}{$H+} uses - SysUtils, variants, + SysUtils, variants, Classes, uengShaderFile, uengShaderGenerator, uengShaderPart, uengShaderFileGenerics, uengShaderFileTypes; @@ -20,6 +20,7 @@ const LSF_ERR_NOT_INIT = $00000001; LSF_ERR_INVALID_HANDLE_SHADER_FILE = $00000010; LSF_ERR_INVALID_HANDLE_SHADER_GENERATOR = $00000011; + LSF_ERR_INVALID_HANDLE_STREAM = $00000012; LSF_ERR_INVALID_GENERATOR_NAME = $00000020; LSF_ERR_INVALID_PROPERTY_INDEX = $00000021; LSF_ERR_INVALID_PROPERTY_NAME = $00000022; @@ -38,13 +39,23 @@ const LSF_ERR_SHADER_PART = $0000100B; LSF_ERR_UNKNOWN = $FFFFFFFF; + {%H-}LSF_SEEK_BEG = soBeginning; + {%H-}LSF_SEEK_CUR = soCurrent; + {%H-}LSF_SEEK_END = soEnd; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type TlsfErrorCode = Cardinal; TlsfLogLevel = Cardinal; + TlsfSeekOrigin = Cardinal; TlsfShaderFileHandle = Pointer; TlsfShaderGeneratorHandle = Pointer; + TlsfStreamHandle = Pointer; + TlsfShaderFileLogEvent = procedure(const aLogLevel: TlsfLogLevel; const aMsg: PAnsiChar; const aUserArgs: Pointer); stdcall; + TlsfSaveDataCallback = procedure(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer); stdcall; + TlsfLoadDataCallback = function(const aFilename: PAnsiChar; const aHandle: TlsfStreamHandle; const aUserArgs: Pointer): Boolean; stdcall; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //internal types and contstants///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -56,7 +67,9 @@ type TPropertyMap = specialize TutlMap; TShaderGeneratorHandleHashSet = specialize TutlHashSet; TShaderGeneratorHashSet = specialize TutlHashSet; + TStreamHashSet = specialize TutlHashSet; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TShaderGenerator = class(TObject) private fOwner: TShaderFile; @@ -80,6 +93,7 @@ type destructor Destroy; override; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TShaderFile = class(TengShaderFile) private fLogUserArgs: Pointer; @@ -93,7 +107,7 @@ type property LogUserArgs: Pointer read fLogUserArgs write fLogUserArgs; property GeneratorNames: String read fGeneratorNames; - procedure LoadFromFile(const aFilename: String); reintroduce; + procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil); reintroduce; function CreateGenerator(const aName: String): TShaderGenerator; function DestroyGenerator(const aGenerator: TShaderGenerator): TlsfErrorCode; @@ -103,10 +117,31 @@ type end; TShaderFileHashSet = specialize TutlHashSet; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TFileWriterProxy = class(TInterfacedObject, IengShaderFileWriter) + private + fUserArgs: Pointer; + fCallback: TlsfSaveDataCallback; + public + procedure SaveStream(const aFilename: String; const aStream: TStream); + constructor Create(const aCallback: TlsfSaveDataCallback; const aUserArgs: Pointer); + end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TFileReaderProxy = class(TInterfacedObject, IengShaderFileReader) + private + fUserArgs: Pointer; + fCallback: TlsfLoadDataCallback; + public + function LoadStream(const aFilename: String; const aStream: TStream): Boolean; + constructor Create(const aCallback: TlsfLoadDataCallback; const aUserArgs: Pointer); + end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// var ShaderFiles: TShaderFileHashSet = nil; ShaderGenerators: TShaderGeneratorHandleHashSet = nil; + Streams: TStreamHashSet = nil; LastErrorCode: TlsfErrorCode = LSF_ERR_NONE; LastErrorMsg: String = ''; LastErrorTrace: String = ''; @@ -159,51 +194,41 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function CheckIfInitialized: Boolean; begin - try - result := Assigned(ShaderFiles); - if not result then - SetLastError(LSf_ERR_NOT_INIT, 'libShaderFile has not been initialized. call lsf_init before using any other methods.'); - except - on e: Exception do begin - SetLastError(e); - result := false; - end; - end; + result := Assigned(ShaderFiles); + if not result then + SetLastError(LSf_ERR_NOT_INIT, 'libShaderFile has not been initialized. call lsf_init before using any other methods.'); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function CheckShaderFileHandle(const aHandle: TlsfShaderFileHandle): Boolean; begin - try - result := CheckIfInitialized; - if result then begin - result := ShaderFiles.Contains(TShaderFile(aHandle)); - if not result then - SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_FILE, Format('0x%x is not a valid shader file handle', [{%H-}PtrUInt(aHandle)])); - end; - except - on e: Exception do begin - SetLastError(e); - result := false; - end; + result := CheckIfInitialized; + if result then begin + result := ShaderFiles.Contains(TShaderFile(aHandle)); + if not result then + SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_FILE, Format('0x%x is not a valid shader file handle', [{%H-}PtrUInt(aHandle)])); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function CheckShaderGeneratorHandle(const aHandle: TlsfShaderGeneratorHandle): Boolean; begin - try - result := CheckIfInitialized; - if result then begin - result := ShaderGenerators.Contains(TShaderGenerator(aHandle)); - if not result then - SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_GENERATOR, Format('0x%x is not a valid shader generator handle', [{%H-}PtrUInt(aHandle)])); - end; - except - on e: Exception do begin - SetLastError(e); - result := false; - end; + result := CheckIfInitialized; + if result then begin + result := ShaderGenerators.Contains(TShaderGenerator(aHandle)); + if not result then + SetLastError(LSF_ERR_INVALID_HANDLE_SHADER_GENERATOR, Format('0x%x is not a valid shader generator handle', [{%H-}PtrUInt(aHandle)])); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function CheckStreamHandle(const aHandle: TlsfStreamHandle): Boolean; +begin + result := CheckIfInitialized; + if result then begin + result := Streams.Contains(TStream(aHandle)); + if not result then + SetLastError(LSF_ERR_INVALID_HANDLE_STREAM, Format('0x%x is not a valid stream handle', [{%H-}PtrUInt(aHandle)])); end; end; @@ -263,6 +288,23 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function lsf_ShaderFile_loadFromFunc(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar; + const aCallback: TlsfLoadDataCallback; const aUserArgs: Pointer): TlsfErrorCode; stdcall; +begin + try + result := LSF_ERR_NONE; + if not CheckShaderFileHandle(aHandle) + then result := LastErrorCode + else TShaderFile(aHandle).LoadFromFile(aFilename, TFileReaderProxy.Create(aCallback, aUserArgs)); + except + on e: Exception do begin + SetLastError(e); + result := LastErrorCode; + end; + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function lsf_ShaderFile_saveToFile(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar): TlsfErrorCode; stdcall; begin @@ -279,6 +321,23 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function lsf_ShaderFile_saveToFunc(const aHandle: TlsfShaderFileHandle; const aFilename: PAnsiChar; + const aCallback: TlsfSaveDataCallback; const aUserArgs: Pointer): TlsfErrorCode; stdcall; +begin + try + result := LSF_ERR_NONE; + if not CheckShaderFileHandle(aHandle) + then result := LastErrorCode + else TShaderFile(aHandle).SaveToFile(aFilename, TFileWriterProxy.Create(aCallback, aUserArgs)); + except + on e: Exception do begin + SetLastError(e); + result := LastErrorCode; + end; + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function lsf_ShaderFile_getGeneratorNames(const aHandle: TlsfShaderFileHandle): PAnsiChar; stdcall; begin @@ -439,6 +498,83 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Stream//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function lsf_Stream_getSize(const aHandle: TlsfStreamHandle): Integer; stdcall; +begin + try + if CheckStreamHandle(aHandle) + then result := TStream(aHandle).Size + else result := -1; + except + on e: Exception do begin + SetLastError(e); + result := LastErrorCode; + end; + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function lsf_Stream_setSize(const aHandle: TlsfStreamHandle; const aSize: Integer): TlsfErrorCode; stdcall; +begin + try + if CheckStreamHandle(aHandle) + then TStream(aHandle).Size := aSize + else result := LastErrorCode; + except + on e: Exception do begin + SetLastError(e); + result := LastErrorCode; + end; + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function lsf_Stream_seek(const aHandle: TlsfStreamHandle; const aOffset: Integer; const aOrigin: TlsfSeekOrigin): Integer; stdcall; +begin + try + if CheckStreamHandle(aHandle) + then result := TStream(aHandle).Seek(aOrigin, aOrigin) + else result := -1; + except + on e: Exception do begin + SetLastError(e); + result := LastErrorCode; + end; + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function lsf_Stream_read(const aHandle: TlsfStreamHandle; const aBuffer: Pointer; const aSize: Integer): Integer; stdcall; +begin + try + if CheckStreamHandle(aHandle) + then result := TStream(aHandle).Read(aBuffer^, aSize) + else result := -1; + except + on e: Exception do begin + SetLastError(e); + result := LastErrorCode; + end; + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function lsf_Stream_write(const aHandle: TlsfStreamHandle; const aBuffer: Pointer; const aSize: Integer): Integer; stdcall; +begin + try + if CheckStreamHandle(aHandle) + then result := TStream(aHandle).Write(aBuffer^, aSize) + else result := -1; + except + on e: Exception do begin + SetLastError(e); + result := LastErrorCode; + end; + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Global//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -448,6 +584,7 @@ begin result := LSF_ERR_NONE; ShaderFiles := TShaderFileHashSet.Create(true); ShaderGenerators := TShaderGeneratorHandleHashSet.Create(true); + Streams := TStreamHashSet.Create(false); except on e: Exception do begin SetLastError(e); @@ -479,6 +616,7 @@ function lsf_finish: TlsfErrorCode; stdcall; begin try result := LSF_ERR_NONE; + FreeAndNil(Streams); FreeAndNil(ShaderGenerators); FreeAndNil(ShaderFiles); except @@ -493,7 +631,9 @@ exports lsf_ShaderFile_create, lsf_ShaderFile_setLogCallback, lsf_ShaderFile_loadFromFile, + lsf_ShaderFile_loadFromFunc, lsf_ShaderFile_saveToFile, + lsf_ShaderFile_saveToFunc, lsf_ShaderFile_getGeneratorNames, lsf_ShaderFile_destroy, @@ -506,6 +646,12 @@ exports lsf_Generator_generateCode, lsf_Generator_destroy, + lsf_Stream_getSize, + lsf_Stream_setSize, + lsf_Stream_seek, + lsf_Stream_read, + lsf_Stream_write, + lsf_init, lsf_getLastErrorCode, lsf_getLastErrorMsg, @@ -617,11 +763,11 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TShaderFile.LoadFromFile(const aFilename: String); +procedure TShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader); var i: Integer; begin - inherited LoadFromFile(aFilename, nil); + inherited LoadFromFile(aFilename, aFileReader); fGeneratorNames := ''; for i := 0 to GeneratorCount-1 do fGeneratorNames := fGeneratorNames + inherited GeneratorNames[i] + sLineBreak; @@ -678,4 +824,47 @@ begin inherited Destroy; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TFileWriterProxy////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TFileWriterProxy.SaveStream(const aFilename: String; const aStream: TStream); +begin + Streams.Add(aStream); + try + fCallback(PAnsiChar(aFilename), TlsfStreamHandle(aStream), fUserArgs); + finally + Streams.Remove(aStream); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TFileWriterProxy.Create(const aCallback: TlsfSaveDataCallback; const aUserArgs: Pointer); +begin + inherited Create; + fCallback := aCallback; + fUserArgs := aUserArgs; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TFileReaderProxy////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFileReaderProxy.LoadStream(const aFilename: String; const aStream: TStream): Boolean; +begin + Streams.Add(aStream); + try + result := fCallback(PAnsiChar(aFilename), TlsfStreamHandle(aStream), fUserArgs); + finally + Streams.Remove(aStream); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TFileReaderProxy.Create(const aCallback: TlsfLoadDataCallback; const aUserArgs: Pointer); +begin + inherited Create; + fCallback := aCallback; + fUserArgs := aUserArgs; +end; + + end.