Updated the classes in sfwl. Also added coloir to it as it's quite useful.

This commit is contained in:
Relintai 2024-01-20 10:27:23 +01:00
parent 8e2f809e02
commit 2564606779
77 changed files with 11426 additions and 1054 deletions

View File

@ -1,831 +0,0 @@
/*
Copyright (c) 2013-2019, tinydir authors:
- Cong Xu
- Lautis Sun
- Baudouin Feildel
- Andargor <andargor@yahoo.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TINYDIR_H
#define TINYDIR_H
#ifdef __cplusplus
extern "C" {
#endif
#if ((defined _UNICODE) && !(defined UNICODE))
#define UNICODE
#endif
#if ((defined UNICODE) && !(defined _UNICODE))
#define _UNICODE
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <tchar.h>
# pragma warning(push)
# pragma warning (disable : 4996)
#else
# include <dirent.h>
# include <libgen.h>
# include <sys/stat.h>
# include <stddef.h>
#endif
#ifdef __MINGW32__
# include <tchar.h>
#endif
/* types */
/* Windows UNICODE wide character support */
#if defined _MSC_VER || defined __MINGW32__
# define _tinydir_char_t TCHAR
# define TINYDIR_STRING(s) _TEXT(s)
# define _tinydir_strlen _tcslen
# define _tinydir_strcpy _tcscpy
# define _tinydir_strcat _tcscat
# define _tinydir_strcmp _tcscmp
# define _tinydir_strrchr _tcsrchr
# define _tinydir_strncmp _tcsncmp
#else
# define _tinydir_char_t char
# define TINYDIR_STRING(s) s
# define _tinydir_strlen strlen
# define _tinydir_strcpy strcpy
# define _tinydir_strcat strcat
# define _tinydir_strcmp strcmp
# define _tinydir_strrchr strrchr
# define _tinydir_strncmp strncmp
#endif
#if (defined _MSC_VER || defined __MINGW32__)
# include <windows.h>
# define _TINYDIR_PATH_MAX MAX_PATH
#elif defined __linux__
# include <limits.h>
# ifdef PATH_MAX
# define _TINYDIR_PATH_MAX PATH_MAX
# endif
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
# include <sys/param.h>
# if defined(BSD)
# include <limits.h>
# ifdef PATH_MAX
# define _TINYDIR_PATH_MAX PATH_MAX
# endif
# endif
#endif
#ifndef _TINYDIR_PATH_MAX
#define _TINYDIR_PATH_MAX 4096
#endif
#ifdef _MSC_VER
/* extra chars for the "\\*" mask */
# define _TINYDIR_PATH_EXTRA 2
#else
# define _TINYDIR_PATH_EXTRA 0
#endif
#define _TINYDIR_FILENAME_MAX 256
#if (defined _MSC_VER || defined __MINGW32__)
#define _TINYDIR_DRIVE_MAX 3
#endif
#ifdef _MSC_VER
# define _TINYDIR_FUNC static __inline
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
# define _TINYDIR_FUNC static __inline__
#else
# define _TINYDIR_FUNC static inline
#endif
/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
#ifdef TINYDIR_USE_READDIR_R
/* readdir_r is a POSIX-only function, and may not be available under various
* environments/settings, e.g. MinGW. Use readdir fallback */
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\
_POSIX_SOURCE
# define _TINYDIR_HAS_READDIR_R
#endif
#if _POSIX_C_SOURCE >= 200112L
# define _TINYDIR_HAS_FPATHCONF
# include <unistd.h>
#endif
#if _BSD_SOURCE || _SVID_SOURCE || \
(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
# define _TINYDIR_HAS_DIRFD
# include <sys/types.h>
#endif
#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\
defined _PC_NAME_MAX
# define _TINYDIR_USE_FPATHCONF
#endif
#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\
!(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
# define _TINYDIR_USE_READDIR
#endif
/* Use readdir by default */
#else
# define _TINYDIR_USE_READDIR
#endif
/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
#ifndef _MSC_VER
#if (defined __MINGW32__) && (defined _UNICODE)
#define _TINYDIR_DIR _WDIR
#define _tinydir_dirent _wdirent
#define _tinydir_opendir _wopendir
#define _tinydir_readdir _wreaddir
#define _tinydir_closedir _wclosedir
#else
#define _TINYDIR_DIR DIR
#define _tinydir_dirent dirent
#define _tinydir_opendir opendir
#define _tinydir_readdir readdir
#define _tinydir_closedir closedir
#endif
#endif
/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE)
#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
#else
#error "Either define both alloc and free or none of them!"
#endif
#if !defined(_TINYDIR_MALLOC)
#define _TINYDIR_MALLOC(_size) malloc(_size)
#define _TINYDIR_FREE(_ptr) free(_ptr)
#endif /* !defined(_TINYDIR_MALLOC) */
typedef struct tinydir_file
{
_tinydir_char_t path[_TINYDIR_PATH_MAX];
_tinydir_char_t name[_TINYDIR_FILENAME_MAX];
_tinydir_char_t *extension;
int is_dir;
int is_reg;
#ifndef _MSC_VER
#ifdef __MINGW32__
struct _stat _s;
#else
struct stat _s;
#endif
#endif
} tinydir_file;
typedef struct tinydir_dir
{
_tinydir_char_t path[_TINYDIR_PATH_MAX];
int has_next;
size_t n_files;
tinydir_file *_files;
#ifdef _MSC_VER
HANDLE _h;
WIN32_FIND_DATA _f;
#else
_TINYDIR_DIR *_d;
struct _tinydir_dirent *_e;
#ifndef _TINYDIR_USE_READDIR
struct _tinydir_dirent *_ep;
#endif
#endif
} tinydir_dir;
/* declarations */
_TINYDIR_FUNC
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path);
_TINYDIR_FUNC
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path);
_TINYDIR_FUNC
void tinydir_close(tinydir_dir *dir);
_TINYDIR_FUNC
int tinydir_next(tinydir_dir *dir);
_TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file);
_TINYDIR_FUNC
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i);
_TINYDIR_FUNC
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i);
_TINYDIR_FUNC
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path);
_TINYDIR_FUNC
void _tinydir_get_ext(tinydir_file *file);
_TINYDIR_FUNC
int _tinydir_file_cmp(const void *a, const void *b);
#ifndef _MSC_VER
#ifndef _TINYDIR_USE_READDIR
_TINYDIR_FUNC
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
#endif
#endif
/* definitions*/
_TINYDIR_FUNC
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
{
#ifndef _MSC_VER
#ifndef _TINYDIR_USE_READDIR
int error;
int size; /* using int size */
#endif
#else
_tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
#endif
_tinydir_char_t *pathp;
if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0)
{
errno = EINVAL;
return -1;
}
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
{
errno = ENAMETOOLONG;
return -1;
}
/* initialise dir */
dir->_files = NULL;
#ifdef _MSC_VER
dir->_h = INVALID_HANDLE_VALUE;
#else
dir->_d = NULL;
#ifndef _TINYDIR_USE_READDIR
dir->_ep = NULL;
#endif
#endif
tinydir_close(dir);
_tinydir_strcpy(dir->path, path);
/* Remove trailing slashes */
pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/')))
{
*pathp = TINYDIR_STRING('\0');
pathp++;
}
#ifdef _MSC_VER
_tinydir_strcpy(path_buf, dir->path);
_tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
#if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0);
#else
dir->_h = FindFirstFile(path_buf, &dir->_f);
#endif
if (dir->_h == INVALID_HANDLE_VALUE)
{
errno = ENOENT;
#else
dir->_d = _tinydir_opendir(path);
if (dir->_d == NULL)
{
#endif
goto bail;
}
/* read first file */
dir->has_next = 1;
#ifndef _MSC_VER
#ifdef _TINYDIR_USE_READDIR
dir->_e = _tinydir_readdir(dir->_d);
#else
/* allocate dirent buffer for readdir_r */
size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
if (size == -1) return -1;
dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
if (dir->_ep == NULL) return -1;
error = readdir_r(dir->_d, dir->_ep, &dir->_e);
if (error != 0) return -1;
#endif
if (dir->_e == NULL)
{
dir->has_next = 0;
}
#endif
return 0;
bail:
tinydir_close(dir);
return -1;
}
_TINYDIR_FUNC
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
{
/* Count the number of files first, to pre-allocate the files array */
size_t n_files = 0;
if (tinydir_open(dir, path) == -1)
{
return -1;
}
while (dir->has_next)
{
n_files++;
if (tinydir_next(dir) == -1)
{
goto bail;
}
}
tinydir_close(dir);
if (n_files == 0 || tinydir_open(dir, path) == -1)
{
return -1;
}
dir->n_files = 0;
dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
if (dir->_files == NULL)
{
goto bail;
}
while (dir->has_next)
{
tinydir_file *p_file;
dir->n_files++;
p_file = &dir->_files[dir->n_files - 1];
if (tinydir_readfile(dir, p_file) == -1)
{
goto bail;
}
if (tinydir_next(dir) == -1)
{
goto bail;
}
/* Just in case the number of files has changed between the first and
second reads, terminate without writing into unallocated memory */
if (dir->n_files == n_files)
{
break;
}
}
qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
return 0;
bail:
tinydir_close(dir);
return -1;
}
_TINYDIR_FUNC
void tinydir_close(tinydir_dir *dir)
{
if (dir == NULL)
{
return;
}
memset(dir->path, 0, sizeof(dir->path));
dir->has_next = 0;
dir->n_files = 0;
_TINYDIR_FREE(dir->_files);
dir->_files = NULL;
#ifdef _MSC_VER
if (dir->_h != INVALID_HANDLE_VALUE)
{
FindClose(dir->_h);
}
dir->_h = INVALID_HANDLE_VALUE;
#else
if (dir->_d)
{
_tinydir_closedir(dir->_d);
}
dir->_d = NULL;
dir->_e = NULL;
#ifndef _TINYDIR_USE_READDIR
_TINYDIR_FREE(dir->_ep);
dir->_ep = NULL;
#endif
#endif
}
_TINYDIR_FUNC
int tinydir_next(tinydir_dir *dir)
{
if (dir == NULL)
{
errno = EINVAL;
return -1;
}
if (!dir->has_next)
{
errno = ENOENT;
return -1;
}
#ifdef _MSC_VER
if (FindNextFile(dir->_h, &dir->_f) == 0)
#else
#ifdef _TINYDIR_USE_READDIR
dir->_e = _tinydir_readdir(dir->_d);
#else
if (dir->_ep == NULL)
{
return -1;
}
if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0)
{
return -1;
}
#endif
if (dir->_e == NULL)
#endif
{
dir->has_next = 0;
#ifdef _MSC_VER
if (GetLastError() != ERROR_SUCCESS &&
GetLastError() != ERROR_NO_MORE_FILES)
{
tinydir_close(dir);
errno = EIO;
return -1;
}
#endif
}
return 0;
}
_TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
{
const _tinydir_char_t *filename;
if (dir == NULL || file == NULL)
{
errno = EINVAL;
return -1;
}
#ifdef _MSC_VER
if (dir->_h == INVALID_HANDLE_VALUE)
#else
if (dir->_e == NULL)
#endif
{
errno = ENOENT;
return -1;
}
filename =
#ifdef _MSC_VER
dir->_f.cFileName;
#else
dir->_e->d_name;
#endif
if (_tinydir_strlen(dir->path) +
_tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >=
_TINYDIR_PATH_MAX)
{
/* the path for the file will be too long */
errno = ENAMETOOLONG;
return -1;
}
if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX)
{
errno = ENAMETOOLONG;
return -1;
}
_tinydir_strcpy(file->path, dir->path);
if (_tinydir_strcmp(dir->path, TINYDIR_STRING("/")) != 0)
_tinydir_strcat(file->path, TINYDIR_STRING("/"));
_tinydir_strcpy(file->name, filename);
_tinydir_strcat(file->path, filename);
#ifndef _MSC_VER
#ifdef __MINGW32__
if (_tstat(
#elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) \
|| ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|| ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L))
if (lstat(
#else
if (stat(
#endif
file->path, &file->_s) == -1)
{
return -1;
}
#endif
_tinydir_get_ext(file);
file->is_dir =
#ifdef _MSC_VER
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
#else
S_ISDIR(file->_s.st_mode);
#endif
file->is_reg =
#ifdef _MSC_VER
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
(
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) &&
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
#endif
#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
#endif
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) &&
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
#else
S_ISREG(file->_s.st_mode);
#endif
return 0;
}
_TINYDIR_FUNC
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
{
if (dir == NULL || file == NULL)
{
errno = EINVAL;
return -1;
}
if (i >= dir->n_files)
{
errno = ENOENT;
return -1;
}
memcpy(file, &dir->_files[i], sizeof(tinydir_file));
_tinydir_get_ext(file);
return 0;
}
_TINYDIR_FUNC
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
{
_tinydir_char_t path[_TINYDIR_PATH_MAX];
if (dir == NULL)
{
errno = EINVAL;
return -1;
}
if (i >= dir->n_files || !dir->_files[i].is_dir)
{
errno = ENOENT;
return -1;
}
_tinydir_strcpy(path, dir->_files[i].path);
tinydir_close(dir);
if (tinydir_open_sorted(dir, path) == -1)
{
return -1;
}
return 0;
}
/* Open a single file given its path */
_TINYDIR_FUNC
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
{
tinydir_dir dir;
int result = 0;
int found = 0;
_tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
_tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX];
_tinydir_char_t *dir_name;
_tinydir_char_t *base_name;
#if (defined _MSC_VER || defined __MINGW32__)
_tinydir_char_t drive_buf[_TINYDIR_PATH_MAX];
_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
#endif
if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
{
errno = EINVAL;
return -1;
}
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
{
errno = ENAMETOOLONG;
return -1;
}
/* Get the parent path */
#if (defined _MSC_VER || defined __MINGW32__)
#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
errno = _tsplitpath_s(
path,
drive_buf, _TINYDIR_DRIVE_MAX,
dir_name_buf, _TINYDIR_FILENAME_MAX,
file_name_buf, _TINYDIR_FILENAME_MAX,
ext_buf, _TINYDIR_FILENAME_MAX);
#else
_tsplitpath(
path,
drive_buf,
dir_name_buf,
file_name_buf,
ext_buf);
#endif
if (errno)
{
return -1;
}
/* _splitpath_s not work fine with only filename and widechar support */
#ifdef _UNICODE
if (drive_buf[0] == L'\xFEFE')
drive_buf[0] = '\0';
if (dir_name_buf[0] == L'\xFEFE')
dir_name_buf[0] = '\0';
#endif
/* Emulate the behavior of dirname by returning "." for dir name if it's
empty */
if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
{
_tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
}
/* Concatenate the drive letter and dir name to form full dir name */
_tinydir_strcat(drive_buf, dir_name_buf);
dir_name = drive_buf;
/* Concatenate the file name and extension to form base name */
_tinydir_strcat(file_name_buf, ext_buf);
base_name = file_name_buf;
#else
_tinydir_strcpy(dir_name_buf, path);
dir_name = dirname(dir_name_buf);
_tinydir_strcpy(file_name_buf, path);
base_name = basename(file_name_buf);
#endif
/* Special case: if the path is a root dir, open the parent dir as the file */
#if (defined _MSC_VER || defined __MINGW32__)
if (_tinydir_strlen(base_name) == 0)
#else
if ((_tinydir_strcmp(base_name, TINYDIR_STRING("/"))) == 0)
#endif
{
memset(file, 0, sizeof * file);
file->is_dir = 1;
file->is_reg = 0;
_tinydir_strcpy(file->path, dir_name);
file->extension = file->path + _tinydir_strlen(file->path);
return 0;
}
/* Open the parent directory */
if (tinydir_open(&dir, dir_name) == -1)
{
return -1;
}
/* Read through the parent directory and look for the file */
while (dir.has_next)
{
if (tinydir_readfile(&dir, file) == -1)
{
result = -1;
goto bail;
}
if (_tinydir_strcmp(file->name, base_name) == 0)
{
/* File found */
found = 1;
break;
}
tinydir_next(&dir);
}
if (!found)
{
result = -1;
errno = ENOENT;
}
bail:
tinydir_close(&dir);
return result;
}
_TINYDIR_FUNC
void _tinydir_get_ext(tinydir_file *file)
{
_tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
if (period == NULL)
{
file->extension = &(file->name[_tinydir_strlen(file->name)]);
}
else
{
file->extension = period + 1;
}
}
_TINYDIR_FUNC
int _tinydir_file_cmp(const void *a, const void *b)
{
const tinydir_file *fa = (const tinydir_file *)a;
const tinydir_file *fb = (const tinydir_file *)b;
if (fa->is_dir != fb->is_dir)
{
return -(fa->is_dir - fb->is_dir);
}
return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
}
#ifndef _MSC_VER
#ifndef _TINYDIR_USE_READDIR
/*
The following authored by Ben Hutchings <ben@decadent.org.uk>
from https://womble.decadent.org.uk/readdir_r-advisory.html
*/
/* Calculate the required buffer size (in bytes) for directory *
* entries read from the given directory handle. Return -1 if this *
* this cannot be done. *
* *
* This code does not trust values of NAME_MAX that are less than *
* 255, since some systems (including at least HP-UX) incorrectly *
* define it to be a smaller value. */
_TINYDIR_FUNC
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
{
long name_max;
size_t name_end;
/* parameter may be unused */
(void)dirp;
#if defined _TINYDIR_USE_FPATHCONF
name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
if (name_max == -1)
#if defined(NAME_MAX)
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
return (size_t)(-1);
#endif
#elif defined(NAME_MAX)
name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
#error "buffer size for readdir_r cannot be determined"
#endif
name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
return (name_end > sizeof(struct _tinydir_dirent) ?
name_end : sizeof(struct _tinydir_dirent));
}
#endif
#endif
#ifdef __cplusplus
}
#endif
# if defined (_MSC_VER)
# pragma warning(pop)
# endif
#endif

