Update code style

This commit is contained in:
Dennis Eichhorn 2023-12-12 03:14:55 +00:00
parent b34004c1cb
commit 33b480fbae
31 changed files with 2370 additions and 2369 deletions

View File

@ -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

View File

@ -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;
}
} }
} }
} }

View File

@ -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;
}
} }
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
} }
} }

View File

@ -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

View File

@ -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);
}
} }
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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;
}
} }
} }
} }

View File

@ -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;
}
} }
} }
} }

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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) {
/* /*

View File

@ -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;
} }
} }

View File

@ -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;
}
} }
} }

View File

@ -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;
}
} }
} }

View File

@ -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;
} }
} }

View File

@ -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;
} }
} }

View File

@ -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);
} }
} }

View File

@ -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);
} }
} }

View File

@ -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;
}
} }
} }
} }

View File

@ -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
View 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

View File

@ -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;
} }
} }

View 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

View File

@ -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};
} }
} }

View File

@ -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;
} }
} }