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:
yellows8 2017-11-23 15:00:56 -05:00
parent 0bc5be0708
commit 25f2839c75
18 changed files with 2166 additions and 10 deletions

View File

@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
TARGET := nx TARGET := nx
#BUILD := build #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 DATA := data
INCLUDES := include INCLUDES := include

View File

@ -21,6 +21,8 @@ extern "C" {
#include <switch/kernel/virtmem.h> #include <switch/kernel/virtmem.h>
#include <switch/kernel/version.h> #include <switch/kernel/version.h>
#include <switch/util/utf.h>
#include <switch/services/sm.h> #include <switch/services/sm.h>
#include <switch/services/fs.h> #include <switch/services/fs.h>
#include <switch/services/applet.h> #include <switch/services/applet.h>
@ -38,6 +40,7 @@ extern "C" {
#include <switch/gfx/ioctl.h> #include <switch/gfx/ioctl.h>
#include <switch/devices/usb_comms.h> #include <switch/devices/usb_comms.h>
#include <switch/devices/fs_dev.h>
#ifdef __cplusplus #ifdef __cplusplus
} }

View 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);

View File

@ -2,6 +2,8 @@
// We use wrapped handles for type safety. // We use wrapped handles for type safety.
#define FS_MAX_PATH 0x301
typedef struct { typedef struct {
Handle h; Handle h;
} FsFileSystem; } FsFileSystem;
@ -18,12 +20,39 @@ typedef struct {
Handle h; Handle h;
} FsStorage; } 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 { typedef enum {
ENTRYTYPE_FILE=0, ENTRYTYPE_FILE=0,
ENTRYTYPE_DIR =1 ENTRYTYPE_DIR =1
} FsEntryType; } 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(); Result fsInitialize();
void fsExit(void); void fsExit(void);
@ -51,11 +80,15 @@ void fsFsClose(FsFileSystem* fs);
// IFile // IFile
Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, size_t* out); 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 fsFileFlush(FsFile* f);
Result fsFileSetSize(FsFile* f, u64 sz); Result fsFileSetSize(FsFile* f, u64 sz);
Result fsFileGetSize(FsFile* f, u64* out); Result fsFileGetSize(FsFile* f, u64* out);
void fsFileClose(FsFile* f); 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 // todo: IStorage

View 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

File diff suppressed because it is too large Load Diff

View File

@ -254,7 +254,7 @@ Result fsFsDeleteDirectoryRecursively(FsFileSystem* fs, const char* path) {
return rc; return rc;
} }
Result fsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) { Result fsFsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0); ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0);
@ -287,7 +287,7 @@ Result fsRenameFile(FsFileSystem* fs, const char* path0, const char* path1) {
return rc; return rc;
} }
Result fsRenameDirectory(FsFileSystem* fs, const char* path0, const char* path1) { Result fsFsRenameDirectory(FsFileSystem* fs, const char* path0, const char* path1) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendStatic(&c, path0, FS_MAX_PATH, 0); 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; 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; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendBuffer(&c, buf, len, 1); ipcAddSendBuffer(&c, buf, len, 1);
@ -717,7 +717,8 @@ Result fsFileGetSize(FsFile* f, u64* out) {
u64 size; u64 size;
} *resp = r.Raw; } *resp = r.Raw;
rc = resp->size; rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->size;
} }
return rc; return rc;
@ -727,3 +728,80 @@ void fsFileClose(FsFile* f) {
svcCloseHandle(f->h); 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;
}

View File

@ -32,17 +32,21 @@ void __attribute__((weak)) __appInit(void)
{ {
// Initialize default services. // Initialize default services.
smInitialize(); smInitialize();
fsInitialize();
appletInitialize(); appletInitialize();
hidInitialize(); hidInitialize();
fsInitialize();
//fsdevInit();
} }
void __attribute__((weak)) __appExit(void) void __attribute__((weak)) __appExit(void)
{ {
// Cleanup default services. // Cleanup default services.
//fsdevExit();
fsExit();
hidExit(); hidExit();
appletExit(); appletExit();
fsExit();
smExit(); smExit();
} }

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}