View File

@ -3,8 +3,10 @@
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#ifndef CHAR_RANGE_INC
#define CHAR_RANGE_INC
//--STRIP
//--STRIP
#include "core/typedefs.h"
@ -1430,4 +1432,6 @@ static CharRange xid_continue[] = {
{ 0x0, 0x0 },
};
//--STRIP
#endif // CHAR_RANGE_INC
//--STRIP

View File

@ -3,8 +3,10 @@
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#ifndef CHAR_UTILS_H
#define CHAR_UTILS_H
//--STRIP
//--STRIP
#include "core/typedefs.h"
@ -86,4 +88,6 @@ static _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
return (p_char == '_');
}
//--STRIP
#endif // CHAR_UTILS_H
//--STRIP

522
sfwl/core/color.cpp Normal file
View File

@ -0,0 +1,522 @@
/*************************************************************************/
/* color.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/color.h"
#include "core/math_funcs.h"
//--STRIP
uint32_t Color::to_argb32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
return c;
}
uint32_t Color::to_abgr32() const {
uint32_t c = (uint8_t)Math::round(a * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(r * 255);
return c;
}
uint32_t Color::to_rgba32() const {
uint32_t c = (uint8_t)Math::round(r * 255);
c <<= 8;
c |= (uint8_t)Math::round(g * 255);
c <<= 8;
c |= (uint8_t)Math::round(b * 255);
c <<= 8;
c |= (uint8_t)Math::round(a * 255);
return c;
}
uint64_t Color::to_abgr64() const {
uint64_t c = (uint16_t)Math::round(a * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(r * 65535);
return c;
}
uint64_t Color::to_argb64() const {
uint64_t c = (uint16_t)Math::round(a * 65535);
c <<= 16;
c |= (uint16_t)Math::round(r * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
return c;
}
uint64_t Color::to_rgba64() const {
uint64_t c = (uint16_t)Math::round(r * 65535);
c <<= 16;
c |= (uint16_t)Math::round(g * 65535);
c <<= 16;
c |= (uint16_t)Math::round(b * 65535);
c <<= 16;
c |= (uint16_t)Math::round(a * 65535);
return c;
}
float Color::get_h() const {
float min = MIN(r, g);
min = MIN(min, b);
float max = MAX(r, g);
max = MAX(max, b);
float delta = max - min;
if (delta == 0) {
return 0;
}
float h;
if (r == max) {
h = (g - b) / delta; // between yellow & magenta
} else if (g == max) {
h = 2 + (b - r) / delta; // between cyan & yellow
} else {
h = 4 + (r - g) / delta; // between magenta & cyan
}
h /= 6.0;
if (h < 0) {
h += 1.0;
}
return h;
}
float Color::get_s() const {
float min = MIN(r, g);
min = MIN(min, b);
float max = MAX(r, g);
max = MAX(max, b);
float delta = max - min;
return (max != 0) ? (delta / max) : 0;
}
float Color::get_v() const {
float max = MAX(r, g);
max = MAX(max, b);
return max;
}
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
int i;
float f, p, q, t;
a = p_alpha;
if (p_s == 0) {
// acp_hromatic (grey)
r = g = b = p_v;
return;
}
p_h *= 6.0;
p_h = Math::fmod(p_h, 6);
i = Math::floor(p_h);
f = p_h - i;
p = p_v * (1 - p_s);
q = p_v * (1 - p_s * f);
t = p_v * (1 - p_s * (1 - f));
switch (i) {
case 0: // Red is the dominant color
r = p_v;
g = t;
b = p;
break;
case 1: // Green is the dominant color
r = q;
g = p_v;
b = p;
break;
case 2:
r = p;
g = p_v;
b = t;
break;
case 3: // Blue is the dominant color
r = p;
g = q;
b = p_v;
break;
case 4:
r = t;
g = p;
b = p_v;
break;
default: // (5) Red is the dominant color
r = p_v;
g = p;
b = q;
break;
}
}
bool Color::is_equal_approx(const Color &p_color) const {
return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a);
}
Color Color::clamp(const Color &p_min, const Color &p_max) const {
return Color(
CLAMP(r, p_min.r, p_max.r),
CLAMP(g, p_min.g, p_max.g),
CLAMP(b, p_min.b, p_max.b),
CLAMP(a, p_min.a, p_max.a));
}
void Color::invert() {
r = 1.0 - r;
g = 1.0 - g;
b = 1.0 - b;
}
void Color::contrast() {
r = Math::fmod(r + 0.5, 1.0);
g = Math::fmod(g + 0.5, 1.0);
b = Math::fmod(b + 0.5, 1.0);
}
Color Color::hex(uint32_t p_hex) {
float a = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float b = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float g = (p_hex & 0xFF) / 255.0;
p_hex >>= 8;
float r = (p_hex & 0xFF) / 255.0;
return Color(r, g, b, a);
}
Color Color::hex64(uint64_t p_hex) {
float a = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float b = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float g = (p_hex & 0xFFFF) / 65535.0;
p_hex >>= 16;
float r = (p_hex & 0xFFFF) / 65535.0;
return Color(r, g, b, a);
}
Color Color::from_rgbe9995(uint32_t p_rgbe) {
float r = p_rgbe & 0x1ff;
float g = (p_rgbe >> 9) & 0x1ff;
float b = (p_rgbe >> 18) & 0x1ff;
float e = (p_rgbe >> 27);
float m = Math::pow(2, e - 15.0 - 9.0);
float rd = r * m;
float gd = g * m;
float bd = b * m;
return Color(rd, gd, bd, 1.0f);
}
static float _parse_col(const String &p_str, int p_ofs) {
int ig = 0;
for (int i = 0; i < 2; i++) {
int c = p_str[i + p_ofs];
int v = 0;
if (c >= '0' && c <= '9') {
v = c - '0';
} else if (c >= 'a' && c <= 'f') {
v = c - 'a';
v += 10;
} else if (c >= 'A' && c <= 'F') {
v = c - 'A';
v += 10;
} else {
return -1;
}
if (i == 0) {
ig += v * 16;
} else {
ig += v;
}
}
return ig;
}
Color Color::inverted() const {
Color c = *this;
c.invert();
return c;
}
Color Color::contrasted() const {
Color c = *this;
c.contrast();
return c;
}
Color Color::html(const String &p_color) {
String color = p_color;
if (color.length() == 0) {
return Color();
}
if (color[0] == '#') {
color = color.substr(1, color.length() - 1);
}
if (color.length() == 3 || color.length() == 4) {
String exp_color;
for (int i = 0; i < color.length(); i++) {
exp_color += color[i];
exp_color += color[i];
}
color = exp_color;
}
bool alpha = false;
if (color.length() == 8) {
alpha = true;
} else if (color.length() == 6) {
alpha = false;
} else {
ERR_FAIL_V_MSG(Color(), "Invalid color code: " + p_color + ".");
}
int a = 255;
if (alpha) {
a = _parse_col(color, 0);
ERR_FAIL_COND_V_MSG(a < 0, Color(), "Invalid color code: " + p_color + ".");
}
int from = alpha ? 2 : 0;
int r = _parse_col(color, from + 0);
ERR_FAIL_COND_V_MSG(r < 0, Color(), "Invalid color code: " + p_color + ".");
int g = _parse_col(color, from + 2);
ERR_FAIL_COND_V_MSG(g < 0, Color(), "Invalid color code: " + p_color + ".");
int b = _parse_col(color, from + 4);
ERR_FAIL_COND_V_MSG(b < 0, Color(), "Invalid color code: " + p_color + ".");
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
}
bool Color::html_is_valid(const String &p_color) {
String color = p_color;
if (color.length() == 0) {
return false;
}
if (color[0] == '#') {
color = color.substr(1, color.length() - 1);
}
bool alpha = false;
if (color.length() == 8) {
alpha = true;
} else if (color.length() == 6) {
alpha = false;
} else {
return false;
}
if (alpha) {
int a = _parse_col(color, 0);
if (a < 0) {
return false;
}
}
int from = alpha ? 2 : 0;
int r = _parse_col(color, from + 0);
if (r < 0) {
return false;
}
int g = _parse_col(color, from + 2);
if (g < 0) {
return false;
}
int b = _parse_col(color, from + 4);
if (b < 0) {
return false;
}
return true;
}
String _to_hex(float p_val) {
int v = Math::round(p_val * 255);
v = CLAMP(v, 0, 255);
String ret;
for (int i = 0; i < 2; i++) {
CharType c[2] = { 0, 0 };
int lv = v & 0xF;
if (lv < 10) {
c[0] = '0' + lv;
} else {
c[0] = 'a' + lv - 10;
}
v >>= 4;
String cs = (const CharType *)c;
ret = cs + ret;
}
return ret;
}
String Color::to_html(bool p_alpha) const {
String txt;
txt += _to_hex(r);
txt += _to_hex(g);
txt += _to_hex(b);
if (p_alpha) {
txt = _to_hex(a) + txt;
}
return txt;
}
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
Color c;
c.set_hsv(p_h, p_s, p_v, p_a);
return c;
}
Color::operator String() const {
return "(" + String::num(r, 4) + ", " + String::num(g, 4) + ", " + String::num(b, 4) + ", " + String::num(a, 4) + ")";
}
Color Color::operator+(const Color &p_color) const {
return Color(
r + p_color.r,
g + p_color.g,
b + p_color.b,
a + p_color.a);
}
void Color::operator+=(const Color &p_color) {
r = r + p_color.r;
g = g + p_color.g;
b = b + p_color.b;
a = a + p_color.a;
}
Color Color::operator-(const Color &p_color) const {
return Color(
r - p_color.r,
g - p_color.g,
b - p_color.b,
a - p_color.a);
}
void Color::operator-=(const Color &p_color) {
r = r - p_color.r;
g = g - p_color.g;
b = b - p_color.b;
a = a - p_color.a;
}
Color Color::operator*(const Color &p_color) const {
return Color(
r * p_color.r,
g * p_color.g,
b * p_color.b,
a * p_color.a);
}
Color Color::operator*(const real_t &rvalue) const {
return Color(
r * rvalue,
g * rvalue,
b * rvalue,
a * rvalue);
}
void Color::operator*=(const Color &p_color) {
r = r * p_color.r;
g = g * p_color.g;
b = b * p_color.b;
a = a * p_color.a;
}
void Color::operator*=(const real_t &rvalue) {
r = r * rvalue;
g = g * rvalue;
b = b * rvalue;
a = a * rvalue;
}
Color Color::operator/(const Color &p_color) const {
return Color(
r / p_color.r,
g / p_color.g,
b / p_color.b,
a / p_color.a);
}
Color Color::operator/(const real_t &rvalue) const {
return Color(
r / rvalue,
g / rvalue,
b / rvalue,
a / rvalue);
}
void Color::operator/=(const Color &p_color) {
r = r / p_color.r;
g = g / p_color.g;
b = b / p_color.b;
a = a / p_color.a;
}
void Color::operator/=(const real_t &rvalue) {
if (rvalue == 0) {
r = 1.0;
g = 1.0;
b = 1.0;
a = 1.0;
} else {
r = r / rvalue;
g = g / rvalue;
b = b / rvalue;
a = a / rvalue;
}
};
Color Color::operator-() const {
return Color(
1.0 - r,
1.0 - g,
1.0 - b,
1.0 - a);
}

247
sfwl/core/color.h Normal file
View File

@ -0,0 +1,247 @@
//--STRIP
#ifndef COLOR_H
#define COLOR_H
//--STRIP
/*************************************************************************/
/* color.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/math_funcs.h"
#include "core/ustring.h"
//--STRIP
struct _NO_DISCARD_CLASS_ Color {
union {
struct {
float r;
float g;
float b;
float a;
};
float components[4];
};
bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
uint32_t to_rgba32() const;
uint32_t to_argb32() const;
uint32_t to_abgr32() const;
uint64_t to_rgba64() const;
uint64_t to_argb64() const;
uint64_t to_abgr64() const;
float get_h() const;
float get_s() const;
float get_v() const;
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
_FORCE_INLINE_ float &operator[](int idx) {
return components[idx];
}
_FORCE_INLINE_ const float &operator[](int idx) const {
return components[idx];
}
Color operator+(const Color &p_color) const;
void operator+=(const Color &p_color);
Color operator-() const;
Color operator-(const Color &p_color) const;
void operator-=(const Color &p_color);
Color operator*(const Color &p_color) const;
Color operator*(const real_t &rvalue) const;
void operator*=(const Color &p_color);
void operator*=(const real_t &rvalue);
Color operator/(const Color &p_color) const;
Color operator/(const real_t &rvalue) const;
void operator/=(const Color &p_color);
void operator/=(const real_t &rvalue);
bool is_equal_approx(const Color &p_color) const;
Color clamp(const Color &p_min = Color(0, 0, 0, 0), const Color &p_max = Color(1, 1, 1, 1)) const;
void invert();
void contrast();
Color inverted() const;
Color contrasted() const;
_FORCE_INLINE_ float get_luminance() const {
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
_FORCE_INLINE_ Color linear_interpolate(const Color &p_to, float p_weight) const {
Color res = *this;
res.r += (p_weight * (p_to.r - r));
res.g += (p_weight * (p_to.g - g));
res.b += (p_weight * (p_to.b - b));
res.a += (p_weight * (p_to.a - a));
return res;
}
_FORCE_INLINE_ Color darkened(float p_amount) const {
Color res = *this;
res.r = res.r * (1.0f - p_amount);
res.g = res.g * (1.0f - p_amount);
res.b = res.b * (1.0f - p_amount);
return res;
}
_FORCE_INLINE_ Color lightened(float p_amount) const {
Color res = *this;
res.r = res.r + (1.0f - res.r) * p_amount;
res.g = res.g + (1.0f - res.g) * p_amount;
res.b = res.b + (1.0f - res.b) * p_amount;
return res;
}
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
const float pow2to9 = 512.0f;
const float B = 15.0f;
//const float Emax = 31.0f;
const float N = 9.0f;
float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);
float cRed = MAX(0.0f, MIN(sharedexp, r));
float cGreen = MAX(0.0f, MIN(sharedexp, g));
float cBlue = MAX(0.0f, MIN(sharedexp, b));
float cMax = MAX(cRed, MAX(cGreen, cBlue));
// expp = MAX(-B - 1, log2(maxc)) + 1 + B
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
float exps = expp + 1.0f;
if (0.0 <= sMax && sMax < pow2to9) {
exps = expp;
}
float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
}
_FORCE_INLINE_ Color blend(const Color &p_over) const {
Color res;
float sa = 1.0 - p_over.a;
res.a = a * sa + p_over.a;
if (res.a == 0) {
return Color(0, 0, 0, 0);
} else {
res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
}
return res;
}
_FORCE_INLINE_ Color to_linear() const {
return Color(
r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
a);
}
_FORCE_INLINE_ Color to_srgb() const {
return Color(
r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
}
static Color hex(uint32_t p_hex);
static Color hex64(uint64_t p_hex);
static Color html(const String &p_color);
static bool html_is_valid(const String &p_color);
String to_html(bool p_alpha = true) const;
Color from_hsv(float p_h, float p_s, float p_v, float p_a) const;
static Color from_rgbe9995(uint32_t p_rgbe);
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
operator String() const;
static _FORCE_INLINE_ Color color8(int r, int g, int b) {
return Color(static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f);
}
static _FORCE_INLINE_ Color color8(int r, int g, int b, int a) {
return Color(static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f, static_cast<float>(a) / 255.0f);
}
_FORCE_INLINE_ void set_r8(int32_t r8) { r = (CLAMP(r8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_r8() const { return int32_t(CLAMP(Math::round(r * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_g8(int32_t g8) { g = (CLAMP(g8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_g8() const { return int32_t(CLAMP(Math::round(g * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_b8(int32_t b8) { b = (CLAMP(b8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_b8() const { return int32_t(CLAMP(Math::round(b * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_a8(int32_t a8) { a = (CLAMP(a8, 0, 255) / 255.0f); }
_FORCE_INLINE_ int32_t get_a8() const { return int32_t(CLAMP(Math::round(a * 255.0f), 0.0f, 255.0f)); }
_FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v(), a); }
_FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v(), a); }
_FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v, a); }
/**
* No construct parameters, r=0, g=0, b=0. a=255
*/
_FORCE_INLINE_ Color() {
r = 0;
g = 0;
b = 0;
a = 1.0;
}
/**
* RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
*/
_FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
r = p_r;
g = p_g;
b = p_b;
a = p_a;
}
/**
* Construct a Color from another Color, but with the specified alpha value.
*/
_FORCE_INLINE_ Color(const Color &p_c, float p_a) {
r = p_c.r;
g = p_c.g;
b = p_c.b;
a = p_a;
}
};
bool Color::operator<(const Color &p_color) const {
if (r == p_color.r) {
if (g == p_color.g) {
if (b == p_color.b) {
return (a < p_color.a);
} else {
return (b < p_color.b);
}
} else {
return g < p_color.g;
}
} else {
return r < p_color.r;
}
}
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef COWDATA_H_
#define COWDATA_H_
//--STRIP
/*************************************************************************/
/* cowdata.h */
@ -368,4 +370,6 @@ CowData<T>::~CowData() {
_unref(_ptr);
}
//--STRIP
#endif /* COW_H_ */
//--STRIP

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +1,147 @@
//--STRIP
#ifndef DIR_ACCESS_H
#define DIR_ACCESS_H
//--STRIP
/*************************************************************************/
/* dir_access.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/error_list.h"
#include "core/ustring.h"
//--STRIP
struct tinydir_file;
struct tinydir_dir;
#if defined(_WIN64) || defined(_WIN32)
struct DirAccessWindowsPrivate;
#elif defined(__APPLE__)
#include <dirent.h>
#else
struct __dirstream;
typedef struct __dirstream DIR;
#endif
class DirAccess {
Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
public:
Error open_dir(const String &path, bool skip_specials = true);
Error open_dir(const char *path, bool skip_specials = true);
void close_dir();
virtual Error list_dir_begin(bool skip_specials = false); ///< This starts dir listing
virtual String get_next();
virtual bool current_is_dir() const;
virtual bool current_is_hidden() const;
virtual bool current_is_file() const;
virtual bool current_is_special_dir() const;
bool has_next();
bool read();
bool next();
virtual void list_dir_end(); ///<
bool current_is_ok();
String current_get_name();
String current_get_path();
String current_get_extension();
const char *current_get_name_cstr();
const char *current_get_path_cstr();
const char *current_get_extension_cstr();
bool current_is_file();
bool current_is_dir();
bool current_is_special_dir();
virtual int get_drive_count();
virtual String get_drive(int p_drive);
virtual int get_current_drive();
virtual bool drives_are_shortcuts();
bool is_dir_open();
bool is_dir_closed();
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
virtual String get_current_dir(); ///< return current dir location
virtual String get_current_dir_without_drive();
virtual Error make_dir(String p_dir);
virtual Error make_dir_recursive(String p_dir);
virtual Error erase_contents_recursive(); //super dangerous, use with care!
virtual bool file_exists(String p_file);
virtual bool dir_exists(String p_dir);
static bool exists(String p_dir);
virtual uint64_t get_space_left();
Error copy_dir(String p_from, String p_to, int p_chmod_flags = -1, bool p_copy_links = false);
virtual Error copy(String p_from, String p_to, int p_chmod_flags = -1);
virtual Error rename(String p_from, String p_to);
virtual Error remove(String p_name);
virtual bool is_link(String p_file);
virtual String read_link(String p_file);
virtual Error create_link(String p_source, String p_target);
virtual uint64_t get_modified_time(String p_file);
virtual String get_filesystem_type() const;
static String get_full_path(const String &p_path);
static DirAccess *create_for_path(const String &p_path);
static DirAccess *create();
Error open(const String &p_path);
static String get_filesystem_abspath_for(String p_path);
static bool is_special(const String &p_path);
DirAccess();
virtual ~DirAccess();
private:
bool _skip_specials;
int _read_file_result;
tinydir_dir *_dir;
tinydir_file *_file;
protected:
#if defined(_WIN64) || defined(_WIN32)
#else
virtual String fix_unicode_name(const char *p_name) const { return String::utf8(p_name); }
virtual bool is_hidden(const String &p_name);
#endif
bool _dir_open;
bool next_is_dir;
bool _skip_specials;
#if defined(_WIN64) || defined(_WIN32)
enum {
MAX_DRIVES = 26
};
DirAccessWindowsPrivate *p;
/* Windows stuff */
char drives[MAX_DRIVES]; // a-z:
int drive_count;
String current_dir;
bool _cisdir;
bool _cishidden;
bool _cisspecial;
#else
String current_dir;
DIR *dir_stream;
bool _cisdir;
bool _cishidden;
bool _cisspecial;
#endif
};
struct DirAccessRef {
DirAccess *f;
_FORCE_INLINE_ bool is_null() const { return f == nullptr; }
_FORCE_INLINE_ bool is_valid() const { return f != nullptr; }
_FORCE_INLINE_ operator bool() const { return f != nullptr; }
_FORCE_INLINE_ operator DirAccess *() { return f; }
_FORCE_INLINE_ DirAccess *operator->() {
return f;
}
DirAccessRef(DirAccess *fa) { f = fa; }
DirAccessRef(DirAccessRef &&other) {
f = other.f;
other.f = nullptr;
}
~DirAccessRef() {
if (f) {
memdelete(f);
}
}
};
//--STRIP
#endif
//--STRIP

