New upstream version 18.0.1+dfsg1
This commit is contained in:
parent
6efda2859e
commit
f2cf6cce50
1337 changed files with 41178 additions and 84670 deletions
|
|
@ -24,19 +24,15 @@
|
|||
#define UNUSED_PARAMETER(param) (void)param
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define DEPRECATED_START __declspec(deprecated)
|
||||
#define DEPRECATED_END
|
||||
#define DEPRECATED __declspec(deprecated)
|
||||
#define FORCE_INLINE __forceinline
|
||||
#else
|
||||
#define DEPRECATED_START
|
||||
#define DEPRECATED_END __attribute__ ((deprecated))
|
||||
#define DEPRECATED __attribute__ ((deprecated))
|
||||
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma warning (disable : 4996)
|
||||
|
||||
/* Microsoft is one of the most inept companies on the face of the planet.
|
||||
* The fact that even visual studio 2013 doesn't support the standard 'inline'
|
||||
* keyword is so incredibly stupid that I just can't imagine what sort of
|
||||
|
|
|
|||
|
|
@ -254,6 +254,20 @@ static inline void circlebuf_pop_back(struct circlebuf *cb, void *data,
|
|||
cb->end_pos -= size;
|
||||
}
|
||||
|
||||
static inline void *circlebuf_data(struct circlebuf *cb, size_t idx)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t*)cb->data;
|
||||
size_t offset = cb->start_pos + idx;
|
||||
|
||||
if (idx > cb->size)
|
||||
return NULL;
|
||||
|
||||
if (offset >= cb->capacity)
|
||||
offset -= cb->capacity;
|
||||
|
||||
return ptr + offset;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include "config-file.h"
|
||||
#include "threading.h"
|
||||
#include "platform.h"
|
||||
#include "base.h"
|
||||
#include "bmem.h"
|
||||
|
|
@ -57,8 +58,19 @@ struct config_data {
|
|||
char *file;
|
||||
struct darray sections; /* struct config_section */
|
||||
struct darray defaults; /* struct config_section */
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
static inline bool init_mutex(config_t *config)
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
if (pthread_mutexattr_init(&attr) != 0)
|
||||
return false;
|
||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
|
||||
return false;
|
||||
return pthread_mutex_init(&config->mutex, &attr) == 0;
|
||||
}
|
||||
|
||||
config_t *config_create(const char *file)
|
||||
{
|
||||
struct config_data *config;
|
||||
|
|
@ -70,6 +82,12 @@ config_t *config_create(const char *file)
|
|||
fclose(f);
|
||||
|
||||
config = bzalloc(sizeof(struct config_data));
|
||||
|
||||
if (!init_mutex(config)) {
|
||||
bfree(config);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
config->file = bstrdup(file);
|
||||
return config;
|
||||
}
|
||||
|
|
@ -278,6 +296,11 @@ int config_open(config_t **config, const char *file,
|
|||
if (!*config)
|
||||
return CONFIG_ERROR;
|
||||
|
||||
if (!init_mutex(*config)) {
|
||||
bfree(*config);
|
||||
return CONFIG_ERROR;
|
||||
}
|
||||
|
||||
(*config)->file = bstrdup(file);
|
||||
|
||||
errorcode = config_parse_file(&(*config)->sections, file, always_open);
|
||||
|
|
@ -301,6 +324,11 @@ int config_open_string(config_t **config, const char *str)
|
|||
if (!*config)
|
||||
return CONFIG_ERROR;
|
||||
|
||||
if (!init_mutex(*config)) {
|
||||
bfree(*config);
|
||||
return CONFIG_ERROR;
|
||||
}
|
||||
|
||||
(*config)->file = NULL;
|
||||
|
||||
lexer_init(&lex);
|
||||
|
|
@ -333,9 +361,13 @@ int config_save(config_t *config)
|
|||
dstr_init(&str);
|
||||
dstr_init(&tmp);
|
||||
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
|
||||
f = os_fopen(config->file, "wb");
|
||||
if (!f)
|
||||
if (!f) {
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
return CONFIG_FILENOTFOUND;
|
||||
}
|
||||
|
||||
for (i = 0; i < config->sections.num; i++) {
|
||||
struct config_section *section = darray_item(
|
||||
|
|
@ -371,6 +403,8 @@ int config_save(config_t *config)
|
|||
fwrite(str.array, 1, str.len, f);
|
||||
fclose(f);
|
||||
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
|
||||
dstr_free(&tmp);
|
||||
dstr_free(&str);
|
||||
|
||||
|
|
@ -391,6 +425,8 @@ int config_save_safe(config_t *config, const char *temp_ext,
|
|||
return CONFIG_ERROR;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
|
||||
dstr_copy(&temp_file, config->file);
|
||||
if (*temp_ext != '.')
|
||||
dstr_cat(&temp_file, ".");
|
||||
|
|
@ -419,6 +455,7 @@ int config_save_safe(config_t *config, const char *temp_ext,
|
|||
os_rename(temp_file.array, file);
|
||||
|
||||
cleanup:
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
dstr_free(&temp_file);
|
||||
dstr_free(&backup_file);
|
||||
return ret;
|
||||
|
|
@ -442,6 +479,7 @@ void config_close(config_t *config)
|
|||
darray_free(&config->defaults);
|
||||
darray_free(&config->sections);
|
||||
bfree(config->file);
|
||||
pthread_mutex_destroy(&config->mutex);
|
||||
bfree(config);
|
||||
}
|
||||
|
||||
|
|
@ -453,14 +491,20 @@ size_t config_num_sections(config_t *config)
|
|||
const char *config_get_section(config_t *config, size_t idx)
|
||||
{
|
||||
struct config_section *section;
|
||||
const char *name = NULL;
|
||||
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
|
||||
if (idx >= config->sections.num)
|
||||
return NULL;
|
||||
goto unlock;
|
||||
|
||||
section = darray_item(sizeof(struct config_section), &config->sections,
|
||||
idx);
|
||||
name = section->name;
|
||||
|
||||
return section->name;
|
||||
unlock:
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
return name;
|
||||
}
|
||||
|
||||
static const struct config_item *config_find_item(const struct darray *sections,
|
||||
|
|
@ -487,14 +531,16 @@ static const struct config_item *config_find_item(const struct darray *sections,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void config_set_item(struct darray *sections, const char *section,
|
||||
const char *name, char *value)
|
||||
static void config_set_item(config_t *config, struct darray *sections,
|
||||
const char *section, const char *name, char *value)
|
||||
{
|
||||
struct config_section *sec = NULL;
|
||||
struct config_section *array = sections->array;
|
||||
struct config_item *item;
|
||||
size_t i, j;
|
||||
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
|
||||
for (i = 0; i < sections->num; i++) {
|
||||
struct config_section *cur_sec = array+i;
|
||||
struct config_item *items = cur_sec->items.array;
|
||||
|
|
@ -506,7 +552,7 @@ static void config_set_item(struct darray *sections, const char *section,
|
|||
if (astrcmpi(item->name, name) == 0) {
|
||||
bfree(item->value);
|
||||
item->value = value;
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -524,6 +570,9 @@ static void config_set_item(struct darray *sections, const char *section,
|
|||
item = darray_push_back_new(sizeof(struct config_item), &sec->items);
|
||||
item->name = bstrdup(name);
|
||||
item->value = value;
|
||||
|
||||
unlock:
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
}
|
||||
|
||||
void config_set_string(config_t *config, const char *section,
|
||||
|
|
@ -531,7 +580,8 @@ void config_set_string(config_t *config, const char *section,
|
|||
{
|
||||
if (!value)
|
||||
value = "";
|
||||
config_set_item(&config->sections, section, name, bstrdup(value));
|
||||
config_set_item(config, &config->sections, section, name,
|
||||
bstrdup(value));
|
||||
}
|
||||
|
||||
void config_set_int(config_t *config, const char *section,
|
||||
|
|
@ -540,7 +590,7 @@ void config_set_int(config_t *config, const char *section,
|
|||
struct dstr str;
|
||||
dstr_init(&str);
|
||||
dstr_printf(&str, "%"PRId64, value);
|
||||
config_set_item(&config->sections, section, name, str.array);
|
||||
config_set_item(config, &config->sections, section, name, str.array);
|
||||
}
|
||||
|
||||
void config_set_uint(config_t *config, const char *section,
|
||||
|
|
@ -549,14 +599,14 @@ void config_set_uint(config_t *config, const char *section,
|
|||
struct dstr str;
|
||||
dstr_init(&str);
|
||||
dstr_printf(&str, "%"PRIu64, value);
|
||||
config_set_item(&config->sections, section, name, str.array);
|
||||
config_set_item(config, &config->sections, section, name, str.array);
|
||||
}
|
||||
|
||||
void config_set_bool(config_t *config, const char *section,
|
||||
const char *name, bool value)
|
||||
{
|
||||
char *str = bstrdup(value ? "true" : "false");
|
||||
config_set_item(&config->sections, section, name, str);
|
||||
config_set_item(config, &config->sections, section, name, str);
|
||||
}
|
||||
|
||||
void config_set_double(config_t *config, const char *section,
|
||||
|
|
@ -564,7 +614,7 @@ void config_set_double(config_t *config, const char *section,
|
|||
{
|
||||
char *str = bzalloc(64);
|
||||
os_dtostr(value, str, 64);
|
||||
config_set_item(&config->sections, section, name, str);
|
||||
config_set_item(config, &config->sections, section, name, str);
|
||||
}
|
||||
|
||||
void config_set_default_string(config_t *config, const char *section,
|
||||
|
|
@ -572,7 +622,8 @@ void config_set_default_string(config_t *config, const char *section,
|
|||
{
|
||||
if (!value)
|
||||
value = "";
|
||||
config_set_item(&config->defaults, section, name, bstrdup(value));
|
||||
config_set_item(config, &config->defaults, section, name,
|
||||
bstrdup(value));
|
||||
}
|
||||
|
||||
void config_set_default_int(config_t *config, const char *section,
|
||||
|
|
@ -581,7 +632,7 @@ void config_set_default_int(config_t *config, const char *section,
|
|||
struct dstr str;
|
||||
dstr_init(&str);
|
||||
dstr_printf(&str, "%"PRId64, value);
|
||||
config_set_item(&config->defaults, section, name, str.array);
|
||||
config_set_item(config, &config->defaults, section, name, str.array);
|
||||
}
|
||||
|
||||
void config_set_default_uint(config_t *config, const char *section,
|
||||
|
|
@ -590,14 +641,14 @@ void config_set_default_uint(config_t *config, const char *section,
|
|||
struct dstr str;
|
||||
dstr_init(&str);
|
||||
dstr_printf(&str, "%"PRIu64, value);
|
||||
config_set_item(&config->defaults, section, name, str.array);
|
||||
config_set_item(config, &config->defaults, section, name, str.array);
|
||||
}
|
||||
|
||||
void config_set_default_bool(config_t *config, const char *section,
|
||||
const char *name, bool value)
|
||||
{
|
||||
char *str = bstrdup(value ? "true" : "false");
|
||||
config_set_item(&config->defaults, section, name, str);
|
||||
config_set_item(config, &config->defaults, section, name, str);
|
||||
}
|
||||
|
||||
void config_set_default_double(config_t *config, const char *section,
|
||||
|
|
@ -606,20 +657,25 @@ void config_set_default_double(config_t *config, const char *section,
|
|||
struct dstr str;
|
||||
dstr_init(&str);
|
||||
dstr_printf(&str, "%g", value);
|
||||
config_set_item(&config->defaults, section, name, str.array);
|
||||
config_set_item(config, &config->defaults, section, name, str.array);
|
||||
}
|
||||
|
||||
const char *config_get_string(const config_t *config, const char *section,
|
||||
const char *config_get_string(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const struct config_item *item = config_find_item(&config->sections,
|
||||
section, name);
|
||||
const struct config_item *item;
|
||||
const char *value = NULL;
|
||||
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
|
||||
item = config_find_item(&config->sections, section, name);
|
||||
if (!item)
|
||||
item = config_find_item(&config->defaults, section, name);
|
||||
if (!item)
|
||||
return NULL;
|
||||
if (item)
|
||||
value = item->value;
|
||||
|
||||
return item->value;
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline int64_t str_to_int64(const char *str)
|
||||
|
|
@ -644,7 +700,7 @@ static inline uint64_t str_to_uint64(const char *str)
|
|||
return strtoull(str, NULL, 10);
|
||||
}
|
||||
|
||||
int64_t config_get_int(const config_t *config, const char *section,
|
||||
int64_t config_get_int(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_string(config, section, name);
|
||||
|
|
@ -654,7 +710,7 @@ int64_t config_get_int(const config_t *config, const char *section,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint64_t config_get_uint(const config_t *config, const char *section,
|
||||
uint64_t config_get_uint(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_string(config, section, name);
|
||||
|
|
@ -664,7 +720,7 @@ uint64_t config_get_uint(const config_t *config, const char *section,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool config_get_bool(const config_t *config, const char *section,
|
||||
bool config_get_bool(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_string(config, section, name);
|
||||
|
|
@ -675,7 +731,7 @@ bool config_get_bool(const config_t *config, const char *section,
|
|||
return false;
|
||||
}
|
||||
|
||||
double config_get_double(const config_t *config, const char *section,
|
||||
double config_get_double(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_string(config, section, name);
|
||||
|
|
@ -689,6 +745,9 @@ bool config_remove_value(config_t *config, const char *section,
|
|||
const char *name)
|
||||
{
|
||||
struct darray *sections = &config->sections;
|
||||
bool success = false;
|
||||
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
|
||||
for (size_t i = 0; i < sections->num; i++) {
|
||||
struct config_section *sec = darray_item(
|
||||
|
|
@ -706,27 +765,34 @@ bool config_remove_value(config_t *config, const char *section,
|
|||
config_item_free(item);
|
||||
darray_erase(sizeof(struct config_item),
|
||||
&sec->items, j);
|
||||
return true;
|
||||
success = true;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
unlock:
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
const char *config_get_default_string(const config_t *config,
|
||||
const char *config_get_default_string(config_t *config,
|
||||
const char *section, const char *name)
|
||||
{
|
||||
const struct config_item *item;
|
||||
const char *value = NULL;
|
||||
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
|
||||
item = config_find_item(&config->defaults, section, name);
|
||||
if (!item)
|
||||
return NULL;
|
||||
if (item)
|
||||
value = item->value;
|
||||
|
||||
return item->value;
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
return value;
|
||||
}
|
||||
|
||||
int64_t config_get_default_int(const config_t *config, const char *section,
|
||||
int64_t config_get_default_int(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_default_string(config, section, name);
|
||||
|
|
@ -736,7 +802,7 @@ int64_t config_get_default_int(const config_t *config, const char *section,
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint64_t config_get_default_uint(const config_t *config, const char *section,
|
||||
uint64_t config_get_default_uint(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_default_string(config, section, name);
|
||||
|
|
@ -746,7 +812,7 @@ uint64_t config_get_default_uint(const config_t *config, const char *section,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool config_get_default_bool(const config_t *config, const char *section,
|
||||
bool config_get_default_bool(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_default_string(config, section, name);
|
||||
|
|
@ -757,7 +823,7 @@ bool config_get_default_bool(const config_t *config, const char *section,
|
|||
return false;
|
||||
}
|
||||
|
||||
double config_get_default_double(const config_t *config, const char *section,
|
||||
double config_get_default_double(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
const char *value = config_get_default_string(config, section, name);
|
||||
|
|
@ -767,15 +833,23 @@ double config_get_default_double(const config_t *config, const char *section,
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
bool config_has_user_value(const config_t *config, const char *section,
|
||||
bool config_has_user_value(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
return config_find_item(&config->sections, section, name) != NULL;
|
||||
bool success;
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
success = config_find_item(&config->sections, section, name) != NULL;
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool config_has_default_value(const config_t *config, const char *section,
|
||||
bool config_has_default_value(config_t *config, const char *section,
|
||||
const char *name)
|
||||
{
|
||||
return config_find_item(&config->defaults, section, name) != NULL;
|
||||
bool success;
|
||||
pthread_mutex_lock(&config->mutex);
|
||||
success = config_find_item(&config->defaults, section, name) != NULL;
|
||||
pthread_mutex_unlock(&config->mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,15 +64,15 @@ EXPORT void config_set_bool(config_t *config, const char *section,
|
|||
EXPORT void config_set_double(config_t *config, const char *section,
|
||||
const char *name, double value);
|
||||
|
||||
EXPORT const char *config_get_string(const config_t *config,
|
||||
EXPORT const char *config_get_string(config_t *config,
|
||||
const char *section, const char *name);
|
||||
EXPORT int64_t config_get_int(const config_t *config, const char *section,
|
||||
EXPORT int64_t config_get_int(config_t *config, const char *section,
|
||||
const char *name);
|
||||
EXPORT uint64_t config_get_uint(const config_t *config, const char *section,
|
||||
EXPORT uint64_t config_get_uint(config_t *config, const char *section,
|
||||
const char *name);
|
||||
EXPORT bool config_get_bool(const config_t *config, const char *section,
|
||||
EXPORT bool config_get_bool(config_t *config, const char *section,
|
||||
const char *name);
|
||||
EXPORT double config_get_double(const config_t *config, const char *section,
|
||||
EXPORT double config_get_double(config_t *config, const char *section,
|
||||
const char *name);
|
||||
|
||||
EXPORT bool config_remove_value(config_t *config, const char *section,
|
||||
|
|
@ -107,20 +107,20 @@ EXPORT void config_set_default_double(config_t *config, const char *section,
|
|||
|
||||
/* These functions allow you to get the current default values rather than get
|
||||
* the actual values. Probably almost never really needed */
|
||||
EXPORT const char *config_get_default_string(const config_t *config,
|
||||
EXPORT const char *config_get_default_string(config_t *config,
|
||||
const char *section, const char *name);
|
||||
EXPORT int64_t config_get_default_int(const config_t *config,
|
||||
EXPORT int64_t config_get_default_int(config_t *config,
|
||||
const char *section, const char *name);
|
||||
EXPORT uint64_t config_get_default_uint(const config_t *config,
|
||||
EXPORT uint64_t config_get_default_uint(config_t *config,
|
||||
const char *section, const char *name);
|
||||
EXPORT bool config_get_default_bool(const config_t *config,
|
||||
EXPORT bool config_get_default_bool(config_t *config,
|
||||
const char *section, const char *name);
|
||||
EXPORT double config_get_default_double(const config_t *config,
|
||||
EXPORT double config_get_default_double(config_t *config,
|
||||
const char *section, const char *name);
|
||||
|
||||
EXPORT bool config_has_user_value(const config_t *config,
|
||||
EXPORT bool config_has_user_value(config_t *config,
|
||||
const char *section, const char *name);
|
||||
EXPORT bool config_has_default_value(const config_t *config,
|
||||
EXPORT bool config_has_default_value(config_t *config,
|
||||
const char *section, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -719,28 +719,31 @@ bool get_dll_ver(const wchar_t *lib, struct win_version_info *ver_info)
|
|||
BOOL success;
|
||||
LPVOID data;
|
||||
DWORD size;
|
||||
char utf8_lib[512];
|
||||
|
||||
if (!ver_initialized && !initialize_version_functions())
|
||||
return false;
|
||||
if (!ver_initialize_success)
|
||||
return false;
|
||||
|
||||
os_wcs_to_utf8(lib, 0, utf8_lib, sizeof(utf8_lib));
|
||||
|
||||
size = get_file_version_info_size(lib, NULL);
|
||||
if (!size) {
|
||||
blog(LOG_ERROR, "Failed to get windows version info size");
|
||||
blog(LOG_ERROR, "Failed to get %s version info size", utf8_lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
data = bmalloc(size);
|
||||
if (!get_file_version_info(lib, 0, size, data)) {
|
||||
blog(LOG_ERROR, "Failed to get windows version info");
|
||||
blog(LOG_ERROR, "Failed to get %s version info", utf8_lib);
|
||||
bfree(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
success = ver_query_value(data, L"\\", (LPVOID*)&info, &len);
|
||||
if (!success || !info || !len) {
|
||||
blog(LOG_ERROR, "Failed to get windows version info value");
|
||||
blog(LOG_ERROR, "Failed to get %s version info value", utf8_lib);
|
||||
bfree(data);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -754,6 +757,16 @@ bool get_dll_ver(const wchar_t *lib, struct win_version_info *ver_info)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool is_64_bit_windows(void)
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
return true;
|
||||
#elif defined(_WIN32)
|
||||
BOOL b64 = false;
|
||||
return IsWow64Process(GetCurrentProcess(), &b64) && b64;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define WINVER_REG_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
|
||||
|
||||
void get_win_ver(struct win_version_info *info)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
|
|
@ -657,3 +658,123 @@ const char *os_get_path_extension(const char *path)
|
|||
|
||||
return path + pos;
|
||||
}
|
||||
|
||||
static inline bool valid_string(const char *str)
|
||||
{
|
||||
while (str && *str) {
|
||||
if (*(str++) != ' ')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void replace_text(struct dstr *str, size_t pos, size_t len,
|
||||
const char *new_text)
|
||||
{
|
||||
struct dstr front = {0};
|
||||
struct dstr back = {0};
|
||||
|
||||
dstr_left(&front, str, pos);
|
||||
dstr_right(&back, str, pos + len);
|
||||
dstr_copy_dstr(str, &front);
|
||||
dstr_cat(str, new_text);
|
||||
dstr_cat_dstr(str, &back);
|
||||
dstr_free(&front);
|
||||
dstr_free(&back);
|
||||
}
|
||||
|
||||
static void erase_ch(struct dstr *str, size_t pos)
|
||||
{
|
||||
struct dstr new_str = {0};
|
||||
dstr_left(&new_str, str, pos);
|
||||
dstr_cat(&new_str, str->array + pos + 1);
|
||||
dstr_free(str);
|
||||
*str = new_str;
|
||||
}
|
||||
|
||||
char *os_generate_formatted_filename(const char *extension, bool space,
|
||||
const char *format)
|
||||
{
|
||||
time_t now = time(0);
|
||||
struct tm *cur_time;
|
||||
cur_time = localtime(&now);
|
||||
|
||||
const size_t spec_count = 23;
|
||||
static const char *spec[][2] = {
|
||||
{"%CCYY", "%Y"},
|
||||
{"%YY", "%y"},
|
||||
{"%MM", "%m"},
|
||||
{"%DD", "%d"},
|
||||
{"%hh", "%H"},
|
||||
{"%mm", "%M"},
|
||||
{"%ss", "%S"},
|
||||
{"%%", "%%"},
|
||||
|
||||
{"%a", ""},
|
||||
{"%A", ""},
|
||||
{"%b", ""},
|
||||
{"%B", ""},
|
||||
{"%d", ""},
|
||||
{"%H", ""},
|
||||
{"%I", ""},
|
||||
{"%m", ""},
|
||||
{"%M", ""},
|
||||
{"%p", ""},
|
||||
{"%S", ""},
|
||||
{"%y", ""},
|
||||
{"%Y", ""},
|
||||
{"%z", ""},
|
||||
{"%Z", ""},
|
||||
};
|
||||
|
||||
char convert[128] = {0};
|
||||
struct dstr sf;
|
||||
struct dstr c = {0};
|
||||
size_t pos = 0;
|
||||
|
||||
dstr_init_copy(&sf, format);
|
||||
|
||||
while (pos < sf.len) {
|
||||
for (size_t i = 0; i < spec_count && !convert[0]; i++) {
|
||||
size_t len = strlen(spec[i][0]);
|
||||
|
||||
const char *cmp = sf.array + pos;
|
||||
|
||||
if (astrcmp_n(cmp, spec[i][0], len) == 0) {
|
||||
if (strlen(spec[i][1]))
|
||||
strftime(convert, sizeof(convert),
|
||||
spec[i][1], cur_time);
|
||||
else
|
||||
strftime(convert, sizeof(convert),
|
||||
spec[i][0], cur_time);
|
||||
|
||||
|
||||
dstr_copy(&c, convert);
|
||||
if (c.len && valid_string(c.array))
|
||||
replace_text(&sf, pos, len, convert);
|
||||
}
|
||||
}
|
||||
|
||||
if (convert[0]) {
|
||||
pos += strlen(convert);
|
||||
convert[0] = 0;
|
||||
} else if (!convert[0] && sf.array[pos] == '%') {
|
||||
erase_ch(&sf, pos);
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!space)
|
||||
dstr_replace(&sf, " ", "_");
|
||||
|
||||
dstr_cat_ch(&sf, '.');
|
||||
dstr_cat(&sf, extension);
|
||||
dstr_free(&c);
|
||||
|
||||
if (sf.len > 255)
|
||||
dstr_mid(&sf, &sf, 0, 255);
|
||||
|
||||
return sf.array;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ EXPORT int os_mkdirs(const char *path);
|
|||
EXPORT int os_rename(const char *old_path, const char *new_path);
|
||||
EXPORT int os_copyfile(const char *file_in, const char *file_out);
|
||||
|
||||
EXPORT char *os_generate_formatted_filename(const char *extension, bool space,
|
||||
const char *format);
|
||||
|
||||
struct os_inhibit_info;
|
||||
typedef struct os_inhibit_info os_inhibit_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ public:
|
|||
inline operator T*() const {return ptr;}
|
||||
inline T *operator->() const {return ptr;}
|
||||
|
||||
inline const T *Get() const {return ptr;}
|
||||
|
||||
inline CoTaskMemPtr& operator=(T* val)
|
||||
{
|
||||
Clear();
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ struct win_version_info {
|
|||
int revis;
|
||||
};
|
||||
|
||||
EXPORT bool is_64_bit_windows(void);
|
||||
EXPORT bool get_dll_ver(const wchar_t *lib, struct win_version_info *info);
|
||||
EXPORT void get_win_ver(struct win_version_info *info);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue