mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-02 16:59:03 +00:00
[makerom/ctrool] Implemented ROMFS unicode support. (oschar.c)
This commit is contained in:
@@ -99,6 +99,7 @@
|
||||
<ClCompile Include="exheader.c" />
|
||||
<ClCompile Include="filepath.c" />
|
||||
<ClCompile Include="firm.c" />
|
||||
<ClCompile Include="oschar.c" />
|
||||
<ClCompile Include="windows\getopt.c" />
|
||||
<ClCompile Include="windows\getopt1.c" />
|
||||
<ClCompile Include="ivfc.c" />
|
||||
@@ -130,6 +131,7 @@
|
||||
<ClInclude Include="exheader.h" />
|
||||
<ClInclude Include="filepath.h" />
|
||||
<ClInclude Include="firm.h" />
|
||||
<ClInclude Include="oschar.h" />
|
||||
<ClInclude Include="windows\getopt.h" />
|
||||
<ClInclude Include="info.h" />
|
||||
<ClInclude Include="ivfc.h" />
|
||||
|
||||
@@ -114,6 +114,9 @@
|
||||
<ClCompile Include="tinyxml\tinyxmlparser.cpp">
|
||||
<Filter>Source Files\tinyxml</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="oschar.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="cia.h">
|
||||
@@ -203,5 +206,8 @@
|
||||
<ClInclude Include="tinyxml\tinyxml.h">
|
||||
<Filter>Header Files\tinyxml</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="oschar.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+1
-1
@@ -102,7 +102,7 @@ int main(int argc, char* argv[])
|
||||
char keysetfname[512] = "keys.xml";
|
||||
keyset tmpkeys;
|
||||
unsigned int checkkeysetfile = 0;
|
||||
|
||||
|
||||
memset(&ctx, 0, sizeof(toolcontext));
|
||||
ctx.actions = InfoFlag | ExtractFlag;
|
||||
ctx.filetype = FILETYPE_UNKNOWN;
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#include "oschar.h"
|
||||
|
||||
int os_fstat(const oschar_t *path)
|
||||
{
|
||||
struct _osstat st;
|
||||
return os_stat(path, &st);
|
||||
}
|
||||
|
||||
uint64_t os_fsize(const oschar_t *path)
|
||||
{
|
||||
struct _osstat st;
|
||||
if (os_stat(path, &st) != 0)
|
||||
return 0;
|
||||
else
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
int os_makedir(const oschar_t *dir)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _wmkdir(dir);
|
||||
#else
|
||||
return mkdir(dir, 0777);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t utf16_strlen(const utf16char_t *str)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; str[i] != 0x0; i++);
|
||||
return i;
|
||||
}
|
||||
|
||||
void utf16_fputs(const utf16char_t *str, FILE *out)
|
||||
{
|
||||
oschar_t *_str = os_CopyConvertUTF16Str(str);
|
||||
os_fputs(_str, out);
|
||||
free(_str);
|
||||
}
|
||||
|
||||
char* strcopy_8to8(const char *src)
|
||||
{
|
||||
uint32_t src_len;
|
||||
char *dst;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
dst = calloc(src_len + 1, sizeof(char));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
strncpy(dst, src, src_len);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
utf16char_t* strcopy_8to16(const char *src)
|
||||
{
|
||||
uint32_t src_len, i;
|
||||
utf16char_t *dst;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
dst = calloc(src_len + 1, sizeof(utf16char_t));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
for (i = 0; i < src_len; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
utf16char_t* strcopy_16to16(const utf16char_t *src)
|
||||
{
|
||||
uint32_t src_len, i;
|
||||
utf16char_t *dst;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = utf16_strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
dst = calloc(src_len + 1, sizeof(utf16char_t));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
for (i = 0; i < src_len; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
utf16char_t* strcopy_UTF8toUTF16(const char *src)
|
||||
{
|
||||
uint32_t src_len, dst_len;
|
||||
size_t in_bytes, out_bytes;
|
||||
utf16char_t *dst;
|
||||
char *in, *out;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = strlen(src);
|
||||
dst_len = src_len + 1;
|
||||
|
||||
// Allocate memory for string
|
||||
dst = calloc(dst_len, sizeof(utf16char_t));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
in = (char*)src;
|
||||
out = (char*)dst;
|
||||
in_bytes = src_len*sizeof(char);
|
||||
out_bytes = dst_len*sizeof(utf16char_t);
|
||||
|
||||
iconv_t cd = iconv_open("UTF-16LE", "UTF-8");
|
||||
iconv(cd, &in, &in_bytes, &out, &out_bytes);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char* strcopy_UTF16toUTF8(const utf16char_t *src)
|
||||
{
|
||||
uint32_t src_len, dst_len;
|
||||
size_t in_bytes, out_bytes;
|
||||
char *dst;
|
||||
char *in, *out;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = utf16_strlen(src);
|
||||
dst_len = src_len * 2;
|
||||
|
||||
// Allocate memory for string
|
||||
dst = calloc(dst_len, sizeof(char)); // twice the size, as UTF-8 will use up to two bytes for converted UTF16 chars afaik
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
in = (char*)src;
|
||||
out = (char*)dst;
|
||||
in_bytes = src_len*sizeof(uint16_t);
|
||||
out_bytes = dst_len*sizeof(char);
|
||||
|
||||
iconv_t cd = iconv_open("UTF-8", "UTF-16LE");
|
||||
iconv(cd, &in, &in_bytes, &out, &out_bytes);
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add)
|
||||
{
|
||||
uint32_t len;
|
||||
oschar_t *new_path;
|
||||
|
||||
len = os_strlen(src) + os_strlen(add) + 0x10;
|
||||
new_path = calloc(len, sizeof(oschar_t));
|
||||
|
||||
#ifdef _WIN32
|
||||
_snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, add);
|
||||
#else
|
||||
snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, add);
|
||||
#endif
|
||||
|
||||
return new_path;
|
||||
}
|
||||
|
||||
oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add)
|
||||
{
|
||||
uint32_t len;
|
||||
oschar_t *new_path, *_add;
|
||||
|
||||
_add = os_CopyConvertUTF16Str(add);
|
||||
|
||||
len = os_strlen(src) + os_strlen(_add) + 0x10;
|
||||
new_path = calloc(len, sizeof(oschar_t));
|
||||
|
||||
#ifdef _WIN32
|
||||
_snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, _add);
|
||||
#else
|
||||
snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, _add);
|
||||
#endif
|
||||
|
||||
free(_add);
|
||||
return new_path;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
// Nintendo uses UTF16-LE chars for extended ASCII support
|
||||
typedef uint16_t utf16char_t;
|
||||
|
||||
// Native OS char type for unicode support
|
||||
#ifdef _WIN32
|
||||
typedef wchar_t oschar_t; // UTF16-LE
|
||||
#else
|
||||
typedef char oschar_t; // UTF8
|
||||
#endif
|
||||
|
||||
// Simple redirect macros for functions and types
|
||||
#ifdef _WIN32
|
||||
#define os_strlen wcslen
|
||||
#define os_strcmp wcscmp
|
||||
#define os_fputs fputws
|
||||
|
||||
#define os_CopyStr strcopy_16to16
|
||||
#define os_CopyConvertCharStr strcopy_8to16
|
||||
#define os_CopyConvertUTF16Str strcopy_16to16
|
||||
#define utf16_CopyStr strcopy_16to16
|
||||
#define utf16_CopyConvertOsStr strcopy_16to16
|
||||
|
||||
#define _osdirent _wdirent
|
||||
#define _OSDIR _WDIR
|
||||
#define os_readdir _wreaddir
|
||||
#define os_opendir _wopendir
|
||||
#define os_closedir _wclosedir
|
||||
#define os_chdir _wchdir
|
||||
|
||||
#define _osstat _stat64
|
||||
#define os_stat _wstat64
|
||||
|
||||
#define os_fopen _wfopen
|
||||
#define OS_MODE_READ L"rb"
|
||||
#define OS_MODE_WRITE L"wb"
|
||||
#define OS_MODE_EDIT L"rb+"
|
||||
#define OS_PATH_SEPARATOR '\\'
|
||||
#else
|
||||
#define os_strlen strlen
|
||||
#define os_strcmp strcmp
|
||||
#define os_fputs fputs
|
||||
|
||||
#define os_CopyStr strcopy_8to8
|
||||
#define os_CopyConvertUTF16Str strcopy_UTF16toUTF8
|
||||
#define os_CopyConvertCharStr strcopy_8to8
|
||||
#define utf16_CopyStr strcopy_16to16
|
||||
#define utf16_CopyConvertOsStr strcopy_UTF8toUTF16
|
||||
|
||||
#define _osdirent dirent
|
||||
#define _OSDIR DIR
|
||||
#define os_readdir readdir
|
||||
#define os_opendir opendir
|
||||
#define os_closedir closedir
|
||||
#define os_chdir chdir
|
||||
|
||||
#define _osstat stat
|
||||
#define os_stat stat
|
||||
|
||||
#define os_fopen fopen
|
||||
#define OS_MODE_READ "rb"
|
||||
#define OS_MODE_WRITE "wb"
|
||||
#define OS_MODE_EDIT "rb+"
|
||||
#define OS_PATH_SEPARATOR '/'
|
||||
#endif
|
||||
|
||||
/* File related */
|
||||
int os_fstat(const oschar_t* path);
|
||||
uint64_t os_fsize(const oschar_t* path);
|
||||
int os_makedir(const oschar_t *dir);
|
||||
|
||||
/* UTF16 String property functions */
|
||||
uint32_t utf16_strlen(const utf16char_t* str);
|
||||
void utf16_fputs(const utf16char_t *str, FILE *out);
|
||||
|
||||
/* String Copy and Conversion */
|
||||
char* strcopy_8to8(const char *src);
|
||||
utf16char_t* strcopy_8to16(const char *src);
|
||||
utf16char_t* strcopy_16to16(const utf16char_t *src);
|
||||
#ifndef _WIN32
|
||||
utf16char_t* strcopy_UTF8toUTF16(const char *src);
|
||||
char* strcopy_UTF16toUTF8(const utf16char_t *src);
|
||||
#endif
|
||||
|
||||
/* String Append and Create */
|
||||
oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add);
|
||||
oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add);
|
||||
+51
-29
@@ -96,8 +96,13 @@ void romfs_process(romfs_context* ctx, u32 actions)
|
||||
if (actions & InfoFlag)
|
||||
romfs_print(ctx);
|
||||
|
||||
romfs_visit_dir(ctx, 0, 0, actions, settings_get_romfs_dir_path(ctx->usersettings));
|
||||
if (settings_get_romfs_dir_path(ctx->usersettings)->valid)
|
||||
ctx->extractdir = os_CopyConvertCharStr(settings_get_romfs_dir_path(ctx->usersettings)->pathname);
|
||||
else
|
||||
ctx->extractdir = NULL;
|
||||
|
||||
romfs_visit_dir(ctx, 0, 0, actions, ctx->extractdir);
|
||||
free(ctx->extractdir);
|
||||
}
|
||||
|
||||
int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer)
|
||||
@@ -171,12 +176,12 @@ int romfs_fileblock_readentry(romfs_context* ctx, u32 fileoffset, romfs_fileentr
|
||||
|
||||
|
||||
|
||||
void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions, filepath* rootpath)
|
||||
void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions, const oschar_t* rootpath)
|
||||
{
|
||||
u32 siblingoffset;
|
||||
u32 childoffset;
|
||||
u32 fileoffset;
|
||||
filepath currentpath;
|
||||
oschar_t* currentpath;
|
||||
romfs_direntry* entry = &ctx->direntry;
|
||||
|
||||
|
||||
@@ -190,32 +195,39 @@ void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions,
|
||||
// fwprintf(stdout, L"%ls\n", entry->name);
|
||||
|
||||
|
||||
if (rootpath && rootpath->valid)
|
||||
if (rootpath && os_strlen(rootpath))
|
||||
{
|
||||
filepath_copy(¤tpath, rootpath);
|
||||
filepath_append_utf16(¤tpath, entry->name);
|
||||
if (currentpath.valid)
|
||||
if (utf16_strlen((const utf16char_t*)entry->name) > 0)
|
||||
currentpath = os_AppendUTF16StrToPath(rootpath, (const utf16char_t*)entry->name);
|
||||
else // root dir, use the provided extract path instead of the empty root name.
|
||||
currentpath = os_CopyStr(rootpath);
|
||||
|
||||
if (currentpath)
|
||||
{
|
||||
makedir(currentpath.pathname);
|
||||
os_makedir(currentpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error creating directory in root %s\n", rootpath->pathname);
|
||||
fputs("Error creating directory in root ", stderr);
|
||||
os_fputs(rootpath, stderr);
|
||||
fputs("\n", stderr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filepath_init(¤tpath);
|
||||
|
||||
currentpath = os_CopyConvertUTF16Str((const utf16char_t*)entry->name);
|
||||
if (settings_get_list_romfs_files(ctx->usersettings))
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for(i=0; i<depth; i++)
|
||||
printf(" ");
|
||||
fwprintf(stdout, L"%ls\n", entry->name);
|
||||
os_fputs(currentpath, stdout);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
free(currentpath);
|
||||
currentpath = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -224,20 +236,22 @@ void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions,
|
||||
fileoffset = getle32(entry->fileoffset);
|
||||
|
||||
if (fileoffset != (~0))
|
||||
romfs_visit_file(ctx, fileoffset, depth+1, actions, ¤tpath);
|
||||
romfs_visit_file(ctx, fileoffset, depth+1, actions, currentpath);
|
||||
|
||||
if (childoffset != (~0))
|
||||
romfs_visit_dir(ctx, childoffset, depth+1, actions, ¤tpath);
|
||||
romfs_visit_dir(ctx, childoffset, depth+1, actions, currentpath);
|
||||
|
||||
if (siblingoffset != (~0))
|
||||
romfs_visit_dir(ctx, siblingoffset, depth, actions, rootpath);
|
||||
|
||||
free(currentpath);
|
||||
}
|
||||
|
||||
|
||||
void romfs_visit_file(romfs_context* ctx, u32 fileoffset, u32 depth, u32 actions, filepath* rootpath)
|
||||
void romfs_visit_file(romfs_context* ctx, u32 fileoffset, u32 depth, u32 actions, const oschar_t* rootpath)
|
||||
{
|
||||
u32 siblingoffset = 0;
|
||||
filepath currentpath;
|
||||
oschar_t* currentpath = NULL;
|
||||
romfs_fileentry* entry = &ctx->fileentry;
|
||||
|
||||
|
||||
@@ -250,55 +264,63 @@ void romfs_visit_file(romfs_context* ctx, u32 fileoffset, u32 depth, u32 actions
|
||||
// getle64(entry->datasize), getle32(entry->unknown));
|
||||
// fwprintf(stdout, L"%ls\n", entry->name);
|
||||
|
||||
if (rootpath && rootpath->valid)
|
||||
if (rootpath && os_strlen(rootpath))
|
||||
{
|
||||
filepath_copy(¤tpath, rootpath);
|
||||
filepath_append_utf16(¤tpath, entry->name);
|
||||
if (currentpath.valid)
|
||||
currentpath = os_AppendUTF16StrToPath(rootpath, (const utf16char_t*)entry->name);
|
||||
if (currentpath)
|
||||
{
|
||||
fprintf(stdout, "Saving %s...\n", currentpath.pathname);
|
||||
romfs_extract_datafile(ctx, getle64(entry->dataoffset), getle64(entry->datasize), ¤tpath);
|
||||
fputs("Saving ", stdout);
|
||||
os_fputs(currentpath, stdout);
|
||||
fputs("...\n", stdout);
|
||||
romfs_extract_datafile(ctx, getle64(entry->dataoffset), getle64(entry->datasize), currentpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error creating directory in root %s\n", rootpath->pathname);
|
||||
fputs("Error creating file in root ", stderr);
|
||||
os_fputs(rootpath, stderr);
|
||||
fputs("\n", stderr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filepath_init(¤tpath);
|
||||
currentpath = os_CopyConvertUTF16Str((const utf16char_t*)entry->name);
|
||||
if (settings_get_list_romfs_files(ctx->usersettings))
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for(i=0; i<depth; i++)
|
||||
printf(" ");
|
||||
fwprintf(stdout, L"%ls\n", entry->name);
|
||||
os_fputs(currentpath, stdout);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
free(currentpath);
|
||||
currentpath = NULL;
|
||||
}
|
||||
|
||||
siblingoffset = getle32(entry->siblingoffset);
|
||||
|
||||
if (siblingoffset != (~0))
|
||||
romfs_visit_file(ctx, siblingoffset, depth, actions, rootpath);
|
||||
|
||||
free(currentpath);
|
||||
}
|
||||
|
||||
void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, filepath* path)
|
||||
void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const oschar_t* path)
|
||||
{
|
||||
FILE* outfile = 0;
|
||||
u32 max;
|
||||
u8 buffer[4096];
|
||||
|
||||
|
||||
if (path == 0 || path->valid == 0)
|
||||
if (path == NULL || os_strlen(path) == 0)
|
||||
goto clean;
|
||||
|
||||
offset += ctx->datablockoffset;
|
||||
|
||||
fseeko64(ctx->file, offset, SEEK_SET);
|
||||
outfile = fopen(path->pathname, "wb");
|
||||
if (outfile == 0)
|
||||
outfile = os_fopen(path, OS_MODE_WRITE);
|
||||
if (outfile == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error opening file for writing\n");
|
||||
goto clean;
|
||||
|
||||
+5
-4
@@ -4,7 +4,7 @@
|
||||
#include "types.h"
|
||||
#include "info.h"
|
||||
#include "ctr.h"
|
||||
#include "filepath.h"
|
||||
#include "oschar.h"
|
||||
#include "settings.h"
|
||||
#include "ivfc.h"
|
||||
|
||||
@@ -55,6 +55,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
oschar_t* extractdir;
|
||||
settings* usersettings;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
@@ -81,9 +82,9 @@ int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* b
|
||||
int romfs_dirblock_readentry(romfs_context* ctx, u32 diroffset, romfs_direntry* entry);
|
||||
int romfs_fileblock_read(romfs_context* ctx, u32 fileoffset, u32 filesize, void* buffer);
|
||||
int romfs_fileblock_readentry(romfs_context* ctx, u32 fileoffset, romfs_fileentry* entry);
|
||||
void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions, filepath* rootpath);
|
||||
void romfs_visit_file(romfs_context* ctx, u32 fileoffset, u32 depth, u32 actions, filepath* rootpath);
|
||||
void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, filepath* path);
|
||||
void romfs_visit_dir(romfs_context* ctx, u32 diroffset, u32 depth, u32 actions, const oschar_t* rootpath);
|
||||
void romfs_visit_file(romfs_context* ctx, u32 fileoffset, u32 depth, u32 actions, const oschar_t* rootpath);
|
||||
void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const oschar_t* path);
|
||||
void romfs_process(romfs_context* ctx, u32 actions);
|
||||
void romfs_print(romfs_context* ctx);
|
||||
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include "utils.h"
|
||||
@@ -202,4 +204,4 @@ u64 _fsize(const char *filename)
|
||||
else
|
||||
return st.st_size;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@
|
||||
<NMakeCleanCommandLine>make clean</NMakeCleanCommandLine>
|
||||
<NMakeReBuildCommandLine>make rebuild</NMakeReBuildCommandLine>
|
||||
<NMakePreprocessorDefinitions>WIN32;_DEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
|
||||
<IncludePath>C:\Program Files\mingw-w64\x86_64-5.2.0-win32-seh-rt_v4-rev0\mingw64\x86_64-w64-mingw32\include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>C:\Program Files\mingw-w64\x86_64-4.9.2-win32-seh-rt_v4-rev2\mingw64\x86_64-w64-mingw32\include</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<NMakeBuildCommandLine>make</NMakeBuildCommandLine>
|
||||
@@ -104,6 +104,7 @@
|
||||
<ClInclude Include="desc\dev_sigdata.h" />
|
||||
<ClInclude Include="desc\presets.h" />
|
||||
<ClInclude Include="desc\prod_sigdata.h" />
|
||||
<ClInclude Include="oschar.h" />
|
||||
<ClInclude Include="romfs_fs.h" />
|
||||
<ClInclude Include="elf.h" />
|
||||
<ClInclude Include="exefs.h" />
|
||||
@@ -188,7 +189,6 @@
|
||||
<ClInclude Include="tmd_read.h" />
|
||||
<ClInclude Include="types.h" />
|
||||
<ClInclude Include="user_settings.h" />
|
||||
<ClInclude Include="utf.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
<ClInclude Include="yaml_parser.h" />
|
||||
</ItemGroup>
|
||||
@@ -201,6 +201,7 @@
|
||||
<ClCompile Include="code.c" />
|
||||
<ClCompile Include="crypto.c" />
|
||||
<ClCompile Include="ctr_utils.c" />
|
||||
<ClCompile Include="oschar.c" />
|
||||
<ClCompile Include="polarssl\aes.c" />
|
||||
<ClCompile Include="polarssl\padlock.c" />
|
||||
<ClCompile Include="romfs_fs.c" />
|
||||
@@ -236,7 +237,6 @@
|
||||
<ClCompile Include="titleid.c" />
|
||||
<ClCompile Include="tmd.c" />
|
||||
<ClCompile Include="user_settings.c" />
|
||||
<ClCompile Include="utf.c" />
|
||||
<ClCompile Include="utils.c" />
|
||||
<ClCompile Include="yaml_parser.c" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -156,9 +156,6 @@
|
||||
<ClInclude Include="user_settings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -339,6 +336,9 @@
|
||||
<ClInclude Include="romfs_fs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="oschar.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="accessdesc.c">
|
||||
@@ -407,9 +407,6 @@
|
||||
<ClCompile Include="user_settings.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -479,6 +476,9 @@
|
||||
<ClCompile Include="polarssl\padlock.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="oschar.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Makefile">
|
||||
|
||||
+2
-1
@@ -153,7 +153,7 @@ int ImportNcchForCci(cci_settings *set)
|
||||
|
||||
bool CanCiaBeCci(u64 titleId, u16 count, tmd_content_chunk *content)
|
||||
{
|
||||
if(GetTidCategory(titleId) != PROGRAM_ID_CATEGORY_APPLICATION && GetTidCategory(titleId) != PROGRAM_ID_CATEGORY_SYSTEM_APPLICATION)
|
||||
if(GetTidCategory(titleId) != PROGRAM_ID_CATEGORY_APPLICATION)
|
||||
return false;
|
||||
|
||||
if(count > CCI_MAX_CONTENT)
|
||||
@@ -222,6 +222,7 @@ int ProcessCiaForCci(cci_settings *set)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This need to be more automagical */
|
||||
void GetTitleSaveSize(cci_settings *set)
|
||||
{
|
||||
if(set->rsf->SystemControlInfo.SaveDataSize)
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#include "oschar.h"
|
||||
|
||||
int os_fstat(const oschar_t *path)
|
||||
{
|
||||
struct _osstat st;
|
||||
return os_stat(path, &st);
|
||||
}
|
||||
|
||||
uint64_t os_fsize(const oschar_t *path)
|
||||
{
|
||||
struct _osstat st;
|
||||
if (os_stat(path, &st) != 0)
|
||||
return 0;
|
||||
else
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
int os_makedir(const oschar_t *dir)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _wmkdir(dir);
|
||||
#else
|
||||
return mkdir(dir, 0777);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t utf16_strlen(const utf16char_t *str)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; str[i] != 0x0; i++);
|
||||
return i;
|
||||
}
|
||||
|
||||
void utf16_fputs(const utf16char_t *str, FILE *out)
|
||||
{
|
||||
oschar_t *_str = os_CopyConvertUTF16Str(str);
|
||||
os_fputs(_str, out);
|
||||
free(_str);
|
||||
}
|
||||
|
||||
char* strcopy_8to8(const char *src)
|
||||
{
|
||||
uint32_t src_len;
|
||||
char *dst;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
dst = calloc(src_len + 1, sizeof(char));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
strncpy(dst, src, src_len);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
utf16char_t* strcopy_8to16(const char *src)
|
||||
{
|
||||
uint32_t src_len, i;
|
||||
utf16char_t *dst;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
dst = calloc(src_len + 1, sizeof(utf16char_t));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
for (i = 0; i < src_len; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
utf16char_t* strcopy_16to16(const utf16char_t *src)
|
||||
{
|
||||
uint32_t src_len, i;
|
||||
utf16char_t *dst;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = utf16_strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
dst = calloc(src_len + 1, sizeof(utf16char_t));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
for (i = 0; i < src_len; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
utf16char_t* strcopy_UTF8toUTF16(const char *src)
|
||||
{
|
||||
uint32_t src_len, dst_len;
|
||||
size_t in_bytes, out_bytes;
|
||||
utf16char_t *dst;
|
||||
char *in, *out;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = strlen(src);
|
||||
dst_len = src_len + 1;
|
||||
|
||||
// Allocate memory for string
|
||||
dst = calloc(dst_len, sizeof(utf16char_t));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
in = (char*)src;
|
||||
out = (char*)dst;
|
||||
in_bytes = src_len*sizeof(char);
|
||||
out_bytes = dst_len*sizeof(utf16char_t);
|
||||
|
||||
iconv_t cd = iconv_open("UTF-16LE", "UTF-8");
|
||||
iconv(cd, &in, &in_bytes, &out, &out_bytes);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char* strcopy_UTF16toUTF8(const utf16char_t *src)
|
||||
{
|
||||
uint32_t src_len, dst_len;
|
||||
size_t in_bytes, out_bytes;
|
||||
char *dst;
|
||||
char *in, *out;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src_len = utf16_strlen(src);
|
||||
dst_len = src_len * 2;
|
||||
|
||||
// Allocate memory for string
|
||||
dst = calloc(dst_len, sizeof(char)); // twice the size, as UTF-8 will use up to two bytes for converted UTF16 chars afaik
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
in = (char*)src;
|
||||
out = (char*)dst;
|
||||
in_bytes = src_len*sizeof(uint16_t);
|
||||
out_bytes = dst_len*sizeof(char);
|
||||
|
||||
iconv_t cd = iconv_open("UTF-8", "UTF-16LE");
|
||||
iconv(cd, &in, &in_bytes, &out, &out_bytes);
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add)
|
||||
{
|
||||
uint32_t len;
|
||||
oschar_t *new_path;
|
||||
|
||||
len = os_strlen(src) + os_strlen(add) + 0x10;
|
||||
new_path = calloc(len, sizeof(oschar_t));
|
||||
|
||||
#ifdef _WIN32
|
||||
_snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, add);
|
||||
#else
|
||||
snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, add);
|
||||
#endif
|
||||
|
||||
return new_path;
|
||||
}
|
||||
|
||||
oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add)
|
||||
{
|
||||
uint32_t len;
|
||||
oschar_t *new_path, *_add;
|
||||
|
||||
_add = os_CopyConvertUTF16Str(add);
|
||||
|
||||
len = os_strlen(src) + os_strlen(_add) + 0x10;
|
||||
new_path = calloc(len, sizeof(oschar_t));
|
||||
|
||||
#ifdef _WIN32
|
||||
_snwprintf(new_path, len, L"%s%c%s", src, OS_PATH_SEPARATOR, _add);
|
||||
#else
|
||||
snprintf(new_path, len, "%s%c%s", src, OS_PATH_SEPARATOR, _add);
|
||||
#endif
|
||||
|
||||
free(_add);
|
||||
return new_path;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
// Nintendo uses UTF16-LE chars for extended ASCII support
|
||||
typedef uint16_t utf16char_t;
|
||||
|
||||
// Native OS char type for unicode support
|
||||
#ifdef _WIN32
|
||||
typedef wchar_t oschar_t; // UTF16-LE
|
||||
#else
|
||||
typedef char oschar_t; // UTF8
|
||||
#endif
|
||||
|
||||
// Simple redirect macros for functions and types
|
||||
#ifdef _WIN32
|
||||
#define os_strlen wcslen
|
||||
#define os_strcmp wcscmp
|
||||
#define os_fputs fputws
|
||||
|
||||
#define os_CopyStr strcopy_16to16
|
||||
#define os_CopyConvertCharStr strcopy_8to16
|
||||
#define os_CopyConvertUTF16Str strcopy_16to16
|
||||
#define utf16_CopyStr strcopy_16to16
|
||||
#define utf16_CopyConvertOsStr strcopy_16to16
|
||||
|
||||
#define _osdirent _wdirent
|
||||
#define _OSDIR _WDIR
|
||||
#define os_readdir _wreaddir
|
||||
#define os_opendir _wopendir
|
||||
#define os_closedir _wclosedir
|
||||
#define os_chdir _wchdir
|
||||
|
||||
#define _osstat _stat64
|
||||
#define os_stat _wstat64
|
||||
|
||||
#define os_fopen _wfopen
|
||||
#define OS_MODE_READ L"rb"
|
||||
#define OS_MODE_WRITE L"wb"
|
||||
#define OS_MODE_EDIT L"rb+"
|
||||
#define OS_PATH_SEPARATOR '\\'
|
||||
#else
|
||||
#define os_strlen strlen
|
||||
#define os_strcmp strcmp
|
||||
#define os_fputs fputs
|
||||
|
||||
#define os_CopyStr strcopy_8to8
|
||||
#define os_CopyConvertUTF16Str strcopy_UTF16toUTF8
|
||||
#define os_CopyConvertCharStr strcopy_8to8
|
||||
#define utf16_CopyStr strcopy_16to16
|
||||
#define utf16_CopyConvertOsStr strcopy_UTF8toUTF16
|
||||
|
||||
#define _osdirent dirent
|
||||
#define _OSDIR DIR
|
||||
#define os_readdir readdir
|
||||
#define os_opendir opendir
|
||||
#define os_closedir closedir
|
||||
#define os_chdir chdir
|
||||
|
||||
#define _osstat stat
|
||||
#define os_stat stat
|
||||
|
||||
#define os_fopen fopen
|
||||
#define OS_MODE_READ "rb"
|
||||
#define OS_MODE_WRITE "wb"
|
||||
#define OS_MODE_EDIT "rb+"
|
||||
#define OS_PATH_SEPARATOR '/'
|
||||
#endif
|
||||
|
||||
/* File related */
|
||||
int os_fstat(const oschar_t* path);
|
||||
uint64_t os_fsize(const oschar_t* path);
|
||||
int os_makedir(const oschar_t *dir);
|
||||
|
||||
/* UTF16 String property functions */
|
||||
uint32_t utf16_strlen(const utf16char_t* str);
|
||||
void utf16_fputs(const utf16char_t *str, FILE *out);
|
||||
|
||||
/* String Copy and Conversion */
|
||||
char* strcopy_8to8(const char *src);
|
||||
utf16char_t* strcopy_8to16(const char *src);
|
||||
utf16char_t* strcopy_16to16(const utf16char_t *src);
|
||||
#ifndef _WIN32
|
||||
utf16char_t* strcopy_UTF8toUTF16(const char *src);
|
||||
char* strcopy_UTF16toUTF8(const utf16char_t *src);
|
||||
#endif
|
||||
|
||||
/* String Append and Create */
|
||||
oschar_t* os_AppendToPath(const oschar_t *src, const oschar_t *add);
|
||||
oschar_t* os_AppendUTF16StrToPath(const oschar_t *src, const utf16char_t *add);
|
||||
+19
-127
@@ -1,6 +1,5 @@
|
||||
#include "lib.h"
|
||||
#include "romfs_fs.h"
|
||||
#include "utf.h"
|
||||
|
||||
/* This is the FS interface for ROMFS generation */
|
||||
/* Tested working on Windows/Linux/OSX */
|
||||
@@ -8,109 +7,6 @@ int PopulateDir(romfs_dir *dir);
|
||||
int InitDir(romfs_dir *dir);
|
||||
int ManageDir(romfs_dir *dir);
|
||||
|
||||
u32 fs_strlen(const fs_char *str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return strlen_char16(str);
|
||||
#else
|
||||
return strlen(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 romfs_strlen(const romfs_char *str)
|
||||
{
|
||||
return strlen_char16(str);
|
||||
}
|
||||
|
||||
int fs_strcmp(const fs_char *str1, const fs_char *str2)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return wcscmp(str1, str2);
|
||||
#else
|
||||
return strcmp(str1, str2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FILE* fs_fopen(fs_char *path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _wfopen(path, L"rb");
|
||||
#else
|
||||
return fopen(path, "rb");
|
||||
#endif
|
||||
}
|
||||
|
||||
u64 fs_fsize(fs_char *path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return wGetFileSize64(path);
|
||||
#else
|
||||
return GetFileSize64(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
fs_char* fs_AppendToPath(const fs_char *src, const fs_char *add)
|
||||
{
|
||||
u32 src_len, add_len;
|
||||
fs_char *new_path;
|
||||
|
||||
src_len = fs_strlen(src);
|
||||
add_len = fs_strlen(add);
|
||||
new_path = calloc(src_len + add_len + 0x10, sizeof(fs_char));
|
||||
|
||||
#ifdef _WIN32
|
||||
_snwprintf(new_path, src_len + add_len + 0x10, L"%s%c%s", src, FS_PATH_SEPARATOR, add);
|
||||
#else
|
||||
snprintf(new_path, src_len + add_len + 0x10, "%s%c%s", src, FS_PATH_SEPARATOR, add);
|
||||
#endif
|
||||
|
||||
return new_path;
|
||||
}
|
||||
|
||||
fs_char* fs_CopyStr(const fs_char *src)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return strcopy_16to16(src);
|
||||
#else
|
||||
return strcopy_8to8(src);
|
||||
#endif
|
||||
}
|
||||
|
||||
romfs_char* romfs_CopyConvertStr(const fs_char *src)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return strcopy_16to16(src);
|
||||
#else
|
||||
return strcopy_utf8to16(src);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
romfs_char* romfs_CopyStr(const romfs_char *src)
|
||||
{
|
||||
return strcopy_16to16(src);
|
||||
}
|
||||
|
||||
void fs_fputs(const fs_char *str, FILE *out)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fwprintf(out,L"%s", str);
|
||||
#else
|
||||
fprintf(out,"%s", str);
|
||||
#endif
|
||||
}
|
||||
|
||||
void romfs_fputs(const romfs_char *str, FILE *out)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fwprintf(out,L"%s", str);
|
||||
#else
|
||||
const char *name = (const char*)str;
|
||||
for (u32 i = 0; i < romfs_strlen(str)*2; i += 2)
|
||||
fputc(name[i],out);
|
||||
#endif
|
||||
}
|
||||
|
||||
int InitDir(romfs_dir *dir)
|
||||
{
|
||||
@@ -148,13 +44,9 @@ int ManageDir(romfs_dir *dir)
|
||||
int OpenRootDir(const char *path, romfs_dir *dir)
|
||||
{
|
||||
// Create native FS path
|
||||
#ifdef _WIN32
|
||||
dir->path = strcopy_8to16(path);
|
||||
#else
|
||||
dir->path = strcopy_8to8(path);
|
||||
#endif
|
||||
dir->path = os_CopyConvertCharStr(path);
|
||||
// Copy romfs name (empty string)
|
||||
dir->name = romfs_CopyStr(ROMFS_EMPTY_PATH);
|
||||
dir->name = utf16_CopyStr(ROMFS_EMPTY_PATH);
|
||||
dir->namesize = 0;
|
||||
|
||||
return PopulateDir(dir);
|
||||
@@ -162,26 +54,26 @@ int OpenRootDir(const char *path, romfs_dir *dir)
|
||||
|
||||
int PopulateDir(romfs_dir *dir)
|
||||
{
|
||||
fs_DIR *dp, *tmp_dp;
|
||||
struct fs_dirent *entry;
|
||||
_OSDIR *dp, *tmp_dp;
|
||||
struct _osdirent *entry;
|
||||
|
||||
if (InitDir(dir))
|
||||
return MEM_ERROR;
|
||||
|
||||
// Open Directory
|
||||
if((dp = fs_opendir(dir->path)) == NULL)
|
||||
if((dp = os_opendir(dir->path)) == NULL)
|
||||
{
|
||||
printf("[ROMFS] Failed to open directory: \"");
|
||||
fs_fputs(dir->path, stdout);
|
||||
os_fputs(dir->path, stdout);
|
||||
printf("\"\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Process Entries
|
||||
while ((entry = fs_readdir(dp)) != NULL)
|
||||
while ((entry = os_readdir(dp)) != NULL)
|
||||
{
|
||||
// Skip if "." or ".."
|
||||
if (fs_strcmp(entry->d_name, FS_CURRENT_DIR_PATH) == 0 || fs_strcmp(entry->d_name, FS_PARENT_DIR_PATH) == 0)
|
||||
if (os_strcmp(entry->d_name, OS_CURRENT_DIR_PATH) == 0 || os_strcmp(entry->d_name, OS_PARENT_DIR_PATH) == 0)
|
||||
continue;
|
||||
|
||||
// Ensures that there is always memory for child directory and file structs
|
||||
@@ -189,15 +81,15 @@ int PopulateDir(romfs_dir *dir)
|
||||
return MEM_ERROR;
|
||||
|
||||
// Get native FS path
|
||||
fs_char *path = fs_AppendToPath(dir->path, entry->d_name);
|
||||
oschar_t *path = os_AppendToPath(dir->path, entry->d_name);
|
||||
|
||||
// Opening directory with fs path to test if directory
|
||||
if ((tmp_dp = fs_opendir(path)) != NULL) {
|
||||
fs_closedir(tmp_dp);
|
||||
if ((tmp_dp = os_opendir(path)) != NULL) {
|
||||
os_closedir(tmp_dp);
|
||||
|
||||
dir->child[dir->u_child].path = path;
|
||||
dir->child[dir->u_child].name = romfs_CopyConvertStr(entry->d_name);
|
||||
dir->child[dir->u_child].namesize = fs_strlen(entry->d_name)*sizeof(romfs_char);
|
||||
dir->child[dir->u_child].name = utf16_CopyConvertOsStr(entry->d_name);
|
||||
dir->child[dir->u_child].namesize = os_strlen(entry->d_name)*sizeof(utf16char_t);
|
||||
dir->u_child++;
|
||||
|
||||
// Populate directory
|
||||
@@ -206,14 +98,14 @@ int PopulateDir(romfs_dir *dir)
|
||||
// Otherwise this is a file
|
||||
else {
|
||||
dir->file[dir->u_file].path = path;
|
||||
dir->file[dir->u_file].name = romfs_CopyConvertStr(entry->d_name);
|
||||
dir->file[dir->u_file].namesize = fs_strlen(entry->d_name)*sizeof(romfs_char);
|
||||
dir->file[dir->u_file].size = fs_fsize(path);
|
||||
dir->file[dir->u_file].name = utf16_CopyConvertOsStr(entry->d_name);
|
||||
dir->file[dir->u_file].namesize = os_strlen(entry->d_name)*sizeof(utf16char_t);
|
||||
dir->file[dir->u_file].size = os_fsize(path);
|
||||
dir->u_file++;
|
||||
}
|
||||
}
|
||||
|
||||
fs_closedir(dp);
|
||||
os_closedir(dp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -225,7 +117,7 @@ void PrintDir(romfs_dir *dir, u32 depth)
|
||||
printf(" ");
|
||||
|
||||
if (depth > 0)
|
||||
romfs_fputs(dir->name, stdout);
|
||||
utf16_fputs(dir->name, stdout);
|
||||
else
|
||||
printf("romfs:");
|
||||
putchar('\n');
|
||||
@@ -236,7 +128,7 @@ void PrintDir(romfs_dir *dir, u32 depth)
|
||||
{
|
||||
for(u32 j = 0; j < depth+1; j++)
|
||||
printf(" ");
|
||||
romfs_fputs(dir->file[i].name, stdout);
|
||||
utf16_fputs(dir->file[i].name, stdout);
|
||||
printf(" (0x%"PRIx64")\n", dir->file[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-42
@@ -1,39 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#define romfs_char u16
|
||||
#define fs_char wchar_t
|
||||
#define fs_dirent _wdirent
|
||||
#define fs_DIR _WDIR
|
||||
#define fs_readdir _wreaddir
|
||||
#define fs_chdir _wchdir
|
||||
#define fs_opendir _wopendir
|
||||
#define fs_closedir _wclosedir
|
||||
#define FS_PATH_SEPARATOR '\\'
|
||||
#else
|
||||
#define romfs_char u16
|
||||
#define fs_char char
|
||||
#define fs_dirent dirent
|
||||
#define fs_DIR DIR
|
||||
#define fs_readdir readdir
|
||||
#define fs_chdir chdir
|
||||
#define fs_opendir opendir
|
||||
#define fs_closedir closedir
|
||||
#define FS_PATH_SEPARATOR '/'
|
||||
#endif
|
||||
#include "oschar.h"
|
||||
|
||||
struct romfs_file
|
||||
{
|
||||
fs_char *path;
|
||||
romfs_char *name;
|
||||
oschar_t *path;
|
||||
utf16char_t *name;
|
||||
u32 namesize;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
struct romfs_dir
|
||||
{
|
||||
fs_char *path;
|
||||
romfs_char *name;
|
||||
oschar_t *path;
|
||||
utf16char_t *name;
|
||||
u32 namesize;
|
||||
|
||||
struct romfs_dir *child;
|
||||
@@ -48,22 +27,10 @@ struct romfs_dir
|
||||
typedef struct romfs_file romfs_file;
|
||||
typedef struct romfs_dir romfs_dir;
|
||||
|
||||
static const romfs_char ROMFS_EMPTY_PATH[2] = { 0 };
|
||||
static const fs_char FS_EMPTY_PATH[2] = { 0 };
|
||||
static const fs_char FS_CURRENT_DIR_PATH[2] = { '.' };
|
||||
static const fs_char FS_PARENT_DIR_PATH[3] = { '.', '.' };
|
||||
|
||||
u32 romfs_strlen(const romfs_char *str);
|
||||
u32 fs_strlen(const fs_char *str);
|
||||
int fs_strcmp(const fs_char *str1, const fs_char *str2);
|
||||
FILE* fs_fopen(fs_char *path);
|
||||
u64 fs_fsize(fs_char *path);
|
||||
|
||||
fs_char* fs_AppendToPath(const fs_char *src, const fs_char *add);
|
||||
fs_char* fs_CopyStr(const fs_char *src);
|
||||
romfs_char* romfs_CopyStr(const romfs_char *src);
|
||||
void fs_fputs(const fs_char *str, FILE *out);
|
||||
void romfs_fputs(const romfs_char *str, FILE *out);
|
||||
static const utf16char_t ROMFS_EMPTY_PATH[2] = { 0 };
|
||||
static const oschar_t OS_EMPTY_PATH[2] = { 0 };
|
||||
static const oschar_t OS_CURRENT_DIR_PATH[2] = { '.' };
|
||||
static const oschar_t OS_PARENT_DIR_PATH[3] = { '.', '.' };
|
||||
|
||||
int OpenRootDir(const char *path, romfs_dir *dir);
|
||||
void PrintDir(romfs_dir *dir, u32 depth);
|
||||
|
||||
+11
-12
@@ -19,7 +19,7 @@ void PopulateRomfs(romfs_buildctx *ctx);
|
||||
void BuildRomfsHeader(romfs_buildctx *ctx);
|
||||
void BuildIvfcHeader(romfs_buildctx *ctx);
|
||||
void GenIvfcHashTree(romfs_buildctx *ctx);
|
||||
u32 CalcPathHash(u32 parent, const romfs_char* path);
|
||||
u32 CalcPathHash(u32 parent, const utf16char_t* path);
|
||||
|
||||
|
||||
int PrepareBuildRomFsBinary(ncch_settings *ncchset, romfs_buildctx *ctx)
|
||||
@@ -32,7 +32,6 @@ int PrepareBuildRomFsBinary(ncch_settings *ncchset, romfs_buildctx *ctx)
|
||||
/* Import FS and process */
|
||||
OpenRootDir(ncchset->rsfSet->RomFs.RootPath,fs_raw);
|
||||
FilterRomFS(fs_raw,ctx->fs,filter_criteria);
|
||||
|
||||
|
||||
/* free unfiltered FS */
|
||||
FreeDir(fs_raw);
|
||||
@@ -186,10 +185,10 @@ int FilterRomFS(romfs_dir *fs_raw, romfs_dir *fs_filtered, void *filter_criteria
|
||||
if(!IsDirWanted(fs_raw,filter_criteria))
|
||||
return 0;
|
||||
|
||||
fs_filtered->path = fs_CopyStr(fs_raw->path);
|
||||
fs_filtered->path = os_CopyStr(fs_raw->path);
|
||||
|
||||
fs_filtered->namesize = fs_raw->namesize;
|
||||
fs_filtered->name = romfs_CopyStr(fs_raw->name);
|
||||
fs_filtered->name = utf16_CopyStr(fs_raw->name);
|
||||
|
||||
fs_filtered->u_child = 0;
|
||||
fs_filtered->m_child = fs_raw->u_child;
|
||||
@@ -212,10 +211,10 @@ int FilterRomFS(romfs_dir *fs_raw, romfs_dir *fs_filtered, void *filter_criteria
|
||||
{
|
||||
if(IsFileWanted(&fs_raw->file[i],filter_criteria))
|
||||
{
|
||||
fs_filtered->file[fs_filtered->u_file].path = fs_CopyStr(fs_raw->file[i].path);
|
||||
fs_filtered->file[fs_filtered->u_file].path = os_CopyStr(fs_raw->file[i].path);
|
||||
|
||||
fs_filtered->file[fs_filtered->u_file].namesize = fs_raw->file[i].namesize;
|
||||
fs_filtered->file[fs_filtered->u_file].name = romfs_CopyStr(fs_raw->file[i].name);
|
||||
fs_filtered->file[fs_filtered->u_file].name = utf16_CopyStr(fs_raw->file[i].name);
|
||||
|
||||
fs_filtered->file[fs_filtered->u_file].size = fs_raw->file[i].size;
|
||||
|
||||
@@ -277,13 +276,13 @@ void BuildRomfsHeader(romfs_buildctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetFileHashTableIndex(romfs_buildctx *ctx, u32 parent, const romfs_char *path)
|
||||
u32 GetFileHashTableIndex(romfs_buildctx *ctx, u32 parent, const utf16char_t *path)
|
||||
{
|
||||
u32 hash = CalcPathHash(parent, path);
|
||||
return hash % ctx->m_fileHashTable;
|
||||
}
|
||||
|
||||
u32 GetDirHashTableIndex(romfs_buildctx *ctx, u32 parent, const romfs_char* path)
|
||||
u32 GetDirHashTableIndex(romfs_buildctx *ctx, u32 parent, const utf16char_t* path)
|
||||
{
|
||||
u32 hash = CalcPathHash(parent, path);
|
||||
return hash % ctx->m_dirHashTable;
|
||||
@@ -317,11 +316,11 @@ void AddFileToRomfs(romfs_buildctx *ctx, romfs_file *file, u32 parent, u32 sibli
|
||||
|
||||
if (ctx->verbose) {
|
||||
printf("[ROMFS] Reading \"");
|
||||
fs_fputs(file->path, stdout);
|
||||
os_fputs(file->path, stdout);
|
||||
printf("\"... ");
|
||||
}
|
||||
|
||||
FILE *fp = fs_fopen(file->path);
|
||||
FILE *fp = os_fopen(file->path, OS_MODE_READ);
|
||||
fread(data_pos, file->size, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
@@ -463,9 +462,9 @@ void GenIvfcHashTree(romfs_buildctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
u32 CalcPathHash(u32 parent, const romfs_char* path)
|
||||
u32 CalcPathHash(u32 parent, const utf16char_t* path)
|
||||
{
|
||||
u32 len = romfs_strlen(path);
|
||||
u32 len = utf16_strlen(path);
|
||||
u32 hash = parent ^ 123456789;
|
||||
for( u32 i = 0; i < len; i++ )
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "romfs.h"
|
||||
|
||||
int PrepareBuildRomFsBinary(ncch_settings *ncchset, romfs_buildctx *ctx);
|
||||
int BuildRomFsBinary(romfs_buildctx *ctx);
|
||||
|
||||
+1
-1
@@ -44,4 +44,4 @@ typedef uint64_t u64;
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
typedef int64_t s64;
|
||||
-563
@@ -1,563 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001-2004 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Sept 2001: fixed const & error conditions per
|
||||
mods suggested by S. Parent & A. Lillich.
|
||||
June 2002: Tim Dodd added detection and handling of incomplete
|
||||
source sequences, enhanced error detection, added casts
|
||||
to eliminate compiler warnings.
|
||||
July 2003: slight mods to back out aggressive FFFE detection.
|
||||
Jan 2004: updated switches in from-UTF8 conversions.
|
||||
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
|
||||
|
||||
See the header file "utf.h" for complete documentation.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "utf.h"
|
||||
#ifdef CVTUTF_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
static const int halfShift = 10; /* used for shifting by 10 bits */
|
||||
|
||||
static const UTF32 halfBase = 0x0010000UL;
|
||||
static const UTF32 halfMask = 0x3FFUL;
|
||||
|
||||
#define UNI_SUR_HIGH_START (UTF32)0xD800
|
||||
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
|
||||
#define UNI_SUR_LOW_START (UTF32)0xDC00
|
||||
#define UNI_SUR_LOW_END (UTF32)0xDFFF
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Index into the table below with the first byte of a UTF-8 sequence to
|
||||
* get the number of trailing bytes that are supposed to follow it.
|
||||
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
|
||||
* left as-is for anyone who may want to do such conversion, which was
|
||||
* allowed in earlier algorithms.
|
||||
*/
|
||||
static const char trailingBytesForUTF8[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
||||
};
|
||||
|
||||
/*
|
||||
* Magic values subtracted from a buffer value during UTF8 conversion.
|
||||
* This table contains as many values as there might be trailing bytes
|
||||
* in a UTF-8 sequence.
|
||||
*/
|
||||
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
|
||||
|
||||
/*
|
||||
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
|
||||
* into the first byte, depending on how many bytes follow. There are
|
||||
* as many entries in this table as there are UTF-8 sequence types.
|
||||
* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
|
||||
* for *legal* UTF-8 will be 4 or fewer bytes total.
|
||||
*/
|
||||
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* The interface converts a whole buffer to avoid function-call overhead.
|
||||
* Constants have been gathered. Loops & conditionals have been removed as
|
||||
* much as possible for efficiency, in favor of drop-through switches.
|
||||
* (See "Note A" at the bottom of the file for equivalent code.)
|
||||
* If your compiler supports it, the "isLegalUTF8" call can be turned
|
||||
* into an inline function.
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
UTF16* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
if (target >= targetEnd) {
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch = *source++;
|
||||
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
||||
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = (UTF16)ch; /* normal case */
|
||||
}
|
||||
} else if (ch > UNI_MAX_LEGAL_UTF32) {
|
||||
if (flags == strictConversion) {
|
||||
result = sourceIllegal;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if (target + 1 >= targetEnd) {
|
||||
--source; /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch -= halfBase;
|
||||
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
||||
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
UTF32* target = *targetStart;
|
||||
UTF32 ch, ch2;
|
||||
while (source < sourceEnd) {
|
||||
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
|
||||
/* If the 16 bits following the high surrogate are in the source buffer... */
|
||||
if (source < sourceEnd) {
|
||||
ch2 = *source;
|
||||
/* If it's a low surrogate, convert to UTF32. */
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
||||
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
|
||||
++source;
|
||||
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
} else { /* We don't have the 16 bits following the high surrogate. */
|
||||
--source; /* return to the high surrogate */
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
} else if (flags == strictConversion) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (target >= targetEnd) {
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
*target++ = ch;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
#ifdef CVTUTF_DEBUG
|
||||
if (result == sourceIllegal) {
|
||||
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
UTF8* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
|
||||
/* If the 16 bits following the high surrogate are in the source buffer... */
|
||||
if (source < sourceEnd) {
|
||||
UTF32 ch2 = *source;
|
||||
/* If it's a low surrogate, convert to UTF32. */
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
||||
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
|
||||
++source;
|
||||
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
} else { /* We don't have the 16 bits following the high surrogate. */
|
||||
--source; /* return to the high surrogate */
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
} else if (flags == strictConversion) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Figure out how many bytes the result will require */
|
||||
if (ch < (UTF32)0x80) { bytesToWrite = 1;
|
||||
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
|
||||
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
|
||||
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
|
||||
} else { bytesToWrite = 3;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
target -= bytesToWrite; result = targetExhausted; break;
|
||||
}
|
||||
switch (bytesToWrite) { /* note: everything falls through. */
|
||||
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
|
||||
}
|
||||
target += bytesToWrite;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
UTF8* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
ch = *source++;
|
||||
if (flags == strictConversion ) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Figure out how many bytes the result will require. Turn any
|
||||
* illegally large UTF32 things (> Plane 17) into replacement chars.
|
||||
*/
|
||||
if (ch < (UTF32)0x80) { bytesToWrite = 1;
|
||||
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
|
||||
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
|
||||
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
|
||||
} else { bytesToWrite = 3;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
result = sourceIllegal;
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
--source; /* Back up source pointer! */
|
||||
target -= bytesToWrite; result = targetExhausted; break;
|
||||
}
|
||||
switch (bytesToWrite) { /* note: everything falls through. */
|
||||
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
|
||||
}
|
||||
target += bytesToWrite;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
||||
* This must be called with the length pre-determined by the first byte.
|
||||
* If not calling this from ConvertUTF8to*, then the length can be set by:
|
||||
* length = trailingBytesForUTF8[*source]+1;
|
||||
* and the sequence is illegal right away if there aren't that many bytes
|
||||
* available.
|
||||
* If presented with a length > 4, this returns false. The Unicode
|
||||
* definition of UTF-8 goes up to 4-byte sequences.
|
||||
*/
|
||||
|
||||
static Boolean isLegalUTF8(const UTF8 *source, int length) {
|
||||
UTF8 a;
|
||||
const UTF8 *srcptr = source+length;
|
||||
switch (length) {
|
||||
default: return false;
|
||||
/* Everything else falls through when "true"... */
|
||||
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
|
||||
switch (*source) {
|
||||
/* no fall-through in this inner switch */
|
||||
case 0xE0: if (a < 0xA0) return false; break;
|
||||
case 0xED: if (a > 0x9F) return false; break;
|
||||
case 0xF0: if (a < 0x90) return false; break;
|
||||
case 0xF4: if (a > 0x8F) return false; break;
|
||||
default: if (a < 0x80) return false;
|
||||
}
|
||||
|
||||
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
|
||||
}
|
||||
if (*source > 0xF4) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Exported function to return whether a UTF-8 sequence is legal or not.
|
||||
* This is not used here; it's just exported.
|
||||
*/
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
|
||||
int length = trailingBytesForUTF8[*source]+1;
|
||||
if (length > sourceEnd - source) {
|
||||
return false;
|
||||
}
|
||||
return isLegalUTF8(source, length);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Exported function to return the total number of bytes in a codepoint
|
||||
* represented in UTF-8, given the value of the first byte.
|
||||
*/
|
||||
unsigned getNumBytesForUTF8(UTF8 first) {
|
||||
return trailingBytesForUTF8[first] + 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Exported function to return whether a UTF-8 string is legal or not.
|
||||
* This is not used here; it's just exported.
|
||||
*/
|
||||
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd) {
|
||||
while (*source != sourceEnd) {
|
||||
int length = trailingBytesForUTF8[**source] + 1;
|
||||
if (length > sourceEnd - *source || !isLegalUTF8(*source, length))
|
||||
return false;
|
||||
*source += length;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
UTF16* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch = 0;
|
||||
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
||||
if (extraBytesToRead >= sourceEnd - source) {
|
||||
result = sourceExhausted; break;
|
||||
}
|
||||
/* Do this check whether lenient or strict */
|
||||
if (!isLegalUTF8(source, extraBytesToRead+1)) {
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead) {
|
||||
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
||||
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
||||
case 3: ch += *source++; ch <<= 6;
|
||||
case 2: ch += *source++; ch <<= 6;
|
||||
case 1: ch += *source++; ch <<= 6;
|
||||
case 0: ch += *source++;
|
||||
}
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if (target >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = (UTF16)ch; /* normal case */
|
||||
}
|
||||
} else if (ch > UNI_MAX_UTF16) {
|
||||
if (flags == strictConversion) {
|
||||
result = sourceIllegal;
|
||||
source -= (extraBytesToRead+1); /* return to the start */
|
||||
break; /* Bail out; shouldn't continue */
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if (target + 1 >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch -= halfBase;
|
||||
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
||||
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
UTF32* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch = 0;
|
||||
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
||||
if (extraBytesToRead >= sourceEnd - source) {
|
||||
result = sourceExhausted; break;
|
||||
}
|
||||
/* Do this check whether lenient or strict */
|
||||
if (!isLegalUTF8(source, extraBytesToRead+1)) {
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead) {
|
||||
case 5: ch += *source++; ch <<= 6;
|
||||
case 4: ch += *source++; ch <<= 6;
|
||||
case 3: ch += *source++; ch <<= 6;
|
||||
case 2: ch += *source++; ch <<= 6;
|
||||
case 1: ch += *source++; ch <<= 6;
|
||||
case 0: ch += *source++;
|
||||
}
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if (target >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up the source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
if (ch <= UNI_MAX_LEGAL_UTF32) {
|
||||
/*
|
||||
* UTF-16 surrogate values are illegal in UTF-32, and anything
|
||||
* over Plane 17 (> 0x10FFFF) is illegal.
|
||||
*/
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = ch;
|
||||
}
|
||||
} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
|
||||
result = sourceIllegal;
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Note A.
|
||||
The fall-through switches in UTF-8 reading code save a
|
||||
temp variable, some decrements & conditionals. The switches
|
||||
are equivalent to the following loop:
|
||||
{
|
||||
int tmpBytesToRead = extraBytesToRead+1;
|
||||
do {
|
||||
ch += *source++;
|
||||
--tmpBytesToRead;
|
||||
if (tmpBytesToRead) ch <<= 6;
|
||||
} while (tmpBytesToRead > 0);
|
||||
}
|
||||
In UTF-8 writing code, the switches on "bytesToWrite" are
|
||||
similarly unrolled loops.
|
||||
|
||||
--------------------------------------------------------------------- */
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright 2001-2004 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Header file.
|
||||
|
||||
Several funtions are included here, forming a complete set of
|
||||
conversions between the three formats. UTF-7 is not included
|
||||
here, but is handled in a separate source file.
|
||||
|
||||
Each of these routines takes pointers to input buffers and output
|
||||
buffers. The input buffers are const.
|
||||
|
||||
Each routine converts the text between *sourceStart and sourceEnd,
|
||||
putting the result into the buffer between *targetStart and
|
||||
targetEnd. Note: the end pointers are *after* the last item: e.g.
|
||||
*(sourceEnd - 1) is the last item.
|
||||
|
||||
The return result indicates whether the conversion was successful,
|
||||
and if not, whether the problem was in the source or target buffers.
|
||||
(Only the first encountered problem is indicated.)
|
||||
|
||||
After the conversion, *sourceStart and *targetStart are both
|
||||
updated to point to the end of last text successfully converted in
|
||||
the respective buffers.
|
||||
|
||||
Input parameters:
|
||||
sourceStart - pointer to a pointer to the source buffer.
|
||||
The contents of this are modified on return so that
|
||||
it points at the next thing to be converted.
|
||||
targetStart - similarly, pointer to pointer to the target buffer.
|
||||
sourceEnd, targetEnd - respectively pointers to the ends of the
|
||||
two buffers, for overflow checking only.
|
||||
|
||||
These conversion functions take a ConversionFlags argument. When this
|
||||
flag is set to strict, both irregular sequences and isolated surrogates
|
||||
will cause an error. When the flag is set to lenient, both irregular
|
||||
sequences and isolated surrogates are converted.
|
||||
|
||||
Whether the flag is strict or lenient, all illegal sequences will cause
|
||||
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
|
||||
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
|
||||
must check for illegal sequences.
|
||||
|
||||
When the flag is set to lenient, characters over 0x10FFFF are converted
|
||||
to the replacement character; otherwise (when the flag is set to strict)
|
||||
they constitute an error.
|
||||
|
||||
Output parameters:
|
||||
The value "sourceIllegal" is returned from some routines if the input
|
||||
sequence is malformed. When "sourceIllegal" is returned, the source
|
||||
value will point to the illegal value that caused the problem. E.g.,
|
||||
in UTF-8 when a sequence is malformed, it points to the start of the
|
||||
malformed sequence.
|
||||
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Fixes & updates, Sept 2001.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#pragma once
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
The following 4 definitions are compiler-specific.
|
||||
The C standard does not guarantee that wchar_t has at least
|
||||
16 bits, so wchar_t is no less portable than unsigned short!
|
||||
All should be unsigned values to avoid sign extension during
|
||||
bit mask & shift operations.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
typedef unsigned int UTF32; /* at least 32 bits */
|
||||
typedef unsigned short UTF16; /* at least 16 bits */
|
||||
typedef unsigned char UTF8; /* typically 8 bits */
|
||||
typedef unsigned char Boolean; /* 0 or 1 */
|
||||
|
||||
/* Some fundamental constants */
|
||||
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
|
||||
#define UNI_MAX_BMP (UTF32)0x0000FFFF
|
||||
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
|
||||
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
|
||||
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
|
||||
|
||||
#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4
|
||||
|
||||
#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF
|
||||
#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE
|
||||
|
||||
typedef enum {
|
||||
conversionOK, /* conversion successful */
|
||||
sourceExhausted, /* partial character in source, but hit end */
|
||||
targetExhausted, /* insuff. room in target for conversion */
|
||||
sourceIllegal /* source sequence is illegal/malformed */
|
||||
} ConversionResult;
|
||||
|
||||
typedef enum {
|
||||
strictConversion = 0,
|
||||
lenientConversion
|
||||
} ConversionFlags;
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (
|
||||
const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
|
||||
|
||||
unsigned getNumBytesForUTF8(UTF8 first);
|
||||
|
||||
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd);
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
+3
-99
@@ -1,5 +1,7 @@
|
||||
#include "lib.h"
|
||||
#include "utf.h"
|
||||
#ifndef _WIN32
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include "polarssl/base64.h"
|
||||
|
||||
@@ -106,95 +108,6 @@ void memdump(FILE* fout, const char* prefix, const u8* data, u32 size)
|
||||
}
|
||||
}
|
||||
|
||||
u32 strlen_char16(const u16 *str)
|
||||
{
|
||||
u32 i;
|
||||
for (i = 0; str[i] != 0x0; i++);
|
||||
return i;
|
||||
}
|
||||
|
||||
char* strcopy_8to8(const char *src)
|
||||
{
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
u32 src_len = strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
char *dst = calloc(src_len + 1, sizeof(u8));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
strncpy(dst, src, src_len);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
u16* strcopy_8to16(const char *src)
|
||||
{
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
u32 src_len = strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
u16 *dst = calloc(src_len+1, sizeof(u16));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
for (u32 i = 0; i < src_len; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
u16* strcopy_16to16(const u16 *src)
|
||||
{
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
u32 src_len = strlen_char16(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
u16 *dst = calloc(src_len + 1, sizeof(u16));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
// Copy elements from src into dst
|
||||
for (u32 i = 0; i < src_len; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
u16* strcopy_utf8to16(const char *src)
|
||||
{
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
u32 src_len = strlen(src);
|
||||
|
||||
// Allocate memory for expanded string
|
||||
u16 *dst = calloc(src_len + 1, sizeof(u16));
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
UTF16 *target_start = dst;
|
||||
UTF16 *target_end = (target_start + (src_len*sizeof(u16)));
|
||||
|
||||
UTF8 *src_start = (UTF8*)src;
|
||||
UTF8 *src_end = (UTF8*)(src + src_len*sizeof(char));
|
||||
|
||||
ConvertUTF8toUTF16((const UTF8 **)&src_start, src_end, &target_start, target_end, strictConversion);
|
||||
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Base64
|
||||
bool IsValidB64Char(char chr)
|
||||
{
|
||||
@@ -347,15 +260,6 @@ int TruncateFile64(char *filename, u64 filelen)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Wide Char IO
|
||||
#ifdef _WIN32
|
||||
u64 wGetFileSize64(u16 *filename)
|
||||
{
|
||||
struct _stat64 st;
|
||||
_wstat64((wchar_t*)filename, &st);
|
||||
return st.st_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
//IO Misc
|
||||
u8* ImportFile(char *file, u64 size)
|
||||
|
||||
@@ -20,13 +20,6 @@ u64 max64(u64 a, u64 b);
|
||||
// Strings
|
||||
void memdump(FILE* fout, const char* prefix, const const u8* data, u32 size);
|
||||
char* replace_filextention(const char *input, const char *extention);
|
||||
u32 strlen_char16(const u16 *str);
|
||||
char* strcopy_8to8(const char *src);
|
||||
u16* strcopy_8to16(const char *src);
|
||||
u16* strcopy_16to16(const u16 *src);
|
||||
#ifndef _WIN32
|
||||
u16* strcopy_utf8to16(const char *src);
|
||||
#endif
|
||||
|
||||
// Base64
|
||||
bool IsValidB64Char(char chr);
|
||||
@@ -45,14 +38,8 @@ u64 u64GetRand(void);
|
||||
bool AssertFile(char *filename);
|
||||
u64 GetFileSize64(char *filename);
|
||||
int makedir(const char* dir);
|
||||
char *getcwdir(char *buffer,int maxlen);
|
||||
int TruncateFile64(char *filename, u64 filelen);
|
||||
|
||||
//Wide Char IO
|
||||
#ifdef _WIN32
|
||||
u64 wGetFileSize64(u16 *filename);
|
||||
#endif
|
||||
|
||||
//IO Misc
|
||||
u8* ImportFile(char *file, u64 size);
|
||||
void WriteBuffer(const void *buffer, u64 size, u64 offset, FILE *output);
|
||||
|
||||
Reference in New Issue
Block a user