View File

@ -3,8 +3,10 @@
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#ifndef ERROR_LIST_H
#define ERROR_LIST_H
//--STRIP
/** Error List. Please never compare an error against FAILED
* Either do result != OK , or !result. This way, Error fail
@ -65,4 +67,6 @@ enum Error {
ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
//--STRIP
//--STRIP
#include "core/logger.h"
@ -247,7 +249,7 @@ _FORCE_INLINE_ void _RLOG_MACRO_TEMPLATE_FUNC(STR str, A p0, B p1, C p2, D p3, E
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, msg); \
GENERATE_TRAP
#define CRASH_NOW(msg) \
#define CRASH_NOW() \
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, "CRASH!"); \
GENERATE_TRAP
@ -291,4 +293,6 @@ _FORCE_INLINE_ void _RLOG_MACRO_TEMPLATE_FUNC(STR str, A p0, B p1, C p2, D p3, E
#define DEV_CHECK_ONCE(m_cond)
#endif
//--STRIP
#endif
//--STRIP

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,203 @@
//--STRIP
#ifndef FILE_ACCESS_H
#define FILE_ACCESS_H
//--STRIP
/*************************************************************************/
/* file_access.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/error_list.h"
#include "core/math_defs.h"
#include "core/ustring.h"
//--STRIP
#if defined(_WIN64) || defined(_WIN32)
// Mingw
struct _iobuf;
typedef struct _iobuf FILE;
#elif defined(__APPLE__)
struct __sFILE;
typedef struct __sFILE FILE;
typedef void (*FileCloseNotificationFunc)(const String &p_file, int p_flags);
#else
struct _IO_FILE;
typedef struct _IO_FILE FILE;
typedef void (*FileCloseNotificationFunc)(const String &p_file, int p_flags);
#endif
class FileAccess {
public:
//TODO should probably have some simple buffered open / close / write / read api.
typedef void (*FileCloseFailNotify)(const String &);
String read_file(const String &path);
bool endian_swap;
bool real_is_double;
Vector<uint8_t> read_file_bin(const String &path);
Error read_file_into_bin(const String &path, Vector<uint8_t> *data);
virtual uint32_t _get_unix_permissions(const String &p_file);
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
Error write_file(const String &path, const String &str);
Error write_file_bin(const String &path, const Vector<uint8_t> &data);
protected:
String fix_path(const String &p_path) const;
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual uint64_t _get_modified_time(const String &p_file);
static FileCloseFailNotify close_fail_notify;
private:
static bool backup_save;
public:
static void set_file_close_fail_notify_callback(FileCloseFailNotify p_cbk) { close_fail_notify = p_cbk; }
enum ModeFlags {
READ = 1,
WRITE = 2,
READ_WRITE = 3,
WRITE_READ = 7,
};
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual String get_path() const; /// returns the path for the current open file
virtual String get_path_absolute() const; /// returns the absolute path for the current open file
virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file with negative offset
virtual uint64_t get_position() const; ///< get position in the file
virtual uint64_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual uint16_t get_16() const; ///< get 16 bits uint
virtual uint32_t get_32() const; ///< get 32 bits uint
virtual uint64_t get_64() const; ///< get 64 bits uint
virtual float get_float() const;
virtual double get_double() const;
virtual real_t get_real() const;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
virtual String get_line() const;
virtual String get_token() const;
virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
virtual String get_as_utf8_string(bool p_skip_cr = true) const; // Skip CR by default for compat.
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
* It's not about the current CPU type but file formats.
* this flags get reset to false (little endian) on each open
*/
virtual void set_endian_swap(bool p_swap) { endian_swap = p_swap; }
inline bool get_endian_swap() const { return endian_swap; }
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
virtual void store_float(float p_dest);
virtual void store_double(double p_dest);
virtual void store_real(real_t p_real);
virtual void store_string(const String &p_string);
virtual void store_line(const String &p_line);
virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
void store_buffer_vec(const Vector<uint8_t> &data); ///< store an array of bytes
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
Error open(const String &p_path, int p_mode_flags);
static FileAccess *create(); /// Helper that Creates a file access
static FileAccess *create_and_open(const String &p_path, int p_mode_flags, Error *r_error = nullptr);
static bool exists(const String &p_name); ///< return true if a file exists
static uint64_t get_modified_time(const String &p_file);
static uint32_t get_unix_permissions(const String &p_file);
static Error set_unix_permissions(const String &p_file, uint32_t p_permissions);
static void set_backup_save(bool p_enable) { backup_save = p_enable; };
static bool is_backup_save_enabled() { return backup_save; };
static Vector<uint8_t> get_file_as_array(const String &p_path, Error *r_error = nullptr);
static String get_file_as_string(const String &p_path, Error *r_error = nullptr);
FileAccess();
virtual ~FileAccess();
private:
#if defined(_WIN64) || defined(_WIN32)
#else
static FileCloseNotificationFunc close_notification_func;
#endif
protected:
#if defined(_WIN64) || defined(_WIN32)
void check_errors() const;
FILE *f;
int flags;
mutable int prev_op;
mutable Error last_error;
String path;
String path_src;
String save_path;
#else
void check_errors() const;
FILE *f;
int flags;
mutable Error last_error;
String save_path;
String path;
String path_src;
#endif
};
struct FileAccessRef {
FileAccess *f;
_FORCE_INLINE_ bool is_null() const { return f == nullptr; }
_FORCE_INLINE_ bool is_valid() const { return f != nullptr; }
_FORCE_INLINE_ operator bool() const { return f != nullptr; }
_FORCE_INLINE_ operator FileAccess *() { return f; }
_FORCE_INLINE_ FileAccess *operator->() {
return f;
}
FileAccessRef(FileAccess *fa) { f = fa; }
FileAccessRef(FileAccessRef &&other) {
f = other.f;
other.f = nullptr;
}
~FileAccessRef() {
if (f) {
memdelete(f);
}
}
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef HASH_MAP_H
#define HASH_MAP_H
//--STRIP
/*************************************************************************/
/* hash_map.h */
@ -640,4 +642,6 @@ private:
}
};
//--STRIP
#endif // HASH_MAP_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef HASH_SET_H
#define HASH_SET_H
//--STRIP
/*************************************************************************/
/* hash_set.h */
@ -479,4 +481,6 @@ public:
}
};
//--STRIP
#endif // HASH_SET_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef HASHFUNCS_H
#define HASHFUNCS_H
//--STRIP
/*************************************************************************/
/* hashfuncs.h */
@ -7,8 +9,17 @@
/*************************************************************************/
//--STRIP
#include "core/aabb.h"
#include "core/math_defs.h"
#include "core/math_funcs.h"
#include "core/rect2.h"
#include "core/rect2i.h"
#include "core/vector2.h"
#include "core/vector2i.h"
#include "core/vector3.h"
#include "core/vector3i.h"
#include "core/vector4.h"
#include "core/vector4i.h"
#include "core/string_name.h"
#include "core/ustring.h"
#include "core/typedefs.h"
@ -297,6 +308,66 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) {
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) {
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
h = hash_murmur3_one_32(p_vec.z, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) {
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
h = hash_murmur3_one_32(p_vec.z, h);
h = hash_murmur3_one_32(p_vec.w, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) {
uint32_t h = hash_murmur3_one_real(p_vec.x);
h = hash_murmur3_one_real(p_vec.y, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) {
uint32_t h = hash_murmur3_one_real(p_vec.x);
h = hash_murmur3_one_real(p_vec.y, h);
h = hash_murmur3_one_real(p_vec.z, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector4 &p_vec) {
uint32_t h = hash_murmur3_one_real(p_vec.x);
h = hash_murmur3_one_real(p_vec.y, h);
h = hash_murmur3_one_real(p_vec.z, h);
h = hash_murmur3_one_real(p_vec.w, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) {
uint32_t h = hash_murmur3_one_32(p_rect.position.x);
h = hash_murmur3_one_32(p_rect.position.y, h);
h = hash_murmur3_one_32(p_rect.size.x, h);
h = hash_murmur3_one_32(p_rect.size.y, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) {
uint32_t h = hash_murmur3_one_real(p_rect.position.x);
h = hash_murmur3_one_real(p_rect.position.y, h);
h = hash_murmur3_one_real(p_rect.size.x, h);
h = hash_murmur3_one_real(p_rect.size.y, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) {
uint32_t h = hash_murmur3_one_real(p_aabb.position.x);
h = hash_murmur3_one_real(p_aabb.position.y, h);
h = hash_murmur3_one_real(p_aabb.position.z, h);
h = hash_murmur3_one_real(p_aabb.size.x, h);
h = hash_murmur3_one_real(p_aabb.size.y, h);
h = hash_murmur3_one_real(p_aabb.size.z, h);
return hash_fmix32(h);
}
};
template <typename T>
@ -320,6 +391,20 @@ struct HashMapComparatorDefault<double> {
}
};
template <>
struct HashMapComparatorDefault<Vector2> {
static bool compare(const Vector2 &p_lhs, const Vector2 &p_rhs) {
return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y)));
}
};
template <>
struct HashMapComparatorDefault<Vector3> {
static bool compare(const Vector3 &p_lhs, const Vector3 &p_rhs) {
return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y))) && ((p_lhs.z == p_rhs.z) || (Math::is_nan(p_lhs.z) && Math::is_nan(p_rhs.z)));
}
};
constexpr uint32_t HASH_TABLE_SIZE_MAX = 29;
const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
@ -416,4 +501,6 @@ static _FORCE_INLINE_ uint32_t fastmod(const uint32_t n, const uint64_t c, const
#endif // _MSC_VER
}
//--STRIP
#endif // HASHFUNCS_H
//--STRIP

