This libarchive function, the role is to extract the compressed package to the object.
mdfunc will libarchive api initialized to global variables, compared to the common dll packaging method, it is more efficient.
Code: Select all
archive_init() {
global
LoadLibraryW(A_AhkDir "\libcrypto-1_1-x64.dll")
archive_mod := LoadLibraryW(A_AhkDir "\libarchive.dll")
archive_read_new := mdfunc(GetProcAddress(archive_mod, "archive_read_new"), 8)
archive_read_free := mdfunc(GetProcAddress(archive_mod, "archive_read_free"), [8, 5])
archive_read_close := mdfunc(GetProcAddress(archive_mod, "archive_read_close"), [8, 5])
archive_read_support_filter_all := mdfunc(GetProcAddress(archive_mod, "archive_read_support_filter_all"), [8, 8])
archive_read_support_format_all := mdfunc(GetProcAddress(archive_mod, "archive_read_support_format_all"), [8, 8])
archive_read_open_memory := mdfunc(GetProcAddress(archive_mod, "archive_read_open_memory"), [8, 8, 8, 5])
archive_read_open_filename_w := mdfunc(GetProcAddress(archive_mod, "archive_read_open_filename_w"), [8, 11, 5, 5])
archive_read_data_skip := mdfunc(GetProcAddress(archive_mod, "archive_read_data_skip"), [8, 5])
archive_entry_filetype := mdfunc(GetProcAddress(archive_mod, "archive_entry_filetype"), [8, 5])
archive_entry_size := mdfunc(GetProcAddress(archive_mod, "archive_entry_size"), [8, 5])
archive_read_data := mdfunc(GetProcAddress(archive_mod, "archive_read_data"), [8, 8, 8, 8])
archive_read_next_header := mdfunc(GetProcAddress(archive_mod, "archive_read_next_header"), [8, 8, 5])
archive_entry_pathname_w := DynaCall(GetProcAddress(archive_mod, "archive_entry_pathname_w"), 'w==t')
}
archive(pt) {
static _ := archive_init()
a := archive_read_new()
archive_read_support_filter_all(a)
archive_read_support_format_all(a)
if 0 = (pt is Buffer
? archive_read_open_memory(a, pt.ptr, pt.size)
: archive_read_open_filename_w(a, pt, 10240))
{
t := UMap()
entry := 0
ptr := GetVar(entry)
while 0 = archive_read_next_header(a, ptr)
{
switch archive_entry_filetype(entry)
{
case 0x8000:
sz := archive_entry_size(entry)
buf := Buffer(sz)
archive_read_data(a, buf.ptr, sz)
t[archive_entry_pathname_w(entry)] := buf
case 0x4000: ; dir
t[archive_entry_pathname_w(entry)] := 0
}
}
}
archive_read_close(a)
archive_read_free(a)
return t ?? 0
}
I used the same method to package sqlite3. the old method to read a 70,000 rows * 8 columns of the database to the object, it takes 1.9 seconds. The new method takes only 0.6 seconds.
I would very much like to start more discussion on mdfunc. Are there more similar ways of using it or what are its drawbacks and what are the things to be aware of.
[Mod action: Moved topic from “AutoHotkey Development” which is for discussing the future of the AutoHotkey language itself.]