mirror of
https://github.com/bkaradzic/bx.git
synced 2026-02-17 20:52:37 +01:00
Added .ini settings utility.
This commit is contained in:
1
3rdparty/ini/README.md
vendored
Normal file
1
3rdparty/ini/README.md
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
https://github.com/mattiasgustavsson/libs/
|
||||||
1056
3rdparty/ini/ini.h
vendored
Normal file
1056
3rdparty/ini/ini.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
333
3rdparty/ini/ini.md
vendored
Normal file
333
3rdparty/ini/ini.md
vendored
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
ini.h
|
||||||
|
=====
|
||||||
|
|
||||||
|
Library: [ini.h](../ini.h)
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
Loading an ini file and retrieving values
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define INI_IMPLEMENTATION
|
||||||
|
#include "ini.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
FILE* fp = fopen( "test.ini", "r" );
|
||||||
|
fseek( fp, 0, SEEK_END );
|
||||||
|
int size = ftell( fp );
|
||||||
|
fseek( fp, 0, SEEK_SET );
|
||||||
|
char* data = (char*) malloc( size + 1 );
|
||||||
|
fread( data, 1, size, fp );
|
||||||
|
data[ size ] = '\0';
|
||||||
|
fclose( fp );
|
||||||
|
|
||||||
|
ini_t* ini = ini_load( data );
|
||||||
|
free( data );
|
||||||
|
int second_index = ini_find_property( ini, INI_GLOBAL_SECTION, "SecondSetting" );
|
||||||
|
char const* second = ini_property_value( ini, INI_GLOBAL_SECTION, second_index );
|
||||||
|
printf( "%s=%s\n", "SecondSetting", second );
|
||||||
|
int section = ini_find_section( ini, "MySection" );
|
||||||
|
int third_index = ini_find_property( ini, section, "ThirdSetting" );
|
||||||
|
char const* third = ini_property_value( ini, section, third_index );
|
||||||
|
printf( "%s=%s\n", "ThirdSetting", third );
|
||||||
|
ini_destroy( ini );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Creating a new ini file
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define INI_IMPLEMENTATION
|
||||||
|
#include "ini.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
ini_t* ini = ini_create();
|
||||||
|
ini_property_add( ini, INI_GLOBAL_SECTION, "FirstSetting", "Test" );
|
||||||
|
ini_property_add( ini, INI_GLOBAL_SECTION, "SecondSetting", "2" );
|
||||||
|
int section = ini_section_add( ini, "MySection" );
|
||||||
|
ini_property_add( ini, section, "ThirdSetting", "Three" );
|
||||||
|
|
||||||
|
int size = ini_save( ini, NULL, 0 ); // Find the size needed
|
||||||
|
char* data = (char*) malloc( size );
|
||||||
|
size = ini_save( ini, data, size ); // Actually save the file
|
||||||
|
ini_destroy( ini );
|
||||||
|
|
||||||
|
FILE* fp = fopen( "test.ini", "w" );
|
||||||
|
fwrite( data, 1, size, fp );
|
||||||
|
fclose( fp );
|
||||||
|
free( data );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
API Documentation
|
||||||
|
=================
|
||||||
|
|
||||||
|
ini.h is a small library for reading classic .ini files. It is a single-header library, and does not need any .lib files
|
||||||
|
or other binaries, or any build scripts. To use it, you just include ini.h to get the API declarations. To get the
|
||||||
|
definitions, you must include ini.h from *one* single C or C++ file, and #define the symbol `INI_IMPLEMENTATION` before
|
||||||
|
you do.
|
||||||
|
|
||||||
|
|
||||||
|
Customization
|
||||||
|
-------------
|
||||||
|
There are a few different things in ini.h which are configurable by #defines. The customizations only affect the
|
||||||
|
implementation, so will only need to be defined in the file where you have the #define INI_IMPLEMENTATION.
|
||||||
|
|
||||||
|
Note that if all customizations are utilized, ini.h will include no external files whatsoever, which might be useful
|
||||||
|
if you need full control over what code is being built.
|
||||||
|
|
||||||
|
|
||||||
|
### Custom memory allocators
|
||||||
|
|
||||||
|
To store the internal data structures, ini.h needs to do dynamic allocation by calling `malloc`. Programs might want to
|
||||||
|
keep track of allocations done, or use custom defined pools to allocate memory from. ini.h allows for specifying custom
|
||||||
|
memory allocation functions for `malloc` and `free`.
|
||||||
|
This is done with the following code:
|
||||||
|
|
||||||
|
#define INI_IMPLEMENTATION
|
||||||
|
#define INI_MALLOC( ctx, size ) ( my_custom_malloc( ctx, size ) )
|
||||||
|
#define INI_FREE( ctx, ptr ) ( my_custom_free( ctx, ptr ) )
|
||||||
|
#include "ini.h"
|
||||||
|
|
||||||
|
where `my_custom_malloc` and `my_custom_free` are your own memory allocation/deallocation functions. The `ctx` parameter
|
||||||
|
is an optional parameter of type `void*`. When `ini_create` or `ini_load` is called, you can pass in a `memctx`
|
||||||
|
parameter, which can be a pointer to anything you like, and which will be passed through as the `ctx` parameter to every
|
||||||
|
`INI_MALLOC`/`INI_FREE` call. For example, if you are doing memory tracking, you can pass a pointer to your tracking
|
||||||
|
data as `memctx`, and in your custom allocation/deallocation function, you can cast the `ctx` param back to the
|
||||||
|
right type, and access the tracking data.
|
||||||
|
|
||||||
|
If no custom allocator is defined, ini.h will default to `malloc` and `free` from the C runtime library.
|
||||||
|
|
||||||
|
|
||||||
|
### Custom C runtime function
|
||||||
|
|
||||||
|
The library makes use of three additional functions from the C runtime library, and for full flexibility, it allows you
|
||||||
|
to substitute them for your own. Here's an example:
|
||||||
|
|
||||||
|
#define INI_IMPLEMENTATION
|
||||||
|
#define INI_MEMCPY( dst, src, cnt ) ( my_memcpy_func( dst, src, cnt ) )
|
||||||
|
#define INI_STRLEN( s ) ( my_strlen_func( s ) )
|
||||||
|
#define INI_STRICMP( s1, s2 ) ( my_stricmp_func( s1, s2 ) )
|
||||||
|
#include "ini.h"
|
||||||
|
|
||||||
|
If no custom function is defined, ini.h will default to the C runtime library equivalent.
|
||||||
|
|
||||||
|
|
||||||
|
ini_create
|
||||||
|
----------
|
||||||
|
|
||||||
|
ini_t* ini_create( void* memctx )
|
||||||
|
|
||||||
|
Instantiates a new, empty ini structure, which can be manipulated with other API calls, to fill it with data. To save it
|
||||||
|
out to an ini-file string, use `ini_save`. When no longer needed, it can be destroyed by calling `ini_destroy`.
|
||||||
|
`memctx` is a pointer to user defined data which will be passed through to the custom INI_MALLOC/INI_FREE calls. It can
|
||||||
|
be NULL if no user defined data is needed.
|
||||||
|
|
||||||
|
|
||||||
|
ini_load
|
||||||
|
--------
|
||||||
|
|
||||||
|
ini_t* ini_load( char const* data, void* memctx )
|
||||||
|
|
||||||
|
Parse the zero-terminated string `data` containing an ini-file, and create a new ini_t instance containing the data.
|
||||||
|
The instance can be manipulated with other API calls to enumerate sections/properties and retrieve values. When no
|
||||||
|
longer needed, it can be destroyed by calling `ini_destroy`. `memctx` is a pointer to user defined data which will be
|
||||||
|
passed through to the custom INI_MALLOC/INI_FREE calls. It can be NULL if no user defined data is needed.
|
||||||
|
|
||||||
|
|
||||||
|
ini_save
|
||||||
|
--------
|
||||||
|
|
||||||
|
int ini_save( ini_t const* ini, char* data, int size )
|
||||||
|
|
||||||
|
Saves an ini structure as a zero-terminated ini-file string, into the specified buffer. Returns the number of bytes
|
||||||
|
written, including the zero terminator. If `data` is NULL, nothing is written, but `ini_save` still returns the number
|
||||||
|
of bytes it would have written. If the size of `data`, as specified in the `size` parameter, is smaller than that
|
||||||
|
required, only part of the ini-file string will be written. `ini_save` still returns the number of bytes it would have
|
||||||
|
written had the buffer been large enough.
|
||||||
|
|
||||||
|
|
||||||
|
ini_destroy
|
||||||
|
-----------
|
||||||
|
|
||||||
|
void ini_destroy( ini_t* ini )
|
||||||
|
|
||||||
|
Destroy an `ini_t` instance created by calling `ini_load` or `ini_create`, releasing the memory allocated by it. No
|
||||||
|
further API calls are valid on an `ini_t` instance after calling `ini_destroy` on it.
|
||||||
|
|
||||||
|
|
||||||
|
ini_section_count
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
int ini_section_count( ini_t const* ini )
|
||||||
|
|
||||||
|
Returns the number of sections in an ini file. There's at least one section in an ini file (the global section), but
|
||||||
|
there can be many more, each specified in the file by the section name wrapped in square brackets [ ].
|
||||||
|
|
||||||
|
|
||||||
|
ini_section_name
|
||||||
|
----------------
|
||||||
|
|
||||||
|
char const* ini_section_name( ini_t const* ini, int section )
|
||||||
|
|
||||||
|
Returns the name of the section with the specified index. `section` must be non-negative and less than the value
|
||||||
|
returned by `ini_section_count`, or `ini_section_name` will return NULL. The defined constant `INI_GLOBAL_SECTION` can
|
||||||
|
be used to indicate the global section.
|
||||||
|
|
||||||
|
|
||||||
|
ini_property_count
|
||||||
|
------------------
|
||||||
|
|
||||||
|
int ini_property_count( ini_t const* ini, int section )
|
||||||
|
|
||||||
|
Returns the number of properties belonging to the section with the specified index. `section` must be non-negative and
|
||||||
|
less than the value returned by `ini_section_count`, or `ini_section_name` will return 0. The defined constant
|
||||||
|
`INI_GLOBAL_SECTION` can be used to indicate the global section. Properties are declared in the ini-file on he format
|
||||||
|
`name=value`.
|
||||||
|
|
||||||
|
|
||||||
|
ini_property_name
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
char const* ini_property_name( ini_t const* ini, int section, int property )
|
||||||
|
|
||||||
|
Returns the name of the property with the specified index `property` in the section with the specified index `section`.
|
||||||
|
`section` must be non-negative and less than the value returned by `ini_section_count`, and `property` must be
|
||||||
|
non-negative and less than the value returned by `ini_property_count`, or `ini_property_name` will return NULL. The
|
||||||
|
defined constant `INI_GLOBAL_SECTION` can be used to indicate the global section.
|
||||||
|
|
||||||
|
|
||||||
|
ini_property_value
|
||||||
|
------------------
|
||||||
|
|
||||||
|
char const* ini_property_value( ini_t const* ini, int section, int property )
|
||||||
|
|
||||||
|
Returns the value of the property with the specified index `property` in the section with the specified index `section`.
|
||||||
|
`section` must be non-negative and less than the value returned by `ini_section_count`, and `property` must be
|
||||||
|
non-negative and less than the value returned by `ini_property_count`, or `ini_property_value` will return NULL. The
|
||||||
|
defined constant `INI_GLOBAL_SECTION` can be used to indicate the global section.
|
||||||
|
|
||||||
|
|
||||||
|
ini_find_section
|
||||||
|
----------------
|
||||||
|
|
||||||
|
int ini_find_section( ini_t const* ini, char const* name, int name_length )
|
||||||
|
|
||||||
|
Finds the section with the specified name, and returns its index. `name_length` specifies the number of characters in
|
||||||
|
`name`, which does not have to be zero-terminated. If `name_length` is zero, the length is determined automatically, but
|
||||||
|
in this case `name` has to be zero-terminated. If no section with the specified name could be found, the value
|
||||||
|
`INI_NOT_FOUND` is returned.
|
||||||
|
|
||||||
|
|
||||||
|
ini_find_property
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
int ini_find_property( ini_t const* ini, int section, char const* name, int name_length )
|
||||||
|
|
||||||
|
Finds the property with the specified name, within the section with the specified index, and returns the index of the
|
||||||
|
property. `name_length` specifies the number of characters in `name`, which does not have to be zero-terminated. If
|
||||||
|
`name_length` is zero, the length is determined automatically, but in this case `name` has to be zero-terminated. If no
|
||||||
|
property with the specified name could be found within the specified section, the value `INI_NOT_FOUND` is returned.
|
||||||
|
`section` must be non-negative and less than the value returned by `ini_section_count`, or `ini_find_property` will
|
||||||
|
return `INI_NOT_FOUND`. The defined constant `INI_GLOBAL_SECTION` can be used to indicate the global section.
|
||||||
|
|
||||||
|
|
||||||
|
ini_section_add
|
||||||
|
---------------
|
||||||
|
|
||||||
|
int ini_section_add( ini_t* ini, char const* name, int length )
|
||||||
|
|
||||||
|
Adds a section with the specified name, and returns the index it was added at. There is no check done to see if a
|
||||||
|
section with the specified name already exists - multiple sections of the same name are allowed. `length` specifies the
|
||||||
|
number of characters in `name`, which does not have to be zero-terminated. If `length` is zero, the length is determined
|
||||||
|
automatically, but in this case `name` has to be zero-terminated.
|
||||||
|
|
||||||
|
|
||||||
|
ini_property_add
|
||||||
|
----------------
|
||||||
|
|
||||||
|
void ini_property_add( ini_t* ini, int section, char const* name, int name_length, char const* value, int value_length )
|
||||||
|
|
||||||
|
Adds a property with the specified name and value to the specified section, and returns the index it was added at. There
|
||||||
|
is no check done to see if a property with the specified name already exists - multiple properties of the same name are
|
||||||
|
allowed. `name_length` and `value_length` specifies the number of characters in `name` and `value`, which does not have
|
||||||
|
to be zero-terminated. If `name_length` or `value_length` is zero, the length is determined automatically, but in this
|
||||||
|
case `name`/`value` has to be zero-terminated. `section` must be non-negative and less than the value returned by
|
||||||
|
`ini_section_count`, or the property will not be added. The defined constant `INI_GLOBAL_SECTION` can be used to
|
||||||
|
indicate the global section.
|
||||||
|
|
||||||
|
|
||||||
|
ini_section_remove
|
||||||
|
------------------
|
||||||
|
|
||||||
|
void ini_section_remove( ini_t* ini, int section )
|
||||||
|
|
||||||
|
Removes the section with the specified index, and all properties within it. `section` must be non-negative and less than
|
||||||
|
the value returned by `ini_section_count`. The defined constant `INI_GLOBAL_SECTION` can be used to indicate the global
|
||||||
|
section. Note that removing a section will shuffle section indices, so that section indices you may have stored will no
|
||||||
|
longer indicate the same section as it did before the remove. Use the find functions to update your indices.
|
||||||
|
|
||||||
|
|
||||||
|
ini_property_remove
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
void ini_property_remove( ini_t* ini, int section, int property )
|
||||||
|
|
||||||
|
Removes the property with the specified index from the specified section. `section` must be non-negative and less than
|
||||||
|
the value returned by `ini_section_count`, and `property` must be non-negative and less than the value returned by
|
||||||
|
`ini_property_count`. The defined constant `INI_GLOBAL_SECTION` can be used to indicate the global section. Note that
|
||||||
|
removing a property will shuffle property indices within the specified section, so that property indices you may have
|
||||||
|
stored will no longer indicate the same property as it did before the remove. Use the find functions to update your
|
||||||
|
indices.
|
||||||
|
|
||||||
|
|
||||||
|
ini_section_name_set
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
void ini_section_name_set( ini_t* ini, int section, char const* name, int length )
|
||||||
|
|
||||||
|
Change the name of the section with the specified index. `section` must be non-negative and less than the value returned
|
||||||
|
by `ini_section_count`. The defined constant `INI_GLOBAL_SECTION` can be used to indicate the global section. `length`
|
||||||
|
specifies the number of characters in `name`, which does not have to be zero-terminated. If `length` is zero, the length
|
||||||
|
is determined automatically, but in this case `name` has to be zero-terminated.
|
||||||
|
|
||||||
|
|
||||||
|
ini_property_name_set
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
void ini_property_name_set( ini_t* ini, int section, int property, char const* name, int length )
|
||||||
|
|
||||||
|
Change the name of the property with the specified index in the specified section. `section` must be non-negative and
|
||||||
|
less than the value returned by `ini_section_count`, and `property` must be non-negative and less than the value
|
||||||
|
returned by `ini_property_count`. The defined constant `INI_GLOBAL_SECTION` can be used to indicate the global section.
|
||||||
|
`length` specifies the number of characters in `name`, which does not have to be zero-terminated. If `length` is zero,
|
||||||
|
the length is determined automatically, but in this case `name` has to be zero-terminated.
|
||||||
|
|
||||||
|
|
||||||
|
ini_property_value_set
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
void ini_property_value_set( ini_t* ini, int section, int property, char const* value, int length )
|
||||||
|
|
||||||
|
Change the value of the property with the specified index in the specified section. `section` must be non-negative and
|
||||||
|
less than the value returned by `ini_section_count`, and `property` must be non-negative and less than the value
|
||||||
|
returned by `ini_property_count`. The defined constant `INI_GLOBAL_SECTION` can be used to indicate the global section.
|
||||||
|
`length` specifies the number of characters in `value`, which does not have to be zero-terminated. If `length` is zero,
|
||||||
|
the length is determined automatically, but in this case `value` has to be zero-terminated.
|
||||||
@@ -200,10 +200,10 @@ namespace bx
|
|||||||
|
|
||||||
inline MemoryWriter::MemoryWriter(MemoryBlockI* _memBlock)
|
inline MemoryWriter::MemoryWriter(MemoryBlockI* _memBlock)
|
||||||
: m_memBlock(_memBlock)
|
: m_memBlock(_memBlock)
|
||||||
, m_data(NULL)
|
, m_data(NULL)
|
||||||
, m_pos(0)
|
, m_pos(0)
|
||||||
, m_top(0)
|
, m_top(0)
|
||||||
, m_size(0)
|
, m_size(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,11 +391,19 @@ namespace bx
|
|||||||
inline int64_t getSize(SeekerI* _seeker)
|
inline int64_t getSize(SeekerI* _seeker)
|
||||||
{
|
{
|
||||||
int64_t offset = _seeker->seek();
|
int64_t offset = _seeker->seek();
|
||||||
int64_t size = _seeker->seek(0, Whence::End);
|
int64_t size = _seeker->seek(0, Whence::End);
|
||||||
_seeker->seek(offset, Whence::Begin);
|
_seeker->seek(offset, Whence::Begin);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int64_t getRemain(SeekerI* _seeker)
|
||||||
|
{
|
||||||
|
int64_t offset = _seeker->seek();
|
||||||
|
int64_t size = _seeker->seek(0, Whence::End);
|
||||||
|
_seeker->seek(offset, Whence::Begin);
|
||||||
|
return size-offset;
|
||||||
|
}
|
||||||
|
|
||||||
inline int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err)
|
inline int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err)
|
||||||
{
|
{
|
||||||
BX_ERROR_SCOPE(_err);
|
BX_ERROR_SCOPE(_err);
|
||||||
|
|||||||
@@ -11,9 +11,10 @@
|
|||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
///
|
||||||
struct EncodingType
|
struct EncodingType
|
||||||
{
|
{
|
||||||
enum Enum
|
enum Enum ///
|
||||||
{
|
{
|
||||||
Unorm,
|
Unorm,
|
||||||
Int,
|
Int,
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace bx
|
|||||||
uint32_t m_size;
|
uint32_t m_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
/// Sizer writer. Dummy writter that only counts number of bytes written into it.
|
||||||
class SizerWriter : public WriterSeekerI
|
class SizerWriter : public WriterSeekerI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -226,7 +226,7 @@ namespace bx
|
|||||||
int64_t m_size;
|
int64_t m_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
/// Static (fixed size) memory block writer.
|
||||||
class StaticMemoryBlockWriter : public MemoryWriter
|
class StaticMemoryBlockWriter : public MemoryWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -288,6 +288,9 @@ namespace bx
|
|||||||
/// Returns size of file.
|
/// Returns size of file.
|
||||||
int64_t getSize(SeekerI* _seeker);
|
int64_t getSize(SeekerI* _seeker);
|
||||||
|
|
||||||
|
/// Returns remaining size from current offset of file.
|
||||||
|
int64_t getRemain(SeekerI* _seeker);
|
||||||
|
|
||||||
/// Peek data.
|
/// Peek data.
|
||||||
int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err = NULL);
|
int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err = NULL);
|
||||||
|
|
||||||
@@ -301,16 +304,16 @@ namespace bx
|
|||||||
/// Align writer stream (pads stream with zeros).
|
/// Align writer stream (pads stream with zeros).
|
||||||
int32_t align(WriterSeekerI* _writer, uint32_t _alignment, Error* _err = NULL);
|
int32_t align(WriterSeekerI* _writer, uint32_t _alignment, Error* _err = NULL);
|
||||||
|
|
||||||
///
|
/// Open for read.
|
||||||
bool open(ReaderOpenI* _reader, const FilePath& _filePath, Error* _err = NULL);
|
bool open(ReaderOpenI* _reader, const FilePath& _filePath, Error* _err = NULL);
|
||||||
|
|
||||||
///
|
/// Open fro write.
|
||||||
bool open(WriterOpenI* _writer, const FilePath& _filePath, bool _append = false, Error* _err = NULL);
|
bool open(WriterOpenI* _writer, const FilePath& _filePath, bool _append = false, Error* _err = NULL);
|
||||||
|
|
||||||
///
|
/// Open process.
|
||||||
bool open(ProcessOpenI* _process, const FilePath& _filePath, const StringView& _args, Error* _err = NULL);
|
bool open(ProcessOpenI* _process, const FilePath& _filePath, const StringView& _args, Error* _err = NULL);
|
||||||
|
|
||||||
///
|
/// Close.
|
||||||
void close(CloserI* _reader);
|
void close(CloserI* _reader);
|
||||||
|
|
||||||
} // namespace bx
|
} // namespace bx
|
||||||
|
|||||||
61
include/bx/settings.h
Normal file
61
include/bx/settings.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2017 Branimir Karadzic. All rights reserved.
|
||||||
|
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BX_SETTINGS_H_HEADER_GUARD
|
||||||
|
#define BX_SETTINGS_H_HEADER_GUARD
|
||||||
|
|
||||||
|
#include "allocator.h"
|
||||||
|
#include "readerwriter.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
namespace bx
|
||||||
|
{
|
||||||
|
///
|
||||||
|
class Settings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
Settings(AllocatorI* _allocator, const void* _data = NULL, uint32_t _len = 0);
|
||||||
|
|
||||||
|
///
|
||||||
|
~Settings();
|
||||||
|
|
||||||
|
///
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
///
|
||||||
|
void load(const void* _data, uint32_t _len);
|
||||||
|
|
||||||
|
///
|
||||||
|
const char* get(const StringView& _name) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
void set(const StringView& _name, const StringView& _value = "");
|
||||||
|
|
||||||
|
///
|
||||||
|
void remove(const StringView& _name) const;
|
||||||
|
|
||||||
|
///
|
||||||
|
int32_t read(ReaderSeekerI* _reader, Error* _err);
|
||||||
|
|
||||||
|
///
|
||||||
|
int32_t write(WriterI* _writer, Error* _err) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Settings();
|
||||||
|
|
||||||
|
AllocatorI* m_allocator;
|
||||||
|
void* m_ini;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
int32_t read(ReaderSeekerI* _reader, Settings& _settings, Error* _err = NULL);
|
||||||
|
|
||||||
|
///
|
||||||
|
int32_t write(WriterI* _writer, const Settings& _settings, Error* _err = NULL);
|
||||||
|
|
||||||
|
} // namespace bx
|
||||||
|
|
||||||
|
#endif // BX_SETTINGS_H_HEADER_GUARD
|
||||||
@@ -200,6 +200,15 @@ namespace bx
|
|||||||
/// Find substring in string. Case insensitive. Limit search to _max characters.
|
/// Find substring in string. Case insensitive. Limit search to _max characters.
|
||||||
const char* strFindI(const StringView& _str, const StringView& _find, int32_t _num = INT32_MAX);
|
const char* strFindI(const StringView& _str, const StringView& _find, int32_t _num = INT32_MAX);
|
||||||
|
|
||||||
|
///
|
||||||
|
StringView strLTrim(const StringView& _str, const StringView& _chars);
|
||||||
|
|
||||||
|
///
|
||||||
|
StringView strRTrim(const StringView& _str, const StringView& _chars);
|
||||||
|
|
||||||
|
///
|
||||||
|
StringView strTrim(const StringView& _str, const StringView& _chars);
|
||||||
|
|
||||||
/// Find new line. Returns pointer after new line terminator.
|
/// Find new line. Returns pointer after new line terminator.
|
||||||
const char* strnl(const char* _str);
|
const char* strnl(const char* _str);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ project "bx"
|
|||||||
|
|
||||||
includedirs {
|
includedirs {
|
||||||
path.join(BX_DIR, "include"),
|
path.join(BX_DIR, "include"),
|
||||||
|
path.join(BX_DIR, "3rdparty"),
|
||||||
}
|
}
|
||||||
|
|
||||||
files {
|
files {
|
||||||
@@ -40,6 +41,7 @@ project "bx"
|
|||||||
path.join(BX_DIR, "src/os.cpp"),
|
path.join(BX_DIR, "src/os.cpp"),
|
||||||
path.join(BX_DIR, "src/process.cpp"),
|
path.join(BX_DIR, "src/process.cpp"),
|
||||||
path.join(BX_DIR, "src/semaphore.cpp"),
|
path.join(BX_DIR, "src/semaphore.cpp"),
|
||||||
|
path.join(BX_DIR, "src/settings.cpp"),
|
||||||
path.join(BX_DIR, "src/sort.cpp"),
|
path.join(BX_DIR, "src/sort.cpp"),
|
||||||
path.join(BX_DIR, "src/string.cpp"),
|
path.join(BX_DIR, "src/string.cpp"),
|
||||||
path.join(BX_DIR, "src/thread.cpp"),
|
path.join(BX_DIR, "src/thread.cpp"),
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ solution "bx"
|
|||||||
language "C++"
|
language "C++"
|
||||||
|
|
||||||
BX_DIR = path.getabsolute("..")
|
BX_DIR = path.getabsolute("..")
|
||||||
local BX_BUILD_DIR = path.join(BX_DIR, ".build")
|
BX_BUILD_DIR = path.join(BX_DIR, ".build")
|
||||||
local BX_THIRD_PARTY_DIR = path.join(BX_DIR, "3rdparty")
|
BX_THIRD_PARTY_DIR = path.join(BX_DIR, "3rdparty")
|
||||||
|
|
||||||
dofile "toolchain.lua"
|
dofile "toolchain.lua"
|
||||||
toolchain(BX_BUILD_DIR, BX_THIRD_PARTY_DIR)
|
toolchain(BX_BUILD_DIR, BX_THIRD_PARTY_DIR)
|
||||||
|
|||||||
213
src/settings.cpp
Normal file
213
src/settings.cpp
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2017 Branimir Karadzic. All rights reserved.
|
||||||
|
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bx/settings.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
#define INI_MALLOC(_ctx, _size) (BX_ALLOC(reinterpret_cast<bx::AllocatorI*>(_ctx), _size) )
|
||||||
|
#define INI_FREE(_ctx, _ptr) (BX_FREE(reinterpret_cast<bx::AllocatorI*>(_ctx), _ptr) )
|
||||||
|
#define INI_MEMCPY(_dst, _src, _count) (bx::memCopy(_dst, _src, _count) )
|
||||||
|
#define INI_STRLEN(_str) (bx::strLen(_str) )
|
||||||
|
#define INI_STRICMP(_s1, _s2, _len) (bx::strCmpI(_s1, _s2, _len) )
|
||||||
|
|
||||||
|
#define INI_IMPLEMENTATION
|
||||||
|
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_PUSH();
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wsign-compare");
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-function");
|
||||||
|
#include <ini/ini.h>
|
||||||
|
BX_PRAGMA_DIAGNOSTIC_POP();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace bx
|
||||||
|
{
|
||||||
|
|
||||||
|
Settings::Settings(AllocatorI* _allocator, const void* _data, uint32_t _len)
|
||||||
|
: m_allocator(_allocator)
|
||||||
|
, m_ini(NULL)
|
||||||
|
{
|
||||||
|
load(_data, _len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INI_T(_ptr) reinterpret_cast<ini_t*>(_ptr)
|
||||||
|
|
||||||
|
Settings::~Settings()
|
||||||
|
{
|
||||||
|
ini_destroy(INI_T(m_ini) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::clear()
|
||||||
|
{
|
||||||
|
load(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::load(const void* _data, uint32_t _len)
|
||||||
|
{
|
||||||
|
if (NULL != m_ini)
|
||||||
|
{
|
||||||
|
ini_destroy(INI_T(m_ini) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == _data)
|
||||||
|
{
|
||||||
|
m_ini = ini_create(m_allocator);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BX_UNUSED(_len);
|
||||||
|
m_ini = ini_load( (const char*)_data, m_allocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Settings::get(const StringView& _name) const
|
||||||
|
{
|
||||||
|
ini_t* ini = INI_T(m_ini);
|
||||||
|
|
||||||
|
FilePath uri(_name);
|
||||||
|
const StringView path = strTrim(uri.getPath(), "/");
|
||||||
|
const StringView& fileName = uri.getFileName();
|
||||||
|
|
||||||
|
int32_t section = INI_GLOBAL_SECTION;
|
||||||
|
|
||||||
|
if (!path.isEmpty() )
|
||||||
|
{
|
||||||
|
section = ini_find_section(ini, path.getPtr(), path.getLength()-1);
|
||||||
|
if (INI_NOT_FOUND == section)
|
||||||
|
{
|
||||||
|
section = INI_GLOBAL_SECTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t property = ini_find_property(ini, section, fileName.getPtr(), fileName.getLength() );
|
||||||
|
if (INI_NOT_FOUND == property)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ini_property_value(ini, section, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::set(const StringView& _name, const StringView& _value)
|
||||||
|
{
|
||||||
|
ini_t* ini = INI_T(m_ini);
|
||||||
|
|
||||||
|
FilePath uri(_name);
|
||||||
|
const StringView path = strTrim(uri.getPath(), "/");
|
||||||
|
const StringView& fileName = uri.getFileName();
|
||||||
|
|
||||||
|
int32_t section = INI_GLOBAL_SECTION;
|
||||||
|
|
||||||
|
if (!path.isEmpty() )
|
||||||
|
{
|
||||||
|
section = ini_find_section(ini, path.getPtr(), path.getLength()-1);
|
||||||
|
if (INI_NOT_FOUND == section)
|
||||||
|
{
|
||||||
|
section = ini_section_add(ini, path.getPtr(), path.getLength()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t property = ini_find_property(ini, section, fileName.getPtr(), fileName.getLength() );
|
||||||
|
if (INI_NOT_FOUND == property)
|
||||||
|
{
|
||||||
|
ini_property_add(
|
||||||
|
ini
|
||||||
|
, section
|
||||||
|
, fileName.getPtr()
|
||||||
|
, fileName.getLength()
|
||||||
|
, _value.getPtr()
|
||||||
|
, _value.getLength()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ini_property_value_set(
|
||||||
|
ini
|
||||||
|
, section
|
||||||
|
, property
|
||||||
|
, _value.getPtr()
|
||||||
|
, _value.getLength()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::remove(const StringView& _name) const
|
||||||
|
{
|
||||||
|
ini_t* ini = INI_T(m_ini);
|
||||||
|
|
||||||
|
FilePath uri(_name);
|
||||||
|
const StringView path = strTrim(uri.getPath(), "/");
|
||||||
|
const StringView& fileName = uri.getFileName();
|
||||||
|
|
||||||
|
int32_t section = INI_GLOBAL_SECTION;
|
||||||
|
|
||||||
|
if (!path.isEmpty() )
|
||||||
|
{
|
||||||
|
section = ini_find_section(ini, path.getPtr(), path.getLength()-1);
|
||||||
|
if (INI_NOT_FOUND == section)
|
||||||
|
{
|
||||||
|
section = INI_GLOBAL_SECTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t property = ini_find_property(ini, section, fileName.getPtr(), fileName.getLength() );
|
||||||
|
if (INI_NOT_FOUND == property)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_property_remove(ini, section, property);
|
||||||
|
|
||||||
|
if (INI_GLOBAL_SECTION != section
|
||||||
|
&& 0 == ini_property_count(ini, section) )
|
||||||
|
{
|
||||||
|
ini_section_remove(ini, section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Settings::read(ReaderSeekerI* _reader, Error* _err)
|
||||||
|
{
|
||||||
|
int32_t size = int32_t(getRemain(_reader) );
|
||||||
|
|
||||||
|
void* data = BX_ALLOC(m_allocator, size);
|
||||||
|
|
||||||
|
int32_t total = bx::read(_reader, data, size, _err);
|
||||||
|
load(data, size);
|
||||||
|
|
||||||
|
BX_FREE(m_allocator, data);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Settings::write(WriterI* _writer, Error* _err) const
|
||||||
|
{
|
||||||
|
ini_t* ini = INI_T(m_ini);
|
||||||
|
|
||||||
|
int32_t size = ini_save(ini, NULL, 0);
|
||||||
|
void* data = BX_ALLOC(m_allocator, size);
|
||||||
|
|
||||||
|
ini_save(ini, (char*)data, size);
|
||||||
|
int32_t total = bx::write(_writer, data, size-1, _err);
|
||||||
|
|
||||||
|
BX_FREE(m_allocator, data);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef INI_T
|
||||||
|
|
||||||
|
int32_t read(ReaderSeekerI* _reader, Settings& _settings, Error* _err)
|
||||||
|
{
|
||||||
|
BX_ERROR_SCOPE(_err);
|
||||||
|
return _settings.read(_reader, _err);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t write(WriterI* _writer, const Settings& _settings, Error* _err)
|
||||||
|
{
|
||||||
|
BX_ERROR_SCOPE(_err);
|
||||||
|
return _settings.write(_writer, _err);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace bx
|
||||||
@@ -333,9 +333,9 @@ namespace bx
|
|||||||
return strCat(_dst, _dstSize, _str.getPtr(), min(_str.getLength(), _num) );
|
return strCat(_dst, _dstSize, _str.getPtr(), min(_str.getLength(), _num) );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* strFind(const char* _str, int32_t _max, char _ch)
|
inline const char* strFindUnsafe(const char* _str, int32_t _len, char _ch)
|
||||||
{
|
{
|
||||||
for (int32_t ii = 0, len = strLen(_str, _max); ii < len; ++ii)
|
for (int32_t ii = 0; ii < _len; ++ii)
|
||||||
{
|
{
|
||||||
if (_str[ii] == _ch)
|
if (_str[ii] == _ch)
|
||||||
{
|
{
|
||||||
@@ -346,14 +346,19 @@ namespace bx
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const char* strFind(const char* _str, int32_t _max, char _ch)
|
||||||
|
{
|
||||||
|
return strFindUnsafe(_str, strLen(_str, _max), _ch);
|
||||||
|
}
|
||||||
|
|
||||||
const char* strFind(const StringView& _str, char _ch)
|
const char* strFind(const StringView& _str, char _ch)
|
||||||
{
|
{
|
||||||
return strFind(_str.getPtr(), _str.getLength(), _ch);
|
return strFind(_str.getPtr(), _str.getLength(), _ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char* strRFind(const char* _str, int32_t _max, char _ch)
|
inline const char* strRFindUnsafe(const char* _str, int32_t _len, char _ch)
|
||||||
{
|
{
|
||||||
for (int32_t ii = strLen(_str, _max); 0 <= ii; --ii)
|
for (int32_t ii = _len; 0 <= ii; --ii)
|
||||||
{
|
{
|
||||||
if (_str[ii] == _ch)
|
if (_str[ii] == _ch)
|
||||||
{
|
{
|
||||||
@@ -364,6 +369,11 @@ namespace bx
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const char* strRFind(const char* _str, int32_t _max, char _ch)
|
||||||
|
{
|
||||||
|
return strRFindUnsafe(_str, strLen(_str, _max), _ch);
|
||||||
|
}
|
||||||
|
|
||||||
const char* strRFind(const StringView& _str, char _ch)
|
const char* strRFind(const StringView& _str, char _ch)
|
||||||
{
|
{
|
||||||
return strRFind(_str.getPtr(), _str.getLength(), _ch);
|
return strRFind(_str.getPtr(), _str.getLength(), _ch);
|
||||||
@@ -430,6 +440,44 @@ namespace bx
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringView strLTrim(const StringView& _str, const StringView& _chars)
|
||||||
|
{
|
||||||
|
const char* ptr = _str.getPtr();
|
||||||
|
const char* chars = _chars.getPtr();
|
||||||
|
const uint32_t charsLen = _chars.getLength();
|
||||||
|
for (uint32_t ii = 0, len = _str.getLength(); ii < len; ++ii)
|
||||||
|
{
|
||||||
|
if (NULL == strFindUnsafe(chars, charsLen, ptr[ii]) )
|
||||||
|
{
|
||||||
|
return StringView(ptr + ii, len-ii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringView();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView strRTrim(const StringView& _str, const StringView& _chars)
|
||||||
|
{
|
||||||
|
const char* ptr = _str.getPtr();
|
||||||
|
const char* chars = _chars.getPtr();
|
||||||
|
const uint32_t charsLen = _chars.getLength();
|
||||||
|
|
||||||
|
for (int32_t len = _str.getLength(), ii = len-1; 0 <= ii; --ii)
|
||||||
|
{
|
||||||
|
if (NULL == strFindUnsafe(chars, charsLen, ptr[ii]) )
|
||||||
|
{
|
||||||
|
return StringView(ptr, ii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringView();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView strTrim(const StringView& _str, const StringView& _chars)
|
||||||
|
{
|
||||||
|
return strLTrim(strRTrim(_str, _chars), _chars);
|
||||||
|
}
|
||||||
|
|
||||||
const char* strnl(const char* _str)
|
const char* strnl(const char* _str)
|
||||||
{
|
{
|
||||||
for (; '\0' != *_str; _str += strLen(_str, 1024) )
|
for (; '\0' != *_str; _str += strLen(_str, 1024) )
|
||||||
|
|||||||
@@ -80,10 +80,10 @@ static const FilePathSplit s_filePathSplit[] =
|
|||||||
{
|
{
|
||||||
{ "\\abc/def\\../..\\../test.txt", true, "/", "test.txt", "test", ".txt" },
|
{ "\\abc/def\\../..\\../test.txt", true, "/", "test.txt", "test", ".txt" },
|
||||||
{ "/abv/gd/555/333/pod.mac", true, "/abv/gd/555/333/", "pod.mac", "pod", ".mac" },
|
{ "/abv/gd/555/333/pod.mac", true, "/abv/gd/555/333/", "pod.mac", "pod", ".mac" },
|
||||||
{ "archive.tar.gz", false, "", "archive.tar.gz", "archive", ".tar.gz" },
|
{ "archive.tar.gz", false, "", "archive.tar.gz", "archive", ".tar.gz" },
|
||||||
{ "tmp/archive.tar.gz", false, "tmp/", "archive.tar.gz", "archive", ".tar.gz" },
|
{ "tmp/archive.tar.gz", false, "tmp/", "archive.tar.gz", "archive", ".tar.gz" },
|
||||||
{ "/tmp/archive.tar.gz", true, "/tmp/", "archive.tar.gz", "archive", ".tar.gz" },
|
{ "/tmp/archive.tar.gz", true, "/tmp/", "archive.tar.gz", "archive", ".tar.gz" },
|
||||||
{ "d:/tmp/archive.tar.gz", true, "D:/tmp/", "archive.tar.gz", "archive", ".tar.gz" },
|
{ "d:/tmp/archive.tar.gz", true, "D:/tmp/", "archive.tar.gz", "archive", ".tar.gz" },
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE("FilePath", "")
|
TEST_CASE("FilePath", "")
|
||||||
|
|||||||
49
tests/settings_test.cpp
Normal file
49
tests/settings_test.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 Branimir Karadzic. All rights reserved.
|
||||||
|
* License: https://github.com/bkaradzic/bx#license-bsd-2-clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test.h"
|
||||||
|
#include <bx/settings.h>
|
||||||
|
#include <bx/file.h>
|
||||||
|
|
||||||
|
TEST_CASE("Settings", "")
|
||||||
|
{
|
||||||
|
bx::FilePath filePath;
|
||||||
|
filePath.set(bx::TempDir::Tag);
|
||||||
|
filePath.join("settings.ini");
|
||||||
|
|
||||||
|
bx::DefaultAllocator allocator;
|
||||||
|
|
||||||
|
bx::Settings settings(&allocator);
|
||||||
|
|
||||||
|
settings.set("meh/podmac", "true");
|
||||||
|
settings.set("test/foo/bar/abvgd", "1389");
|
||||||
|
|
||||||
|
bx::FileWriter writer;
|
||||||
|
if (bx::open(&writer, filePath) )
|
||||||
|
{
|
||||||
|
bx::write(&writer, settings);
|
||||||
|
bx::close(&writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(NULL == settings.get("meh") );
|
||||||
|
REQUIRE(0 == bx::strCmp(settings.get("meh/podmac"), "true") );
|
||||||
|
REQUIRE(0 == bx::strCmp(settings.get("test/foo/bar/abvgd"), "1389") );
|
||||||
|
|
||||||
|
settings.remove("meh/podmac");
|
||||||
|
REQUIRE(NULL == settings.get("meh/podmac") );
|
||||||
|
|
||||||
|
settings.clear();
|
||||||
|
|
||||||
|
bx::FileReader reader;
|
||||||
|
if (bx::open(&reader, filePath) )
|
||||||
|
{
|
||||||
|
bx::read(&reader, settings);
|
||||||
|
bx::close(&writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(NULL == settings.get("meh") );
|
||||||
|
REQUIRE(0 == bx::strCmp(settings.get("meh/podmac"), "true") );
|
||||||
|
REQUIRE(0 == bx::strCmp(settings.get("test/foo/bar/abvgd"), "1389") );
|
||||||
|
}
|
||||||
@@ -196,6 +196,8 @@ TEST_CASE("strFind", "")
|
|||||||
REQUIRE(NULL == bx::strFind(test, "Quick1") );
|
REQUIRE(NULL == bx::strFind(test, "Quick1") );
|
||||||
REQUIRE(&test[4] == bx::strFind(bx::StringView(test, 9), "Quick") );
|
REQUIRE(&test[4] == bx::strFind(bx::StringView(test, 9), "Quick") );
|
||||||
REQUIRE(&test[4] == bx::strFind(test, "Quick") );
|
REQUIRE(&test[4] == bx::strFind(test, "Quick") );
|
||||||
|
|
||||||
|
REQUIRE(NULL == bx::strFind("vgd", 'a') );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,3 +363,19 @@ TEST_CASE("StringView", "")
|
|||||||
sv.clear();
|
sv.clear();
|
||||||
REQUIRE(0 == sv.getLength() );
|
REQUIRE(0 == sv.getLength() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Trim", "")
|
||||||
|
{
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strLTrim("abvgd", "ab"), "vgd") );
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strLTrim("abvgd", "vagbd"), "") );
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strLTrim("abvgd", "vgd"), "abvgd") );
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strLTrim("/555333/podmac/", "/"), "555333/podmac/") );
|
||||||
|
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strRTrim("abvgd", "vagbd"), "") );
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strRTrim("abvgd", "abv"), "abvgd") );
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strRTrim("/555333/podmac/", "/"), "/555333/podmac") );
|
||||||
|
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strTrim("abvgd", "da"), "bvg") );
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strTrim("<1389>", "<>"), "1389") );
|
||||||
|
REQUIRE(0 == bx::strCmp(bx::strTrim("/555333/podmac/", "/"), "555333/podmac") );
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user