Skip to content

Commit

Permalink
新增LibZip支持
Browse files Browse the repository at this point in the history
  • Loading branch information
埃博拉酱 committed Aug 29, 2022
1 parent 2b812a3 commit de68cdc
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 99 deletions.
Binary file removed +MATLAB/+internal/private/WindowsCall.mexw64
Binary file not shown.
146 changes: 146 additions & 0 deletions Windows平台/LipZip.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include "pch.h"
#include "MexAPI.h"
#include <zip.h>
#include "MATLAB异常.h"
zip_int64_t 取文件数目(zip_t* Zip)
{
const zip_int64_t 数目 = zip_get_num_entries(Zip, 0);
if (数目 == -1) [[unlikely]]
throw MATLAB异常(Zip档案无效);
}
API声明(ZipOpen)
{
std::string path = 万能转码<std::string>(std::move(inputs[1]));
int 错误代码;
if (const zip_t* const Zip = zip_open(path.c_str(), ZIP_RDONLY, &错误代码))
outputs[1] = 数组工厂.createScalar((uint64_t)Zip);
else[[unlikely]]
throw MATLAB异常(Zip打开失败, LibZip异常, 错误代码);
}
constexpr zip_flags_t 文件名旗帜 = ZIP_FL_NOCASE | ZIP_FL_ENC_UTF_8;
API声明(ZipNameLocate)
{
zip_t* const Zip = 万能转码<zip_t*>(std::move(inputs[1]));
Array&UTF16 = inputs[2];
const size_t 个数 = UTF16.getNumberOfElements();
TypedArray<zip_int64_t>Locate = 数组工厂.createArray<zip_int64_t>({ 个数 });
const std::unique_ptr<std::string[]>UTF8 = 万能转码<std::unique_ptr<std::string[]>>(std::move(UTF16));
for (size_t a = 0; a < 个数; ++a)
if ((Locate[a] = zip_name_locate(Zip, UTF8[a].c_str(), 文件名旗帜)) == -1) [[unlikely]]
{
const int 错误代码 = zip_get_error(Zip)->zip_err;
if (错误代码 != ZIP_ER_NOENT) [[unlikely]]
throw MATLAB异常(Zip文件名搜索失败, LibZip异常, 错误代码, a);
}
outputs[1] = std::move(Locate);
}
API声明(ZipFopen)
{
zip_t* const Zip = 万能转码<zip_t*>(std::move(inputs[1]));
switch(inputs.size())
{
case 2:
{
const zip_int64_t 文件数目 = 取文件数目(Zip);
TypedArray<uint64_t>返回列表 = 数组工厂.createArray<uint64_t>({ (size_t)文件数目 });
for (zip_int64_t a = 0; a < 文件数目; ++a)
if (!(返回列表[a] = (uint64_t)zip_fopen_index(Zip, a, 0))) [[unlikely]]
throw MATLAB异常(Zip文件打开失败, LibZip异常, zip_get_error(Zip)->zip_err, a);
outputs[1] = std::move(返回列表);
}
break;
case 3:
{
Array& 文件参数 = inputs[2];
const size_t 文件数目 = 文件参数.getNumberOfElements();
TypedArray<uint64_t>返回列表 = 数组工厂.createArray<uint64_t>({ 文件数目 });
switch (文件参数.getType())
{
case ArrayType::CELL:
case ArrayType::CHAR:
case ArrayType::MATLAB_STRING:
{
std::unique_ptr<std::string[]>文件名 = 万能转码<std::unique_ptr<std::string[]>>(std::move(文件参数));
for (size_t a = 0; a < 文件数目; ++a)
if (!(返回列表[a] = (uint64_t)zip_fopen(Zip, 文件名[a].c_str(), 文件名旗帜))) [[unlikely]]
throw MATLAB异常(Zip文件打开失败, LibZip异常, zip_get_error(Zip)->zip_err, a);
}
break;
case ArrayType::UINT64:
{
TypedArray<uint64_t>文件索引(std::move(文件参数));
for (size_t a = 0; a < 文件数目; ++a)
if (!(返回列表[a] = (uint64_t)zip_fopen_index(Zip, 文件索引[a], 0))) [[unlikely]]
throw MATLAB异常(Zip文件打开失败, LibZip异常, zip_get_error(Zip)->zip_err, a);
}
break;
[[unlikely]] default:
throw MATLAB异常(输入参数类型错误, 2);
}
outputs[1] = std::move(返回列表);
}
break;
[[unlikely]] default:
throw MATLAB异常(输入参数数目错误);
}
}
API声明(ZipFread)
{
TypedArray<uint64_t>文件列表(std::move(inputs[1]));
const zip_uint64_t nbytes = 万能转码<uint64_t>(std::move(inputs[2]));
const size_t 文件数目 = 文件列表.getNumberOfElements();
buffer_ptr_t<uint8_t>读入字节 = 数组工厂.createBuffer<uint8_t>(文件数目 * nbytes);
TypedArray<zip_int64_t>实际读数 = 数组工厂.createArray<zip_int64_t>({ 文件数目 });
uint8_t* 写出头 = 读入字节.get();
for (size_t a = 0; a < 文件数目; ++a)
{
zip_file_t* const 文件 = (zip_file_t*)(uint64_t)文件列表[a];
if ((实际读数[a] = zip_fread(文件, 写出头, nbytes)) == -1) [[unlikely]]
throw MATLAB异常(Zip文件读入失败, LibZip异常, zip_file_get_error(文件)->zip_err, a);
写出头 += nbytes;
}
outputs[1] = 数组工厂.createArrayFromBuffer({ nbytes,文件数目 }, std::move(读入字节));
outputs[2] = std::move(实际读数);
}
API声明(ZipFclose)
{
for (uint64_t 文件 : TypedArray<uint64_t>(std::move(inputs[1])))
zip_fclose((zip_file_t*)文件);
}
API声明(ZipDiscard)
{
zip_discard(万能转码<zip_t*>(std::move(inputs[1])));
}
API声明(ZipGetName)
{
zip_t* const Zip = 万能转码<zip_t*>(std::move(inputs[1]));
switch (inputs.size())
{
case 2:
{
const zip_int64_t 文件数目 = 取文件数目(Zip);
std::unique_ptr<const char* []>文件名列表 = std::make_unique_for_overwrite<const char* []>(文件数目);
for (zip_int64_t a = 0; a < 文件数目; ++a)
if (!(文件名列表[a] = zip_get_name(Zip, a, 0))) [[unlikely]]
throw MATLAB异常(Zip文件名获取失败, LibZip异常, zip_get_error(Zip)->zip_err, a);
outputs[1] = 万能转码(文件名列表.get(), 文件数目);
}
case 3:
{
TypedArray<uint64_t> 文件索引(std::move(inputs[2]));
const size_t 文件数目 = 文件索引.getNumberOfElements();
std::unique_ptr<const char* []>文件名列表 = std::make_unique_for_overwrite<const char* []>(文件数目);
for (size_t a = 0; a < 文件数目; ++a)
if (!(文件名列表[a] = zip_get_name(Zip, 文件索引[a], 0))) [[unlikely]]
throw MATLAB异常(Zip文件名获取失败, LibZip异常, zip_get_error(Zip)->zip_err, a);
outputs[1] = 万能转码(文件名列表.get(), 文件数目);
}
break;
[[unlikely]] default:
throw MATLAB异常(输入参数数目错误);
}
}
API声明(ZipGetNumEntries)
{
outputs[1] = 数组工厂.createScalar(取文件数目(万能转码<zip_t*>(std::move(inputs[1]))));
}
12 changes: 12 additions & 0 deletions Windows平台/MATLAB异常.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "pch.h"
#include "MATLAB异常.h"
#include <Mex工具.h>
MATLAB异常::operator StructArray()const noexcept
{
StructArray 返回 = 数组工厂.createStructArray({ 1 }, { "ExceptionType","InnerException","ErrorCode","Index"});
返回[0]["ExceptionType"] = 数组工厂.createScalar<uint8_t>(异常类型);
返回[0]["InnerException"] = 数组工厂.createScalar<uint8_t>(内部异常);
返回[0]["ErrorCode"] = 数组工厂.createScalar(错误代码);
返回[0]["Index"] = 数组工厂.createScalar(第几个);
return 返回;
}
36 changes: 36 additions & 0 deletions Windows平台/MATLAB异常.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once
#include <Mex类型.h>
using namespace matlab::data;
enum MATLAB异常类型 :uint8_t
{
成功,
输入不是字符串,
文件操作失败,
Zip打开失败,
Zip文件名搜索失败,
Zip文件打开失败,
输入参数类型错误,
Zip文件读入失败,
输入参数数目错误,
Zip档案无效,
Zip文件名获取失败,
};
enum 内部异常类型 :uint8_t
{
无,
Win32异常,
LibZip异常,
};
struct MATLAB异常
{
MATLAB异常类型 异常类型 = 成功;
内部异常类型 内部异常 = 无;
int 错误代码 = 0;
size_t 第几个 = 0;
constexpr MATLAB异常() {}
constexpr MATLAB异常(MATLAB异常类型 异常类型) :异常类型(异常类型) {}
constexpr MATLAB异常(MATLAB异常类型 异常类型, size_t 第几个) : 异常类型(异常类型), 第几个(第几个) {}
constexpr MATLAB异常(MATLAB异常类型 异常类型, 内部异常类型 内部异常, int 错误代码) : 异常类型(异常类型), 内部异常(内部异常), 错误代码(错误代码) {}
constexpr MATLAB异常(MATLAB异常类型 异常类型, 内部异常类型 内部异常, int 错误代码, size_t 第几个) : 异常类型(异常类型), 内部异常(内部异常), 错误代码(错误代码), 第几个(第几个) {}
operator StructArray()const noexcept;
};
25 changes: 25 additions & 0 deletions Windows平台/MexAPI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include <Mex工具.h>

