mirror of
https://github.com/libretro/libretro-common.git
synced 2024-11-27 10:20:53 +00:00
Resync
This commit is contained in:
parent
f0f3ea1827
commit
3ad323ec8a
316
formats/json/jsonsax.c
Normal file
316
formats/json/jsonsax.c
Normal file
@ -0,0 +1,316 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (jsonsax.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <retro_inline.h>
|
||||
#include <formats/jsonsax.h>
|
||||
|
||||
#ifdef JSONSAX_ERRORS
|
||||
const char* jsonsax_errors[] =
|
||||
{
|
||||
"Ok",
|
||||
"Interrupted",
|
||||
"Missing key",
|
||||
"Unterminated key",
|
||||
"Missing value",
|
||||
"Unterminated object",
|
||||
"Unterminated array",
|
||||
"Unterminated string",
|
||||
"Invalid value"
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const jsonsax_handlers_t* handlers;
|
||||
|
||||
const char* json;
|
||||
void* ud;
|
||||
jmp_buf env;
|
||||
}
|
||||
state_t;
|
||||
|
||||
static INLINE void skip_spaces( state_t* state )
|
||||
{
|
||||
while ( isspace( (unsigned char)*state->json ) )
|
||||
state->json++;
|
||||
}
|
||||
|
||||
static INLINE void skip_digits( state_t* state )
|
||||
{
|
||||
while ( isdigit( (unsigned char)*state->json ) )
|
||||
state->json++;
|
||||
}
|
||||
|
||||
#define HANDLE_0( event ) \
|
||||
do { \
|
||||
if ( state->handlers->event && state->handlers->event( state->ud ) ) \
|
||||
longjmp( state->env, JSONSAX_INTERRUPTED ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define HANDLE_1( event, arg1 ) \
|
||||
do { \
|
||||
if ( state->handlers->event && state->handlers->event( state->ud, arg1 ) ) \
|
||||
longjmp( state->env, JSONSAX_INTERRUPTED ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define HANDLE_2( event, arg1, arg2 ) \
|
||||
do { \
|
||||
if ( state->handlers->event && state->handlers->event( state->ud, arg1, arg2 ) ) \
|
||||
longjmp( state->env, JSONSAX_INTERRUPTED ); \
|
||||
} while ( 0 )
|
||||
|
||||
static void jsonx_parse_value(state_t* state);
|
||||
|
||||
static void jsonx_parse_object( state_t* state )
|
||||
{
|
||||
state->json++; /* we're sure the current character is a '{' */
|
||||
skip_spaces( state );
|
||||
HANDLE_0( start_object );
|
||||
|
||||
while ( *state->json != '}' )
|
||||
{
|
||||
const char *name = NULL;
|
||||
if ( *state->json != '"' )
|
||||
longjmp( state->env, JSONSAX_MISSING_KEY );
|
||||
|
||||
name = ++state->json;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
const char* quote = strchr( state->json, '"' );
|
||||
|
||||
if ( !quote )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_KEY );
|
||||
|
||||
state->json = quote + 1;
|
||||
|
||||
if ( quote[ -1 ] != '\\' )
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE_2( key, name, state->json - name - 1 );
|
||||
skip_spaces( state );
|
||||
|
||||
if ( *state->json != ':' )
|
||||
longjmp( state->env, JSONSAX_MISSING_VALUE );
|
||||
|
||||
state->json++;
|
||||
skip_spaces( state );
|
||||
jsonx_parse_value( state );
|
||||
skip_spaces( state );
|
||||
|
||||
if ( *state->json != ',' )
|
||||
break;
|
||||
|
||||
state->json++;
|
||||
skip_spaces( state );
|
||||
}
|
||||
|
||||
if ( *state->json != '}' )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_OBJECT );
|
||||
|
||||
state->json++;
|
||||
HANDLE_0( end_object );
|
||||
}
|
||||
|
||||
static void jsonx_parse_array(state_t* state)
|
||||
{
|
||||
unsigned int ndx = 0;
|
||||
|
||||
state->json++; /* we're sure the current character is a '[' */
|
||||
skip_spaces( state );
|
||||
HANDLE_0( start_array );
|
||||
|
||||
while ( *state->json != ']' )
|
||||
{
|
||||
HANDLE_1( array_index, ndx++ );
|
||||
jsonx_parse_value( state );
|
||||
skip_spaces( state );
|
||||
|
||||
if ( *state->json != ',' )
|
||||
break;
|
||||
|
||||
state->json++;
|
||||
skip_spaces( state );
|
||||
}
|
||||
|
||||
if ( *state->json != ']' )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_ARRAY );
|
||||
|
||||
state->json++;
|
||||
HANDLE_0( end_array );
|
||||
}
|
||||
|
||||
static void jsonx_parse_string(state_t* state)
|
||||
{
|
||||
const char* string = ++state->json;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
const char* quote = strchr( state->json, '"' );
|
||||
|
||||
if ( !quote )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_STRING );
|
||||
|
||||
state->json = quote + 1;
|
||||
|
||||
if ( quote[ -1 ] != '\\' )
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE_2( string, string, state->json - string - 1 );
|
||||
}
|
||||
|
||||
static void jsonx_parse_boolean(state_t* state)
|
||||
{
|
||||
if ( !strncmp( state->json, "true", 4 ) )
|
||||
{
|
||||
state->json += 4;
|
||||
HANDLE_1( boolean, 1 );
|
||||
}
|
||||
else if ( !strncmp( state->json, "false", 5 ) )
|
||||
{
|
||||
state->json += 5;
|
||||
HANDLE_1( boolean, 0 );
|
||||
}
|
||||
else
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
}
|
||||
|
||||
static void jsonx_parse_null(state_t* state)
|
||||
{
|
||||
if ( !strncmp( state->json + 1, "ull", 3 ) ) /* we're sure the current character is a 'n' */
|
||||
{
|
||||
state->json += 4;
|
||||
HANDLE_0( null );
|
||||
}
|
||||
else
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
}
|
||||
|
||||
static void jsonx_parse_number(state_t* state)
|
||||
{
|
||||
const char* number = state->json;
|
||||
|
||||
if ( *state->json == '-' )
|
||||
state->json++;
|
||||
|
||||
if ( !isdigit( (unsigned char)*state->json ) )
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
|
||||
skip_digits( state );
|
||||
|
||||
if ( *state->json == '.' )
|
||||
{
|
||||
state->json++;
|
||||
|
||||
if ( !isdigit( (unsigned char)*state->json ) )
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
|
||||
skip_digits( state );
|
||||
}
|
||||
|
||||
if ( *state->json == 'e' || *state->json == 'E' )
|
||||
{
|
||||
state->json++;
|
||||
|
||||
if ( *state->json == '-' || *state->json == '+' )
|
||||
state->json++;
|
||||
|
||||
if ( !isdigit( (unsigned char)*state->json ) )
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
|
||||
skip_digits( state );
|
||||
}
|
||||
|
||||
HANDLE_2( number, number, state->json - number );
|
||||
}
|
||||
|
||||
static void jsonx_parse_value(state_t* state)
|
||||
{
|
||||
skip_spaces( state );
|
||||
|
||||
switch ( *state->json )
|
||||
{
|
||||
case '{':
|
||||
jsonx_parse_object(state);
|
||||
break;
|
||||
case '[':
|
||||
jsonx_parse_array( state );
|
||||
break;
|
||||
case '"':
|
||||
jsonx_parse_string( state );
|
||||
break;
|
||||
case 't':
|
||||
case 'f':
|
||||
jsonx_parse_boolean( state );
|
||||
break;
|
||||
case 'n':
|
||||
jsonx_parse_null( state );
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
jsonx_parse_number( state );
|
||||
break;
|
||||
|
||||
default:
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
}
|
||||
}
|
||||
|
||||
int jsonsax_parse( const char* json, const jsonsax_handlers_t* handlers, void* userdata )
|
||||
{
|
||||
state_t state;
|
||||
int res;
|
||||
|
||||
state.json = json;
|
||||
state.handlers = handlers;
|
||||
state.ud = userdata;
|
||||
|
||||
if ( ( res = setjmp( state.env ) ) == 0 )
|
||||
{
|
||||
if ( handlers->start_document )
|
||||
handlers->start_document( userdata );
|
||||
|
||||
jsonx_parse_value(&state);
|
||||
|
||||
if ( handlers->end_document )
|
||||
handlers->end_document( userdata );
|
||||
|
||||
res = JSONSAX_OK;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
3894
formats/json/jsonsax_full.c
Normal file
3894
formats/json/jsonsax_full.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
samples/net/http_test
Normal file
BIN
samples/net/http_test
Normal file
Binary file not shown.
BIN
samples/net/net_ifinfo
Normal file
BIN
samples/net/net_ifinfo
Normal file
Binary file not shown.
102
samples/streams/rzip/Makefile
Normal file
102
samples/streams/rzip/Makefile
Normal file
@ -0,0 +1,102 @@
|
||||
TARGET := rzip
|
||||
|
||||
LIBRETRO_COMM_DIR := ../../..
|
||||
LIBRETRO_DEPS_DIR := ../../../../deps
|
||||
|
||||
# Attempt to detect target platform
|
||||
ifeq '$(findstring ;,$(PATH))' ';'
|
||||
UNAME := Windows
|
||||
else
|
||||
UNAME := $(shell uname 2>/dev/null || echo Unknown)
|
||||
UNAME := $(patsubst CYGWIN%,Cygwin,$(UNAME))
|
||||
UNAME := $(patsubst MSYS%,MSYS,$(UNAME))
|
||||
UNAME := $(patsubst MINGW%,MSYS,$(UNAME))
|
||||
endif
|
||||
|
||||
# Add '.exe' extension on Windows platforms
|
||||
ifeq ($(UNAME), Windows)
|
||||
TARGET := rzip.exe
|
||||
endif
|
||||
ifeq ($(UNAME), MSYS)
|
||||
TARGET := rzip.exe
|
||||
endif
|
||||
|
||||
SOURCES := \
|
||||
rzip.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path_io.c \
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/file_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/interface_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/memory_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/rzip_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/stdin_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/trans_stream.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/trans_stream_pipe.c \
|
||||
$(LIBRETRO_COMM_DIR)/streams/trans_stream_zlib.c \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.c
|
||||
|
||||
ifneq ($(wildcard $(LIBRETRO_DEPS_DIR)/*),)
|
||||
# If we are building from inside the RetroArch
|
||||
# directory (i.e. if an 'external' deps directory
|
||||
# is avaiable), bake in zlib support
|
||||
SOURCES += \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/adler32.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/libz-crc32.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/deflate.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/gzclose.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/gzlib.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/gzread.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/gzwrite.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/inffast.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/inflate.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/inftrees.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/trees.c \
|
||||
$(LIBRETRO_DEPS_DIR)/libz/zutil.c
|
||||
INCLUDE_DIRS := -I$(LIBRETRO_COMM_DIR)/include/compat/zlib
|
||||
else
|
||||
# If this is a stand-alone libretro-common directory,
|
||||
# rely on system zlib library (note: only likely to
|
||||
# work on Unix-based platforms...)
|
||||
LDFLAGS += -lz
|
||||
endif
|
||||
|
||||
OBJS := $(SOURCES:.c=.o)
|
||||
INCLUDE_DIRS += -I$(LIBRETRO_COMM_DIR)/include
|
||||
CFLAGS += -DHAVE_ZLIB -Wall -pedantic -std=gnu99 $(INCLUDE_DIRS)
|
||||
|
||||
# Silence "ISO C does not support the 'I64' ms_printf length modifier"
|
||||
# warnings when using MinGW
|
||||
ifeq ($(UNAME), Windows)
|
||||
CFLAGS += -Wno-format
|
||||
endif
|
||||
ifeq ($(UNAME), MSYS)
|
||||
CFLAGS += -Wno-format
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g -DDEBUG -D_DEBUG
|
||||
else
|
||||
CFLAGS += -O2 -DNDEBUG
|
||||
endif
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(OBJS)
|
||||
|
||||
.PHONY: clean
|
364
samples/streams/rzip/rzip.c
Normal file
364
samples/streams/rzip/rzip.c
Normal file
@ -0,0 +1,364 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (config_file_test.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include <file/file_path.h>
|
||||
#include <streams/interface_stream.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <streams/rzip_stream.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#define FILE_TRANSFER_CHUNK_SIZE 4096
|
||||
|
||||
enum rzip_action_type
|
||||
{
|
||||
RZIP_ACTION_QUERY = 0,
|
||||
RZIP_ACTION_COMPRESS,
|
||||
RZIP_ACTION_EXTRACT
|
||||
};
|
||||
|
||||
static void rand_str(char *dst, size_t len)
|
||||
{
|
||||
char charset[] = "0123456789"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
while (len-- > 0)
|
||||
{
|
||||
size_t i = (double)rand() / RAND_MAX * (sizeof(charset) - 1);
|
||||
*dst++ = charset[i];
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char in_file_path[PATH_MAX_LENGTH];
|
||||
char out_file_path[PATH_MAX_LENGTH];
|
||||
enum rzip_action_type action = RZIP_ACTION_QUERY;
|
||||
intfstream_t *in_file = NULL;
|
||||
intfstream_t *out_file = NULL;
|
||||
int64_t in_file_size = 0;
|
||||
int64_t in_file_raw_size = 0;
|
||||
int64_t out_file_size = 0;
|
||||
int64_t file_size_diff = 0;
|
||||
int64_t total_data_read = 0;
|
||||
bool in_file_compressed = false;
|
||||
bool valid_args = false;
|
||||
bool in_place = false;
|
||||
int ret = 1;
|
||||
|
||||
in_file_path[0] = '\0';
|
||||
out_file_path[0] = '\0';
|
||||
|
||||
/* Parse arguments */
|
||||
if ((argc > 1) && !string_is_empty(argv[1]))
|
||||
{
|
||||
valid_args = true;
|
||||
|
||||
if (string_is_equal(argv[1], "i"))
|
||||
action = RZIP_ACTION_QUERY;
|
||||
else if (string_is_equal(argv[1], "a"))
|
||||
action = RZIP_ACTION_COMPRESS;
|
||||
else if (string_is_equal(argv[1], "x"))
|
||||
action = RZIP_ACTION_EXTRACT;
|
||||
else
|
||||
valid_args = false;
|
||||
}
|
||||
|
||||
/* Get input file path */
|
||||
if (valid_args && (argc > 2) && !string_is_empty(argv[2]))
|
||||
{
|
||||
strlcpy(in_file_path, argv[2], sizeof(in_file_path));
|
||||
path_resolve_realpath(in_file_path, sizeof(in_file_path), true);
|
||||
valid_args = valid_args && !string_is_empty(in_file_path);
|
||||
}
|
||||
else
|
||||
valid_args = false;
|
||||
|
||||
/* Ensure arguments are valid */
|
||||
if (!valid_args)
|
||||
{
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr, "- Query file status: %s i <input file>\n", argv[0]);
|
||||
fprintf(stderr, "- Compress file: %s a <input file> <output file (optional)>\n", argv[0]);
|
||||
fprintf(stderr, "- Extract file: %s x <input file> <output file (optional)>\n", argv[0]);
|
||||
fprintf(stderr, "Omitting <output file> will overwrite <input file>\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Ensure that input file exists */
|
||||
if (!path_is_valid(in_file_path))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input file does not exist: %s\n", in_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Get output file path, if specified */
|
||||
if ((argc > 3) && !string_is_empty(argv[3]))
|
||||
{
|
||||
strlcpy(out_file_path, argv[3], sizeof(out_file_path));
|
||||
path_resolve_realpath(out_file_path, sizeof(out_file_path), true);
|
||||
}
|
||||
|
||||
/* If we are compressing/extracting and an
|
||||
* output file was not specified, generate a
|
||||
* temporary output file path */
|
||||
if ((action != RZIP_ACTION_QUERY) &&
|
||||
string_is_empty(out_file_path))
|
||||
{
|
||||
const char *in_file_name = path_basename(in_file_path);
|
||||
char in_file_dir[PATH_MAX_LENGTH];
|
||||
|
||||
in_file_dir[0] = '\0';
|
||||
|
||||
fill_pathname_parent_dir(in_file_dir, in_file_path, sizeof(in_file_dir));
|
||||
|
||||
if (string_is_empty(in_file_name))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid input file: %s\n", in_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
srand((unsigned int)time(NULL));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char tmp_str[10] = {0};
|
||||
|
||||
/* Generate 'random' file name */
|
||||
rand_str(tmp_str, sizeof(tmp_str) - 1);
|
||||
tmp_str[0] = '.';
|
||||
|
||||
out_file_path[0] = '\0';
|
||||
|
||||
if (!string_is_empty(in_file_dir))
|
||||
fill_pathname_join(out_file_path, in_file_dir,
|
||||
tmp_str, sizeof(out_file_path));
|
||||
else
|
||||
strlcpy(out_file_path, tmp_str, sizeof(out_file_path));
|
||||
|
||||
strlcat(out_file_path, ".", sizeof(out_file_path));
|
||||
strlcat(out_file_path, in_file_name, sizeof(out_file_path));
|
||||
path_resolve_realpath(out_file_path, sizeof(out_file_path), true);
|
||||
|
||||
if (!path_is_valid(out_file_path))
|
||||
break;
|
||||
}
|
||||
|
||||
in_place = true;
|
||||
}
|
||||
|
||||
/* Ensure that input and output files
|
||||
* are different */
|
||||
if (string_is_equal(in_file_path, out_file_path))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input and output are the same file: %s\n", in_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Get input file size */
|
||||
in_file_size = (int64_t)path_get_size(in_file_path);
|
||||
|
||||
if (in_file_size < 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Input file is empty: %s\n", in_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Open input file
|
||||
* > Always use RZIP interface */
|
||||
in_file = intfstream_open_rzip_file(
|
||||
in_file_path, RETRO_VFS_FILE_ACCESS_READ);
|
||||
|
||||
if (!in_file)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to open input file: %s\n", in_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Get input file compression status */
|
||||
in_file_compressed = intfstream_is_compressed(in_file);
|
||||
|
||||
/* Get raw (uncompressed) input file size */
|
||||
in_file_raw_size = intfstream_get_size(in_file);
|
||||
|
||||
/* If this is a query operation, just
|
||||
* print current state */
|
||||
if (action == RZIP_ACTION_QUERY)
|
||||
{
|
||||
printf("%s: %s\n",
|
||||
in_file_compressed ? "File is in RZIP format" : "File is NOT in RZIP format",
|
||||
in_file_path);
|
||||
printf(" Size on disk: %" PRIi64 " bytes\n", in_file_size);
|
||||
if (in_file_compressed)
|
||||
printf(" Uncompressed size: %" PRIi64 " bytes\n", in_file_raw_size);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Check whether file is already in the
|
||||
* requested state */
|
||||
if ((in_file_compressed && (action == RZIP_ACTION_COMPRESS)) ||
|
||||
(!in_file_compressed && (action == RZIP_ACTION_EXTRACT)))
|
||||
{
|
||||
printf("Input file is %s: %s\n",
|
||||
in_file_compressed ?
|
||||
"already in RZIP format - cannot compress" :
|
||||
"not in RZIP format - cannot extract",
|
||||
in_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Check whether output file already exists */
|
||||
if (path_is_valid(out_file_path))
|
||||
{
|
||||
char reply[8];
|
||||
|
||||
reply[0] = '\0';
|
||||
|
||||
printf("WARNING: Output file already exists: %s\n", out_file_path);
|
||||
printf(" Overwrite? [Y/n]: ");
|
||||
fgets(reply, sizeof(reply), stdin);
|
||||
if (reply[0] != 'Y')
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Open output file */
|
||||
if (in_file_compressed)
|
||||
out_file = intfstream_open_file(
|
||||
out_file_path, RETRO_VFS_FILE_ACCESS_WRITE,
|
||||
RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
else
|
||||
out_file = intfstream_open_rzip_file(
|
||||
out_file_path, RETRO_VFS_FILE_ACCESS_WRITE);
|
||||
|
||||
if (!out_file)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to open output file: %s\n", out_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Start file transfer */
|
||||
printf("%s file\n", in_file_compressed ? "Extracting" : "Compressing");
|
||||
printf(" From: %s\n", in_file_path);
|
||||
printf(" To: %s\n", in_place ? in_file_path : out_file_path);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int64_t data_written = 0;
|
||||
uint8_t buffer[FILE_TRANSFER_CHUNK_SIZE];
|
||||
/* Read a single chunk from input file */
|
||||
int64_t data_read = intfstream_read(
|
||||
in_file, buffer, sizeof(buffer));
|
||||
|
||||
if (data_read < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to read from input file: %s\n", in_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
total_data_read += data_read;
|
||||
|
||||
/* Check whether we have reached the end of the file */
|
||||
if (data_read == 0)
|
||||
{
|
||||
/* Close files */
|
||||
intfstream_flush(out_file);
|
||||
intfstream_close(out_file);
|
||||
free(out_file);
|
||||
out_file = NULL;
|
||||
|
||||
intfstream_close(in_file);
|
||||
free(in_file);
|
||||
in_file = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write chunk to backup file */
|
||||
data_written = intfstream_write(out_file, buffer, data_read);
|
||||
|
||||
if (data_written != data_read)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to write to output file: %s\n", out_file_path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Update progress */
|
||||
printf("\rProgress: %" PRIi64 " %%", total_data_read * 100 / in_file_raw_size);
|
||||
fflush(stdout);
|
||||
}
|
||||
printf("\rProgress: 100 %%\n");
|
||||
|
||||
/* Display final status 'report' */
|
||||
printf("%s complete:\n", in_file_compressed ? "Extraction" : "Compression");
|
||||
|
||||
out_file_size = (int64_t)path_get_size(out_file_path);
|
||||
file_size_diff = (in_file_size > out_file_size) ?
|
||||
(in_file_size - out_file_size) :
|
||||
(out_file_size - in_file_size);
|
||||
|
||||
printf(" %" PRIi64 " -> %" PRIi64 " bytes [%" PRIi64 " %% %s]\n",
|
||||
in_file_size, out_file_size,
|
||||
file_size_diff * 100 / in_file_size,
|
||||
(out_file_size >= in_file_size) ?
|
||||
"increase" : "decrease");
|
||||
|
||||
/* If this was an in-place operation,
|
||||
* replace input file with output file */
|
||||
if (in_place)
|
||||
{
|
||||
filestream_delete(in_file_path);
|
||||
if (filestream_rename(out_file_path, in_file_path))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Failed to rename temporary file\n");
|
||||
fprintf(stderr, " From: %s\n", out_file_path);
|
||||
fprintf(stderr, " To: %s\n", in_file_path);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
if (in_file)
|
||||
{
|
||||
intfstream_close(in_file);
|
||||
free(in_file);
|
||||
}
|
||||
|
||||
if (out_file)
|
||||
{
|
||||
intfstream_close(out_file);
|
||||
free(out_file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
86
test/hash/test_hash.c
Normal file
86
test/hash/test_hash.c
Normal file
@ -0,0 +1,86 @@
|
||||
/* Copyright (C) 2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_stdstring.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <lrc_hash.h>
|
||||
|
||||
#define SUITE_NAME "hash"
|
||||
|
||||
START_TEST (test_sha256)
|
||||
{
|
||||
char output[65];
|
||||
sha256_hash(output, (uint8_t*)"abc", 3);
|
||||
ck_assert(!strcmp(output,
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sha1)
|
||||
{
|
||||
char output[41];
|
||||
char tmpfile[512];
|
||||
FILE *fd;
|
||||
tmpnam(tmpfile);
|
||||
fd = fopen(tmpfile, "wb");
|
||||
ck_assert(fd != NULL);
|
||||
fwrite("abc", 1, 3, fd);
|
||||
fclose(fd);
|
||||
sha1_calculate(tmpfile, output);
|
||||
|
||||
ck_assert(!strcmp(output,
|
||||
"A9993E364706816ABA3E25717850C26C9CD0D89D"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_djb2)
|
||||
{
|
||||
ck_assert_uint_eq(djb2_calculate("retroarch"), 0xFADF3BCF);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_sha256);
|
||||
tcase_add_test(tc_core, test_sha1);
|
||||
tcase_add_test(tc_core, test_djb2);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
1300
test/lists/test_linked_list.c
Normal file
1300
test/lists/test_linked_list.c
Normal file
File diff suppressed because it is too large
Load Diff
410
test/queues/test_generic_queue.c
Normal file
410
test/queues/test_generic_queue.c
Normal file
@ -0,0 +1,410 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_generic_queue.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <queues/generic_queue.h>
|
||||
|
||||
#define SUITE_NAME "Generic Queue"
|
||||
|
||||
static char *_value_1 = "value1";
|
||||
static char *_value_2 = "value2";
|
||||
static char *_value_3 = "value3";
|
||||
|
||||
START_TEST (test_generic_queue_create)
|
||||
{
|
||||
generic_queue_t *queue = generic_queue_new();
|
||||
ck_assert_ptr_nonnull(queue);
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_free)
|
||||
{
|
||||
generic_queue_t *queue = generic_queue_new();
|
||||
generic_queue_free(queue, NULL);
|
||||
generic_queue_free(NULL, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_push_pop)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
char *value;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_pop(queue);
|
||||
ck_assert_ptr_eq(value, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_push(queue, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
generic_queue_push(queue, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 2);
|
||||
value = (char *) generic_queue_pop(queue);
|
||||
ck_assert_ptr_eq(value, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_pop(queue);
|
||||
ck_assert_ptr_eq(value, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_peek)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
ck_assert_ptr_null(generic_queue_peek(queue));
|
||||
ck_assert_ptr_null(generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_push(queue, _value_1);
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek(queue));
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_push(queue, _value_2);
|
||||
ck_assert_ptr_eq(_value_2, generic_queue_peek(queue));
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_push(queue, _value_3);
|
||||
ck_assert_ptr_eq(_value_3, generic_queue_peek(queue));
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_shift_unshift)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
char *value;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_shift(queue, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_unshift(queue);
|
||||
ck_assert_ptr_eq(value, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_shift(queue, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
generic_queue_shift(queue, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 2);
|
||||
value = (char *) generic_queue_unshift(queue);
|
||||
ck_assert_ptr_eq(value, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_unshift(queue);
|
||||
ck_assert_ptr_eq(value, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_empty)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
ck_assert_ptr_null(generic_queue_pop(queue));
|
||||
ck_assert_ptr_null(generic_queue_unshift(queue));
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void _free_value(void *value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_iterator)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_1);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_2);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_3);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
iterator = generic_queue_iterator(queue, false);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_3);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_2);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_1);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_shift_free)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
|
||||
generic_queue_shift(queue, _value_1);
|
||||
generic_queue_shift(queue, _value_2);
|
||||
generic_queue_shift(queue, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_remove_one)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
ck_assert_ptr_null(iterator);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void _verify_queue_values(generic_queue_t *queue, int count, ...)
|
||||
{
|
||||
va_list values_list;
|
||||
void **values;
|
||||
int i;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
values = (void **)malloc(count * sizeof(void *));
|
||||
|
||||
ck_assert_int_eq(count, generic_queue_length(queue));
|
||||
|
||||
va_start(values_list, count);
|
||||
for (i = 0; i < count; i++)
|
||||
values[i] = va_arg(values_list, void *);
|
||||
va_end(values_list);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(values[i], generic_queue_iterator_value(iterator));
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
}
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
iterator = generic_queue_iterator(queue, false);
|
||||
for (i = count - 1; i >= 0; i--)
|
||||
{
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(values[i], generic_queue_iterator_value(iterator));
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
}
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
free(values);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_iterator_remove_first)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
generic_queue_iterator_free(iterator);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_2, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_iterator_remove_middle)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
generic_queue_iterator_free(iterator);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_iterator_remove_last)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, false);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
generic_queue_iterator_free(iterator);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_2);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_remove_first)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
ck_assert_ptr_eq(generic_queue_remove(queue, _value_1), _value_1);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_2, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_remove_middle)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
ck_assert_ptr_eq(generic_queue_remove(queue, _value_2), _value_2);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_remove_last)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
ck_assert_ptr_eq(generic_queue_remove(queue, _value_3), _value_3);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_2);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_iterator_free)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
|
||||
generic_queue_iterator_free(iterator);
|
||||
generic_queue_iterator_free(NULL);
|
||||
|
||||
generic_queue_free(queue, _free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_generic_queue_create);
|
||||
tcase_add_test(tc_core, test_generic_queue_free);
|
||||
tcase_add_test(tc_core, test_generic_queue_push_pop);
|
||||
tcase_add_test(tc_core, test_generic_queue_peek);
|
||||
tcase_add_test(tc_core, test_generic_queue_shift_unshift);
|
||||
tcase_add_test(tc_core, test_generic_queue_empty);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator);
|
||||
tcase_add_test(tc_core, test_generic_queue_shift_free);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_one);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_remove_first);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_remove_middle);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_remove_last);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_first);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_middle);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_last);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_free);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
321
test/string/test_stdstring.c
Normal file
321
test/string/test_stdstring.c
Normal file
@ -0,0 +1,321 @@
|
||||
/* Copyright (C) 2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_stdstring.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#define SUITE_NAME "stdstring"
|
||||
|
||||
START_TEST (test_string_filter)
|
||||
{
|
||||
char test1[] = "foo bar some string";
|
||||
char test2[] = "";
|
||||
string_remove_all_chars(test1, 's');
|
||||
string_remove_all_chars(test2, '0');
|
||||
string_remove_all_chars(NULL, 'a');
|
||||
ck_assert(!strcmp(test1, "foo bar ome tring"));
|
||||
ck_assert(!strcmp(test2, ""));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_replace)
|
||||
{
|
||||
char test1[] = "foo bar some string";
|
||||
string_replace_all_chars(test1, 's', 'S');
|
||||
string_replace_all_chars(NULL, 'a', 'A');
|
||||
ck_assert(!strcmp(test1, "foo bar Some String"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_case)
|
||||
{
|
||||
char test1[] = "foo";
|
||||
char test2[] = "01foOo[]_";
|
||||
ck_assert(!strcmp(string_to_upper(test1), "FOO"));
|
||||
ck_assert(!strcmp(string_to_upper(test2), "01FOOO[]_"));
|
||||
ck_assert(!strcmp(string_to_lower(test2), "01fooo[]_"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_char_classify)
|
||||
{
|
||||
ck_assert(ISSPACE(' '));
|
||||
ck_assert(ISSPACE('\n'));
|
||||
ck_assert(ISSPACE('\r'));
|
||||
ck_assert(ISSPACE('\t'));
|
||||
ck_assert(!ISSPACE('a'));
|
||||
|
||||
ck_assert(ISALPHA('a'));
|
||||
ck_assert(ISALPHA('Z'));
|
||||
ck_assert(!ISALPHA('5'));
|
||||
|
||||
ck_assert(ISALNUM('a'));
|
||||
ck_assert(ISALNUM('Z'));
|
||||
ck_assert(ISALNUM('5'));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_num_conv)
|
||||
{
|
||||
ck_assert_uint_eq(3, string_to_unsigned("3"));
|
||||
ck_assert_uint_eq(2147483647, string_to_unsigned("2147483647"));
|
||||
ck_assert_uint_eq(0, string_to_unsigned("foo"));
|
||||
ck_assert_uint_eq(0, string_to_unsigned("-1"));
|
||||
ck_assert_uint_eq(0, string_to_unsigned(NULL));
|
||||
|
||||
ck_assert_uint_eq(10, string_hex_to_unsigned("0xa"));
|
||||
ck_assert_uint_eq(10, string_hex_to_unsigned("a"));
|
||||
ck_assert_uint_eq(255, string_hex_to_unsigned("FF"));
|
||||
ck_assert_uint_eq(255, string_hex_to_unsigned("0xff"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned("0xfzzf"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned("0x"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned("0xx"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned(NULL));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_tokenizer)
|
||||
{
|
||||
char *testinput = "@@1@@2@@3@@@@9@@@";
|
||||
char **ptr = &testinput;
|
||||
char *token = NULL;
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, ""));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "1"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "2"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "3"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, ""));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "9"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "@"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token == NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_replacesubstr)
|
||||
{
|
||||
char *res = string_replace_substring("foobaarhellowooorldtest", "oo", "ooo");
|
||||
ck_assert(res != NULL);
|
||||
ck_assert(!strcmp(res, "fooobaarhellowoooorldtest"));
|
||||
free(res);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_trim)
|
||||
{
|
||||
char test1[] = "\t \t\nhey there \n \n";
|
||||
char test2[] = "\t \t\nhey there \n \n";
|
||||
char test3[] = "\t \t\nhey there \n \n";
|
||||
ck_assert(string_trim_whitespace_left(test1) == (char*)test1);
|
||||
ck_assert(!strcmp(test1, "hey there \n \n"));
|
||||
ck_assert(string_trim_whitespace_right(test2) == (char*)test2);
|
||||
ck_assert(!strcmp(test2, "\t \t\nhey there"));
|
||||
ck_assert(string_trim_whitespace(test3) == (char*)test3);
|
||||
ck_assert(!strcmp(test3, "hey there"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_comparison)
|
||||
{
|
||||
ck_assert(string_is_not_equal_fast("foo", "bar", 3));
|
||||
ck_assert(string_is_equal_fast("foo2", "foo2", 4));
|
||||
ck_assert(!string_is_equal_fast("foo1", "foo2", 4));
|
||||
ck_assert(string_is_equal_fast("foo1", "foo2", 3));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_word_wrap)
|
||||
{
|
||||
const char *testtxt = (
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nec "
|
||||
"enim quis orci euismod efficitur at nec arcu. Vivamus imperdiet est "
|
||||
"feugiat massa rhoncus porttitor at vitae ante. Nunc a orci vel ipsum "
|
||||
"tempor posuere sed a lacus. Ut erat odio, ultrices vitae iaculis "
|
||||
"fringilla, iaculis ut eros.\nSed facilisis viverra lectus et "
|
||||
"ullamcorper. Aenean risus ex, ornare eget scelerisque ac, imperdiet eu "
|
||||
"ipsum. Morbi pellentesque erat metus, sit amet aliquet libero rutrum "
|
||||
"et. Integer non ullamcorper tellus.");
|
||||
const char *expected = (
|
||||
"Lorem ipsum dolor sit amet, consectetur\n"
|
||||
"adipiscing elit. Nam nec enim quis orci\n"
|
||||
"euismod efficitur at nec arcu. Vivamus\n"
|
||||
"imperdiet est feugiat massa rhoncus\n"
|
||||
"porttitor at vitae ante. Nunc a orci vel\n"
|
||||
"ipsum tempor posuere sed a lacus. Ut\n"
|
||||
"erat odio, ultrices vitae iaculis\n"
|
||||
"fringilla, iaculis ut eros.\n"
|
||||
"Sed facilisis viverra lectus et\n"
|
||||
"ullamcorper. "
|
||||
"Aenean risus ex, ornare eget scelerisque ac, imperdiet eu ipsum. Morbi "
|
||||
"pellentesque erat metus, sit amet aliquet libero rutrum et. Integer "
|
||||
"non ullamcorper tellus.");
|
||||
|
||||
char output[1024];
|
||||
|
||||
word_wrap(output, testtxt, 40, true, 10);
|
||||
ck_assert(!strcmp(output, expected));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_strlcpy)
|
||||
{
|
||||
char buf1[8];
|
||||
ck_assert_uint_eq(3, strlcpy(buf1, "foo", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foo", 4));
|
||||
ck_assert_uint_eq(11, strlcpy(buf1, "foo12345678", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foo1234", 8));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_strlcat)
|
||||
{
|
||||
char buf1[8];
|
||||
buf1[0] = 'f';
|
||||
buf1[1] = '\0';
|
||||
ck_assert_uint_eq(10, strlcat(buf1, "ooooooooo", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foooooo\0", 8));
|
||||
ck_assert_uint_eq(13, strlcat(buf1, "123456", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foooooo\0", 8));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_strldup)
|
||||
{
|
||||
char buf1[8] = "foo";
|
||||
char *tv1 = strldup(buf1, 16);
|
||||
char *tv2 = strldup(buf1, 2);
|
||||
ck_assert(tv1 != (char*)buf1);
|
||||
ck_assert(tv2 != (char*)buf1);
|
||||
ck_assert_uint_eq(strlen(tv2), 1);
|
||||
ck_assert(tv2[0] == 'f' && tv2[1] == 0);
|
||||
free(tv1);
|
||||
free(tv2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_utf8_conv_utf32)
|
||||
{
|
||||
uint32_t output[12];
|
||||
const char test1[] = "aæ⠻จйγチℝ\xff";
|
||||
ck_assert_uint_eq(8, utf8_conv_utf32(output, 12, test1, strlen(test1)));
|
||||
ck_assert_uint_eq(97, output[0]);
|
||||
ck_assert_uint_eq(230, output[1]);
|
||||
ck_assert_uint_eq(10299, output[2]);
|
||||
ck_assert_uint_eq(3592, output[3]);
|
||||
ck_assert_uint_eq(1081, output[4]);
|
||||
ck_assert_uint_eq(947, output[5]);
|
||||
ck_assert_uint_eq(12481, output[6]);
|
||||
ck_assert_uint_eq(8477, output[7]);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_utf8_util)
|
||||
{
|
||||
const char *test1 = "aæ⠻จ𠀤";
|
||||
const char **tptr = &test1;
|
||||
char out[64];
|
||||
ck_assert_uint_eq(utf8len(test1), 5);
|
||||
ck_assert_uint_eq(utf8len(NULL), 0);
|
||||
ck_assert(&test1[1 + 2 + 3] == utf8skip(test1, 3));
|
||||
|
||||
ck_assert_uint_eq(97, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(230, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(10299, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(3592, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(131108, utf8_walk(tptr));
|
||||
|
||||
//ck_assert_uint_eq(1, utf8cpy(out, 64, test1, 1));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_utf16_conv)
|
||||
{
|
||||
const uint16_t test1[] = {0x0061, 0x00e6, 0x283b, 0x0e08, 0xd840, 0xdc24};
|
||||
char out[64];
|
||||
size_t outlen = sizeof(out);
|
||||
ck_assert(utf16_conv_utf8((uint8_t*)out, &outlen, test1, sizeof(test1) / 2));
|
||||
ck_assert_uint_eq(outlen, 13);
|
||||
ck_assert(!memcmp(out, "aæ⠻จ𠀤", 13));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_string_comparison);
|
||||
tcase_add_test(tc_core, test_string_num_conv);
|
||||
tcase_add_test(tc_core, test_string_char_classify);
|
||||
tcase_add_test(tc_core, test_string_case);
|
||||
tcase_add_test(tc_core, test_string_filter);
|
||||
tcase_add_test(tc_core, test_string_replace);
|
||||
tcase_add_test(tc_core, test_string_tokenizer);
|
||||
tcase_add_test(tc_core, test_string_trim);
|
||||
tcase_add_test(tc_core, test_string_replacesubstr);
|
||||
tcase_add_test(tc_core, test_word_wrap);
|
||||
tcase_add_test(tc_core, test_strlcpy);
|
||||
tcase_add_test(tc_core, test_strlcat);
|
||||
tcase_add_test(tc_core, test_strldup);
|
||||
tcase_add_test(tc_core, test_utf8_conv_utf32);
|
||||
tcase_add_test(tc_core, test_utf16_conv);
|
||||
tcase_add_test(tc_core, test_utf8_util);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
112
test/utils/test_utils.c
Normal file
112
test/utils/test_utils.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* Copyright (C) 2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_stdstring.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <utils/md5.h>
|
||||
#include <encodings/crc32.h>
|
||||
|
||||
#define SUITE_NAME "hash"
|
||||
|
||||
START_TEST (test_md5)
|
||||
{
|
||||
uint8_t output[16];
|
||||
MD5_CTX ctx;
|
||||
MD5_Init(&ctx);
|
||||
MD5_Final(output, &ctx);
|
||||
ck_assert(!memcmp(
|
||||
"\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e",
|
||||
output, 16));
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Final(output, &ctx);
|
||||
ck_assert(!memcmp(
|
||||
"\x9e\x10\x7d\x9d\x37\x2b\xb6\x82\x6b\xd8\x1d\x35\x42\xa4\x19\xd6",
|
||||
output, 16));
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Final(output, &ctx);
|
||||
ck_assert(!memcmp(
|
||||
"\x4e\x67\xdb\x4a\x7a\x40\x6b\x0c\xfd\xad\xd8\x87\xcd\xe7\x88\x8e",
|
||||
output, 16));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_crc32)
|
||||
{
|
||||
char buf1[] = "retroarch";
|
||||
char buf2[] = "12345678";
|
||||
char buf3[] = "The quick brown fox jumps over the lazy dog";
|
||||
uint32_t test1 = encoding_crc32(0, (uint8_t*)buf1, strlen(buf1));
|
||||
uint32_t test2 = encoding_crc32(0, (uint8_t*)buf2, strlen(buf2));
|
||||
uint32_t test3 = encoding_crc32(0, (uint8_t*)buf3, strlen(buf3));
|
||||
ck_assert_uint_eq(0x3cae141a, test1);
|
||||
ck_assert_uint_eq(0x9ae0daaf, test2);
|
||||
ck_assert_uint_eq(0x414fa339, test3);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_crc32_file)
|
||||
{
|
||||
char tmpfile[512];
|
||||
FILE *fd;
|
||||
tmpnam(tmpfile);
|
||||
fd = fopen(tmpfile, "wb");
|
||||
ck_assert(fd != NULL);
|
||||
fwrite("12345678", 1, 8, fd);
|
||||
fclose(fd);
|
||||
|
||||
ck_assert_uint_eq(file_crc32(0, tmpfile), 0x9ae0daaf);
|
||||
/* Error checking */
|
||||
ck_assert_uint_eq(file_crc32(0, "/this/path/should/not/exist"), 0);
|
||||
ck_assert_uint_eq(file_crc32(0, NULL), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_md5);
|
||||
tcase_add_test(tc_core, test_crc32);
|
||||
tcase_add_test(tc_core, test_crc32_file);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
@ -131,7 +131,7 @@
|
||||
#endif
|
||||
|
||||
#if defined(__PS3__) || defined(__PSL1GHT__)
|
||||
#include "defines/ps3_defines.h"
|
||||
#include <defines/ps3_defines.h>
|
||||
#if defined(__PSL1GHT__)
|
||||
#include <lv2/sysfs.h>
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user