mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-26 01:28:40 +00:00
Update code style
This commit is contained in:
parent
b34004c1cb
commit
33b480fbae
|
|
@ -17,46 +17,43 @@
|
|||
#include "../DatabaseType.h"
|
||||
#include "../DatabaseStatus.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
typedef struct {
|
||||
size_t rows = 0;
|
||||
size_t columns = 0;
|
||||
char **results = NULL;
|
||||
} QueryResult;
|
||||
typedef struct {
|
||||
size_t rows = 0;
|
||||
size_t columns = 0;
|
||||
char **results = NULL;
|
||||
} QueryResult;
|
||||
|
||||
struct ConnectionAbstract {
|
||||
void *con = NULL;
|
||||
struct ConnectionAbstract {
|
||||
void *con = NULL;
|
||||
|
||||
DbConnectionConfig dbdata;
|
||||
DbConnectionConfig dbdata;
|
||||
|
||||
DatabaseType type = DatabaseType::UNDEFINED;
|
||||
DatabaseType type = DatabaseType::UNDEFINED;
|
||||
|
||||
DatabaseStatus status = DatabaseStatus::CLOSED;
|
||||
DatabaseStatus status = DatabaseStatus::CLOSED;
|
||||
|
||||
virtual void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
return;
|
||||
virtual void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
virtual void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
free(con);
|
||||
}
|
||||
|
||||
virtual void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
free(con);
|
||||
}
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
}
|
||||
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
}
|
||||
|
||||
virtual QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
return QueryResult();
|
||||
}
|
||||
};
|
||||
}
|
||||
virtual QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
return QueryResult();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -21,40 +21,37 @@
|
|||
#include "PostgresqlConnection.h"
|
||||
#include "SQLiteConnection.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
ConnectionAbstract *create_connection(DbConnectionConfig dbdata)
|
||||
{
|
||||
ConnectionAbstract *create_connection(DbConnectionConfig dbdata)
|
||||
{
|
||||
switch (dbdata.db) {
|
||||
case DatabaseType::MYSQL:
|
||||
return new MysqlConnection(dbdata);
|
||||
case DatabaseType::PGSQL:
|
||||
return new PostgresqlConnection(dbdata);
|
||||
case DatabaseType::SQLSRV:
|
||||
return NULL;
|
||||
case DatabaseType::SQLITE:
|
||||
return new SQLiteConnection(dbdata);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
switch (dbdata.db) {
|
||||
case DatabaseType::MYSQL:
|
||||
return new MysqlConnection(dbdata);
|
||||
case DatabaseType::PGSQL:
|
||||
return new PostgresqlConnection(dbdata);
|
||||
case DatabaseType::SQLSRV:
|
||||
return NULL;
|
||||
case DatabaseType::SQLITE:
|
||||
return new SQLiteConnection(dbdata);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void close(ConnectionAbstract *db, DbConnectionConfig dbdata)
|
||||
{
|
||||
switch (dbdata.db) {
|
||||
case DatabaseType::MYSQL:
|
||||
return ((MysqlConnection *) db)->close();
|
||||
case DatabaseType::PGSQL:
|
||||
return ((PostgresqlConnection *) db)->close();
|
||||
case DatabaseType::SQLSRV:
|
||||
return;
|
||||
case DatabaseType::SQLITE:
|
||||
return ((SQLiteConnection *) db)->close();
|
||||
default:
|
||||
return;
|
||||
}
|
||||
void close(ConnectionAbstract *db, DbConnectionConfig dbdata)
|
||||
{
|
||||
switch (dbdata.db) {
|
||||
case DatabaseType::MYSQL:
|
||||
return ((MysqlConnection *) db)->close();
|
||||
case DatabaseType::PGSQL:
|
||||
return ((PostgresqlConnection *) db)->close();
|
||||
case DatabaseType::SQLSRV:
|
||||
return;
|
||||
case DatabaseType::SQLITE:
|
||||
return ((SQLiteConnection *) db)->close();
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,45 +15,42 @@
|
|||
|
||||
#include "../DatabaseType.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
typedef struct {
|
||||
DatabaseType db = DatabaseType::UNDEFINED;
|
||||
|
||||
const char *database = NULL;
|
||||
|
||||
const char *host = NULL;
|
||||
|
||||
int port = 0;
|
||||
|
||||
const char *login = NULL;
|
||||
|
||||
const char *password = NULL;
|
||||
} DbConnectionConfig;
|
||||
|
||||
void free_DbConnectionConfig(DbConnectionConfig *dbdata)
|
||||
{
|
||||
typedef struct {
|
||||
DatabaseType db = DatabaseType::UNDEFINED;
|
||||
if (dbdata->database != NULL) {
|
||||
free((char *) dbdata->database);
|
||||
dbdata->database = NULL;
|
||||
}
|
||||
|
||||
const char *database = NULL;
|
||||
if (dbdata->host != NULL) {
|
||||
free((char *) dbdata->host);
|
||||
dbdata->host = NULL;
|
||||
}
|
||||
|
||||
const char *host = NULL;
|
||||
if (dbdata->login != NULL) {
|
||||
free((char *) dbdata->login);
|
||||
dbdata->login = NULL;
|
||||
}
|
||||
|
||||
int port = 0;
|
||||
|
||||
const char *login = NULL;
|
||||
|
||||
const char *password = NULL;
|
||||
} DbConnectionConfig;
|
||||
|
||||
void free_DbConnectionConfig(DbConnectionConfig *dbdata)
|
||||
{
|
||||
if (dbdata->database != NULL) {
|
||||
free((char *) dbdata->database);
|
||||
dbdata->database = NULL;
|
||||
}
|
||||
|
||||
if (dbdata->host != NULL) {
|
||||
free((char *) dbdata->host);
|
||||
dbdata->host = NULL;
|
||||
}
|
||||
|
||||
if (dbdata->login != NULL) {
|
||||
free((char *) dbdata->login);
|
||||
dbdata->login = NULL;
|
||||
}
|
||||
|
||||
if (dbdata->password != NULL) {
|
||||
free((char *) dbdata->password);
|
||||
dbdata->password = NULL;
|
||||
}
|
||||
if (dbdata->password != NULL) {
|
||||
free((char *) dbdata->password);
|
||||
dbdata->password = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,131 +20,128 @@
|
|||
#include "../DatabaseType.h"
|
||||
#include "../DatabaseStatus.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
struct MysqlConnection : ConnectionAbstract {
|
||||
MysqlConnection(DbConnectionConfig dbdata)
|
||||
{
|
||||
this->type = DatabaseType::MYSQL;
|
||||
this->dbdata = dbdata;
|
||||
}
|
||||
struct MysqlConnection : ConnectionAbstract {
|
||||
MysqlConnection(DbConnectionConfig dbdata)
|
||||
{
|
||||
this->type = DatabaseType::MYSQL;
|
||||
this->dbdata = dbdata;
|
||||
}
|
||||
|
||||
void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||
void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||
|
||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||
|| this->dbdata.host == NULL
|
||||
|| this->dbdata.port == 0
|
||||
|| this->dbdata.database == NULL
|
||||
|| this->dbdata.login == NULL
|
||||
|| this->dbdata.password == NULL
|
||||
) {
|
||||
this->status = DatabaseStatus::FAILURE;
|
||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||
|| this->dbdata.host == NULL
|
||||
|| this->dbdata.port == 0
|
||||
|| this->dbdata.database == NULL
|
||||
|| this->dbdata.login == NULL
|
||||
|| this->dbdata.password == NULL
|
||||
) {
|
||||
this->status = DatabaseStatus::FAILURE;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
this->close();
|
||||
|
||||
this->con = mysql_init(NULL);
|
||||
this->con = mysql_real_connect(
|
||||
(::MYSQL *) this->con,
|
||||
this->dbdata.host,
|
||||
this->dbdata.login,
|
||||
this->dbdata.password,
|
||||
this->dbdata.database,
|
||||
this->dbdata.port,
|
||||
NULL, 0
|
||||
);
|
||||
|
||||
if (!this->con) {
|
||||
this->status = DatabaseStatus::MISSING_DATABASE;
|
||||
|
||||
mysql_close((::MYSQL *) this->con);
|
||||
this->con = NULL;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
mysql_close((::MYSQL *) this->con);
|
||||
}
|
||||
this->close();
|
||||
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
this->con = mysql_init(NULL);
|
||||
this->con = mysql_real_connect(
|
||||
(::MYSQL *) this->con,
|
||||
this->dbdata.host,
|
||||
this->dbdata.login,
|
||||
this->dbdata.password,
|
||||
this->dbdata.database,
|
||||
this->dbdata.port,
|
||||
NULL, 0
|
||||
);
|
||||
|
||||
if (!this->con) {
|
||||
this->status = DatabaseStatus::MISSING_DATABASE;
|
||||
|
||||
mysql_close((::MYSQL *) this->con);
|
||||
this->con = NULL;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
mysql_close((::MYSQL *) this->con);
|
||||
}
|
||||
|
||||
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
QueryResult result;
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
}
|
||||
|
||||
MYSQL_RES *res;
|
||||
int status = 0;
|
||||
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
QueryResult result;
|
||||
|
||||
if (paramValues != NULL) {
|
||||
return result;
|
||||
} else {
|
||||
status = mysql_query((::MYSQL *) this->con, stmt);
|
||||
res = mysql_store_result((::MYSQL *) this->con);
|
||||
}
|
||||
MYSQL_RES *res;
|
||||
int status = 0;
|
||||
|
||||
if (res == NULL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.rows = mysql_num_rows(res);
|
||||
result.columns = mysql_num_fields(res);
|
||||
|
||||
if (result.rows == 0 || result.columns == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
|
||||
|
||||
char *temp = NULL;
|
||||
size_t valLen = 0;
|
||||
size_t *lengths;
|
||||
|
||||
::MYSQL_ROW row;
|
||||
size_t i = 0;
|
||||
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
lengths = mysql_fetch_lengths(res);
|
||||
for (int j = 0; j < result.columns; ++j) {
|
||||
temp = row[j];
|
||||
|
||||
if (temp == NULL) {
|
||||
result.results[i * result.columns + j] = NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
valLen = lengths[j];
|
||||
|
||||
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
|
||||
memcpy(result.results[i * result.columns + j], temp, valLen);
|
||||
result.results[i * result.columns + j][valLen] = '\0';
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
if (paramValues != NULL) {
|
||||
return result;
|
||||
} else {
|
||||
status = mysql_query((::MYSQL *) this->con, stmt);
|
||||
res = mysql_store_result((::MYSQL *) this->con);
|
||||
}
|
||||
|
||||
if (res == NULL) {
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
result.rows = mysql_num_rows(res);
|
||||
result.columns = mysql_num_fields(res);
|
||||
|
||||
if (result.rows == 0 || result.columns == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
|
||||
|
||||
char *temp = NULL;
|
||||
size_t valLen = 0;
|
||||
size_t *lengths;
|
||||
|
||||
::MYSQL_ROW row;
|
||||
size_t i = 0;
|
||||
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
lengths = mysql_fetch_lengths(res);
|
||||
for (int j = 0; j < result.columns; ++j) {
|
||||
temp = row[j];
|
||||
|
||||
if (temp == NULL) {
|
||||
result.results[i * result.columns + j] = NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
valLen = lengths[j];
|
||||
|
||||
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
|
||||
memcpy(result.results[i * result.columns + j], temp, valLen);
|
||||
result.results[i * result.columns + j][valLen] = '\0';
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -20,125 +20,122 @@
|
|||
#include "../DatabaseType.h"
|
||||
#include "../DatabaseStatus.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
struct PostgresqlConnection : ConnectionAbstract {
|
||||
PostgresqlConnection(DbConnectionConfig dbdata)
|
||||
{
|
||||
this->type = DatabaseType::PGSQL;
|
||||
this->dbdata = dbdata;
|
||||
}
|
||||
struct PostgresqlConnection : ConnectionAbstract {
|
||||
PostgresqlConnection(DbConnectionConfig dbdata)
|
||||
{
|
||||
this->type = DatabaseType::PGSQL;
|
||||
this->dbdata = dbdata;
|
||||
}
|
||||
|
||||
void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||
void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||
|
||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||
|| this->dbdata.host == NULL
|
||||
|| this->dbdata.port == 0
|
||||
|| this->dbdata.database == NULL
|
||||
|| this->dbdata.login == NULL
|
||||
|| this->dbdata.password == NULL
|
||||
) {
|
||||
this->status = DatabaseStatus::FAILURE;
|
||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||
|| this->dbdata.host == NULL
|
||||
|| this->dbdata.port == 0
|
||||
|| this->dbdata.database == NULL
|
||||
|| this->dbdata.login == NULL
|
||||
|| this->dbdata.password == NULL
|
||||
) {
|
||||
this->status = DatabaseStatus::FAILURE;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
this->close();
|
||||
|
||||
char port[12];
|
||||
sprintf(port, "%d", this->dbdata.port);
|
||||
|
||||
this->con = PQsetdbLogin(
|
||||
this->dbdata.host,
|
||||
port,
|
||||
NULL,
|
||||
NULL,
|
||||
this->dbdata.database,
|
||||
this->dbdata.login,
|
||||
this->dbdata.password
|
||||
);
|
||||
|
||||
ConnStatusType stat = PQstatus((PGconn *) this->con);
|
||||
|
||||
if (stat != ConnStatusType::CONNECTION_OK) {
|
||||
this->status = DatabaseStatus::MISSING_DATABASE;
|
||||
|
||||
PQfinish((PGconn *) this->con);
|
||||
this->con = NULL;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
PQfinish((PGconn *) this->con);
|
||||
}
|
||||
this->close();
|
||||
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
char port[12];
|
||||
sprintf(port, "%d", this->dbdata.port);
|
||||
|
||||
this->con = PQsetdbLogin(
|
||||
this->dbdata.host,
|
||||
port,
|
||||
NULL,
|
||||
NULL,
|
||||
this->dbdata.database,
|
||||
this->dbdata.login,
|
||||
this->dbdata.password
|
||||
);
|
||||
|
||||
ConnStatusType stat = PQstatus((PGconn *) this->con);
|
||||
|
||||
if (stat != ConnStatusType::CONNECTION_OK) {
|
||||
this->status = DatabaseStatus::MISSING_DATABASE;
|
||||
|
||||
PQfinish((PGconn *) this->con);
|
||||
this->con = NULL;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
PQfinish((PGconn *) this->con);
|
||||
}
|
||||
|
||||
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
QueryResult result;
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
}
|
||||
|
||||
PGresult *res;
|
||||
if (paramValues != NULL) {
|
||||
res = PQexecParams((PGconn *) this->con, stmt, 1, NULL, (const char* const*) paramValues, NULL, NULL, 0);
|
||||
} else {
|
||||
res = PQexec((PGconn *) this->con, stmt);
|
||||
}
|
||||
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
QueryResult result;
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
|
||||
PQclear(res);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result.rows = PQntuples(res);
|
||||
result.columns = PQnfields(res);
|
||||
|
||||
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
|
||||
|
||||
char *temp = NULL;
|
||||
size_t valLen = 0;
|
||||
|
||||
for (size_t i = 0; i < result.rows; ++i) {
|
||||
for (size_t j = 0; j < result.columns; ++j) {
|
||||
temp = PQgetvalue(res, i, j);
|
||||
|
||||
if (temp == NULL) {
|
||||
result.results[i * result.columns + j] = NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
valLen = strlen(temp);
|
||||
|
||||
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
|
||||
memcpy(result.results[i * result.columns + j], temp, valLen);
|
||||
result.results[i * result.columns + j][valLen] = '\0';
|
||||
}
|
||||
}
|
||||
PGresult *res;
|
||||
if (paramValues != NULL) {
|
||||
res = PQexecParams((PGconn *) this->con, stmt, 1, NULL, (const char* const*) paramValues, NULL, NULL, 0);
|
||||
} else {
|
||||
res = PQexec((PGconn *) this->con, stmt);
|
||||
}
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
|
||||
PQclear(res);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
result.rows = PQntuples(res);
|
||||
result.columns = PQnfields(res);
|
||||
|
||||
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
|
||||
|
||||
char *temp = NULL;
|
||||
size_t valLen = 0;
|
||||
|
||||
for (size_t i = 0; i < result.rows; ++i) {
|
||||
for (size_t j = 0; j < result.columns; ++j) {
|
||||
temp = PQgetvalue(res, i, j);
|
||||
|
||||
if (temp == NULL) {
|
||||
result.results[i * result.columns + j] = NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
valLen = strlen(temp);
|
||||
|
||||
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
|
||||
memcpy(result.results[i * result.columns + j], temp, valLen);
|
||||
result.results[i * result.columns + j][valLen] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -20,142 +20,139 @@
|
|||
#include "../DatabaseType.h"
|
||||
#include "../DatabaseStatus.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
struct SQLiteConnection : ConnectionAbstract {
|
||||
SQLiteConnection(DbConnectionConfig dbdata)
|
||||
{
|
||||
this->type = DatabaseType::MYSQL;
|
||||
this->dbdata = dbdata;
|
||||
}
|
||||
struct SQLiteConnection : ConnectionAbstract {
|
||||
SQLiteConnection(DbConnectionConfig dbdata)
|
||||
{
|
||||
this->type = DatabaseType::MYSQL;
|
||||
this->dbdata = dbdata;
|
||||
}
|
||||
|
||||
void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||
void connect(DbConnectionConfig *dbdata = NULL)
|
||||
{
|
||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||
|
||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||
|| this->dbdata.database == NULL
|
||||
) {
|
||||
this->status = DatabaseStatus::FAILURE;
|
||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||
|| this->dbdata.database == NULL
|
||||
) {
|
||||
this->status = DatabaseStatus::FAILURE;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
this->close();
|
||||
|
||||
int stat = sqlite3_open(this->dbdata.host, (sqlite3 **) &this->con);
|
||||
if (stat != SQLITE_OK) {
|
||||
this->status = DatabaseStatus::MISSING_DATABASE;
|
||||
|
||||
sqlite3_close((sqlite3 *) this->con);
|
||||
this->con = NULL;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
sqlite3_close((sqlite3 *) this->con);
|
||||
}
|
||||
this->close();
|
||||
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
int stat = sqlite3_open(this->dbdata.host, (sqlite3 **) &this->con);
|
||||
if (stat != SQLITE_OK) {
|
||||
this->status = DatabaseStatus::MISSING_DATABASE;
|
||||
|
||||
sqlite3_close((sqlite3 *) this->con);
|
||||
this->con = NULL;
|
||||
|
||||
if (this->dbdata.password != NULL) {
|
||||
free((char *) this->dbdata.password);
|
||||
this->dbdata.password = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (this->con != NULL) {
|
||||
sqlite3_close((sqlite3 *) this->con);
|
||||
}
|
||||
|
||||
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
QueryResult result;
|
||||
this->con = NULL;
|
||||
this->status = DatabaseStatus::CLOSED;
|
||||
}
|
||||
|
||||
sqlite3_stmt *res;
|
||||
int status = 0;
|
||||
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||
{
|
||||
QueryResult result;
|
||||
|
||||
if (paramValues != NULL) {
|
||||
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
||||
sqlite3_stmt *res;
|
||||
int status = 0;
|
||||
|
||||
// @todo sqlite3_bind_int(res, 1, 3);
|
||||
} else {
|
||||
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
||||
}
|
||||
if (paramValues != NULL) {
|
||||
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
||||
|
||||
if (res == NULL) {
|
||||
return result;
|
||||
}
|
||||
// @todo sqlite3_bind_int(res, 1, 3);
|
||||
} else {
|
||||
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
||||
}
|
||||
|
||||
status = sqlite3_step(res);
|
||||
if (res == NULL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.rows = 100;
|
||||
result.columns = sqlite3_column_count(res);
|
||||
status = sqlite3_step(res);
|
||||
|
||||
if (result.rows == 0 || result.columns == 0) {
|
||||
return result;
|
||||
}
|
||||
result.rows = 100;
|
||||
result.columns = sqlite3_column_count(res);
|
||||
|
||||
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
|
||||
if (result.rows == 0 || result.columns == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char *temp = NULL;
|
||||
size_t valLen = 0;
|
||||
char ** tempStorage = NULL;
|
||||
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
|
||||
|
||||
size_t i = 0;
|
||||
while (status == SQLITE_ROW) {
|
||||
if (i == result.rows) {
|
||||
tempStorage = (char **) malloc((result.rows + 100) * result.columns * sizeof(char*));
|
||||
memcpy(tempStorage, result.results, result.rows * result.columns * sizeof(char*));
|
||||
char *temp = NULL;
|
||||
size_t valLen = 0;
|
||||
char ** tempStorage = NULL;
|
||||
|
||||
free(result.results);
|
||||
result.results = tempStorage;
|
||||
|
||||
result.rows += 100;
|
||||
}
|
||||
|
||||
for (int j = 0; j < result.columns; ++j) {
|
||||
temp = (char *) sqlite3_column_text(res, j);
|
||||
|
||||
if (temp == NULL) {
|
||||
result.results[i * result.columns + j] = NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
valLen = strlen(temp);
|
||||
|
||||
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
|
||||
memcpy(result.results[i * result.columns + j], temp, valLen);
|
||||
result.results[i * result.columns + j][valLen] = '\0';
|
||||
}
|
||||
|
||||
status = sqlite3_step(res);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
--i;
|
||||
if (i != result.rows) {
|
||||
tempStorage = (char **) malloc(i * result.columns * sizeof(char*));
|
||||
memcpy(tempStorage, result.results, i * result.columns * sizeof(char*));
|
||||
size_t i = 0;
|
||||
while (status == SQLITE_ROW) {
|
||||
if (i == result.rows) {
|
||||
tempStorage = (char **) malloc((result.rows + 100) * result.columns * sizeof(char*));
|
||||
memcpy(tempStorage, result.results, result.rows * result.columns * sizeof(char*));
|
||||
|
||||
free(result.results);
|
||||
result.results = tempStorage;
|
||||
|
||||
result.rows = i;
|
||||
result.rows += 100;
|
||||
}
|
||||
|
||||
sqlite3_finalize(res);
|
||||
for (int j = 0; j < result.columns; ++j) {
|
||||
temp = (char *) sqlite3_column_text(res, j);
|
||||
|
||||
return result;
|
||||
if (temp == NULL) {
|
||||
result.results[i * result.columns + j] = NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
valLen = strlen(temp);
|
||||
|
||||
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
|
||||
memcpy(result.results[i * result.columns + j], temp, valLen);
|
||||
result.results[i * result.columns + j][valLen] = '\0';
|
||||
}
|
||||
|
||||
status = sqlite3_step(res);
|
||||
|
||||
++i;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
--i;
|
||||
if (i != result.rows) {
|
||||
tempStorage = (char **) malloc(i * result.columns * sizeof(char*));
|
||||
memcpy(tempStorage, result.results, i * result.columns * sizeof(char*));
|
||||
|
||||
free(result.results);
|
||||
result.results = tempStorage;
|
||||
|
||||
result.rows = i;
|
||||
}
|
||||
|
||||
sqlite3_finalize(res);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -10,19 +10,16 @@
|
|||
#ifndef DATASTORAGE_DATABASE_STATUS_H
|
||||
#define DATASTORAGE_DATABASE_STATUS_H
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
typedef enum {
|
||||
OK = 0,
|
||||
MISSING_DATABASE = 1,
|
||||
MISSING_TABLE = 2,
|
||||
FAILURE = 3,
|
||||
READONLY = 4,
|
||||
CLOSED = 5
|
||||
} DatabaseStatus;
|
||||
}
|
||||
typedef enum {
|
||||
OK = 0,
|
||||
MISSING_DATABASE = 1,
|
||||
MISSING_TABLE = 2,
|
||||
FAILURE = 3,
|
||||
READONLY = 4,
|
||||
CLOSED = 5
|
||||
} DatabaseStatus;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -12,32 +12,29 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
typedef enum {
|
||||
MYSQL = 1,
|
||||
SQLITE = 2,
|
||||
PGSQL = 3,
|
||||
SQLSRV = 4,
|
||||
UNDEFINED = 5
|
||||
} DatabaseType;
|
||||
typedef enum {
|
||||
MYSQL = 1,
|
||||
SQLITE = 2,
|
||||
PGSQL = 3,
|
||||
SQLSRV = 4,
|
||||
UNDEFINED = 5
|
||||
} DatabaseType;
|
||||
|
||||
DatabaseType database_type_from_str(const char* type)
|
||||
{
|
||||
if (strcmp(type, "mysql") == 0) {
|
||||
return DatabaseType::MYSQL;
|
||||
} else if (strcmp(type, "sqlite") == 0) {
|
||||
return DatabaseType::SQLITE;
|
||||
} else if (strcmp(type, "pqsql") == 0) {
|
||||
return DatabaseType::PGSQL;
|
||||
} else if (strcmp(type, "mssql") == 0) {
|
||||
return DatabaseType::SQLSRV;
|
||||
}
|
||||
|
||||
return DatabaseType::UNDEFINED;
|
||||
DatabaseType database_type_from_str(const char* type)
|
||||
{
|
||||
if (strcmp(type, "mysql") == 0) {
|
||||
return DatabaseType::MYSQL;
|
||||
} else if (strcmp(type, "sqlite") == 0) {
|
||||
return DatabaseType::SQLITE;
|
||||
} else if (strcmp(type, "pqsql") == 0) {
|
||||
return DatabaseType::PGSQL;
|
||||
} else if (strcmp(type, "mssql") == 0) {
|
||||
return DatabaseType::SQLSRV;
|
||||
}
|
||||
|
||||
return DatabaseType::UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,42 +18,39 @@
|
|||
#include "ReadMapper.h"
|
||||
#include "MapperAbstract.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
static DataStorage::Database::ConnectionAbstract *db;
|
||||
static const char *dateTimeFormat = "Y-m-d H:i:s";
|
||||
static DataStorage::Database::ConnectionAbstract *db;
|
||||
static const char *dateTimeFormat = "Y-m-d H:i:s";
|
||||
|
||||
struct DataMapperFactory {
|
||||
static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||
{
|
||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||
readMapper->mapper = mapper;
|
||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
||||
struct DataMapperFactory {
|
||||
static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||
{
|
||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||
readMapper->mapper = mapper;
|
||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
||||
|
||||
return readMapper;
|
||||
}
|
||||
return readMapper;
|
||||
}
|
||||
|
||||
static ReadMapper *get(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||
{
|
||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||
readMapper->mapper = mapper;
|
||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
||||
static ReadMapper *get(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||
{
|
||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||
readMapper->mapper = mapper;
|
||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
||||
|
||||
return readMapper->get();
|
||||
}
|
||||
return readMapper->get();
|
||||
}
|
||||
|
||||
static ReadMapper *getAll(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||
{
|
||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||
readMapper->mapper = mapper;
|
||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
||||
static ReadMapper *getAll(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||
{
|
||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||
readMapper->mapper = mapper;
|
||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
||||
|
||||
return readMapper->getAll();
|
||||
}
|
||||
};
|
||||
}
|
||||
return readMapper->getAll();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,208 +13,205 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
typedef enum {
|
||||
MAPPER_DEFAULT = 0,
|
||||
MAPPER_GET = 1,
|
||||
MAPPER_GET_ALL = 4,
|
||||
MAPPER_FIND = 7,
|
||||
MAPPER_GET_RAW = 8,
|
||||
MAPPER_GET_RANDOM = 11,
|
||||
MAPPER_COUNT_MODELS = 12,
|
||||
MAPPER_CREATE = 1001,
|
||||
MAPPER_UPDATE = 2001,
|
||||
MAPPER_DELETE = 3001
|
||||
} MapperType;
|
||||
|
||||
typedef enum {
|
||||
FIELD_TYPE_INT = 1,
|
||||
FIELD_TYPE_FLOAT = 2,
|
||||
FIELD_TYPE_STRING = 3,
|
||||
FIELD_TYPE_BOOL = 4
|
||||
} FieldType;
|
||||
|
||||
typedef struct {
|
||||
const char *name = NULL;
|
||||
size_t size = 0;
|
||||
} ModelStructure;
|
||||
|
||||
void free_ModelStructure(ModelStructure *data)
|
||||
{
|
||||
typedef enum {
|
||||
MAPPER_DEFAULT = 0,
|
||||
MAPPER_GET = 1,
|
||||
MAPPER_GET_ALL = 4,
|
||||
MAPPER_FIND = 7,
|
||||
MAPPER_GET_RAW = 8,
|
||||
MAPPER_GET_RANDOM = 11,
|
||||
MAPPER_COUNT_MODELS = 12,
|
||||
MAPPER_CREATE = 1001,
|
||||
MAPPER_UPDATE = 2001,
|
||||
MAPPER_DELETE = 3001
|
||||
} MapperType;
|
||||
/* Not necessary
|
||||
if (data->name != NULL) {
|
||||
free((void *) data->name);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
FIELD_TYPE_INT = 1,
|
||||
FIELD_TYPE_FLOAT = 2,
|
||||
FIELD_TYPE_STRING = 3,
|
||||
FIELD_TYPE_BOOL = 4
|
||||
} FieldType;
|
||||
typedef struct {
|
||||
const char *name = NULL;
|
||||
int type = FieldType::FIELD_TYPE_INT;
|
||||
const char *internal = NULL;
|
||||
bool readonly = false;
|
||||
bool autocomplete = false;
|
||||
} DataMapperColumn;
|
||||
|
||||
typedef struct {
|
||||
const char *name = NULL;
|
||||
size_t size = 0;
|
||||
} ModelStructure;
|
||||
|
||||
void free_ModelStructure(ModelStructure *data)
|
||||
{
|
||||
/* Not necessary
|
||||
if (data->name != NULL) {
|
||||
free((void *) data->name);
|
||||
}
|
||||
*/
|
||||
void free_DataMapperColumn(DataMapperColumn *data)
|
||||
{
|
||||
if (data->name != NULL) {
|
||||
free((void *) data->name);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name = NULL;
|
||||
int type = FieldType::FIELD_TYPE_INT;
|
||||
const char *internal = NULL;
|
||||
bool readonly = false;
|
||||
bool autocomplete = false;
|
||||
} DataMapperColumn;
|
||||
if (data->internal != NULL) {
|
||||
free((void *) data->internal);
|
||||
}
|
||||
}
|
||||
|
||||
void free_DataMapperColumn(DataMapperColumn *data)
|
||||
{
|
||||
if (data->name != NULL) {
|
||||
free((void *) data->name);
|
||||
}
|
||||
typedef struct {
|
||||
const char *member = NULL;
|
||||
const char *mapper = NULL;
|
||||
const char *external = NULL;
|
||||
const char *table = NULL;
|
||||
const char *self = NULL;
|
||||
const char *column = NULL;
|
||||
bool conditional = false;
|
||||
const char *by = NULL;
|
||||
} TableRelation;
|
||||
|
||||
if (data->internal != NULL) {
|
||||
free((void *) data->internal);
|
||||
}
|
||||
void free_TableRelation(TableRelation *data)
|
||||
{
|
||||
/* Not necessary
|
||||
if (data->member != NULL) {
|
||||
free((void *) data->member);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *member = NULL;
|
||||
const char *mapper = NULL;
|
||||
const char *external = NULL;
|
||||
const char *table = NULL;
|
||||
const char *self = NULL;
|
||||
const char *column = NULL;
|
||||
bool conditional = false;
|
||||
const char *by = NULL;
|
||||
} TableRelation;
|
||||
|
||||
void free_TableRelation(TableRelation *data)
|
||||
{
|
||||
/* Not necessary
|
||||
if (data->member != NULL) {
|
||||
free((void *) data->member);
|
||||
}
|
||||
|
||||
if (data->mapper != NULL) {
|
||||
free((void *) data->mapper);
|
||||
}
|
||||
|
||||
if (data->external != NULL) {
|
||||
free((void *) data->external);
|
||||
}
|
||||
|
||||
if (data->table != NULL) {
|
||||
free((void *) data->table);
|
||||
}
|
||||
|
||||
if (data->self != NULL) {
|
||||
free((void *) data->self);
|
||||
}
|
||||
|
||||
if (data->column != NULL) {
|
||||
free((void *) data->column);
|
||||
}
|
||||
|
||||
if (data->self != NULL) {
|
||||
free((void *) data->self);
|
||||
}
|
||||
|
||||
if (data->by != NULL) {
|
||||
free((void *) data->by);
|
||||
}
|
||||
*/
|
||||
if (data->mapper != NULL) {
|
||||
free((void *) data->mapper);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *TABLE = NULL;
|
||||
const char *PRIMARYFIELD = NULL;
|
||||
const char *CREATED_AT = NULL;
|
||||
const char *PARENT = NULL;
|
||||
void *MODEL = NULL;
|
||||
if (data->external != NULL) {
|
||||
free((void *) data->external);
|
||||
}
|
||||
|
||||
int MEMBER_COUNT = 0;
|
||||
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
|
||||
if (data->table != NULL) {
|
||||
free((void *) data->table);
|
||||
}
|
||||
|
||||
int COLUMN_COUNT = 0;
|
||||
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
|
||||
if (data->self != NULL) {
|
||||
free((void *) data->self);
|
||||
}
|
||||
|
||||
int OWNS_ONE_COUNT = 0;
|
||||
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
|
||||
if (data->column != NULL) {
|
||||
free((void *) data->column);
|
||||
}
|
||||
|
||||
int HAS_MANY_COUNT = 0;
|
||||
DataStorage::Database::TableRelation *HAS_MANY = NULL;
|
||||
if (data->self != NULL) {
|
||||
free((void *) data->self);
|
||||
}
|
||||
|
||||
int BELONGS_TO_COUNT = 0;
|
||||
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
|
||||
} MapperData;
|
||||
if (data->by != NULL) {
|
||||
free((void *) data->by);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void free_MapperData(DataStorage::Database::MapperData *data)
|
||||
{
|
||||
/* Not necessary
|
||||
if (data->TABLE != NULL) {
|
||||
free((void *) data->TABLE);
|
||||
}
|
||||
typedef struct {
|
||||
const char *TABLE = NULL;
|
||||
const char *PRIMARYFIELD = NULL;
|
||||
const char *CREATED_AT = NULL;
|
||||
const char *PARENT = NULL;
|
||||
void *MODEL = NULL;
|
||||
|
||||
if (data->PRIMARYFIELD != NULL) {
|
||||
free((void *) data->PRIMARYFIELD);
|
||||
}
|
||||
int MEMBER_COUNT = 0;
|
||||
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
|
||||
|
||||
if (data->CREATED_AT != NULL) {
|
||||
free((void *) data->CREATED_AT);
|
||||
}
|
||||
int COLUMN_COUNT = 0;
|
||||
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
|
||||
|
||||
if (data->PARENT != NULL) {
|
||||
free((void *) data->PARENT);
|
||||
}
|
||||
int OWNS_ONE_COUNT = 0;
|
||||
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
|
||||
|
||||
if (data->MODEL != NULL) {
|
||||
free(data->MODEL);
|
||||
int HAS_MANY_COUNT = 0;
|
||||
DataStorage::Database::TableRelation *HAS_MANY = NULL;
|
||||
|
||||
int BELONGS_TO_COUNT = 0;
|
||||
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
|
||||
} MapperData;
|
||||
|
||||
void free_MapperData(DataStorage::Database::MapperData *data)
|
||||
{
|
||||
/* Not necessary
|
||||
if (data->TABLE != NULL) {
|
||||
free((void *) data->TABLE);
|
||||
}
|
||||
|
||||
if (data->PRIMARYFIELD != NULL) {
|
||||
free((void *) data->PRIMARYFIELD);
|
||||
}
|
||||
|
||||
if (data->CREATED_AT != NULL) {
|
||||
free((void *) data->CREATED_AT);
|
||||
}
|
||||
|
||||
if (data->PARENT != NULL) {
|
||||
free((void *) data->PARENT);
|
||||
}
|
||||
|
||||
if (data->MODEL != NULL) {
|
||||
free(data->MODEL);
|
||||
}
|
||||
*/
|
||||
|
||||
int i = 0;
|
||||
if (data->MODEL_STRUCTURE != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->MEMBER_COUNT; ++i) {
|
||||
free_ModelStructure(&data->MODEL_STRUCTURE[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
int i = 0;
|
||||
if (data->MODEL_STRUCTURE != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->MEMBER_COUNT; ++i) {
|
||||
free_ModelStructure(&data->MODEL_STRUCTURE[i]);
|
||||
}
|
||||
*/
|
||||
free(data->MODEL_STRUCTURE);
|
||||
}
|
||||
|
||||
free(data->MODEL_STRUCTURE);
|
||||
if (data->COLUMNS != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->COLUMN_COUNT; ++i) {
|
||||
free_DataMapperColumn(&data->COLUMNS[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
if (data->COLUMNS != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->COLUMN_COUNT; ++i) {
|
||||
free_DataMapperColumn(&data->COLUMNS[i]);
|
||||
}
|
||||
*/
|
||||
free(data->COLUMNS);
|
||||
}
|
||||
|
||||
free(data->COLUMNS);
|
||||
if (data->OWNS_ONE != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->OWNS_ONE_COUNT; ++i) {
|
||||
free_TableRelation(&data->OWNS_ONE[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
if (data->OWNS_ONE != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->OWNS_ONE_COUNT; ++i) {
|
||||
free_TableRelation(&data->OWNS_ONE[i]);
|
||||
}
|
||||
*/
|
||||
free(data->OWNS_ONE);
|
||||
}
|
||||
|
||||
free(data->OWNS_ONE);
|
||||
if (data->HAS_MANY != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->HAS_MANY_COUNT; ++i) {
|
||||
free_TableRelation(&data->HAS_MANY[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
if (data->HAS_MANY != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->HAS_MANY_COUNT; ++i) {
|
||||
free_TableRelation(&data->HAS_MANY[i]);
|
||||
}
|
||||
*/
|
||||
free(data->HAS_MANY);
|
||||
}
|
||||
|
||||
free(data->HAS_MANY);
|
||||
if (data->BELONGS_TO != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->BELONGS_TO_COUNT; ++i) {
|
||||
free_TableRelation(&data->BELONGS_TO[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
if (data->BELONGS_TO != NULL) {
|
||||
/* not neccessary
|
||||
for (i = 0; i < data->BELONGS_TO_COUNT; ++i) {
|
||||
free_TableRelation(&data->BELONGS_TO[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
free(data->BELONGS_TO);
|
||||
}
|
||||
free(data->BELONGS_TO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,96 +12,94 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../Connection/ConnectionAbstract.h"
|
||||
#include "DataMapperTypes.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
struct MapperAbstract {
|
||||
const DataStorage::Database::MapperData *mapper = NULL;
|
||||
struct MapperAbstract {
|
||||
const DataStorage::Database::MapperData *mapper = NULL;
|
||||
|
||||
const DataStorage::Database::ConnectionAbstract *db = NULL;
|
||||
const DataStorage::Database::ConnectionAbstract *db = NULL;
|
||||
|
||||
DataStorage::Database::MapperType type = DataStorage::Database::MapperType::MAPPER_DEFAULT;
|
||||
DataStorage::Database::MapperType type = DataStorage::Database::MapperType::MAPPER_DEFAULT;
|
||||
|
||||
int MEMBERS = 0;
|
||||
int MEMBERS = 0;
|
||||
|
||||
int COLUMN_COUNT = 0;
|
||||
int COLUMN_COUNT = 0;
|
||||
|
||||
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
|
||||
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
|
||||
|
||||
char *PRIMARYFIELD = NULL;
|
||||
char *PRIMARYFIELD = NULL;
|
||||
|
||||
bool AUTOINCREMENT = true;
|
||||
bool AUTOINCREMENT = true;
|
||||
|
||||
char *CREATE_AT = NULL;
|
||||
char *CREATE_AT = NULL;
|
||||
|
||||
char *TABLE = NULL;
|
||||
char *TABLE = NULL;
|
||||
|
||||
char *PARENT = NULL;
|
||||
char *PARENT = NULL;
|
||||
|
||||
char *MODEL = NULL;
|
||||
char *MODEL = NULL;
|
||||
|
||||
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
|
||||
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
|
||||
|
||||
DataStorage::Database::TableRelation *HAS_MANY = NULL;
|
||||
DataStorage::Database::TableRelation *HAS_MANY = NULL;
|
||||
|
||||
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
|
||||
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
|
||||
|
||||
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
|
||||
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
|
||||
|
||||
void *address(uintptr_t objPos, char *name)
|
||||
{
|
||||
uintptr_t pos = objPos;
|
||||
for (int i = 0; i < this->MEMBERS; ++i) {
|
||||
if (strcmp(this->MODEL_STRUCTURE[i].name, name) == 0) {
|
||||
return (void *) pos;
|
||||
}
|
||||
|
||||
pos += this->MODEL_STRUCTURE[i].size;
|
||||
void *address(uintptr_t objPos, char *name)
|
||||
{
|
||||
uintptr_t pos = objPos;
|
||||
for (int i = 0; i < this->MEMBERS; ++i) {
|
||||
if (strcmp(this->MODEL_STRUCTURE[i].name, name) == 0) {
|
||||
return (void *) pos;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
pos += this->MODEL_STRUCTURE[i].size;
|
||||
}
|
||||
|
||||
DataMapperColumn *findByColumnName(char *column)
|
||||
{
|
||||
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
|
||||
if (strcmp(this->COLUMNS[i].name, column) == 0) {
|
||||
return &this->COLUMNS[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DataMapperColumn *findByColumnName(char *column)
|
||||
{
|
||||
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
|
||||
if (strcmp(this->COLUMNS[i].name, column) == 0) {
|
||||
return &this->COLUMNS[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DataMapperColumn *findByMemberName(char *member)
|
||||
{
|
||||
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
|
||||
if (strcmp(this->COLUMNS[i].internal, member) == 0) {
|
||||
return &this->COLUMNS[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DataMapperColumn *findByMemberName(char *member)
|
||||
{
|
||||
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
|
||||
if (strcmp(this->COLUMNS[i].internal, member) == 0) {
|
||||
return &this->COLUMNS[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MapperAbstract *where(
|
||||
char *member,
|
||||
void *value,
|
||||
int valueType,
|
||||
const char *logic = "=",
|
||||
const char *connector = "AND"
|
||||
) {
|
||||
return this;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void *execute(void *options = NULL);
|
||||
};
|
||||
}
|
||||
MapperAbstract *where(
|
||||
char *member,
|
||||
void *value,
|
||||
int valueType,
|
||||
const char *logic = "=",
|
||||
const char *connector = "AND"
|
||||
) {
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void *execute(void *options = NULL);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,54 +17,51 @@
|
|||
#include "DataMapperFactory.h"
|
||||
#include "MapperAbstract.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
{
|
||||
struct ReadMapper : MapperAbstract {
|
||||
ReadMapper *get()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
struct ReadMapper : MapperAbstract {
|
||||
ReadMapper *get()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
ReadMapper *getAll()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
ReadMapper *getAll()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void *execute(void *options = NULL)
|
||||
{
|
||||
switch(this->type) {
|
||||
case DataStorage::Database::MapperType::MAPPER_GET:
|
||||
return this->executeGet(options);
|
||||
case DataStorage::Database::MapperType::MAPPER_GET_RAW:
|
||||
return this->executeGetRaw(options);
|
||||
case DataStorage::Database::MapperType::MAPPER_GET_ALL:
|
||||
return this->executeGetAll(options);
|
||||
default:
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
void *execute(void *options = NULL)
|
||||
{
|
||||
switch(this->type) {
|
||||
case DataStorage::Database::MapperType::MAPPER_GET:
|
||||
return this->executeGet(options);
|
||||
case DataStorage::Database::MapperType::MAPPER_GET_RAW:
|
||||
return this->executeGetRaw(options);
|
||||
case DataStorage::Database::MapperType::MAPPER_GET_ALL:
|
||||
return this->executeGetAll(options);
|
||||
default:
|
||||
return NULL;
|
||||
};
|
||||
}
|
||||
|
||||
void *executeGet(void *options)
|
||||
{
|
||||
int *primaryKeys = NULL;
|
||||
const char *memberOfPrimaryField = findByColumnName((char *) this->mapper->PRIMARYFIELD)->internal;
|
||||
void *executeGet(void *options)
|
||||
{
|
||||
int *primaryKeys = NULL;
|
||||
const char *memberOfPrimaryField = findByColumnName((char *) this->mapper->PRIMARYFIELD)->internal;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *executeGetRaw(void *options)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void *executeGetRaw(void *options)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *executeGetAll(void *options)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
}
|
||||
void *executeGetAll(void *options)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,48 +13,45 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *type;
|
||||
void *def;
|
||||
bool is_nullable = true;
|
||||
bool is_primary = false;
|
||||
bool is_unique = false;
|
||||
bool autoincrement = false;
|
||||
char *foreignTable;
|
||||
char *foreignKey;
|
||||
} DbField;
|
||||
|
||||
void free_DbField(DbField *field)
|
||||
{
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *type;
|
||||
void *def;
|
||||
bool is_nullable = true;
|
||||
bool is_primary = false;
|
||||
bool is_unique = false;
|
||||
bool autoincrement = false;
|
||||
char *foreignTable;
|
||||
char *foreignKey;
|
||||
} DbField;
|
||||
if (field->name != NULL) {
|
||||
free(field->name);
|
||||
field->name = NULL;
|
||||
}
|
||||
|
||||
void free_DbField(DbField *field)
|
||||
{
|
||||
if (field->name != NULL) {
|
||||
free(field->name);
|
||||
field->name = NULL;
|
||||
}
|
||||
if (field->type != NULL) {
|
||||
free(field->type);
|
||||
field->type = NULL;
|
||||
}
|
||||
|
||||
if (field->type != NULL) {
|
||||
free(field->type);
|
||||
field->type = NULL;
|
||||
}
|
||||
if (field->def != NULL) {
|
||||
free(field->def);
|
||||
field->def = NULL;
|
||||
}
|
||||
|
||||
if (field->def != NULL) {
|
||||
free(field->def);
|
||||
field->def = NULL;
|
||||
}
|
||||
if (field->foreignTable != NULL) {
|
||||
free(field->foreignTable);
|
||||
field->foreignTable = NULL;
|
||||
}
|
||||
|
||||
if (field->foreignTable != NULL) {
|
||||
free(field->foreignTable);
|
||||
field->foreignTable = NULL;
|
||||
}
|
||||
|
||||
if (field->foreignKey != NULL) {
|
||||
free(field->foreignKey);
|
||||
field->foreignKey = NULL;
|
||||
}
|
||||
if (field->foreignKey != NULL) {
|
||||
free(field->foreignKey);
|
||||
field->foreignKey = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,31 +15,28 @@
|
|||
|
||||
#include "DbField.h"
|
||||
|
||||
namespace DataStorage
|
||||
namespace DataStorage::Database
|
||||
{
|
||||
namespace Database
|
||||
typedef struct {
|
||||
char *name;
|
||||
DbField *fields;
|
||||
size_t field_size = 0;
|
||||
} DbSchema;
|
||||
|
||||
void free_DbSchema(DbSchema *schema)
|
||||
{
|
||||
typedef struct {
|
||||
char *name;
|
||||
DbField *fields;
|
||||
size_t field_size = 0;
|
||||
} DbSchema;
|
||||
if (schema->name != NULL) {
|
||||
free(schema->name);
|
||||
schema->name = NULL;
|
||||
}
|
||||
|
||||
void free_DbSchema(DbSchema *schema)
|
||||
{
|
||||
if (schema->name != NULL) {
|
||||
free(schema->name);
|
||||
schema->name = NULL;
|
||||
if (schema->fields != NULL) {
|
||||
for (int i = 0; i < schema->field_size; ++i) {
|
||||
free_DbField(&schema->fields[i]);
|
||||
}
|
||||
|
||||
if (schema->fields != NULL) {
|
||||
for (int i = 0; i < schema->field_size; ++i) {
|
||||
free_DbField(&schema->fields[i]);
|
||||
}
|
||||
|
||||
free(schema->fields);
|
||||
schema->fields = NULL;
|
||||
}
|
||||
free(schema->fields);
|
||||
schema->fields = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#define HASH_MD5_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc1321
|
||||
|
||||
|
|
@ -37,7 +39,7 @@ namespace Hash {
|
|||
uint32_t a, b, c, d;
|
||||
uint32_t aa, bb, cc, dd;
|
||||
|
||||
ptr = data;
|
||||
ptr = (const unsigned char *) data;
|
||||
|
||||
a = ctx->a;
|
||||
b = ctx->b;
|
||||
|
|
|
|||
968
Hash/MeowHash.h
968
Hash/MeowHash.h
File diff suppressed because it is too large
Load Diff
|
|
@ -200,7 +200,7 @@ void sha_256_write(struct Sha_256 *sha_256, const void *data, size_t len)
|
|||
{
|
||||
sha_256->total_len += len;
|
||||
|
||||
const uint8_t *p = data;
|
||||
const uint8_t *p = (uint8_t *) data;
|
||||
|
||||
while (len > 0) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -14,67 +14,64 @@
|
|||
#include <opencv2/opencv.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Image
|
||||
namespace Image::BillDetection
|
||||
{
|
||||
namespace BillDetection
|
||||
cv::Mat highlightBill(cv::Mat in)
|
||||
{
|
||||
cv::Mat highlightBill(cv::Mat in)
|
||||
{
|
||||
cv::Mat gray;
|
||||
cv::cvtColor(in, gray, cv::COLOR_BGR2GRAY);
|
||||
cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0);
|
||||
cv::Mat gray;
|
||||
cv::cvtColor(in, gray, cv::COLOR_BGR2GRAY);
|
||||
cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0);
|
||||
|
||||
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9, 9));
|
||||
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9, 9));
|
||||
|
||||
cv::Mat dilated;
|
||||
cv::dilate(gray, dilated, kernel);
|
||||
cv::Mat dilated;
|
||||
cv::dilate(gray, dilated, kernel);
|
||||
|
||||
cv::Mat edges;
|
||||
cv::Canny(dilated, edges, 84, 3);
|
||||
cv::Mat edges;
|
||||
cv::Canny(dilated, edges, 84, 3);
|
||||
|
||||
std::vector<cv::Vec4i> lines;
|
||||
lines.clear();
|
||||
std::vector<cv::Vec4i> lines;
|
||||
lines.clear();
|
||||
|
||||
cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25);
|
||||
cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25);
|
||||
|
||||
std::vector<cv::Vec4i>::iterator it = lines.begin();
|
||||
for(; it != lines.end(); ++it) {
|
||||
cv::Vec4i l = *it;
|
||||
cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8);
|
||||
}
|
||||
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_KCOS);
|
||||
|
||||
std::vector<std::vector<cv::Point>> contoursCleaned;
|
||||
for (int i = 0; i < contours.size(); ++i) {
|
||||
if (cv::arcLength(contours[i], false) > 100) {
|
||||
contoursCleaned.push_back(contours[i]);
|
||||
}
|
||||
}
|
||||
std::vector<std::vector<cv::Point>> contoursArea;
|
||||
for (int i = 0; i < contoursCleaned.size(); ++i) {
|
||||
if (cv::contourArea(contoursCleaned[i]) > 10000) {
|
||||
contoursArea.push_back(contoursCleaned[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Approximate polygon
|
||||
/* Question: we probably don't want a polygon all the time?! */
|
||||
// @todo bad implementation, focus on single square
|
||||
std::vector<std::vector<cv::Point> > contoursDraw (contoursArea.size());
|
||||
for (int i = 0; i < contoursArea.size(); ++i){
|
||||
cv::approxPolyDP(cv::Mat(contoursArea[i]), contoursDraw[i], 40, true);
|
||||
}
|
||||
|
||||
cv::Mat mask = cv::Mat(in.size(), CV_8UC3, cv::Scalar(255, 255, 255));
|
||||
cv::drawContours(mask, contoursDraw, -1, cv::Scalar(0, 0, 0), cv::FILLED, 1);
|
||||
|
||||
cv::Mat out = cv::Mat::zeros(in.size(), CV_8UC3);
|
||||
cv::bitwise_or(in, mask, out);
|
||||
|
||||
return out;
|
||||
std::vector<cv::Vec4i>::iterator it = lines.begin();
|
||||
for(; it != lines.end(); ++it) {
|
||||
cv::Vec4i l = *it;
|
||||
cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8);
|
||||
}
|
||||
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_KCOS);
|
||||
|
||||
std::vector<std::vector<cv::Point>> contoursCleaned;
|
||||
for (int i = 0; i < contours.size(); ++i) {
|
||||
if (cv::arcLength(contours[i], false) > 100) {
|
||||
contoursCleaned.push_back(contours[i]);
|
||||
}
|
||||
}
|
||||
std::vector<std::vector<cv::Point>> contoursArea;
|
||||
for (int i = 0; i < contoursCleaned.size(); ++i) {
|
||||
if (cv::contourArea(contoursCleaned[i]) > 10000) {
|
||||
contoursArea.push_back(contoursCleaned[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Approximate polygon
|
||||
/* Question: we probably don't want a polygon all the time?! */
|
||||
// @todo bad implementation, focus on single square
|
||||
std::vector<std::vector<cv::Point> > contoursDraw (contoursArea.size());
|
||||
for (int i = 0; i < contoursArea.size(); ++i){
|
||||
cv::approxPolyDP(cv::Mat(contoursArea[i]), contoursDraw[i], 40, true);
|
||||
}
|
||||
|
||||
cv::Mat mask = cv::Mat(in.size(), CV_8UC3, cv::Scalar(255, 255, 255));
|
||||
cv::drawContours(mask, contoursDraw, -1, cv::Scalar(0, 0, 0), cv::FILLED, 1);
|
||||
|
||||
cv::Mat out = cv::Mat::zeros(in.size(), CV_8UC3);
|
||||
cv::bitwise_or(in, mask, out);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,36 +13,23 @@
|
|||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
namespace Image
|
||||
namespace Image::ImageUtils
|
||||
{
|
||||
namespace ImageUtils
|
||||
inline
|
||||
float lightnessFromRgb(int r, int g, int b)
|
||||
{
|
||||
inline
|
||||
float lightnessFromRgb(int r, int g, int b)
|
||||
{
|
||||
float vR = r / 255.0;
|
||||
float vG = g / 255.0;
|
||||
float vB = b / 255.0;
|
||||
float vR = r / 255.0;
|
||||
float vG = g / 255.0;
|
||||
float vB = b / 255.0;
|
||||
|
||||
float lR = vR <= 0.04045 ? vR / 12.92 : pow(((vR + 0.055) / 1.055), 2.4);
|
||||
float lG = vG <= 0.04045 ? vG / 12.92 : pow(((vG + 0.055) / 1.055), 2.4);
|
||||
float lB = vB <= 0.04045 ? vB / 12.92 : pow(((vB + 0.055) / 1.055), 2.4);
|
||||
float lR = vR <= 0.04045 ? vR / 12.92 : pow(((vR + 0.055) / 1.055), 2.4);
|
||||
float lG = vG <= 0.04045 ? vG / 12.92 : pow(((vG + 0.055) / 1.055), 2.4);
|
||||
float lB = vB <= 0.04045 ? vB / 12.92 : pow(((vB + 0.055) / 1.055), 2.4);
|
||||
|
||||
float y = 0.2126 * lR + 0.7152 * lG + 0.0722 * lB;
|
||||
float lStar = y <= 216.0 / 24389.0 ? y * 24389.0 / 27.0 : pow(y, (1.0 / 3.0)) * 116.0 - 16.0;
|
||||
float y = 0.2126 * lR + 0.7152 * lG + 0.0722 * lB;
|
||||
float lStar = y <= 216.0 / 24389.0 ? y * 24389.0 / 27.0 : pow(y, (1.0 / 3.0)) * 116.0 - 16.0;
|
||||
|
||||
return lStar / 100.0;
|
||||
}
|
||||
|
||||
inline
|
||||
int rgbToInt(int r, int g, int b)
|
||||
{
|
||||
int rgb = r;
|
||||
rgb = (rgb << 8) + g;
|
||||
rgb = (rgb << 8) + b;
|
||||
|
||||
return rgb;
|
||||
}
|
||||
return lStar / 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "ImageUtils.h"
|
||||
#include "../Utils/MathUtils.h"
|
||||
|
||||
namespace Image
|
||||
namespace Image::Kernel
|
||||
{
|
||||
const float KERNEL_RIDGE_1[3][3] = {
|
||||
{0.0, -1.0, 0.0},
|
||||
|
|
@ -62,19 +62,16 @@ namespace Image
|
|||
{-1.0 / 256.0, -4.0 / 256.0, -6.0 / 256.0, -4.0 / 256.0, -1.0 / 256.0},
|
||||
};
|
||||
|
||||
namespace Kernel
|
||||
inline
|
||||
cv::Mat convolve(cv::Mat in, const float kernel[][3])
|
||||
{
|
||||
inline
|
||||
cv::Mat convolve(cv::Mat in, const float kernel[][3])
|
||||
{
|
||||
cv::Size dim = in.size();
|
||||
cv::Mat out(in.size(), in.type());
|
||||
cv::Size dim = in.size();
|
||||
cv::Mat out(in.size(), in.type());
|
||||
|
||||
cv::Mat mKernel(3, 3, CV_32F, (float *) kernel);
|
||||
cv::filter2D(in, out, -1, mKernel);
|
||||
cv::Mat mKernel(3, 3, CV_32F, (float *) kernel);
|
||||
cv::filter2D(in, out, -1, mKernel);
|
||||
|
||||
return out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
111
Image/Skew.h
111
Image/Skew.h
|
|
@ -16,77 +16,74 @@
|
|||
|
||||
#include "../Utils/MathUtils.h"
|
||||
|
||||
namespace Image
|
||||
namespace Image::Skew
|
||||
{
|
||||
namespace Skew
|
||||
cv::Mat deskewHoughLines(cv::Mat in, int maxDegree = 45)
|
||||
{
|
||||
cv::Mat deskewHoughLines(cv::Mat in, int maxDegree = 45)
|
||||
{
|
||||
cv::Size dim = in.size();
|
||||
cv::Size dim = in.size();
|
||||
|
||||
cv::Mat inv;
|
||||
cv::cvtColor(in, inv, cv::COLOR_BGR2GRAY);
|
||||
cv::threshold(inv, inv, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
|
||||
cv::Mat inv;
|
||||
cv::cvtColor(in, inv, cv::COLOR_BGR2GRAY);
|
||||
cv::threshold(inv, inv, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
|
||||
|
||||
std::vector<cv::Vec4i> lines;
|
||||
cv::HoughLinesP(inv, lines, 1.0, OMS_PI / 180, 200, dim.width / 12, dim.width / 150);
|
||||
std::vector<cv::Vec4i> lines;
|
||||
cv::HoughLinesP(inv, lines, 1.0, OMS_PI / 180, 200, dim.width / 12, dim.width / 150);
|
||||
|
||||
int imageOrientation = 0; // > 0 -> image is horizontal
|
||||
int imageOrientation = 0; // > 0 -> image is horizontal
|
||||
|
||||
std::vector<float> tmpAngles;
|
||||
for (int i = 0; i < lines.size(); ++i) {
|
||||
float angle = atan2(lines[i][3] - lines[i][1], lines[i][2] - lines[i][0]);
|
||||
tmpAngles.push_back(angle);
|
||||
std::vector<float> tmpAngles;
|
||||
for (int i = 0; i < lines.size(); ++i) {
|
||||
float angle = atan2(lines[i][3] - lines[i][1], lines[i][2] - lines[i][0]);
|
||||
tmpAngles.push_back(angle);
|
||||
|
||||
imageOrientation += oms_abs(angle) > OMS_PI / 4 ? 1 : -1;
|
||||
}
|
||||
imageOrientation += oms_abs(angle) > OMS_PI / 4 ? 1 : -1;
|
||||
}
|
||||
|
||||
std::vector<float> angles;
|
||||
for (int i = 0; i < tmpAngles.size(); ++i) {
|
||||
if (imageOrientation > 0) {
|
||||
if (oms_deg2rad(90 - maxDegree) < oms_abs(tmpAngles[i]) && oms_abs(tmpAngles[i]) < oms_deg2rad(90 + maxDegree)) {
|
||||
angles.push_back(tmpAngles[i]);
|
||||
}
|
||||
} else {
|
||||
if (oms_abs(tmpAngles[i]) < oms_deg2rad(maxDegree)) {
|
||||
angles.push_back(tmpAngles[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (angles.size() < 5) {
|
||||
return in;
|
||||
}
|
||||
|
||||
float median = 0.0;
|
||||
for (int i = 0; i < angles.size(); ++i) {
|
||||
median += angles[i];
|
||||
}
|
||||
|
||||
float angleDeg = oms_rad2deg(median / angles.size());
|
||||
|
||||
cv::Mat orientFix;
|
||||
std::vector<float> angles;
|
||||
for (int i = 0; i < tmpAngles.size(); ++i) {
|
||||
if (imageOrientation > 0) {
|
||||
if (angleDeg < 0) {
|
||||
cv::rotate(in, orientFix, cv::ROTATE_90_CLOCKWISE);
|
||||
angleDeg += 90.0;
|
||||
} else if (angleDeg > 0) {
|
||||
cv::rotate(in, orientFix, cv::ROTATE_90_COUNTERCLOCKWISE);
|
||||
angleDeg -= 90.0;
|
||||
} else {
|
||||
orientFix = in;
|
||||
if (oms_deg2rad(90 - maxDegree) < oms_abs(tmpAngles[i]) && oms_abs(tmpAngles[i]) < oms_deg2rad(90 + maxDegree)) {
|
||||
angles.push_back(tmpAngles[i]);
|
||||
}
|
||||
} else {
|
||||
if (oms_abs(tmpAngles[i]) < oms_deg2rad(maxDegree)) {
|
||||
angles.push_back(tmpAngles[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (angles.size() < 5) {
|
||||
return in;
|
||||
}
|
||||
|
||||
float median = 0.0;
|
||||
for (int i = 0; i < angles.size(); ++i) {
|
||||
median += angles[i];
|
||||
}
|
||||
|
||||
float angleDeg = oms_rad2deg(median / angles.size());
|
||||
|
||||
cv::Mat orientFix;
|
||||
if (imageOrientation > 0) {
|
||||
if (angleDeg < 0) {
|
||||
cv::rotate(in, orientFix, cv::ROTATE_90_CLOCKWISE);
|
||||
angleDeg += 90.0;
|
||||
} else if (angleDeg > 0) {
|
||||
cv::rotate(in, orientFix, cv::ROTATE_90_COUNTERCLOCKWISE);
|
||||
angleDeg -= 90.0;
|
||||
} else {
|
||||
orientFix = in;
|
||||
}
|
||||
|
||||
cv::Mat rot = cv::getRotationMatrix2D(cv::Point2f(dim.width / 2, dim.height / 2), angleDeg, 1.0);
|
||||
|
||||
cv::Mat out;
|
||||
cv::warpAffine(orientFix, out, rot, dim, cv::INTER_LINEAR, cv::BORDER_REPLICATE);
|
||||
|
||||
return out;
|
||||
} else {
|
||||
orientFix = in;
|
||||
}
|
||||
|
||||
cv::Mat rot = cv::getRotationMatrix2D(cv::Point2f(dim.width / 2, dim.height / 2), angleDeg, 1.0);
|
||||
|
||||
cv::Mat out;
|
||||
cv::warpAffine(orientFix, out, rot, dim, cv::INTER_LINEAR, cv::BORDER_REPLICATE);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,65 +16,62 @@
|
|||
#include "ImageUtils.h"
|
||||
#include "../Utils/MathUtils.h"
|
||||
|
||||
namespace Image
|
||||
namespace Image::Thresholding
|
||||
{
|
||||
namespace Thresholding
|
||||
cv::Mat integralThresholding(cv::Mat in)
|
||||
{
|
||||
cv::Mat integralThresholding(cv::Mat in)
|
||||
{
|
||||
cv::Size dim = in.size();
|
||||
cv::Mat out(dim, in.type());
|
||||
cv::Size dim = in.size();
|
||||
cv::Mat out(dim, in.type());
|
||||
|
||||
float *intImg = (float *) malloc(dim.width * dim.height * sizeof(float));
|
||||
float sum;
|
||||
float *intImg = (float *) malloc(dim.width * dim.height * sizeof(float));
|
||||
float sum;
|
||||
|
||||
cv::Vec3b bgr;
|
||||
for (int i = 0; i < dim.width; ++i) {
|
||||
sum = 0.0;
|
||||
cv::Vec3b bgr;
|
||||
for (int i = 0; i < dim.width; ++i) {
|
||||
sum = 0.0;
|
||||
|
||||
for (int j = 0; j < dim.height; ++j) {
|
||||
bgr = in.at<cv::Vec3b>(j, i);
|
||||
sum += Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
|
||||
for (int j = 0; j < dim.height; ++j) {
|
||||
bgr = in.at<cv::Vec3b>(j, i);
|
||||
sum += Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
|
||||
|
||||
intImg[i * j] = i == 0 ? sum : intImg[(i - 1) * j] + sum;
|
||||
}
|
||||
intImg[i * j] = i == 0 ? sum : intImg[(i - 1) * j] + sum;
|
||||
}
|
||||
|
||||
int s = dim.width / 96.0;
|
||||
int t = 30;
|
||||
|
||||
int x1, x2;
|
||||
int y1, y2;
|
||||
int count;
|
||||
float brightness;
|
||||
int color;
|
||||
|
||||
for (int i = 0; i < dim.width; ++i) {
|
||||
for (int j = 0; j < dim.height; ++j) {
|
||||
x1 = oms_max(1, i - s / 2.0);
|
||||
x2 = oms_min(i + s / 2.0, dim.width - 1);
|
||||
|
||||
y1 = oms_max(1, j - s / 2.0);
|
||||
y2 = oms_min(j + s / 2.0, dim.height - 1);
|
||||
|
||||
count = (x2 - x1) * (y2 - y1);
|
||||
sum = intImg[x2 * y2] - intImg[x2 * (y1 - 1)] - intImg[(x1 - 1) * y2] + intImg[(x1 - 1) * (y1 - 1)];
|
||||
|
||||
bgr = in.at<cv::Vec3b>(j, i);
|
||||
brightness = Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
|
||||
|
||||
color = brightness * count <= (sum * (100.0 - t) / 100.0) && brightness < 0.95 ? 0 : 255;
|
||||
|
||||
out.at<cv::Vec3b>(j, i)[0] = color;
|
||||
out.at<cv::Vec3b>(j, i)[1] = color;
|
||||
out.at<cv::Vec3b>(j, i)[2] = color;
|
||||
}
|
||||
}
|
||||
|
||||
free(intImg);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int s = dim.width / 96.0;
|
||||
int t = 30;
|
||||
|
||||
int x1, x2;
|
||||
int y1, y2;
|
||||
int count;
|
||||
float brightness;
|
||||
int color;
|
||||
|
||||
for (int i = 0; i < dim.width; ++i) {
|
||||
for (int j = 0; j < dim.height; ++j) {
|
||||
x1 = oms_max(1, i - s / 2.0);
|
||||
x2 = oms_min(i + s / 2.0, dim.width - 1);
|
||||
|
||||
y1 = oms_max(1, j - s / 2.0);
|
||||
y2 = oms_min(j + s / 2.0, dim.height - 1);
|
||||
|
||||
count = (x2 - x1) * (y2 - y1);
|
||||
sum = intImg[x2 * y2] - intImg[x2 * (y1 - 1)] - intImg[(x1 - 1) * y2] + intImg[(x1 - 1) * (y1 - 1)];
|
||||
|
||||
bgr = in.at<cv::Vec3b>(j, i);
|
||||
brightness = Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
|
||||
|
||||
color = brightness * count <= (sum * (100.0 - t) / 100.0) && brightness < 0.95 ? 0 : 255;
|
||||
|
||||
out.at<cv::Vec3b>(j, i)[0] = color;
|
||||
out.at<cv::Vec3b>(j, i)[1] = color;
|
||||
out.at<cv::Vec3b>(j, i)[2] = color;
|
||||
}
|
||||
}
|
||||
|
||||
free(intImg);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,205 +16,202 @@
|
|||
|
||||
#include "../Hash/MeowHash.h"
|
||||
|
||||
namespace Stdlib
|
||||
namespace Stdlib::HashTable
|
||||
{
|
||||
namespace HashTable
|
||||
typedef struct {
|
||||
const char *key;
|
||||
void *value;
|
||||
} entry;
|
||||
|
||||
struct ht {
|
||||
bool is_fixed = false;
|
||||
entry *entries;
|
||||
size_t max;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *key;
|
||||
void *value;
|
||||
|
||||
ht *table;
|
||||
size_t index;
|
||||
} it;
|
||||
|
||||
inline
|
||||
unsigned long long hash_key(const char *key)
|
||||
{
|
||||
typedef struct {
|
||||
const char *key;
|
||||
void *value;
|
||||
} entry;
|
||||
|
||||
struct ht {
|
||||
bool is_fixed = false;
|
||||
entry *entries;
|
||||
size_t max;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *key;
|
||||
void *value;
|
||||
|
||||
ht *table;
|
||||
size_t index;
|
||||
} it;
|
||||
|
||||
inline
|
||||
unsigned long long hash_key(const char *key)
|
||||
{
|
||||
return (unsigned long long) MeowU64From(
|
||||
Hash::Meow::MeowHash(Hash::Meow::MeowDefaultSeed,
|
||||
strlen(key),
|
||||
(void *) key),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
ht *create_table(int max = 0, bool is_fixed = false)
|
||||
{
|
||||
ht *table = (ht *) malloc(sizeof(ht));
|
||||
if (table == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table->size = 0;
|
||||
table->max = max == 0 ? 16 : max;
|
||||
table->is_fixed = is_fixed;
|
||||
|
||||
table->entries = (entry *) calloc(table->max, sizeof(entry));
|
||||
if (table->entries == NULL) {
|
||||
free(table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void *get_entry(ht *table, const char *key)
|
||||
{
|
||||
unsigned long long hash = hash_key(key);
|
||||
size_t index = (size_t) (hash & (unsigned long long)(table->max - 1));
|
||||
|
||||
while (table->entries[index].key != NULL) {
|
||||
if (strcmp(key, table->entries[index].key) == 0) {
|
||||
return table->entries[index].value;
|
||||
}
|
||||
|
||||
++index;
|
||||
if (index >= table->max) {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
return (unsigned long long) MeowU64From(
|
||||
Hash::Meow::MeowHash(Hash::Meow::MeowDefaultSeed,
|
||||
strlen(key),
|
||||
(void *) key),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
ht *create_table(int max = 0, bool is_fixed = false)
|
||||
{
|
||||
ht *table = (ht *) malloc(sizeof(ht));
|
||||
if (table == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *_set_entry(entry *entries, size_t max, const char *key, void *value, size_t *size)
|
||||
{
|
||||
unsigned long long hash = hash_key(key);
|
||||
size_t index = (size_t) (hash & (unsigned long long)(max - 1));
|
||||
table->size = 0;
|
||||
table->max = max == 0 ? 16 : max;
|
||||
table->is_fixed = is_fixed;
|
||||
|
||||
while (entries[index].key != NULL) {
|
||||
if (strcmp(key, entries[index].key) == 0) {
|
||||
entries[index].value = value;
|
||||
|
||||
return entries[index].key;
|
||||
}
|
||||
|
||||
++index;
|
||||
if (index >= max) {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (size != NULL) {
|
||||
#ifdef _WIN32
|
||||
key = _strdup(key);
|
||||
#else
|
||||
key = strdup(key);
|
||||
#endif
|
||||
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
++(*size);
|
||||
}
|
||||
|
||||
entries[index].key = (char *) key;
|
||||
entries[index].value = value;
|
||||
|
||||
return key;
|
||||
table->entries = (entry *) calloc(table->max, sizeof(entry));
|
||||
if (table->entries == NULL) {
|
||||
free(table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool expand_table(ht *table)
|
||||
{
|
||||
size_t new_max = table->max * 2;
|
||||
if (new_max < table->max) {
|
||||
return false;
|
||||
return table;
|
||||
}
|
||||
|
||||
void *get_entry(ht *table, const char *key)
|
||||
{
|
||||
unsigned long long hash = hash_key(key);
|
||||
size_t index = (size_t) (hash & (unsigned long long)(table->max - 1));
|
||||
|
||||
while (table->entries[index].key != NULL) {
|
||||
if (strcmp(key, table->entries[index].key) == 0) {
|
||||
return table->entries[index].value;
|
||||
}
|
||||
|
||||
entry *new_entries = (entry *) calloc(new_max, sizeof(entry));
|
||||
if (new_entries == NULL) {
|
||||
return false;
|
||||
++index;
|
||||
if (index >= table->max) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < table->max; ++i) {
|
||||
entry tmp = table->entries[i];
|
||||
if (tmp.key != NULL) {
|
||||
_set_entry(new_entries, new_max, tmp.key, tmp.value, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
free(table->entries);
|
||||
table->entries = new_entries;
|
||||
table->max = new_max;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *set_entry(ht *table, const char *key, void *value)
|
||||
{
|
||||
if (value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *_set_entry(entry *entries, size_t max, const char *key, void *value, size_t *size)
|
||||
{
|
||||
unsigned long long hash = hash_key(key);
|
||||
size_t index = (size_t) (hash & (unsigned long long)(max - 1));
|
||||
|
||||
while (entries[index].key != NULL) {
|
||||
if (strcmp(key, entries[index].key) == 0) {
|
||||
entries[index].value = value;
|
||||
|
||||
return entries[index].key;
|
||||
}
|
||||
|
||||
++index;
|
||||
if (index >= max) {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (size != NULL) {
|
||||
#ifdef _WIN32
|
||||
key = _strdup(key);
|
||||
#else
|
||||
key = strdup(key);
|
||||
#endif
|
||||
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (table->is_fixed && table->size == table->max) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!table->is_fixed && table->size >= table->max / 2) {
|
||||
if (!expand_table(table)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return _set_entry(table->entries, table->max, key, value, &table->size);
|
||||
++(*size);
|
||||
}
|
||||
|
||||
it table_iterator(ht *table)
|
||||
{
|
||||
it it;
|
||||
it.table = table;
|
||||
it.index = 0;
|
||||
entries[index].key = (char *) key;
|
||||
entries[index].value = value;
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
bool next(it *it)
|
||||
{
|
||||
ht *table = it->table;
|
||||
while (it->index < table->max) {
|
||||
size_t i = it->index;
|
||||
++(it->index);
|
||||
|
||||
if (table->entries[i].key != NULL) {
|
||||
entry tmp = table->entries[i];
|
||||
it->key = tmp.key;
|
||||
it->value = tmp.value;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
bool expand_table(ht *table)
|
||||
{
|
||||
size_t new_max = table->max * 2;
|
||||
if (new_max < table->max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void free_table(ht *table)
|
||||
{
|
||||
if (!table || !table->entries) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < table->max; ++i) {
|
||||
if (table->entries[i].key) {
|
||||
free((void *) table->entries[i].key);
|
||||
}
|
||||
}
|
||||
|
||||
free(table->entries);
|
||||
entry *new_entries = (entry *) calloc(new_max, sizeof(entry));
|
||||
if (new_entries == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < table->max; ++i) {
|
||||
entry tmp = table->entries[i];
|
||||
if (tmp.key != NULL) {
|
||||
_set_entry(new_entries, new_max, tmp.key, tmp.value, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
free(table->entries);
|
||||
table->entries = new_entries;
|
||||
table->max = new_max;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *set_entry(ht *table, const char *key, void *value)
|
||||
{
|
||||
if (value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (table->is_fixed && table->size == table->max) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!table->is_fixed && table->size >= table->max / 2) {
|
||||
if (!expand_table(table)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return _set_entry(table->entries, table->max, key, value, &table->size);
|
||||
}
|
||||
|
||||
it table_iterator(ht *table)
|
||||
{
|
||||
it it;
|
||||
it.table = table;
|
||||
it.index = 0;
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
bool next(it *it)
|
||||
{
|
||||
ht *table = it->table;
|
||||
while (it->index < table->max) {
|
||||
size_t i = it->index;
|
||||
++(it->index);
|
||||
|
||||
if (table->entries[i].key != NULL) {
|
||||
entry tmp = table->entries[i];
|
||||
it->key = tmp.key;
|
||||
it->value = tmp.value;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void free_table(ht *table)
|
||||
{
|
||||
if (!table || !table->entries) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < table->max; ++i) {
|
||||
if (table->entries[i].key) {
|
||||
free((void *) table->entries[i].key);
|
||||
}
|
||||
}
|
||||
|
||||
free(table->entries);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,7 @@ namespace Utils
|
|||
|
||||
if (pos != NULL) {
|
||||
memcpy(dir, arg, (pos - arg) * sizeof(char));
|
||||
|
||||
chdir(dir);
|
||||
|
||||
free(dir);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,48 +13,45 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace Utils
|
||||
namespace Utils::ArraySort
|
||||
{
|
||||
namespace ArraySort
|
||||
inline
|
||||
void reverse_int(int64_t *arr, size_t size)
|
||||
{
|
||||
inline
|
||||
void reverse_int(int64_t *arr, size_t size)
|
||||
{
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
int64_t tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
int64_t tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void reverse_float(float *arr, size_t size)
|
||||
{
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
float tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
inline
|
||||
void reverse_float(float *arr, size_t size)
|
||||
{
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
float tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void reverse_double(double *arr, size_t size)
|
||||
{
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
double tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
inline
|
||||
void reverse_double(double *arr, size_t size)
|
||||
{
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
double tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void reverse_char(char **arr, size_t size)
|
||||
{
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
char* tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
inline
|
||||
void reverse_char(char **arr, size_t size)
|
||||
{
|
||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||
char* tmp = arr[low];
|
||||
arr[low] = arr[high];
|
||||
arr[high] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,195 +16,192 @@
|
|||
|
||||
#include "StringUtils.h"
|
||||
|
||||
namespace Utils
|
||||
namespace Utils::ArrayUtils
|
||||
{
|
||||
namespace ArrayUtils
|
||||
inline
|
||||
char* get_arg(const char *id, char **argv, size_t size)
|
||||
{
|
||||
inline
|
||||
char* get_arg(const char *id, char **argv, size_t size)
|
||||
{
|
||||
if (Utils::StringUtils::is_number(id)) {
|
||||
return argv[atoi(id)];
|
||||
}
|
||||
if (Utils::StringUtils::is_number(id)) {
|
||||
return argv[atoi(id)];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size - 1; ++i) {
|
||||
if (strcmp(id, argv[i]) == 0) {
|
||||
return i + 1 >= size ? NULL : argv[i + 1];
|
||||
}
|
||||
for (size_t i = 0; i < size - 1; ++i) {
|
||||
if (strcmp(id, argv[i]) == 0) {
|
||||
return i + 1 >= size ? NULL : argv[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
bool has_arg(const char *id, char **argv, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (strcmp(id, argv[i]) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline
|
||||
double array_sum_double(double *array, size_t size)
|
||||
{
|
||||
double sum = 0.0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
sum += array[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
inline
|
||||
float array_sum_float(float *array, size_t size)
|
||||
{
|
||||
float sum = 0.0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
sum += array[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
inline
|
||||
int64_t array_sum_int(int64_t *array, size_t size)
|
||||
{
|
||||
int64_t sum = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
sum += array[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_string(const char *element, const char **array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (strcmp(element, array[i]) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_double(double element, double *array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (array[i] == element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_float(float element, float *array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (array[i] == element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_int(int64_t element, int64_t *array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (array[i] == element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline
|
||||
double* merge_arrays_double(double* array1, size_t size1, double* array2, size_t size2)
|
||||
{
|
||||
double* merged = (double*) malloc((size1 + size2) * sizeof(double));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
bool has_arg(const char *id, char **argv, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (strcmp(id, argv[i]) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = array1[i];
|
||||
}
|
||||
|
||||
inline
|
||||
double array_sum_double(double *array, size_t size)
|
||||
{
|
||||
double sum = 0.0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
sum += array[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[size1 + i] = array2[i];
|
||||
}
|
||||
|
||||
inline
|
||||
float array_sum_float(float *array, size_t size)
|
||||
{
|
||||
float sum = 0.0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
sum += array[i];
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
return sum;
|
||||
inline
|
||||
float* merge_arrays_float(float* array1, size_t size1, float* array2, size_t size2)
|
||||
{
|
||||
float* merged = (float*) malloc((size1 + size2) * sizeof(float));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
int64_t array_sum_int(int64_t *array, size_t size)
|
||||
{
|
||||
int64_t sum = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
sum += array[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = array1[i];
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_string(const char *element, const char **array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (strcmp(element, array[i]) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[size1 + i] = array2[i];
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_double(double element, double *array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (array[i] == element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
return -1;
|
||||
inline
|
||||
int64_t* merge_arrays_int(int64_t* array1, size_t size1, int64_t* array2, size_t size2)
|
||||
{
|
||||
int64_t* merged = (int64_t*) malloc((size1 + size2) * sizeof(int64_t));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_float(float element, float *array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (array[i] == element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = array1[i];
|
||||
}
|
||||
|
||||
inline
|
||||
size_t find_in_array_int(int64_t element, int64_t *array, size_t size)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (array[i] == element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[size1 + i] = array2[i];
|
||||
}
|
||||
|
||||
inline
|
||||
double* merge_arrays_double(double* array1, size_t size1, double* array2, size_t size2)
|
||||
{
|
||||
double* merged = (double*) malloc((size1 + size2) * sizeof(double));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = array1[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[size1 + i] = array2[i];
|
||||
}
|
||||
|
||||
return merged;
|
||||
char** merge_arrays_char(const char** array1, size_t size1, const char** array2, size_t size2)
|
||||
{
|
||||
char** merged = (char**) malloc((size1 + size2) * sizeof(char*));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
float* merge_arrays_float(float* array1, size_t size1, float* array2, size_t size2)
|
||||
{
|
||||
float* merged = (float*) malloc((size1 + size2) * sizeof(float));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = array1[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[size1 + i] = array2[i];
|
||||
}
|
||||
|
||||
return merged;
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = (char*) malloc((strlen(array1[i]) + 1) * sizeof(char));
|
||||
strcpy(merged[i], array1[i]);
|
||||
}
|
||||
|
||||
inline
|
||||
int64_t* merge_arrays_int(int64_t* array1, size_t size1, int64_t* array2, size_t size2)
|
||||
{
|
||||
int64_t* merged = (int64_t*) malloc((size1 + size2) * sizeof(int64_t));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = array1[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[size1 + i] = array2[i];
|
||||
}
|
||||
|
||||
return merged;
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[i] = (char*) malloc((strlen(array2[i]) + 1) * sizeof(char));
|
||||
strcpy(merged[i], array2[i]);
|
||||
}
|
||||
|
||||
char** merge_arrays_char(const char** array1, size_t size1, const char** array2, size_t size2)
|
||||
{
|
||||
char** merged = (char**) malloc((size1 + size2) * sizeof(char*));
|
||||
if (merged == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size1; ++i) {
|
||||
merged[i] = (char*) malloc((strlen(arr1[i]) + 1) * sizeof(char));
|
||||
strcpy(merged[i], arr1[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size2; ++i) {
|
||||
merged[i] = (char*) malloc((strlen(arr2[i]) + 1) * sizeof(char));
|
||||
strcpy(merged[i], arr2[i]);
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
57
Utils/ColorUtils.h
Normal file
57
Utils/ColorUtils.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Karaka
|
||||
*
|
||||
* @package Utils
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 1.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
#ifndef UTILS_STRING_UTILS_H
|
||||
#define UTILS_STRING_UTILS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace Utils::ColorUtils
|
||||
{
|
||||
typedef struct {
|
||||
char r = 0;
|
||||
char g = 0;
|
||||
char b = 0;
|
||||
} RGB;
|
||||
|
||||
inline
|
||||
RGB* int_to_rgb(int rgb)
|
||||
{
|
||||
RGB* result = (RGB*) malloc(1 * sizeof(RGB));
|
||||
|
||||
result->r = rgb & 255;
|
||||
result->g = (rgb >> 8) & 255;
|
||||
result->b = (rgb >> 16) & 255;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
int rgb_to_int(RGB* rgb)
|
||||
{
|
||||
int i = (255 & rgb->r) << 16;
|
||||
i += (255 & rgb->g) << 8;
|
||||
i += (255 & rgb->b);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
int rgb_to_int(char r, char g, char b)
|
||||
{
|
||||
int i = (255 & r) << 16;
|
||||
i += (255 & g) << 8;
|
||||
i += (255 & b);
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -23,111 +23,108 @@
|
|||
|
||||
#include "OSWrapper.h"
|
||||
|
||||
namespace Utils
|
||||
namespace Utils::FileUtils
|
||||
{
|
||||
namespace FileUtils
|
||||
inline
|
||||
bool file_exists (const char *filename)
|
||||
{
|
||||
inline
|
||||
bool file_exists (const char *filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return access(filename, 0) == 0;
|
||||
#else
|
||||
struct stat buffer;
|
||||
return stat(filename, &buffer) == 0;
|
||||
#endif
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return access(filename, 0) == 0;
|
||||
#else
|
||||
struct stat buffer;
|
||||
return stat(filename, &buffer) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
time_t last_modification (const char *filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILETIME modtime;
|
||||
HANDLE h;
|
||||
inline
|
||||
time_t last_modification (const char *filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILETIME modtime;
|
||||
HANDLE h;
|
||||
|
||||
size_t nameLength = strlen(filename);
|
||||
size_t nameLength = strlen(filename);
|
||||
|
||||
wchar_t *wtext = (wchar_t *) calloc(nameLength, sizeof(char));
|
||||
mbstowcs_s(NULL, wtext, nameLength, filename, nameLength);
|
||||
LPWSTR pFilename = wtext;
|
||||
|
||||
if (!pFilename) {
|
||||
free(wtext);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
h = CreateFileW(pFilename, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
wchar_t *wtext = (wchar_t *) calloc(nameLength, sizeof(char));
|
||||
mbstowcs_s(NULL, wtext, nameLength, filename, nameLength);
|
||||
LPWSTR pFilename = wtext;
|
||||
|
||||
if (!pFilename) {
|
||||
free(wtext);
|
||||
free(pFilename);
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return (time_t) 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GetFileTime(h, NULL, NULL, &modtime) == 0) {
|
||||
return (time_t) 0;
|
||||
}
|
||||
h = CreateFileW(pFilename, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
unsigned long long seconds = ((unsigned long long) (modtime.dwHighDateTime)) << 32;
|
||||
seconds |= modtime.dwLowDateTime;
|
||||
free(wtext);
|
||||
free(pFilename);
|
||||
|
||||
return (seconds - 116444736000000000) / 10000000;
|
||||
#else
|
||||
struct stat buffer;
|
||||
stat(filename, &buffer);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return (time_t) 0;
|
||||
}
|
||||
|
||||
return (time_t) buffer.st_mtim.tv_sec;
|
||||
#endif
|
||||
if (GetFileTime(h, NULL, NULL, &modtime) == 0) {
|
||||
return (time_t) 0;
|
||||
}
|
||||
|
||||
return (time_t) 0;
|
||||
unsigned long long seconds = ((unsigned long long) (modtime.dwHighDateTime)) << 32;
|
||||
seconds |= modtime.dwLowDateTime;
|
||||
|
||||
return (seconds - 116444736000000000) / 10000000;
|
||||
#else
|
||||
struct stat buffer;
|
||||
stat(filename, &buffer);
|
||||
|
||||
return (time_t) buffer.st_mtim.tv_sec;
|
||||
#endif
|
||||
|
||||
return (time_t) 0;
|
||||
}
|
||||
|
||||
inline
|
||||
const char* file_extension (const char *filename)
|
||||
{
|
||||
char *dot = strrchr((char *) filename, '.');
|
||||
|
||||
if (!dot || dot == filename) {
|
||||
return "";
|
||||
}
|
||||
|
||||
inline
|
||||
const char* file_extension (const char *filename)
|
||||
{
|
||||
char *dot = strrchr((char *) filename, '.');
|
||||
return dot + 1;
|
||||
}
|
||||
|
||||
if (!dot || dot == filename) {
|
||||
return "";
|
||||
}
|
||||
typedef struct {
|
||||
char *content;
|
||||
int size = 0; // doesn't include null termination (same as strlen)
|
||||
} file_body;
|
||||
|
||||
return dot + 1;
|
||||
file_body read_file (const char *filename)
|
||||
{
|
||||
file_body file = {0};
|
||||
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
return file;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *content;
|
||||
int size = 0; // doesn't include null termination (same as strlen)
|
||||
} file_body;
|
||||
fseek(fp, 0, SEEK_END);
|
||||
file.size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
file_body read_file (const char *filename)
|
||||
{
|
||||
file_body file = {0};
|
||||
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
return file;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
file.size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
file.content = (char *) malloc((file.size + 1) * sizeof(char));
|
||||
if (!file.content) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
fread(file.content, file.size, 1, fp);
|
||||
file.content[file.size] = 0;
|
||||
|
||||
fclose(fp);
|
||||
file.content = (char *) malloc((file.size + 1) * sizeof(char));
|
||||
if (!file.content) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
fread(file.content, file.size, 1, fp);
|
||||
file.content[file.size] = 0;
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,30 +14,26 @@
|
|||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace Utils
|
||||
namespace Utils::Rng::StringUtils
|
||||
{
|
||||
namespace Rng
|
||||
{
|
||||
namespace StringUtils
|
||||
{
|
||||
inline
|
||||
char* generate_string(
|
||||
size_t min = 10, size_t max = 10,
|
||||
char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", int charsetLength = 62
|
||||
) {
|
||||
srand(time(0));
|
||||
inline
|
||||
char* generate_string(
|
||||
size_t min = 10, size_t max = 10,
|
||||
char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", int charsetLength = 62
|
||||
) {
|
||||
srand(time(0));
|
||||
|
||||
size_t length = (rand() % (max - min + 1)) + min;
|
||||
char *randomString = (char *) malloc(length + 1);
|
||||
size_t length = (rand() % (max - min + 1)) + min;
|
||||
char *randomString = (char *) malloc(length + 1);
|
||||
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
randomString[i] = charset[rand() % charsetLength];
|
||||
}
|
||||
|
||||
randomString[length] = '\0';
|
||||
|
||||
return randomString;
|
||||
}
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
randomString[i] = charset[rand() % charsetLength];
|
||||
}
|
||||
|
||||
randomString[length] = '\0';
|
||||
|
||||
return randomString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -17,212 +17,223 @@
|
|||
#include "MathUtils.h"
|
||||
#include "ArraySort.h"
|
||||
|
||||
namespace Utils
|
||||
namespace Utils::StringUtils
|
||||
{
|
||||
namespace StringUtils
|
||||
inline
|
||||
char *search_replace(const char *haystack, const char *needle, const char *replace)
|
||||
{
|
||||
inline
|
||||
char *search_replace(const char *haystack, const char *needle, const char *replace)
|
||||
{
|
||||
const char *haystackT = haystack;
|
||||
const char *haystackT = haystack;
|
||||
|
||||
size_t i;
|
||||
size_t match = 0;
|
||||
size_t oldLength = strlen(needle);
|
||||
size_t newLength = strlen(replace);
|
||||
size_t i;
|
||||
size_t match = 0;
|
||||
size_t oldLength = strlen(needle);
|
||||
size_t newLength = strlen(replace);
|
||||
|
||||
for (i = 0; haystack[i] != '\0'; ++i) {
|
||||
if (strstr(&haystack[i], needle) == &haystack[i]) {
|
||||
++match;
|
||||
for (i = 0; haystack[i] != '\0'; ++i) {
|
||||
if (strstr(&haystack[i], needle) == &haystack[i]) {
|
||||
++match;
|
||||
|
||||
i += oldLength - 1;
|
||||
}
|
||||
i += oldLength - 1;
|
||||
}
|
||||
|
||||
char *result = (char *) malloc(i + match * (newLength - oldLength) + 1);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t c = 0;
|
||||
while (*haystack && c < i + match * (newLength - oldLength)) {
|
||||
if (strstr(haystack, needle) == haystack) {
|
||||
strcpy(&result[c], (char *) replace);
|
||||
|
||||
c += newLength;
|
||||
haystack += oldLength;
|
||||
} else {
|
||||
result[c++] = *haystack++;
|
||||
}
|
||||
}
|
||||
|
||||
if (c > i + match * (newLength - oldLength)) {
|
||||
c = i + match * (newLength - oldLength);
|
||||
}
|
||||
|
||||
result[c] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
bool is_number(const char *s)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
if (!isdigit(*s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++s;
|
||||
}
|
||||
|
||||
return true;
|
||||
char *result = (char *) malloc(i + match * (newLength - oldLength) + 1);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t str_count(char *str, char *substr)
|
||||
{
|
||||
int l1 = strlen(str);
|
||||
int l2 = strlen(substr);
|
||||
size_t c = 0;
|
||||
while (*haystack && c < i + match * (newLength - oldLength)) {
|
||||
if (strstr(haystack, needle) == haystack) {
|
||||
strcpy(&result[c], (char *) replace);
|
||||
|
||||
if (l2 == 0 || l1 < l2) {
|
||||
return 0;
|
||||
c += newLength;
|
||||
haystack += oldLength;
|
||||
} else {
|
||||
result[c++] = *haystack++;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (str = strstr(str, substr); str; str = strstr(str + l2, substr)) {
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
char *strsep(char **sp, char *sep)
|
||||
{
|
||||
char *p, *s;
|
||||
|
||||
if (sp == NULL || *sp == NULL || **sp == '\0') {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
s = *sp;
|
||||
p = s + strcspn(s, sep);
|
||||
|
||||
if (*p != '\0') {
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
*sp = p;
|
||||
|
||||
return(s);
|
||||
if (c > i + match * (newLength - oldLength)) {
|
||||
c = i + match * (newLength - oldLength);
|
||||
}
|
||||
|
||||
int str_split(char **list, char *str, const char delim)
|
||||
{
|
||||
size_t splits = str_count(str, (char *) &delim) + 1;
|
||||
list = (char **) malloc(splits * sizeof(char *));
|
||||
result[c] = '\0';
|
||||
|
||||
char *token;
|
||||
int i = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
while ((token = strsep(&str, (char *) &delim)) != NULL) {
|
||||
list[i] = (char *) malloc(strlen(token + 1) * sizeof(char));
|
||||
memcpy(list[i], token, (strlen(token) + 1) * sizeof(char));
|
||||
|
||||
++i;
|
||||
inline
|
||||
bool is_number(const char *s)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
if (!isdigit(*s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return i;
|
||||
++s;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char **values;
|
||||
int *masks;
|
||||
int size;
|
||||
} text_diff;
|
||||
return true;
|
||||
}
|
||||
|
||||
text_diff computeLCSDiff(char **from, int fromSize, char **to, int toSize)
|
||||
{
|
||||
char **diffValues = (char **) malloc(fromSize * toSize * sizeof(char *));
|
||||
int *diffMasks = (int *) calloc(fromSize * toSize, sizeof(int));
|
||||
inline
|
||||
size_t str_count(char *str, char *substr)
|
||||
{
|
||||
int l1 = strlen(str);
|
||||
int l2 = strlen(substr);
|
||||
|
||||
int *dm = (int *) calloc((fromSize + 1) * (toSize + 1), sizeof(int));
|
||||
if (l2 == 0 || l1 < l2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!diffValues || !diffMasks || !dm) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
int count = 0;
|
||||
for (str = strstr(str, substr); str; str = strstr(str + l2, substr)) {
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
inline
|
||||
char *strsep(char **sp, char *sep)
|
||||
{
|
||||
char *p, *s;
|
||||
|
||||
if (sp == NULL || *sp == NULL || **sp == '\0') {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
s = *sp;
|
||||
p = s + strcspn(s, sep);
|
||||
|
||||
if (*p != '\0') {
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
*sp = p;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
// @todo Implement delim as const char* (also allow \0 length)
|
||||
inline
|
||||
int str_split(char **list, char *str, const char delim)
|
||||
{
|
||||
size_t splits = str_count(str, (char *) &delim) + 1;
|
||||
list = (char **) malloc(splits * sizeof(char *));
|
||||
|
||||
char *token;
|
||||
int i = 0;
|
||||
|
||||
while ((token = strsep(&str, (char *) &delim)) != NULL) {
|
||||
list[i] = (char *) malloc(strlen(token + 1) * sizeof(char));
|
||||
memcpy(list[i], token, (strlen(token) + 1) * sizeof(char));
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// @todo Implement delim as const char* (also allow \0 length)
|
||||
inline
|
||||
char* str_combine(char **str, size_t size, const char delim)
|
||||
{
|
||||
if (size < 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t total_size = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
total_size += strlen(str[i]);
|
||||
}
|
||||
|
||||
// If delim ever becomes a string replace * 1 with * strlen(delimiter)
|
||||
total_size += (size - 1) * 1 + 1;
|
||||
|
||||
char *result = (char *) malloc(total_size * sizeof(char));
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(result, str[0]);
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
strcat(result, &delim);
|
||||
strcat(result, str[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char **values;
|
||||
int64_t *masks;
|
||||
size_t size;
|
||||
} text_diff;
|
||||
|
||||
text_diff computeLCSDiff(char **from, int fromSize, char **to, int toSize)
|
||||
{
|
||||
char **diffValues = (char **) malloc(fromSize * toSize * sizeof(char *));
|
||||
int64_t *diffMasks = (int64_t *) calloc(fromSize * toSize, sizeof(int64_t));
|
||||
|
||||
int *dm = (int *) calloc((fromSize + 1) * (toSize + 1), sizeof(int));
|
||||
|
||||
if (!diffValues || !diffMasks || !dm) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
/* Handled with calloc
|
||||
for (j = 0; j <= toSize; ++j) {
|
||||
dm[0 + j] = 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= fromSize; ++i) {
|
||||
dm[i * fromSize + 0] = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
for (i = 1; i <= fromSize; ++i) {
|
||||
for (j = 1; j <= toSize; ++j) {
|
||||
dm[i * fromSize + j] = strcmp(from[i - 1], to[j - 1]) == 0
|
||||
? dm[(i - 1) * fromSize + (j - 1)] + 1
|
||||
: oms_max(dm[(i - 1) * fromSize + j], dm[i * fromSize + (j - 1)]);
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
size_t diffIndex = 0;
|
||||
|
||||
/* Handled with calloc
|
||||
for (j = 0; j <= toSize; ++j) {
|
||||
dm[0 + j] = 0;
|
||||
}
|
||||
i = fromSize;
|
||||
j = toSize;
|
||||
|
||||
for (i = 1; i <= fromSize; ++i) {
|
||||
dm[i * fromSize + 0] = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
for (i = 1; i <= fromSize; ++i) {
|
||||
for (j = 1; j <= toSize; ++j) {
|
||||
dm[i * fromSize + j] = strcmp(from[i - 1], to[j - 1]) == 0
|
||||
? dm[(i - 1) * fromSize + (j - 1)] + 1
|
||||
: oms_max(dm[(i - 1) * fromSize + j], dm[i * fromSize + (j - 1)]);
|
||||
}
|
||||
}
|
||||
|
||||
int diffIndex = 0;
|
||||
|
||||
i = fromSize;
|
||||
j = toSize;
|
||||
|
||||
while ((i > 0 || j > 0) && diffIndex < fromSize * toSize) {
|
||||
if (j > 0 && dm[i * fromSize + (j - 1)] == dm[i * fromSize + j]) {
|
||||
diffValues[diffIndex] = (char *) malloc((strlen(to[j - 1]) + 1) * sizeof(char));
|
||||
if (!diffValues[diffIndex]) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
strcpy_s(diffValues[diffIndex], (strlen(to[j - 1]) + 1) * sizeof(char), to[j - 1]);
|
||||
#else
|
||||
strcpy(diffValues[diffIndex], to[j - 1]);
|
||||
#endif
|
||||
|
||||
diffMasks[diffIndex] = 1;
|
||||
|
||||
--j;
|
||||
++diffIndex;
|
||||
while ((i > 0 || j > 0) && diffIndex < fromSize * toSize) {
|
||||
if (j > 0 && dm[i * fromSize + (j - 1)] == dm[i * fromSize + j]) {
|
||||
diffValues[diffIndex] = (char *) malloc((strlen(to[j - 1]) + 1) * sizeof(char));
|
||||
if (!diffValues[diffIndex]) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i > 0 && dm[(i - 1) * fromSize + j] == dm[i * fromSize + j]) {
|
||||
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
|
||||
if (!diffValues[diffIndex]) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
#ifdef _WIN32
|
||||
strcpy_s(diffValues[diffIndex], (strlen(to[j - 1]) + 1) * sizeof(char), to[j - 1]);
|
||||
#else
|
||||
strcpy(diffValues[diffIndex], to[j - 1]);
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
diffMasks[diffIndex] = 1;
|
||||
|
||||
#ifdef _WIN32
|
||||
strcpy_s(diffValues[diffIndex], (strlen(from[i - 1]) + 1) * sizeof(char), from[i - 1]);
|
||||
#else
|
||||
strcpy(diffValues[diffIndex], from[i - 1]);
|
||||
#endif
|
||||
--j;
|
||||
++diffIndex;
|
||||
|
||||
diffMasks[diffIndex] = -1;
|
||||
|
||||
--i;
|
||||
++diffIndex;
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i > 0 && dm[(i - 1) * fromSize + j] == dm[i * fromSize + j]) {
|
||||
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
|
||||
if (!diffValues[diffIndex]) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
|
@ -236,41 +247,61 @@ namespace Utils
|
|||
strcpy(diffValues[diffIndex], from[i - 1]);
|
||||
#endif
|
||||
|
||||
/* Handled with calloc
|
||||
diffMasks[diffIndex] = 0;
|
||||
*/
|
||||
diffMasks[diffIndex] = -1;
|
||||
|
||||
--i;
|
||||
--j;
|
||||
++diffIndex;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
free(dm);
|
||||
|
||||
// @todo do we even need to realloc?
|
||||
char **diffValuesT = (char **) realloc(diffValues, diffIndex * sizeof(char *));
|
||||
if (!diffValuesT) {
|
||||
free(diffValues);
|
||||
}
|
||||
diffValues = diffValuesT;
|
||||
|
||||
int *diffMasksT = (int *) realloc(diffMasks, diffIndex * sizeof(int));
|
||||
if (!diffMasksT) {
|
||||
free(diffMasks);
|
||||
}
|
||||
diffMasks = diffMasksT;
|
||||
|
||||
if (!diffValues || !diffMasks) {
|
||||
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
|
||||
if (!diffValues[diffIndex]) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
return text_diff{};
|
||||
continue;
|
||||
}
|
||||
|
||||
ArraySort::reverse_char(diffValues, diffIndex);
|
||||
ArraySort::reverse_int(diffMasks, diffIndex);
|
||||
#ifdef _WIN32
|
||||
strcpy_s(diffValues[diffIndex], (strlen(from[i - 1]) + 1) * sizeof(char), from[i - 1]);
|
||||
#else
|
||||
strcpy(diffValues[diffIndex], from[i - 1]);
|
||||
#endif
|
||||
|
||||
return text_diff{diffValues, diffMasks, diffIndex};
|
||||
/* Handled with calloc
|
||||
diffMasks[diffIndex] = 0;
|
||||
*/
|
||||
|
||||
--i;
|
||||
--j;
|
||||
++diffIndex;
|
||||
}
|
||||
|
||||
free(dm);
|
||||
|
||||
// @todo do we even need to realloc?
|
||||
char **diffValuesT = (char **) realloc(diffValues, diffIndex * sizeof(char *));
|
||||
if (!diffValuesT) {
|
||||
free(diffValues);
|
||||
}
|
||||
diffValues = diffValuesT;
|
||||
|
||||
int64_t *diffMasksT = (int64_t *) realloc(diffMasks, diffIndex * sizeof(int64_t));
|
||||
if (!diffMasksT) {
|
||||
free(diffMasks);
|
||||
}
|
||||
diffMasks = diffMasksT;
|
||||
|
||||
if (!diffValues || !diffMasks) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
return text_diff{};
|
||||
}
|
||||
|
||||
ArraySort::reverse_char(diffValues, diffIndex);
|
||||
ArraySort::reverse_int(diffMasks, diffIndex);
|
||||
|
||||
return text_diff{diffValues, diffMasks, diffIndex};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
449
Utils/WebUtils.h
449
Utils/WebUtils.h
|
|
@ -23,276 +23,273 @@
|
|||
|
||||
#include "FileUtils.h"
|
||||
|
||||
namespace Utils
|
||||
namespace Utils::WebUtils
|
||||
{
|
||||
namespace WebUtils
|
||||
static bool CURL_SETUP = false;
|
||||
|
||||
inline
|
||||
void setup()
|
||||
{
|
||||
static bool CURL_SETUP = false;
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
Utils::WebUtils::CURL_SETUP = true;
|
||||
}
|
||||
|
||||
inline
|
||||
void setup()
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
Utils::WebUtils::CURL_SETUP = true;
|
||||
}
|
||||
inline
|
||||
void clean()
|
||||
{
|
||||
curl_global_cleanup();
|
||||
Utils::WebUtils::CURL_SETUP = false;
|
||||
}
|
||||
|
||||
inline
|
||||
void clean()
|
||||
{
|
||||
curl_global_cleanup();
|
||||
Utils::WebUtils::CURL_SETUP = false;
|
||||
}
|
||||
int write_download_data (void *ptr, size_t size, size_t nmeb, void *stream)
|
||||
{
|
||||
Utils::FileUtils::file_body *out = (Utils::FileUtils::file_body *) stream;
|
||||
size_t outSize = size * nmeb;
|
||||
|
||||
int write_download_data (void *ptr, size_t size, size_t nmeb, void *stream)
|
||||
{
|
||||
Utils::FileUtils::file_body *out = (Utils::FileUtils::file_body *) stream;
|
||||
size_t outSize = size * nmeb;
|
||||
if (out->size == 0) {
|
||||
// first time this function is called for a specific resource
|
||||
out->content = (char *) malloc((outSize + 1) * sizeof(char));
|
||||
if (!out->content) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
if (out->size == 0) {
|
||||
// first time this function is called for a specific resource
|
||||
out->content = (char *) malloc((outSize + 1) * sizeof(char));
|
||||
if (!out->content) {
|
||||
fprintf(stderr, "CRITICAL: malloc failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out->content) {
|
||||
memcpy(out->content, ptr, outSize * sizeof(char));
|
||||
|
||||
out->size = (int) outSize;
|
||||
out->content[out->size] = 0;
|
||||
}
|
||||
} else {
|
||||
// the max buffer (16384 = 16k) is exceeded, then this is called again and needs to get extended
|
||||
char *temp = (char *) malloc((outSize + out->size + 1) * sizeof(char));
|
||||
|
||||
memcpy(temp, out->content, out->size * sizeof(char));
|
||||
memcpy(temp + out->size * sizeof(char), ptr, outSize * sizeof(char));
|
||||
|
||||
free(out->content);
|
||||
|
||||
out->content = temp;
|
||||
out->size += outSize;
|
||||
out->content[out->size] = 0;
|
||||
}
|
||||
|
||||
return out->size;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
size_t size = 0;
|
||||
const char **resources = NULL;
|
||||
} ResourceTypes;
|
||||
|
||||
typedef struct {
|
||||
size_t size = 0;
|
||||
const char **urls = NULL;
|
||||
} Urls;
|
||||
|
||||
Utils::FileUtils::file_body download (char *url)
|
||||
{
|
||||
Utils::FileUtils::file_body page = {0};
|
||||
|
||||
if (!Utils::WebUtils::CURL_SETUP) {
|
||||
Utils::WebUtils::setup();
|
||||
}
|
||||
|
||||
CURL *h = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(h, CURLOPT_URL, url);
|
||||
curl_easy_setopt(h, CURLOPT_PRIVATE, url);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEDATA, &page);
|
||||
curl_easy_perform(h);
|
||||
curl_easy_cleanup(h);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
inline
|
||||
void add_transfer(CURLM *cm, char *url, int *left)
|
||||
{
|
||||
CURL *h = curl_easy_init();
|
||||
|
||||
Utils::FileUtils::file_body *page = (Utils::FileUtils::file_body *) malloc(sizeof(Utils::FileUtils::file_body));
|
||||
page->size = 0;
|
||||
|
||||
curl_easy_setopt(h, CURLOPT_URL, url);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEDATA, page);
|
||||
curl_easy_setopt(h, CURLOPT_PRIVATE, page);
|
||||
|
||||
curl_easy_setopt(h, CURLOPT_ACCEPT_ENCODING, "");
|
||||
curl_easy_setopt(h, CURLOPT_TIMEOUT, 5L);
|
||||
curl_easy_setopt(h, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(h, CURLOPT_MAXREDIRS, 10L);
|
||||
curl_easy_setopt(h, CURLOPT_CONNECTTIMEOUT, 2L);
|
||||
curl_easy_setopt(h, CURLOPT_COOKIEFILE, "");
|
||||
curl_easy_setopt(h, CURLOPT_FILETIME, 1L);
|
||||
curl_easy_setopt(h, CURLOPT_USERAGENT, "firefox");
|
||||
curl_easy_setopt(h, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||
curl_easy_setopt(h, CURLOPT_UNRESTRICTED_AUTH, 1L);
|
||||
curl_easy_setopt(h, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
|
||||
curl_easy_setopt(h, CURLOPT_EXPECT_100_TIMEOUT_MS, 0L);
|
||||
|
||||
curl_multi_add_handle(cm, h);
|
||||
|
||||
++(*left);
|
||||
}
|
||||
|
||||
size_t follow_links(CURLM *cm, Utils::FileUtils::file_body *page, char *url, int *left)
|
||||
{
|
||||
int opts = HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_NONET;
|
||||
htmlDocPtr doc = htmlReadMemory(page->content, page->size, url, NULL, opts);
|
||||
|
||||
if(!doc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmlChar *xpath = (xmlChar*) "//img/@src";
|
||||
xmlXPathContextPtr context = xmlXPathNewContext(doc);
|
||||
xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context);
|
||||
xmlXPathFreeContext(context);
|
||||
if (out->content) {
|
||||
memcpy(out->content, ptr, outSize * sizeof(char));
|
||||
|
||||
if(!result) {
|
||||
return 0;
|
||||
out->size = (int) outSize;
|
||||
out->content[out->size] = 0;
|
||||
}
|
||||
} else {
|
||||
// the max buffer (16384 = 16k) is exceeded, then this is called again and needs to get extended
|
||||
char *temp = (char *) malloc((outSize + out->size + 1) * sizeof(char));
|
||||
|
||||
xmlNodeSetPtr nodeset = result->nodesetval;
|
||||
if(xmlXPathNodeSetIsEmpty(nodeset)) {
|
||||
xmlXPathFreeObject(result);
|
||||
return 0;
|
||||
}
|
||||
memcpy(temp, out->content, out->size * sizeof(char));
|
||||
memcpy(temp + out->size * sizeof(char), ptr, outSize * sizeof(char));
|
||||
|
||||
size_t count = 0;
|
||||
int i;
|
||||
free(out->content);
|
||||
|
||||
for(i = 0; i < nodeset->nodeNr; i++) {
|
||||
double r = rand();
|
||||
int x = r * nodeset->nodeNr / RAND_MAX;
|
||||
const xmlNode *node = nodeset->nodeTab[x]->xmlChildrenNode;
|
||||
xmlChar *href = xmlNodeListGetString(doc, node, 1);
|
||||
out->content = temp;
|
||||
out->size += outSize;
|
||||
out->content[out->size] = 0;
|
||||
}
|
||||
|
||||
// follow relative link
|
||||
if(true) {
|
||||
xmlChar *orig = href;
|
||||
return out->size;
|
||||
}
|
||||
|
||||
// @todo consider base= tag which has an impact on relative links
|
||||
href = xmlBuildURI(href, (xmlChar *) url);
|
||||
xmlFree(orig);
|
||||
}
|
||||
typedef struct {
|
||||
size_t size = 0;
|
||||
const char **resources = NULL;
|
||||
} ResourceTypes;
|
||||
|
||||
char *link = (char *) href;
|
||||
if(!link || strlen(link) < 10) {
|
||||
continue;
|
||||
}
|
||||
typedef struct {
|
||||
size_t size = 0;
|
||||
const char **urls = NULL;
|
||||
} Urls;
|
||||
|
||||
if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8) || !strncmp(link, "www.", 4)) {
|
||||
Utils::WebUtils::add_transfer(cm, link, left);
|
||||
Utils::FileUtils::file_body download (char *url)
|
||||
{
|
||||
Utils::FileUtils::file_body page = {0};
|
||||
|
||||
// limit to max 1000 links per page to follow
|
||||
if(count++ == 1000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!Utils::WebUtils::CURL_SETUP) {
|
||||
Utils::WebUtils::setup();
|
||||
}
|
||||
|
||||
xmlFree(link);
|
||||
}
|
||||
CURL *h = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(h, CURLOPT_URL, url);
|
||||
curl_easy_setopt(h, CURLOPT_PRIVATE, url);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEDATA, &page);
|
||||
curl_easy_perform(h);
|
||||
curl_easy_cleanup(h);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
inline
|
||||
void add_transfer(CURLM *cm, char *url, int *left)
|
||||
{
|
||||
CURL *h = curl_easy_init();
|
||||
|
||||
Utils::FileUtils::file_body *page = (Utils::FileUtils::file_body *) malloc(sizeof(Utils::FileUtils::file_body));
|
||||
page->size = 0;
|
||||
|
||||
curl_easy_setopt(h, CURLOPT_URL, url);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
|
||||
curl_easy_setopt(h, CURLOPT_WRITEDATA, page);
|
||||
curl_easy_setopt(h, CURLOPT_PRIVATE, page);
|
||||
|
||||
curl_easy_setopt(h, CURLOPT_ACCEPT_ENCODING, "");
|
||||
curl_easy_setopt(h, CURLOPT_TIMEOUT, 5L);
|
||||
curl_easy_setopt(h, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(h, CURLOPT_MAXREDIRS, 10L);
|
||||
curl_easy_setopt(h, CURLOPT_CONNECTTIMEOUT, 2L);
|
||||
curl_easy_setopt(h, CURLOPT_COOKIEFILE, "");
|
||||
curl_easy_setopt(h, CURLOPT_FILETIME, 1L);
|
||||
curl_easy_setopt(h, CURLOPT_USERAGENT, "firefox");
|
||||
curl_easy_setopt(h, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||
curl_easy_setopt(h, CURLOPT_UNRESTRICTED_AUTH, 1L);
|
||||
curl_easy_setopt(h, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
|
||||
curl_easy_setopt(h, CURLOPT_EXPECT_100_TIMEOUT_MS, 0L);
|
||||
|
||||
curl_multi_add_handle(cm, h);
|
||||
|
||||
++(*left);
|
||||
}
|
||||
|
||||
size_t follow_links(CURLM *cm, Utils::FileUtils::file_body *page, char *url, int *left)
|
||||
{
|
||||
int opts = HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_NONET;
|
||||
htmlDocPtr doc = htmlReadMemory(page->content, page->size, url, NULL, opts);
|
||||
|
||||
if(!doc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmlChar *xpath = (xmlChar*) "//img/@src";
|
||||
xmlXPathContextPtr context = xmlXPathNewContext(doc);
|
||||
xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context);
|
||||
xmlXPathFreeContext(context);
|
||||
|
||||
if(!result) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmlNodeSetPtr nodeset = result->nodesetval;
|
||||
if(xmlXPathNodeSetIsEmpty(nodeset)) {
|
||||
xmlXPathFreeObject(result);
|
||||
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *multi_download(
|
||||
Urls urls,
|
||||
const char *baseDir,
|
||||
int max_parrallel = 1,
|
||||
ResourceTypes *resources = NULL
|
||||
) {
|
||||
if (!Utils::WebUtils::CURL_SETUP) {
|
||||
Utils::WebUtils::setup();
|
||||
size_t count = 0;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nodeset->nodeNr; i++) {
|
||||
double r = rand();
|
||||
int x = r * nodeset->nodeNr / RAND_MAX;
|
||||
const xmlNode *node = nodeset->nodeTab[x]->xmlChildrenNode;
|
||||
xmlChar *href = xmlNodeListGetString(doc, node, 1);
|
||||
|
||||
// follow relative link
|
||||
if(true) {
|
||||
xmlChar *orig = href;
|
||||
|
||||
// @todo consider base= tag which has an impact on relative links
|
||||
href = xmlBuildURI(href, (xmlChar *) url);
|
||||
xmlFree(orig);
|
||||
}
|
||||
|
||||
CURLM *cm = curl_multi_init();
|
||||
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, max_parrallel);
|
||||
curl_multi_setopt(cm, CURLMOPT_MAX_TOTAL_CONNECTIONS, max_parrallel);
|
||||
curl_multi_setopt(cm, CURLMOPT_MAX_HOST_CONNECTIONS, 5);
|
||||
|
||||
#ifdef CURLPIPE_MULTIPLEX
|
||||
curl_multi_setopt(cm, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||
#endif
|
||||
|
||||
int downloads = 0;
|
||||
int left = 0;
|
||||
|
||||
for(downloads = 0; downloads < max_parrallel && downloads < urls.size; ++downloads) {
|
||||
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
|
||||
char *link = (char *) href;
|
||||
if(!link || strlen(link) < 10) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CURLMsg *msg;
|
||||
int msgs_left = -1;
|
||||
if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8) || !strncmp(link, "www.", 4)) {
|
||||
Utils::WebUtils::add_transfer(cm, link, left);
|
||||
|
||||
do {
|
||||
int alive = 1;
|
||||
curl_multi_perform(cm, &alive);
|
||||
// limit to max 1000 links per page to follow
|
||||
if(count++ == 1000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while((msg = curl_multi_info_read(cm, &msgs_left))) {
|
||||
if(msg->msg == CURLMSG_DONE) {
|
||||
CURL *e = msg->easy_handle;
|
||||
char *url;
|
||||
Utils::FileUtils::file_body *page;
|
||||
xmlFree(link);
|
||||
}
|
||||
|
||||
curl_easy_getinfo(e, CURLINFO_PRIVATE, &page);
|
||||
curl_easy_getinfo(e, CURLINFO_EFFECTIVE_URL, &url);
|
||||
xmlXPathFreeObject(result);
|
||||
|
||||
if (msg->data.result == CURLE_OK) {
|
||||
long statusCode = 0;
|
||||
curl_easy_getinfo(e, CURLINFO_RESPONSE_CDE, &statusCode);
|
||||
return count;
|
||||
}
|
||||
|
||||
if (statusCode == 200) {
|
||||
char *ctype;
|
||||
curl_easy_getinfo(e, CURLINFO_CONTENT_TYPE, &ctype);
|
||||
void *multi_download(
|
||||
Urls urls,
|
||||
const char *baseDir,
|
||||
int max_parrallel = 1,
|
||||
ResourceTypes *resources = NULL
|
||||
) {
|
||||
if (!Utils::WebUtils::CURL_SETUP) {
|
||||
Utils::WebUtils::setup();
|
||||
}
|
||||
|
||||
// @todo save file (how to handle base resources, either pass base url or save based on url?)
|
||||
CURLM *cm = curl_multi_init();
|
||||
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, max_parrallel);
|
||||
curl_multi_setopt(cm, CURLMOPT_MAX_TOTAL_CONNECTIONS, max_parrallel);
|
||||
curl_multi_setopt(cm, CURLMOPT_MAX_HOST_CONNECTIONS, 5);
|
||||
|
||||
if (ctype != NULL && strlen(ctype) > 10 && strstr(ctype, "text/html")) {
|
||||
// @todo check limits
|
||||
left += follow_links(cm, page, url, &left);
|
||||
}
|
||||
#ifdef CURLPIPE_MULTIPLEX
|
||||
curl_multi_setopt(cm, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||
#endif
|
||||
|
||||
int downloads = 0;
|
||||
int left = 0;
|
||||
|
||||
for(downloads = 0; downloads < max_parrallel && downloads < urls.size; ++downloads) {
|
||||
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
|
||||
}
|
||||
|
||||
CURLMsg *msg;
|
||||
int msgs_left = -1;
|
||||
|
||||
do {
|
||||
int alive = 1;
|
||||
curl_multi_perform(cm, &alive);
|
||||
|
||||
while((msg = curl_multi_info_read(cm, &msgs_left))) {
|
||||
if(msg->msg == CURLMSG_DONE) {
|
||||
CURL *e = msg->easy_handle;
|
||||
char *url;
|
||||
Utils::FileUtils::file_body *page;
|
||||
|
||||
curl_easy_getinfo(e, CURLINFO_PRIVATE, &page);
|
||||
curl_easy_getinfo(e, CURLINFO_EFFECTIVE_URL, &url);
|
||||
|
||||
if (msg->data.result == CURLE_OK) {
|
||||
long statusCode = 0;
|
||||
curl_easy_getinfo(e, CURLINFO_RESPONSE_CDE, &statusCode);
|
||||
|
||||
if (statusCode == 200) {
|
||||
char *ctype;
|
||||
curl_easy_getinfo(e, CURLINFO_CONTENT_TYPE, &ctype);
|
||||
|
||||
// @todo save file (how to handle base resources, either pass base url or save based on url?)
|
||||
|
||||
if (ctype != NULL && strlen(ctype) > 10 && strstr(ctype, "text/html")) {
|
||||
// @todo check limits
|
||||
left += follow_links(cm, page, url, &left);
|
||||
}
|
||||
}
|
||||
|
||||
curl_multi_remove_handle(cm, e);
|
||||
curl_easy_cleanup(e);
|
||||
free(page->content);
|
||||
free(page);
|
||||
|
||||
--left;
|
||||
} else {
|
||||
fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
|
||||
}
|
||||
|
||||
if(downloads < urls.size) {
|
||||
++downloads;
|
||||
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
|
||||
}
|
||||
curl_multi_remove_handle(cm, e);
|
||||
curl_easy_cleanup(e);
|
||||
free(page->content);
|
||||
free(page);
|
||||
|
||||
--left;
|
||||
} else {
|
||||
fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
|
||||
}
|
||||
|
||||
if(left > 0) {
|
||||
curl_multi_wait(cm, NULL, 0, 1000, NULL);
|
||||
if(downloads < urls.size) {
|
||||
++downloads;
|
||||
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
|
||||
}
|
||||
} while(left > 0);
|
||||
}
|
||||
|
||||
curl_multi_cleanup(cm);
|
||||
if(left > 0) {
|
||||
curl_multi_wait(cm, NULL, 0, 1000, NULL);
|
||||
}
|
||||
} while(left > 0);
|
||||
|
||||
return null;
|
||||
}
|
||||
curl_multi_cleanup(cm);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user