331
sfwl/core/inet_address.cpp Normal file
View File

@ -0,0 +1,331 @@
//Based on:
// Copyright 2010, Shuo Chen. All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Shuo Chen (chenshuo at chenshuo dot com)
//--STRIP
#include "inet_address.h"
//--STRIP
#include <cstdio>
#include <cstring>
#if defined(_WIN64) || defined(_WIN32)
#ifdef __GNUC__
#define GCCWIN
// Mingw / gcc on windows
// #define _WIN32_WINNT 0x0501
#include <winsock2.h>
#include <ws2tcpip.h>
extern "C" {
WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT Family, PCSTR pszAddrString, PVOID pAddrBuf);
#ifdef __MINGW64_VERSION_MAJOR
#if __MINGW64_VERSION_MAJOR >= 7
WINSOCK_API_LINKAGE PCSTR WSAAPI inet_ntop(INT Family, const VOID * pAddr, PSTR pStringBuf, size_t StringBufSize);
#else
WINSOCK_API_LINKAGE PCSTR WSAAPI inet_ntop(INT Family, VOID * pAddr, PSTR pStringBuf, size_t StringBufSize);
#endif
#else
WINSOCK_API_LINKAGE PCSTR WSAAPI inet_ntop(INT Family, VOID * pAddr, PSTR pStringBuf, size_t StringBufSize);
#endif
}
#else
// Windows...
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <in6addr.h>
#include <winsock2.h>
#include <ws2tcpip.h>
extern "C" {
PCSTR WSAAPI inet_ntop( _In_ INT Family,_In_ const VOID * pAddr,_Out_writes_(StringBufSize) PSTR pStringBuf, _In_ size_t StringBufSize);
WINSOCK_API_LINKAGE INT WSAAPI inet_pton(_In_ INT Family,_In_ PCSTR pszAddrString, _When_(Family == AF_INET, _Out_writes_bytes_(sizeof(IN_ADDR)))_When_(Family == AF_INET6, _Out_writes_bytes_(sizeof(IN6_ADDR)))PVOID pAddrBuf);
}
#endif
struct in6__addruint {
union {
u_char Byte[16];
u_short Word[8];
uint32_t __s6_addr32[4];
} uext;
};
#else
#include <netdb.h>
#include <netinet/tcp.h>
#include <strings.h> // memset
#endif
#ifdef _MSC_VER
#pragma comment(lib, "ws2_32")
#endif
// INADDR_ANY use (type)value casting.
static const in_addr_t kInaddrAny = INADDR_ANY;
static const in_addr_t kInaddrLoopback = INADDR_ANY;
// /* Structure describing an Internet socket address. */
// struct sock_addrin {
// sa_family_t sin_family; /* address family: AF_INET */
// uint16_t sin_port; /* port in network byte order */
// struct in_addr sin_addr; /* internet address */
// };
// /* Internet address. */
// typedef uint32_t in_addr_t;
// struct in_addr {
// in_addr_t s_addr; /* address in network byte order */
// };
// struct sockaddr_in6 {
// sa_family_t sin6_family; /* address family: AF_INET6 */
// uint16_t sin6_port; /* port in network byte order */
// uint32_t sin6_flowinfo; /* IPv6 flow information */
// struct in6_addr sin6_addr; /* IPv6 address */
// uint32_t sin6_scope_id; /* IPv6 scope-id */
// };
/*
#ifdef __linux__
#if !(__GNUC_PREREQ(4, 6))
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
#endif
#endif
*/
// Defined here so we don't need to include <windows.h> in the header
struct InetAddress::InetAddressData {
union {
struct sockaddr_in _addr;
struct sockaddr_in6 _addr6;
};
};
String InetAddress::to_ip_port() const {
char buf[64] = "";
uint16_t port = ntohs(_data->_addr.sin_port);
snprintf(buf, sizeof(buf), ":%u", port);
return to_ip() + String(buf);
}
bool InetAddress::is_intranet_ip() const {
if (_data->_addr.sin_family == AF_INET) {
uint32_t ip_addr = ntohl(_data->_addr.sin_addr.s_addr);
if ((ip_addr >= 0x0A000000 && ip_addr <= 0x0AFFFFFF) ||
(ip_addr >= 0xAC100000 && ip_addr <= 0xAC1FFFFF) ||
(ip_addr >= 0xC0A80000 && ip_addr <= 0xC0A8FFFF) ||
ip_addr == 0x7f000001)
{
return true;
}
} else {
auto addrP = ip6_net_endian();
// Loopback ip
if (*addrP == 0 && *(addrP + 1) == 0 && *(addrP + 2) == 0 &&
ntohl(*(addrP + 3)) == 1) {
return true;
}
// Privated ip is prefixed by FEC0::/10 or FE80::/10, need testing
auto i32 = (ntohl(*addrP) & 0xffc00000);
if (i32 == 0xfec00000 || i32 == 0xfe800000) {
return true;
}
if (*addrP == 0 && *(addrP + 1) == 0 && ntohl(*(addrP + 2)) == 0xffff) {
// the IPv6 version of an IPv4 IP address
uint32_t ip_addr = ntohl(*(addrP + 3));
if ((ip_addr >= 0x0A000000 && ip_addr <= 0x0AFFFFFF) ||
(ip_addr >= 0xAC100000 && ip_addr <= 0xAC1FFFFF) ||
(ip_addr >= 0xC0A80000 && ip_addr <= 0xC0A8FFFF) ||
ip_addr == 0x7f000001)
{
return true;
}
}
}
return false;
}
bool InetAddress::is_loopback_ip() const {
if (!is_ip_v6()) {
uint32_t ip_addr = ntohl(_data->_addr.sin_addr.s_addr);
if (ip_addr == 0x7f000001) {
return true;
}
} else {
auto addrP = ip6_net_endian();
if (*addrP == 0 && *(addrP + 1) == 0 && *(addrP + 2) == 0 &&
ntohl(*(addrP + 3)) == 1) {
return true;
}
// the IPv6 version of an IPv4 loopback address
if (*addrP == 0 && *(addrP + 1) == 0 && ntohl(*(addrP + 2)) == 0xffff &&
ntohl(*(addrP + 3)) == 0x7f000001) {
return true;
}
}
return false;
}
const struct sockaddr *InetAddress::get_sock_addr() const {
return static_cast<const struct sockaddr *>((void *)(&_data->_addr6));
}
void InetAddress::set_sock_addr_inet6(const struct sockaddr_in6 &addr6) {
_data->_addr6 = addr6;
_is_ip_v6 = (_data->_addr6.sin6_family == AF_INET6);
_is_unspecified = false;
}
sa_family_t InetAddress::family() const {
return _data->_addr.sin_family;
}
String InetAddress::to_ip() const {
char buf[64];
if (_data->_addr.sin_family == AF_INET) {
#if defined GCCWIN || (_MSC_VER && _MSC_VER >= 1900)
::inet_ntop(AF_INET, (PVOID)&_data->_addr.sin_addr, buf, sizeof(buf));
#else
::inet_ntop(AF_INET, &_data->_addr.sin_addr, buf, sizeof(buf));
#endif
} else if (_data->_addr.sin_family == AF_INET6) {
#if defined GCCWIN || (_MSC_VER && _MSC_VER >= 1900)
::inet_ntop(AF_INET6, (PVOID)&_data->_addr6.sin6_addr, buf, sizeof(buf));
#else
::inet_ntop(AF_INET6, &_data->_addr6.sin6_addr, buf, sizeof(buf));
#endif
}
return buf;
}
uint32_t InetAddress::ip_net_endian() const {
// assert(family() == AF_INET);
return _data->_addr.sin_addr.s_addr;
}
const uint32_t *InetAddress::ip6_net_endian() const {
// assert(family() == AF_INET6);
#if defined __linux__ || defined __HAIKU__
return _data->_addr6.sin6_addr.s6_addr32;
#elif defined(_WIN64) || defined(_WIN32)
// TODO is this OK ?
const struct in6__addruint *_addrtemp =
reinterpret_cast<const struct in6__addruint *>(&_data->_addr6.sin6_addr);
return (*_addrtemp).uext.__s6_addr32;
#else
return _data->_addr6.sin6_addr.__u6_addr.__u6_addr32;
#endif
}
uint16_t InetAddress::port_net_endian() const {
return _data->_addr.sin_port;
}
void InetAddress::set_port_net_endian(uint16_t port) {
_data->_addr.sin_port = port;
}
inline bool InetAddress::is_unspecified() const {
return _is_unspecified;
}
uint16_t InetAddress::to_port() const {
return ntohs(port_net_endian());
}
bool InetAddress::is_ip_v6() const {
return _is_ip_v6;
}
InetAddress::InetAddress(uint16_t port, bool loopbackOnly, bool ipv6) {
_data = memnew(InetAddressData);
_is_ip_v6 = ipv6;
if (ipv6) {
memset(&_data->_addr6, 0, sizeof(_data->_addr6));
_data->_addr6.sin6_family = AF_INET6;
in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any;
_data->_addr6.sin6_addr = ip;
_data->_addr6.sin6_port = htons(port);
} else {
memset(&_data->_addr, 0, sizeof(_data->_addr));
_data->_addr.sin_family = AF_INET;
in_addr_t ip = loopbackOnly ? kInaddrLoopback : kInaddrAny;
_data->_addr.sin_addr.s_addr = htonl(ip);
_data->_addr.sin_port = htons(port);
}
_is_unspecified = false;
}
InetAddress::InetAddress(const String &ip, uint16_t port, bool ipv6) {
_data = memnew(InetAddressData);
_is_ip_v6 = ipv6;
if (ipv6) {
memset(&_data->_addr6, 0, sizeof(_data->_addr6));
_data->_addr6.sin6_family = AF_INET6;
_data->_addr6.sin6_port = htons(port);
if (::inet_pton(AF_INET6, ip.utf8().get_data(), &_data->_addr6.sin6_addr) <= 0) {
return;
}
} else {
memset(&_data->_addr, 0, sizeof(_data->_addr));
_data->_addr.sin_family = AF_INET;
_data->_addr.sin_port = htons(port);
if (::inet_pton(AF_INET, ip.utf8().get_data(), &_data->_addr.sin_addr) <= 0) {
return;
}
}
_is_unspecified = false;
}
InetAddress::InetAddress(const struct sockaddr_in &addr) {
_data = memnew(InetAddressData);
_data->_addr = addr;
_is_unspecified = false;
}
InetAddress::InetAddress(const struct sockaddr_in6 &addr) {
_data = memnew(InetAddressData);
_data->_addr6 = addr;
_is_ip_v6 = true;
_is_unspecified = false;
}
InetAddress::~InetAddress() {
memdelete(_data);
}

96
sfwl/core/inet_address.h Normal file
View File

@ -0,0 +1,96 @@
//Based on:
// Copyright 2010, Shuo Chen. All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Shuo Chen (chenshuo at chenshuo dot com)
//
// This is a public header file, it must only include public header files.
// Taken from Muduo and modified
// Copyright 2016, Tao An. All rights reserved.
// https://github.com/an-tao/trantor
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Tao An
//--STRIP
#ifndef INET_ADDRESS_H
#define INET_ADDRESS_H
//--STRIP
//On windows link to ws2_32
//--STRIP
#include "int_types.h"
//--STRIP
#if defined(_WIN64) || defined(_WIN32)
using sa_family_t = unsigned short;
using in_addr_t = uint32_t;
using uint16_t = unsigned short;
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
//--STRIP
#include "core/ustring.h"
#include "int_types.h"
//--STRIP
struct sockaddr_in;
struct sockaddr_in6;
class InetAddress {
public:
struct InetAddressData;
sa_family_t family() const;
String to_ip() const;
String to_ip_port() const;
uint16_t to_port() const;
bool is_ip_v6() const;
bool is_intranet_ip() const;
bool is_loopback_ip() const;
const struct sockaddr *get_sock_addr() const;
void set_sock_addr_inet6(const struct sockaddr_in6 &addr6);
uint32_t ip_net_endian() const;
const uint32_t *ip6_net_endian() const;
uint16_t port_net_endian() const;
void set_port_net_endian(uint16_t port);
inline bool is_unspecified() const;
InetAddress(uint16_t port = 0, bool loopbackOnly = false, bool ipv6 = false);
InetAddress(const String &ip, uint16_t port, bool ipv6 = false);
explicit InetAddress(const struct sockaddr_in &addr);
explicit InetAddress(const struct sockaddr_in6 &addr);
~InetAddress();
private:
InetAddressData *_data;
bool _is_ip_v6;
bool _is_unspecified;
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef GLOBALS_LIST_H
#define GLOBALS_LIST_H
//--STRIP
/*************************************************************************/
/* list.h */
@ -674,4 +676,6 @@ public:
};
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef LOCAL_VECTOR_H
#define LOCAL_VECTOR_H
//--STRIP
/*************************************************************************/
/* local_vector.h */
@ -296,4 +298,6 @@ template <class T, class I = int32_t, bool force_trivial = false>
class LocalVectori : public LocalVector<T, I, force_trivial> {
};
//--STRIP
#endif // LOCAL_VECTOR_H
//--STRIP

View File

@ -1,7 +1,7 @@
//--STRIP
#ifndef LOGGER_H
#define LOGGER_H
//--STRIP
class String;
@ -71,4 +71,6 @@ public:
static void log_ret_ptr(String *str);
};
//--STRIP
#endif
//--STRIP