//SHFileOperation

#ifdef CopyFile
#undef CopyFile
#endif
API声明(CopyFile);
API声明(Delete);
#ifdef MoveFile
#undef MoveFile
#endif
API声明(MoveFile);

//LibZip

API声明(ZipOpen);
API声明(ZipNameLocate);
API声明(ZipFopen);
API声明(ZipFread);
API声明(ZipFclose);
API声明(ZipDiscard);
API声明(ZipGetName);
API声明(ZipGetNumEntries);
101 changes: 5 additions & 96 deletions Windows平台/MexFunction.cpp
Original file line number Diff line number Diff line change
@@ -1,90 +1,7 @@
#include "pch.h"
#include <Mex工具.h>
#include <shellapi.h>
enum MATLAB异常类型:uint8_t
{
成功,
输入不是字符串,
文件操作失败
};
struct MATLAB异常
{
MATLAB异常类型 异常类型;
int Windows错误代码 = 0;
};
String 字符串转换(Array& 输入)
{
switch (输入.getType())
{
case ArrayType::CHAR:
{
String 返回 = CharArray(std::move(输入)).toUTF16();
返回.push_back(0);
return std::move(返回);
}
case ArrayType::MATLAB_STRING:
{
StringArray 数组(std::move(输入));
String 返回 = std::move(数组[0]);
返回.push_back(0);
const size_t 数组长度 = 数组.getNumberOfElements();
for (uint8_t a = 1; a < 数组长度; ++a)
返回.append(数组[a]).push_back(0);
return std::move(返回);
}
case ArrayType::CELL:
{
CellArray 数组(std::move(输入));
String 返回 = CharArrayRef(数组[0]).toUTF16();
返回.push_back(0);
const size_t 数组长度 = 数组.getNumberOfElements();
for (uint8_t a = 1; a < 数组长度; ++a)
返回.append(CharArrayRef(数组[a]).toUTF16()).push_back(0);
return std::move(返回);
}
default:
throw MATLAB异常{ 输入不是字符串 };
}
}
TypedArray<bool> 执行操作(SHFILEOPSTRUCTW& 操作结构)
{
const int 异常 = SHFileOperationW(&操作结构);
if (异常&&异常!=ERROR_CANCELLED)
throw MATLAB异常{ 文件操作失败,异常 };
else
return 数组工厂.createScalar<bool>(操作结构.fAnyOperationsAborted);
}
TypedArray<bool> CopyMove(ArgumentList& inputs,UINT wFunc)
{
String From = 字符串转换(inputs[1]);
FILEOP_FLAGS Flags = FOF_ALLOWUNDO;
Array& ArrayTo = inputs[2];
if (ArrayTo.getNumberOfElements() > 1 && ArrayTo.getType() != ArrayType::CHAR)
Flags |= FOF_MULTIDESTFILES;
String To = 字符串转换(ArrayTo);
SHFILEOPSTRUCTW 操作结构{ .hwnd = nullptr,.wFunc = wFunc,.pFrom = (wchar_t*)From.c_str() ,.pTo = (wchar_t*)To.c_str(),.fFlags = Flags };
return 执行操作(操作结构);
}
#ifdef CopyFile
#undef CopyFile
#endif
API声明(CopyFile)
{
outputs[1] = CopyMove(inputs, FO_COPY);
}
API声明(Delete)
{
const String From = 字符串转换(inputs[1]);
SHFILEOPSTRUCTW 操作结构{ .hwnd = nullptr,.wFunc = FO_DELETE,.pFrom = (wchar_t*)From.c_str(),.fFlags = FOF_ALLOWUNDO };
outputs[1] = 执行操作(操作结构);
}
#ifdef MoveFile
#undef MoveFile
#endif
API声明(MoveFile)
{
outputs[1] = CopyMove(inputs, FO_MOVE);
}
#include <Mex实现.h>
#include "MATLAB异常.h"
#include "MexAPI.h"
void MexFunction::operator()(ArgumentList& outputs, ArgumentList& inputs)
{
static const StructArray 异常结构 = 数组工厂.createStructArray({ 1 }, { "ExceptionType","WindowsErrorCode" });
Expand All @@ -100,18 +17,10 @@ void MexFunction::operator()(ArgumentList& outputs, ArgumentList& inputs)
}
catch (MATLAB异常 异常)
{
StructArray 返回 = 异常结构;
返回[0]["ExceptionType"] = 数组工厂.createScalar<uint8_t>(异常.异常类型);
返回[0]["WindowsErrorCode"] = 数组工厂.createScalar(异常.Windows错误代码);
outputs[0] = 返回;
outputs[0] = 异常;
异常输出补全(outputs);
return;
}
static const StructArray 成功结构 = [](StructArray 异常结构)
{
异常结构[0]["ExceptionType"] = 数组工厂.createScalar<uint8_t>(成功);
return 异常结构;
}
(异常结构);
static const StructArray 成功结构 = MATLAB异常();
outputs[0] = 成功结构;
}
Loading

0 comments on commit de68cdc

Please sign in to comment.