mirror of
https://github.com/Relintai/sfw.git
synced 2025-01-17 14:47:18 +01:00
Updated the classes in sfwl. Also added coloir to it as it's quite useful.
This commit is contained in:
parent
8e2f809e02
commit
2564606779
@ -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
|
@ -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
|
||||
|
@ -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
522
sfwl/core/color.cpp
Normal 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
247
sfwl/core/color.h
Normal 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
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
331
sfwl/core/inet_address.cpp
Normal 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
96
sfwl/core/inet_address.h
Normal 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
|
@ -1,5 +1,7 @@
|
||||
//--STRIP
|
||||
#ifndef GLOBALS_LIST_H
|
||||
#define GLOBALS_LIST_H
|
||||
//--STRIP
|
||||
|
||||
/*************************************************************************/
|
||||
/* list.h */
|
||||
@ -674,4 +676,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
//--STRIP
|
||||
#endif
|
||||
//--STRIP
|
||||
|
@ -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
|
||||
|
@ -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
148
sfwl/core/marshalls.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
356
sfwl/core/socket.cpp
Normal 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
69
sfwl/core/socket.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
761
sfwl/core/sub_process.cpp
Normal 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
160
sfwl/core/sub_process.h
Normal 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
|
@ -111,7 +111,4 @@ Thread::ID Thread::get_caller_id() {
|
||||
return caller_id;
|
||||
}
|
||||
}
|
||||
|
||||
//--STRIP
|
||||
#endif // THREAD_H
|
||||
//--STRIP
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
10
sfwl/core/version.h
Normal file
@ -0,0 +1,10 @@
|
||||
//--STRIP
|
||||
#ifndef SFW_VERSION_H
|
||||
#define SFW_VERSION_H
|
||||
//--STRIP
|
||||
|
||||
#define SFW_VERSION 1
|
||||
|
||||
//--STRIP
|
||||
#endif
|
||||
//--STRIP
|
@ -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
|
||||
|
@ -1,5 +1,7 @@
|
||||
//--STRIP
|
||||
#ifndef VSET_H
|
||||
#define VSET_H
|
||||
//--STRIP
|
||||
|
||||
/*************************************************************************/
|
||||
/* vset.h */
|
||||
@ -115,4 +117,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//--STRIP
|
||||
#endif // VSET_H
|
||||
//--STRIP
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,7 @@
|
||||
//--STRIP
|
||||
#ifndef OBJECTRC_H
|
||||
#define OBJECTRC_H
|
||||
//--STRIP
|
||||
|
||||
/*************************************************************************/
|
||||
/* object_rc.h */
|
||||
@ -51,4 +53,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//--STRIP
|
||||
#endif
|
||||
//--STRIP
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,7 @@
|
||||
//--STRIP
|
||||
#ifndef REFERENCE_H
|
||||
#define REFERENCE_H
|
||||
//--STRIP
|
||||
|
||||
/*************************************************************************/
|
||||
/* reference.h */
|
||||
@ -267,4 +269,6 @@ public:
|
||||
};
|
||||
*/
|
||||
|
||||
//--STRIP
|
||||
#endif
|
||||
//--STRIP
|
||||
|
@ -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
@ -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
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user