148
sfwl/core/marshalls.h Normal file
View File

@ -0,0 +1,148 @@
//--STRIP
#ifndef MARSHALLS_H
#define MARSHALLS_H
//--STRIP
/*************************************************************************/
/* marshalls.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/int_types.h"
#include "core/math_defs.h"
//--STRIP
/**
* Miscellaneous helpers for marshalling data types, and encoding
* in an endian independent way
*/
union MarshallFloat {
uint32_t i; ///< int
float f; ///< float
};
union MarshallDouble {
uint64_t l; ///< long long
double d; ///< double
};
static inline unsigned int encode_uint16(uint16_t p_uint, uint8_t *p_arr) {
for (int i = 0; i < 2; i++) {
*p_arr = p_uint & 0xFF;
p_arr++;
p_uint >>= 8;
}
return sizeof(uint16_t);
}
static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) {
for (int i = 0; i < 4; i++) {
*p_arr = p_uint & 0xFF;
p_arr++;
p_uint >>= 8;
}
return sizeof(uint32_t);
}
static inline unsigned int encode_float(float p_float, uint8_t *p_arr) {
MarshallFloat mf;
mf.f = p_float;
encode_uint32(mf.i, p_arr);
return sizeof(uint32_t);
}
static inline unsigned int encode_uint64(uint64_t p_uint, uint8_t *p_arr) {
for (int i = 0; i < 8; i++) {
*p_arr = p_uint & 0xFF;
p_arr++;
p_uint >>= 8;
}
return sizeof(uint64_t);
}
static inline unsigned int encode_double(double p_double, uint8_t *p_arr) {
MarshallDouble md;
md.d = p_double;
encode_uint64(md.l, p_arr);
return sizeof(uint64_t);
}
static inline int encode_cstring(const char *p_string, uint8_t *p_data) {
int len = 0;
while (*p_string) {
if (p_data) {
*p_data = (uint8_t)*p_string;
p_data++;
}
p_string++;
len++;
};
if (p_data) {
*p_data = 0;
}
return len + 1;
}
static inline uint16_t decode_uint16(const uint8_t *p_arr) {
uint16_t u = 0;
for (int i = 0; i < 2; i++) {
uint16_t b = *p_arr;
b <<= (i * 8);
u |= b;
p_arr++;
}
return u;
}
static inline uint32_t decode_uint32(const uint8_t *p_arr) {
uint32_t u = 0;
for (int i = 0; i < 4; i++) {
uint32_t b = *p_arr;
b <<= (i * 8);
u |= b;
p_arr++;
}
return u;
}
static inline float decode_float(const uint8_t *p_arr) {
MarshallFloat mf;
mf.i = decode_uint32(p_arr);
return mf.f;
}
static inline uint64_t decode_uint64(const uint8_t *p_arr) {
uint64_t u = 0;
for (int i = 0; i < 8; i++) {
uint64_t b = (*p_arr) & 0xFF;
b <<= (i * 8);
u |= b;
p_arr++;
}
return u;
}
static inline double decode_double(const uint8_t *p_arr) {
MarshallDouble md;
md.l = decode_uint64(p_arr);
return md.d;
}
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef MATH_DEFS_H
#define MATH_DEFS_H
//--STRIP
/*************************************************************************/
/* math_defs.h */
@ -95,4 +97,6 @@ typedef double real_t;
typedef float real_t;
#endif
//--STRIP
#endif // MATH_DEFS_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef MATH_FUNCS_H
#define MATH_FUNCS_H
//--STRIP
/*************************************************************************/
/* math_funcs.h */
@ -641,4 +643,6 @@ public:
}
};
//--STRIP
#endif // MATH_FUNCS_H
//--STRIP

View File

@ -23,15 +23,15 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
#ifdef _MSC_VER
void operator delete(void *p_mem, const char *p_description) {
CRASH_NOW_MSG("Call to placement delete should not happen.");
CRASH_MSG("Call to placement delete should not happen.");
}
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
CRASH_NOW_MSG("Call to placement delete should not happen.");
CRASH_MSG("Call to placement delete should not happen.");
}
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
CRASH_NOW_MSG("Call to placement delete should not happen.");
CRASH_MSG("Call to placement delete should not happen.");
}
#endif

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef MEMORY_H
#define MEMORY_H
//--STRIP
/*************************************************************************/
/* memory.h */
@ -179,4 +181,6 @@ struct _GlobalNilClass {
static _GlobalNil _nil;
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef MUTEX_H
#define MUTEX_H
//--STRIP
/*************************************************************************/
/* mutex.h */
@ -94,4 +96,6 @@ using BinaryMutex = MutexImpl<FakeMutex>; // Non-recursive, handle with care
#endif // !NO_THREADS
//--STRIP
#endif // MUTEX_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef GHASH_MAP_H
#define GHASH_MAP_H
//--STRIP
/*************************************************************************/
/* og_hash_map.h */
@ -578,4 +580,6 @@ public:
}
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef ORDERED_HASH_MAP_H
#define ORDERED_HASH_MAP_H
//--STRIP
/*************************************************************************/
/* ordered_hash_map.h */
@ -284,4 +286,6 @@ public:
}
};
//--STRIP
#endif // ORDERED_HASH_MAP_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef PAGED_ALLOCATOR_H
#define PAGED_ALLOCATOR_H
//--STRIP
/*************************************************************************/
/* paged_allocator.h */
@ -107,4 +109,6 @@ public:
}
};
//--STRIP
#endif // PAGED_ALLOCATOR_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef PAIR_H
#define PAIR_H
//--STRIP
/*************************************************************************/
/* pair.h */
@ -89,4 +91,6 @@ struct KeyValueSort {
}
};
//--STRIP
#endif // PAIR_H
//--STRIP

View File

@ -1,8 +1,10 @@
// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
//--STRIP
#ifndef RANDOM_H
#define RANDOM_H
//--STRIP
//--STRIP
#include "core/typedefs.h"
@ -15,4 +17,6 @@ uint32_t pcg32_random_r(pcg32_random_t* rng);
void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq);
uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound);
//--STRIP
#endif // RANDOM_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef POOL_ALLOCATOR_H
#define POOL_ALLOCATOR_H
//--STRIP
/*************************************************************************/
/* pool_allocator.h */
@ -124,4 +126,6 @@ public:
virtual ~PoolAllocator();
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef POOL_VECTOR_H
#define POOL_VECTOR_H
//--STRIP
/*************************************************************************/
/* pool_vector.h */
@ -709,4 +711,6 @@ void PoolVector<T>::sort() {
sorter.sort(w.ptr(), len);
}
//--STRIP
#endif // POOL_VECTOR_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef RANDOM_PCG_H
#define RANDOM_PCG_H
//--STRIP
/*************************************************************************/
/* random_pcg.h */
@ -115,4 +117,6 @@ public:
int random(int p_from, int p_to);
};
//--STRIP
#endif // RANDOM_PCG_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef RB_MAP_H
#define RB_MAP_H
//--STRIP
/*************************************************************************/
/* rb_map.h */
@ -652,4 +654,6 @@ public:
}
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef RB_SET_H
#define RB_SET_H
//--STRIP
/*************************************************************************/
/* rb_set.h */
@ -606,4 +608,6 @@ public:
}
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
//--STRIP
/*************************************************************************/
/* ring_buffer.h */
@ -196,4 +198,6 @@ public:
~RingBuffer<T>(){};
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef RWLOCK_H
#define RWLOCK_H
//--STRIP
/*************************************************************************/
/* rw_lock.h */
@ -90,4 +92,6 @@ public:
}
};
//--STRIP
#endif // RWLOCK_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef SAFE_REFCOUNT_H
#define SAFE_REFCOUNT_H
//--STRIP
/*************************************************************************/
/* safe_refcount.h */
@ -307,4 +309,6 @@ public:
#endif
//--STRIP
#endif // SAFE_REFCOUNT_H
//--STRIP

View File

@ -1,6 +1,7 @@
//--STRIP
#ifndef SFW_CORE_H
#define SFW_CORE_H
//--STRIP
class SFWCore {
public:
@ -11,4 +12,6 @@ protected:
static bool _initialized;
};
//--STRIP
#endif
//--STRIP

View File

@ -4,12 +4,19 @@
//--STRIP
#include "core/sfw_time.h"
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <ctime>
//--STRIP
#if defined(_WIN64) || defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winnt.h>
#else
#include <sys/time.h>
#include <unistd.h>
#endif
#if 0
uint64_t SFWTime::time_gpu() {
GLint64 t = 123456789;
@ -114,8 +121,8 @@ static uint64_t nanotimer(uint64_t *out_freq) {
}
uint64_t SFWTime::time_ns() {
static __thread uint64_t epoch = 0;
static __thread uint64_t freq = 0;
static thread_local uint64_t epoch = 0;
static thread_local uint64_t freq = 0;
if (!freq) {
epoch = nanotimer(&freq);
}

View File

@ -1,5 +1,7 @@
#ifndef SFWTime_H
#define SFWTime_H
//--STRIP
#ifndef SFW_TIME_H
#define SFW_TIME_H
//--STRIP
// -----------------------------------------------------------------------------
// time framework utils
@ -26,4 +28,6 @@ public:
static void sleep_ns(double us);
};
//--STRIP
#endif
//--STRIP

356
sfwl/core/socket.cpp Normal file
View File

@ -0,0 +1,356 @@
//--STRIP
#include "socket.h"
//--STRIP
//Based on:
/**
*
* Socket.cc
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#if !defined(_WIN64) && !defined(_WIN32)
#include <unistd.h>
#endif
#include <fcntl.h>
///usr/include/asm-generic/errno-base.h
//http://www.virtsync.com/c-error-codes-include-errno
#include <cerrno>
#if defined(_WIN64) || defined(_WIN32)
#include <ws2tcpip.h>
#else
#include <netinet/tcp.h>
#include <sys/socket.h>
#endif
//--STRIP
#include "core/error_macros.h"
#include "core/ustring.h"
//--STRIP
void Socket::create_net_socket() {
create(AF_INET);
}
void Socket::create(int family) {
#ifdef __linux__
_socket = ::socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
#else
_socket = static_cast<int>(::socket(family, SOCK_STREAM, IPPROTO_TCP));
#endif
}
void Socket::close_socket() {
if (!_socket) {
return;
}
#if !defined(_WIN64) && !defined(_WIN32)
close(_socket);
#else
closesocket(_socket);
#endif
_socket = 0;
}
// taken from muduo
int Socket::set_non_block() {
ERR_FAIL_COND_V(_socket == 0, -1);
#if defined(_WIN64) || defined(_WIN32)
// TODO how to set FD_CLOEXEC on windows? is it necessary?
u_long arg = 1;
auto ret = ioctlsocket(_socket, (long)FIONBIO, &arg);
if (ret) {
//LOG_ERR("ioctlsocket error");
return -1;
}
return 0;
#else
// non-block
int flags = ::fcntl(_socket, F_GETFL, 0);
flags |= O_NONBLOCK;
int ret = ::fcntl(_socket, F_SETFL, flags);
// TODO check
return ret;
#endif
}
// taken from muduo
int Socket::set_close_on_exit() {
ERR_FAIL_COND_V(_socket == 0, -1);
#if defined(_WIN64) || defined(_WIN32)
// TODO how to set FD_CLOEXEC on windows? is it necessary?
return 0;
#else
// close-on-exec
int flags = ::fcntl(_socket, F_GETFD, 0);
flags |= FD_CLOEXEC;
int ret = ::fcntl(_socket, F_SETFD, flags);
// TODO check
return ret;
#endif
}
int Socket::get_error() {
ERR_FAIL_COND_V(_socket == 0, -1);
int optval;
socklen_t optlen = static_cast<socklen_t>(sizeof optval);
#if defined(_WIN64) || defined(_WIN32)
if (::getsockopt(_socket, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) < 0)
#else
if (::getsockopt(_socket, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0)
#endif
{
return errno;
} else {
return optval;
}
}
int Socket::connect(const InetAddress &addr) {
ERR_FAIL_COND_V(_socket == 0, -1);
if (addr.is_ip_v6()) {
return ::connect(_socket, addr.get_sock_addr(), static_cast<socklen_t>(sizeof(struct sockaddr_in6)));
} else {
return ::connect(_socket, addr.get_sock_addr(), static_cast<socklen_t>(sizeof(struct sockaddr_in)));
}
}
bool Socket::is_self_connect() {
ERR_FAIL_COND_V(_socket == 0, false);
struct sockaddr_in6 localaddr = get_local_addr();
struct sockaddr_in6 peeraddr = get_peer_addr();
if (localaddr.sin6_family == AF_INET) {
const struct sockaddr_in *laddr4 = reinterpret_cast<struct sockaddr_in *>(&localaddr);
const struct sockaddr_in *raddr4 = reinterpret_cast<struct sockaddr_in *>(&peeraddr);
return laddr4->sin_port == raddr4->sin_port && laddr4->sin_addr.s_addr == raddr4->sin_addr.s_addr;
} else if (localaddr.sin6_family == AF_INET6) {
return localaddr.sin6_port == peeraddr.sin6_port && memcmp(&localaddr.sin6_addr, &peeraddr.sin6_addr, sizeof localaddr.sin6_addr) == 0;
} else {
return false;
}
}
int Socket::bind_address(const InetAddress &address) {
ERR_FAIL_COND_V(_socket == 0, -1);
int ret;
if (address.is_ip_v6()) {
ret = ::bind(_socket, address.get_sock_addr(), sizeof(sockaddr_in6));
} else {
ret = ::bind(_socket, address.get_sock_addr(), sizeof(sockaddr_in));
}
if (ret != 0) {
#if defined(_WIN64) || defined(_WIN32)
return WSAGetLastError();
#else
return errno;
#endif
}
return ret;
}
int Socket::listen() {
ERR_FAIL_COND_V(_socket == 0, -1);
return ::listen(_socket, SOMAXCONN);
}
int Socket::accept(Socket *sock) {
ERR_FAIL_COND_V(!sock, -1);
struct sockaddr_in6 addr6;
memset(&addr6, 0, sizeof(addr6));
socklen_t size = sizeof(addr6);
#ifdef __linux__
int connfd = ::accept4(_socket, (struct sockaddr *)&addr6, &size, SOCK_NONBLOCK | SOCK_CLOEXEC);
#else
int connfd = static_cast<int>(::accept(_socket, (struct sockaddr *)&addr6, &size));
#endif
if (connfd >= 0) {
sock->_socket = connfd;
sock->_address.set_sock_addr_inet6(addr6);
#ifndef __linux__
sock->set_non_block();
sock->set_close_on_exit();
#endif
}
return connfd;
}
int Socket::close_write() {
ERR_FAIL_COND_V(_socket == 0, -1);
#if !defined(_WIN64) && !defined(_WIN32)
return ::shutdown(_socket, SHUT_WR);
#else
return ::shutdown(_socket, SD_SEND);
#endif
}
int Socket::read(char *buffer, uint64_t len) {
//ERR_FAIL_COND_V(_socket == 0, -1);
#if !defined(_WIN64) && !defined(_WIN32)
return ::read(_socket, buffer, len);
#else
return recv(_socket, buffer, static_cast<int>(len), 0);
#endif
}
int Socket::send(const char *buffer, uint64_t len) {
//ERR_FAIL_COND_V(_socket == 0, -1);
#if !defined(_WIN64) && !defined(_WIN32)
return write(_socket, buffer, len);
#else
errno = 0;
return ::send(_socket, buffer, static_cast<int>(len), 0);
#endif
}
void Socket::set_tcp_nodelay(bool on) {
ERR_FAIL_COND(_socket == 0);
#if defined(_WIN64) || defined(_WIN32)
char optval = on ? 1 : 0;
#else
int optval = on ? 1 : 0;
#endif
::setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, &optval, static_cast<socklen_t>(sizeof optval));
}
void Socket::set_reuse_addr(bool on) {
ERR_FAIL_COND(_socket == 0);
#if defined(_WIN64) || defined(_WIN32)
char optval = on ? 1 : 0;
#else
int optval = on ? 1 : 0;
#endif
::setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, &optval, static_cast<socklen_t>(sizeof optval));
}
int Socket::set_reuse_port(bool on) {
ERR_FAIL_COND_V(_socket == 0, -1);
#ifdef SO_REUSEPORT
#if defined(_WIN64) || defined(_WIN32)
char optval = on ? 1 : 0;
#else
int optval = on ? 1 : 0;
#endif
int ret = ::setsockopt(_socket, SOL_SOCKET, SO_REUSEPORT, &optval, static_cast<socklen_t>(sizeof optval));
return ret;
#else
if (on) {
//LOG_ERR("SO_REUSEPORT is not supported.");
return -1;
}
return 0;
#endif
}
void Socket::set_keep_alive(bool on) {
ERR_FAIL_COND(_socket == 0);
#if defined(_WIN64) || defined(_WIN32)
char optval = on ? 1 : 0;
#else
int optval = on ? 1 : 0;
#endif
::setsockopt(_socket, SOL_SOCKET, SO_KEEPALIVE, &optval, static_cast<socklen_t>(sizeof optval));
}
struct sockaddr_in6 Socket::get_local_addr(int *r_err) {
struct sockaddr_in6 localaddr = { 0 };
ERR_FAIL_COND_V(_socket == 0, localaddr);
memset(&localaddr, 0, sizeof(localaddr));
socklen_t addrlen = static_cast<socklen_t>(sizeof localaddr);
int err = ::getsockname(_socket, static_cast<struct sockaddr *>((void *)(&localaddr)), &addrlen);
if (r_err) {
*r_err = err;
}
return localaddr;
}
struct sockaddr_in6 Socket::get_peer_addr(int *r_err) {
struct sockaddr_in6 peeraddr = { 0 };
ERR_FAIL_COND_V(_socket == 0, peeraddr);
memset(&peeraddr, 0, sizeof(peeraddr));
socklen_t addrlen = static_cast<socklen_t>(sizeof peeraddr);
int err = ::getpeername(_socket, static_cast<struct sockaddr *>((void *)(&peeraddr)), &addrlen);
if (r_err) {
*r_err = err;
}
return peeraddr;
}
int Socket::global_init() {
#if defined(_WIN64) || defined(_WIN32)
int r;
WSADATA wsa_data;
r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
return r;
#else
return 0;
#endif
}
Socket::Socket() {
_socket = 0;
}
Socket::Socket(int socketFD, const InetAddress &address) {
_socket = socketFD;
_address = address;
}
Socket::~Socket() {
if (_socket >= 0) {
close_socket();
}
}

69
sfwl/core/socket.h Normal file
View File

@ -0,0 +1,69 @@
//--STRIP
#ifndef SOCKET_H
#define SOCKET_H
//--STRIP
//Based on:
/**
*
* Socket.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
//--STRIP
#include "inet_address.h"
//--STRIP
class Socket {
public:
void create_net_socket();
void create(int family);
void close_socket();
int connect(const InetAddress &address);
int bind_address(const InetAddress &address);
int listen();
int accept(Socket *sock);
int close_write();
int read(char *buffer, uint64_t len);
int send(const char *buffer, uint64_t len);
bool is_self_connect();
void set_tcp_nodelay(bool on);
void set_reuse_addr(bool on);
int set_reuse_port(bool on);
void set_keep_alive(bool on);
int set_non_block();
int set_close_on_exit();
int get_error();
struct sockaddr_in6 get_local_addr(int *r_err = NULL);
struct sockaddr_in6 get_peer_addr(int *r_err = NULL);
static int global_init();
Socket();
Socket(int socketFD, const InetAddress &address);
~Socket();
int _socket;
InetAddress _address;
};
//--STRIP
#endif // SOCKET_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef SORT_ARRAY_H
#define SORT_ARRAY_H
//--STRIP
/*************************************************************************/
/* sort_array.h */
@ -297,4 +299,6 @@ public:
#undef ERR_BAD_COMPARE
//--STRIP
#endif // SORT_ARRAY_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef SPIN_LOCK_H
#define SPIN_LOCK_H
//--STRIP
/*************************************************************************/
/* spin_lock.h */
@ -25,4 +27,7 @@ public:
locked.clear(std::memory_order_release);
}
};
//--STRIP
#endif // SPIN_LOCK_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef STRING_NAME_H
#define STRING_NAME_H
//--STRIP
/*************************************************************************/
/* string_name.h */
@ -205,4 +207,6 @@ StringName _scs_create(const char *p_chr, bool p_static = false);
//#define SNAME(m_arg) ([]() -> const StringName & { static StringName sname = _scs_create(m_arg, true); return sname; })()
//--STRIP
#endif // STRING_NAME_H
//--STRIP

