547 lines
25 KiB
C
547 lines
25 KiB
C
/*
|
|
Copyright (c) 2013-2014 Anton Titov.
|
|
|
|
Copyright (c) 2013-2014 pCloud Ltd. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met: Redistributions of source code must retain the above
|
|
copyright notice, this list of conditions and the following
|
|
disclaimer. Redistributions in binary form must reproduce the
|
|
above copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided
|
|
with the distribution. Neither the name of pCloud Ltd nor the
|
|
names of its contributors may be used to endorse or promote
|
|
products derived from this software without specific prior written
|
|
permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL pCloud
|
|
Ltd BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE.
|
|
*/
|
|
|
|
#ifndef _PSYNC_LIBS_H
|
|
#define _PSYNC_LIBS_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <pthread.h>
|
|
|
|
#include "pcompiler.h"
|
|
#include "pstatus.h"
|
|
#include "putil.h"
|
|
#include "psynclib.h" // need for macros...
|
|
|
|
#include <sqlite3.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#define D_NONE 0
|
|
#define D_BUG 10
|
|
#define D_CRITICAL 20
|
|
#define D_ERROR 30
|
|
#define D_WARNING 40
|
|
#define D_NOTICE 50
|
|
|
|
// required for pcloud api; 7=>linux
|
|
#define P_OS_ID 7
|
|
|
|
#define DEBUG_LEVELS \
|
|
{ \
|
|
{D_BUG, "BUG"}, {D_CRITICAL, "CRITICAL ERROR"}, {D_ERROR, "ERROR"}, \
|
|
{D_WARNING, "WARNING"}, { \
|
|
D_NOTICE, "NOTICE" \
|
|
} \
|
|
}
|
|
|
|
#ifndef DEBUG_LEVEL
|
|
#define DEBUG_LEVEL D_NOTICE
|
|
#endif
|
|
|
|
#define IS_DEBUG (DEBUG_LEVEL >= D_WARNING)
|
|
|
|
#if defined(assert)
|
|
#undef assert
|
|
#endif
|
|
|
|
#define PSYNC_SSL_DEBUG_LEVEL \
|
|
0 /* Please make sure this setting is always set to 0 for release builds !!! \
|
|
Possible values are in the range [0, 5] */
|
|
|
|
#define debug(level, ...) \
|
|
do { \
|
|
if (level <= DEBUG_LEVEL) \
|
|
psync_debug(__FILE__, __FUNCTION__, __LINE__, level, __VA_ARGS__); \
|
|
} while (0)
|
|
#define assert(cond) \
|
|
do { \
|
|
if (D_WARNING <= DEBUG_LEVEL && unlikely(!(cond))) { \
|
|
debug(D_WARNING, "assertion %s failed, aborting", TO_STR(cond)); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
#define assertw(cond) \
|
|
do { \
|
|
if (D_WARNING <= DEBUG_LEVEL && unlikely(!(cond))) { \
|
|
debug(D_WARNING, "assertion %s failed", TO_STR(cond)); \
|
|
} \
|
|
} while (0)
|
|
#define debug_execute(level, expr) \
|
|
do { \
|
|
if (level <= DEBUG_LEVEL) \
|
|
(expr); \
|
|
} while (0)
|
|
|
|
#define PSYNC_TNUMBER 1
|
|
#define PSYNC_TSTRING 2
|
|
#define PSYNC_TREAL 3
|
|
#define PSYNC_TNULL 4
|
|
#define PSYNC_TBOOL 5
|
|
|
|
#define psync_is_null(v) ((v).type == PSYNC_TNULL)
|
|
#define psync_get_number(v) \
|
|
(likely((v).type == PSYNC_TNUMBER) \
|
|
? (v).num \
|
|
: psync_err_number_expected(__FILE__, __FUNCTION__, __LINE__, &(v)))
|
|
#define psync_get_snumber(v) \
|
|
(likely((v).type == PSYNC_TNUMBER) \
|
|
? (int64_t)((v).num) \
|
|
: (int64_t)psync_err_number_expected(__FILE__, __FUNCTION__, __LINE__, \
|
|
&(v)))
|
|
#define psync_get_number_or_null(v) \
|
|
(((v).type == PSYNC_TNUMBER) \
|
|
? (v).num \
|
|
: (likely((v).type == PSYNC_TNULL) \
|
|
? 0 \
|
|
: psync_err_number_expected(__FILE__, __FUNCTION__, __LINE__, \
|
|
&(v))))
|
|
#define psync_get_snumber_or_null(v) \
|
|
(((v).type == PSYNC_TNUMBER) \
|
|
? (int64_t)(v).num \
|
|
: (likely((v).type == PSYNC_TNULL) \
|
|
? 0 \
|
|
: (int64_t)psync_err_number_expected(__FILE__, __FUNCTION__, \
|
|
__LINE__, &(v))))
|
|
#define psync_get_string(v) \
|
|
(likely((v).type == PSYNC_TSTRING) \
|
|
? (v).str \
|
|
: psync_err_string_expected(__FILE__, __FUNCTION__, __LINE__, &(v)))
|
|
#define psync_get_string_or_null(v) \
|
|
(((v).type == PSYNC_TSTRING) \
|
|
? (v).str \
|
|
: (likely((v).type == PSYNC_TNULL) \
|
|
? NULL \
|
|
: psync_err_string_expected(__FILE__, __FUNCTION__, __LINE__, \
|
|
&(v))))
|
|
#define psync_dup_string(v) \
|
|
(likely((v).type == PSYNC_TSTRING) \
|
|
? psync_strndup((v).str, (v).length) \
|
|
: psync_strdup(psync_err_string_expected(__FILE__, __FUNCTION__, \
|
|
__LINE__, &(v))))
|
|
#define psync_get_lstring(v, l) \
|
|
psync_lstring_expected(__FILE__, __FUNCTION__, __LINE__, &(v), l)
|
|
#define psync_get_lstring_or_null(v, l) \
|
|
((v).type == PSYNC_TNULL \
|
|
? NULL \
|
|
: psync_lstring_expected(__FILE__, __FUNCTION__, __LINE__, &(v), l))
|
|
#define psync_get_real(v) \
|
|
(likely((v).type == PSYNC_TREAL) \
|
|
? (v).real \
|
|
: psync_err_real_expected(__FILE__, __FUNCTION__, __LINE__, &(v)))
|
|
|
|
#if D_WARNING <= DEBUG_LEVEL
|
|
#define likely_log(x) \
|
|
(likely(x) ? 1 \
|
|
: psync_debug(__FILE__, __FUNCTION__, __LINE__, D_WARNING, \
|
|
"assertion likely_log(%s) failed", TO_STR(x)) * \
|
|
0)
|
|
#define unlikely_log(x) \
|
|
(unlikely(x) ? psync_debug(__FILE__, __FUNCTION__, __LINE__, D_WARNING, \
|
|
"assertion unlikely_log(%s) failed", TO_STR(x)) \
|
|
: 0)
|
|
#if defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
|
|
#undef PTHREAD_MUTEX_INITIALIZER
|
|
#define PTHREAD_MUTEX_INITIALIZER PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
|
|
#endif
|
|
#define pthread_mutex_lock(mutex) \
|
|
do { \
|
|
int __mutex_result = pthread_mutex_lock(mutex); \
|
|
if (unlikely(__mutex_result)) { \
|
|
debug(D_CRITICAL, "pthread_mutex_lock returned %d", __mutex_result); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
#define pthread_mutex_unlock(mutex) \
|
|
do { \
|
|
int __mutex_result = pthread_mutex_unlock(mutex); \
|
|
if (unlikely(__mutex_result)) { \
|
|
debug(D_CRITICAL, "pthread_mutex_unlock returned %d", __mutex_result); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
#define PRINT_RETURN(x) \
|
|
((x) * psync_debug(__FILE__, __FUNCTION__, __LINE__, D_NOTICE, \
|
|
"returning %d", (int)(x)))
|
|
#define PRINT_RETURN_CONST(x) \
|
|
((x) * \
|
|
psync_debug(__FILE__, __FUNCTION__, __LINE__, D_NOTICE, "returning " #x))
|
|
#define PRINT_RETURN_FORMAT(x, format, ...) \
|
|
((x) * psync_debug(__FILE__, __FUNCTION__, __LINE__, D_NOTICE, \
|
|
"returning %d" format, (int)(x), __VA_ARGS__))
|
|
#define PRINT_NEG_RETURN(x) \
|
|
((x < 0) ? (x) * psync_debug(__FILE__, __FUNCTION__, __LINE__, D_WARNING, \
|
|
"returning %d", (int)(x)) \
|
|
: (x))
|
|
#define PRINT_NEG_RETURN_FORMAT(x, format, ...) \
|
|
((x < 0) ? (x) * psync_debug(__FILE__, __FUNCTION__, __LINE__, D_WARNING, \
|
|
"returning %d " format, (int)(x), __VA_ARGS__) \
|
|
: (x))
|
|
#else
|
|
#define likely_log likely
|
|
#define unlikely_log unlikely
|
|
#define PRINT_RETURN(x) (x)
|
|
#define PRINT_RETURN_CONST(x) (x)
|
|
#define PRINT_RETURN_FORMAT(x, format, ...) (x)
|
|
#define PRINT_NEG_RETURN(x) (x)
|
|
#define PRINT_NEG_RETURN_FORMAT(x, format, ...) (x)
|
|
#endif
|
|
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
|
|
#define psync_new(type) (type *)psync_malloc(sizeof(type))
|
|
#define psync_new_cnt(type, cnt) (type *)psync_malloc(sizeof(type) * (cnt))
|
|
|
|
#define psync_binhex(dst, src, cnt) \
|
|
do { \
|
|
size_t it__; \
|
|
size_t cnt__ = (cnt); \
|
|
const uint8_t *src__ = (const uint8_t *)(src); \
|
|
uint16_t *dst__ = (uint16_t *)(dst); \
|
|
for (it__ = 0; it__ < cnt__; it__++) \
|
|
dst__[it__] = __hex_lookup[src__[it__]]; \
|
|
} while (0)
|
|
|
|
#define psync_get_result_cell(res, row, col) \
|
|
(res)->data[(row) * (res)->cols + (col)]
|
|
|
|
typedef struct {
|
|
uint32_t type;
|
|
uint32_t length;
|
|
union {
|
|
uint64_t num;
|
|
int64_t snum;
|
|
const char *str;
|
|
double real;
|
|
};
|
|
} psync_variant;
|
|
|
|
typedef struct {
|
|
sqlite3_stmt *stmt;
|
|
const char *sql;
|
|
int column_count;
|
|
int locked;
|
|
psync_variant row[];
|
|
} psync_sql_res;
|
|
|
|
typedef struct {
|
|
uint32_t rows;
|
|
uint32_t cols;
|
|
uint64_t data[];
|
|
} psync_full_result_int;
|
|
|
|
struct psync_list_builder_t_;
|
|
|
|
typedef struct psync_list_builder_t_ psync_list_builder_t;
|
|
|
|
struct psync_task_manager_t_;
|
|
|
|
typedef struct psync_task_manager_t_ *psync_task_manager_t;
|
|
|
|
typedef const uint64_t *psync_uint_row;
|
|
typedef const char *const *psync_str_row;
|
|
typedef const psync_variant *psync_variant_row;
|
|
|
|
typedef void (*psync_run_after_t)(void *);
|
|
typedef int (*psync_list_builder_sql_callback)(psync_list_builder_t *, void *,
|
|
psync_variant_row);
|
|
|
|
typedef void (*psync_task_callback_t)(void *, void *);
|
|
|
|
typedef void (*psync_transaction_callback_t)(void *);
|
|
|
|
extern int psync_do_run;
|
|
extern int psync_recache_contacts;
|
|
extern pstatus_t psync_status;
|
|
extern char psync_my_auth[64], psync_my_2fa_code[32], *psync_my_user,
|
|
*psync_my_pass, *psync_my_2fa_token, *psync_my_verify_token;
|
|
extern int psync_my_2fa_code_type, psync_my_2fa_trust, psync_my_2fa_has_devices,
|
|
psync_my_2fa_type;
|
|
extern uint64_t psync_my_userid;
|
|
extern pthread_mutex_t psync_my_auth_mutex;
|
|
extern PSYNC_THREAD uint32_t psync_error;
|
|
extern uint16_t const *__hex_lookup;
|
|
extern const char base64_table[];
|
|
|
|
char *psync_strdup(const char *str) PSYNC_MALLOC PSYNC_NONNULL(1);
|
|
char *psync_strnormalize_filename(const char *str) PSYNC_MALLOC
|
|
PSYNC_NONNULL(1);
|
|
char *psync_strndup(const char *str, size_t len) PSYNC_MALLOC PSYNC_NONNULL(1);
|
|
char *psync_strcat(const char *str, ...) PSYNC_MALLOC PSYNC_SENTINEL;
|
|
int psync_slprintf(char *str, size_t size, const char *format, ...)
|
|
PSYNC_NONNULL(1, 3);
|
|
|
|
unsigned char *psync_base32_encode(const unsigned char *str, size_t length,
|
|
size_t *ret_length);
|
|
unsigned char *psync_base32_decode(const unsigned char *str, size_t length,
|
|
size_t *ret_length);
|
|
|
|
unsigned char *psync_base64_encode(const unsigned char *str, size_t length,
|
|
size_t *ret_length);
|
|
unsigned char *psync_base64_decode(const unsigned char *str, size_t length,
|
|
size_t *ret_length);
|
|
|
|
int psync_is_valid_utf8(const char *str);
|
|
|
|
int psync_sql_connect(const char *db) PSYNC_NONNULL(1);
|
|
int psync_sql_close();
|
|
int psync_sql_reopen(const char *path);
|
|
void psync_sql_checkpoint_lock();
|
|
void psync_sql_checkpoint_unlock();
|
|
|
|
#if IS_DEBUG
|
|
|
|
#define psync_sql_trylock() psync_sql_do_trylock(__FILE__, __LINE__)
|
|
#define psync_sql_lock() psync_sql_do_lock(__FILE__, __LINE__)
|
|
#define psync_sql_rdlock() psync_sql_do_rdlock(__FILE__, __LINE__)
|
|
#define psync_sql_statement(sql) psync_sql_do_statement(sql, __FILE__, __LINE__)
|
|
#define psync_sql_start_transaction() \
|
|
psync_sql_do_start_transaction(__FILE__, __LINE__)
|
|
|
|
#define psync_sql_query_nocache(sql) \
|
|
psync_sql_do_query_nocache(sql, __FILE__, __LINE__)
|
|
#define psync_sql_query(sql) psync_sql_do_query(sql, __FILE__, __LINE__)
|
|
#define psync_sql_query_rdlock_nocache(sql) \
|
|
psync_sql_do_query_rdlock_nocache(sql, __FILE__, __LINE__)
|
|
#define psync_sql_query_rdlock(sql) \
|
|
psync_sql_do_query_rdlock(sql, __FILE__, __LINE__)
|
|
#define psync_sql_query_nolock_nocache(sql) \
|
|
psync_sql_do_query_nolock_nocache(sql, __FILE__, __LINE__)
|
|
#define psync_sql_query_nolock(sql) \
|
|
psync_sql_do_query_nolock(sql, __FILE__, __LINE__)
|
|
#define psync_sql_prep_statement_nocache(sql) \
|
|
psync_sql_do_prep_statement_nocache(sql, __FILE__, __LINE__)
|
|
#define psync_sql_prep_statement(sql) \
|
|
psync_sql_do_prep_statement(sql, __FILE__, __LINE__)
|
|
|
|
int psync_sql_do_trylock(const char *file, unsigned line);
|
|
void psync_sql_do_lock(const char *file, unsigned line);
|
|
void psync_sql_do_rdlock(const char *file, unsigned line);
|
|
int psync_sql_do_statement(const char *sql, const char *file, unsigned line)
|
|
PSYNC_NONNULL(1);
|
|
int psync_sql_do_start_transaction(const char *file, unsigned line);
|
|
|
|
psync_sql_res *psync_sql_do_query_nocache(const char *sql, const char *file,
|
|
unsigned line) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_do_query(const char *sql, const char *file,
|
|
unsigned line) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_do_query_rdlock_nocache(const char *sql,
|
|
const char *file,
|
|
unsigned line)
|
|
PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_do_query_rdlock(const char *sql, const char *file,
|
|
unsigned line) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_do_query_nolock_nocache(const char *sql,
|
|
const char *file,
|
|
unsigned line)
|
|
PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_do_query_nolock(const char *sql, const char *file,
|
|
unsigned line) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_do_prep_statement_nocache(const char *sql,
|
|
const char *file,
|
|
unsigned line)
|
|
PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_do_prep_statement(const char *sql, const char *file,
|
|
unsigned line) PSYNC_NONNULL(1);
|
|
|
|
void psync_sql_dump_locks();
|
|
|
|
#else
|
|
|
|
int psync_sql_trylock();
|
|
void psync_sql_lock();
|
|
void psync_sql_rdlock();
|
|
int psync_sql_statement(const char *sql) PSYNC_NONNULL(1);
|
|
int psync_sql_start_transaction();
|
|
|
|
psync_sql_res *psync_sql_query_nocache(const char *sql) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_query(const char *sql) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_query_rdlock_nocache(const char *sql) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_query_rdlock(const char *sql) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_query_nolock(const char *sql) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_query_nolock_nocache(const char *sql) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_prep_statement(const char *sql) PSYNC_NONNULL(1);
|
|
psync_sql_res *psync_sql_prep_statement_nocache(const char *sql)
|
|
PSYNC_NONNULL(1);
|
|
|
|
#endif
|
|
|
|
void psync_sql_unlock();
|
|
void psync_sql_rdunlock();
|
|
int psync_sql_has_waiters();
|
|
int psync_sql_isrdlocked();
|
|
int psync_sql_islocked();
|
|
int psync_sql_tryupgradelock();
|
|
int psync_sql_sync();
|
|
int psync_sql_commit_transaction();
|
|
int psync_sql_rollback_transaction();
|
|
|
|
void psync_sql_transation_add_callbacks(
|
|
psync_transaction_callback_t commit_callback,
|
|
psync_transaction_callback_t rollback_callback, void *ptr);
|
|
|
|
char *psync_sql_cellstr(const char *sql) PSYNC_NONNULL(1);
|
|
int64_t psync_sql_cellint(const char *sql, int64_t dflt) PSYNC_NONNULL(1);
|
|
char **psync_sql_rowstr(const char *sql) PSYNC_NONNULL(1);
|
|
psync_variant *psync_sql_row(const char *sql) PSYNC_NONNULL(1);
|
|
int psync_sql_reset(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
int psync_sql_run(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
int psync_sql_run_free(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
int psync_sql_run_free_nocache(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
void psync_sql_bind_uint(psync_sql_res *res, int n, uint64_t val)
|
|
PSYNC_NONNULL(1);
|
|
void psync_sql_bind_int(psync_sql_res *res, int n, int64_t val)
|
|
PSYNC_NONNULL(1);
|
|
void psync_sql_bind_double(psync_sql_res *res, int n, double val)
|
|
PSYNC_NONNULL(1);
|
|
void psync_sql_bind_string(psync_sql_res *res, int n, const char *str)
|
|
PSYNC_NONNULL(1);
|
|
void psync_sql_bind_lstring(psync_sql_res *res, int n, const char *str,
|
|
size_t len) PSYNC_NONNULL(1);
|
|
void psync_sql_bind_blob(psync_sql_res *res, int n, const char *str, size_t len)
|
|
PSYNC_NONNULL(1);
|
|
void psync_sql_bind_null(psync_sql_res *res, int n) PSYNC_NONNULL(1);
|
|
void psync_sql_free_result(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
void psync_sql_free_result_nocache(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
psync_variant_row psync_sql_fetch_row(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
psync_str_row psync_sql_fetch_rowstr(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
psync_uint_row psync_sql_fetch_rowint(psync_sql_res *res) PSYNC_NONNULL(1);
|
|
psync_full_result_int *psync_sql_fetchall_int(psync_sql_res *res)
|
|
PSYNC_NONNULL(1);
|
|
uint32_t psync_sql_affected_rows() PSYNC_PURE;
|
|
uint64_t psync_sql_insertid() PSYNC_PURE;
|
|
|
|
int psync_rename_conflicted_file(const char *path);
|
|
|
|
void psync_libs_init();
|
|
void psync_run_after_sec(psync_run_after_t run, void *ptr, uint32_t seconds);
|
|
void psync_free_after_sec(void *ptr, uint32_t seconds);
|
|
|
|
int psync_match_pattern(const char *name, const char *pattern, size_t plen);
|
|
|
|
uint64_t psync_ato64(const char *str);
|
|
uint32_t psync_ato32(const char *str);
|
|
|
|
psync_list_builder_t *psync_list_builder_create(size_t element_size,
|
|
size_t offset);
|
|
void psync_list_bulder_add_sql(psync_list_builder_t *builder,
|
|
psync_sql_res *res,
|
|
psync_list_builder_sql_callback callback);
|
|
void *psync_list_bulder_add_element(psync_list_builder_t *builder);
|
|
void psync_list_add_string_offset(psync_list_builder_t *builder, size_t offset);
|
|
void psync_list_add_lstring_offset(psync_list_builder_t *builder, size_t offset,
|
|
size_t length);
|
|
void *psync_list_builder_finalize(psync_list_builder_t *builder);
|
|
|
|
psync_task_manager_t
|
|
psync_task_run_tasks(psync_task_callback_t const *callbacks,
|
|
void *const *params, int cnt);
|
|
void *psync_task_papi_result(psync_task_manager_t tm, int id);
|
|
void psync_task_free(psync_task_manager_t tm);
|
|
int psync_task_complete(void *h, void *data);
|
|
|
|
void psync_pqsort(void *base, size_t cnt, size_t sort_first, size_t size,
|
|
int (*compar)(const void *, const void *));
|
|
void psync_qpartition(void *base, size_t cnt, size_t sort_first, size_t size,
|
|
int (*compar)(const void *, const void *));
|
|
|
|
void psync_try_free_memory();
|
|
|
|
int psync_debug(const char *file, const char *function, int unsigned line,
|
|
int unsigned level, const char *fmt, ...) PSYNC_COLD
|
|
PSYNC_FORMAT(printf, 5, 6) PSYNC_NONNULL(5);
|
|
|
|
uint64_t psync_err_number_expected(const char *file, const char *function,
|
|
int unsigned line,
|
|
const psync_variant *v) PSYNC_COLD;
|
|
const char *psync_err_string_expected(const char *file, const char *function,
|
|
int unsigned line,
|
|
const psync_variant *v) PSYNC_COLD;
|
|
const char *psync_lstring_expected(const char *file, const char *function,
|
|
int unsigned line, const psync_variant *v,
|
|
size_t *len) PSYNC_NONNULL(4, 5);
|
|
double psync_err_real_expected(const char *file, const char *function,
|
|
int unsigned line,
|
|
const psync_variant *v) PSYNC_COLD;
|
|
|
|
/* needs 12 characters of buffer space on top of the length of the prefix */
|
|
static inline void psync_get_string_id(char *dst, const char *prefix,
|
|
uint64_t id) {
|
|
size_t plen;
|
|
plen = strlen(prefix);
|
|
dst = (char *)memcpy(dst, prefix, plen) + plen;
|
|
do {
|
|
*dst++ = base64_table[id % 64];
|
|
id /= 64;
|
|
} while (id);
|
|
*dst = 0;
|
|
}
|
|
|
|
/* needs 24 characters of buffer space on top of the length of the prefix */
|
|
static inline void psync_get_string_id2(char *dst, const char *prefix,
|
|
uint64_t id1, uint64_t id2) {
|
|
size_t plen;
|
|
plen = strlen(prefix);
|
|
dst = (char *)memcpy(dst, prefix, plen) + plen;
|
|
do {
|
|
*dst++ = base64_table[id1 % 64];
|
|
id1 /= 64;
|
|
} while (id1);
|
|
*dst++ = '.';
|
|
do {
|
|
*dst++ = base64_table[id2 % 64];
|
|
id2 /= 64;
|
|
} while (id2);
|
|
*dst = 0;
|
|
}
|
|
|
|
static inline size_t psync_strlcpy(char *dst, const char *src, size_t size) {
|
|
size_t len;
|
|
len = strlen(src);
|
|
if (likely_log(len < size)) {
|
|
memcpy(dst, src, len + 1);
|
|
return len;
|
|
} else if (likely_log(size)) {
|
|
memcpy(dst, src, size - 1);
|
|
dst[size - 1] = 0;
|
|
return size - 1;
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|