Extracting compressed archives from within Igor Pro using the CallFunction XOP and libarchive
thomas_braun
The following Igor Pro code uses the CallFunction XOP to uncompress zip and tar files.
#pragma TextEncoding = "UTF-8"
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#include "FCALL_functions"
/// This example shows how the CallFunction-XOP is used to extract an archive.
///
/// The libarchive library is used for extraction (https://github.com/libarchive/libarchive)
///
/// How to run this example:
/// - have some tar or zip archive file ready you want to decompress.
/// (The archive.dll for this example is compiled with zip and tar support only.)
///
/// - Run UncompressFiles(archiveName, targetPath) -- e.g. UncompressFiles("C:\\archive\\data.zip", "C:\\analysis")
static StrConstant UCF_LIBARCHIVE_DLL = "archive.dll"
static StrConstant UCF_ARCHIVE_ENTRYPTR = "root:arcEntry"
static StrConstant UCF_ARCHIVE_BUFFERPTR = "root:arcBuffer"
static StrConstant UCF_ARCHIVE_SIZETR = "root:arcSize"
static StrConstant UCF_ARCHIVE_OFFSETPTR = "root:arcOffset"
static Constant UCF_ARCHIVE_BLOCKSIZE = 10240
static Constant ARCHIVE_EXTRACT_TIME = 0x0004
static Constant ARCHIVE_EXTRACT_PERM = 0x0002
static Constant ARCHIVE_EXTRACT_ACL = 0x0020
static Constant ARCHIVE_EXTRACT_FFLAGS = 0x0040
static Constant ARCHIVE_OK = 0
static Constant ARCHIVE_EOF = 1
static Constant ARCHIVE_WARN = -20
/// @brief Extracts an archive to a target path
/// @param[in] arcFileName full file path to the archive file
/// @param[in] targetPath file path to the location where the archive is decompressed, use "" for current path of Igor process
/// @returns NaN on error, 0 otherwise
Function UncompressFiles(arcFileName, targetPath)
string arcFileName, targetPath
string libHandle
string dllPath, functionName, entryPath, entryTarget
variable numItems, result
UInt64 archiveRead, archiveWrite
Int64 entrySize
string reflectedProcpath = FunctionPath("UncompressFiles")
numItems = ItemsInList(reflectedProcpath, ":")
if(!numItems)
return NaN
endif
reflectedProcpath = RemoveListItem(numItems - 1, reflectedProcpath, ":")
dllPath = reflectedProcpath + UCF_LIBARCHIVE_DLL
if(!IsEmpty(targetPath))
targetPath = ParseFilepath(5, targetPath, "\\", 0, 0)
targetPath = ParseFilepath(2, targetPath, "\\", 0, 0)
endif
UCF_CreateFunctionTemplates()
Make/O/L/U/N=1 $UCF_ARCHIVE_ENTRYPTR, $UCF_ARCHIVE_BUFFERPTR, $UCF_ARCHIVE_SIZETR
Make/O/L/N=1 $UCF_ARCHIVE_OFFSETPTR
libHandle = FCALL_Load(dllPath)
[archiveRead] = UCF_archive_read_new(libHandle)
UCF_archive_read_support_format_all(libHandle, archiveRead)
UCF_archive_read_support_compression_all(libHandle, archiveRead)
[archiveWrite] = UCF_archive_write_disk_new(libHandle)
UCF_archive_write_disk_set_options(libHandle, archiveWrite, ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS)
UCF_archive_write_disk_set_standard_lookup(libHandle, archiveWrite)
result = UCF_archive_read_open_filename(libHandle, archiveRead, arcFileName, UCF_ARCHIVE_BLOCKSIZE)
if(result != ARCHIVE_OK)
printf "Error %d on open file %s\r", result, arcFileName
FCALL_Free(libHandle)
return NaN
endif
for(;;)
result = UCF_archive_read_next_header(libHandle, archiveRead, UCF_ARCHIVE_ENTRYPTR)
if(result == ARCHIVE_EOF)
break
endif
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, archiveRead)
endif
if(result < ARCHIVE_WARN)
FCALL_Free(libHandle)
return NaN
endif
WAVE entry = $UCF_ARCHIVE_ENTRYPTR
entryPath = UCF_archive_entry_pathname(libHandle, entry[0])
entryTarget = UCF_FormatFilePath(targetPath + entryPath)
printf "%s ", ReplaceString("\\\\", entryTarget, "\\")
UCF_archive_entry_set_pathname(libHandle, entry[0], entryTarget)
result = UCF_archive_write_header(libHandle, archiveWrite, entry[0])
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, archiveWrite)
else
[entrySize] = UCF_archive_entry_size(libHandle, entry[0])
result = copy_data(libHandle, archiveRead, archiveWrite, entrySize)
if(result < ARCHIVE_WARN)
FCALL_Free(libHandle)
return NaN
endif
endif
result = UCF_archive_write_finish_entry(libHandle, archiveWrite)
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, archiveRead)
endif
if(result < ARCHIVE_WARN)
FCALL_Free(libHandle)
return NaN
endif
printf "\r"
endfor
UCF_archive_read_close(libHandle, archiveRead)
UCF_archive_read_free(libHandle, archiveRead)
UCF_archive_write_close(libHandle, archiveWrite)
UCF_archive_write_free(libHandle, archiveWrite)
FCALL_Free(libHandle)
return 0
End
/// @brief Copy data for one archived file from the archive to the unpacked file
/// Show some basic progress.
static Function copy_data(String libHandle, UInt64 arcread, UInt64 arcWrite, Int64 entrySize)
variable result, perc, oldperc
string dots
WAVE buffer = $UCF_ARCHIVE_BUFFERPTR
WAVE size = $UCF_ARCHIVE_SIZETR
WAVE offset = $UCF_ARCHIVE_OFFSETPTR
printf "["
for(;;)
result = UCF_archive_read_data_block(libHandle, arcread, UCF_ARCHIVE_BUFFERPTR, UCF_ARCHIVE_SIZETR, UCF_ARCHIVE_OFFSETPTR)
if(result == ARCHIVE_EOF)
dots = PadString("", 100 - oldperc, char2num("."))
printf dots + "]"
return ARCHIVE_OK
endif
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, arcread)
return result
endif
result = UCF_archive_write_data_block(libHandle, arcWrite, buffer[0], size[0], offset[0])
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, arcWrite)
return result
endif
if(entrySize)
perc = trunc(offset[0] * 100 / entrySize)
if(perc != oldperc)
dots = PadString("", perc - oldperc, char2num("."))
printf dots
oldperc = perc
DoUpdate
endif
endif
endfor
End
/// Function wrappers for the library calls
static Function [UInt64 arcHandle] UCF_archive_read_new(String libHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_new"
jsonID = jsonIDList[%$(funcName)]
[arcHandle] = UCF_ParseResultToUInt64(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
return [arcHandle]
End
static Function UCF_archive_read_support_format_all(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_support_format_all"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_support_compression_all(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_support_compression_all"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function [UInt64 arcHandle] UCF_archive_write_disk_new(String libHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_disk_new"
jsonID = jsonIDList[%$(funcName)]
[arcHandle] = UCF_ParseResultToUInt64(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
return [arcHandle]
End
static Function UCF_archive_write_disk_set_options(String libHandle, UInt64 arcHandle, Variable flags)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_disk_set_options"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetVariable(jsonID, "/Parameter/1/value", flags)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_disk_set_standard_lookup(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_disk_set_standard_lookup"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_open_filename(String libHandle, UInt64 arcHandle, String fileName, Variable blockSize)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_open_filename"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetString(jsonID, "/Parameter/1/value", fileName)
JSON_SetVariable(jsonID, "/Parameter/2/value", blockSize)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_next_header(String libHandle, UInt64 arcHandle, String entryPtr)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_next_header"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetString(jsonID, "/Parameter/1/value", entryPtr)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_error_string(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_error_string"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
return UCF_ParseResultToString(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_header(String libHandle, UInt64 arcHandle, UInt64 entry)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_header"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetUInt64(jsonID, "/Parameter/1/value", entry)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function [Int64 entrySize] UCF_archive_entry_size(String libHandle, UInt64 arcEntry)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_entry_size"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcEntry)
[entrySize] = UCF_ParseResultToInt64(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
return [entrySize]
End
static Function UCF_archive_read_data_block(String libHandle, UInt64 arcHandle, String bufferPtr, String sizePtr, String offsetPtr)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_data_block"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetString(jsonID, "/Parameter/1/value", bufferPtr)
JSON_SetString(jsonID, "/Parameter/2/value", sizePtr)
JSON_SetString(jsonID, "/Parameter/3/value", offsetPtr)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_data_block(String libHandle, UInt64 arcHandle, UInt64 buffer, UInt64 size, Int64 offset)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_data_block"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetUInt64(jsonID, "/Parameter/1/value", buffer)
JSON_SetUInt64(jsonID, "/Parameter/2/value", size)
JSON_SetInt64(jsonID, "/Parameter/3/value", offset)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_finish_entry(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_finish_entry"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_close(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_close"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_free(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_free"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_write_close(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_close"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_write_free(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_free"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_entry_pathname(String libHandle, UInt64 arcEntry)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_entry_pathname"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcEntry)
return UCF_ParseResultToString(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_entry_set_pathname(String libHandle, UInt64 arcEntry, String pathName)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_entry_set_pathname"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcEntry)
JSON_SetString(jsonID, "/Parameter/1/value", pathName)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
/// Various support functions
static Function/S UCF_FormatFilePath(fPath)
string fPath
string winFilePath = ParseFilepath(5, fPath, "\\", 0, 0)
return ReplaceString("\\", winFilePath, "\\\\")
End
static Function UCF_ParseResultToNumber(Variable jsonID)
variable result = JSON_GetVariable(jsonID, "/result/value")
JSON_Release(jsonID)
return result
End
static Function/S UCF_ParseResultToString(Variable jsonID)
string result = JSON_GetString(jsonID, "/result/value")
JSON_Release(jsonID)
return result
End
static Function [Int64 result] UCF_ParseResultToInt64(Variable jsonID)
[result] = JSON_GetInt64(jsonID, "/result/value")
JSON_Release(jsonID)
return [result]
End
static Function [UInt64 result] UCF_ParseResultToUInt64(Variable jsonID)
[result] = JSON_GetUInt64(jsonID, "/result/value")
JSON_Release(jsonID)
return [result]
End
threadsafe static Function IsEmpty(str)
string& str
variable len = strlen(str)
return numtype(len) == 2 || len <= 0
End
/// @brief Creates a json template for a specific library function
/// The templates are later used in the wrapper function that execute the call to the library
static Function UCF_AddFunctionTemplate(functionName, paramList, [callFunctionName])
string functionName, paramList, callFunctionName
WAVE jsonIDList
WAVE/T functionNameList
variable size
size = DimSize(jsonIDList, 0)
Redimension/N=(size + 1) jsonIDList, functionNameList
functionNameList[size] = SelectString(ParamIsDefault(callFunctionName), callFunctionName, functionName)
jsonIDList[size] = FCALL_SetupParameterIn(paramList)
SetDimLabel 0, size, $functionName, jsonIDList, functionNameList
End
/// @brief Creates json templates for libarchive functions
static Function UCF_CreateFunctionTemplates()
Make/O/D/N=(0) jsonIDList
Make/O/T/N=(0) functionNameList
// archive_read_new
UCF_AddFunctionTemplate("archive_read_new", "UINT64")
// archive_read_support_format_all
UCF_AddFunctionTemplate("archive_read_support_format_all", "INT32;UINT64")
// archive_read_support_compression_all
UCF_AddFunctionTemplate("archive_read_support_compression_all", "INT32;UINT64")
// archive_write_disk_new
UCF_AddFunctionTemplate("archive_write_disk_new", "UINT64")
// archive_write_disk_set_options
UCF_AddFunctionTemplate("archive_write_disk_set_options", "INT32;UINT64;INT32")
// archive_write_disk_set_standard_lookup
UCF_AddFunctionTemplate("archive_write_disk_set_standard_lookup", "INT32;UINT64")
// archive_read_open_filename
UCF_AddFunctionTemplate("archive_read_open_filename", "INT32;UINT64;STRING;UINT64")
// archive_read_next_header
UCF_AddFunctionTemplate("archive_read_next_header", "INT32;UINT64;WAVEREF")
// archive_error_string
UCF_AddFunctionTemplate("archive_error_string", "STRING;UINT64")
// archive_write_header
UCF_AddFunctionTemplate("archive_write_header", "INT32;UINT64;UINT64")
// archive_entry_size
UCF_AddFunctionTemplate("archive_entry_size", "INT32;UINT64")
// archive_read_data_block
UCF_AddFunctionTemplate("archive_read_data_block", "INT32;UINT64;WAVEREF;WAVEREF;WAVEREF")
// archive_write_data_block
UCF_AddFunctionTemplate("archive_write_data_block", "INT32;UINT64;UINT64;UINT64;INT64")
// archive_write_finish_entry
UCF_AddFunctionTemplate("archive_write_finish_entry", "INT32;UINT64")
// archive_read_close
UCF_AddFunctionTemplate("archive_read_close", "INT32;UINT64")
// archive_read_free
UCF_AddFunctionTemplate("archive_read_free", "INT32;UINT64")
// archive_write_close
UCF_AddFunctionTemplate("archive_write_close", "INT32;UINT64")
// archive_write_free
UCF_AddFunctionTemplate("archive_write_free", "INT32;UINT64")
// archive_entry_pathname
UCF_AddFunctionTemplate("archive_entry_pathname", "STRING;UINT64")
// archive_entry_set_pathname
UCF_AddFunctionTemplate("archive_entry_set_pathname", "INT32;UINT64;STRING")
End
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#include "FCALL_functions"
/// This example shows how the CallFunction-XOP is used to extract an archive.
///
/// The libarchive library is used for extraction (https://github.com/libarchive/libarchive)
///
/// How to run this example:
/// - have some tar or zip archive file ready you want to decompress.
/// (The archive.dll for this example is compiled with zip and tar support only.)
///
/// - Run UncompressFiles(archiveName, targetPath) -- e.g. UncompressFiles("C:\\archive\\data.zip", "C:\\analysis")
static StrConstant UCF_LIBARCHIVE_DLL = "archive.dll"
static StrConstant UCF_ARCHIVE_ENTRYPTR = "root:arcEntry"
static StrConstant UCF_ARCHIVE_BUFFERPTR = "root:arcBuffer"
static StrConstant UCF_ARCHIVE_SIZETR = "root:arcSize"
static StrConstant UCF_ARCHIVE_OFFSETPTR = "root:arcOffset"
static Constant UCF_ARCHIVE_BLOCKSIZE = 10240
static Constant ARCHIVE_EXTRACT_TIME = 0x0004
static Constant ARCHIVE_EXTRACT_PERM = 0x0002
static Constant ARCHIVE_EXTRACT_ACL = 0x0020
static Constant ARCHIVE_EXTRACT_FFLAGS = 0x0040
static Constant ARCHIVE_OK = 0
static Constant ARCHIVE_EOF = 1
static Constant ARCHIVE_WARN = -20
/// @brief Extracts an archive to a target path
/// @param[in] arcFileName full file path to the archive file
/// @param[in] targetPath file path to the location where the archive is decompressed, use "" for current path of Igor process
/// @returns NaN on error, 0 otherwise
Function UncompressFiles(arcFileName, targetPath)
string arcFileName, targetPath
string libHandle
string dllPath, functionName, entryPath, entryTarget
variable numItems, result
UInt64 archiveRead, archiveWrite
Int64 entrySize
string reflectedProcpath = FunctionPath("UncompressFiles")
numItems = ItemsInList(reflectedProcpath, ":")
if(!numItems)
return NaN
endif
reflectedProcpath = RemoveListItem(numItems - 1, reflectedProcpath, ":")
dllPath = reflectedProcpath + UCF_LIBARCHIVE_DLL
if(!IsEmpty(targetPath))
targetPath = ParseFilepath(5, targetPath, "\\", 0, 0)
targetPath = ParseFilepath(2, targetPath, "\\", 0, 0)
endif
UCF_CreateFunctionTemplates()
Make/O/L/U/N=1 $UCF_ARCHIVE_ENTRYPTR, $UCF_ARCHIVE_BUFFERPTR, $UCF_ARCHIVE_SIZETR
Make/O/L/N=1 $UCF_ARCHIVE_OFFSETPTR
libHandle = FCALL_Load(dllPath)
[archiveRead] = UCF_archive_read_new(libHandle)
UCF_archive_read_support_format_all(libHandle, archiveRead)
UCF_archive_read_support_compression_all(libHandle, archiveRead)
[archiveWrite] = UCF_archive_write_disk_new(libHandle)
UCF_archive_write_disk_set_options(libHandle, archiveWrite, ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS)
UCF_archive_write_disk_set_standard_lookup(libHandle, archiveWrite)
result = UCF_archive_read_open_filename(libHandle, archiveRead, arcFileName, UCF_ARCHIVE_BLOCKSIZE)
if(result != ARCHIVE_OK)
printf "Error %d on open file %s\r", result, arcFileName
FCALL_Free(libHandle)
return NaN
endif
for(;;)
result = UCF_archive_read_next_header(libHandle, archiveRead, UCF_ARCHIVE_ENTRYPTR)
if(result == ARCHIVE_EOF)
break
endif
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, archiveRead)
endif
if(result < ARCHIVE_WARN)
FCALL_Free(libHandle)
return NaN
endif
WAVE entry = $UCF_ARCHIVE_ENTRYPTR
entryPath = UCF_archive_entry_pathname(libHandle, entry[0])
entryTarget = UCF_FormatFilePath(targetPath + entryPath)
printf "%s ", ReplaceString("\\\\", entryTarget, "\\")
UCF_archive_entry_set_pathname(libHandle, entry[0], entryTarget)
result = UCF_archive_write_header(libHandle, archiveWrite, entry[0])
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, archiveWrite)
else
[entrySize] = UCF_archive_entry_size(libHandle, entry[0])
result = copy_data(libHandle, archiveRead, archiveWrite, entrySize)
if(result < ARCHIVE_WARN)
FCALL_Free(libHandle)
return NaN
endif
endif
result = UCF_archive_write_finish_entry(libHandle, archiveWrite)
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, archiveRead)
endif
if(result < ARCHIVE_WARN)
FCALL_Free(libHandle)
return NaN
endif
printf "\r"
endfor
UCF_archive_read_close(libHandle, archiveRead)
UCF_archive_read_free(libHandle, archiveRead)
UCF_archive_write_close(libHandle, archiveWrite)
UCF_archive_write_free(libHandle, archiveWrite)
FCALL_Free(libHandle)
return 0
End
/// @brief Copy data for one archived file from the archive to the unpacked file
/// Show some basic progress.
static Function copy_data(String libHandle, UInt64 arcread, UInt64 arcWrite, Int64 entrySize)
variable result, perc, oldperc
string dots
WAVE buffer = $UCF_ARCHIVE_BUFFERPTR
WAVE size = $UCF_ARCHIVE_SIZETR
WAVE offset = $UCF_ARCHIVE_OFFSETPTR
printf "["
for(;;)
result = UCF_archive_read_data_block(libHandle, arcread, UCF_ARCHIVE_BUFFERPTR, UCF_ARCHIVE_SIZETR, UCF_ARCHIVE_OFFSETPTR)
if(result == ARCHIVE_EOF)
dots = PadString("", 100 - oldperc, char2num("."))
printf dots + "]"
return ARCHIVE_OK
endif
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, arcread)
return result
endif
result = UCF_archive_write_data_block(libHandle, arcWrite, buffer[0], size[0], offset[0])
if(result < ARCHIVE_OK)
print "error: " + UCF_archive_error_string(libHandle, arcWrite)
return result
endif
if(entrySize)
perc = trunc(offset[0] * 100 / entrySize)
if(perc != oldperc)
dots = PadString("", perc - oldperc, char2num("."))
printf dots
oldperc = perc
DoUpdate
endif
endif
endfor
End
/// Function wrappers for the library calls
static Function [UInt64 arcHandle] UCF_archive_read_new(String libHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_new"
jsonID = jsonIDList[%$(funcName)]
[arcHandle] = UCF_ParseResultToUInt64(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
return [arcHandle]
End
static Function UCF_archive_read_support_format_all(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_support_format_all"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_support_compression_all(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_support_compression_all"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function [UInt64 arcHandle] UCF_archive_write_disk_new(String libHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_disk_new"
jsonID = jsonIDList[%$(funcName)]
[arcHandle] = UCF_ParseResultToUInt64(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
return [arcHandle]
End
static Function UCF_archive_write_disk_set_options(String libHandle, UInt64 arcHandle, Variable flags)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_disk_set_options"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetVariable(jsonID, "/Parameter/1/value", flags)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_disk_set_standard_lookup(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_disk_set_standard_lookup"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_open_filename(String libHandle, UInt64 arcHandle, String fileName, Variable blockSize)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_open_filename"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetString(jsonID, "/Parameter/1/value", fileName)
JSON_SetVariable(jsonID, "/Parameter/2/value", blockSize)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_next_header(String libHandle, UInt64 arcHandle, String entryPtr)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_next_header"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetString(jsonID, "/Parameter/1/value", entryPtr)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_error_string(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_error_string"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
return UCF_ParseResultToString(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_header(String libHandle, UInt64 arcHandle, UInt64 entry)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_header"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetUInt64(jsonID, "/Parameter/1/value", entry)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function [Int64 entrySize] UCF_archive_entry_size(String libHandle, UInt64 arcEntry)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_entry_size"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcEntry)
[entrySize] = UCF_ParseResultToInt64(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
return [entrySize]
End
static Function UCF_archive_read_data_block(String libHandle, UInt64 arcHandle, String bufferPtr, String sizePtr, String offsetPtr)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_data_block"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetString(jsonID, "/Parameter/1/value", bufferPtr)
JSON_SetString(jsonID, "/Parameter/2/value", sizePtr)
JSON_SetString(jsonID, "/Parameter/3/value", offsetPtr)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_data_block(String libHandle, UInt64 arcHandle, UInt64 buffer, UInt64 size, Int64 offset)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_data_block"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_SetUInt64(jsonID, "/Parameter/1/value", buffer)
JSON_SetUInt64(jsonID, "/Parameter/2/value", size)
JSON_SetInt64(jsonID, "/Parameter/3/value", offset)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_write_finish_entry(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_finish_entry"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
return UCF_ParseResultToNumber(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_close(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_close"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_read_free(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_read_free"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_write_close(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_close"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_write_free(String libHandle, UInt64 arcHandle)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_write_free"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcHandle)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function/S UCF_archive_entry_pathname(String libHandle, UInt64 arcEntry)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_entry_pathname"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcEntry)
return UCF_ParseResultToString(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
static Function UCF_archive_entry_set_pathname(String libHandle, UInt64 arcEntry, String pathName)
variable jsonID
WAVE jsonIDList
WAVE/T functionNameList
string funcName = "archive_entry_set_pathname"
jsonID = jsonIDList[%$(funcName)]
JSON_SetUInt64(jsonID, "/Parameter/0/value", arcEntry)
JSON_SetString(jsonID, "/Parameter/1/value", pathName)
JSON_Release(FCALL_Call(libHandle, functionNameList[%$(funcName)], jsonID))
End
/// Various support functions
static Function/S UCF_FormatFilePath(fPath)
string fPath
string winFilePath = ParseFilepath(5, fPath, "\\", 0, 0)
return ReplaceString("\\", winFilePath, "\\\\")
End
static Function UCF_ParseResultToNumber(Variable jsonID)
variable result = JSON_GetVariable(jsonID, "/result/value")
JSON_Release(jsonID)
return result
End
static Function/S UCF_ParseResultToString(Variable jsonID)
string result = JSON_GetString(jsonID, "/result/value")
JSON_Release(jsonID)
return result
End
static Function [Int64 result] UCF_ParseResultToInt64(Variable jsonID)
[result] = JSON_GetInt64(jsonID, "/result/value")
JSON_Release(jsonID)
return [result]
End
static Function [UInt64 result] UCF_ParseResultToUInt64(Variable jsonID)
[result] = JSON_GetUInt64(jsonID, "/result/value")
JSON_Release(jsonID)
return [result]
End
threadsafe static Function IsEmpty(str)
string& str
variable len = strlen(str)
return numtype(len) == 2 || len <= 0
End
/// @brief Creates a json template for a specific library function
/// The templates are later used in the wrapper function that execute the call to the library
static Function UCF_AddFunctionTemplate(functionName, paramList, [callFunctionName])
string functionName, paramList, callFunctionName
WAVE jsonIDList
WAVE/T functionNameList
variable size
size = DimSize(jsonIDList, 0)
Redimension/N=(size + 1) jsonIDList, functionNameList
functionNameList[size] = SelectString(ParamIsDefault(callFunctionName), callFunctionName, functionName)
jsonIDList[size] = FCALL_SetupParameterIn(paramList)
SetDimLabel 0, size, $functionName, jsonIDList, functionNameList
End
/// @brief Creates json templates for libarchive functions
static Function UCF_CreateFunctionTemplates()
Make/O/D/N=(0) jsonIDList
Make/O/T/N=(0) functionNameList
// archive_read_new
UCF_AddFunctionTemplate("archive_read_new", "UINT64")
// archive_read_support_format_all
UCF_AddFunctionTemplate("archive_read_support_format_all", "INT32;UINT64")
// archive_read_support_compression_all
UCF_AddFunctionTemplate("archive_read_support_compression_all", "INT32;UINT64")
// archive_write_disk_new
UCF_AddFunctionTemplate("archive_write_disk_new", "UINT64")
// archive_write_disk_set_options
UCF_AddFunctionTemplate("archive_write_disk_set_options", "INT32;UINT64;INT32")
// archive_write_disk_set_standard_lookup
UCF_AddFunctionTemplate("archive_write_disk_set_standard_lookup", "INT32;UINT64")
// archive_read_open_filename
UCF_AddFunctionTemplate("archive_read_open_filename", "INT32;UINT64;STRING;UINT64")
// archive_read_next_header
UCF_AddFunctionTemplate("archive_read_next_header", "INT32;UINT64;WAVEREF")
// archive_error_string
UCF_AddFunctionTemplate("archive_error_string", "STRING;UINT64")
// archive_write_header
UCF_AddFunctionTemplate("archive_write_header", "INT32;UINT64;UINT64")
// archive_entry_size
UCF_AddFunctionTemplate("archive_entry_size", "INT32;UINT64")
// archive_read_data_block
UCF_AddFunctionTemplate("archive_read_data_block", "INT32;UINT64;WAVEREF;WAVEREF;WAVEREF")
// archive_write_data_block
UCF_AddFunctionTemplate("archive_write_data_block", "INT32;UINT64;UINT64;UINT64;INT64")
// archive_write_finish_entry
UCF_AddFunctionTemplate("archive_write_finish_entry", "INT32;UINT64")
// archive_read_close
UCF_AddFunctionTemplate("archive_read_close", "INT32;UINT64")
// archive_read_free
UCF_AddFunctionTemplate("archive_read_free", "INT32;UINT64")
// archive_write_close
UCF_AddFunctionTemplate("archive_write_close", "INT32;UINT64")
// archive_write_free
UCF_AddFunctionTemplate("archive_write_free", "INT32;UINT64")
// archive_entry_pathname
UCF_AddFunctionTemplate("archive_entry_pathname", "STRING;UINT64")
// archive_entry_set_pathname
UCF_AddFunctionTemplate("archive_entry_set_pathname", "INT32;UINT64;STRING")
End
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More