761
sfwl/core/sub_process.cpp Normal file
View File

@ -0,0 +1,761 @@
/*************************************************************************/
/* sub_process.cpp */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "sub_process.h"
//--STRIP
#if defined(_WIN64) || defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef struct tagLOGCONTEXTW {
WCHAR lcName[40];
UINT lcOptions;
UINT lcStatus;
UINT lcLocks;
UINT lcMsgBase;
UINT lcDevice;
UINT lcPktRate;
DWORD lcPktData;
DWORD lcPktMode;
DWORD lcMoveMask;
DWORD lcBtnDnMask;
DWORD lcBtnUpMask;
LONG lcInOrgX;
LONG lcInOrgY;
LONG lcInOrgZ;
LONG lcInExtX;
LONG lcInExtY;
LONG lcInExtZ;
LONG lcOutOrgX;
LONG lcOutOrgY;
LONG lcOutOrgZ;
LONG lcOutExtX;
LONG lcOutExtY;
LONG lcOutExtZ;
DWORD lcSensX;
DWORD lcSensY;
DWORD lcSensZ;
BOOL lcSysMode;
int lcSysOrgX;
int lcSysOrgY;
int lcSysExtX;
int lcSysExtY;
DWORD lcSysSensX;
DWORD lcSysSensY;
} LOGCONTEXTW;
typedef HANDLE(WINAPI *WTOpenPtr)(HWND p_window, LOGCONTEXTW *p_ctx, BOOL p_enable);
// TODO clean these up
#include <avrt.h>
#include <direct.h>
#include <knownfolders.h>
#include <process.h>
#include <regstr.h>
#include <shlobj.h>
#include <wchar.h>
struct SubProcess::SubProcessWindowsData {
struct ProcessInfo {
STARTUPINFO si;
PROCESS_INFORMATION pi;
};
HANDLE _pipe_handles[2];
ProcessInfo _process_info;
};
Error SubProcess::start() {
if (_executable_path.empty()) {
return ERR_FILE_BAD_PATH;
}
if (is_process_running()) {
return ERR_BUSY;
}
String path = _executable_path.replace("/", "\\");
String cmdline = _quote_command_line_argument(path);
for (int i = 0; i < _arguments.size(); ++i) {
cmdline += " " + _quote_command_line_argument(_arguments[i]);
}
ZeroMemory(&_data->_process_info.si, sizeof(_data->_process_info.si));
_data->_process_info.si.cb = sizeof(_data->_process_info.si);
ZeroMemory(&_data->_process_info.pi, sizeof(_data->_process_info.pi));
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&_data->_process_info.si;
Char16String modstr = cmdline.utf16(); // Windows wants to change this no idea why.
bool inherit_handles = false;
if (_read_output) {
// Create pipe for StdOut and StdErr.
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true;
sa.lpSecurityDescriptor = NULL;
ERR_FAIL_COND_V(!CreatePipe(&_data->_pipe_handles[0], &_data->_pipe_handles[1], &sa, 0), ERR_CANT_FORK);
ERR_FAIL_COND_V(!SetHandleInformation(_data->_pipe_handles[0], HANDLE_FLAG_INHERIT, 0), ERR_CANT_FORK); // Read handle is for host process only and should not be inherited.
_data->_process_info.si.dwFlags |= STARTF_USESTDHANDLES;
_data->_process_info.si.hStdOutput = _data->_pipe_handles[1];
if (_read_std_err) {
_data->_process_info.si.hStdError = _data->_pipe_handles[1];
}
inherit_handles = true;
}
DWORD creaton_flags = NORMAL_PRIORITY_CLASS;
if (_open_console) {
creaton_flags |= CREATE_NEW_CONSOLE;
} else {
creaton_flags |= CREATE_NO_WINDOW;
}
int ret = CreateProcessW(nullptr, (LPWSTR)(modstr.ptrw()), nullptr, nullptr, inherit_handles, creaton_flags, nullptr, nullptr, si_w, &_data->_process_info.pi);
if (!ret && _read_output) {
CloseHandle(_data->_pipe_handles[0]); // Cleanup pipe handles.
CloseHandle(_data->_pipe_handles[1]);
_data->_pipe_handles[0] = NULL;
_data->_pipe_handles[1] = NULL;
}
ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
if (_blocking) {
if (_read_output) {
CloseHandle(_data->_pipe_handles[1]); // Close pipe write handle (only child process is writing).
int bytes_in_buffer = 0;
const int CHUNK_SIZE = 4096;
DWORD read = 0;
for (;;) { // Read StdOut and StdErr from pipe.
_bytes.resize(bytes_in_buffer + CHUNK_SIZE);
const bool success = ReadFile(_data->_pipe_handles[0], _bytes.ptr() + bytes_in_buffer, CHUNK_SIZE, &read, NULL);
if (!success || read == 0) {
break;
}
// Assume that all possible encodings are ASCII-compatible.
// Break at newline to allow receiving long output in portions.
int newline_index = -1;
for (int i = read - 1; i >= 0; i--) {
if (_bytes[bytes_in_buffer + i] == '\n') {
newline_index = i;
break;
}
}
if (newline_index == -1) {
bytes_in_buffer += read;
continue;
}
const int bytes_to_convert = bytes_in_buffer + (newline_index + 1);
_append_to_pipe(_bytes.ptr(), bytes_to_convert);
bytes_in_buffer = read - (newline_index + 1);
memmove(_bytes.ptr(), _bytes.ptr() + bytes_to_convert, bytes_in_buffer);
}
if (bytes_in_buffer > 0) {
_append_to_pipe(_bytes.ptr(), bytes_in_buffer);
}
CloseHandle(_data->_pipe_handles[0]); // Close pipe read handle.
}
WaitForSingleObject(_data->_process_info.pi.hProcess, INFINITE);
DWORD ret2;
GetExitCodeProcess(_data->_process_info.pi.hProcess, &ret2);
_exitcode = ret2;
CloseHandle(_data->_process_info.pi.hProcess);
CloseHandle(_data->_process_info.pi.hThread);
} else {
if (_read_output) {
//eventually we will need to keep this
CloseHandle(_data->_pipe_handles[1]); // Close pipe write handle (only child process is writing).
_data->_pipe_handles[1] = NULL;
}
_process_started = true;
ProcessID pid = _data->_process_info.pi.dwProcessId;
_process_id = pid;
}
return OK;
}
Error SubProcess::stop() {
if (!_process_started) {
return OK;
}
if (_data->_pipe_handles[0]) {
CloseHandle(_data->_pipe_handles[0]); // Cleanup pipe handles.
_data->_pipe_handles[0] = NULL;
}
if (_data->_pipe_handles[1]) {
CloseHandle(_data->_pipe_handles[1]);
_data->_pipe_handles[1] = NULL;
}
const int ret = TerminateProcess(_data->_process_info.pi.hProcess, 0);
CloseHandle(_data->_process_info.pi.hProcess);
CloseHandle(_data->_process_info.pi.hThread);
ZeroMemory(&_data->_process_info.si, sizeof(_data->_process_info.si));
_data->_process_info.si.cb = sizeof(_data->_process_info.si);
ZeroMemory(&_data->_process_info.pi, sizeof(_data->_process_info.pi));
_process_started = false;
return ret != 0 ? OK : FAILED;
}
Error SubProcess::poll() {
if (!_process_started) {
return FAILED;
}
if (!_data->_pipe_handles[0]) {
return FAILED;
}
_pipe.clear();
int bytes_in_buffer = 0;
const int CHUNK_SIZE = 4096;
DWORD read = 0;
_bytes.resize(bytes_in_buffer + CHUNK_SIZE);
const bool success = ReadFile(_data->_pipe_handles[0], _bytes.ptr() + bytes_in_buffer, CHUNK_SIZE, &read, NULL);
if (!success) {
stop();
return ERR_FILE_EOF;
}
if (read == 0) {
return OK;
}
// Assume that all possible encodings are ASCII-compatible.
// Break at newline to allow receiving long output in portions.
int newline_index = -1;
for (int i = read - 1; i >= 0; i--) {
if (_bytes[bytes_in_buffer + i] == '\n') {
newline_index = i;
break;
}
}
if (newline_index == -1) {
bytes_in_buffer += read;
return OK;
}
const int bytes_to_convert = bytes_in_buffer + (newline_index + 1);
_append_to_pipe(_bytes.ptr(), bytes_to_convert);
bytes_in_buffer = read - (newline_index + 1);
memmove(_bytes.ptr(), _bytes.ptr() + bytes_to_convert, bytes_in_buffer);
if (bytes_in_buffer > 0) {
_append_to_pipe(_bytes.ptr(), bytes_in_buffer);
}
return OK;
}
Error SubProcess::send_signal(const int p_signal) {
//Not Yet Impl
ERR_FAIL_V(ERR_BUG);
}
Error SubProcess::send_data(const String &p_data) {
//Not Yet Impl
ERR_FAIL_V(ERR_BUG);
}
bool SubProcess::is_process_running() const {
if (_process_id == 0) {
return false;
}
if (!_process_started) {
return false;
}
DWORD dw_exit_code = 0;
if (!GetExitCodeProcess(_data->_process_info.pi.hProcess, &dw_exit_code)) {
return false;
}
if (dw_exit_code != STILL_ACTIVE) {
return false;
}
return true;
}
String SubProcess::_quote_command_line_argument(const String &p_text) const {
for (int i = 0; i < p_text.size(); i++) {
CharType c = p_text[i];
if (c == ' ' || c == '&' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '=' || c == ';' || c == '!' || c == '\'' || c == '+' || c == ',' || c == '`' || c == '~') {
return "\"" + p_text + "\"";
}
}
return p_text;
}
void SubProcess::_append_to_pipe(char *p_bytes, int p_size) {
// Try to convert from default ANSI code page to Unicode.
LocalVector<wchar_t> wchars;
int total_wchars = MultiByteToWideChar(CP_ACP, 0, p_bytes, p_size, nullptr, 0);
if (total_wchars > 0) {
wchars.resize(total_wchars);
if (MultiByteToWideChar(CP_ACP, 0, p_bytes, p_size, wchars.ptr(), total_wchars) == 0) {
wchars.clear();
}
}
if (_pipe_mutex) {
_pipe_mutex->lock();
}
if (wchars.empty()) {
// Let's hope it's compatible with UTF-8.
_pipe += String::utf8(p_bytes, p_size);
} else {
_pipe += String(wchars.ptr(), total_wchars);
}
if (_pipe_mutex) {
_pipe_mutex->unlock();
}
}
SubProcess::SubProcess() {
_data = memnew(SubProcessWindowsData);
_blocking = false;
_read_output = true;
_read_std = true;
_read_std_err = false;
_use_pipe_mutex = false;
_pipe_mutex = NULL;
_open_console = false;
_process_id = ProcessID();
_exitcode = 0;
_data->_pipe_handles[0] = NULL;
_data->_pipe_handles[1] = NULL;
_process_started = false;
ZeroMemory(&_data->_process_info.si, sizeof(_data->_process_info.si));
_data->_process_info.si.cb = sizeof(_data->_process_info.si);
ZeroMemory(&_data->_process_info.pi, sizeof(_data->_process_info.pi));
}
SubProcess::~SubProcess() {
stop();
memdelete(_data);
}
#else
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
Error SubProcess::start() {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
// Actual virtual call goes to OS_JavaScript.
ERR_FAIL_V(ERR_BUG);
#else
if (_executable_path.empty()) {
return ERR_FILE_BAD_PATH;
}
if (is_process_running()) {
return ERR_BUSY;
}
if (_blocking && _read_output) {
String argss;
argss = "\"" + _executable_path + "\"";
for (int i = 0; i < _arguments.size(); i++) {
argss += String(" \"") + _arguments[i] + "\"";
}
if (_read_std_err) {
argss += " 2>&1"; // Read stderr too
} else {
argss += " 2>/dev/null"; //silence stderr
}
FILE *f = popen(argss.utf8().get_data(), "r");
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot pipe stream from process running with following arguments '" + argss + "'.");
char buf[65535];
while (fgets(buf, 65535, f)) {
if (_pipe_mutex) {
_pipe_mutex->lock();
}
_pipe += String::utf8(buf);
if (_pipe_mutex) {
_pipe_mutex->unlock();
}
}
int rv = pclose(f);
_exitcode = WEXITSTATUS(rv);
return OK;
}
if (!_blocking && _read_output) {
String argss;
argss = "\"" + _executable_path + "\"";
for (int i = 0; i < _arguments.size(); i++) {
argss += String(" \"") + _arguments[i] + "\"";
}
if (_read_std_err) {
argss += " 2>&1"; // Read stderr too
} else {
argss += " 2>/dev/null"; //silence stderr
}
_process_fp = popen(argss.utf8().get_data(), "r");
ERR_FAIL_COND_V_MSG(!_process_fp, ERR_CANT_OPEN, "Cannot pipe stream from process running with following arguments '" + argss + "'.");
return OK;
}
// We just run it, no need to worry about output
pid_t pid = fork();
ERR_FAIL_COND_V(pid < 0, ERR_CANT_FORK);
if (pid == 0) {
// is child
if (!_blocking) {
// For non blocking calls, create a new session-ID so parent won't wait for it.
// This ensures the process won't go zombie at end.
setsid();
}
Vector<CharString> cs;
cs.push_back(_executable_path.utf8());
for (int i = 0; i < _arguments.size(); i++) {
cs.push_back(_arguments[i].utf8());
}
Vector<char *> args;
for (int i = 0; i < cs.size(); i++) {
args.push_back((char *)cs[i].get_data());
}
args.push_back(0);
execvp(_executable_path.utf8().get_data(), &args[0]);
// still alive? something failed..
fprintf(stderr, "**ERROR** SubProcess::execute - Could not create child process while executing: %s\n", _executable_path.utf8().get_data());
raise(SIGKILL);
}
if (_blocking) {
int status;
waitpid(pid, &status, 0);
_exitcode = WIFEXITED(status) ? WEXITSTATUS(status) : status;
} else {
_process_id = pid;
}
return OK;
#endif
}
Error SubProcess::stop() {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
// Actual virtual call goes to OS_JavaScript.
ERR_FAIL_V(ERR_BUG);
#else
if (_process_fp) {
int rv = pclose(_process_fp);
_process_fp = NULL;
_exitcode = WEXITSTATUS(rv);
_process_id = 0;
return OK;
}
if (_process_id) {
int ret = ::kill(_process_id, SIGKILL);
if (!ret) {
//avoid zombie process
int st;
::waitpid(_process_id, &st, 0);
}
_process_id = 0;
return ret ? ERR_INVALID_PARAMETER : OK;
}
return OK;
#endif
}
Error SubProcess::poll() {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
// Actual virtual call goes to OS_JavaScript.
ERR_FAIL_V(ERR_BUG);
#else
if (_process_fp) {
if (fgets(_process_buf, 65535, _process_fp)) {
if (_pipe_mutex) {
_pipe_mutex->lock();
}
_pipe = String::utf8(_process_buf);
if (_pipe_mutex) {
_pipe_mutex->unlock();
}
} else {
// The process finished
// Cleanup:
stop();
return ERR_FILE_EOF;
}
}
return OK;
#endif
}
Error SubProcess::send_signal(const int p_signal) {
//Not Yet Impl
ERR_FAIL_V(ERR_BUG);
}
Error SubProcess::send_data(const String &p_data) {
//Not Yet Impl
ERR_FAIL_V(ERR_BUG);
}
bool SubProcess::is_process_running() const {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
// Actual virtual call goes to OS_JavaScript.
ERR_FAIL_V(false);
#else
if (_process_fp) {
return !feof(_process_fp);
}
if (_process_id == 0) {
return false;
}
int status = 0;
if (waitpid(_process_id, &status, WNOHANG) != 0) {
return false;
}
return true;
#endif
}
SubProcess::SubProcess() {
_blocking = false;
_read_output = true;
_read_std = true;
_read_std_err = false;
_use_pipe_mutex = false;
_pipe_mutex = NULL;
_open_console = false;
_process_id = ProcessID();
_exitcode = 0;
_process_fp = NULL;
}
SubProcess::~SubProcess() {
stop();
}
#endif
SubProcess *SubProcess::create() {
return memnew(SubProcess());
}
String SubProcess::get_executable_path() const {
return _executable_path;
}
void SubProcess::set_executable_path(const String &p_executable_path) {
ERR_FAIL_COND(is_process_running());
_executable_path = p_executable_path;
}
Vector<String> SubProcess::get_arguments() const {
return _arguments;
}
void SubProcess::set_arguments(const Vector<String> &p_arguments) {
ERR_FAIL_COND(is_process_running());
_arguments = p_arguments;
}
bool SubProcess::get_blocking() const {
return _blocking;
}
void SubProcess::set_blocking(const bool p_value) {
ERR_FAIL_COND(is_process_running());
_blocking = p_value;
}
bool SubProcess::get_read_output() const {
return _read_output;
}
void SubProcess::set_read_output(const bool p_value) {
ERR_FAIL_COND(is_process_running());
_read_output = p_value;
}
bool SubProcess::get_read_std() const {
return _read_std;
}
void SubProcess::set_read_std(const bool p_value) {
ERR_FAIL_COND(is_process_running());
_read_std = p_value;
}
bool SubProcess::get_read_std_err() const {
return _read_std_err;
}
void SubProcess::set_read_std_err(const bool p_value) {
ERR_FAIL_COND(is_process_running());
_read_std_err = p_value;
}
bool SubProcess::get_use_pipe_mutex() const {
return _use_pipe_mutex;
}
void SubProcess::set_use_pipe_mutex(const bool p_value) {
ERR_FAIL_COND(is_process_running());
_use_pipe_mutex = p_value;
}
bool SubProcess::get_open_console() const {
return _open_console;
}
void SubProcess::set_open_console(const bool p_value) {
ERR_FAIL_COND(is_process_running());
_open_console = p_value;
}
Error SubProcess::run(const String &p_executable_path, const Vector<String> &p_arguments, bool p_output, bool p_blocking, bool p_read_std_err, bool p_use_pipe_mutex, bool p_open_console) {
if (is_process_running()) {
return ERR_ALREADY_IN_USE;
}
_executable_path = p_executable_path;
_arguments = p_arguments;
_blocking = p_blocking;
_read_output = p_output;
_read_std = true;
_read_std_err = p_read_std_err;
_use_pipe_mutex = p_use_pipe_mutex;
_open_console = p_open_console;
_setup_pipe_mutex();
return start();
}
/*
SubProcess::SubProcess() {
_blocking = false;
_read_output = true;
_read_std = true;
_read_std_err = false;
_use_pipe_mutex = false;
_pipe_mutex = NULL;
_open_console = false;
_process_id = ProcessID();
_exitcode = 0;
};
*/
void SubProcess::_setup_pipe_mutex() {
if (_use_pipe_mutex) {
if (!_pipe_mutex) {
_pipe_mutex = memnew(Mutex);
}
} else {
if (_pipe_mutex) {
memdelete(_pipe_mutex);
_pipe_mutex = NULL;
}
}
}

