mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
Update libaaf to v1.0-1-gdef35bf
This commit is contained in:
parent
2b1349ffc2
commit
bd937366fd
38 changed files with 9153 additions and 7831 deletions
716
libs/aaf/utils.c
716
libs/aaf/utils.c
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2017-2023 Adrien Gesta-Fline
|
||||
* Copyright (C) 2017-2024 Adrien Gesta-Fline
|
||||
*
|
||||
* This file is part of libAAF.
|
||||
*
|
||||
|
|
@ -18,104 +18,107 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/limits.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <mntent.h>
|
||||
#include <unistd.h> /* access() */
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/syslimits.h>
|
||||
#include <unistd.h> /* access() */
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||
#include <limits.h>
|
||||
#define R_OK 4 /* Test for read permission. */
|
||||
#define W_OK 2 /* Test for write permission. */
|
||||
#define F_OK 0 /* Test for existence. */
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h> // access()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "aaf/utils.h"
|
||||
|
||||
#define BUILD_PATH_DEFAULT_BUF_SIZE 1024
|
||||
|
||||
aafPosition_t
|
||||
laaf_util_converUnit (aafPosition_t value, aafRational_t* valueEditRate, aafRational_t* destEditRate)
|
||||
static int
|
||||
utf8CodeLen (const uint16_t* u16Code);
|
||||
static int
|
||||
utf16CodeLen (const uint16_t* u16Code);
|
||||
static int
|
||||
utf16CodeToUTF8 (const uint16_t* u16Code, char* u8Code, int* u16Len, int* u8Len);
|
||||
static long
|
||||
utf8strLen (const uint16_t* u16str);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
wchar_t*
|
||||
laaf_util_windows_utf8toutf16 (const char* str)
|
||||
{
|
||||
if (!valueEditRate || !destEditRate) {
|
||||
return value;
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (valueEditRate->numerator == destEditRate->numerator &&
|
||||
valueEditRate->denominator == destEditRate->denominator) {
|
||||
/* same rate, no conversion */
|
||||
return value;
|
||||
int needed = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
|
||||
|
||||
if (needed == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double valueEditRateFloat = ((valueEditRate->denominator == 0) ? 0.0 : ((float)valueEditRate->numerator / valueEditRate->denominator));
|
||||
double destEditRateFloat = ((destEditRate->denominator == 0) ? 0.0 : ((float)destEditRate->numerator / destEditRate->denominator));
|
||||
wchar_t* wbuf = malloc ((size_t)needed * sizeof (wchar_t));
|
||||
|
||||
if (valueEditRateFloat == 0) {
|
||||
return 0;
|
||||
if (!wbuf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value * (destEditRateFloat / valueEditRateFloat);
|
||||
int rc = MultiByteToWideChar (CP_UTF8, 0, str, -1, wbuf, needed);
|
||||
|
||||
if (rc == 0) {
|
||||
free (wbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wbuf;
|
||||
}
|
||||
|
||||
char*
|
||||
laaf_util_wstr2str (const wchar_t* wstr)
|
||||
laaf_util_windows_utf16toutf8 (const wchar_t* wstr)
|
||||
{
|
||||
if (wstr == NULL) {
|
||||
if (!wstr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t strsz = wcslen (wstr) + 1;
|
||||
char* str = malloc (strsz);
|
||||
int needed = WideCharToMultiByte (CP_UTF8, 0, wstr, -1, NULL, 0, 0, 0);
|
||||
|
||||
if (str == NULL) {
|
||||
// error( "Could not allocate memory : %s", strerror(errno) );
|
||||
if (needed == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rc = snprintf (str, strsz, "%ls", wstr);
|
||||
char* buf = malloc ((size_t)needed * sizeof (char));
|
||||
|
||||
if (rc < 0 || (unsigned)rc >= strsz) {
|
||||
// error( "Failed converting wide char str to byte char str%s", (reqlen < 0) ? " : encoding error" : "" );
|
||||
free (str);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
int rc = WideCharToMultiByte (CP_UTF8, 0, wstr, -1, buf, needed, 0, 0);
|
||||
|
||||
if (rc == 0) {
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
wchar_t*
|
||||
laaf_util_str2wstr (const char* str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t strsz = strlen (str) + 1;
|
||||
wchar_t* wstr = malloc (strsz * sizeof (wchar_t));
|
||||
|
||||
if (str == NULL) {
|
||||
// error( "Could not allocate memory : %s", strerror(errno) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rc = swprintf (wstr, strsz, L"%" WPRIs, str);
|
||||
|
||||
if (rc < 0 || (unsigned)rc >= strsz) {
|
||||
// error( "Failed converting byte char str to wide char str%s", (reqlen < 0) ? " : encoding error" : "" );
|
||||
free (wstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wstr;
|
||||
}
|
||||
|
||||
int
|
||||
laaf_util_wstr_contains_nonlatin (const wchar_t* str)
|
||||
{
|
||||
for (size_t i = 0; str[i] != 0x0000; i++) {
|
||||
/* if char is out of the Basic Latin range */
|
||||
if (str[i] > 0xff) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
char*
|
||||
laaf_util_clean_filename (char* fname)
|
||||
|
|
@ -124,62 +127,52 @@ laaf_util_clean_filename (char* fname)
|
|||
* sanitize file/dir name
|
||||
* https://stackoverflow.com/a/31976060
|
||||
*/
|
||||
size_t len = strlen (fname);
|
||||
if (!fname) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
unsigned char c = fname[i];
|
||||
char* p = fname;
|
||||
|
||||
if (c == '/' ||
|
||||
c == '<' ||
|
||||
c == '>' ||
|
||||
c == ':' ||
|
||||
c == '"' ||
|
||||
c == '|' ||
|
||||
c == '?' ||
|
||||
c == '*' ||
|
||||
c == '\\' ||
|
||||
(c > 0 && c < 0x20)) {
|
||||
fname[i] = '_';
|
||||
while (*p) {
|
||||
if (*p == '/' ||
|
||||
*p == '<' ||
|
||||
*p == '>' ||
|
||||
*p == ':' ||
|
||||
*p == '"' ||
|
||||
*p == '|' ||
|
||||
*p == '?' ||
|
||||
*p == '*' ||
|
||||
*p == '\\' ||
|
||||
(*p > 0 && *p < 0x20)) {
|
||||
*p = '_';
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
/* windows filenames can't end with ' ' or '.' */
|
||||
for (int i = len - 1; i > 0; i--) {
|
||||
char c = fname[i];
|
||||
if (c != ' ' && c != '.') {
|
||||
break;
|
||||
}
|
||||
fname[i] = '_';
|
||||
|
||||
p = fname + strlen (fname) - 1;
|
||||
|
||||
while (*p && (*p == ' ' || *p == '.')) {
|
||||
*p = '\0';
|
||||
p--;
|
||||
}
|
||||
|
||||
if (*fname == '\0')
|
||||
return NULL;
|
||||
|
||||
return fname;
|
||||
}
|
||||
|
||||
const char*
|
||||
laaf_util_fop_get_file (const char* filepath)
|
||||
{
|
||||
if (filepath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* end = filepath + strlen (filepath);
|
||||
|
||||
while (end > filepath && !IS_DIR_SEP (*end)) {
|
||||
--end;
|
||||
}
|
||||
|
||||
return (IS_DIR_SEP (*end)) ? end + 1 : end;
|
||||
}
|
||||
|
||||
int
|
||||
laaf_util_fop_is_wstr_fileext (const wchar_t* filepath, const wchar_t* ext)
|
||||
laaf_util_is_fileext (const char* filepath, const char* ext)
|
||||
{
|
||||
if (filepath == NULL) {
|
||||
if (!filepath || !ext) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const wchar_t* end = filepath + wcslen (filepath);
|
||||
size_t extlen = 0;
|
||||
const char* end = filepath + strlen (filepath);
|
||||
size_t extlen = 0;
|
||||
|
||||
while (end > filepath && (*end) != '.') {
|
||||
--end;
|
||||
|
|
@ -191,14 +184,11 @@ laaf_util_fop_is_wstr_fileext (const wchar_t* filepath, const wchar_t* ext)
|
|||
extlen--;
|
||||
}
|
||||
|
||||
if (extlen != wcslen (ext)) {
|
||||
if (!extlen || extlen != strlen (ext)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// printf(" end: %ls ext: %ls\n", end, ext );
|
||||
|
||||
for (size_t i = 0; i < extlen; i++) {
|
||||
// printf("end: %c != %c\n", *(end+i), *(ext+i));
|
||||
if (tolower (*(end + i)) != tolower (*(ext + i))) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -212,7 +202,7 @@ laaf_util_build_path (const char* sep, const char* first, ...)
|
|||
{
|
||||
char* str = malloc (BUILD_PATH_DEFAULT_BUF_SIZE);
|
||||
|
||||
if (str == NULL) {
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -232,13 +222,13 @@ laaf_util_build_path (const char* sep, const char* first, ...)
|
|||
const char* arg = first;
|
||||
|
||||
do {
|
||||
int arglen = strlen (arg);
|
||||
int argstart = 0;
|
||||
int has_leading_sep = 0;
|
||||
size_t arglen = strlen (arg);
|
||||
size_t argstart = 0;
|
||||
int has_leading_sep = 0;
|
||||
|
||||
/* trim leading DIR_SEP */
|
||||
for (int i = 0; arg[i] != 0x00; i++) {
|
||||
if (IS_DIR_SEP (arg[i])) {
|
||||
if (IS_ANY_DIR_SEP (arg[i])) {
|
||||
has_leading_sep = 1;
|
||||
argstart++;
|
||||
} else {
|
||||
|
|
@ -247,39 +237,41 @@ laaf_util_build_path (const char* sep, const char* first, ...)
|
|||
}
|
||||
|
||||
/* trim trailing DIR_SEP */
|
||||
for (int i = arglen - 1; i >= argstart; i--) {
|
||||
if (IS_DIR_SEP (arg[i])) {
|
||||
for (size_t i = arglen - 1; i >= argstart; i--) {
|
||||
if (IS_ANY_DIR_SEP (arg[i])) {
|
||||
arglen--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO ? */
|
||||
if (element_count == 0 && has_leading_sep) {
|
||||
} else {
|
||||
}
|
||||
|
||||
size_t reqlen = snprintf (NULL, 0, "%.*s", arglen - argstart, arg + argstart) + 1;
|
||||
size_t reqlen = (arglen - argstart) + 2;
|
||||
|
||||
if (offset + reqlen >= len) {
|
||||
reqlen = ((offset + reqlen) > (len + BUILD_PATH_DEFAULT_BUF_SIZE)) ? (offset + reqlen) : (len + BUILD_PATH_DEFAULT_BUF_SIZE);
|
||||
reqlen = ((offset + reqlen) > (len + BUILD_PATH_DEFAULT_BUF_SIZE)) ? (reqlen) : (len + BUILD_PATH_DEFAULT_BUF_SIZE);
|
||||
|
||||
char* tmp = realloc (str, (offset + reqlen));
|
||||
|
||||
if (tmp) {
|
||||
str = tmp;
|
||||
len = (offset + reqlen);
|
||||
} else {
|
||||
if (!tmp) {
|
||||
free (str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = tmp;
|
||||
len = (offset + reqlen);
|
||||
}
|
||||
|
||||
offset += snprintf (str + offset, len - offset, "%s%.*s",
|
||||
((element_count == 0 && has_leading_sep) || (element_count > 0)) ? sep : "",
|
||||
arglen - argstart,
|
||||
arg + argstart);
|
||||
int written = snprintf (str + offset, len - offset, "%s%.*s",
|
||||
((element_count == 0 && has_leading_sep) || (element_count > 0)) ? sep : "",
|
||||
(uint32_t) (arglen - argstart),
|
||||
arg + argstart);
|
||||
|
||||
if (written < 0 || (size_t)written >= (len - offset)) {
|
||||
free (str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset += (size_t)written;
|
||||
|
||||
element_count++;
|
||||
|
||||
|
|
@ -287,29 +279,183 @@ laaf_util_build_path (const char* sep, const char* first, ...)
|
|||
|
||||
va_end (args);
|
||||
|
||||
/* do not mix between different dirseps and removes any consecutive dirseps */
|
||||
char* i = str;
|
||||
char* o = str;
|
||||
int dirseppassed = 0;
|
||||
while (*i) {
|
||||
if (!dirseppassed && IS_ANY_DIR_SEP (*i)) {
|
||||
*o = *sep;
|
||||
o++;
|
||||
dirseppassed = 1;
|
||||
} else if (!IS_ANY_DIR_SEP (*i)) {
|
||||
dirseppassed = 0;
|
||||
*o = *i;
|
||||
o++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*o = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* format, ...)
|
||||
char*
|
||||
laaf_util_relative_path (const char* filepath, const char* refpath)
|
||||
{
|
||||
int tmpsize = 0;
|
||||
if (!filepath || !refpath || filepath[0] == '\0' || refpath[0] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fprintf( stderr, "%s\n", filepath );
|
||||
// fprintf( stderr, "%s\n", refpath );
|
||||
|
||||
int isWindowsPath = 0;
|
||||
int aWindowsPath = 0;
|
||||
int bWindowsPath = 0;
|
||||
|
||||
char* relpath = NULL;
|
||||
|
||||
if (filepath[0] != '\0' && isalpha (filepath[0]) && filepath[1] == ':') {
|
||||
aWindowsPath = 1;
|
||||
}
|
||||
|
||||
if (refpath[0] != '\0' && isalpha (refpath[0]) && refpath[1] == ':') {
|
||||
bWindowsPath = 1;
|
||||
}
|
||||
|
||||
isWindowsPath = (aWindowsPath + bWindowsPath);
|
||||
|
||||
if (isWindowsPath == 1) {
|
||||
// fprintf( stderr, "Trying to make a relative path out of a windows path and a non-windows path\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (isWindowsPath == 2) {
|
||||
if (tolower (filepath[0]) != tolower (refpath[0])) {
|
||||
// fprintf( stderr, "Both paths target different drives\n" );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int winDriveLetterOffset = isWindowsPath;
|
||||
|
||||
if (strncmp (filepath + winDriveLetterOffset, refpath + winDriveLetterOffset, strlen (refpath)) == 0) {
|
||||
relpath = laaf_util_build_path ("/", "./", filepath + strlen (refpath), NULL);
|
||||
return relpath;
|
||||
}
|
||||
|
||||
char* _filepath = laaf_util_build_path ("/", filepath, NULL);
|
||||
char* _refpath = laaf_util_build_path ("/", refpath, "/", NULL); /* ensures there is always a trailing '/' */
|
||||
|
||||
if (!_filepath || !_refpath) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* parents = NULL;
|
||||
size_t parentsLen = 0;
|
||||
size_t parentsOffset = 0;
|
||||
|
||||
char* p = _refpath + strlen (_refpath);
|
||||
|
||||
while (p > (_refpath + winDriveLetterOffset)) {
|
||||
while (p > (_refpath + winDriveLetterOffset) && !IS_DIR_SEP (*p)) {
|
||||
*p = '\0';
|
||||
p--;
|
||||
}
|
||||
|
||||
if (strncmp (_filepath + winDriveLetterOffset, _refpath + winDriveLetterOffset, strlen (_refpath + winDriveLetterOffset)) == 0) {
|
||||
if (!parents) {
|
||||
relpath = laaf_util_build_path ("/", "./", _filepath + strlen (_refpath), NULL);
|
||||
goto end;
|
||||
} else {
|
||||
relpath = laaf_util_build_path ("/", parents, _filepath + strlen (_refpath), NULL);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = laaf_util_snprintf_realloc (&parents, &parentsLen, parentsOffset, "../");
|
||||
|
||||
assert (ret >= 0);
|
||||
|
||||
parentsOffset += (size_t)ret;
|
||||
p--;
|
||||
}
|
||||
|
||||
end:
|
||||
free (parents);
|
||||
free (_filepath);
|
||||
free (_refpath);
|
||||
|
||||
return relpath;
|
||||
}
|
||||
|
||||
char*
|
||||
laaf_util_absolute_path (const char* relpath)
|
||||
{
|
||||
if (!relpath) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// char *abspath = NULL;
|
||||
wchar_t buf[_MAX_PATH];
|
||||
|
||||
wchar_t* wrelpath = laaf_util_windows_utf8toutf16 (relpath);
|
||||
|
||||
if (!wrelpath) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_wfullpath (buf, wrelpath, _MAX_PATH)) {
|
||||
free (wrelpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* abspath = laaf_util_windows_utf16toutf8 (buf);
|
||||
|
||||
if (!abspath) {
|
||||
free (wrelpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free (wrelpath);
|
||||
|
||||
return abspath;
|
||||
|
||||
#else
|
||||
char buf[PATH_MAX + 1];
|
||||
|
||||
if (!realpath (relpath, buf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return laaf_util_c99strdup (buf);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
laaf_util_snprintf_realloc (char** str, size_t* size, size_t offset, const char* format, ...)
|
||||
{
|
||||
size_t tmpsize = 0;
|
||||
|
||||
if (!size) {
|
||||
size = &tmpsize;
|
||||
}
|
||||
|
||||
int retval, needed;
|
||||
int retval = 0;
|
||||
size_t needed = 0;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, format);
|
||||
|
||||
while (0 <= (retval = vsnprintf ((*str) + offset, (*size) - offset, format, ap)) && (int64_t) ((*size) - offset) < (needed = retval + 1)) {
|
||||
while (0 <= (retval = vsnprintf ((*str) + offset, (*size) - offset, format, ap)) && ((*size) - offset) < (needed = (unsigned)retval + 1)) {
|
||||
va_end (ap);
|
||||
|
||||
*size *= 2;
|
||||
|
||||
if ((int64_t) ((*size) - offset) < needed)
|
||||
if (((*size) - offset) < needed)
|
||||
*size = needed + offset;
|
||||
|
||||
char* p = realloc (*str, *size);
|
||||
|
|
@ -320,7 +466,7 @@ laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* fo
|
|||
free (*str);
|
||||
*str = NULL;
|
||||
*size = 0;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_start (ap, format);
|
||||
|
|
@ -328,38 +474,254 @@ laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* fo
|
|||
|
||||
va_end (ap);
|
||||
|
||||
return retval;
|
||||
return (retval > 0) ? retval : 0;
|
||||
}
|
||||
|
||||
int
|
||||
laaf_util_vsnprintf_realloc (char** str, int* size, int offset, const char* fmt, va_list* args)
|
||||
laaf_util_file_exists (const char* filepath)
|
||||
{
|
||||
va_list args2, args3;
|
||||
#ifdef _WIN32
|
||||
int needed = MultiByteToWideChar (CP_UTF8, 0, filepath, -1, NULL, 0);
|
||||
|
||||
va_copy (args2, *args);
|
||||
va_copy (args3, *args);
|
||||
if (needed == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int needed = vsnprintf (NULL, 0, fmt, args2) + 1;
|
||||
wchar_t* wfilepath = malloc ((size_t)needed * sizeof (wchar_t));
|
||||
|
||||
if (!wfilepath) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rc = MultiByteToWideChar (CP_UTF8, 0, filepath, -1, wfilepath, needed);
|
||||
|
||||
if (rc == 0) {
|
||||
free (wfilepath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_waccess (wfilepath, F_OK) == 0) {
|
||||
free (wfilepath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free (wfilepath);
|
||||
|
||||
#else
|
||||
if (access (filepath, F_OK) == 0) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
utf8CodeLen (const uint16_t* u16Code)
|
||||
{
|
||||
if (u16Code[0] < 0x80) {
|
||||
return 1;
|
||||
} else if (u16Code[0] < 0x800) {
|
||||
return 2;
|
||||
} else if (u16Code[0] < 0xD800 ||
|
||||
u16Code[0] > 0xDFFF) {
|
||||
return 3;
|
||||
} else if (((u16Code[0] & 0xFC00) == 0xD800) &&
|
||||
((u16Code[1] & 0xFC00) == 0xDC00)) {
|
||||
return 4;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
utf16CodeLen (const uint16_t* u16Code)
|
||||
{
|
||||
if (u16Code[0] < 0xD800 ||
|
||||
u16Code[0] > 0xDFFF) {
|
||||
return 1;
|
||||
} else if (((u16Code[0] & 0xFC00) == 0xD800) &&
|
||||
((u16Code[1] & 0xFC00) == 0xDC00)) {
|
||||
return 2;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
utf16CodeToUTF8 (const uint16_t* u16Code, char* u8Code, int* u16Len, int* u8Len)
|
||||
{
|
||||
int len8 = utf8CodeLen (u16Code);
|
||||
int len16 = utf16CodeLen (u16Code);
|
||||
|
||||
if (len8 < 0 || len16 < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*u8Len = len8;
|
||||
*u16Len = len16;
|
||||
|
||||
if (len8 == 1) {
|
||||
u8Code[0] = (char)(u16Code[0]);
|
||||
} else if (len8 == 2) {
|
||||
u8Code[0] = (char)(0xC0 | (u16Code[0] >> 6));
|
||||
u8Code[1] = (char)(0x80 | (u16Code[0] & 0x3F));
|
||||
} else if (len8 == 3) {
|
||||
u8Code[0] = (char)(0xE0 | (u16Code[0] >> 12));
|
||||
u8Code[1] = (char)(0x80 | ((u16Code[0] >> 6) & 0x3F));
|
||||
u8Code[2] = (char)(0x80 | (u16Code[0] & 0x3F));
|
||||
} else {
|
||||
uint32_t c = (u16Code[0] & 0x03FF) << 10;
|
||||
|
||||
c |= (u16Code[1] & 0x03FF);
|
||||
c += 0x10000;
|
||||
|
||||
u8Code[0] = (char)(0xF0 | ((c >> 18) & 0x07));
|
||||
u8Code[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
||||
u8Code[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
||||
u8Code[3] = (char)(0x80 | (c & 0x3F));
|
||||
}
|
||||
|
||||
return *u8Len;
|
||||
}
|
||||
|
||||
static long
|
||||
utf8strLen (const uint16_t* u16str)
|
||||
{
|
||||
long len = 0;
|
||||
const uint16_t* p = u16str;
|
||||
|
||||
while (*p != 0x0000) {
|
||||
int u8CodeLen = utf8CodeLen (p);
|
||||
int u16CodeLen = utf16CodeLen (p);
|
||||
|
||||
if (u8CodeLen < 0 || u16CodeLen < 0) {
|
||||
len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
p += u16CodeLen;
|
||||
len += u8CodeLen;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
laaf_util_utf8strCharLen (const char* u8str)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
while (*u8str) {
|
||||
count += (*u8str++ & 0xC0) != 0x80;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
char*
|
||||
laaf_util_utf16Toutf8 (const uint16_t* u16str)
|
||||
{
|
||||
long u8len = utf8strLen (u16str);
|
||||
|
||||
if (u8len < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* u8str = calloc ((size_t)u8len + 1, sizeof (char));
|
||||
|
||||
if (!u8str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint16_t* u16ptr = u16str;
|
||||
char* u8ptr = u8str;
|
||||
|
||||
while (*u16ptr != 0x0000) {
|
||||
int u8codelen = 0;
|
||||
int u16codelen = 0;
|
||||
|
||||
utf16CodeToUTF8 (u16ptr, u8ptr, &u16codelen, &u8codelen);
|
||||
|
||||
if (u16codelen < 0 || u8codelen < 0) {
|
||||
free (u8str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8ptr += u8codelen;
|
||||
u16ptr += u16codelen;
|
||||
}
|
||||
|
||||
*u8ptr = 0x00;
|
||||
|
||||
return u8str;
|
||||
}
|
||||
|
||||
int
|
||||
laaf_util_vsnprintf_realloc (char** str, size_t* size, size_t offset, const char* fmt, va_list args)
|
||||
{
|
||||
FILE* dummy = NULL;
|
||||
va_list args1;
|
||||
|
||||
size_t tmpsize = 0;
|
||||
|
||||
if (size == NULL) {
|
||||
size = &tmpsize;
|
||||
}
|
||||
|
||||
va_copy (args1, args);
|
||||
|
||||
/* https://stackoverflow.com/a/4116308 */
|
||||
#ifndef _WIN32
|
||||
dummy = fopen ("/dev/null", "wb");
|
||||
#else
|
||||
dummy = fopen ("NUL", "wb");
|
||||
#endif
|
||||
|
||||
if (!dummy) {
|
||||
// fprintf( stderr, "Could not fopen() dummy null file\n" );
|
||||
goto err;
|
||||
}
|
||||
|
||||
int retval = vfprintf (dummy, fmt, args);
|
||||
|
||||
if (retval < 0) {
|
||||
// fprintf( stderr, "vfprintf() error : %s\n", strerror(errno) );
|
||||
goto err;
|
||||
}
|
||||
|
||||
unsigned needed = (unsigned)retval + 1;
|
||||
|
||||
if (needed >= (*size) - offset) {
|
||||
char* p = realloc (*str, offset + needed);
|
||||
char* p = realloc (*str, (offset + needed) * sizeof (char));
|
||||
|
||||
if (p) {
|
||||
*str = p;
|
||||
*size = offset + needed;
|
||||
} else {
|
||||
/* If realloc() fails, the original block is left untouched; it is not freed or moved. */
|
||||
va_end (args2);
|
||||
va_end (args3);
|
||||
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
va_end (args2);
|
||||
|
||||
int written = vsnprintf ((*str) + offset, (*size) - offset, fmt, args3);
|
||||
int written = vsnprintf ((*str) + offset, (*size) - offset, fmt, args1);
|
||||
|
||||
va_end (args3);
|
||||
// assert( written >= 0 && (size_t)written < (*size)-offset );
|
||||
|
||||
if (written < 0 && (size_t)written >= (*size) - offset) {
|
||||
fprintf (stderr, "vsnprintf() error : %s\n", strerror (errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
goto end;
|
||||
|
||||
err:
|
||||
written = -1;
|
||||
|
||||
end:
|
||||
|
||||
if (dummy) {
|
||||
fclose (dummy);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
|
@ -371,7 +733,7 @@ laaf_util_c99strdup (const char* src)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
size_t len = 0;
|
||||
|
||||
while (src[len]) {
|
||||
len++;
|
||||
|
|
@ -379,8 +741,9 @@ laaf_util_c99strdup (const char* src)
|
|||
|
||||
char* str = malloc (len + 1);
|
||||
|
||||
if (!str)
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* p = str;
|
||||
|
||||
|
|
@ -394,24 +757,30 @@ laaf_util_c99strdup (const char* src)
|
|||
}
|
||||
|
||||
int
|
||||
laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, int* bufsz, int offset)
|
||||
laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, size_t* bufsz, size_t offset, const char* padding)
|
||||
{
|
||||
if (stream == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int initialOffset = offset;
|
||||
size_t initialOffset = offset;
|
||||
uint32_t i = 0;
|
||||
|
||||
char hex[49];
|
||||
char ascii[19];
|
||||
|
||||
uint32_t count = 0;
|
||||
size_t count = 0;
|
||||
|
||||
offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " ______________________________ Hex Dump ______________________________\n\n");
|
||||
int rc = laaf_util_snprintf_realloc (buf, bufsz, offset, "%s______________________________ Hex Dump ______________________________\n\n", padding);
|
||||
|
||||
if (rc < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
offset += (size_t)rc;
|
||||
|
||||
while (count < stream_sz) {
|
||||
uint32_t lineLen = (stream_sz - count) / 16;
|
||||
size_t lineLen = (stream_sz - count) / 16;
|
||||
|
||||
if (lineLen <= 0)
|
||||
lineLen = (stream_sz) % 16;
|
||||
|
|
@ -424,22 +793,28 @@ laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, i
|
|||
uint32_t linepos = 0;
|
||||
|
||||
for (i = 0; i < lineLen; i++) {
|
||||
linepos += snprintf (&hex[linepos], sizeof (hex) - (linepos), "%02x%s", *(const unsigned char*)(stream + count + i), (i == 7) ? " " : " ");
|
||||
rc = snprintf (&hex[linepos], sizeof (hex) - (linepos), "%02x%s", *(const unsigned char*)(stream + count + i), (i == 7) ? " " : " ");
|
||||
|
||||
if (rc < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
linepos += (uint32_t)rc;
|
||||
|
||||
if (i < 8) {
|
||||
if (isalnum (*(stream + count + i)))
|
||||
ascii[i] = *(const unsigned char*)(stream + count + i);
|
||||
ascii[i] = *(const char*)(stream + count + i);
|
||||
else
|
||||
ascii[i] = '.';
|
||||
} else if (i > 8) {
|
||||
if (isalnum (*(stream + count + i)))
|
||||
ascii[i + 1] = *(const unsigned char*)(stream + count + i);
|
||||
ascii[i + 1] = *(const char*)(stream + count + i);
|
||||
else
|
||||
ascii[i + 1] = '.';
|
||||
} else {
|
||||
if (isalnum (*(stream + count + i))) {
|
||||
ascii[i] = ' ';
|
||||
ascii[i + 1] = *(const unsigned char*)(stream + count + i);
|
||||
ascii[i + 1] = *(const char*)(stream + count + i);
|
||||
} else {
|
||||
ascii[i] = ' ';
|
||||
ascii[i + 1] = '.';
|
||||
|
|
@ -459,10 +834,21 @@ laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, i
|
|||
|
||||
count += lineLen;
|
||||
|
||||
offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " %s | %s\n", hex, ascii);
|
||||
rc = laaf_util_snprintf_realloc (buf, bufsz, offset, "%s%s | %s\n", padding, hex, ascii);
|
||||
|
||||
if (rc < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
offset += (size_t)rc;
|
||||
}
|
||||
|
||||
offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " ______________________________________________________________________\n\n");
|
||||
rc = laaf_util_snprintf_realloc (buf, bufsz, offset, "%s______________________________________________________________________\n\n", padding);
|
||||
|
||||
return offset - initialOffset; /* bytes written */
|
||||
if (rc < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return (int)(offset - initialOffset); /* bytes written */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue