mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-02-14 09:28:41 +00:00
Update code style
This commit is contained in:
parent
b34004c1cb
commit
33b480fbae
|
|
@ -17,46 +17,43 @@
|
||||||
#include "../DatabaseType.h"
|
#include "../DatabaseType.h"
|
||||||
#include "../DatabaseStatus.h"
|
#include "../DatabaseStatus.h"
|
||||||
|
|
||||||
namespace DataStorage
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
namespace Database
|
typedef struct {
|
||||||
{
|
size_t rows = 0;
|
||||||
typedef struct {
|
size_t columns = 0;
|
||||||
size_t rows = 0;
|
char **results = NULL;
|
||||||
size_t columns = 0;
|
} QueryResult;
|
||||||
char **results = NULL;
|
|
||||||
} QueryResult;
|
|
||||||
|
|
||||||
struct ConnectionAbstract {
|
struct ConnectionAbstract {
|
||||||
void *con = NULL;
|
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)
|
virtual void connect(DbConnectionConfig *dbdata = NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void close()
|
||||||
|
{
|
||||||
|
if (this->con != NULL) {
|
||||||
|
free(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void close()
|
this->con = NULL;
|
||||||
{
|
this->status = DatabaseStatus::CLOSED;
|
||||||
if (this->con != NULL) {
|
}
|
||||||
free(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->con = NULL;
|
virtual QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||||
this->status = DatabaseStatus::CLOSED;
|
{
|
||||||
}
|
return QueryResult();
|
||||||
|
}
|
||||||
virtual QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
};
|
||||||
{
|
|
||||||
return QueryResult();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -21,40 +21,37 @@
|
||||||
#include "PostgresqlConnection.h"
|
#include "PostgresqlConnection.h"
|
||||||
#include "SQLiteConnection.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:
|
||||||
switch (dbdata.db) {
|
return new MysqlConnection(dbdata);
|
||||||
case DatabaseType::MYSQL:
|
case DatabaseType::PGSQL:
|
||||||
return new MysqlConnection(dbdata);
|
return new PostgresqlConnection(dbdata);
|
||||||
case DatabaseType::PGSQL:
|
case DatabaseType::SQLSRV:
|
||||||
return new PostgresqlConnection(dbdata);
|
return NULL;
|
||||||
case DatabaseType::SQLSRV:
|
case DatabaseType::SQLITE:
|
||||||
return NULL;
|
return new SQLiteConnection(dbdata);
|
||||||
case DatabaseType::SQLITE:
|
default:
|
||||||
return new SQLiteConnection(dbdata);
|
return NULL;
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void close(ConnectionAbstract *db, DbConnectionConfig dbdata)
|
void close(ConnectionAbstract *db, DbConnectionConfig dbdata)
|
||||||
{
|
{
|
||||||
switch (dbdata.db) {
|
switch (dbdata.db) {
|
||||||
case DatabaseType::MYSQL:
|
case DatabaseType::MYSQL:
|
||||||
return ((MysqlConnection *) db)->close();
|
return ((MysqlConnection *) db)->close();
|
||||||
case DatabaseType::PGSQL:
|
case DatabaseType::PGSQL:
|
||||||
return ((PostgresqlConnection *) db)->close();
|
return ((PostgresqlConnection *) db)->close();
|
||||||
case DatabaseType::SQLSRV:
|
case DatabaseType::SQLSRV:
|
||||||
return;
|
return;
|
||||||
case DatabaseType::SQLITE:
|
case DatabaseType::SQLITE:
|
||||||
return ((SQLiteConnection *) db)->close();
|
return ((SQLiteConnection *) db)->close();
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,45 +15,42 @@
|
||||||
|
|
||||||
#include "../DatabaseType.h"
|
#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 {
|
if (dbdata->database != NULL) {
|
||||||
DatabaseType db = DatabaseType::UNDEFINED;
|
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;
|
if (dbdata->password != NULL) {
|
||||||
|
free((char *) dbdata->password);
|
||||||
const char *login = NULL;
|
dbdata->password = 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,131 +20,128 @@
|
||||||
#include "../DatabaseType.h"
|
#include "../DatabaseType.h"
|
||||||
#include "../DatabaseStatus.h"
|
#include "../DatabaseStatus.h"
|
||||||
|
|
||||||
namespace DataStorage
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
namespace Database
|
struct MysqlConnection : ConnectionAbstract {
|
||||||
{
|
MysqlConnection(DbConnectionConfig dbdata)
|
||||||
struct MysqlConnection : ConnectionAbstract {
|
{
|
||||||
MysqlConnection(DbConnectionConfig dbdata)
|
this->type = DatabaseType::MYSQL;
|
||||||
{
|
this->dbdata = dbdata;
|
||||||
this->type = DatabaseType::MYSQL;
|
}
|
||||||
this->dbdata = dbdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
void connect(DbConnectionConfig *dbdata = NULL)
|
void connect(DbConnectionConfig *dbdata = NULL)
|
||||||
{
|
{
|
||||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||||
|
|
||||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||||
|| this->dbdata.host == NULL
|
|| this->dbdata.host == NULL
|
||||||
|| this->dbdata.port == 0
|
|| this->dbdata.port == 0
|
||||||
|| this->dbdata.database == NULL
|
|| this->dbdata.database == NULL
|
||||||
|| this->dbdata.login == NULL
|
|| this->dbdata.login == NULL
|
||||||
|| this->dbdata.password == NULL
|
|| this->dbdata.password == NULL
|
||||||
) {
|
) {
|
||||||
this->status = DatabaseStatus::FAILURE;
|
this->status = DatabaseStatus::FAILURE;
|
||||||
|
|
||||||
if (this->dbdata.password != NULL) {
|
if (this->dbdata.password != NULL) {
|
||||||
free((char *) this->dbdata.password);
|
free((char *) this->dbdata.password);
|
||||||
this->dbdata.password = NULL;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
this->close();
|
||||||
{
|
|
||||||
if (this->con != NULL) {
|
|
||||||
mysql_close((::MYSQL *) this->con);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->con = NULL;
|
this->con = mysql_init(NULL);
|
||||||
this->status = DatabaseStatus::CLOSED;
|
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)
|
this->con = NULL;
|
||||||
{
|
this->status = DatabaseStatus::CLOSED;
|
||||||
QueryResult result;
|
}
|
||||||
|
|
||||||
MYSQL_RES *res;
|
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||||
int status = 0;
|
{
|
||||||
|
QueryResult result;
|
||||||
|
|
||||||
if (paramValues != NULL) {
|
MYSQL_RES *res;
|
||||||
return result;
|
int status = 0;
|
||||||
} else {
|
|
||||||
status = mysql_query((::MYSQL *) this->con, stmt);
|
|
||||||
res = mysql_store_result((::MYSQL *) this->con);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res == NULL) {
|
if (paramValues != NULL) {
|
||||||
return result;
|
return result;
|
||||||
}
|
} else {
|
||||||
|
status = mysql_query((::MYSQL *) this->con, stmt);
|
||||||
result.rows = mysql_num_rows(res);
|
res = mysql_store_result((::MYSQL *) this->con);
|
||||||
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 (res == NULL) {
|
||||||
return result;
|
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
|
#endif
|
||||||
|
|
@ -20,125 +20,122 @@
|
||||||
#include "../DatabaseType.h"
|
#include "../DatabaseType.h"
|
||||||
#include "../DatabaseStatus.h"
|
#include "../DatabaseStatus.h"
|
||||||
|
|
||||||
namespace DataStorage
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
namespace Database
|
struct PostgresqlConnection : ConnectionAbstract {
|
||||||
{
|
PostgresqlConnection(DbConnectionConfig dbdata)
|
||||||
struct PostgresqlConnection : ConnectionAbstract {
|
{
|
||||||
PostgresqlConnection(DbConnectionConfig dbdata)
|
this->type = DatabaseType::PGSQL;
|
||||||
{
|
this->dbdata = dbdata;
|
||||||
this->type = DatabaseType::PGSQL;
|
}
|
||||||
this->dbdata = dbdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
void connect(DbConnectionConfig *dbdata = NULL)
|
void connect(DbConnectionConfig *dbdata = NULL)
|
||||||
{
|
{
|
||||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||||
|
|
||||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||||
|| this->dbdata.host == NULL
|
|| this->dbdata.host == NULL
|
||||||
|| this->dbdata.port == 0
|
|| this->dbdata.port == 0
|
||||||
|| this->dbdata.database == NULL
|
|| this->dbdata.database == NULL
|
||||||
|| this->dbdata.login == NULL
|
|| this->dbdata.login == NULL
|
||||||
|| this->dbdata.password == NULL
|
|| this->dbdata.password == NULL
|
||||||
) {
|
) {
|
||||||
this->status = DatabaseStatus::FAILURE;
|
this->status = DatabaseStatus::FAILURE;
|
||||||
|
|
||||||
if (this->dbdata.password != NULL) {
|
if (this->dbdata.password != NULL) {
|
||||||
free((char *) this->dbdata.password);
|
free((char *) this->dbdata.password);
|
||||||
this->dbdata.password = NULL;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
this->close();
|
||||||
{
|
|
||||||
if (this->con != NULL) {
|
|
||||||
PQfinish((PGconn *) this->con);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->con = NULL;
|
char port[12];
|
||||||
this->status = DatabaseStatus::CLOSED;
|
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)
|
this->con = NULL;
|
||||||
{
|
this->status = DatabaseStatus::CLOSED;
|
||||||
QueryResult result;
|
}
|
||||||
|
|
||||||
PGresult *res;
|
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||||
if (paramValues != NULL) {
|
{
|
||||||
res = PQexecParams((PGconn *) this->con, stmt, 1, NULL, (const char* const*) paramValues, NULL, NULL, 0);
|
QueryResult result;
|
||||||
} else {
|
|
||||||
res = PQexec((PGconn *) this->con, stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
|
PGresult *res;
|
||||||
PQclear(res);
|
if (paramValues != NULL) {
|
||||||
|
res = PQexecParams((PGconn *) this->con, stmt, 1, NULL, (const char* const*) paramValues, NULL, NULL, 0);
|
||||||
return result;
|
} else {
|
||||||
}
|
res = PQexec((PGconn *) this->con, stmt);
|
||||||
|
}
|
||||||
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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
return result;
|
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
|
#endif
|
||||||
|
|
@ -20,142 +20,139 @@
|
||||||
#include "../DatabaseType.h"
|
#include "../DatabaseType.h"
|
||||||
#include "../DatabaseStatus.h"
|
#include "../DatabaseStatus.h"
|
||||||
|
|
||||||
namespace DataStorage
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
namespace Database
|
struct SQLiteConnection : ConnectionAbstract {
|
||||||
{
|
SQLiteConnection(DbConnectionConfig dbdata)
|
||||||
struct SQLiteConnection : ConnectionAbstract {
|
{
|
||||||
SQLiteConnection(DbConnectionConfig dbdata)
|
this->type = DatabaseType::MYSQL;
|
||||||
{
|
this->dbdata = dbdata;
|
||||||
this->type = DatabaseType::MYSQL;
|
}
|
||||||
this->dbdata = dbdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
void connect(DbConnectionConfig *dbdata = NULL)
|
void connect(DbConnectionConfig *dbdata = NULL)
|
||||||
{
|
{
|
||||||
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
|
||||||
|
|
||||||
if (this->dbdata.db == DatabaseType::UNDEFINED
|
if (this->dbdata.db == DatabaseType::UNDEFINED
|
||||||
|| this->dbdata.database == NULL
|
|| this->dbdata.database == NULL
|
||||||
) {
|
) {
|
||||||
this->status = DatabaseStatus::FAILURE;
|
this->status = DatabaseStatus::FAILURE;
|
||||||
|
|
||||||
if (this->dbdata.password != NULL) {
|
if (this->dbdata.password != NULL) {
|
||||||
free((char *) this->dbdata.password);
|
free((char *) this->dbdata.password);
|
||||||
this->dbdata.password = NULL;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
this->close();
|
||||||
{
|
|
||||||
if (this->con != NULL) {
|
|
||||||
sqlite3_close((sqlite3 *) this->con);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->con = NULL;
|
int stat = sqlite3_open(this->dbdata.host, (sqlite3 **) &this->con);
|
||||||
this->status = DatabaseStatus::CLOSED;
|
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)
|
this->con = NULL;
|
||||||
{
|
this->status = DatabaseStatus::CLOSED;
|
||||||
QueryResult result;
|
}
|
||||||
|
|
||||||
sqlite3_stmt *res;
|
QueryResult query_execute(char *stmt, char *paramValues = NULL)
|
||||||
int status = 0;
|
{
|
||||||
|
QueryResult result;
|
||||||
|
|
||||||
if (paramValues != NULL) {
|
sqlite3_stmt *res;
|
||||||
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
int status = 0;
|
||||||
|
|
||||||
// @todo sqlite3_bind_int(res, 1, 3);
|
if (paramValues != NULL) {
|
||||||
} else {
|
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
||||||
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res == NULL) {
|
// @todo sqlite3_bind_int(res, 1, 3);
|
||||||
return result;
|
} else {
|
||||||
}
|
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
|
||||||
|
}
|
||||||
|
|
||||||
status = sqlite3_step(res);
|
if (res == NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result.rows = 100;
|
status = sqlite3_step(res);
|
||||||
result.columns = sqlite3_column_count(res);
|
|
||||||
|
|
||||||
if (result.rows == 0 || result.columns == 0) {
|
result.rows = 100;
|
||||||
return result;
|
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;
|
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
|
||||||
size_t valLen = 0;
|
|
||||||
char ** tempStorage = NULL;
|
|
||||||
|
|
||||||
size_t i = 0;
|
char *temp = NULL;
|
||||||
while (status == SQLITE_ROW) {
|
size_t valLen = 0;
|
||||||
if (i == result.rows) {
|
char ** tempStorage = NULL;
|
||||||
tempStorage = (char **) malloc((result.rows + 100) * result.columns * sizeof(char*));
|
|
||||||
memcpy(tempStorage, result.results, result.rows * result.columns * sizeof(char*));
|
|
||||||
|
|
||||||
free(result.results);
|
size_t i = 0;
|
||||||
result.results = tempStorage;
|
while (status == SQLITE_ROW) {
|
||||||
|
if (i == result.rows) {
|
||||||
result.rows += 100;
|
tempStorage = (char **) malloc((result.rows + 100) * result.columns * sizeof(char*));
|
||||||
}
|
memcpy(tempStorage, result.results, result.rows * result.columns * sizeof(char*));
|
||||||
|
|
||||||
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*));
|
|
||||||
|
|
||||||
free(result.results);
|
free(result.results);
|
||||||
result.results = tempStorage;
|
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
|
#endif
|
||||||
|
|
@ -10,19 +10,16 @@
|
||||||
#ifndef DATASTORAGE_DATABASE_STATUS_H
|
#ifndef DATASTORAGE_DATABASE_STATUS_H
|
||||||
#define DATASTORAGE_DATABASE_STATUS_H
|
#define DATASTORAGE_DATABASE_STATUS_H
|
||||||
|
|
||||||
namespace DataStorage
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
namespace Database
|
typedef enum {
|
||||||
{
|
OK = 0,
|
||||||
typedef enum {
|
MISSING_DATABASE = 1,
|
||||||
OK = 0,
|
MISSING_TABLE = 2,
|
||||||
MISSING_DATABASE = 1,
|
FAILURE = 3,
|
||||||
MISSING_TABLE = 2,
|
READONLY = 4,
|
||||||
FAILURE = 3,
|
CLOSED = 5
|
||||||
READONLY = 4,
|
} DatabaseStatus;
|
||||||
CLOSED = 5
|
|
||||||
} DatabaseStatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -12,32 +12,29 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
namespace DataStorage
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
namespace Database
|
typedef enum {
|
||||||
{
|
MYSQL = 1,
|
||||||
typedef enum {
|
SQLITE = 2,
|
||||||
MYSQL = 1,
|
PGSQL = 3,
|
||||||
SQLITE = 2,
|
SQLSRV = 4,
|
||||||
PGSQL = 3,
|
UNDEFINED = 5
|
||||||
SQLSRV = 4,
|
} DatabaseType;
|
||||||
UNDEFINED = 5
|
|
||||||
} DatabaseType;
|
|
||||||
|
|
||||||
DatabaseType database_type_from_str(const char* type)
|
DatabaseType database_type_from_str(const char* type)
|
||||||
{
|
{
|
||||||
if (strcmp(type, "mysql") == 0) {
|
if (strcmp(type, "mysql") == 0) {
|
||||||
return DatabaseType::MYSQL;
|
return DatabaseType::MYSQL;
|
||||||
} else if (strcmp(type, "sqlite") == 0) {
|
} else if (strcmp(type, "sqlite") == 0) {
|
||||||
return DatabaseType::SQLITE;
|
return DatabaseType::SQLITE;
|
||||||
} else if (strcmp(type, "pqsql") == 0) {
|
} else if (strcmp(type, "pqsql") == 0) {
|
||||||
return DatabaseType::PGSQL;
|
return DatabaseType::PGSQL;
|
||||||
} else if (strcmp(type, "mssql") == 0) {
|
} else if (strcmp(type, "mssql") == 0) {
|
||||||
return DatabaseType::SQLSRV;
|
return DatabaseType::SQLSRV;
|
||||||
}
|
|
||||||
|
|
||||||
return DatabaseType::UNDEFINED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return DatabaseType::UNDEFINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,42 +18,39 @@
|
||||||
#include "ReadMapper.h"
|
#include "ReadMapper.h"
|
||||||
#include "MapperAbstract.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 {
|
struct DataMapperFactory {
|
||||||
static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||||
{
|
{
|
||||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||||
readMapper->mapper = mapper;
|
readMapper->mapper = mapper;
|
||||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
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)
|
static ReadMapper *get(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||||
{
|
{
|
||||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||||
readMapper->mapper = mapper;
|
readMapper->mapper = mapper;
|
||||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
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)
|
static ReadMapper *getAll(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
|
||||||
{
|
{
|
||||||
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
|
||||||
readMapper->mapper = mapper;
|
readMapper->mapper = mapper;
|
||||||
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
readMapper->db = db == NULL ? DataStorage::Database::db : db;
|
||||||
|
|
||||||
return readMapper->getAll();
|
return readMapper->getAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -13,208 +13,205 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.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 {
|
/* Not necessary
|
||||||
MAPPER_DEFAULT = 0,
|
if (data->name != NULL) {
|
||||||
MAPPER_GET = 1,
|
free((void *) data->name);
|
||||||
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 {
|
typedef struct {
|
||||||
FIELD_TYPE_INT = 1,
|
const char *name = NULL;
|
||||||
FIELD_TYPE_FLOAT = 2,
|
int type = FieldType::FIELD_TYPE_INT;
|
||||||
FIELD_TYPE_STRING = 3,
|
const char *internal = NULL;
|
||||||
FIELD_TYPE_BOOL = 4
|
bool readonly = false;
|
||||||
} FieldType;
|
bool autocomplete = false;
|
||||||
|
} DataMapperColumn;
|
||||||
|
|
||||||
typedef struct {
|
void free_DataMapperColumn(DataMapperColumn *data)
|
||||||
const char *name = NULL;
|
{
|
||||||
size_t size = 0;
|
if (data->name != NULL) {
|
||||||
} ModelStructure;
|
free((void *) data->name);
|
||||||
|
|
||||||
void free_ModelStructure(ModelStructure *data)
|
|
||||||
{
|
|
||||||
/* Not necessary
|
|
||||||
if (data->name != NULL) {
|
|
||||||
free((void *) data->name);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
if (data->internal != NULL) {
|
||||||
const char *name = NULL;
|
free((void *) data->internal);
|
||||||
int type = FieldType::FIELD_TYPE_INT;
|
}
|
||||||
const char *internal = NULL;
|
}
|
||||||
bool readonly = false;
|
|
||||||
bool autocomplete = false;
|
|
||||||
} DataMapperColumn;
|
|
||||||
|
|
||||||
void free_DataMapperColumn(DataMapperColumn *data)
|
typedef struct {
|
||||||
{
|
const char *member = NULL;
|
||||||
if (data->name != NULL) {
|
const char *mapper = NULL;
|
||||||
free((void *) data->name);
|
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) {
|
void free_TableRelation(TableRelation *data)
|
||||||
free((void *) data->internal);
|
{
|
||||||
}
|
/* Not necessary
|
||||||
|
if (data->member != NULL) {
|
||||||
|
free((void *) data->member);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
if (data->mapper != NULL) {
|
||||||
const char *member = NULL;
|
free((void *) data->mapper);
|
||||||
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);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
if (data->external != NULL) {
|
||||||
const char *TABLE = NULL;
|
free((void *) data->external);
|
||||||
const char *PRIMARYFIELD = NULL;
|
}
|
||||||
const char *CREATED_AT = NULL;
|
|
||||||
const char *PARENT = NULL;
|
|
||||||
void *MODEL = NULL;
|
|
||||||
|
|
||||||
int MEMBER_COUNT = 0;
|
if (data->table != NULL) {
|
||||||
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
|
free((void *) data->table);
|
||||||
|
}
|
||||||
|
|
||||||
int COLUMN_COUNT = 0;
|
if (data->self != NULL) {
|
||||||
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
|
free((void *) data->self);
|
||||||
|
}
|
||||||
|
|
||||||
int OWNS_ONE_COUNT = 0;
|
if (data->column != NULL) {
|
||||||
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
|
free((void *) data->column);
|
||||||
|
}
|
||||||
|
|
||||||
int HAS_MANY_COUNT = 0;
|
if (data->self != NULL) {
|
||||||
DataStorage::Database::TableRelation *HAS_MANY = NULL;
|
free((void *) data->self);
|
||||||
|
}
|
||||||
|
|
||||||
int BELONGS_TO_COUNT = 0;
|
if (data->by != NULL) {
|
||||||
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
|
free((void *) data->by);
|
||||||
} MapperData;
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
void free_MapperData(DataStorage::Database::MapperData *data)
|
typedef struct {
|
||||||
{
|
const char *TABLE = NULL;
|
||||||
/* Not necessary
|
const char *PRIMARYFIELD = NULL;
|
||||||
if (data->TABLE != NULL) {
|
const char *CREATED_AT = NULL;
|
||||||
free((void *) data->TABLE);
|
const char *PARENT = NULL;
|
||||||
}
|
void *MODEL = NULL;
|
||||||
|
|
||||||
if (data->PRIMARYFIELD != NULL) {
|
int MEMBER_COUNT = 0;
|
||||||
free((void *) data->PRIMARYFIELD);
|
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (data->CREATED_AT != NULL) {
|
int COLUMN_COUNT = 0;
|
||||||
free((void *) data->CREATED_AT);
|
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (data->PARENT != NULL) {
|
int OWNS_ONE_COUNT = 0;
|
||||||
free((void *) data->PARENT);
|
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (data->MODEL != NULL) {
|
int HAS_MANY_COUNT = 0;
|
||||||
free(data->MODEL);
|
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;
|
free(data->MODEL_STRUCTURE);
|
||||||
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);
|
if (data->COLUMNS != NULL) {
|
||||||
|
/* not neccessary
|
||||||
|
for (i = 0; i < data->COLUMN_COUNT; ++i) {
|
||||||
|
free_DataMapperColumn(&data->COLUMNS[i]);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (data->COLUMNS != NULL) {
|
free(data->COLUMNS);
|
||||||
/* not neccessary
|
}
|
||||||
for (i = 0; i < data->COLUMN_COUNT; ++i) {
|
|
||||||
free_DataMapperColumn(&data->COLUMNS[i]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
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) {
|
free(data->OWNS_ONE);
|
||||||
/* not neccessary
|
}
|
||||||
for (i = 0; i < data->OWNS_ONE_COUNT; ++i) {
|
|
||||||
free_TableRelation(&data->OWNS_ONE[i]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
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) {
|
free(data->HAS_MANY);
|
||||||
/* not neccessary
|
}
|
||||||
for (i = 0; i < data->HAS_MANY_COUNT; ++i) {
|
|
||||||
free_TableRelation(&data->HAS_MANY[i]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
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) {
|
free(data->BELONGS_TO);
|
||||||
/* not neccessary
|
|
||||||
for (i = 0; i < data->BELONGS_TO_COUNT; ++i) {
|
|
||||||
free_TableRelation(&data->BELONGS_TO[i]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
free(data->BELONGS_TO);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,96 +12,94 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "../Connection/ConnectionAbstract.h"
|
#include "../Connection/ConnectionAbstract.h"
|
||||||
#include "DataMapperTypes.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)
|
void *address(uintptr_t objPos, char *name)
|
||||||
{
|
{
|
||||||
uintptr_t pos = objPos;
|
uintptr_t pos = objPos;
|
||||||
for (int i = 0; i < this->MEMBERS; ++i) {
|
for (int i = 0; i < this->MEMBERS; ++i) {
|
||||||
if (strcmp(this->MODEL_STRUCTURE[i].name, name) == 0) {
|
if (strcmp(this->MODEL_STRUCTURE[i].name, name) == 0) {
|
||||||
return (void *) pos;
|
return (void *) pos;
|
||||||
}
|
|
||||||
|
|
||||||
pos += this->MODEL_STRUCTURE[i].size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
pos += this->MODEL_STRUCTURE[i].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataMapperColumn *findByColumnName(char *column)
|
return NULL;
|
||||||
{
|
}
|
||||||
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
|
|
||||||
if (strcmp(this->COLUMNS[i].name, column) == 0) {
|
DataMapperColumn *findByColumnName(char *column)
|
||||||
return &this->COLUMNS[i];
|
{
|
||||||
}
|
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)
|
return NULL;
|
||||||
{
|
}
|
||||||
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
|
|
||||||
if (strcmp(this->COLUMNS[i].internal, member) == 0) {
|
DataMapperColumn *findByMemberName(char *member)
|
||||||
return &this->COLUMNS[i];
|
{
|
||||||
}
|
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(
|
return NULL;
|
||||||
char *member,
|
}
|
||||||
void *value,
|
|
||||||
int valueType,
|
|
||||||
const char *logic = "=",
|
|
||||||
const char *connector = "AND"
|
|
||||||
) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,54 +17,51 @@
|
||||||
#include "DataMapperFactory.h"
|
#include "DataMapperFactory.h"
|
||||||
#include "MapperAbstract.h"
|
#include "MapperAbstract.h"
|
||||||
|
|
||||||
namespace DataStorage
|
namespace DataStorage::Database
|
||||||
{
|
{
|
||||||
namespace Database
|
struct ReadMapper : MapperAbstract {
|
||||||
{
|
ReadMapper *get()
|
||||||
struct ReadMapper : MapperAbstract {
|
{
|
||||||
ReadMapper *get()
|
return this;
|
||||||
{
|
}
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadMapper *getAll()
|
ReadMapper *getAll()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *execute(void *options = NULL)
|
void *execute(void *options = NULL)
|
||||||
{
|
{
|
||||||
switch(this->type) {
|
switch(this->type) {
|
||||||
case DataStorage::Database::MapperType::MAPPER_GET:
|
case DataStorage::Database::MapperType::MAPPER_GET:
|
||||||
return this->executeGet(options);
|
return this->executeGet(options);
|
||||||
case DataStorage::Database::MapperType::MAPPER_GET_RAW:
|
case DataStorage::Database::MapperType::MAPPER_GET_RAW:
|
||||||
return this->executeGetRaw(options);
|
return this->executeGetRaw(options);
|
||||||
case DataStorage::Database::MapperType::MAPPER_GET_ALL:
|
case DataStorage::Database::MapperType::MAPPER_GET_ALL:
|
||||||
return this->executeGetAll(options);
|
return this->executeGetAll(options);
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void *executeGet(void *options)
|
void *executeGet(void *options)
|
||||||
{
|
{
|
||||||
int *primaryKeys = NULL;
|
int *primaryKeys = NULL;
|
||||||
const char *memberOfPrimaryField = findByColumnName((char *) this->mapper->PRIMARYFIELD)->internal;
|
const char *memberOfPrimaryField = findByColumnName((char *) this->mapper->PRIMARYFIELD)->internal;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *executeGetRaw(void *options)
|
void *executeGetRaw(void *options)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *executeGetAll(void *options)
|
void *executeGetAll(void *options)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -13,48 +13,45 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.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 {
|
if (field->name != NULL) {
|
||||||
char *name;
|
free(field->name);
|
||||||
char *type;
|
field->name = NULL;
|
||||||
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)
|
if (field->type != NULL) {
|
||||||
{
|
free(field->type);
|
||||||
if (field->name != NULL) {
|
field->type = NULL;
|
||||||
free(field->name);
|
}
|
||||||
field->name = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field->type != NULL) {
|
if (field->def != NULL) {
|
||||||
free(field->type);
|
free(field->def);
|
||||||
field->type = NULL;
|
field->def = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field->def != NULL) {
|
if (field->foreignTable != NULL) {
|
||||||
free(field->def);
|
free(field->foreignTable);
|
||||||
field->def = NULL;
|
field->foreignTable = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field->foreignTable != NULL) {
|
if (field->foreignKey != NULL) {
|
||||||
free(field->foreignTable);
|
free(field->foreignKey);
|
||||||
field->foreignTable = NULL;
|
field->foreignKey = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (field->foreignKey != NULL) {
|
|
||||||
free(field->foreignKey);
|
|
||||||
field->foreignKey = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,31 +15,28 @@
|
||||||
|
|
||||||
#include "DbField.h"
|
#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 {
|
if (schema->name != NULL) {
|
||||||
char *name;
|
free(schema->name);
|
||||||
DbField *fields;
|
schema->name = NULL;
|
||||||
size_t field_size = 0;
|
}
|
||||||
} DbSchema;
|
|
||||||
|
|
||||||
void free_DbSchema(DbSchema *schema)
|
if (schema->fields != NULL) {
|
||||||
{
|
for (int i = 0; i < schema->field_size; ++i) {
|
||||||
if (schema->name != NULL) {
|
free_DbField(&schema->fields[i]);
|
||||||
free(schema->name);
|
|
||||||
schema->name = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (schema->fields != NULL) {
|
free(schema->fields);
|
||||||
for (int i = 0; i < schema->field_size; ++i) {
|
schema->fields = NULL;
|
||||||
free_DbField(&schema->fields[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(schema->fields);
|
|
||||||
schema->fields = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#define HASH_MD5_H
|
#define HASH_MD5_H
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
// https://www.rfc-editor.org/rfc/rfc1321
|
// https://www.rfc-editor.org/rfc/rfc1321
|
||||||
|
|
||||||
|
|
@ -37,7 +39,7 @@ namespace Hash {
|
||||||
uint32_t a, b, c, d;
|
uint32_t a, b, c, d;
|
||||||
uint32_t aa, bb, cc, dd;
|
uint32_t aa, bb, cc, dd;
|
||||||
|
|
||||||
ptr = data;
|
ptr = (const unsigned char *) data;
|
||||||
|
|
||||||
a = ctx->a;
|
a = ctx->a;
|
||||||
b = ctx->b;
|
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;
|
sha_256->total_len += len;
|
||||||
|
|
||||||
const uint8_t *p = data;
|
const uint8_t *p = (uint8_t *) data;
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -14,67 +14,64 @@
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
#include <vector>
|
#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::Mat gray;
|
cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0);
|
||||||
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::Mat dilated;
|
||||||
cv::dilate(gray, dilated, kernel);
|
cv::dilate(gray, dilated, kernel);
|
||||||
|
|
||||||
cv::Mat edges;
|
cv::Mat edges;
|
||||||
cv::Canny(dilated, edges, 84, 3);
|
cv::Canny(dilated, edges, 84, 3);
|
||||||
|
|
||||||
std::vector<cv::Vec4i> lines;
|
std::vector<cv::Vec4i> lines;
|
||||||
lines.clear();
|
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();
|
std::vector<cv::Vec4i>::iterator it = lines.begin();
|
||||||
for(; it != lines.end(); ++it) {
|
for(; it != lines.end(); ++it) {
|
||||||
cv::Vec4i l = *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);
|
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<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 <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
namespace Image
|
namespace Image::ImageUtils
|
||||||
{
|
{
|
||||||
namespace ImageUtils
|
inline
|
||||||
|
float lightnessFromRgb(int r, int g, int b)
|
||||||
{
|
{
|
||||||
inline
|
float vR = r / 255.0;
|
||||||
float lightnessFromRgb(int r, int g, int b)
|
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 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 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 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 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 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;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
#include "ImageUtils.h"
|
#include "ImageUtils.h"
|
||||||
#include "../Utils/MathUtils.h"
|
#include "../Utils/MathUtils.h"
|
||||||
|
|
||||||
namespace Image
|
namespace Image::Kernel
|
||||||
{
|
{
|
||||||
const float KERNEL_RIDGE_1[3][3] = {
|
const float KERNEL_RIDGE_1[3][3] = {
|
||||||
{0.0, -1.0, 0.0},
|
{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},
|
{-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::Size dim = in.size();
|
||||||
cv::Mat convolve(cv::Mat in, const float kernel[][3])
|
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::Mat mKernel(3, 3, CV_32F, (float *) kernel);
|
||||||
cv::filter2D(in, out, -1, mKernel);
|
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"
|
#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::Mat inv;
|
||||||
cv::cvtColor(in, inv, cv::COLOR_BGR2GRAY);
|
cv::cvtColor(in, inv, cv::COLOR_BGR2GRAY);
|
||||||
cv::threshold(inv, inv, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
|
cv::threshold(inv, inv, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
|
||||||
|
|
||||||
std::vector<cv::Vec4i> lines;
|
std::vector<cv::Vec4i> lines;
|
||||||
cv::HoughLinesP(inv, lines, 1.0, OMS_PI / 180, 200, dim.width / 12, dim.width / 150);
|
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;
|
std::vector<float> tmpAngles;
|
||||||
for (int i = 0; i < lines.size(); ++i) {
|
for (int i = 0; i < lines.size(); ++i) {
|
||||||
float angle = atan2(lines[i][3] - lines[i][1], lines[i][2] - lines[i][0]);
|
float angle = atan2(lines[i][3] - lines[i][1], lines[i][2] - lines[i][0]);
|
||||||
tmpAngles.push_back(angle);
|
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;
|
std::vector<float> angles;
|
||||||
for (int i = 0; i < tmpAngles.size(); ++i) {
|
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;
|
|
||||||
if (imageOrientation > 0) {
|
if (imageOrientation > 0) {
|
||||||
if (angleDeg < 0) {
|
if (oms_deg2rad(90 - maxDegree) < oms_abs(tmpAngles[i]) && oms_abs(tmpAngles[i]) < oms_deg2rad(90 + maxDegree)) {
|
||||||
cv::rotate(in, orientFix, cv::ROTATE_90_CLOCKWISE);
|
angles.push_back(tmpAngles[i]);
|
||||||
angleDeg += 90.0;
|
|
||||||
} else if (angleDeg > 0) {
|
|
||||||
cv::rotate(in, orientFix, cv::ROTATE_90_COUNTERCLOCKWISE);
|
|
||||||
angleDeg -= 90.0;
|
|
||||||
} else {
|
|
||||||
orientFix = in;
|
|
||||||
}
|
}
|
||||||
|
} 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 {
|
} else {
|
||||||
orientFix = in;
|
orientFix = in;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
cv::Mat rot = cv::getRotationMatrix2D(cv::Point2f(dim.width / 2, dim.height / 2), angleDeg, 1.0);
|
orientFix = in;
|
||||||
|
|
||||||
cv::Mat out;
|
|
||||||
cv::warpAffine(orientFix, out, rot, dim, cv::INTER_LINEAR, cv::BORDER_REPLICATE);
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 "ImageUtils.h"
|
||||||
#include "../Utils/MathUtils.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 *intImg = (float *) malloc(dim.width * dim.height * sizeof(float));
|
||||||
float sum;
|
float sum;
|
||||||
|
|
||||||
cv::Vec3b bgr;
|
cv::Vec3b bgr;
|
||||||
for (int i = 0; i < dim.width; ++i) {
|
for (int i = 0; i < dim.width; ++i) {
|
||||||
sum = 0.0;
|
sum = 0.0;
|
||||||
|
|
||||||
for (int j = 0; j < dim.height; ++j) {
|
for (int j = 0; j < dim.height; ++j) {
|
||||||
bgr = in.at<cv::Vec3b>(j, i);
|
bgr = in.at<cv::Vec3b>(j, i);
|
||||||
sum += Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
|
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"
|
#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 {
|
return (unsigned long long) MeowU64From(
|
||||||
const char *key;
|
Hash::Meow::MeowHash(Hash::Meow::MeowDefaultSeed,
|
||||||
void *value;
|
strlen(key),
|
||||||
} entry;
|
(void *) key),
|
||||||
|
0
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ht *create_table(int max = 0, bool is_fixed = false)
|
||||||
|
{
|
||||||
|
ht *table = (ht *) malloc(sizeof(ht));
|
||||||
|
if (table == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *_set_entry(entry *entries, size_t max, const char *key, void *value, size_t *size)
|
table->size = 0;
|
||||||
{
|
table->max = max == 0 ? 16 : max;
|
||||||
unsigned long long hash = hash_key(key);
|
table->is_fixed = is_fixed;
|
||||||
size_t index = (size_t) (hash & (unsigned long long)(max - 1));
|
|
||||||
|
|
||||||
while (entries[index].key != NULL) {
|
table->entries = (entry *) calloc(table->max, sizeof(entry));
|
||||||
if (strcmp(key, entries[index].key) == 0) {
|
if (table->entries == NULL) {
|
||||||
entries[index].value = value;
|
free(table);
|
||||||
|
return NULL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool expand_table(ht *table)
|
return table;
|
||||||
{
|
}
|
||||||
size_t new_max = table->max * 2;
|
|
||||||
if (new_max < table->max) {
|
void *get_entry(ht *table, const char *key)
|
||||||
return false;
|
{
|
||||||
|
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));
|
++index;
|
||||||
if (new_entries == NULL) {
|
if (index >= table->max) {
|
||||||
return false;
|
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)
|
return NULL;
|
||||||
{
|
}
|
||||||
if (value == 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table->is_fixed && table->size == table->max) {
|
++(*size);
|
||||||
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)
|
entries[index].key = (char *) key;
|
||||||
{
|
entries[index].value = value;
|
||||||
it it;
|
|
||||||
it.table = table;
|
|
||||||
it.index = 0;
|
|
||||||
|
|
||||||
return it;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
bool expand_table(ht *table)
|
||||||
|
{
|
||||||
|
size_t new_max = table->max * 2;
|
||||||
|
if (new_max < table->max) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_table(ht *table)
|
entry *new_entries = (entry *) calloc(new_max, sizeof(entry));
|
||||||
{
|
if (new_entries == NULL) {
|
||||||
if (!table || !table->entries) {
|
return false;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < table->max; ++i) {
|
|
||||||
if (table->entries[i].key) {
|
|
||||||
free((void *) table->entries[i].key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(table->entries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
if (pos != NULL) {
|
||||||
memcpy(dir, arg, (pos - arg) * sizeof(char));
|
memcpy(dir, arg, (pos - arg) * sizeof(char));
|
||||||
|
|
||||||
chdir(dir);
|
chdir(dir);
|
||||||
|
|
||||||
free(dir);
|
free(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,48 +13,45 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils::ArraySort
|
||||||
{
|
{
|
||||||
namespace ArraySort
|
inline
|
||||||
|
void reverse_int(int64_t *arr, size_t size)
|
||||||
{
|
{
|
||||||
inline
|
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||||
void reverse_int(int64_t *arr, size_t size)
|
int64_t tmp = arr[low];
|
||||||
{
|
arr[low] = arr[high];
|
||||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
arr[high] = tmp;
|
||||||
int64_t tmp = arr[low];
|
|
||||||
arr[low] = arr[high];
|
|
||||||
arr[high] = tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void reverse_float(float *arr, size_t size)
|
void reverse_float(float *arr, size_t size)
|
||||||
{
|
{
|
||||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||||
float tmp = arr[low];
|
float tmp = arr[low];
|
||||||
arr[low] = arr[high];
|
arr[low] = arr[high];
|
||||||
arr[high] = tmp;
|
arr[high] = tmp;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void reverse_double(double *arr, size_t size)
|
void reverse_double(double *arr, size_t size)
|
||||||
{
|
{
|
||||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||||
double tmp = arr[low];
|
double tmp = arr[low];
|
||||||
arr[low] = arr[high];
|
arr[low] = arr[high];
|
||||||
arr[high] = tmp;
|
arr[high] = tmp;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void reverse_char(char **arr, size_t size)
|
void reverse_char(char **arr, size_t size)
|
||||||
{
|
{
|
||||||
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
|
||||||
char* tmp = arr[low];
|
char* tmp = arr[low];
|
||||||
arr[low] = arr[high];
|
arr[low] = arr[high];
|
||||||
arr[high] = tmp;
|
arr[high] = tmp;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,195 +16,192 @@
|
||||||
|
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils::ArrayUtils
|
||||||
{
|
{
|
||||||
namespace ArrayUtils
|
inline
|
||||||
|
char* get_arg(const char *id, char **argv, size_t size)
|
||||||
{
|
{
|
||||||
inline
|
if (Utils::StringUtils::is_number(id)) {
|
||||||
char* get_arg(const char *id, char **argv, size_t size)
|
return argv[atoi(id)];
|
||||||
{
|
}
|
||||||
if (Utils::StringUtils::is_number(id)) {
|
|
||||||
return argv[atoi(id)];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size - 1; ++i) {
|
for (size_t i = 0; i < size - 1; ++i) {
|
||||||
if (strcmp(id, argv[i]) == 0) {
|
if (strcmp(id, argv[i]) == 0) {
|
||||||
return i + 1 >= size ? NULL : argv[i + 1];
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
for (size_t i = 0; i < size1; ++i) {
|
||||||
bool has_arg(const char *id, char **argv, size_t size)
|
merged[i] = array1[i];
|
||||||
{
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
if (strcmp(id, argv[i]) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
for (size_t i = 0; i < size2; ++i) {
|
||||||
double array_sum_double(double *array, size_t size)
|
merged[size1 + i] = array2[i];
|
||||||
{
|
|
||||||
double sum = 0.0;
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
sum += array[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
return merged;
|
||||||
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
|
||||||
|
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
|
for (size_t i = 0; i < size1; ++i) {
|
||||||
int64_t array_sum_int(int64_t *array, size_t size)
|
merged[i] = array1[i];
|
||||||
{
|
|
||||||
int64_t sum = 0;
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
sum += array[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
for (size_t i = 0; i < size2; ++i) {
|
||||||
size_t find_in_array_string(const char *element, const char **array, size_t size)
|
merged[size1 + i] = array2[i];
|
||||||
{
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
if (strcmp(element, array[i]) == 0) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
return merged;
|
||||||
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
|
||||||
|
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
|
for (size_t i = 0; i < size1; ++i) {
|
||||||
size_t find_in_array_float(float element, float *array, size_t size)
|
merged[i] = array1[i];
|
||||||
{
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
if (array[i] == element) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
for (size_t i = 0; i < size2; ++i) {
|
||||||
size_t find_in_array_int(int64_t element, int64_t *array, size_t size)
|
merged[size1 + i] = array2[i];
|
||||||
{
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
if (array[i] == element) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
return merged;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size1; ++i) {
|
char** merge_arrays_char(const char** array1, size_t size1, const char** array2, size_t size2)
|
||||||
merged[i] = array1[i];
|
{
|
||||||
}
|
char** merged = (char**) malloc((size1 + size2) * sizeof(char*));
|
||||||
|
if (merged == NULL) {
|
||||||
for (size_t i = 0; i < size2; ++i) {
|
return NULL;
|
||||||
merged[size1 + i] = array2[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return merged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
for (size_t i = 0; i < size1; ++i) {
|
||||||
float* merge_arrays_float(float* array1, size_t size1, float* array2, size_t size2)
|
merged[i] = (char*) malloc((strlen(array1[i]) + 1) * sizeof(char));
|
||||||
{
|
strcpy(merged[i], array1[i]);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
for (size_t i = 0; i < size2; ++i) {
|
||||||
int64_t* merge_arrays_int(int64_t* array1, size_t size1, int64_t* array2, size_t size2)
|
merged[i] = (char*) malloc((strlen(array2[i]) + 1) * sizeof(char));
|
||||||
{
|
strcpy(merged[i], array2[i]);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char** merge_arrays_char(const char** array1, size_t size1, const char** array2, size_t size2)
|
return merged;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
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"
|
#include "OSWrapper.h"
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils::FileUtils
|
||||||
{
|
{
|
||||||
namespace FileUtils
|
inline
|
||||||
|
bool file_exists (const char *filename)
|
||||||
{
|
{
|
||||||
inline
|
#ifdef _WIN32
|
||||||
bool file_exists (const char *filename)
|
return access(filename, 0) == 0;
|
||||||
{
|
#else
|
||||||
#ifdef _WIN32
|
struct stat buffer;
|
||||||
return access(filename, 0) == 0;
|
return stat(filename, &buffer) == 0;
|
||||||
#else
|
#endif
|
||||||
struct stat buffer;
|
}
|
||||||
return stat(filename, &buffer) == 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
time_t last_modification (const char *filename)
|
time_t last_modification (const char *filename)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
FILETIME modtime;
|
FILETIME modtime;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
|
|
||||||
size_t nameLength = strlen(filename);
|
size_t nameLength = strlen(filename);
|
||||||
|
|
||||||
wchar_t *wtext = (wchar_t *) calloc(nameLength, sizeof(char));
|
wchar_t *wtext = (wchar_t *) calloc(nameLength, sizeof(char));
|
||||||
mbstowcs_s(NULL, wtext, nameLength, filename, nameLength);
|
mbstowcs_s(NULL, wtext, nameLength, filename, nameLength);
|
||||||
LPWSTR pFilename = wtext;
|
LPWSTR pFilename = wtext;
|
||||||
|
|
||||||
if (!pFilename) {
|
|
||||||
free(wtext);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h = CreateFileW(pFilename, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
||||||
|
|
||||||
|
if (!pFilename) {
|
||||||
free(wtext);
|
free(wtext);
|
||||||
free(pFilename);
|
|
||||||
|
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
return 0;
|
||||||
return (time_t) 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (GetFileTime(h, NULL, NULL, &modtime) == 0) {
|
h = CreateFileW(pFilename, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
return (time_t) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long long seconds = ((unsigned long long) (modtime.dwHighDateTime)) << 32;
|
free(wtext);
|
||||||
seconds |= modtime.dwLowDateTime;
|
free(pFilename);
|
||||||
|
|
||||||
return (seconds - 116444736000000000) / 10000000;
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
#else
|
return (time_t) 0;
|
||||||
struct stat buffer;
|
}
|
||||||
stat(filename, &buffer);
|
|
||||||
|
|
||||||
return (time_t) buffer.st_mtim.tv_sec;
|
if (GetFileTime(h, NULL, NULL, &modtime) == 0) {
|
||||||
#endif
|
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
|
return dot + 1;
|
||||||
const char* file_extension (const char *filename)
|
}
|
||||||
{
|
|
||||||
char *dot = strrchr((char *) filename, '.');
|
|
||||||
|
|
||||||
if (!dot || dot == filename) {
|
typedef struct {
|
||||||
return "";
|
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 {
|
fseek(fp, 0, SEEK_END);
|
||||||
char *content;
|
file.size = ftell(fp);
|
||||||
int size = 0; // doesn't include null termination (same as strlen)
|
fseek(fp, 0, SEEK_SET);
|
||||||
} file_body;
|
|
||||||
|
|
||||||
file_body read_file (const char *filename)
|
file.content = (char *) malloc((file.size + 1) * sizeof(char));
|
||||||
{
|
if (!file.content) {
|
||||||
file_body file = {0};
|
fprintf(stderr, "CRITICAL: malloc failed");
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
return file;
|
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 <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils::Rng::StringUtils
|
||||||
{
|
{
|
||||||
namespace Rng
|
inline
|
||||||
{
|
char* generate_string(
|
||||||
namespace StringUtils
|
size_t min = 10, size_t max = 10,
|
||||||
{
|
char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", int charsetLength = 62
|
||||||
inline
|
) {
|
||||||
char* generate_string(
|
srand(time(0));
|
||||||
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;
|
size_t length = (rand() % (max - min + 1)) + min;
|
||||||
char *randomString = (char *) malloc(length + 1);
|
char *randomString = (char *) malloc(length + 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
randomString[i] = charset[rand() % charsetLength];
|
randomString[i] = charset[rand() % charsetLength];
|
||||||
}
|
|
||||||
|
|
||||||
randomString[length] = '\0';
|
|
||||||
|
|
||||||
return randomString;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
randomString[length] = '\0';
|
||||||
|
|
||||||
|
return randomString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -17,212 +17,223 @@
|
||||||
#include "MathUtils.h"
|
#include "MathUtils.h"
|
||||||
#include "ArraySort.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
|
const char *haystackT = haystack;
|
||||||
char *search_replace(const char *haystack, const char *needle, const char *replace)
|
|
||||||
{
|
|
||||||
const char *haystackT = haystack;
|
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t match = 0;
|
size_t match = 0;
|
||||||
size_t oldLength = strlen(needle);
|
size_t oldLength = strlen(needle);
|
||||||
size_t newLength = strlen(replace);
|
size_t newLength = strlen(replace);
|
||||||
|
|
||||||
for (i = 0; haystack[i] != '\0'; ++i) {
|
for (i = 0; haystack[i] != '\0'; ++i) {
|
||||||
if (strstr(&haystack[i], needle) == &haystack[i]) {
|
if (strstr(&haystack[i], needle) == &haystack[i]) {
|
||||||
++match;
|
++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
|
char *result = (char *) malloc(i + match * (newLength - oldLength) + 1);
|
||||||
bool is_number(const char *s)
|
if (!result) {
|
||||||
{
|
return NULL;
|
||||||
while (*s != '\0') {
|
|
||||||
if (!isdigit(*s)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
size_t c = 0;
|
||||||
size_t str_count(char *str, char *substr)
|
while (*haystack && c < i + match * (newLength - oldLength)) {
|
||||||
{
|
if (strstr(haystack, needle) == haystack) {
|
||||||
int l1 = strlen(str);
|
strcpy(&result[c], (char *) replace);
|
||||||
int l2 = strlen(substr);
|
|
||||||
|
|
||||||
if (l2 == 0 || l1 < l2) {
|
c += newLength;
|
||||||
return 0;
|
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)
|
if (c > i + match * (newLength - oldLength)) {
|
||||||
{
|
c = i + match * (newLength - oldLength);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_split(char **list, char *str, const char delim)
|
result[c] = '\0';
|
||||||
{
|
|
||||||
size_t splits = str_count(str, (char *) &delim) + 1;
|
|
||||||
list = (char **) malloc(splits * sizeof(char *));
|
|
||||||
|
|
||||||
char *token;
|
return result;
|
||||||
int i = 0;
|
}
|
||||||
|
|
||||||
while ((token = strsep(&str, (char *) &delim)) != NULL) {
|
inline
|
||||||
list[i] = (char *) malloc(strlen(token + 1) * sizeof(char));
|
bool is_number(const char *s)
|
||||||
memcpy(list[i], token, (strlen(token) + 1) * sizeof(char));
|
{
|
||||||
|
while (*s != '\0') {
|
||||||
++i;
|
if (!isdigit(*s)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
++s;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
return true;
|
||||||
char **values;
|
}
|
||||||
int *masks;
|
|
||||||
int size;
|
|
||||||
} text_diff;
|
|
||||||
|
|
||||||
text_diff computeLCSDiff(char **from, int fromSize, char **to, int toSize)
|
inline
|
||||||
{
|
size_t str_count(char *str, char *substr)
|
||||||
char **diffValues = (char **) malloc(fromSize * toSize * sizeof(char *));
|
{
|
||||||
int *diffMasks = (int *) calloc(fromSize * toSize, sizeof(int));
|
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) {
|
int count = 0;
|
||||||
fprintf(stderr, "CRITICAL: malloc failed");
|
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;
|
size_t diffIndex = 0;
|
||||||
int j = 0;
|
|
||||||
|
|
||||||
/* Handled with calloc
|
i = fromSize;
|
||||||
for (j = 0; j <= toSize; ++j) {
|
j = toSize;
|
||||||
dm[0 + j] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i <= fromSize; ++i) {
|
while ((i > 0 || j > 0) && diffIndex < fromSize * toSize) {
|
||||||
dm[i * fromSize + 0] = 0;
|
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");
|
||||||
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;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > 0 && dm[(i - 1) * fromSize + j] == dm[i * fromSize + j]) {
|
#ifdef _WIN32
|
||||||
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
|
strcpy_s(diffValues[diffIndex], (strlen(to[j - 1]) + 1) * sizeof(char), to[j - 1]);
|
||||||
if (!diffValues[diffIndex]) {
|
#else
|
||||||
fprintf(stderr, "CRITICAL: malloc failed");
|
strcpy(diffValues[diffIndex], to[j - 1]);
|
||||||
|
#endif
|
||||||
|
|
||||||
continue;
|
diffMasks[diffIndex] = 1;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
--j;
|
||||||
strcpy_s(diffValues[diffIndex], (strlen(from[i - 1]) + 1) * sizeof(char), from[i - 1]);
|
++diffIndex;
|
||||||
#else
|
|
||||||
strcpy(diffValues[diffIndex], from[i - 1]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
diffMasks[diffIndex] = -1;
|
continue;
|
||||||
|
}
|
||||||
--i;
|
|
||||||
++diffIndex;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (i > 0 && dm[(i - 1) * fromSize + j] == dm[i * fromSize + j]) {
|
||||||
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
|
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
|
||||||
if (!diffValues[diffIndex]) {
|
if (!diffValues[diffIndex]) {
|
||||||
fprintf(stderr, "CRITICAL: malloc failed");
|
fprintf(stderr, "CRITICAL: malloc failed");
|
||||||
|
|
@ -236,41 +247,61 @@ namespace Utils
|
||||||
strcpy(diffValues[diffIndex], from[i - 1]);
|
strcpy(diffValues[diffIndex], from[i - 1]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Handled with calloc
|
diffMasks[diffIndex] = -1;
|
||||||
diffMasks[diffIndex] = 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
--i;
|
--i;
|
||||||
--j;
|
|
||||||
++diffIndex;
|
++diffIndex;
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(dm);
|
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
|
||||||
|
if (!diffValues[diffIndex]) {
|
||||||
// @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) {
|
|
||||||
fprintf(stderr, "CRITICAL: malloc failed");
|
fprintf(stderr, "CRITICAL: malloc failed");
|
||||||
|
|
||||||
return text_diff{};
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArraySort::reverse_char(diffValues, diffIndex);
|
#ifdef _WIN32
|
||||||
ArraySort::reverse_int(diffMasks, diffIndex);
|
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"
|
#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
|
inline
|
||||||
void setup()
|
void clean()
|
||||||
{
|
{
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
curl_global_cleanup();
|
||||||
Utils::WebUtils::CURL_SETUP = true;
|
Utils::WebUtils::CURL_SETUP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
int write_download_data (void *ptr, size_t size, size_t nmeb, void *stream)
|
||||||
void clean()
|
{
|
||||||
{
|
Utils::FileUtils::file_body *out = (Utils::FileUtils::file_body *) stream;
|
||||||
curl_global_cleanup();
|
size_t outSize = size * nmeb;
|
||||||
Utils::WebUtils::CURL_SETUP = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_download_data (void *ptr, size_t size, size_t nmeb, void *stream)
|
if (out->size == 0) {
|
||||||
{
|
// first time this function is called for a specific resource
|
||||||
Utils::FileUtils::file_body *out = (Utils::FileUtils::file_body *) stream;
|
out->content = (char *) malloc((outSize + 1) * sizeof(char));
|
||||||
size_t outSize = size * nmeb;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlChar *xpath = (xmlChar*) "//img/@src";
|
if (out->content) {
|
||||||
xmlXPathContextPtr context = xmlXPathNewContext(doc);
|
memcpy(out->content, ptr, outSize * sizeof(char));
|
||||||
xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context);
|
|
||||||
xmlXPathFreeContext(context);
|
|
||||||
|
|
||||||
if(!result) {
|
out->size = (int) outSize;
|
||||||
return 0;
|
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;
|
memcpy(temp, out->content, out->size * sizeof(char));
|
||||||
if(xmlXPathNodeSetIsEmpty(nodeset)) {
|
memcpy(temp + out->size * sizeof(char), ptr, outSize * sizeof(char));
|
||||||
xmlXPathFreeObject(result);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t count = 0;
|
free(out->content);
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; i < nodeset->nodeNr; i++) {
|
out->content = temp;
|
||||||
double r = rand();
|
out->size += outSize;
|
||||||
int x = r * nodeset->nodeNr / RAND_MAX;
|
out->content[out->size] = 0;
|
||||||
const xmlNode *node = nodeset->nodeTab[x]->xmlChildrenNode;
|
}
|
||||||
xmlChar *href = xmlNodeListGetString(doc, node, 1);
|
|
||||||
|
|
||||||
// follow relative link
|
return out->size;
|
||||||
if(true) {
|
}
|
||||||
xmlChar *orig = href;
|
|
||||||
|
|
||||||
// @todo consider base= tag which has an impact on relative links
|
typedef struct {
|
||||||
href = xmlBuildURI(href, (xmlChar *) url);
|
size_t size = 0;
|
||||||
xmlFree(orig);
|
const char **resources = NULL;
|
||||||
}
|
} ResourceTypes;
|
||||||
|
|
||||||
char *link = (char *) href;
|
typedef struct {
|
||||||
if(!link || strlen(link) < 10) {
|
size_t size = 0;
|
||||||
continue;
|
const char **urls = NULL;
|
||||||
}
|
} Urls;
|
||||||
|
|
||||||
if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8) || !strncmp(link, "www.", 4)) {
|
Utils::FileUtils::file_body download (char *url)
|
||||||
Utils::WebUtils::add_transfer(cm, link, left);
|
{
|
||||||
|
Utils::FileUtils::file_body page = {0};
|
||||||
|
|
||||||
// limit to max 1000 links per page to follow
|
if (!Utils::WebUtils::CURL_SETUP) {
|
||||||
if(count++ == 1000) {
|
Utils::WebUtils::setup();
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
xmlXPathFreeObject(result);
|
||||||
|
return 0;
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *multi_download(
|
size_t count = 0;
|
||||||
Urls urls,
|
int i;
|
||||||
const char *baseDir,
|
|
||||||
int max_parrallel = 1,
|
for(i = 0; i < nodeset->nodeNr; i++) {
|
||||||
ResourceTypes *resources = NULL
|
double r = rand();
|
||||||
) {
|
int x = r * nodeset->nodeNr / RAND_MAX;
|
||||||
if (!Utils::WebUtils::CURL_SETUP) {
|
const xmlNode *node = nodeset->nodeTab[x]->xmlChildrenNode;
|
||||||
Utils::WebUtils::setup();
|
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();
|
char *link = (char *) href;
|
||||||
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, max_parrallel);
|
if(!link || strlen(link) < 10) {
|
||||||
curl_multi_setopt(cm, CURLMOPT_MAX_TOTAL_CONNECTIONS, max_parrallel);
|
continue;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLMsg *msg;
|
if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8) || !strncmp(link, "www.", 4)) {
|
||||||
int msgs_left = -1;
|
Utils::WebUtils::add_transfer(cm, link, left);
|
||||||
|
|
||||||
do {
|
// limit to max 1000 links per page to follow
|
||||||
int alive = 1;
|
if(count++ == 1000) {
|
||||||
curl_multi_perform(cm, &alive);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while((msg = curl_multi_info_read(cm, &msgs_left))) {
|
xmlFree(link);
|
||||||
if(msg->msg == CURLMSG_DONE) {
|
}
|
||||||
CURL *e = msg->easy_handle;
|
|
||||||
char *url;
|
|
||||||
Utils::FileUtils::file_body *page;
|
|
||||||
|
|
||||||
curl_easy_getinfo(e, CURLINFO_PRIVATE, &page);
|
xmlXPathFreeObject(result);
|
||||||
curl_easy_getinfo(e, CURLINFO_EFFECTIVE_URL, &url);
|
|
||||||
|
|
||||||
if (msg->data.result == CURLE_OK) {
|
return count;
|
||||||
long statusCode = 0;
|
}
|
||||||
curl_easy_getinfo(e, CURLINFO_RESPONSE_CDE, &statusCode);
|
|
||||||
|
|
||||||
if (statusCode == 200) {
|
void *multi_download(
|
||||||
char *ctype;
|
Urls urls,
|
||||||
curl_easy_getinfo(e, CURLINFO_CONTENT_TYPE, &ctype);
|
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")) {
|
#ifdef CURLPIPE_MULTIPLEX
|
||||||
// @todo check limits
|
curl_multi_setopt(cm, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||||
left += follow_links(cm, page, url, &left);
|
#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) {
|
curl_multi_remove_handle(cm, e);
|
||||||
++downloads;
|
curl_easy_cleanup(e);
|
||||||
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
|
free(page->content);
|
||||||
}
|
free(page);
|
||||||
|
|
||||||
|
--left;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(left > 0) {
|
if(downloads < urls.size) {
|
||||||
curl_multi_wait(cm, NULL, 0, 1000, NULL);
|
++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