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 "../DatabaseStatus.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
typedef struct {
size_t rows = 0;
size_t columns = 0;
char **results = NULL;
} QueryResult;
typedef struct {
size_t rows = 0;
size_t columns = 0;
char **results = NULL;
} QueryResult;
struct ConnectionAbstract {
void *con = NULL;
struct ConnectionAbstract {
void *con = NULL;
DbConnectionConfig dbdata;
DbConnectionConfig dbdata;
DatabaseType type = DatabaseType::UNDEFINED;
DatabaseType type = DatabaseType::UNDEFINED;
DatabaseStatus status = DatabaseStatus::CLOSED;
DatabaseStatus status = DatabaseStatus::CLOSED;
virtual void connect(DbConnectionConfig *dbdata = NULL)
{
return;
virtual void connect(DbConnectionConfig *dbdata = NULL)
{
return;
}
virtual void close()
{
if (this->con != NULL) {
free(con);
}
virtual void close()
{
if (this->con != NULL) {
free(con);
}
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
}
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
}
virtual QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
return QueryResult();
}
};
}
virtual QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
return QueryResult();
}
};
}
#endif

View File

@ -21,40 +21,37 @@
#include "PostgresqlConnection.h"
#include "SQLiteConnection.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
ConnectionAbstract *create_connection(DbConnectionConfig dbdata)
{
ConnectionAbstract *create_connection(DbConnectionConfig dbdata)
{
switch (dbdata.db) {
case DatabaseType::MYSQL:
return new MysqlConnection(dbdata);
case DatabaseType::PGSQL:
return new PostgresqlConnection(dbdata);
case DatabaseType::SQLSRV:
return NULL;
case DatabaseType::SQLITE:
return new SQLiteConnection(dbdata);
default:
return NULL;
}
switch (dbdata.db) {
case DatabaseType::MYSQL:
return new MysqlConnection(dbdata);
case DatabaseType::PGSQL:
return new PostgresqlConnection(dbdata);
case DatabaseType::SQLSRV:
return NULL;
case DatabaseType::SQLITE:
return new SQLiteConnection(dbdata);
default:
return NULL;
}
}
void close(ConnectionAbstract *db, DbConnectionConfig dbdata)
{
switch (dbdata.db) {
case DatabaseType::MYSQL:
return ((MysqlConnection *) db)->close();
case DatabaseType::PGSQL:
return ((PostgresqlConnection *) db)->close();
case DatabaseType::SQLSRV:
return;
case DatabaseType::SQLITE:
return ((SQLiteConnection *) db)->close();
default:
return;
}
void close(ConnectionAbstract *db, DbConnectionConfig dbdata)
{
switch (dbdata.db) {
case DatabaseType::MYSQL:
return ((MysqlConnection *) db)->close();
case DatabaseType::PGSQL:
return ((PostgresqlConnection *) db)->close();
case DatabaseType::SQLSRV:
return;
case DatabaseType::SQLITE:
return ((SQLiteConnection *) db)->close();
default:
return;
}
}
}

View File

@ -15,45 +15,42 @@
#include "../DatabaseType.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
typedef struct {
DatabaseType db = DatabaseType::UNDEFINED;
const char *database = NULL;
const char *host = NULL;
int port = 0;
const char *login = NULL;
const char *password = NULL;
} DbConnectionConfig;
void free_DbConnectionConfig(DbConnectionConfig *dbdata)
{
typedef struct {
DatabaseType db = DatabaseType::UNDEFINED;
if (dbdata->database != NULL) {
free((char *) dbdata->database);
dbdata->database = NULL;
}
const char *database = NULL;
if (dbdata->host != NULL) {
free((char *) dbdata->host);
dbdata->host = NULL;
}
const char *host = NULL;
if (dbdata->login != NULL) {
free((char *) dbdata->login);
dbdata->login = NULL;
}
int port = 0;
const char *login = NULL;
const char *password = NULL;
} DbConnectionConfig;
void free_DbConnectionConfig(DbConnectionConfig *dbdata)
{
if (dbdata->database != NULL) {
free((char *) dbdata->database);
dbdata->database = NULL;
}
if (dbdata->host != NULL) {
free((char *) dbdata->host);
dbdata->host = NULL;
}
if (dbdata->login != NULL) {
free((char *) dbdata->login);
dbdata->login = NULL;
}
if (dbdata->password != NULL) {
free((char *) dbdata->password);
dbdata->password = NULL;
}
if (dbdata->password != NULL) {
free((char *) dbdata->password);
dbdata->password = NULL;
}
}
}

View File

@ -20,131 +20,128 @@
#include "../DatabaseType.h"
#include "../DatabaseStatus.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
struct MysqlConnection : ConnectionAbstract {
MysqlConnection(DbConnectionConfig dbdata)
{
this->type = DatabaseType::MYSQL;
this->dbdata = dbdata;
}
struct MysqlConnection : ConnectionAbstract {
MysqlConnection(DbConnectionConfig dbdata)
{
this->type = DatabaseType::MYSQL;
this->dbdata = dbdata;
}
void connect(DbConnectionConfig *dbdata = NULL)
{
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
void connect(DbConnectionConfig *dbdata = NULL)
{
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
if (this->dbdata.db == DatabaseType::UNDEFINED
|| this->dbdata.host == NULL
|| this->dbdata.port == 0
|| this->dbdata.database == NULL
|| this->dbdata.login == NULL
|| this->dbdata.password == NULL
) {
this->status = DatabaseStatus::FAILURE;
if (this->dbdata.db == DatabaseType::UNDEFINED
|| this->dbdata.host == NULL
|| this->dbdata.port == 0
|| this->dbdata.database == NULL
|| this->dbdata.login == NULL
|| this->dbdata.password == NULL
) {
this->status = DatabaseStatus::FAILURE;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
this->close();
this->con = mysql_init(NULL);
this->con = mysql_real_connect(
(::MYSQL *) this->con,
this->dbdata.host,
this->dbdata.login,
this->dbdata.password,
this->dbdata.database,
this->dbdata.port,
NULL, 0
);
if (!this->con) {
this->status = DatabaseStatus::MISSING_DATABASE;
mysql_close((::MYSQL *) this->con);
this->con = NULL;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
void close()
{
if (this->con != NULL) {
mysql_close((::MYSQL *) this->con);
}
this->close();
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
this->con = mysql_init(NULL);
this->con = mysql_real_connect(
(::MYSQL *) this->con,
this->dbdata.host,
this->dbdata.login,
this->dbdata.password,
this->dbdata.database,
this->dbdata.port,
NULL, 0
);
if (!this->con) {
this->status = DatabaseStatus::MISSING_DATABASE;
mysql_close((::MYSQL *) this->con);
this->con = NULL;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
}
void close()
{
if (this->con != NULL) {
mysql_close((::MYSQL *) this->con);
}
QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
QueryResult result;
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
}
MYSQL_RES *res;
int status = 0;
QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
QueryResult result;
if (paramValues != NULL) {
return result;
} else {
status = mysql_query((::MYSQL *) this->con, stmt);
res = mysql_store_result((::MYSQL *) this->con);
}
MYSQL_RES *res;
int status = 0;
if (res == NULL) {
return result;
}
result.rows = mysql_num_rows(res);
result.columns = mysql_num_fields(res);
if (result.rows == 0 || result.columns == 0) {
return result;
}
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
char *temp = NULL;
size_t valLen = 0;
size_t *lengths;
::MYSQL_ROW row;
size_t i = 0;
while ((row = mysql_fetch_row(res)) != NULL) {
lengths = mysql_fetch_lengths(res);
for (int j = 0; j < result.columns; ++j) {
temp = row[j];
if (temp == NULL) {
result.results[i * result.columns + j] = NULL;
continue;
}
valLen = lengths[j];
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
memcpy(result.results[i * result.columns + j], temp, valLen);
result.results[i * result.columns + j][valLen] = '\0';
}
++i;
}
if (paramValues != NULL) {
return result;
} else {
status = mysql_query((::MYSQL *) this->con, stmt);
res = mysql_store_result((::MYSQL *) this->con);
}
if (res == NULL) {
return result;
}
};
}
result.rows = mysql_num_rows(res);
result.columns = mysql_num_fields(res);
if (result.rows == 0 || result.columns == 0) {
return result;
}
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
char *temp = NULL;
size_t valLen = 0;
size_t *lengths;
::MYSQL_ROW row;
size_t i = 0;
while ((row = mysql_fetch_row(res)) != NULL) {
lengths = mysql_fetch_lengths(res);
for (int j = 0; j < result.columns; ++j) {
temp = row[j];
if (temp == NULL) {
result.results[i * result.columns + j] = NULL;
continue;
}
valLen = lengths[j];
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
memcpy(result.results[i * result.columns + j], temp, valLen);
result.results[i * result.columns + j][valLen] = '\0';
}
++i;
}
return result;
}
};
}
#endif

View File

@ -20,125 +20,122 @@
#include "../DatabaseType.h"
#include "../DatabaseStatus.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
struct PostgresqlConnection : ConnectionAbstract {
PostgresqlConnection(DbConnectionConfig dbdata)
{
this->type = DatabaseType::PGSQL;
this->dbdata = dbdata;
}
struct PostgresqlConnection : ConnectionAbstract {
PostgresqlConnection(DbConnectionConfig dbdata)
{
this->type = DatabaseType::PGSQL;
this->dbdata = dbdata;
}
void connect(DbConnectionConfig *dbdata = NULL)
{
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
void connect(DbConnectionConfig *dbdata = NULL)
{
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
if (this->dbdata.db == DatabaseType::UNDEFINED
|| this->dbdata.host == NULL
|| this->dbdata.port == 0
|| this->dbdata.database == NULL
|| this->dbdata.login == NULL
|| this->dbdata.password == NULL
) {
this->status = DatabaseStatus::FAILURE;
if (this->dbdata.db == DatabaseType::UNDEFINED
|| this->dbdata.host == NULL
|| this->dbdata.port == 0
|| this->dbdata.database == NULL
|| this->dbdata.login == NULL
|| this->dbdata.password == NULL
) {
this->status = DatabaseStatus::FAILURE;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
this->close();
char port[12];
sprintf(port, "%d", this->dbdata.port);
this->con = PQsetdbLogin(
this->dbdata.host,
port,
NULL,
NULL,
this->dbdata.database,
this->dbdata.login,
this->dbdata.password
);
ConnStatusType stat = PQstatus((PGconn *) this->con);
if (stat != ConnStatusType::CONNECTION_OK) {
this->status = DatabaseStatus::MISSING_DATABASE;
PQfinish((PGconn *) this->con);
this->con = NULL;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
void close()
{
if (this->con != NULL) {
PQfinish((PGconn *) this->con);
}
this->close();
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
char port[12];
sprintf(port, "%d", this->dbdata.port);
this->con = PQsetdbLogin(
this->dbdata.host,
port,
NULL,
NULL,
this->dbdata.database,
this->dbdata.login,
this->dbdata.password
);
ConnStatusType stat = PQstatus((PGconn *) this->con);
if (stat != ConnStatusType::CONNECTION_OK) {
this->status = DatabaseStatus::MISSING_DATABASE;
PQfinish((PGconn *) this->con);
this->con = NULL;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
}
void close()
{
if (this->con != NULL) {
PQfinish((PGconn *) this->con);
}
QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
QueryResult result;
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
}
PGresult *res;
if (paramValues != NULL) {
res = PQexecParams((PGconn *) this->con, stmt, 1, NULL, (const char* const*) paramValues, NULL, NULL, 0);
} else {
res = PQexec((PGconn *) this->con, stmt);
}
QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
QueryResult result;
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
PQclear(res);
return result;
}
result.rows = PQntuples(res);
result.columns = PQnfields(res);
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
char *temp = NULL;
size_t valLen = 0;
for (size_t i = 0; i < result.rows; ++i) {
for (size_t j = 0; j < result.columns; ++j) {
temp = PQgetvalue(res, i, j);
if (temp == NULL) {
result.results[i * result.columns + j] = NULL;
continue;
}
valLen = strlen(temp);
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
memcpy(result.results[i * result.columns + j], temp, valLen);
result.results[i * result.columns + j][valLen] = '\0';
}
}
PGresult *res;
if (paramValues != NULL) {
res = PQexecParams((PGconn *) this->con, stmt, 1, NULL, (const char* const*) paramValues, NULL, NULL, 0);
} else {
res = PQexec((PGconn *) this->con, stmt);
}
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
PQclear(res);
return result;
}
};
}
result.rows = PQntuples(res);
result.columns = PQnfields(res);
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
char *temp = NULL;
size_t valLen = 0;
for (size_t i = 0; i < result.rows; ++i) {
for (size_t j = 0; j < result.columns; ++j) {
temp = PQgetvalue(res, i, j);
if (temp == NULL) {
result.results[i * result.columns + j] = NULL;
continue;
}
valLen = strlen(temp);
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
memcpy(result.results[i * result.columns + j], temp, valLen);
result.results[i * result.columns + j][valLen] = '\0';
}
}
PQclear(res);
return result;
}
};
}
#endif

View File

@ -20,142 +20,139 @@
#include "../DatabaseType.h"
#include "../DatabaseStatus.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
struct SQLiteConnection : ConnectionAbstract {
SQLiteConnection(DbConnectionConfig dbdata)
{
this->type = DatabaseType::MYSQL;
this->dbdata = dbdata;
}
struct SQLiteConnection : ConnectionAbstract {
SQLiteConnection(DbConnectionConfig dbdata)
{
this->type = DatabaseType::MYSQL;
this->dbdata = dbdata;
}
void connect(DbConnectionConfig *dbdata = NULL)
{
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
void connect(DbConnectionConfig *dbdata = NULL)
{
this->dbdata = dbdata == NULL ? this->dbdata : *dbdata;
if (this->dbdata.db == DatabaseType::UNDEFINED
|| this->dbdata.database == NULL
) {
this->status = DatabaseStatus::FAILURE;
if (this->dbdata.db == DatabaseType::UNDEFINED
|| this->dbdata.database == NULL
) {
this->status = DatabaseStatus::FAILURE;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
this->close();
int stat = sqlite3_open(this->dbdata.host, (sqlite3 **) &this->con);
if (stat != SQLITE_OK) {
this->status = DatabaseStatus::MISSING_DATABASE;
sqlite3_close((sqlite3 *) this->con);
this->con = NULL;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
void close()
{
if (this->con != NULL) {
sqlite3_close((sqlite3 *) this->con);
}
this->close();
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
int stat = sqlite3_open(this->dbdata.host, (sqlite3 **) &this->con);
if (stat != SQLITE_OK) {
this->status = DatabaseStatus::MISSING_DATABASE;
sqlite3_close((sqlite3 *) this->con);
this->con = NULL;
if (this->dbdata.password != NULL) {
free((char *) this->dbdata.password);
this->dbdata.password = NULL;
}
}
}
void close()
{
if (this->con != NULL) {
sqlite3_close((sqlite3 *) this->con);
}
QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
QueryResult result;
this->con = NULL;
this->status = DatabaseStatus::CLOSED;
}
sqlite3_stmt *res;
int status = 0;
QueryResult query_execute(char *stmt, char *paramValues = NULL)
{
QueryResult result;
if (paramValues != NULL) {
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
sqlite3_stmt *res;
int status = 0;
// @todo sqlite3_bind_int(res, 1, 3);
} else {
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
}
if (paramValues != NULL) {
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
if (res == NULL) {
return result;
}
// @todo sqlite3_bind_int(res, 1, 3);
} else {
status = sqlite3_prepare_v2((sqlite3 *) this->con, stmt, -1, &res, 0);
}
status = sqlite3_step(res);
if (res == NULL) {
return result;
}
result.rows = 100;
result.columns = sqlite3_column_count(res);
status = sqlite3_step(res);
if (result.rows == 0 || result.columns == 0) {
return result;
}
result.rows = 100;
result.columns = sqlite3_column_count(res);
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
if (result.rows == 0 || result.columns == 0) {
return result;
}
char *temp = NULL;
size_t valLen = 0;
char ** tempStorage = NULL;
result.results = (char **) malloc(result.rows * result.columns * sizeof(char*));
size_t i = 0;
while (status == SQLITE_ROW) {
if (i == result.rows) {
tempStorage = (char **) malloc((result.rows + 100) * result.columns * sizeof(char*));
memcpy(tempStorage, result.results, result.rows * result.columns * sizeof(char*));
char *temp = NULL;
size_t valLen = 0;
char ** tempStorage = NULL;
free(result.results);
result.results = tempStorage;
result.rows += 100;
}
for (int j = 0; j < result.columns; ++j) {
temp = (char *) sqlite3_column_text(res, j);
if (temp == NULL) {
result.results[i * result.columns + j] = NULL;
continue;
}
valLen = strlen(temp);
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
memcpy(result.results[i * result.columns + j], temp, valLen);
result.results[i * result.columns + j][valLen] = '\0';
}
status = sqlite3_step(res);
++i;
}
--i;
if (i != result.rows) {
tempStorage = (char **) malloc(i * result.columns * sizeof(char*));
memcpy(tempStorage, result.results, i * result.columns * sizeof(char*));
size_t i = 0;
while (status == SQLITE_ROW) {
if (i == result.rows) {
tempStorage = (char **) malloc((result.rows + 100) * result.columns * sizeof(char*));
memcpy(tempStorage, result.results, result.rows * result.columns * sizeof(char*));
free(result.results);
result.results = tempStorage;
result.rows = i;
result.rows += 100;
}
sqlite3_finalize(res);
for (int j = 0; j < result.columns; ++j) {
temp = (char *) sqlite3_column_text(res, j);
return result;
if (temp == NULL) {
result.results[i * result.columns + j] = NULL;
continue;
}
valLen = strlen(temp);
result.results[i * result.columns + j] = (char *) malloc((valLen + 1) * sizeof(char));
memcpy(result.results[i * result.columns + j], temp, valLen);
result.results[i * result.columns + j][valLen] = '\0';
}
status = sqlite3_step(res);
++i;
}
};
}
--i;
if (i != result.rows) {
tempStorage = (char **) malloc(i * result.columns * sizeof(char*));
memcpy(tempStorage, result.results, i * result.columns * sizeof(char*));
free(result.results);
result.results = tempStorage;
result.rows = i;
}
sqlite3_finalize(res);
return result;
}
};
}
#endif

View File

@ -10,19 +10,16 @@
#ifndef DATASTORAGE_DATABASE_STATUS_H
#define DATASTORAGE_DATABASE_STATUS_H
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
typedef enum {
OK = 0,
MISSING_DATABASE = 1,
MISSING_TABLE = 2,
FAILURE = 3,
READONLY = 4,
CLOSED = 5
} DatabaseStatus;
}
typedef enum {
OK = 0,
MISSING_DATABASE = 1,
MISSING_TABLE = 2,
FAILURE = 3,
READONLY = 4,
CLOSED = 5
} DatabaseStatus;
}
#endif

View File

@ -12,32 +12,29 @@
#include <string.h>
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
typedef enum {
MYSQL = 1,
SQLITE = 2,
PGSQL = 3,
SQLSRV = 4,
UNDEFINED = 5
} DatabaseType;
typedef enum {
MYSQL = 1,
SQLITE = 2,
PGSQL = 3,
SQLSRV = 4,
UNDEFINED = 5
} DatabaseType;
DatabaseType database_type_from_str(const char* type)
{
if (strcmp(type, "mysql") == 0) {
return DatabaseType::MYSQL;
} else if (strcmp(type, "sqlite") == 0) {
return DatabaseType::SQLITE;
} else if (strcmp(type, "pqsql") == 0) {
return DatabaseType::PGSQL;
} else if (strcmp(type, "mssql") == 0) {
return DatabaseType::SQLSRV;
}
return DatabaseType::UNDEFINED;
DatabaseType database_type_from_str(const char* type)
{
if (strcmp(type, "mysql") == 0) {
return DatabaseType::MYSQL;
} else if (strcmp(type, "sqlite") == 0) {
return DatabaseType::SQLITE;
} else if (strcmp(type, "pqsql") == 0) {
return DatabaseType::PGSQL;
} else if (strcmp(type, "mssql") == 0) {
return DatabaseType::SQLSRV;
}
return DatabaseType::UNDEFINED;
}
}

View File

@ -18,42 +18,39 @@
#include "ReadMapper.h"
#include "MapperAbstract.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
static DataStorage::Database::ConnectionAbstract *db;
static const char *dateTimeFormat = "Y-m-d H:i:s";
static DataStorage::Database::ConnectionAbstract *db;
static const char *dateTimeFormat = "Y-m-d H:i:s";
struct DataMapperFactory {
static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
{
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
readMapper->mapper = mapper;
readMapper->db = db == NULL ? DataStorage::Database::db : db;
struct DataMapperFactory {
static ReadMapper *reader(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
{
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
readMapper->mapper = mapper;
readMapper->db = db == NULL ? DataStorage::Database::db : db;
return readMapper;
}
return readMapper;
}
static ReadMapper *get(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
{
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
readMapper->mapper = mapper;
readMapper->db = db == NULL ? DataStorage::Database::db : db;
static ReadMapper *get(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
{
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
readMapper->mapper = mapper;
readMapper->db = db == NULL ? DataStorage::Database::db : db;
return readMapper->get();
}
return readMapper->get();
}
static ReadMapper *getAll(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
{
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
readMapper->mapper = mapper;
readMapper->db = db == NULL ? DataStorage::Database::db : db;
static ReadMapper *getAll(const DataStorage::Database::MapperData *mapper, DataStorage::Database::ConnectionAbstract *db = NULL)
{
ReadMapper *readMapper = (ReadMapper *) malloc(sizeof(ReadMapper));
readMapper->mapper = mapper;
readMapper->db = db == NULL ? DataStorage::Database::db : db;
return readMapper->getAll();
}
};
}
return readMapper->getAll();
}
};
}
#endif

View File

@ -13,208 +13,205 @@
#include <stdio.h>
#include <stdlib.h>
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
typedef enum {
MAPPER_DEFAULT = 0,
MAPPER_GET = 1,
MAPPER_GET_ALL = 4,
MAPPER_FIND = 7,
MAPPER_GET_RAW = 8,
MAPPER_GET_RANDOM = 11,
MAPPER_COUNT_MODELS = 12,
MAPPER_CREATE = 1001,
MAPPER_UPDATE = 2001,
MAPPER_DELETE = 3001
} MapperType;
typedef enum {
FIELD_TYPE_INT = 1,
FIELD_TYPE_FLOAT = 2,
FIELD_TYPE_STRING = 3,
FIELD_TYPE_BOOL = 4
} FieldType;
typedef struct {
const char *name = NULL;
size_t size = 0;
} ModelStructure;
void free_ModelStructure(ModelStructure *data)
{
typedef enum {
MAPPER_DEFAULT = 0,
MAPPER_GET = 1,
MAPPER_GET_ALL = 4,
MAPPER_FIND = 7,
MAPPER_GET_RAW = 8,
MAPPER_GET_RANDOM = 11,
MAPPER_COUNT_MODELS = 12,
MAPPER_CREATE = 1001,
MAPPER_UPDATE = 2001,
MAPPER_DELETE = 3001
} MapperType;
/* Not necessary
if (data->name != NULL) {
free((void *) data->name);
}
*/
}
typedef enum {
FIELD_TYPE_INT = 1,
FIELD_TYPE_FLOAT = 2,
FIELD_TYPE_STRING = 3,
FIELD_TYPE_BOOL = 4
} FieldType;
typedef struct {
const char *name = NULL;
int type = FieldType::FIELD_TYPE_INT;
const char *internal = NULL;
bool readonly = false;
bool autocomplete = false;
} DataMapperColumn;
typedef struct {
const char *name = NULL;
size_t size = 0;
} ModelStructure;
void free_ModelStructure(ModelStructure *data)
{
/* Not necessary
if (data->name != NULL) {
free((void *) data->name);
}
*/
void free_DataMapperColumn(DataMapperColumn *data)
{
if (data->name != NULL) {
free((void *) data->name);
}
typedef struct {
const char *name = NULL;
int type = FieldType::FIELD_TYPE_INT;
const char *internal = NULL;
bool readonly = false;
bool autocomplete = false;
} DataMapperColumn;
if (data->internal != NULL) {
free((void *) data->internal);
}
}
void free_DataMapperColumn(DataMapperColumn *data)
{
if (data->name != NULL) {
free((void *) data->name);
}
typedef struct {
const char *member = NULL;
const char *mapper = NULL;
const char *external = NULL;
const char *table = NULL;
const char *self = NULL;
const char *column = NULL;
bool conditional = false;
const char *by = NULL;
} TableRelation;
if (data->internal != NULL) {
free((void *) data->internal);
}
void free_TableRelation(TableRelation *data)
{
/* Not necessary
if (data->member != NULL) {
free((void *) data->member);
}
typedef struct {
const char *member = NULL;
const char *mapper = NULL;
const char *external = NULL;
const char *table = NULL;
const char *self = NULL;
const char *column = NULL;
bool conditional = false;
const char *by = NULL;
} TableRelation;
void free_TableRelation(TableRelation *data)
{
/* Not necessary
if (data->member != NULL) {
free((void *) data->member);
}
if (data->mapper != NULL) {
free((void *) data->mapper);
}
if (data->external != NULL) {
free((void *) data->external);
}
if (data->table != NULL) {
free((void *) data->table);
}
if (data->self != NULL) {
free((void *) data->self);
}
if (data->column != NULL) {
free((void *) data->column);
}
if (data->self != NULL) {
free((void *) data->self);
}
if (data->by != NULL) {
free((void *) data->by);
}
*/
if (data->mapper != NULL) {
free((void *) data->mapper);
}
typedef struct {
const char *TABLE = NULL;
const char *PRIMARYFIELD = NULL;
const char *CREATED_AT = NULL;
const char *PARENT = NULL;
void *MODEL = NULL;
if (data->external != NULL) {
free((void *) data->external);
}
int MEMBER_COUNT = 0;
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
if (data->table != NULL) {
free((void *) data->table);
}
int COLUMN_COUNT = 0;
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
if (data->self != NULL) {
free((void *) data->self);
}
int OWNS_ONE_COUNT = 0;
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
if (data->column != NULL) {
free((void *) data->column);
}
int HAS_MANY_COUNT = 0;
DataStorage::Database::TableRelation *HAS_MANY = NULL;
if (data->self != NULL) {
free((void *) data->self);
}
int BELONGS_TO_COUNT = 0;
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
} MapperData;
if (data->by != NULL) {
free((void *) data->by);
}
*/
}
void free_MapperData(DataStorage::Database::MapperData *data)
{
/* Not necessary
if (data->TABLE != NULL) {
free((void *) data->TABLE);
}
typedef struct {
const char *TABLE = NULL;
const char *PRIMARYFIELD = NULL;
const char *CREATED_AT = NULL;
const char *PARENT = NULL;
void *MODEL = NULL;
if (data->PRIMARYFIELD != NULL) {
free((void *) data->PRIMARYFIELD);
}
int MEMBER_COUNT = 0;
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
if (data->CREATED_AT != NULL) {
free((void *) data->CREATED_AT);
}
int COLUMN_COUNT = 0;
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
if (data->PARENT != NULL) {
free((void *) data->PARENT);
}
int OWNS_ONE_COUNT = 0;
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
if (data->MODEL != NULL) {
free(data->MODEL);
int HAS_MANY_COUNT = 0;
DataStorage::Database::TableRelation *HAS_MANY = NULL;
int BELONGS_TO_COUNT = 0;
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
} MapperData;
void free_MapperData(DataStorage::Database::MapperData *data)
{
/* Not necessary
if (data->TABLE != NULL) {
free((void *) data->TABLE);
}
if (data->PRIMARYFIELD != NULL) {
free((void *) data->PRIMARYFIELD);
}
if (data->CREATED_AT != NULL) {
free((void *) data->CREATED_AT);
}
if (data->PARENT != NULL) {
free((void *) data->PARENT);
}
if (data->MODEL != NULL) {
free(data->MODEL);
}
*/
int i = 0;
if (data->MODEL_STRUCTURE != NULL) {
/* not neccessary
for (i = 0; i < data->MEMBER_COUNT; ++i) {
free_ModelStructure(&data->MODEL_STRUCTURE[i]);
}
*/
int i = 0;
if (data->MODEL_STRUCTURE != NULL) {
/* not neccessary
for (i = 0; i < data->MEMBER_COUNT; ++i) {
free_ModelStructure(&data->MODEL_STRUCTURE[i]);
}
*/
free(data->MODEL_STRUCTURE);
}
free(data->MODEL_STRUCTURE);
if (data->COLUMNS != NULL) {
/* not neccessary
for (i = 0; i < data->COLUMN_COUNT; ++i) {
free_DataMapperColumn(&data->COLUMNS[i]);
}
*/
if (data->COLUMNS != NULL) {
/* not neccessary
for (i = 0; i < data->COLUMN_COUNT; ++i) {
free_DataMapperColumn(&data->COLUMNS[i]);
}
*/
free(data->COLUMNS);
}
free(data->COLUMNS);
if (data->OWNS_ONE != NULL) {
/* not neccessary
for (i = 0; i < data->OWNS_ONE_COUNT; ++i) {
free_TableRelation(&data->OWNS_ONE[i]);
}
*/
if (data->OWNS_ONE != NULL) {
/* not neccessary
for (i = 0; i < data->OWNS_ONE_COUNT; ++i) {
free_TableRelation(&data->OWNS_ONE[i]);
}
*/
free(data->OWNS_ONE);
}
free(data->OWNS_ONE);
if (data->HAS_MANY != NULL) {
/* not neccessary
for (i = 0; i < data->HAS_MANY_COUNT; ++i) {
free_TableRelation(&data->HAS_MANY[i]);
}
*/
if (data->HAS_MANY != NULL) {
/* not neccessary
for (i = 0; i < data->HAS_MANY_COUNT; ++i) {
free_TableRelation(&data->HAS_MANY[i]);
}
*/
free(data->HAS_MANY);
}
free(data->HAS_MANY);
if (data->BELONGS_TO != NULL) {
/* not neccessary
for (i = 0; i < data->BELONGS_TO_COUNT; ++i) {
free_TableRelation(&data->BELONGS_TO[i]);
}
*/
if (data->BELONGS_TO != NULL) {
/* not neccessary
for (i = 0; i < data->BELONGS_TO_COUNT; ++i) {
free_TableRelation(&data->BELONGS_TO[i]);
}
*/
free(data->BELONGS_TO);
}
free(data->BELONGS_TO);
}
}
}

View File

@ -12,96 +12,94 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "../Connection/ConnectionAbstract.h"
#include "DataMapperTypes.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
struct MapperAbstract {
const DataStorage::Database::MapperData *mapper = NULL;
struct MapperAbstract {
const DataStorage::Database::MapperData *mapper = NULL;
const DataStorage::Database::ConnectionAbstract *db = NULL;
const DataStorage::Database::ConnectionAbstract *db = NULL;
DataStorage::Database::MapperType type = DataStorage::Database::MapperType::MAPPER_DEFAULT;
DataStorage::Database::MapperType type = DataStorage::Database::MapperType::MAPPER_DEFAULT;
int MEMBERS = 0;
int MEMBERS = 0;
int COLUMN_COUNT = 0;
int COLUMN_COUNT = 0;
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
DataStorage::Database::ModelStructure *MODEL_STRUCTURE = NULL;
char *PRIMARYFIELD = NULL;
char *PRIMARYFIELD = NULL;
bool AUTOINCREMENT = true;
bool AUTOINCREMENT = true;
char *CREATE_AT = NULL;
char *CREATE_AT = NULL;
char *TABLE = NULL;
char *TABLE = NULL;
char *PARENT = NULL;
char *PARENT = NULL;
char *MODEL = NULL;
char *MODEL = NULL;
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
DataStorage::Database::DataMapperColumn *COLUMNS = NULL;
DataStorage::Database::TableRelation *HAS_MANY = NULL;
DataStorage::Database::TableRelation *HAS_MANY = NULL;
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
DataStorage::Database::TableRelation *OWNS_ONE = NULL;
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
DataStorage::Database::TableRelation *BELONGS_TO = NULL;
void *address(uintptr_t objPos, char *name)
{
uintptr_t pos = objPos;
for (int i = 0; i < this->MEMBERS; ++i) {
if (strcmp(this->MODEL_STRUCTURE[i].name, name) == 0) {
return (void *) pos;
}
pos += this->MODEL_STRUCTURE[i].size;
void *address(uintptr_t objPos, char *name)
{
uintptr_t pos = objPos;
for (int i = 0; i < this->MEMBERS; ++i) {
if (strcmp(this->MODEL_STRUCTURE[i].name, name) == 0) {
return (void *) pos;
}
return NULL;
pos += this->MODEL_STRUCTURE[i].size;
}
DataMapperColumn *findByColumnName(char *column)
{
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
if (strcmp(this->COLUMNS[i].name, column) == 0) {
return &this->COLUMNS[i];
}
return NULL;
}
DataMapperColumn *findByColumnName(char *column)
{
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
if (strcmp(this->COLUMNS[i].name, column) == 0) {
return &this->COLUMNS[i];
}
return NULL;
}
DataMapperColumn *findByMemberName(char *member)
{
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
if (strcmp(this->COLUMNS[i].internal, member) == 0) {
return &this->COLUMNS[i];
}
return NULL;
}
DataMapperColumn *findByMemberName(char *member)
{
for (int i = 0; i < this->COLUMN_COUNT; ++i) {
if (strcmp(this->COLUMNS[i].internal, member) == 0) {
return &this->COLUMNS[i];
}
return NULL;
}
MapperAbstract *where(
char *member,
void *value,
int valueType,
const char *logic = "=",
const char *connector = "AND"
) {
return this;
}
return NULL;
}
virtual void *execute(void *options = NULL);
};
}
MapperAbstract *where(
char *member,
void *value,
int valueType,
const char *logic = "=",
const char *connector = "AND"
) {
return this;
}
virtual void *execute(void *options = NULL);
};
}
#endif

View File

@ -17,54 +17,51 @@
#include "DataMapperFactory.h"
#include "MapperAbstract.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
{
struct ReadMapper : MapperAbstract {
ReadMapper *get()
{
return this;
}
struct ReadMapper : MapperAbstract {
ReadMapper *get()
{
return this;
}
ReadMapper *getAll()
{
return this;
}
ReadMapper *getAll()
{
return this;
}
void *execute(void *options = NULL)
{
switch(this->type) {
case DataStorage::Database::MapperType::MAPPER_GET:
return this->executeGet(options);
case DataStorage::Database::MapperType::MAPPER_GET_RAW:
return this->executeGetRaw(options);
case DataStorage::Database::MapperType::MAPPER_GET_ALL:
return this->executeGetAll(options);
default:
return NULL;
};
}
void *execute(void *options = NULL)
{
switch(this->type) {
case DataStorage::Database::MapperType::MAPPER_GET:
return this->executeGet(options);
case DataStorage::Database::MapperType::MAPPER_GET_RAW:
return this->executeGetRaw(options);
case DataStorage::Database::MapperType::MAPPER_GET_ALL:
return this->executeGetAll(options);
default:
return NULL;
};
}
void *executeGet(void *options)
{
int *primaryKeys = NULL;
const char *memberOfPrimaryField = findByColumnName((char *) this->mapper->PRIMARYFIELD)->internal;
void *executeGet(void *options)
{
int *primaryKeys = NULL;
const char *memberOfPrimaryField = findByColumnName((char *) this->mapper->PRIMARYFIELD)->internal;
return NULL;
}
return NULL;
}
void *executeGetRaw(void *options)
{
return NULL;
}
void *executeGetRaw(void *options)
{
return NULL;
}
void *executeGetAll(void *options)
{
return NULL;
}
};
}
void *executeGetAll(void *options)
{
return NULL;
}
};
}
#endif

View File

@ -13,48 +13,45 @@
#include <stdio.h>
#include <stdlib.h>
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
typedef struct {
char *name;
char *type;
void *def;
bool is_nullable = true;
bool is_primary = false;
bool is_unique = false;
bool autoincrement = false;
char *foreignTable;
char *foreignKey;
} DbField;
void free_DbField(DbField *field)
{
typedef struct {
char *name;
char *type;
void *def;
bool is_nullable = true;
bool is_primary = false;
bool is_unique = false;
bool autoincrement = false;
char *foreignTable;
char *foreignKey;
} DbField;
if (field->name != NULL) {
free(field->name);
field->name = NULL;
}
void free_DbField(DbField *field)
{
if (field->name != NULL) {
free(field->name);
field->name = NULL;
}
if (field->type != NULL) {
free(field->type);
field->type = NULL;
}
if (field->type != NULL) {
free(field->type);
field->type = NULL;
}
if (field->def != NULL) {
free(field->def);
field->def = NULL;
}
if (field->def != NULL) {
free(field->def);
field->def = NULL;
}
if (field->foreignTable != NULL) {
free(field->foreignTable);
field->foreignTable = NULL;
}
if (field->foreignTable != NULL) {
free(field->foreignTable);
field->foreignTable = NULL;
}
if (field->foreignKey != NULL) {
free(field->foreignKey);
field->foreignKey = NULL;
}
if (field->foreignKey != NULL) {
free(field->foreignKey);
field->foreignKey = NULL;
}
}
}

View File

@ -15,31 +15,28 @@
#include "DbField.h"
namespace DataStorage
namespace DataStorage::Database
{
namespace Database
typedef struct {
char *name;
DbField *fields;
size_t field_size = 0;
} DbSchema;
void free_DbSchema(DbSchema *schema)
{
typedef struct {
char *name;
DbField *fields;
size_t field_size = 0;
} DbSchema;
if (schema->name != NULL) {
free(schema->name);
schema->name = NULL;
}
void free_DbSchema(DbSchema *schema)
{
if (schema->name != NULL) {
free(schema->name);
schema->name = NULL;
if (schema->fields != NULL) {
for (int i = 0; i < schema->field_size; ++i) {
free_DbField(&schema->fields[i]);
}
if (schema->fields != NULL) {
for (int i = 0; i < schema->field_size; ++i) {
free_DbField(&schema->fields[i]);
}
free(schema->fields);
schema->fields = NULL;
}
free(schema->fields);
schema->fields = NULL;
}
}
}

View File

@ -2,6 +2,8 @@
#define HASH_MD5_H
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
// https://www.rfc-editor.org/rfc/rfc1321
@ -37,7 +39,7 @@ namespace Hash {
uint32_t a, b, c, d;
uint32_t aa, bb, cc, dd;
ptr = data;
ptr = (const unsigned char *) data;
a = ctx->a;
b = ctx->b;

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;
const uint8_t *p = data;
const uint8_t *p = (uint8_t *) data;
while (len > 0) {
/*

View File

@ -14,67 +14,64 @@
#include <opencv2/opencv.hpp>
#include <vector>
namespace Image
namespace Image::BillDetection
{
namespace BillDetection
cv::Mat highlightBill(cv::Mat in)
{
cv::Mat highlightBill(cv::Mat in)
{
cv::Mat gray;
cv::cvtColor(in, gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0);
cv::Mat gray;
cv::cvtColor(in, gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0);
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9, 9));
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9, 9));
cv::Mat dilated;
cv::dilate(gray, dilated, kernel);
cv::Mat dilated;
cv::dilate(gray, dilated, kernel);
cv::Mat edges;
cv::Canny(dilated, edges, 84, 3);
cv::Mat edges;
cv::Canny(dilated, edges, 84, 3);
std::vector<cv::Vec4i> lines;
lines.clear();
std::vector<cv::Vec4i> lines;
lines.clear();
cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25);
cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25);
std::vector<cv::Vec4i>::iterator it = lines.begin();
for(; it != lines.end(); ++it) {
cv::Vec4i l = *it;
cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8);
}
std::vector<std::vector<cv::Point>> contours;
cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_KCOS);
std::vector<std::vector<cv::Point>> contoursCleaned;
for (int i = 0; i < contours.size(); ++i) {
if (cv::arcLength(contours[i], false) > 100) {
contoursCleaned.push_back(contours[i]);
}
}
std::vector<std::vector<cv::Point>> contoursArea;
for (int i = 0; i < contoursCleaned.size(); ++i) {
if (cv::contourArea(contoursCleaned[i]) > 10000) {
contoursArea.push_back(contoursCleaned[i]);
}
}
// Approximate polygon
/* Question: we probably don't want a polygon all the time?! */
// @todo bad implementation, focus on single square
std::vector<std::vector<cv::Point> > contoursDraw (contoursArea.size());
for (int i = 0; i < contoursArea.size(); ++i){
cv::approxPolyDP(cv::Mat(contoursArea[i]), contoursDraw[i], 40, true);
}
cv::Mat mask = cv::Mat(in.size(), CV_8UC3, cv::Scalar(255, 255, 255));
cv::drawContours(mask, contoursDraw, -1, cv::Scalar(0, 0, 0), cv::FILLED, 1);
cv::Mat out = cv::Mat::zeros(in.size(), CV_8UC3);
cv::bitwise_or(in, mask, out);
return out;
std::vector<cv::Vec4i>::iterator it = lines.begin();
for(; it != lines.end(); ++it) {
cv::Vec4i l = *it;
cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8);
}
std::vector<std::vector<cv::Point>> contours;
cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_KCOS);
std::vector<std::vector<cv::Point>> contoursCleaned;
for (int i = 0; i < contours.size(); ++i) {
if (cv::arcLength(contours[i], false) > 100) {
contoursCleaned.push_back(contours[i]);
}
}
std::vector<std::vector<cv::Point>> contoursArea;
for (int i = 0; i < contoursCleaned.size(); ++i) {
if (cv::contourArea(contoursCleaned[i]) > 10000) {
contoursArea.push_back(contoursCleaned[i]);
}
}
// Approximate polygon
/* Question: we probably don't want a polygon all the time?! */
// @todo bad implementation, focus on single square
std::vector<std::vector<cv::Point> > contoursDraw (contoursArea.size());
for (int i = 0; i < contoursArea.size(); ++i){
cv::approxPolyDP(cv::Mat(contoursArea[i]), contoursDraw[i], 40, true);
}
cv::Mat mask = cv::Mat(in.size(), CV_8UC3, cv::Scalar(255, 255, 255));
cv::drawContours(mask, contoursDraw, -1, cv::Scalar(0, 0, 0), cv::FILLED, 1);
cv::Mat out = cv::Mat::zeros(in.size(), CV_8UC3);
cv::bitwise_or(in, mask, out);
return out;
}
}

View File

@ -13,36 +13,23 @@
#include <stdio.h>
#include <math.h>
namespace Image
namespace Image::ImageUtils
{
namespace ImageUtils
inline
float lightnessFromRgb(int r, int g, int b)
{
inline
float lightnessFromRgb(int r, int g, int b)
{
float vR = r / 255.0;
float vG = g / 255.0;
float vB = b / 255.0;
float vR = r / 255.0;
float vG = g / 255.0;
float vB = b / 255.0;
float lR = vR <= 0.04045 ? vR / 12.92 : pow(((vR + 0.055) / 1.055), 2.4);
float lG = vG <= 0.04045 ? vG / 12.92 : pow(((vG + 0.055) / 1.055), 2.4);
float lB = vB <= 0.04045 ? vB / 12.92 : pow(((vB + 0.055) / 1.055), 2.4);
float lR = vR <= 0.04045 ? vR / 12.92 : pow(((vR + 0.055) / 1.055), 2.4);
float lG = vG <= 0.04045 ? vG / 12.92 : pow(((vG + 0.055) / 1.055), 2.4);
float lB = vB <= 0.04045 ? vB / 12.92 : pow(((vB + 0.055) / 1.055), 2.4);
float y = 0.2126 * lR + 0.7152 * lG + 0.0722 * lB;
float lStar = y <= 216.0 / 24389.0 ? y * 24389.0 / 27.0 : pow(y, (1.0 / 3.0)) * 116.0 - 16.0;
float y = 0.2126 * lR + 0.7152 * lG + 0.0722 * lB;
float lStar = y <= 216.0 / 24389.0 ? y * 24389.0 / 27.0 : pow(y, (1.0 / 3.0)) * 116.0 - 16.0;
return lStar / 100.0;
}
inline
int rgbToInt(int r, int g, int b)
{
int rgb = r;
rgb = (rgb << 8) + g;
rgb = (rgb << 8) + b;
return rgb;
}
return lStar / 100.0;
}
}

View File

@ -16,7 +16,7 @@
#include "ImageUtils.h"
#include "../Utils/MathUtils.h"
namespace Image
namespace Image::Kernel
{
const float KERNEL_RIDGE_1[3][3] = {
{0.0, -1.0, 0.0},
@ -62,19 +62,16 @@ namespace Image
{-1.0 / 256.0, -4.0 / 256.0, -6.0 / 256.0, -4.0 / 256.0, -1.0 / 256.0},
};
namespace Kernel
inline
cv::Mat convolve(cv::Mat in, const float kernel[][3])
{
inline
cv::Mat convolve(cv::Mat in, const float kernel[][3])
{
cv::Size dim = in.size();
cv::Mat out(in.size(), in.type());
cv::Size dim = in.size();
cv::Mat out(in.size(), in.type());
cv::Mat mKernel(3, 3, CV_32F, (float *) kernel);
cv::filter2D(in, out, -1, mKernel);
cv::Mat mKernel(3, 3, CV_32F, (float *) kernel);
cv::filter2D(in, out, -1, mKernel);
return out;
}
return out;
}
}

View File

@ -16,77 +16,74 @@
#include "../Utils/MathUtils.h"
namespace Image
namespace Image::Skew
{
namespace Skew
cv::Mat deskewHoughLines(cv::Mat in, int maxDegree = 45)
{
cv::Mat deskewHoughLines(cv::Mat in, int maxDegree = 45)
{
cv::Size dim = in.size();
cv::Size dim = in.size();
cv::Mat inv;
cv::cvtColor(in, inv, cv::COLOR_BGR2GRAY);
cv::threshold(inv, inv, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
cv::Mat inv;
cv::cvtColor(in, inv, cv::COLOR_BGR2GRAY);
cv::threshold(inv, inv, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
std::vector<cv::Vec4i> lines;
cv::HoughLinesP(inv, lines, 1.0, OMS_PI / 180, 200, dim.width / 12, dim.width / 150);
std::vector<cv::Vec4i> lines;
cv::HoughLinesP(inv, lines, 1.0, OMS_PI / 180, 200, dim.width / 12, dim.width / 150);
int imageOrientation = 0; // > 0 -> image is horizontal
int imageOrientation = 0; // > 0 -> image is horizontal
std::vector<float> tmpAngles;
for (int i = 0; i < lines.size(); ++i) {
float angle = atan2(lines[i][3] - lines[i][1], lines[i][2] - lines[i][0]);
tmpAngles.push_back(angle);
std::vector<float> tmpAngles;
for (int i = 0; i < lines.size(); ++i) {
float angle = atan2(lines[i][3] - lines[i][1], lines[i][2] - lines[i][0]);
tmpAngles.push_back(angle);
imageOrientation += oms_abs(angle) > OMS_PI / 4 ? 1 : -1;
}
imageOrientation += oms_abs(angle) > OMS_PI / 4 ? 1 : -1;
}
std::vector<float> angles;
for (int i = 0; i < tmpAngles.size(); ++i) {
if (imageOrientation > 0) {
if (oms_deg2rad(90 - maxDegree) < oms_abs(tmpAngles[i]) && oms_abs(tmpAngles[i]) < oms_deg2rad(90 + maxDegree)) {
angles.push_back(tmpAngles[i]);
}
} else {
if (oms_abs(tmpAngles[i]) < oms_deg2rad(maxDegree)) {
angles.push_back(tmpAngles[i]);
}
}
}
if (angles.size() < 5) {
return in;
}
float median = 0.0;
for (int i = 0; i < angles.size(); ++i) {
median += angles[i];
}
float angleDeg = oms_rad2deg(median / angles.size());
cv::Mat orientFix;
std::vector<float> angles;
for (int i = 0; i < tmpAngles.size(); ++i) {
if (imageOrientation > 0) {
if (angleDeg < 0) {
cv::rotate(in, orientFix, cv::ROTATE_90_CLOCKWISE);
angleDeg += 90.0;
} else if (angleDeg > 0) {
cv::rotate(in, orientFix, cv::ROTATE_90_COUNTERCLOCKWISE);
angleDeg -= 90.0;
} else {
orientFix = in;
if (oms_deg2rad(90 - maxDegree) < oms_abs(tmpAngles[i]) && oms_abs(tmpAngles[i]) < oms_deg2rad(90 + maxDegree)) {
angles.push_back(tmpAngles[i]);
}
} else {
if (oms_abs(tmpAngles[i]) < oms_deg2rad(maxDegree)) {
angles.push_back(tmpAngles[i]);
}
}
}
if (angles.size() < 5) {
return in;
}
float median = 0.0;
for (int i = 0; i < angles.size(); ++i) {
median += angles[i];
}
float angleDeg = oms_rad2deg(median / angles.size());
cv::Mat orientFix;
if (imageOrientation > 0) {
if (angleDeg < 0) {
cv::rotate(in, orientFix, cv::ROTATE_90_CLOCKWISE);
angleDeg += 90.0;
} else if (angleDeg > 0) {
cv::rotate(in, orientFix, cv::ROTATE_90_COUNTERCLOCKWISE);
angleDeg -= 90.0;
} else {
orientFix = in;
}
cv::Mat rot = cv::getRotationMatrix2D(cv::Point2f(dim.width / 2, dim.height / 2), angleDeg, 1.0);
cv::Mat out;
cv::warpAffine(orientFix, out, rot, dim, cv::INTER_LINEAR, cv::BORDER_REPLICATE);
return out;
} else {
orientFix = in;
}
cv::Mat rot = cv::getRotationMatrix2D(cv::Point2f(dim.width / 2, dim.height / 2), angleDeg, 1.0);
cv::Mat out;
cv::warpAffine(orientFix, out, rot, dim, cv::INTER_LINEAR, cv::BORDER_REPLICATE);
return out;
}
}

View File

@ -16,65 +16,62 @@
#include "ImageUtils.h"
#include "../Utils/MathUtils.h"
namespace Image
namespace Image::Thresholding
{
namespace Thresholding
cv::Mat integralThresholding(cv::Mat in)
{
cv::Mat integralThresholding(cv::Mat in)
{
cv::Size dim = in.size();
cv::Mat out(dim, in.type());
cv::Size dim = in.size();
cv::Mat out(dim, in.type());
float *intImg = (float *) malloc(dim.width * dim.height * sizeof(float));
float sum;
float *intImg = (float *) malloc(dim.width * dim.height * sizeof(float));
float sum;
cv::Vec3b bgr;
for (int i = 0; i < dim.width; ++i) {
sum = 0.0;
cv::Vec3b bgr;
for (int i = 0; i < dim.width; ++i) {
sum = 0.0;
for (int j = 0; j < dim.height; ++j) {
bgr = in.at<cv::Vec3b>(j, i);
sum += Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
for (int j = 0; j < dim.height; ++j) {
bgr = in.at<cv::Vec3b>(j, i);
sum += Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
intImg[i * j] = i == 0 ? sum : intImg[(i - 1) * j] + sum;
}
intImg[i * j] = i == 0 ? sum : intImg[(i - 1) * j] + sum;
}
int s = dim.width / 96.0;
int t = 30;
int x1, x2;
int y1, y2;
int count;
float brightness;
int color;
for (int i = 0; i < dim.width; ++i) {
for (int j = 0; j < dim.height; ++j) {
x1 = oms_max(1, i - s / 2.0);
x2 = oms_min(i + s / 2.0, dim.width - 1);
y1 = oms_max(1, j - s / 2.0);
y2 = oms_min(j + s / 2.0, dim.height - 1);
count = (x2 - x1) * (y2 - y1);
sum = intImg[x2 * y2] - intImg[x2 * (y1 - 1)] - intImg[(x1 - 1) * y2] + intImg[(x1 - 1) * (y1 - 1)];
bgr = in.at<cv::Vec3b>(j, i);
brightness = Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
color = brightness * count <= (sum * (100.0 - t) / 100.0) && brightness < 0.95 ? 0 : 255;
out.at<cv::Vec3b>(j, i)[0] = color;
out.at<cv::Vec3b>(j, i)[1] = color;
out.at<cv::Vec3b>(j, i)[2] = color;
}
}
free(intImg);
return out;
}
int s = dim.width / 96.0;
int t = 30;
int x1, x2;
int y1, y2;
int count;
float brightness;
int color;
for (int i = 0; i < dim.width; ++i) {
for (int j = 0; j < dim.height; ++j) {
x1 = oms_max(1, i - s / 2.0);
x2 = oms_min(i + s / 2.0, dim.width - 1);
y1 = oms_max(1, j - s / 2.0);
y2 = oms_min(j + s / 2.0, dim.height - 1);
count = (x2 - x1) * (y2 - y1);
sum = intImg[x2 * y2] - intImg[x2 * (y1 - 1)] - intImg[(x1 - 1) * y2] + intImg[(x1 - 1) * (y1 - 1)];
bgr = in.at<cv::Vec3b>(j, i);
brightness = Image::ImageUtils::lightnessFromRgb(bgr[2], bgr[1], bgr[0]);
color = brightness * count <= (sum * (100.0 - t) / 100.0) && brightness < 0.95 ? 0 : 255;
out.at<cv::Vec3b>(j, i)[0] = color;
out.at<cv::Vec3b>(j, i)[1] = color;
out.at<cv::Vec3b>(j, i)[2] = color;
}
}
free(intImg);
return out;
}
}

View File

@ -16,205 +16,202 @@
#include "../Hash/MeowHash.h"
namespace Stdlib
namespace Stdlib::HashTable
{
namespace HashTable
typedef struct {
const char *key;
void *value;
} entry;
struct ht {
bool is_fixed = false;
entry *entries;
size_t max;
size_t size;
};
typedef struct {
const char *key;
void *value;
ht *table;
size_t index;
} it;
inline
unsigned long long hash_key(const char *key)
{
typedef struct {
const char *key;
void *value;
} entry;
struct ht {
bool is_fixed = false;
entry *entries;
size_t max;
size_t size;
};
typedef struct {
const char *key;
void *value;
ht *table;
size_t index;
} it;
inline
unsigned long long hash_key(const char *key)
{
return (unsigned long long) MeowU64From(
Hash::Meow::MeowHash(Hash::Meow::MeowDefaultSeed,
strlen(key),
(void *) key),
0
);
}
ht *create_table(int max = 0, bool is_fixed = false)
{
ht *table = (ht *) malloc(sizeof(ht));
if (table == NULL) {
return NULL;
}
table->size = 0;
table->max = max == 0 ? 16 : max;
table->is_fixed = is_fixed;
table->entries = (entry *) calloc(table->max, sizeof(entry));
if (table->entries == NULL) {
free(table);
return NULL;
}
return table;
}
void *get_entry(ht *table, const char *key)
{
unsigned long long hash = hash_key(key);
size_t index = (size_t) (hash & (unsigned long long)(table->max - 1));
while (table->entries[index].key != NULL) {
if (strcmp(key, table->entries[index].key) == 0) {
return table->entries[index].value;
}
++index;
if (index >= table->max) {
index = 0;
}
}
return (unsigned long long) MeowU64From(
Hash::Meow::MeowHash(Hash::Meow::MeowDefaultSeed,
strlen(key),
(void *) key),
0
);
}
ht *create_table(int max = 0, bool is_fixed = false)
{
ht *table = (ht *) malloc(sizeof(ht));
if (table == NULL) {
return NULL;
}
const char *_set_entry(entry *entries, size_t max, const char *key, void *value, size_t *size)
{
unsigned long long hash = hash_key(key);
size_t index = (size_t) (hash & (unsigned long long)(max - 1));
table->size = 0;
table->max = max == 0 ? 16 : max;
table->is_fixed = is_fixed;
while (entries[index].key != NULL) {
if (strcmp(key, entries[index].key) == 0) {
entries[index].value = value;
return entries[index].key;
}
++index;
if (index >= max) {
index = 0;
}
}
if (size != NULL) {
#ifdef _WIN32
key = _strdup(key);
#else
key = strdup(key);
#endif
if (key == NULL) {
return NULL;
}
++(*size);
}
entries[index].key = (char *) key;
entries[index].value = value;
return key;
table->entries = (entry *) calloc(table->max, sizeof(entry));
if (table->entries == NULL) {
free(table);
return NULL;
}
bool expand_table(ht *table)
{
size_t new_max = table->max * 2;
if (new_max < table->max) {
return false;
return table;
}
void *get_entry(ht *table, const char *key)
{
unsigned long long hash = hash_key(key);
size_t index = (size_t) (hash & (unsigned long long)(table->max - 1));
while (table->entries[index].key != NULL) {
if (strcmp(key, table->entries[index].key) == 0) {
return table->entries[index].value;
}
entry *new_entries = (entry *) calloc(new_max, sizeof(entry));
if (new_entries == NULL) {
return false;
++index;
if (index >= table->max) {
index = 0;
}
for (size_t i = 0; i < table->max; ++i) {
entry tmp = table->entries[i];
if (tmp.key != NULL) {
_set_entry(new_entries, new_max, tmp.key, tmp.value, NULL);
}
}
free(table->entries);
table->entries = new_entries;
table->max = new_max;
return true;
}
const char *set_entry(ht *table, const char *key, void *value)
{
if (value == NULL) {
return NULL;
}
const char *_set_entry(entry *entries, size_t max, const char *key, void *value, size_t *size)
{
unsigned long long hash = hash_key(key);
size_t index = (size_t) (hash & (unsigned long long)(max - 1));
while (entries[index].key != NULL) {
if (strcmp(key, entries[index].key) == 0) {
entries[index].value = value;
return entries[index].key;
}
++index;
if (index >= max) {
index = 0;
}
}
if (size != NULL) {
#ifdef _WIN32
key = _strdup(key);
#else
key = strdup(key);
#endif
if (key == NULL) {
return NULL;
}
if (table->is_fixed && table->size == table->max) {
return NULL;
}
if (!table->is_fixed && table->size >= table->max / 2) {
if (!expand_table(table)) {
return NULL;
}
}
return _set_entry(table->entries, table->max, key, value, &table->size);
++(*size);
}
it table_iterator(ht *table)
{
it it;
it.table = table;
it.index = 0;
entries[index].key = (char *) key;
entries[index].value = value;
return it;
}
bool next(it *it)
{
ht *table = it->table;
while (it->index < table->max) {
size_t i = it->index;
++(it->index);
if (table->entries[i].key != NULL) {
entry tmp = table->entries[i];
it->key = tmp.key;
it->value = tmp.value;
return true;
}
}
return key;
}
bool expand_table(ht *table)
{
size_t new_max = table->max * 2;
if (new_max < table->max) {
return false;
}
void free_table(ht *table)
{
if (!table || !table->entries) {
return;
}
for (size_t i = 0; i < table->max; ++i) {
if (table->entries[i].key) {
free((void *) table->entries[i].key);
}
}
free(table->entries);
entry *new_entries = (entry *) calloc(new_max, sizeof(entry));
if (new_entries == NULL) {
return false;
}
for (size_t i = 0; i < table->max; ++i) {
entry tmp = table->entries[i];
if (tmp.key != NULL) {
_set_entry(new_entries, new_max, tmp.key, tmp.value, NULL);
}
}
free(table->entries);
table->entries = new_entries;
table->max = new_max;
return true;
}
const char *set_entry(ht *table, const char *key, void *value)
{
if (value == NULL) {
return NULL;
}
if (table->is_fixed && table->size == table->max) {
return NULL;
}
if (!table->is_fixed && table->size >= table->max / 2) {
if (!expand_table(table)) {
return NULL;
}
}
return _set_entry(table->entries, table->max, key, value, &table->size);
}
it table_iterator(ht *table)
{
it it;
it.table = table;
it.index = 0;
return it;
}
bool next(it *it)
{
ht *table = it->table;
while (it->index < table->max) {
size_t i = it->index;
++(it->index);
if (table->entries[i].key != NULL) {
entry tmp = table->entries[i];
it->key = tmp.key;
it->value = tmp.value;
return true;
}
}
return false;
}
void free_table(ht *table)
{
if (!table || !table->entries) {
return;
}
for (size_t i = 0; i < table->max; ++i) {
if (table->entries[i].key) {
free((void *) table->entries[i].key);
}
}
free(table->entries);
}
}

View File

@ -48,9 +48,7 @@ namespace Utils
if (pos != NULL) {
memcpy(dir, arg, (pos - arg) * sizeof(char));
chdir(dir);
free(dir);
}
}

View File

@ -13,48 +13,45 @@
#include <stdio.h>
#include <stdlib.h>
namespace Utils
namespace Utils::ArraySort
{
namespace ArraySort
inline
void reverse_int(int64_t *arr, size_t size)
{
inline
void reverse_int(int64_t *arr, size_t size)
{
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
int64_t tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
int64_t tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
}
inline
void reverse_float(float *arr, size_t size)
{
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
float tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
inline
void reverse_float(float *arr, size_t size)
{
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
float tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
}
inline
void reverse_double(double *arr, size_t size)
{
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
double tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
inline
void reverse_double(double *arr, size_t size)
{
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
double tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
}
inline
void reverse_char(char **arr, size_t size)
{
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
char* tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
inline
void reverse_char(char **arr, size_t size)
{
for (size_t low = 0, high = size - 1; low < high; ++low, --high) {
char* tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
}
}
}

View File

@ -16,195 +16,192 @@
#include "StringUtils.h"
namespace Utils
namespace Utils::ArrayUtils
{
namespace ArrayUtils
inline
char* get_arg(const char *id, char **argv, size_t size)
{
inline
char* get_arg(const char *id, char **argv, size_t size)
{
if (Utils::StringUtils::is_number(id)) {
return argv[atoi(id)];
}
if (Utils::StringUtils::is_number(id)) {
return argv[atoi(id)];
}
for (size_t i = 0; i < size - 1; ++i) {
if (strcmp(id, argv[i]) == 0) {
return i + 1 >= size ? NULL : argv[i + 1];
}
for (size_t i = 0; i < size - 1; ++i) {
if (strcmp(id, argv[i]) == 0) {
return i + 1 >= size ? NULL : argv[i + 1];
}
}
return NULL;
}
inline
bool has_arg(const char *id, char **argv, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (strcmp(id, argv[i]) == 0) {
return true;
}
}
return false;
}
inline
double array_sum_double(double *array, size_t size)
{
double sum = 0.0;
for (size_t i = 0; i < size; ++i) {
sum += array[i];
}
return sum;
}
inline
float array_sum_float(float *array, size_t size)
{
float sum = 0.0;
for (size_t i = 0; i < size; ++i) {
sum += array[i];
}
return sum;
}
inline
int64_t array_sum_int(int64_t *array, size_t size)
{
int64_t sum = 0;
for (size_t i = 0; i < size; ++i) {
sum += array[i];
}
return sum;
}
inline
size_t find_in_array_string(const char *element, const char **array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (strcmp(element, array[i]) == 0) {
return i;
}
}
return -1;
}
inline
size_t find_in_array_double(double element, double *array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (array[i] == element) {
return i;
}
}
return -1;
}
inline
size_t find_in_array_float(float element, float *array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (array[i] == element) {
return i;
}
}
return -1;
}
inline
size_t find_in_array_int(int64_t element, int64_t *array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (array[i] == element) {
return i;
}
}
return -1;
}
inline
double* merge_arrays_double(double* array1, size_t size1, double* array2, size_t size2)
{
double* merged = (double*) malloc((size1 + size2) * sizeof(double));
if (merged == NULL) {
return NULL;
}
inline
bool has_arg(const char *id, char **argv, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (strcmp(id, argv[i]) == 0) {
return true;
}
}
return false;
for (size_t i = 0; i < size1; ++i) {
merged[i] = array1[i];
}
inline
double array_sum_double(double *array, size_t size)
{
double sum = 0.0;
for (size_t i = 0; i < size; ++i) {
sum += array[i];
}
return sum;
for (size_t i = 0; i < size2; ++i) {
merged[size1 + i] = array2[i];
}
inline
float array_sum_float(float *array, size_t size)
{
float sum = 0.0;
for (size_t i = 0; i < size; ++i) {
sum += array[i];
}
return merged;
}
return sum;
inline
float* merge_arrays_float(float* array1, size_t size1, float* array2, size_t size2)
{
float* merged = (float*) malloc((size1 + size2) * sizeof(float));
if (merged == NULL) {
return NULL;
}
inline
int64_t array_sum_int(int64_t *array, size_t size)
{
int64_t sum = 0;
for (size_t i = 0; i < size; ++i) {
sum += array[i];
}
return sum;
for (size_t i = 0; i < size1; ++i) {
merged[i] = array1[i];
}
inline
size_t find_in_array_string(const char *element, const char **array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (strcmp(element, array[i]) == 0) {
return i;
}
}
return -1;
for (size_t i = 0; i < size2; ++i) {
merged[size1 + i] = array2[i];
}
inline
size_t find_in_array_double(double element, double *array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (array[i] == element) {
return i;
}
}
return merged;
}
return -1;
inline
int64_t* merge_arrays_int(int64_t* array1, size_t size1, int64_t* array2, size_t size2)
{
int64_t* merged = (int64_t*) malloc((size1 + size2) * sizeof(int64_t));
if (merged == NULL) {
return NULL;
}
inline
size_t find_in_array_float(float element, float *array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (array[i] == element) {
return i;
}
}
return -1;
for (size_t i = 0; i < size1; ++i) {
merged[i] = array1[i];
}
inline
size_t find_in_array_int(int64_t element, int64_t *array, size_t size)
{
for (size_t i = 0; i < size; ++i) {
if (array[i] == element) {
return i;
}
}
return -1;
for (size_t i = 0; i < size2; ++i) {
merged[size1 + i] = array2[i];
}
inline
double* merge_arrays_double(double* array1, size_t size1, double* array2, size_t size2)
{
double* merged = (double*) malloc((size1 + size2) * sizeof(double));
if (merged == NULL) {
return NULL;
}
return merged;
}
for (size_t i = 0; i < size1; ++i) {
merged[i] = array1[i];
}
for (size_t i = 0; i < size2; ++i) {
merged[size1 + i] = array2[i];
}
return merged;
char** merge_arrays_char(const char** array1, size_t size1, const char** array2, size_t size2)
{
char** merged = (char**) malloc((size1 + size2) * sizeof(char*));
if (merged == NULL) {
return NULL;
}
inline
float* merge_arrays_float(float* array1, size_t size1, float* array2, size_t size2)
{
float* merged = (float*) malloc((size1 + size2) * sizeof(float));
if (merged == NULL) {
return NULL;
}
for (size_t i = 0; i < size1; ++i) {
merged[i] = array1[i];
}
for (size_t i = 0; i < size2; ++i) {
merged[size1 + i] = array2[i];
}
return merged;
for (size_t i = 0; i < size1; ++i) {
merged[i] = (char*) malloc((strlen(array1[i]) + 1) * sizeof(char));
strcpy(merged[i], array1[i]);
}
inline
int64_t* merge_arrays_int(int64_t* array1, size_t size1, int64_t* array2, size_t size2)
{
int64_t* merged = (int64_t*) malloc((size1 + size2) * sizeof(int64_t));
if (merged == NULL) {
return NULL;
}
for (size_t i = 0; i < size1; ++i) {
merged[i] = array1[i];
}
for (size_t i = 0; i < size2; ++i) {
merged[size1 + i] = array2[i];
}
return merged;
for (size_t i = 0; i < size2; ++i) {
merged[i] = (char*) malloc((strlen(array2[i]) + 1) * sizeof(char));
strcpy(merged[i], array2[i]);
}
char** merge_arrays_char(const char** array1, size_t size1, const char** array2, size_t size2)
{
char** merged = (char**) malloc((size1 + size2) * sizeof(char*));
if (merged == NULL) {
return NULL;
}
for (size_t i = 0; i < size1; ++i) {
merged[i] = (char*) malloc((strlen(arr1[i]) + 1) * sizeof(char));
strcpy(merged[i], arr1[i]);
}
for (size_t i = 0; i < size2; ++i) {
merged[i] = (char*) malloc((strlen(arr2[i]) + 1) * sizeof(char));
strcpy(merged[i], arr2[i]);
}
return merged;
}
return merged;
}
}

57
Utils/ColorUtils.h Normal file
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"
namespace Utils
namespace Utils::FileUtils
{
namespace FileUtils
inline
bool file_exists (const char *filename)
{
inline
bool file_exists (const char *filename)
{
#ifdef _WIN32
return access(filename, 0) == 0;
#else
struct stat buffer;
return stat(filename, &buffer) == 0;
#endif
}
#ifdef _WIN32
return access(filename, 0) == 0;
#else
struct stat buffer;
return stat(filename, &buffer) == 0;
#endif
}
inline
time_t last_modification (const char *filename)
{
#ifdef _WIN32
FILETIME modtime;
HANDLE h;
inline
time_t last_modification (const char *filename)
{
#ifdef _WIN32
FILETIME modtime;
HANDLE h;
size_t nameLength = strlen(filename);
size_t nameLength = strlen(filename);
wchar_t *wtext = (wchar_t *) calloc(nameLength, sizeof(char));
mbstowcs_s(NULL, wtext, nameLength, filename, nameLength);
LPWSTR pFilename = wtext;
if (!pFilename) {
free(wtext);
return 0;
}
h = CreateFileW(pFilename, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, 0, NULL);
wchar_t *wtext = (wchar_t *) calloc(nameLength, sizeof(char));
mbstowcs_s(NULL, wtext, nameLength, filename, nameLength);
LPWSTR pFilename = wtext;
if (!pFilename) {
free(wtext);
free(pFilename);
if (h == INVALID_HANDLE_VALUE) {
return (time_t) 0;
}
return 0;
}
if (GetFileTime(h, NULL, NULL, &modtime) == 0) {
return (time_t) 0;
}
h = CreateFileW(pFilename, GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, 0, NULL);
unsigned long long seconds = ((unsigned long long) (modtime.dwHighDateTime)) << 32;
seconds |= modtime.dwLowDateTime;
free(wtext);
free(pFilename);
return (seconds - 116444736000000000) / 10000000;
#else
struct stat buffer;
stat(filename, &buffer);
if (h == INVALID_HANDLE_VALUE) {
return (time_t) 0;
}
return (time_t) buffer.st_mtim.tv_sec;
#endif
if (GetFileTime(h, NULL, NULL, &modtime) == 0) {
return (time_t) 0;
}
return (time_t) 0;
unsigned long long seconds = ((unsigned long long) (modtime.dwHighDateTime)) << 32;
seconds |= modtime.dwLowDateTime;
return (seconds - 116444736000000000) / 10000000;
#else
struct stat buffer;
stat(filename, &buffer);
return (time_t) buffer.st_mtim.tv_sec;
#endif
return (time_t) 0;
}
inline
const char* file_extension (const char *filename)
{
char *dot = strrchr((char *) filename, '.');
if (!dot || dot == filename) {
return "";
}
inline
const char* file_extension (const char *filename)
{
char *dot = strrchr((char *) filename, '.');
return dot + 1;
}
if (!dot || dot == filename) {
return "";
}
typedef struct {
char *content;
int size = 0; // doesn't include null termination (same as strlen)
} file_body;
return dot + 1;
file_body read_file (const char *filename)
{
file_body file = {0};
FILE *fp = fopen(filename, "rb");
if (!fp) {
return file;
}
typedef struct {
char *content;
int size = 0; // doesn't include null termination (same as strlen)
} file_body;
fseek(fp, 0, SEEK_END);
file.size = ftell(fp);
fseek(fp, 0, SEEK_SET);
file_body read_file (const char *filename)
{
file_body file = {0};
FILE *fp = fopen(filename, "rb");
if (!fp) {
return file;
}
fseek(fp, 0, SEEK_END);
file.size = ftell(fp);
fseek(fp, 0, SEEK_SET);
file.content = (char *) malloc((file.size + 1) * sizeof(char));
if (!file.content) {
fprintf(stderr, "CRITICAL: malloc failed");
return file;
}
fread(file.content, file.size, 1, fp);
file.content[file.size] = 0;
fclose(fp);
file.content = (char *) malloc((file.size + 1) * sizeof(char));
if (!file.content) {
fprintf(stderr, "CRITICAL: malloc failed");
return file;
}
fread(file.content, file.size, 1, fp);
file.content[file.size] = 0;
fclose(fp);
return file;
}
}

View File

@ -14,30 +14,26 @@
#include <stdlib.h>
#include <time.h>
namespace Utils
namespace Utils::Rng::StringUtils
{
namespace Rng
{
namespace StringUtils
{
inline
char* generate_string(
size_t min = 10, size_t max = 10,
char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", int charsetLength = 62
) {
srand(time(0));
inline
char* generate_string(
size_t min = 10, size_t max = 10,
char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", int charsetLength = 62
) {
srand(time(0));
size_t length = (rand() % (max - min + 1)) + min;
char *randomString = (char *) malloc(length + 1);
size_t length = (rand() % (max - min + 1)) + min;
char *randomString = (char *) malloc(length + 1);
for (size_t i = 0; i < length; ++i) {
randomString[i] = charset[rand() % charsetLength];
}
randomString[length] = '\0';
return randomString;
}
for (size_t i = 0; i < length; ++i) {
randomString[i] = charset[rand() % charsetLength];
}
randomString[length] = '\0';
return randomString;
}
}
}
#endif

View File

@ -17,212 +17,223 @@
#include "MathUtils.h"
#include "ArraySort.h"
namespace Utils
namespace Utils::StringUtils
{
namespace StringUtils
inline
char *search_replace(const char *haystack, const char *needle, const char *replace)
{
inline
char *search_replace(const char *haystack, const char *needle, const char *replace)
{
const char *haystackT = haystack;
const char *haystackT = haystack;
size_t i;
size_t match = 0;
size_t oldLength = strlen(needle);
size_t newLength = strlen(replace);
size_t i;
size_t match = 0;
size_t oldLength = strlen(needle);
size_t newLength = strlen(replace);
for (i = 0; haystack[i] != '\0'; ++i) {
if (strstr(&haystack[i], needle) == &haystack[i]) {
++match;
for (i = 0; haystack[i] != '\0'; ++i) {
if (strstr(&haystack[i], needle) == &haystack[i]) {
++match;
i += oldLength - 1;
}
i += oldLength - 1;
}
char *result = (char *) malloc(i + match * (newLength - oldLength) + 1);
if (!result) {
return NULL;
}
size_t c = 0;
while (*haystack && c < i + match * (newLength - oldLength)) {
if (strstr(haystack, needle) == haystack) {
strcpy(&result[c], (char *) replace);
c += newLength;
haystack += oldLength;
} else {
result[c++] = *haystack++;
}
}
if (c > i + match * (newLength - oldLength)) {
c = i + match * (newLength - oldLength);
}
result[c] = '\0';
return result;
}
inline
bool is_number(const char *s)
{
while (*s != '\0') {
if (!isdigit(*s)) {
return false;
}
++s;
}
return true;
char *result = (char *) malloc(i + match * (newLength - oldLength) + 1);
if (!result) {
return NULL;
}
inline
size_t str_count(char *str, char *substr)
{
int l1 = strlen(str);
int l2 = strlen(substr);
size_t c = 0;
while (*haystack && c < i + match * (newLength - oldLength)) {
if (strstr(haystack, needle) == haystack) {
strcpy(&result[c], (char *) replace);
if (l2 == 0 || l1 < l2) {
return 0;
c += newLength;
haystack += oldLength;
} else {
result[c++] = *haystack++;
}
int count = 0;
for (str = strstr(str, substr); str; str = strstr(str + l2, substr)) {
++count;
}
return count;
}
char *strsep(char **sp, char *sep)
{
char *p, *s;
if (sp == NULL || *sp == NULL || **sp == '\0') {
return(NULL);
}
s = *sp;
p = s + strcspn(s, sep);
if (*p != '\0') {
*p++ = '\0';
}
*sp = p;
return(s);
if (c > i + match * (newLength - oldLength)) {
c = i + match * (newLength - oldLength);
}
int str_split(char **list, char *str, const char delim)
{
size_t splits = str_count(str, (char *) &delim) + 1;
list = (char **) malloc(splits * sizeof(char *));
result[c] = '\0';
char *token;
int i = 0;
return result;
}
while ((token = strsep(&str, (char *) &delim)) != NULL) {
list[i] = (char *) malloc(strlen(token + 1) * sizeof(char));
memcpy(list[i], token, (strlen(token) + 1) * sizeof(char));
++i;
inline
bool is_number(const char *s)
{
while (*s != '\0') {
if (!isdigit(*s)) {
return false;
}
return i;
++s;
}
typedef struct {
char **values;
int *masks;
int size;
} text_diff;
return true;
}
text_diff computeLCSDiff(char **from, int fromSize, char **to, int toSize)
{
char **diffValues = (char **) malloc(fromSize * toSize * sizeof(char *));
int *diffMasks = (int *) calloc(fromSize * toSize, sizeof(int));
inline
size_t str_count(char *str, char *substr)
{
int l1 = strlen(str);
int l2 = strlen(substr);
int *dm = (int *) calloc((fromSize + 1) * (toSize + 1), sizeof(int));
if (l2 == 0 || l1 < l2) {
return 0;
}
if (!diffValues || !diffMasks || !dm) {
fprintf(stderr, "CRITICAL: malloc failed");
int count = 0;
for (str = strstr(str, substr); str; str = strstr(str + l2, substr)) {
++count;
}
return count;
}
inline
char *strsep(char **sp, char *sep)
{
char *p, *s;
if (sp == NULL || *sp == NULL || **sp == '\0') {
return(NULL);
}
s = *sp;
p = s + strcspn(s, sep);
if (*p != '\0') {
*p++ = '\0';
}
*sp = p;
return(s);
}
// @todo Implement delim as const char* (also allow \0 length)
inline
int str_split(char **list, char *str, const char delim)
{
size_t splits = str_count(str, (char *) &delim) + 1;
list = (char **) malloc(splits * sizeof(char *));
char *token;
int i = 0;
while ((token = strsep(&str, (char *) &delim)) != NULL) {
list[i] = (char *) malloc(strlen(token + 1) * sizeof(char));
memcpy(list[i], token, (strlen(token) + 1) * sizeof(char));
++i;
}
return i;
}
// @todo Implement delim as const char* (also allow \0 length)
inline
char* str_combine(char **str, size_t size, const char delim)
{
if (size < 1) {
return NULL;
}
size_t total_size = 0;
for (size_t i = 0; i < size; ++i) {
total_size += strlen(str[i]);
}
// If delim ever becomes a string replace * 1 with * strlen(delimiter)
total_size += (size - 1) * 1 + 1;
char *result = (char *) malloc(total_size * sizeof(char));
if (!result) {
return NULL;
}
strcpy(result, str[0]);
for (size_t i = 0; i < size; ++i) {
strcat(result, &delim);
strcat(result, str[i]);
}
return result;
}
typedef struct {
char **values;
int64_t *masks;
size_t size;
} text_diff;
text_diff computeLCSDiff(char **from, int fromSize, char **to, int toSize)
{
char **diffValues = (char **) malloc(fromSize * toSize * sizeof(char *));
int64_t *diffMasks = (int64_t *) calloc(fromSize * toSize, sizeof(int64_t));
int *dm = (int *) calloc((fromSize + 1) * (toSize + 1), sizeof(int));
if (!diffValues || !diffMasks || !dm) {
fprintf(stderr, "CRITICAL: malloc failed");
}
int i = 0;
int j = 0;
/* Handled with calloc
for (j = 0; j <= toSize; ++j) {
dm[0 + j] = 0;
}
for (i = 1; i <= fromSize; ++i) {
dm[i * fromSize + 0] = 0;
}
*/
for (i = 1; i <= fromSize; ++i) {
for (j = 1; j <= toSize; ++j) {
dm[i * fromSize + j] = strcmp(from[i - 1], to[j - 1]) == 0
? dm[(i - 1) * fromSize + (j - 1)] + 1
: oms_max(dm[(i - 1) * fromSize + j], dm[i * fromSize + (j - 1)]);
}
}
int i = 0;
int j = 0;
size_t diffIndex = 0;
/* Handled with calloc
for (j = 0; j <= toSize; ++j) {
dm[0 + j] = 0;
}
i = fromSize;
j = toSize;
for (i = 1; i <= fromSize; ++i) {
dm[i * fromSize + 0] = 0;
}
*/
for (i = 1; i <= fromSize; ++i) {
for (j = 1; j <= toSize; ++j) {
dm[i * fromSize + j] = strcmp(from[i - 1], to[j - 1]) == 0
? dm[(i - 1) * fromSize + (j - 1)] + 1
: oms_max(dm[(i - 1) * fromSize + j], dm[i * fromSize + (j - 1)]);
}
}
int diffIndex = 0;
i = fromSize;
j = toSize;
while ((i > 0 || j > 0) && diffIndex < fromSize * toSize) {
if (j > 0 && dm[i * fromSize + (j - 1)] == dm[i * fromSize + j]) {
diffValues[diffIndex] = (char *) malloc((strlen(to[j - 1]) + 1) * sizeof(char));
if (!diffValues[diffIndex]) {
fprintf(stderr, "CRITICAL: malloc failed");
continue;
}
#ifdef _WIN32
strcpy_s(diffValues[diffIndex], (strlen(to[j - 1]) + 1) * sizeof(char), to[j - 1]);
#else
strcpy(diffValues[diffIndex], to[j - 1]);
#endif
diffMasks[diffIndex] = 1;
--j;
++diffIndex;
while ((i > 0 || j > 0) && diffIndex < fromSize * toSize) {
if (j > 0 && dm[i * fromSize + (j - 1)] == dm[i * fromSize + j]) {
diffValues[diffIndex] = (char *) malloc((strlen(to[j - 1]) + 1) * sizeof(char));
if (!diffValues[diffIndex]) {
fprintf(stderr, "CRITICAL: malloc failed");
continue;
}
if (i > 0 && dm[(i - 1) * fromSize + j] == dm[i * fromSize + j]) {
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
if (!diffValues[diffIndex]) {
fprintf(stderr, "CRITICAL: malloc failed");
#ifdef _WIN32
strcpy_s(diffValues[diffIndex], (strlen(to[j - 1]) + 1) * sizeof(char), to[j - 1]);
#else
strcpy(diffValues[diffIndex], to[j - 1]);
#endif
continue;
}
diffMasks[diffIndex] = 1;
#ifdef _WIN32
strcpy_s(diffValues[diffIndex], (strlen(from[i - 1]) + 1) * sizeof(char), from[i - 1]);
#else
strcpy(diffValues[diffIndex], from[i - 1]);
#endif
--j;
++diffIndex;
diffMasks[diffIndex] = -1;
--i;
++diffIndex;
continue;
}
continue;
}
if (i > 0 && dm[(i - 1) * fromSize + j] == dm[i * fromSize + j]) {
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
if (!diffValues[diffIndex]) {
fprintf(stderr, "CRITICAL: malloc failed");
@ -236,41 +247,61 @@ namespace Utils
strcpy(diffValues[diffIndex], from[i - 1]);
#endif
/* Handled with calloc
diffMasks[diffIndex] = 0;
*/
diffMasks[diffIndex] = -1;
--i;
--j;
++diffIndex;
continue;
}
free(dm);
// @todo do we even need to realloc?
char **diffValuesT = (char **) realloc(diffValues, diffIndex * sizeof(char *));
if (!diffValuesT) {
free(diffValues);
}
diffValues = diffValuesT;
int *diffMasksT = (int *) realloc(diffMasks, diffIndex * sizeof(int));
if (!diffMasksT) {
free(diffMasks);
}
diffMasks = diffMasksT;
if (!diffValues || !diffMasks) {
diffValues[diffIndex] = (char *) malloc((strlen(from[i - 1]) + 1) * sizeof(char));
if (!diffValues[diffIndex]) {
fprintf(stderr, "CRITICAL: malloc failed");
return text_diff{};
continue;
}
ArraySort::reverse_char(diffValues, diffIndex);
ArraySort::reverse_int(diffMasks, diffIndex);
#ifdef _WIN32
strcpy_s(diffValues[diffIndex], (strlen(from[i - 1]) + 1) * sizeof(char), from[i - 1]);
#else
strcpy(diffValues[diffIndex], from[i - 1]);
#endif
return text_diff{diffValues, diffMasks, diffIndex};
/* Handled with calloc
diffMasks[diffIndex] = 0;
*/
--i;
--j;
++diffIndex;
}
free(dm);
// @todo do we even need to realloc?
char **diffValuesT = (char **) realloc(diffValues, diffIndex * sizeof(char *));
if (!diffValuesT) {
free(diffValues);
}
diffValues = diffValuesT;
int64_t *diffMasksT = (int64_t *) realloc(diffMasks, diffIndex * sizeof(int64_t));
if (!diffMasksT) {
free(diffMasks);
}
diffMasks = diffMasksT;
if (!diffValues || !diffMasks) {
fprintf(stderr, "CRITICAL: malloc failed");
return text_diff{};
}
ArraySort::reverse_char(diffValues, diffIndex);
ArraySort::reverse_int(diffMasks, diffIndex);
return text_diff{diffValues, diffMasks, diffIndex};
}
}

View File

@ -23,276 +23,273 @@
#include "FileUtils.h"
namespace Utils
namespace Utils::WebUtils
{
namespace WebUtils
static bool CURL_SETUP = false;
inline
void setup()
{
static bool CURL_SETUP = false;
curl_global_init(CURL_GLOBAL_DEFAULT);
Utils::WebUtils::CURL_SETUP = true;
}
inline
void setup()
{
curl_global_init(CURL_GLOBAL_DEFAULT);
Utils::WebUtils::CURL_SETUP = true;
}
inline
void clean()
{
curl_global_cleanup();
Utils::WebUtils::CURL_SETUP = false;
}
inline
void clean()
{
curl_global_cleanup();
Utils::WebUtils::CURL_SETUP = false;
}
int write_download_data (void *ptr, size_t size, size_t nmeb, void *stream)
{
Utils::FileUtils::file_body *out = (Utils::FileUtils::file_body *) stream;
size_t outSize = size * nmeb;
int write_download_data (void *ptr, size_t size, size_t nmeb, void *stream)
{
Utils::FileUtils::file_body *out = (Utils::FileUtils::file_body *) stream;
size_t outSize = size * nmeb;
if (out->size == 0) {
// first time this function is called for a specific resource
out->content = (char *) malloc((outSize + 1) * sizeof(char));
if (!out->content) {
fprintf(stderr, "CRITICAL: malloc failed");
if (out->size == 0) {
// first time this function is called for a specific resource
out->content = (char *) malloc((outSize + 1) * sizeof(char));
if (!out->content) {
fprintf(stderr, "CRITICAL: malloc failed");
return 0;
}
if (out->content) {
memcpy(out->content, ptr, outSize * sizeof(char));
out->size = (int) outSize;
out->content[out->size] = 0;
}
} else {
// the max buffer (16384 = 16k) is exceeded, then this is called again and needs to get extended
char *temp = (char *) malloc((outSize + out->size + 1) * sizeof(char));
memcpy(temp, out->content, out->size * sizeof(char));
memcpy(temp + out->size * sizeof(char), ptr, outSize * sizeof(char));
free(out->content);
out->content = temp;
out->size += outSize;
out->content[out->size] = 0;
}
return out->size;
}
typedef struct {
size_t size = 0;
const char **resources = NULL;
} ResourceTypes;
typedef struct {
size_t size = 0;
const char **urls = NULL;
} Urls;
Utils::FileUtils::file_body download (char *url)
{
Utils::FileUtils::file_body page = {0};
if (!Utils::WebUtils::CURL_SETUP) {
Utils::WebUtils::setup();
}
CURL *h = curl_easy_init();
curl_easy_setopt(h, CURLOPT_URL, url);
curl_easy_setopt(h, CURLOPT_PRIVATE, url);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
curl_easy_setopt(h, CURLOPT_WRITEDATA, &page);
curl_easy_perform(h);
curl_easy_cleanup(h);
return page;
}
inline
void add_transfer(CURLM *cm, char *url, int *left)
{
CURL *h = curl_easy_init();
Utils::FileUtils::file_body *page = (Utils::FileUtils::file_body *) malloc(sizeof(Utils::FileUtils::file_body));
page->size = 0;
curl_easy_setopt(h, CURLOPT_URL, url);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
curl_easy_setopt(h, CURLOPT_WRITEDATA, page);
curl_easy_setopt(h, CURLOPT_PRIVATE, page);
curl_easy_setopt(h, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(h, CURLOPT_TIMEOUT, 5L);
curl_easy_setopt(h, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(h, CURLOPT_MAXREDIRS, 10L);
curl_easy_setopt(h, CURLOPT_CONNECTTIMEOUT, 2L);
curl_easy_setopt(h, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(h, CURLOPT_FILETIME, 1L);
curl_easy_setopt(h, CURLOPT_USERAGENT, "firefox");
curl_easy_setopt(h, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_easy_setopt(h, CURLOPT_UNRESTRICTED_AUTH, 1L);
curl_easy_setopt(h, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
curl_easy_setopt(h, CURLOPT_EXPECT_100_TIMEOUT_MS, 0L);
curl_multi_add_handle(cm, h);
++(*left);
}
size_t follow_links(CURLM *cm, Utils::FileUtils::file_body *page, char *url, int *left)
{
int opts = HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_NONET;
htmlDocPtr doc = htmlReadMemory(page->content, page->size, url, NULL, opts);
if(!doc) {
return 0;
}
xmlChar *xpath = (xmlChar*) "//img/@src";
xmlXPathContextPtr context = xmlXPathNewContext(doc);
xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context);
xmlXPathFreeContext(context);
if (out->content) {
memcpy(out->content, ptr, outSize * sizeof(char));
if(!result) {
return 0;
out->size = (int) outSize;
out->content[out->size] = 0;
}
} else {
// the max buffer (16384 = 16k) is exceeded, then this is called again and needs to get extended
char *temp = (char *) malloc((outSize + out->size + 1) * sizeof(char));
xmlNodeSetPtr nodeset = result->nodesetval;
if(xmlXPathNodeSetIsEmpty(nodeset)) {
xmlXPathFreeObject(result);
return 0;
}
memcpy(temp, out->content, out->size * sizeof(char));
memcpy(temp + out->size * sizeof(char), ptr, outSize * sizeof(char));
size_t count = 0;
int i;
free(out->content);
for(i = 0; i < nodeset->nodeNr; i++) {
double r = rand();
int x = r * nodeset->nodeNr / RAND_MAX;
const xmlNode *node = nodeset->nodeTab[x]->xmlChildrenNode;
xmlChar *href = xmlNodeListGetString(doc, node, 1);
out->content = temp;
out->size += outSize;
out->content[out->size] = 0;
}
// follow relative link
if(true) {
xmlChar *orig = href;
return out->size;
}
// @todo consider base= tag which has an impact on relative links
href = xmlBuildURI(href, (xmlChar *) url);
xmlFree(orig);
}
typedef struct {
size_t size = 0;
const char **resources = NULL;
} ResourceTypes;
char *link = (char *) href;
if(!link || strlen(link) < 10) {
continue;
}
typedef struct {
size_t size = 0;
const char **urls = NULL;
} Urls;
if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8) || !strncmp(link, "www.", 4)) {
Utils::WebUtils::add_transfer(cm, link, left);
Utils::FileUtils::file_body download (char *url)
{
Utils::FileUtils::file_body page = {0};
// limit to max 1000 links per page to follow
if(count++ == 1000) {
break;
}
}
if (!Utils::WebUtils::CURL_SETUP) {
Utils::WebUtils::setup();
}
xmlFree(link);
}
CURL *h = curl_easy_init();
curl_easy_setopt(h, CURLOPT_URL, url);
curl_easy_setopt(h, CURLOPT_PRIVATE, url);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
curl_easy_setopt(h, CURLOPT_WRITEDATA, &page);
curl_easy_perform(h);
curl_easy_cleanup(h);
return page;
}
inline
void add_transfer(CURLM *cm, char *url, int *left)
{
CURL *h = curl_easy_init();
Utils::FileUtils::file_body *page = (Utils::FileUtils::file_body *) malloc(sizeof(Utils::FileUtils::file_body));
page->size = 0;
curl_easy_setopt(h, CURLOPT_URL, url);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(h, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(h, CURLOPT_WRITEFUNCTION, write_download_data);
curl_easy_setopt(h, CURLOPT_WRITEDATA, page);
curl_easy_setopt(h, CURLOPT_PRIVATE, page);
curl_easy_setopt(h, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(h, CURLOPT_TIMEOUT, 5L);
curl_easy_setopt(h, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(h, CURLOPT_MAXREDIRS, 10L);
curl_easy_setopt(h, CURLOPT_CONNECTTIMEOUT, 2L);
curl_easy_setopt(h, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(h, CURLOPT_FILETIME, 1L);
curl_easy_setopt(h, CURLOPT_USERAGENT, "firefox");
curl_easy_setopt(h, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_easy_setopt(h, CURLOPT_UNRESTRICTED_AUTH, 1L);
curl_easy_setopt(h, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
curl_easy_setopt(h, CURLOPT_EXPECT_100_TIMEOUT_MS, 0L);
curl_multi_add_handle(cm, h);
++(*left);
}
size_t follow_links(CURLM *cm, Utils::FileUtils::file_body *page, char *url, int *left)
{
int opts = HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_NONET;
htmlDocPtr doc = htmlReadMemory(page->content, page->size, url, NULL, opts);
if(!doc) {
return 0;
}
xmlChar *xpath = (xmlChar*) "//img/@src";
xmlXPathContextPtr context = xmlXPathNewContext(doc);
xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context);
xmlXPathFreeContext(context);
if(!result) {
return 0;
}
xmlNodeSetPtr nodeset = result->nodesetval;
if(xmlXPathNodeSetIsEmpty(nodeset)) {
xmlXPathFreeObject(result);
return count;
return 0;
}
void *multi_download(
Urls urls,
const char *baseDir,
int max_parrallel = 1,
ResourceTypes *resources = NULL
) {
if (!Utils::WebUtils::CURL_SETUP) {
Utils::WebUtils::setup();
size_t count = 0;
int i;
for(i = 0; i < nodeset->nodeNr; i++) {
double r = rand();
int x = r * nodeset->nodeNr / RAND_MAX;
const xmlNode *node = nodeset->nodeTab[x]->xmlChildrenNode;
xmlChar *href = xmlNodeListGetString(doc, node, 1);
// follow relative link
if(true) {
xmlChar *orig = href;
// @todo consider base= tag which has an impact on relative links
href = xmlBuildURI(href, (xmlChar *) url);
xmlFree(orig);
}
CURLM *cm = curl_multi_init();
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, max_parrallel);
curl_multi_setopt(cm, CURLMOPT_MAX_TOTAL_CONNECTIONS, max_parrallel);
curl_multi_setopt(cm, CURLMOPT_MAX_HOST_CONNECTIONS, 5);
#ifdef CURLPIPE_MULTIPLEX
curl_multi_setopt(cm, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
#endif
int downloads = 0;
int left = 0;
for(downloads = 0; downloads < max_parrallel && downloads < urls.size; ++downloads) {
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
char *link = (char *) href;
if(!link || strlen(link) < 10) {
continue;
}
CURLMsg *msg;
int msgs_left = -1;
if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8) || !strncmp(link, "www.", 4)) {
Utils::WebUtils::add_transfer(cm, link, left);
do {
int alive = 1;
curl_multi_perform(cm, &alive);
// limit to max 1000 links per page to follow
if(count++ == 1000) {
break;
}
}
while((msg = curl_multi_info_read(cm, &msgs_left))) {
if(msg->msg == CURLMSG_DONE) {
CURL *e = msg->easy_handle;
char *url;
Utils::FileUtils::file_body *page;
xmlFree(link);
}
curl_easy_getinfo(e, CURLINFO_PRIVATE, &page);
curl_easy_getinfo(e, CURLINFO_EFFECTIVE_URL, &url);
xmlXPathFreeObject(result);
if (msg->data.result == CURLE_OK) {
long statusCode = 0;
curl_easy_getinfo(e, CURLINFO_RESPONSE_CDE, &statusCode);
return count;
}
if (statusCode == 200) {
char *ctype;
curl_easy_getinfo(e, CURLINFO_CONTENT_TYPE, &ctype);
void *multi_download(
Urls urls,
const char *baseDir,
int max_parrallel = 1,
ResourceTypes *resources = NULL
) {
if (!Utils::WebUtils::CURL_SETUP) {
Utils::WebUtils::setup();
}
// @todo save file (how to handle base resources, either pass base url or save based on url?)
CURLM *cm = curl_multi_init();
curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, max_parrallel);
curl_multi_setopt(cm, CURLMOPT_MAX_TOTAL_CONNECTIONS, max_parrallel);
curl_multi_setopt(cm, CURLMOPT_MAX_HOST_CONNECTIONS, 5);
if (ctype != NULL && strlen(ctype) > 10 && strstr(ctype, "text/html")) {
// @todo check limits
left += follow_links(cm, page, url, &left);
}
#ifdef CURLPIPE_MULTIPLEX
curl_multi_setopt(cm, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
#endif
int downloads = 0;
int left = 0;
for(downloads = 0; downloads < max_parrallel && downloads < urls.size; ++downloads) {
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
}
CURLMsg *msg;
int msgs_left = -1;
do {
int alive = 1;
curl_multi_perform(cm, &alive);
while((msg = curl_multi_info_read(cm, &msgs_left))) {
if(msg->msg == CURLMSG_DONE) {
CURL *e = msg->easy_handle;
char *url;
Utils::FileUtils::file_body *page;
curl_easy_getinfo(e, CURLINFO_PRIVATE, &page);
curl_easy_getinfo(e, CURLINFO_EFFECTIVE_URL, &url);
if (msg->data.result == CURLE_OK) {
long statusCode = 0;
curl_easy_getinfo(e, CURLINFO_RESPONSE_CDE, &statusCode);
if (statusCode == 200) {
char *ctype;
curl_easy_getinfo(e, CURLINFO_CONTENT_TYPE, &ctype);
// @todo save file (how to handle base resources, either pass base url or save based on url?)
if (ctype != NULL && strlen(ctype) > 10 && strstr(ctype, "text/html")) {
// @todo check limits
left += follow_links(cm, page, url, &left);
}
}
curl_multi_remove_handle(cm, e);
curl_easy_cleanup(e);
free(page->content);
free(page);
--left;
} else {
fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
}
if(downloads < urls.size) {
++downloads;
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
}
curl_multi_remove_handle(cm, e);
curl_easy_cleanup(e);
free(page->content);
free(page);
--left;
} else {
fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg);
}
if(left > 0) {
curl_multi_wait(cm, NULL, 0, 1000, NULL);
if(downloads < urls.size) {
++downloads;
Utils::WebUtils::add_transfer(cm, urls.urls[downloads], &left);
}
} while(left > 0);
}
curl_multi_cleanup(cm);
if(left > 0) {
curl_multi_wait(cm, NULL, 0, 1000, NULL);
}
} while(left > 0);
return null;
}
curl_multi_cleanup(cm);
return null;
}
}