mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
Imported util/utf from libctru. Updated appInit/appExit. Fs adjustments + implemented IDirectory. Imported a modified version of sdmc_dev from libctru as fs_dev, this currently isn't usable.
This commit is contained in:
parent
0bc5be0708
commit
25f2839c75
@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH)
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := nx
|
||||
#BUILD := build
|
||||
SOURCES := source/arm source/system source/kernel source/services source/gfx source/devices
|
||||
SOURCES := source/arm source/system source/kernel source/services source/gfx source/devices source/util/utf
|
||||
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
@ -21,6 +21,8 @@ extern "C" {
|
||||
#include <switch/kernel/virtmem.h>
|
||||
#include <switch/kernel/version.h>
|
||||
|
||||
#include <switch/util/utf.h>
|
||||
|
||||
#include <switch/services/sm.h>
|
||||
#include <switch/services/fs.h>
|
||||
#include <switch/services/applet.h>
|
||||
@ -38,6 +40,7 @@ extern "C" {
|
||||
#include <switch/gfx/ioctl.h>
|
||||
|
||||
#include <switch/devices/usb_comms.h>
|
||||
#include <switch/devices/fs_dev.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
17
nx/include/switch/devices/fs_dev.h
Normal file
17
nx/include/switch/devices/fs_dev.h
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @file fs_dev.h
|
||||
* @brief FS driver.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//NOTE: This is currently not usable.
|
||||
|
||||
/// Initializes the FS driver.
|
||||
Result fsdevInit(void);
|
||||
|
||||
/// Enable/disable copy in fsdev_write
|
||||
void fsdevWriteSafe(bool enable);
|
||||
|
||||
/// Exits the FS driver.
|
||||
Result fsdevExit(void);
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
// We use wrapped handles for type safety.
|
||||
|
||||
#define FS_MAX_PATH 0x301
|
||||
|
||||
typedef struct {
|
||||
Handle h;
|
||||
} FsFileSystem;
|
||||
@ -18,12 +20,39 @@ typedef struct {
|
||||
Handle h;
|
||||
} FsStorage;
|
||||
|
||||
/// Directory entry.
|
||||
typedef struct
|
||||
{
|
||||
char name[FS_MAX_PATH]; ///< Entry name.
|
||||
u8 pad[3];
|
||||
u32 attributes; ///< Attributes.
|
||||
u64 fileSize; ///< File size.
|
||||
} FsDirectoryEntry;
|
||||
|
||||
typedef enum {
|
||||
ENTRYTYPE_FILE=0,
|
||||
ENTRYTYPE_DIR =1
|
||||
} FsEntryType;
|
||||
|
||||
#define FS_MAX_PATH 0x301
|
||||
typedef enum
|
||||
{
|
||||
FS_OPEN_READ = BIT(0), ///< Open for reading.
|
||||
FS_OPEN_WRITE = BIT(1), ///< Open for writing.
|
||||
FS_OPEN_APPEND = BIT(2), ///< Append file.
|
||||
} FsFileFlags;
|
||||
|
||||
/// For use with fsFsOpenDirectory.
|
||||
typedef enum
|
||||
{
|
||||
FS_DIROPEN_DIRECTORY = BIT(0), ///< Enable reading directory entries.
|
||||
FS_DIROPEN_FILE = BIT(1), ///< Enable reading file entries.
|
||||
} FsDirectoryFlags;
|
||||
|
||||
/// Attribute flags.
|
||||
typedef enum
|
||||
{
|
||||
FS_ATTRIBUTE_FILE = BIT(0), ///< File.
|
||||
} FsAttribute;
|
||||
|
||||
Result fsInitialize();
|
||||
void fsExit(void);
|
||||
@ -51,11 +80,15 @@ void fsFsClose(FsFileSystem* fs);
|
||||
|
||||
// IFile
|
||||
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out);
|
||||
Result fsFileWrite(FsFile* f, u64 off, void* buf, size_t len, size_t* out);
|
||||
Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len, size_t* out);
|
||||
Result fsFileFlush(FsFile* f);
|
||||
Result fsFileSetSize(FsFile* f, u64 sz);
|
||||
Result fsFileGetSize(FsFile* f, u64* out);
|
||||
void fsFileClose(FsFile* f);
|
||||
|
||||
// todo: IDirectory
|
||||
// IDirectory
|
||||
Result fsDirRead(FsDir* d, u64 inval, size_t* total_entries, size_t max_entries, FsDirectoryEntry *buf);
|
||||
Result fsDirGetEntryCount(FsDir* d, u64* count);
|
||||
void fsDirClose(FsDir* d);
|
||||
|
||||
// todo: IStorage
|
||||
|
156
nx/include/switch/util/utf.h
Normal file
156
nx/include/switch/util/utf.h
Normal file
@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @file utf.h
|
||||
* @brief UTF conversion functions.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/** Convert a UTF-8 sequence into a UTF-32 codepoint
|
||||
*
|
||||
* @param[out] out Output codepoint
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of input code units consumed
|
||||
* @returns -1 for error
|
||||
*/
|
||||
ssize_t decode_utf8 (uint32_t *out, const uint8_t *in);
|
||||
|
||||
/** Convert a UTF-16 sequence into a UTF-32 codepoint
|
||||
*
|
||||
* @param[out] out Output codepoint
|
||||
* @param[in] in Input sequence
|
||||
*
|
||||
* @returns number of input code units consumed
|
||||
* @returns -1 for error
|
||||
*/
|
||||
ssize_t decode_utf16(uint32_t *out, const uint16_t *in);
|
||||
|
||||
/** Convert a UTF-32 codepoint into a UTF-8 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input codepoint
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out must be able to store 4 code units
|
||||
*/
|
||||
ssize_t encode_utf8 (uint8_t *out, uint32_t in);
|
||||
|
||||
/** Convert a UTF-32 codepoint into a UTF-16 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input codepoint
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out must be able to store 2 code units
|
||||
*/
|
||||
ssize_t encode_utf16(uint16_t *out, uint32_t in);
|
||||
|
||||
/** Convert a UTF-8 sequence into a UTF-16 sequence
|
||||
*
|
||||
* Fills the output buffer up to \a len code units.
|
||||
* Returns the number of code units that the input would produce;
|
||||
* if it returns greater than \a len, the output has been
|
||||
* truncated.
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence (null-terminated)
|
||||
* @param[in] len Output length
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out is not null-terminated
|
||||
*/
|
||||
ssize_t utf8_to_utf16(uint16_t *out, const uint8_t *in, size_t len);
|
||||
|
||||
/** Convert a UTF-8 sequence into a UTF-32 sequence
|
||||
*
|
||||
* Fills the output buffer up to \a len code units.
|
||||
* Returns the number of code units that the input would produce;
|
||||
* if it returns greater than \a len, the output has been
|
||||
* truncated.
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence (null-terminated)
|
||||
* @param[in] len Output length
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out is not null-terminated
|
||||
*/
|
||||
ssize_t utf8_to_utf32(uint32_t *out, const uint8_t *in, size_t len);
|
||||
|
||||
/** Convert a UTF-16 sequence into a UTF-8 sequence
|
||||
*
|
||||
* Fills the output buffer up to \a len code units.
|
||||
* Returns the number of code units that the input would produce;
|
||||
* if it returns greater than \a len, the output has been
|
||||
* truncated.
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence (null-terminated)
|
||||
* @param[in] len Output length
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out is not null-terminated
|
||||
*/
|
||||
ssize_t utf16_to_utf8(uint8_t *out, const uint16_t *in, size_t len);
|
||||
|
||||
/** Convert a UTF-16 sequence into a UTF-32 sequence
|
||||
*
|
||||
* Fills the output buffer up to \a len code units.
|
||||
* Returns the number of code units that the input would produce;
|
||||
* if it returns greater than \a len, the output has been
|
||||
* truncated.
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence (null-terminated)
|
||||
* @param[in] len Output length
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out is not null-terminated
|
||||
*/
|
||||
ssize_t utf16_to_utf32(uint32_t *out, const uint16_t *in, size_t len);
|
||||
|
||||
/** Convert a UTF-32 sequence into a UTF-8 sequence
|
||||
*
|
||||
* Fills the output buffer up to \a len code units.
|
||||
* Returns the number of code units that the input would produce;
|
||||
* if it returns greater than \a len, the output has been
|
||||
* truncated.
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence (null-terminated)
|
||||
* @param[in] len Output length
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out is not null-terminated
|
||||
*/
|
||||
ssize_t utf32_to_utf8(uint8_t *out, const uint32_t *in, size_t len);
|
||||
|
||||
/** Convert a UTF-32 sequence into a UTF-16 sequence
|
||||
*
|
||||
* @param[out] out Output sequence
|
||||
* @param[in] in Input sequence (null-terminated)
|
||||
* @param[in] len Output length
|
||||
*
|
||||
* @returns number of output code units produced
|
||||
* @returns -1 for error
|
||||
*
|
||||
* @note \a out is not null-terminated
|
||||
*/
|
||||
ssize_t utf32_to_utf16(uint16_t *out, const uint32_t *in, size_t len);
|
||||
|
1436
nx/source/devices/fs_dev.c
Normal file
1436
nx/source/devices/fs_dev.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -254,7 +254,7 @@ Result fsFsDeleteDirectoryRecursively(FsFileSystem* fs, const char* path) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result fsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
|
||||
Result fsFsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0);
|
||||
@ -287,7 +287,7 @@ Result fsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result fsRenameDirectory(FsFileSystem* fs, const char* path0, const char* path1) {
|
||||
Result fsFsRenameDirectory(FsFileSystem* fs, const char* path0, const char* path1) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0);
|
||||
@ -584,7 +584,7 @@ Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result fsFileWrite(FsFile* f, u64 off, void* buf, size_t len, size_t* out) {
|
||||
Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len, size_t* out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
ipcAddSendBuffer(&c, buf, len, 1);
|
||||
@ -717,7 +717,8 @@ Result fsFileGetSize(FsFile* f, u64* out) {
|
||||
u64 size;
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->size;
|
||||
rc = resp->result;
|
||||
if (R_SUCCEEDED(rc) && out) *out = resp->size;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -727,3 +728,80 @@ void fsFileClose(FsFile* f) {
|
||||
svcCloseHandle(f->h);
|
||||
}
|
||||
|
||||
// IDirectory implementation
|
||||
void fsDirClose(FsDir* d) {
|
||||
svcCloseHandle(d->h);
|
||||
}
|
||||
|
||||
Result fsDirRead(FsDir* d, u64 inval, size_t* total_entries, size_t max_entries, FsDirectoryEntry *buf) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
ipcAddRecvBuffer(&c, buf, sizeof(FsDirectoryEntry)*max_entries, 0);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u64 inval;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 0;
|
||||
raw->inval = inval;
|
||||
|
||||
Result rc = ipcDispatch(d->h);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcCommandResponse r;
|
||||
ipcParseResponse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u64 total_entries;
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (total_entries) *total_entries = resp->total_entries;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result fsDirGetEntryCount(FsDir* d, u64* count) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 1;
|
||||
|
||||
Result rc = ipcDispatch(d->h);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcCommandResponse r;
|
||||
ipcParseResponse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u64 count;
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
if (R_SUCCEEDED(rc) && count) *count = resp->count;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -32,17 +32,21 @@ void __attribute__((weak)) __appInit(void)
|
||||
{
|
||||
// Initialize default services.
|
||||
smInitialize();
|
||||
fsInitialize();
|
||||
appletInitialize();
|
||||
hidInitialize();
|
||||
|
||||
fsInitialize();
|
||||
//fsdevInit();
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __appExit(void)
|
||||
{
|
||||
// Cleanup default services.
|
||||
//fsdevExit();
|
||||
fsExit();
|
||||
|
||||
hidExit();
|
||||
appletExit();
|
||||
fsExit();
|
||||
smExit();
|
||||
}
|
||||
|
||||
|
26
nx/source/util/utf/decode_utf16.c
Normal file
26
nx/source/util/utf/decode_utf16.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "switch/types.h"
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
decode_utf16(uint32_t *out,
|
||||
const uint16_t *in)
|
||||
{
|
||||
uint16_t code1, code2;
|
||||
|
||||
code1 = *in++;
|
||||
if(code1 >= 0xD800 && code1 < 0xDC00)
|
||||
{
|
||||
/* surrogate pair */
|
||||
code2 = *in++;
|
||||
if(code2 >= 0xDC00 && code2 < 0xE000)
|
||||
{
|
||||
*out = (code1 << 10) + code2 - 0x35FDC00;
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = code1;
|
||||
return 1;
|
||||
}
|
88
nx/source/util/utf/decode_utf8.c
Normal file
88
nx/source/util/utf/decode_utf8.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
decode_utf8(uint32_t *out,
|
||||
const uint8_t *in)
|
||||
{
|
||||
uint8_t code1, code2, code3, code4;
|
||||
|
||||
code1 = *in++;
|
||||
if(code1 < 0x80)
|
||||
{
|
||||
/* 1-byte sequence */
|
||||
*out = code1;
|
||||
return 1;
|
||||
}
|
||||
else if(code1 < 0xC2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if(code1 < 0xE0)
|
||||
{
|
||||
/* 2-byte sequence */
|
||||
code2 = *in++;
|
||||
if((code2 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (code1 << 6) + code2 - 0x3080;
|
||||
return 2;
|
||||
}
|
||||
else if(code1 < 0xF0)
|
||||
{
|
||||
/* 3-byte sequence */
|
||||
code2 = *in++;
|
||||
if((code2 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if(code1 == 0xE0 && code2 < 0xA0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
code3 = *in++;
|
||||
if((code3 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (code1 << 12) + (code2 << 6) + code3 - 0xE2080;
|
||||
return 3;
|
||||
}
|
||||
else if(code1 < 0xF5)
|
||||
{
|
||||
/* 4-byte sequence */
|
||||
code2 = *in++;
|
||||
if((code2 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if(code1 == 0xF0 && code2 < 0x90)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if(code1 == 0xF4 && code2 >= 0x90)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
code3 = *in++;
|
||||
if((code3 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
code4 = *in++;
|
||||
if((code4 & 0xC0) != 0x80)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (code1 << 18) + (code2 << 12) + (code3 << 6) + code4 - 0x3C82080;
|
||||
return 4;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
24
nx/source/util/utf/encode_utf16.c
Normal file
24
nx/source/util/utf/encode_utf16.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
encode_utf16(uint16_t *out,
|
||||
uint32_t in)
|
||||
{
|
||||
if(in < 0x10000)
|
||||
{
|
||||
if(out != NULL)
|
||||
*out++ = in;
|
||||
return 1;
|
||||
}
|
||||
else if(in < 0x110000)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 10) + 0xD7C0;
|
||||
*out++ = (in & 0x3FF) + 0xDC00;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
45
nx/source/util/utf/encode_utf8.c
Normal file
45
nx/source/util/utf/encode_utf8.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
encode_utf8(uint8_t *out,
|
||||
uint32_t in)
|
||||
{
|
||||
if(in < 0x80)
|
||||
{
|
||||
if(out != NULL)
|
||||
*out++ = in;
|
||||
return 1;
|
||||
}
|
||||
else if(in < 0x800)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 6) + 0xC0;
|
||||
*out++ = (in & 0x3F) + 0x80;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
else if(in < 0x10000)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 12) + 0xE0;
|
||||
*out++ = ((in >> 6) & 0x3F) + 0x80;
|
||||
*out++ = (in & 0x3F) + 0x80;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
else if(in < 0x110000)
|
||||
{
|
||||
if(out != NULL)
|
||||
{
|
||||
*out++ = (in >> 18) + 0xF0;
|
||||
*out++ = ((in >> 12) & 0x3F) + 0x80;
|
||||
*out++ = ((in >> 6) & 0x3F) + 0x80;
|
||||
*out++ = (in & 0x3F) + 0x80;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
37
nx/source/util/utf/utf16_to_utf32.c
Normal file
37
nx/source/util/utf/utf16_to_utf32.c
Normal file
@ -0,0 +1,37 @@
|
||||
#include "switch/types.h"
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
utf16_to_utf32(uint32_t *out,
|
||||
const uint16_t *in,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
ssize_t units;
|
||||
uint32_t code;
|
||||
|
||||
do
|
||||
{
|
||||
units = decode_utf16(&code, in);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(code > 0)
|
||||
{
|
||||
in += units;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc < len)
|
||||
*out++ = code;
|
||||
}
|
||||
|
||||
if(SSIZE_MAX - 1 >= rc)
|
||||
++rc;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
} while(code > 0);
|
||||
|
||||
return rc;
|
||||
}
|
50
nx/source/util/utf/utf16_to_utf8.c
Normal file
50
nx/source/util/utf/utf16_to_utf8.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include "switch/types.h"
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
utf16_to_utf8(uint8_t *out,
|
||||
const uint16_t *in,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
ssize_t units;
|
||||
uint32_t code;
|
||||
uint8_t encoded[4];
|
||||
|
||||
do
|
||||
{
|
||||
units = decode_utf16(&code, in);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(code > 0)
|
||||
{
|
||||
in += units;
|
||||
|
||||
units = encode_utf8(encoded, code);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc + units <= len)
|
||||
{
|
||||
*out++ = encoded[0];
|
||||
if(units > 1)
|
||||
*out++ = encoded[1];
|
||||
if(units > 2)
|
||||
*out++ = encoded[2];
|
||||
if(units > 3)
|
||||
*out++ = encoded[3];
|
||||
}
|
||||
}
|
||||
|
||||
if(SSIZE_MAX - units >= rc)
|
||||
rc += units;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
} while(code > 0);
|
||||
|
||||
return rc;
|
||||
}
|
36
nx/source/util/utf/utf32_to_utf16.c
Normal file
36
nx/source/util/utf/utf32_to_utf16.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "switch/types.h"
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
utf32_to_utf16(uint16_t *out,
|
||||
const uint32_t *in,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
ssize_t units;
|
||||
uint16_t encoded[2];
|
||||
|
||||
while(*in > 0)
|
||||
{
|
||||
units = encode_utf16(encoded, *in++);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc + units <= len)
|
||||
{
|
||||
*out++ = encoded[0];
|
||||
if(units > 1)
|
||||
*out++ = encoded[1];
|
||||
}
|
||||
}
|
||||
|
||||
if(SSIZE_MAX - units >= rc)
|
||||
rc += units;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
40
nx/source/util/utf/utf32_to_utf8.c
Normal file
40
nx/source/util/utf/utf32_to_utf8.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include "switch/types.h"
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
utf32_to_utf8(uint8_t *out,
|
||||
const uint32_t *in,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
ssize_t units;
|
||||
uint8_t encoded[4];
|
||||
|
||||
while(*in > 0)
|
||||
{
|
||||
units = encode_utf8(encoded, *in++);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc + units <= len)
|
||||
{
|
||||
*out++ = encoded[0];
|
||||
if(units > 1)
|
||||
*out++ = encoded[1];
|
||||
if(units > 2)
|
||||
*out++ = encoded[2];
|
||||
if(units > 3)
|
||||
*out++ = encoded[3];
|
||||
}
|
||||
}
|
||||
|
||||
if(SSIZE_MAX - units >= rc)
|
||||
rc += units;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
46
nx/source/util/utf/utf8_to_utf16.c
Normal file
46
nx/source/util/utf/utf8_to_utf16.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "switch/types.h"
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
utf8_to_utf16(uint16_t *out,
|
||||
const uint8_t *in,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
ssize_t units;
|
||||
uint32_t code;
|
||||
uint16_t encoded[2];
|
||||
|
||||
do
|
||||
{
|
||||
units = decode_utf8(&code, in);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(code > 0)
|
||||
{
|
||||
in += units;
|
||||
|
||||
units = encode_utf16(encoded, code);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc + units <= len)
|
||||
{
|
||||
*out++ = encoded[0];
|
||||
if(units > 1)
|
||||
*out++ = encoded[1];
|
||||
}
|
||||
}
|
||||
|
||||
if(SSIZE_MAX - units >= rc)
|
||||
rc += units;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
} while(code > 0);
|
||||
|
||||
return rc;
|
||||
}
|
37
nx/source/util/utf/utf8_to_utf32.c
Normal file
37
nx/source/util/utf/utf8_to_utf32.c
Normal file
@ -0,0 +1,37 @@
|
||||
#include "switch/types.h"
|
||||
#include "switch/util/utf.h"
|
||||
|
||||
ssize_t
|
||||
utf8_to_utf32(uint32_t *out,
|
||||
const uint8_t *in,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
ssize_t units;
|
||||
uint32_t code;
|
||||
|
||||
do
|
||||
{
|
||||
units = decode_utf8(&code, in);
|
||||
if(units == -1)
|
||||
return -1;
|
||||
|
||||
if(code > 0)
|
||||
{
|
||||
in += units;
|
||||
|
||||
if(out != NULL)
|
||||
{
|
||||
if(rc < len)
|
||||
*out++ = code;
|
||||
}
|
||||
|
||||
if(SSIZE_MAX - 1 >= rc)
|
||||
++rc;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
} while(code > 0);
|
||||
|
||||
return rc;
|
||||
}
|
Loading…
Reference in New Issue
Block a user