160
sfwl/core/sub_process.h Normal file
View File

@ -0,0 +1,160 @@
//--STRIP
#ifndef SUB_PROCESS_H
#define SUB_PROCESS_H
//--STRIP
/*************************************************************************/
/* sub_process.h */
/* From https://github.com/Relintai/pandemonium_engine (MIT) */
/*************************************************************************/
//--STRIP
#include "core/list.h"
#include "core/math_defs.h"
#include "core/memory.h"
#include "core/mutex.h"
#include "core/typedefs.h"
#include "core/ustring.h"
#include "core/error_list.h"
#include <stdio.h>
//--STRIP
#if defined(_WIN64) || defined(_WIN32)
//--STRIP
#include "core/local_vector.h"
//--STRIP
#endif
/**
* Multi-Platform abstraction for running and communicating with sub processes
*/
class SubProcess {
public:
typedef int64_t ProcessID;
#if defined(_WIN64) || defined(_WIN32)
struct SubProcessWindowsData;
#endif
static SubProcess *create();
String get_executable_path() const;
void set_executable_path(const String &p_executable_path);
Vector<String> get_arguments() const;
void set_arguments(const Vector<String> &p_arguments);
bool get_blocking() const;
void set_blocking(const bool p_value);
bool get_read_output() const;
void set_read_output(const bool p_value);
bool get_read_std() const;
void set_read_std(const bool p_value);
bool get_read_std_err() const;
void set_read_std_err(const bool p_value);
bool get_use_pipe_mutex() const;
void set_use_pipe_mutex(const bool p_value);
bool get_open_console() const;
void set_open_console(const bool p_value);
String get_data() const {
return _pipe;
}
int get_process_id() const {
return _process_id;
}
int get_exitcode() const {
return _exitcode;
}
virtual Error start();
virtual Error stop();
virtual Error poll();
virtual Error send_signal(const int p_signal);
virtual Error send_data(const String &p_data);
virtual bool is_process_running() const;
Error run(const String &p_executable_path, const Vector<String> &p_arguments = Vector<String>(), bool p_output = true, bool p_blocking = true, bool p_read_std_err = false, bool p_use_pipe_mutex = false, bool p_open_console = false);
SubProcess();
virtual ~SubProcess();
protected:
void _setup_pipe_mutex();
String _executable_path;
Vector<String> _arguments;
bool _blocking;
bool _read_output;
bool _read_std;
bool _read_std_err;
String _pipe;
bool _use_pipe_mutex;
Mutex *_pipe_mutex;
bool _open_console;
ProcessID _process_id;
int _exitcode;
#if defined(_WIN64) || defined(_WIN32)
String _quote_command_line_argument(const String &p_text) const;
void _append_to_pipe(char *p_bytes, int p_size);
bool _process_started;
LocalVector<char> _bytes;
SubProcessWindowsData *_data;
#else
FILE *_process_fp;
char _process_buf[65535];
#endif
};
struct SubProcessRef {
SubProcess *f;
_FORCE_INLINE_ bool is_null() const { return f == nullptr; }
_FORCE_INLINE_ bool is_valid() const { return f != nullptr; }
_FORCE_INLINE_ operator bool() const { return f != nullptr; }
_FORCE_INLINE_ operator SubProcess *() { return f; }
_FORCE_INLINE_ SubProcess *operator->() {
return f;
}
SubProcessRef(SubProcess *fa) { f = fa; }
SubProcessRef(SubProcessRef &&other) {
f = other.f;
other.f = nullptr;
}
~SubProcessRef() {
if (f) {
memdelete(f);
}
}
};
//--STRIP
#endif
//--STRIP

View File

@ -111,7 +111,4 @@ Thread::ID Thread::get_caller_id() {
return caller_id;
}
}
//--STRIP
#endif // THREAD_H
//--STRIP
#endif

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef THREAD_SAFE_H
#define THREAD_SAFE_H
//--STRIP
/*************************************************************************/
/* thread_safe.h */
@ -15,4 +17,6 @@
#define _THREAD_SAFE_LOCK_ _thread_safe_.lock();
#define _THREAD_SAFE_UNLOCK_ _thread_safe_.unlock();
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef TIGHT_LOCAL_VECTOR_H
#define TIGHT_LOCAL_VECTOR_H
//--STRIP
/*************************************************************************/
/* tight_local_vector.h */
@ -292,4 +294,6 @@ template <class T, class I = int32_t, bool force_trivial = false>
class TightLocalVectori : public TightLocalVector<T, I, force_trivial> {
};
//--STRIP
#endif // TIGHT_LOCAL_VECTOR_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef TYPEDEFS_H
#define TYPEDEFS_H
//--STRIP
/*************************************************************************/
/* typedefs.h */
@ -403,4 +405,6 @@ struct _GlobalLock {
#define HAS_TRIVIAL_COPY(T) __has_trivial_copy(T)
#endif
//--STRIP
#endif // TYPEDEFS_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef UCAPS_H
#define UCAPS_H
//--STRIP
/*************************************************************************/
/* ucaps.h */
@ -1386,4 +1388,7 @@ static int _find_lower(int ch) {
return ch;
}
//--STRIP
#endif
//--STRIP

View File

@ -10,6 +10,7 @@
//--STRIP
#include "core/ustring.h"
#include "core/color.h"
#include "core/math_funcs.h"
#include "core/memory.h"
#include "ucaps.h"
@ -4563,6 +4564,10 @@ bool String::is_valid_unsigned_integer() const {
return true;
}
bool String::is_valid_html_color() const {
return Color::html_is_valid(*this);
}
bool String::is_valid_filename() const {
String stripped = strip_edges();
if (*this != stripped) {

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef USTRING_H
#define USTRING_H
//--STRIP
/*************************************************************************/
/* ustring.h */
@ -480,6 +482,7 @@ public:
bool is_valid_integer() const;
bool is_valid_float() const;
bool is_valid_hex_number(bool p_with_prefix) const;
bool is_valid_html_color() const;
bool is_valid_ip_address() const;
bool is_valid_filename() const;
bool is_valid_bool() const;
@ -603,4 +606,6 @@ String RTR(const String &);
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end);
//--STRIP
#endif // USTRING_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef VECTOR_H
#define VECTOR_H
//--STRIP
/*************************************************************************/
/* vector.h */
@ -171,4 +173,6 @@ bool Vector<T>::push_back(T p_elem) {
return false;
}
//--STRIP
#endif
//--STRIP

10
sfwl/core/version.h Normal file
View File

@ -0,0 +1,10 @@
//--STRIP
#ifndef SFW_VERSION_H
#define SFW_VERSION_H
//--STRIP
#define SFW_VERSION 1
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef VMAP_H
#define VMAP_H
//--STRIP
/*************************************************************************/
/* vmap.h */
@ -176,4 +178,7 @@ public:
return *this;
}
};
//--STRIP
#endif // VMAP_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef VSET_H
#define VSET_H
//--STRIP
/*************************************************************************/
/* vset.h */
@ -115,4 +117,6 @@ public:
}
};
//--STRIP
#endif // VSET_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef ARRAY_H
#define ARRAY_H
//--STRIP
/*************************************************************************/
/* array.h */
@ -89,4 +91,6 @@ public:
~Array();
};
//--STRIP
#endif // ARRAY_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef CORE_STRING_NAMES_H
#define CORE_STRING_NAMES_H
//--STRIP
/*************************************************************************/
/* core_string_names.h */
@ -65,4 +67,6 @@ public:
StringName a8;
};
//--STRIP
#endif // SCENE_STRING_NAMES_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef DICTIONARY_H
#define DICTIONARY_H
//--STRIP
/*************************************************************************/
/* dictionary.h */
@ -69,4 +71,6 @@ public:
~Dictionary();
};
//--STRIP
#endif // DICTIONARY_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef OBJECT_H
#define OBJECT_H
//--STRIP
//--STRIP
#include "core/hash_map.h"
@ -25,7 +27,7 @@ private:
void operator=(const m_class &p_rval) {} \
\
public: \
virtual String get_class() const { \
virtual String get_class() const { \
return String(#m_class); \
} \
virtual const StringName *_get_class_namev() const { \
@ -50,10 +52,10 @@ public:
static String inherits_static() { \
return String(#m_inherits); \
} \
virtual bool is_class(const String &p_class) const { \
virtual bool is_class(const String &p_class) const { \
return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); \
} \
virtual bool is_class_ptr(void *p_ptr) const { \
virtual bool is_class_ptr(void *p_ptr) const { \
return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); \
} \
static void get_valid_parents_static(Vector<String> *p_parents) { \
@ -280,4 +282,6 @@ public:
}
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef OBJECTID_H
#define OBJECTID_H
//--STRIP
/*************************************************************************/
/* object_id.h */
@ -12,4 +14,6 @@
typedef uint64_t ObjectID;
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef OBJECTRC_H
#define OBJECTRC_H
//--STRIP
/*************************************************************************/
/* object_rc.h */
@ -51,4 +53,6 @@ public:
}
};
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef SIGNAL_H
#define SIGNAL_H
//--STRIP
//--STRIP
#include "core/vector.h"
@ -171,4 +173,6 @@ bool Signal::is_connected(T *obj, void (*func)(T*, Signal *)) {
return false;
}
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef REF_PTR_H
#define REF_PTR_H
//--STRIP
/*************************************************************************/
/* ref_ptr.h */
@ -35,4 +37,6 @@ public:
~RefPtr();
};
//--STRIP
#endif // REF_PTR_H
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef REFERENCE_H
#define REFERENCE_H
//--STRIP
/*************************************************************************/
/* reference.h */
@ -267,4 +269,6 @@ public:
};
*/
//--STRIP
#endif
//--STRIP

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef RESOURCE_H
#define RESOURCE_H
//--STRIP
//--STRIP
#include "object/reference.h"
@ -22,4 +24,6 @@ public:
virtual ~Resource();
};
//--STRIP
#endif
//--STRIP

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
//--STRIP
#ifndef VARIANT_H
#define VARIANT_H
//--STRIP
/*************************************************************************/
/* variant.h */
@ -7,9 +9,21 @@
/*************************************************************************/
//--STRIP
#include "core/math_defs.h"
#include "core/aabb.h"
#include "core/basis.h"
#include "core/color.h"
#include "core/face3.h"
#include "core/plane.h"
#include "core/pool_vector.h"
#include "core/projection.h"
#include "core/quaternion.h"
#include "core/transform.h"
#include "core/transform_2d.h"
#include "core/ustring.h"
#include "core/vector3.h"
#include "core/vector3i.h"
#include "core/vector4.h"
#include "core/vector4i.h"
#include "object/array.h"
#include "object/dictionary.h"
#include "object/ref_ptr.h"
@ -23,6 +37,13 @@ typedef PoolVector<uint8_t> PoolByteArray;
typedef PoolVector<int> PoolIntArray;
typedef PoolVector<real_t> PoolRealArray;
typedef PoolVector<String> PoolStringArray;
typedef PoolVector<Vector2> PoolVector2Array;
typedef PoolVector<Vector2i> PoolVector2iArray;
typedef PoolVector<Vector3> PoolVector3Array;
typedef PoolVector<Vector3i> PoolVector3iArray;
typedef PoolVector<Vector4> PoolVector4Array;
typedef PoolVector<Vector4i> PoolVector4iArray;
typedef PoolVector<Color> PoolColorArray;
// Temporary workaround until c++11 alignas()
#ifdef __GNUC__
@ -51,7 +72,26 @@ public:
REAL,
STRING,
// math types
RECT2,
RECT2I,
VECTOR2,
VECTOR2I,
VECTOR3,
VECTOR3I,
VECTOR4,
VECTOR4I,
PLANE,
QUATERNION,
AABB,
BASIS,
TRANSFORM,
TRANSFORM2D,
PROJECTION,
// misc types
COLOR,
OBJECT,
STRING_NAME,
DICTIONARY,
@ -62,6 +102,13 @@ public:
POOL_INT_ARRAY,
POOL_REAL_ARRAY,
POOL_STRING_ARRAY,
POOL_VECTOR2_ARRAY,
POOL_VECTOR2I_ARRAY,
POOL_VECTOR3_ARRAY,
POOL_VECTOR3I_ARRAY,
POOL_VECTOR4_ARRAY,
POOL_VECTOR4I_ARRAY,
POOL_COLOR_ARRAY,
VARIANT_MAX // 38
@ -94,6 +141,11 @@ private:
bool _bool;
int64_t _int;
double _real;
Transform2D *_transform2d;
::AABB *_aabb;
Basis *_basis;
Transform *_transform;
Projection *_projection;
void *_ptr; //generic pointer
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
} _data GCC_ALIGNED_8;
@ -138,7 +190,23 @@ public:
operator double() const;
operator String() const;
operator StringName() const;
operator Rect2() const;
operator Rect2i() const;
operator Vector2() const;
operator Vector2i() const;
operator Vector3() const;
operator Vector3i() const;
operator Vector4() const;
operator Vector4i() const;
operator Plane() const;
operator ::AABB() const;
operator Quaternion() const;
operator Basis() const;
operator Transform() const;
operator Transform2D() const;
operator Projection() const;
operator Color() const;
operator RefPtr() const;
operator Object *() const;
@ -150,6 +218,15 @@ public:
operator PoolVector<int>() const;
operator PoolVector<real_t>() const;
operator PoolVector<String>() const;
operator PoolVector<Vector2>() const;
operator PoolVector<Vector2i>() const;
operator PoolVector<Vector3>() const;
operator PoolVector<Vector3i>() const;
operator PoolVector<Vector4>() const;
operator PoolVector<Vector4i>() const;
operator PoolVector<Color>() const;
operator PoolVector<Plane>() const;
operator PoolVector<Face3>() const;
operator Vector<Variant>() const;
operator Vector<uint8_t>() const;
@ -157,6 +234,15 @@ public:
operator Vector<real_t>() const;
operator Vector<String>() const;
operator Vector<StringName>() const;
operator Vector<Vector3>() const;
operator Vector<Vector3i>() const;
operator Vector<Vector4>() const;
operator Vector<Vector4i>() const;
operator Vector<Color>() const;
operator Vector<Vector2>() const;
operator Vector<Vector2i>() const;
operator Vector<Plane>() const;
// some core type enums to convert to
operator Margin() const;
@ -183,16 +269,40 @@ public:
Variant(const StringName &p_string);
Variant(const char *const p_cstring);
Variant(const CharType *p_wstring);
Variant(const Vector2 &p_vector2);
Variant(const Vector2i &p_vector2);
Variant(const Rect2 &p_rect2);
Variant(const Rect2i &p_rect2);
Variant(const Vector3 &p_vector3);
Variant(const Vector3i &p_vector3);
Variant(const Vector4 &p_vector4);
Variant(const Vector4i &p_vector4);
Variant(const Projection &p_projection);
Variant(const Plane &p_plane);
Variant(const ::AABB &p_aabb);
Variant(const Quaternion &p_quat);
Variant(const Basis &p_matrix);
Variant(const Transform2D &p_transform);
Variant(const Transform &p_transform);
Variant(const Color &p_color);
Variant(const RefPtr &p_resource);
Variant(const Object *p_object);
Variant(const Dictionary &p_dictionary);
Variant(const Array &p_array);
Variant(const PoolVector<Plane> &p_array);
Variant(const PoolVector<uint8_t> &p_raw_array);
Variant(const PoolVector<int> &p_int_array);
Variant(const PoolVector<real_t> &p_real_array);
Variant(const PoolVector<String> &p_string_array);
Variant(const PoolVector<Vector3> &p_vector3_array);
Variant(const PoolVector<Vector3i> &p_vector3_array);
Variant(const PoolVector<Color> &p_color_array);
Variant(const PoolVector<Face3> &p_face_array);
Variant(const PoolVector<Vector2> &p_vector2_array);
Variant(const PoolVector<Vector2i> &p_vector2_array);
Variant(const PoolVector<Vector4> &p_vector4_array);
Variant(const PoolVector<Vector4i> &p_vector4_array);
Variant(const Vector<Variant> &p_array);
Variant(const Vector<uint8_t> &p_array);
@ -200,6 +310,14 @@ public:
Variant(const Vector<real_t> &p_array);
Variant(const Vector<String> &p_array);
Variant(const Vector<StringName> &p_array);
Variant(const Vector<Vector3> &p_array);
Variant(const Vector<Vector3i> &p_array);
Variant(const Vector<Color> &p_array);
Variant(const Vector<Plane> &p_array);
Variant(const Vector<Vector2> &p_array);
Variant(const Vector<Vector2i> &p_array);
Variant(const Vector<Vector4> &p_array);
Variant(const Vector<Vector4i> &p_array);
// If this changes the table in variant_op must be updated
enum Operator {
@ -321,4 +439,7 @@ const Variant::ObjData &Variant::_get_obj() const {
}
String vformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant());
//--STRIP
#endif
//--STRIP

File diff suppressed because it is too large Load Diff

View File

@ -91,6 +91,11 @@
//--STRIP
{{FILE:sfwl/core/string_name.cpp}}
//--STRIP
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/color.cpp}}
//--STRIP
//#include "core/pcg.h"
//--STRIP
@ -101,14 +106,34 @@
//--STRIP
{{FILE:sfwl/core/file_access.cpp}}
{{FILE:sfwl/core/3rd_tinydir.h}}
//--STRIP
//#include "dir_access.h"
//#include "3rd_tinydir.h"
//--STRIP
{{FILE:sfwl/core/dir_access.cpp}}
//--STRIP
//System includes
//--STRIP
{{FILE:sfwl/core/inet_address.cpp}}
//--STRIP
//#include "core/error_macros.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/socket.cpp}}
//--STRIP
//Win Only
//#include <avrt.h>
//#include <direct.h>
//#include <knownfolders.h>
//#include <process.h>
//#include <regstr.h>
//#include <shlobj.h>
//#include <wchar.h>
//--STRIP
{{FILE:sfwl/core/sub_process.cpp}}
//--STRIP
//#include "core/pool_vector.h"
//#include "core/string_name.h"

View File

@ -1,6 +1,8 @@
#ifndef SFWL_H
#define SFWL_H
{{FILEINLINE:sfwl/core/version.h}}
{{FILEINLINE:tools/merger/sfw_readme.inl.h}}
{{FILEINLINE:tools/merger/sfw_linceses_core.inl.h}}
@ -38,6 +40,11 @@
//--STRIP
{{FILE:sfwl/core/typedefs.h}}
//--STRIP
//#include "core/int_types.h"
//#include "core/math_defs.h"
//--STRIP
{{FILE:sfwl/core/marshalls.h}}
//--STRIP
//#include "core/int_types.h"
@ -199,6 +206,12 @@
//--STRIP
{{FILE:sfwl/core/string_name.h}}
//--STRIP
//#include "core/math_funcs.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/color.h}}
//--STRIP
//Needs ustring.h
//--STRIP
@ -309,6 +322,29 @@
//--STRIP
{{FILE:sfwl/core/dir_access.h}}
//--STRIP
//#include "int_types.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/inet_address.h}}
//--STRIP
//#include "inet_address.h"
//--STRIP
{{FILE:sfwl/core/socket.h}}
//--STRIP
//#include "core/list.h"
//#include "core/math_defs.h"
//#include "core/memory.h"
//#include "core/mutex.h"
//#include "core/typedefs.h"
//#include "core/ustring.h"
//#include <stdio.h>
//Win Only
//#include "core/local_vector.h"
//--STRIP
{{FILE:sfwl/core/sub_process.h}}
//--STRIP
//no includes
//--STRIP

View File

@ -91,6 +91,11 @@
//--STRIP
{{FILE:sfwl/core/string_name.cpp}}
//--STRIP
//#include "core/math_funcs.h"
//--STRIP
{{FILE:sfwl/core/color.cpp}}
//--STRIP
//#include "core/pcg.h"
//--STRIP
@ -101,14 +106,34 @@
//--STRIP
{{FILE:sfwl/core/file_access.cpp}}
{{FILE:sfwl/core/3rd_tinydir.h}}
//--STRIP
//#include "dir_access.h"
//#include "3rd_tinydir.h"
//--STRIP
{{FILE:sfwl/core/dir_access.cpp}}
//--STRIP
//System includes
//--STRIP
{{FILE:sfwl/core/inet_address.cpp}}
//--STRIP
//#include "core/error_macros.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/socket.cpp}}
//--STRIP
//Win Only
//#include <avrt.h>
//#include <direct.h>
//#include <knownfolders.h>
//#include <process.h>
//#include <regstr.h>
//#include <shlobj.h>
//#include <wchar.h>
//--STRIP
{{FILE:sfwl/core/sub_process.cpp}}
//--STRIP
//#include "core/pool_vector.h"
//#include "core/string_name.h"

View File

@ -1,6 +1,8 @@
#ifndef SFWL_H
#define SFWL_H
{{FILEINLINE:sfwl/core/version.h}}
{{FILEINLINE:tools/merger/sfw_readme.inl.h}}
{{FILEINLINE:tools/merger/sfw_linceses_core.inl.h}}
@ -38,6 +40,11 @@
//--STRIP
{{FILE:sfwl/core/typedefs.h}}
//--STRIP
//#include "core/int_types.h"
//#include "core/math_defs.h"
//--STRIP
{{FILE:sfwl/core/marshalls.h}}
//--STRIP
//#include "core/int_types.h"
@ -199,6 +206,12 @@
//--STRIP
{{FILE:sfwl/core/string_name.h}}
//--STRIP
//#include "core/math_funcs.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/color.h}}
//--STRIP
//Needs ustring.h
//--STRIP
@ -309,6 +322,29 @@
//--STRIP
{{FILE:sfwl/core/dir_access.h}}
//--STRIP
//#include "int_types.h"
//#include "core/ustring.h"
//--STRIP
{{FILE:sfwl/core/inet_address.h}}
//--STRIP
//#include "inet_address.h"
//--STRIP
{{FILE:sfwl/core/socket.h}}
//--STRIP
//#include "core/list.h"
//#include "core/math_defs.h"
//#include "core/memory.h"
//#include "core/mutex.h"
//#include "core/typedefs.h"
//#include "core/ustring.h"
//#include <stdio.h>
//Win Only
//#include "core/local_vector.h"
//--STRIP
{{FILE:sfwl/core/sub_process.h}}
//--STRIP
//no includes
//--STRIP