Base frontend module

- Naming style migrated to camel-case
- P7lib logger sources added
- Vcpkg manifest, CMake presets and build moved to root
- SDL2, Vulkan and RmlUi dependencies added
- Logger LOG macro added
- Logger  configuration
- SDL2 window configuration
- Vulkan configuration
- RmlUi configuration
- SDL event loop
This commit is contained in:
legatt 2025-08-08 00:07:32 +03:00
parent 06ecfe88c1
commit 32f4597c4d
142 changed files with 39333 additions and 423 deletions

12
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"configurations": [
{
"type": "cmake",
"request": "launch",
"name": "Debug portfile(s)",
"cmakeDebugType": "external",
"pipeName": "\\\\.\\pipe\\vcpkg_ext_portfile_dbg",
"preLaunchTask": "Debug vcpkg commands"
}
]
}

15
CMakeLists.txt Normal file
View File

@ -0,0 +1,15 @@
cmake_minimum_required (VERSION 3.8)
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project ("EtrediaEmpires")
add_subdirectory ("p7lib")
add_subdirectory ("ECSAPI")
add_subdirectory ("frontend")

View File

@ -1,12 +0,0 @@
{
"version": 3,
"configurePresets": [
{
"name": "DEBUG",
"inherits": "x64-debug",
"environment": {
"VCPKG_ROOT": "E:/vcpkg/vcpkg"
}
}
]
}

View File

@ -13,15 +13,15 @@ find_package(EnTT CONFIG REQUIRED)
# Link library
add_library(ECS ${HEADERS} ${SOURCES})
add_library(ECS::ECS ALIAS ECS)
add_library(${PROJECT_NAME} ${HEADERS} ${SOURCES})
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_link_libraries(ECS PUBLIC Economy::Economy)
target_link_libraries(ECS PRIVATE EnTT::EnTT)
target_link_libraries(${PROJECT_NAME} PUBLIC Economy::Economy)
target_link_libraries(${PROJECT_NAME} PRIVATE EnTT::EnTT)
target_include_directories(ECS PUBLIC include/)
target_include_directories(${PROJECT_NAME} PUBLIC include/)
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET ECS PROPERTY CXX_STANDARD 20)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()

View File

@ -5,10 +5,10 @@
namespace ee_ecs
{
void init(init_configuration config);
void init(InitConfiguration config);
void start();
template<typename T>
const std::vector<enterprise_info> get_all_enterprises();
//const enterprise_info get_enterprise(uint32_t id);
const std::vector<EnterpriseInfo> getAllEnterprises();
//const EnterpriseInfo getEnterprise(uint32_t id);
}

View File

@ -6,19 +6,19 @@
namespace ee_ecs
{
struct init_configuration
struct InitConfiguration
{
std::unordered_map<int16_t, ee_economy::container> states;
std::unordered_map<int16_t, ee_economy::Container> states;
};
struct enterprise_info
struct EnterpriseInfo
{
const ee_economy::enterprise* info = nullptr;
const ee_economy::container* storage = nullptr;
const ee_economy::Enterprise* info = nullptr;
const ee_economy::Container* storage = nullptr;
std::variant<
const ee_economy::miner*,
const ee_economy::deliverer*
> special_info;
const ee_economy::Miner*,
const ee_economy::Deliverer*
> specialInfo;
};
}

View File

@ -7,28 +7,27 @@
namespace ee_ecs
{
class world
class World
{
private:
entt::registry registry;
std::unordered_map<int16_t, entt::entity> states_table;
std::unordered_map<int16_t, entt::entity> statesTable;
void update_enterprises();
void updateEnterprises();
public:
// Run every registered system
void update();
entt::entity register_state(const int16_t id, const ee_economy::container &resources);
entt::entity registerState(const int16_t id, const ee_economy::Container &resources);
entt::entity spawn_enterprise(
const bool is_building,
entt::entity spawnEnterprise(
const bool isBuilding,
const ee_economy::ACTION_TYPE action,
const entt::entity state,
const ee_economy::enterprise_defaults &defaults
const ee_economy::EnterpriseDefaults &defaults
);
entt::registry& get_registry();
entt::registry& getRegistry();
};
}

View File

@ -2,13 +2,13 @@
#include <ee_ecs/ecs.hpp>
static ee_ecs::world world_instance;
static ee_ecs::World worldInstance;
void ee_ecs::init(ee_ecs::init_configuration config)
void ee_ecs::init(ee_ecs::InitConfiguration config)
{
for (auto& [id, container]: config.states)
{
world_instance.register_state(id, container);
worldInstance.registerState(id, container);
}
}
@ -18,24 +18,24 @@ void ee_ecs::start()
}
template<typename T>
const std::vector<ee_ecs::enterprise_info> ee_ecs::get_all_enterprises()
const std::vector<ee_ecs::EnterpriseInfo> ee_ecs::getAllEnterprises()
{
std::vector<enterprise_info> result;
std::vector<EnterpriseInfo> result;
//TODO: REPLACE VIEWS WITH GROUPS!
auto enterprises = world_instance.get_registry().group<>(entt::get<
ee_economy::enterprise,
ee_economy::container,
auto enterprises = worldInstance.getRegistry().group<>(entt::get<
ee_economy::Enterprise,
ee_economy::Container,
T
>);
result.reserve(enterprises.size_hint());
for (auto [entity, enterprise, container, action]: enterprises.each())
{
enterprise_info eninfo;
EnterpriseInfo eninfo;
eninfo.info = &enterprise;
eninfo.storage = &container;
eninfo.special_info = &action;
eninfo.specialInfo = &action;
result.push_back(eninfo);
}

View File

@ -2,61 +2,61 @@
#include <ee_ecs/ecs.hpp>
#include <stdexcept>
void ee_ecs::world::update_enterprises()
void ee_ecs::World::updateEnterprises()
{
ee_economy::enterprise_routine(this->registry);
ee_economy::enterpriseRoutine(this->registry);
ee_economy::mining(this->registry);
ee_economy::delivering(this->registry);
}
void ee_ecs::world::update()
void ee_ecs::World::update()
{
this->update_enterprises();
this->updateEnterprises();
}
entt::entity ee_ecs::world::register_state(const int16_t id, const ee_economy::container &resources)
entt::entity ee_ecs::World::registerState(const int16_t id, const ee_economy::Container &resources)
{
if (this->states_table.contains(id))
if (this->statesTable.contains(id))
throw std::invalid_argument("State with this Id is already registered");
entt::entity entity = this->registry.create();
this->registry.emplace<ee_economy::state>(entity, id);
this->registry.emplace<ee_economy::container>(
this->registry.emplace<ee_economy::State>(entity, id);
this->registry.emplace<ee_economy::Container>(
entity,
resources.capacity,
resources.total,
resources.content
);
this->states_table[id] = entity;
this->statesTable[id] = entity;
return entity;
}
entt::entity ee_ecs::world::spawn_enterprise(
const bool is_building,
entt::entity ee_ecs::World::spawnEnterprise(
const bool isBuilding,
const ee_economy::ACTION_TYPE action,
const entt::entity state,
const ee_economy::enterprise_defaults &defaults
const ee_economy::EnterpriseDefaults &defaults
)
{
entt::entity entity = this->registry.create();
this->registry.emplace<ee_economy::enterprise>(
this->registry.emplace<ee_economy::Enterprise>(
entity,
is_building,
isBuilding,
state,
action,
defaults.base_efficiency * defaults.factor_efficiency,
defaults.baseEfficiency * defaults.factorEfficiency,
defaults.base_efficiency,
defaults.factor_efficiency
defaults.baseEfficiency,
defaults.factorEfficiency
);
this->registry.emplace<ee_economy::container>(
this->registry.emplace<ee_economy::Container>(
entity,
defaults.container.capacity,
defaults.container.total,
@ -67,13 +67,13 @@ entt::entity ee_ecs::world::spawn_enterprise(
{
case ee_economy::ACTION_TYPE::MINING:
{
this->registry.emplace<ee_economy::miner>(entity, defaults.resource_target);
this->registry.emplace<ee_economy::Miner>(entity, defaults.resourceTarget);
break;
}
case ee_economy::ACTION_TYPE::DELIVERY:
{
this->registry.emplace<ee_economy::deliverer>(entity, defaults.resource_target);
this->registry.emplace<ee_economy::Deliverer>(entity, defaults.resourceTarget);
break;
}
@ -84,4 +84,4 @@ entt::entity ee_ecs::world::spawn_enterprise(
return entity;
}
entt::registry& ee_ecs::world::get_registry() {return this->registry;}
entt::registry& ee_ecs::World::getRegistry() {return this->registry;}

View File

@ -1,3 +1,5 @@
project(ecs_tests)
# List sources
set(SOURCES "test_conf.hpp" "main.cpp" "world.cpp" "benchmark.cpp")
@ -10,14 +12,14 @@ find_package(GTest CONFIG REQUIRED)
include(GoogleTest)
add_executable(ecs_tests ${SOURCES})
target_link_libraries(ecs_tests PRIVATE GTest::gtest_main)
target_link_libraries(ecs_tests PRIVATE ECS::ECS)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest_main)
target_link_libraries(${PROJECT_NAME} PRIVATE ECS::ECS)
# Test
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET ecs_tests PROPERTY CXX_STANDARD 20)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()
gtest_discover_tests(ecs_tests)
gtest_discover_tests(${PROJECT_NAME})

View File

@ -17,7 +17,7 @@ private:
};
template<typename Func, typename... Args>
void generic_with(Func func) {
void genericWith(Func func) {
timer timer;
func();
timer.elapsed();
@ -25,7 +25,7 @@ void generic_with(Func func) {
TEST_F(WorldBenchmark, UpdateSystems)
{
generic_with([&]() {
genericWith([&]() {
world.update();
});
}

View File

@ -5,27 +5,27 @@
struct WorldBenchmark : testing::Test
{
ee_ecs::world world;
ee_ecs::World world;
void SetUp()
{
for (int16_t i = 0; i < 1000; i++)
{
ee_economy::container resources = {.capacity = 100.0};
ee_economy::Container resources = {.capacity = 100.0};
resources.add(ee_economy::RESOURCE_TYPE::COAL, 100.0);
entt::entity state = world.register_state(i, resources);
entt::entity state = world.registerState(i, resources);
ee_economy::enterprise_defaults miner = {
ee_economy::EnterpriseDefaults miner = {
.container = {.capacity = 100.0},
.resource_target = ee_economy::RESOURCE_TYPE::GOLD,
.base_efficiency = 1.0
.resourceTarget = ee_economy::RESOURCE_TYPE::GOLD,
.baseEfficiency = 1.0
};
world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner);
}
}

View File

@ -5,76 +5,76 @@
TEST(WorldTest, RegisterState)
{
ee_ecs::world world;
ee_ecs::World world;
ee_economy::container res = {.capacity = 100.0};
ee_economy::Container res = {.capacity = 100.0};
res.add(ee_economy::RESOURCE_TYPE::COAL, 98.0);
entt::entity state = world.register_state(10, res);
entt::entity state = world.registerState(10, res);
ee_economy::state registered_state = world.get_registry().get<ee_economy::state>(state);
ee_economy::container registered_container = world.get_registry().get<ee_economy::container>(state);
ee_economy::State registeredState = world.getRegistry().get<ee_economy::State>(state);
ee_economy::Container registeredContainer = world.getRegistry().get<ee_economy::Container>(state);
ASSERT_EQ(registered_state.external_id, 10);
ASSERT_DOUBLE_EQ(registered_container.content[ee_economy::RESOURCE_TYPE::COAL], 98.0);
ASSERT_EQ(registeredState.externalId, 10);
ASSERT_DOUBLE_EQ(registeredContainer.content[ee_economy::RESOURCE_TYPE::COAL], 98.0);
}
TEST(WorldTest, RegisterStateDuplicate)
{
ee_ecs::world world;
ee_ecs::World world;
world.register_state(10, {});
world.registerState(10, {});
ASSERT_THROW({
world.register_state(10, {});
world.registerState(10, {});
}, std::invalid_argument);
}
TEST(WorldTest, SpawnMiner)
{
ee_ecs::world world;
ee_ecs::World world;
entt::entity state = world.get_registry().create();
world.get_registry().emplace<ee_economy::state>(state, (int16_t)0);
world.get_registry().emplace<ee_economy::container>(state, 100.0);
entt::entity state = world.getRegistry().create();
world.getRegistry().emplace<ee_economy::State>(state, (int16_t)0);
world.getRegistry().emplace<ee_economy::Container>(state, 100.0);
ee_economy::enterprise_defaults defaults = {
ee_economy::EnterpriseDefaults defaults = {
.container = {.capacity = 100.0 },
.resource_target = ee_economy::RESOURCE_TYPE::COAL,
.base_efficiency = 1.0,
.resourceTarget = ee_economy::RESOURCE_TYPE::COAL,
.baseEfficiency = 1.0,
};
entt::entity enterprise = world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, defaults);
entt::entity enterprise = world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, defaults);
ee_economy::enterprise registered_enterprise = world.get_registry().get<ee_economy::enterprise>(enterprise);
ee_economy::miner registered_action = world.get_registry().get<ee_economy::miner>(enterprise);
ee_economy::container registered_container = world.get_registry().get<ee_economy::container>(enterprise);
ee_economy::Enterprise registeredEnterprise = world.getRegistry().get<ee_economy::Enterprise>(enterprise);
ee_economy::Miner registeredAction = world.getRegistry().get<ee_economy::Miner>(enterprise);
ee_economy::Container registeredContainer = world.getRegistry().get<ee_economy::Container>(enterprise);
ASSERT_DOUBLE_EQ(registered_enterprise.base_efficiency, 1.0);
ASSERT_EQ(registered_action.resource, ee_economy::RESOURCE_TYPE::COAL);
ASSERT_DOUBLE_EQ(registered_container.capacity, 100.0);
ASSERT_DOUBLE_EQ(registeredEnterprise.baseEfficiency, 1.0);
ASSERT_EQ(registeredAction.resource, ee_economy::RESOURCE_TYPE::COAL);
ASSERT_DOUBLE_EQ(registeredContainer.capacity, 100.0);
}
TEST(WorldTest, SpawnDeliverer)
{
ee_ecs::world world;
ee_ecs::World world;
entt::entity state = world.get_registry().create();
world.get_registry().emplace<ee_economy::state>(state, (int16_t)0);
world.get_registry().emplace<ee_economy::container>(state, 100.0);
entt::entity state = world.getRegistry().create();
world.getRegistry().emplace<ee_economy::State>(state, (int16_t)0);
world.getRegistry().emplace<ee_economy::Container>(state, 100.0);
ee_economy::enterprise_defaults defaults = {
ee_economy::EnterpriseDefaults defaults = {
.container = {.capacity = 100.0 },
.resource_target = ee_economy::RESOURCE_TYPE::COAL,
.base_efficiency = 1.0,
.resourceTarget = ee_economy::RESOURCE_TYPE::COAL,
.baseEfficiency = 1.0,
};
entt::entity enterprise = world.spawn_enterprise(false, ee_economy::ACTION_TYPE::DELIVERY, state, defaults);
entt::entity enterprise = world.spawnEnterprise(false, ee_economy::ACTION_TYPE::DELIVERY, state, defaults);
ee_economy::enterprise registered_enterprise = world.get_registry().get<ee_economy::enterprise>(enterprise);
ee_economy::deliverer registered_action = world.get_registry().get<ee_economy::deliverer>(enterprise);
ee_economy::container registered_container = world.get_registry().get<ee_economy::container>(enterprise);
ee_economy::Enterprise registeredEnterprise = world.getRegistry().get<ee_economy::Enterprise>(enterprise);
ee_economy::Deliverer registeredAction = world.getRegistry().get<ee_economy::Deliverer>(enterprise);
ee_economy::Container registeredContainer = world.getRegistry().get<ee_economy::Container>(enterprise);
ASSERT_DOUBLE_EQ(registered_enterprise.base_efficiency, 1.0);
ASSERT_EQ(registered_action.resource, ee_economy::RESOURCE_TYPE::COAL);
ASSERT_DOUBLE_EQ(registered_container.capacity, 100.0);
ASSERT_DOUBLE_EQ(registeredEnterprise.baseEfficiency, 1.0);
ASSERT_EQ(registeredAction.resource, ee_economy::RESOURCE_TYPE::COAL);
ASSERT_DOUBLE_EQ(registeredContainer.capacity, 100.0);
}

View File

@ -21,13 +21,13 @@ find_package(EnTT CONFIG REQUIRED)
# Link library
add_library(Economy ${HEADERS} ${HEADERS_COMPONENTS} ${SOURCES} ${SOURCES_SYSTEMS})
add_library(Economy::Economy ALIAS Economy)
add_library(${PROJECT_NAME} ${HEADERS} ${HEADERS_COMPONENTS} ${SOURCES} ${SOURCES_SYSTEMS})
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_link_libraries(Economy PRIVATE EnTT::EnTT)
target_link_libraries(${PROJECT_NAME} PRIVATE EnTT::EnTT)
target_include_directories(Economy PUBLIC include/)
target_include_directories(${PROJECT_NAME} PUBLIC include/)
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET Economy PROPERTY CXX_STANDARD 20)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()

View File

@ -4,7 +4,7 @@
namespace ee_economy
{
struct container
struct Container
{
double capacity = 0.;
double total = 0.;

View File

@ -4,7 +4,7 @@
namespace ee_economy
{
struct deliver_contract
struct DeliverContract
{
entt::entity from;
entt::entity to;
@ -15,10 +15,10 @@ namespace ee_economy
double distance = 1.0;
};
struct deliverer
struct Deliverer
{
RESOURCE_TYPE resource = RESOURCE_TYPE::NONE;
std::vector<deliver_contract> contracts;
std::vector<DeliverContract> contracts;
};
}

View File

@ -5,9 +5,9 @@
namespace ee_economy
{
struct enterprise
struct Enterprise
{
bool is_building = false;
bool isBuilding = false;
entt::entity state;
ACTION_TYPE action = ACTION_TYPE::STORE;
@ -17,39 +17,39 @@ namespace ee_economy
* Production -
*/
double efficiency = 0.;
double base_efficiency = 0.;
double factor_efficiency = 1.;
double baseEfficiency = 0.;
double factorEfficiency = 1.;
std::vector<entt::entity> links_from;
std::vector<entt::entity> links_to;
std::vector<entt::entity> linksFrom;
std::vector<entt::entity> linksTo;
uint16_t staff_size = 1;
uint16_t staffSize = 1;
// This can be splitted in percents between bank enterprises in future
double total_money = 0;
double totalMoney = 0;
double salary = 0;
bool is_bankrupt = false;
bool isBankrupt = false;
void set_money(double value)
void setMoney(double value)
{
total_money = value;
totalMoney = value;
}
inline void update_efficiency()
inline void updateEfficiency()
{
this->efficiency = this->base_efficiency * this->factor_efficiency;
this->efficiency = this->baseEfficiency * this->factorEfficiency;
}
void set_base_efficiency(double value)
void setBaseEfficiency(double value)
{
this->base_efficiency = value;
update_efficiency();
this->baseEfficiency = value;
updateEfficiency();
}
void set_factor_efficiency(double value)
void setFactorEfficiency(double value)
{
this->factor_efficiency = value;
update_efficiency();
this->factorEfficiency = value;
updateEfficiency();
}
};
}

View File

@ -4,7 +4,7 @@
namespace ee_economy
{
struct miner
struct Miner
{
RESOURCE_TYPE resource = RESOURCE_TYPE::NONE;
};

View File

@ -2,7 +2,7 @@
namespace ee_economy
{
struct producer
struct Producer
{
};

View File

@ -3,7 +3,7 @@
namespace ee_economy
{
struct state {
int16_t external_id = -1;
struct State {
int16_t externalId = -1;
};
}

View File

@ -4,12 +4,12 @@
namespace ee_economy
{
struct enterprise_defaults
struct EnterpriseDefaults
{
container container;
Container container;
RESOURCE_TYPE resource_target = RESOURCE_TYPE::NONE;
double base_efficiency = 0.0;
double factor_efficiency = 1.0;
RESOURCE_TYPE resourceTarget = RESOURCE_TYPE::NONE;
double baseEfficiency = 0.0;
double factorEfficiency = 1.0;
};
}

View File

@ -6,18 +6,18 @@
namespace ee_economy
{
struct exchange_rule
struct ExchangeRule
{
double out_value;
double outValue;
std::unordered_map<RESOURCE_TYPE, double> consume;
};
const std::unordered_map<RESOURCE_TYPE, exchange_rule> resources_exchange = {
const std::unordered_map<RESOURCE_TYPE, exchange_rule> resourcesExchange = {
{
RESOURCE_TYPE::FABRIC,
exchange_rule {
.out_value = 2.,
.outValue = 2.,
.consume = {
{RESOURCE_TYPE::WOOL, 3.}
}

View File

@ -3,7 +3,7 @@
namespace ee_economy
{
void enterprise_routine(entt::registry& registry);
void enterpriseRoutine(entt::registry& registry);
void mining(entt::registry& registry);
// void producing(entt::registry& registry);

View File

@ -2,54 +2,54 @@
void ee_economy::delivering(entt::registry &registry)
{
auto deliverers = registry.view<enterprise, deliverer, container>();
auto deliverers = registry.view<Enterprise, Deliverer, Container>();
for (auto [entity, enterprise, deliverer, storage]: deliverers.each())
{
if (enterprise.is_bankrupt) continue;
if (enterprise.isBankrupt) continue;
for (deliver_contract &contract: deliverer.contracts)
for (DeliverContract &contract: deliverer.contracts)
{
double paid_amount = contract.amount;
double paidAmount = contract.amount;
if (contract.cost > 0)
{
ee_economy::enterprise &sponsor = registry.get<ee_economy::enterprise>(contract.sponsor);
Enterprise &sponsor = registry.get<Enterprise>(contract.sponsor);
double cost_per_one = contract.cost / contract.amount;
double costPerOne = contract.cost / contract.amount;
double payment = contract.cost;
if (payment > sponsor.total_money)
if (payment > sponsor.totalMoney)
{
payment = (int)(sponsor.total_money / cost_per_one) * cost_per_one;
paid_amount = payment / cost_per_one;
payment = (int)(sponsor.totalMoney / costPerOne) * costPerOne;
paidAmount = payment / costPerOne;
}
sponsor.set_money(sponsor.total_money - payment);
enterprise.set_money(enterprise.total_money + payment);
sponsor.setMoney(sponsor.totalMoney - payment);
enterprise.setMoney(enterprise.totalMoney + payment);
contract.cost -= payment;
}
container &from_storage = registry.get<container>(contract.from);
container &to_storage = registry.get<container>(contract.to);
Container &fromStorage = registry.get<Container>(contract.from);
Container &toStorage = registry.get<Container>(contract.to);
double deliver_value = enterprise.efficiency;
double deliverValue = enterprise.efficiency;
if (contract.amount < enterprise.efficiency)
deliver_value = contract.amount;
if (to_storage.total + deliver_value > to_storage.capacity)
deliver_value = to_storage.capacity - to_storage.total;
if (deliver_value > from_storage.content[deliverer.resource])
deliver_value = from_storage.content[deliverer.resource];
if (deliver_value > paid_amount)
deliver_value = paid_amount;
if (deliver_value < 0.0)
deliver_value = 0.0;
deliverValue = contract.amount;
if (toStorage.total + deliverValue > toStorage.capacity)
deliverValue = toStorage.capacity - toStorage.total;
if (deliverValue > fromStorage.content[deliverer.resource])
deliverValue = fromStorage.content[deliverer.resource];
if (deliverValue > paidAmount)
deliverValue = paidAmount;
if (deliverValue < 0.0)
deliverValue = 0.0;
to_storage.add(deliverer.resource, deliver_value);
from_storage.add(deliverer.resource, -deliver_value);
contract.amount -= deliver_value;
toStorage.add(deliverer.resource, deliverValue);
fromStorage.add(deliverer.resource, -deliverValue);
contract.amount -= deliverValue;
}
std::erase_if(deliverer.contracts, [](const deliver_contract &contract) {
std::erase_if(deliverer.contracts, [](const DeliverContract &contract) {
return contract.amount <= 0.0;
});
}

View File

@ -1,20 +1,20 @@
#include <ee_economy/economy.hpp>
void ee_economy::enterprise_routine(entt::registry &registry)
void ee_economy::enterpriseRoutine(entt::registry &registry)
{
auto enterprises = registry.view<enterprise>();
auto enterprises = registry.view<Enterprise>();
for (auto [entity, enterprise]: enterprises.each())
{
double salary_debt = enterprise.salary * enterprise.staff_size;
if (enterprise.total_money < salary_debt)
double salaryDebt = enterprise.salary * enterprise.staffSize;
if (enterprise.totalMoney < salaryDebt)
{
enterprise.is_bankrupt = true;
enterprise.set_money(0.0);
enterprise.isBankrupt = true;
enterprise.setMoney(0.0);
}
else
{
enterprise.set_money(enterprise.total_money - salary_debt);
enterprise.setMoney(enterprise.totalMoney - salaryDebt);
}
}
}

View File

@ -2,21 +2,21 @@
void ee_economy::mining(entt::registry &registry)
{
auto miners = registry.view<enterprise, miner, container>();
auto miners = registry.view<Enterprise, Miner, Container>();
for (auto [entity, enterprise, miner, local_storage]: miners.each())
for (auto [entity, enterprise, miner, localStorage]: miners.each())
{
if (enterprise.is_bankrupt) continue;
if (enterprise.isBankrupt) continue;
container& state = registry.get<container>(enterprise.state);
Container& state = registry.get<Container>(enterprise.state);
double mined_value = enterprise.efficiency;
if (local_storage.total + mined_value > local_storage.capacity)
mined_value = local_storage.capacity - local_storage.total;
if (mined_value > state.content[miner.resource])
mined_value = state.content[miner.resource];
double minedValue = enterprise.efficiency;
if (localStorage.total + minedValue > localStorage.capacity)
minedValue = localStorage.capacity - localStorage.total;
if (minedValue > state.content[miner.resource])
minedValue = state.content[miner.resource];
local_storage.add(miner.resource, mined_value);
state.add(miner.resource, -mined_value);
localStorage.add(miner.resource, minedValue);
state.add(miner.resource, -minedValue);
}
}

View File

@ -1,3 +1,5 @@
project(economy_tests)
# List sources
set(SOURCES "test_conf.hpp" "main.cpp"
@ -11,14 +13,14 @@ find_package(GTest CONFIG REQUIRED)
include(GoogleTest)
add_executable(economy_tests ${SOURCES})
target_link_libraries(economy_tests PRIVATE GTest::gtest_main)
target_link_libraries(economy_tests PRIVATE Economy::Economy)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest_main)
target_link_libraries(${PROJECT_NAME} PRIVATE Economy::Economy)
# Test
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET economy_tests PROPERTY CXX_STANDARD 20)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()
gtest_discover_tests(economy_tests)
gtest_discover_tests(${PROJECT_NAME})

View File

@ -6,140 +6,140 @@ TEST_F(SystemsTest, DeliverySingleNormal)
{
// [Miner -> Storage] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(deliverer);
ee_economy::Enterprise &delivererEnterprise = registry.get<ee_economy::Enterprise>(deliverer);
ee_economy::Deliverer &delivererDeliverer = registry.get<ee_economy::Deliverer>(deliverer);
deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
deliverer_enterprise.set_base_efficiency(1.0);
deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
delivererEnterprise.setBaseEfficiency(1.0);
delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
ee_economy::container &from_container = registry.get<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(storage);
ee_economy::Container &fromContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Container &toContainer = registry.get<ee_economy::Container>(storage);
from_container.capacity = 15.0;
from_container.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
fromContainer.capacity = 15.0;
fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
to_container.capacity = 15.0;
toContainer.capacity = 15.0;
ee_economy::delivering(registry);
ASSERT_DOUBLE_EQ(from_container.total, 14.0);
ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 14.0);
ASSERT_DOUBLE_EQ(to_container.total, 1.0);
ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 1.0);
ASSERT_EQ(deliverer_deliverer.contracts.size(), 1);
ASSERT_DOUBLE_EQ(fromContainer.total, 14.0);
ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 14.0);
ASSERT_DOUBLE_EQ(toContainer.total, 1.0);
ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 1.0);
ASSERT_EQ(delivererDeliverer.contracts.size(), 1);
}
TEST_F(SystemsTest, DeliverySingleEmpty)
{
// [Miner -> Storage] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(deliverer);
ee_economy::Enterprise &delivererEnterprise = registry.get<ee_economy::Enterprise>(deliverer);
ee_economy::Deliverer &delivererDeliverer = registry.get<ee_economy::Deliverer>(deliverer);
deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
deliverer_enterprise.set_base_efficiency(1.0);
deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
delivererEnterprise.setBaseEfficiency(1.0);
delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
ee_economy::container &from_container = registry.get<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(storage);
ee_economy::Container &fromContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Container &toContainer = registry.get<ee_economy::Container>(storage);
from_container.capacity = 15.0;
to_container.capacity = 15.0;
fromContainer.capacity = 15.0;
toContainer.capacity = 15.0;
ee_economy::delivering(registry);
ASSERT_DOUBLE_EQ(from_container.total, 0.0);
ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(to_container.total, 0.0);
ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_EQ(deliverer_deliverer.contracts.size(), 1);
ASSERT_DOUBLE_EQ(fromContainer.total, 0.0);
ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(toContainer.total, 0.0);
ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_EQ(delivererDeliverer.contracts.size(), 1);
}
TEST_F(SystemsTest, DeliverySinglePoor)
{
// [Miner -> Storage] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(deliverer);
ee_economy::Enterprise &delivererEnterprise = registry.get<ee_economy::Enterprise>(deliverer);
ee_economy::Deliverer &delivererDeliverer = registry.get<ee_economy::Deliverer>(deliverer);
deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
deliverer_enterprise.set_base_efficiency(1.0);
deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
delivererEnterprise.setBaseEfficiency(1.0);
delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
ee_economy::container &from_container = registry.get<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(storage);
ee_economy::Container &fromContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Container &toContainer = registry.get<ee_economy::Container>(storage);
from_container.capacity = 15.0;
from_container.add(ee_economy::RESOURCE_TYPE::COAL, 0.5);
fromContainer.capacity = 15.0;
fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 0.5);
to_container.capacity = 15.0;
toContainer.capacity = 15.0;
ee_economy::delivering(registry);
ASSERT_DOUBLE_EQ(from_container.total, 0.0);
ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(to_container.total, 0.5);
ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.5);
ASSERT_EQ(deliverer_deliverer.contracts.size(), 1);
ASSERT_DOUBLE_EQ(fromContainer.total, 0.0);
ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(toContainer.total, 0.5);
ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.5);
ASSERT_EQ(delivererDeliverer.contracts.size(), 1);
}
TEST_F(SystemsTest, DeliverySingleFinishContract)
{
// [Miner -> Storage] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(deliverer);
ee_economy::Enterprise &delivererEnterprise = registry.get<ee_economy::Enterprise>(deliverer);
ee_economy::Deliverer &delivererDeliverer = registry.get<ee_economy::Deliverer>(deliverer);
deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
deliverer_enterprise.set_base_efficiency(15.0);
deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
delivererEnterprise.setBaseEfficiency(15.0);
delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
ee_economy::container &from_container = registry.get<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(storage);
ee_economy::Container &fromContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Container &toContainer = registry.get<ee_economy::Container>(storage);
from_container.capacity = 15.0;
from_container.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
fromContainer.capacity = 15.0;
fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
to_container.capacity = 15.0;
toContainer.capacity = 15.0;
ee_economy::delivering(registry);
ASSERT_DOUBLE_EQ(from_container.total, 5.0);
ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 5.0);
ASSERT_DOUBLE_EQ(to_container.total, 10.0);
ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 10.0);
ASSERT_EQ(deliverer_deliverer.contracts.size(), 0);
ASSERT_DOUBLE_EQ(fromContainer.total, 5.0);
ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 5.0);
ASSERT_DOUBLE_EQ(toContainer.total, 10.0);
ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 10.0);
ASSERT_EQ(delivererDeliverer.contracts.size(), 0);
}
TEST_F(SystemsTest, DeliveryMultipleFinishPoorCycle)
{
// [Miner -> Storage | Storage -> Miner] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(deliverer);
ee_economy::Enterprise &delivererEnterprise = registry.get<ee_economy::Enterprise>(deliverer);
ee_economy::Deliverer &delivererDeliverer = registry.get<ee_economy::Deliverer>(deliverer);
deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
deliverer_enterprise.set_base_efficiency(16.0);
deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .amount = 20.0});
deliverer_deliverer.contracts.push_back({.from = storage, .to = miner, .amount = 5.0});
delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
delivererEnterprise.setBaseEfficiency(16.0);
delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 20.0});
delivererDeliverer.contracts.push_back({.from = storage, .to = miner, .amount = 5.0});
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::container &storage_container = registry.get<ee_economy::container>(storage);
ee_economy::Container &minerContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Container &storageContainer = registry.get<ee_economy::Container>(storage);
miner_container.capacity = 15.0;
miner_container.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
minerContainer.capacity = 15.0;
minerContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
storage_container.capacity = 15.0;
storageContainer.capacity = 15.0;
ee_economy::delivering(registry);
ASSERT_DOUBLE_EQ(miner_container.total, 5.0);
ASSERT_DOUBLE_EQ(miner_container.content[ee_economy::RESOURCE_TYPE::COAL], 5.0);
ASSERT_DOUBLE_EQ(storage_container.total, 10.0);
ASSERT_DOUBLE_EQ(storage_container.content[ee_economy::RESOURCE_TYPE::COAL], 10.0);
ASSERT_EQ(deliverer_deliverer.contracts.size(), 1);
ASSERT_EQ(deliverer_deliverer.contracts[0].from, miner);
ASSERT_DOUBLE_EQ(minerContainer.total, 5.0);
ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 5.0);
ASSERT_DOUBLE_EQ(storageContainer.total, 10.0);
ASSERT_DOUBLE_EQ(storageContainer.content[ee_economy::RESOURCE_TYPE::COAL], 10.0);
ASSERT_EQ(delivererDeliverer.contracts.size(), 1);
ASSERT_EQ(delivererDeliverer.contracts[0].from, miner);
}
TEST_F(SystemsTest, DeliveryPayment)
@ -147,12 +147,12 @@ TEST_F(SystemsTest, DeliveryPayment)
// [Miner -> Storage] by Deliverer for $Miner
// [Miner -> Storage] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(deliverer);
ee_economy::Enterprise &delivererEnterprise = registry.get<ee_economy::Enterprise>(deliverer);
ee_economy::Deliverer &delivererDeliverer = registry.get<ee_economy::Deliverer>(deliverer);
deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
deliverer_enterprise.set_base_efficiency(10.0);
deliverer_deliverer.contracts.push_back({
delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
delivererEnterprise.setBaseEfficiency(10.0);
delivererDeliverer.contracts.push_back({
.from = miner,
.to = storage,
.sponsor = miner,
@ -160,26 +160,26 @@ TEST_F(SystemsTest, DeliveryPayment)
.cost = 100.0
});
ee_economy::container &from_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &from_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(storage);
ee_economy::Container &fromContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Enterprise &fromEnterprise = registry.get<ee_economy::Enterprise>(miner);
ee_economy::Container &toContainer = registry.get<ee_economy::Container>(storage);
from_container.capacity = 10.0;
from_container.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
from_enterprise.set_money(95.0);
fromContainer.capacity = 10.0;
fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
fromEnterprise.setMoney(95.0);
to_container.capacity = 10.0;
toContainer.capacity = 10.0;
ee_economy::delivering(registry);
ASSERT_DOUBLE_EQ(from_container.total, 1.0);
ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 1.0);
ASSERT_DOUBLE_EQ(to_container.total, 9.0);
ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 9.0);
ASSERT_DOUBLE_EQ(from_enterprise.total_money, 5.0);
ASSERT_DOUBLE_EQ(deliverer_enterprise.total_money, 90.0);
ASSERT_DOUBLE_EQ(fromContainer.total, 1.0);
ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 1.0);
ASSERT_DOUBLE_EQ(toContainer.total, 9.0);
ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 9.0);
ASSERT_DOUBLE_EQ(fromEnterprise.totalMoney, 5.0);
ASSERT_DOUBLE_EQ(delivererEnterprise.totalMoney, 90.0);
ee_economy::deliver_contract contract = deliverer_deliverer.contracts[0];
ee_economy::DeliverContract contract = delivererDeliverer.contracts[0];
ASSERT_DOUBLE_EQ(contract.cost, 10.0);
ASSERT_DOUBLE_EQ(contract.amount, 1.0);
}
@ -188,27 +188,27 @@ TEST_F(SystemsTest, DeliveryBankrupt)
{
// [Miner -> Storage] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(deliverer);
ee_economy::Enterprise &delivererEnterprise = registry.get<ee_economy::Enterprise>(deliverer);
ee_economy::Deliverer &delivererDeliverer = registry.get<ee_economy::Deliverer>(deliverer);
deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
deliverer_enterprise.set_base_efficiency(1.0);
deliverer_enterprise.is_bankrupt = true;
delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL;
delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0});
delivererEnterprise.setBaseEfficiency(1.0);
delivererEnterprise.isBankrupt = true;
ee_economy::container &from_container = registry.get<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(storage);
ee_economy::Container &fromContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Container &toContainer = registry.get<ee_economy::Container>(storage);
from_container.capacity = 15.0;
from_container.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
fromContainer.capacity = 15.0;
fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0);
to_container.capacity = 15.0;
toContainer.capacity = 15.0;
ee_economy::delivering(registry);
ASSERT_DOUBLE_EQ(from_container.total, 15.0);
ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 15.0);
ASSERT_DOUBLE_EQ(to_container.total, 0.0);
ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_EQ(deliverer_deliverer.contracts.size(), 1);
ASSERT_DOUBLE_EQ(fromContainer.total, 15.0);
ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 15.0);
ASSERT_DOUBLE_EQ(toContainer.total, 0.0);
ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_EQ(delivererDeliverer.contracts.size(), 1);
}

View File

@ -4,26 +4,26 @@
TEST_F(SystemsTest, RoutineNormal)
{
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
miner_enterprise.set_money(1000000000.0);
miner_enterprise.salary = 100000.0;
miner_enterprise.staff_size = 10;
ee_economy::Enterprise &minerEnterprise = registry.get<ee_economy::Enterprise>(miner);
minerEnterprise.setMoney(1000000000.0);
minerEnterprise.salary = 100000.0;
minerEnterprise.staffSize = 10;
ee_economy::enterprise_routine(registry);
ee_economy::enterpriseRoutine(registry);
ASSERT_DOUBLE_EQ(miner_enterprise.total_money, 999000000.0);
ASSERT_FALSE(miner_enterprise.is_bankrupt);
ASSERT_DOUBLE_EQ(minerEnterprise.totalMoney, 999000000.0);
ASSERT_FALSE(minerEnterprise.isBankrupt);
}
TEST_F(SystemsTest, RoutineBankruptcy)
{
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
miner_enterprise.set_money(1000000.0);
miner_enterprise.salary = 100000.0;
miner_enterprise.staff_size = 11;
ee_economy::Enterprise &minerEnterprise = registry.get<ee_economy::Enterprise>(miner);
minerEnterprise.setMoney(1000000.0);
minerEnterprise.salary = 100000.0;
minerEnterprise.staffSize = 11;
ee_economy::enterprise_routine(registry);
ee_economy::enterpriseRoutine(registry);
ASSERT_DOUBLE_EQ(miner_enterprise.total_money, 0.0);
ASSERT_TRUE(miner_enterprise.is_bankrupt);
ASSERT_DOUBLE_EQ(minerEnterprise.totalMoney, 0.0);
ASSERT_TRUE(minerEnterprise.isBankrupt);
}

View File

@ -4,110 +4,110 @@
TEST_F(SystemsTest, MiningNormal)
{
ee_economy::container &state_container = registry.get<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(miner);
ee_economy::Container &stateContainer = registry.get<ee_economy::Container>(state);
ee_economy::Container &minerContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Enterprise &minerEnterprise = registry.get<ee_economy::Enterprise>(miner);
ee_economy::Miner &minerMiner = registry.get<ee_economy::Miner>(miner);
state_container.capacity = 15.0;
state_container.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
stateContainer.capacity = 15.0;
stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
miner_container.capacity = 5.0;
miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL;
miner_enterprise.set_base_efficiency(0.1);
minerContainer.capacity = 5.0;
minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL;
minerEnterprise.setBaseEfficiency(0.1);
ee_economy::mining(registry);
ASSERT_DOUBLE_EQ(state_container.total, 9.9);
ASSERT_DOUBLE_EQ(state_container.content[ee_economy::RESOURCE_TYPE::COAL], 9.9);
ASSERT_DOUBLE_EQ(miner_container.total, 0.1);
ASSERT_DOUBLE_EQ(miner_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.1);
ASSERT_DOUBLE_EQ(stateContainer.total, 9.9);
ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 9.9);
ASSERT_DOUBLE_EQ(minerContainer.total, 0.1);
ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.1);
}
TEST_F(SystemsTest, MiningEmptyState)
{
ee_economy::container &state_container = registry.get<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(miner);
ee_economy::Container &stateContainer = registry.get<ee_economy::Container>(state);
ee_economy::Container &minerContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Enterprise &minerEnterprise = registry.get<ee_economy::Enterprise>(miner);
ee_economy::Miner &minerMiner = registry.get<ee_economy::Miner>(miner);
state_container.capacity = 15.0;
stateContainer.capacity = 15.0;
miner_container.capacity = 5.0;
miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL;
miner_enterprise.set_base_efficiency(0.1);
minerContainer.capacity = 5.0;
minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL;
minerEnterprise.setBaseEfficiency(0.1);
ee_economy::mining(registry);
ASSERT_DOUBLE_EQ(state_container.total, 0.0);
ASSERT_DOUBLE_EQ(state_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(miner_container.total, 0.0);
ASSERT_DOUBLE_EQ(miner_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(stateContainer.total, 0.0);
ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(minerContainer.total, 0.0);
ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
}
TEST_F(SystemsTest, MiningPoorState)
{
ee_economy::container &state_container = registry.get<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(miner);
ee_economy::Container &stateContainer = registry.get<ee_economy::Container>(state);
ee_economy::Container &minerContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Enterprise &minerEnterprise = registry.get<ee_economy::Enterprise>(miner);
ee_economy::Miner &minerMiner = registry.get<ee_economy::Miner>(miner);
state_container.capacity = 15.0;
state_container.add(ee_economy::RESOURCE_TYPE::COAL, 0.05);
stateContainer.capacity = 15.0;
stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 0.05);
miner_container.capacity = 5.0;
miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL;
miner_enterprise.set_base_efficiency(0.1);
minerContainer.capacity = 5.0;
minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL;
minerEnterprise.setBaseEfficiency(0.1);
ee_economy::mining(registry);
ASSERT_DOUBLE_EQ(state_container.total, 0.0);
ASSERT_DOUBLE_EQ(state_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(miner_container.total, 0.05);
ASSERT_DOUBLE_EQ(miner_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.05);
ASSERT_DOUBLE_EQ(stateContainer.total, 0.0);
ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(minerContainer.total, 0.05);
ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.05);
}
TEST_F(SystemsTest, MiningReachCap)
{
ee_economy::container &state_container = registry.get<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(miner);
ee_economy::Container &stateContainer = registry.get<ee_economy::Container>(state);
ee_economy::Container &minerContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Enterprise &minerEnterprise = registry.get<ee_economy::Enterprise>(miner);
ee_economy::Miner &minerMiner = registry.get<ee_economy::Miner>(miner);
state_container.capacity = 15.0;
state_container.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
stateContainer.capacity = 15.0;
stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
miner_container.capacity = 0.05;
miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL;
miner_enterprise.set_base_efficiency(0.1);
minerContainer.capacity = 0.05;
minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL;
minerEnterprise.setBaseEfficiency(0.1);
ee_economy::mining(registry);
ASSERT_DOUBLE_EQ(state_container.total, 9.95);
ASSERT_DOUBLE_EQ(state_container.content[ee_economy::RESOURCE_TYPE::COAL], 9.95);
ASSERT_DOUBLE_EQ(miner_container.total, 0.05);
ASSERT_DOUBLE_EQ(miner_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.05);
ASSERT_DOUBLE_EQ(stateContainer.total, 9.95);
ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 9.95);
ASSERT_DOUBLE_EQ(minerContainer.total, 0.05);
ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.05);
}
TEST_F(SystemsTest, MiningBankrupt)
{
ee_economy::container &state_container = registry.get<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(miner);
ee_economy::Container &stateContainer = registry.get<ee_economy::Container>(state);
ee_economy::Container &minerContainer = registry.get<ee_economy::Container>(miner);
ee_economy::Enterprise &minerEnterprise = registry.get<ee_economy::Enterprise>(miner);
ee_economy::Miner &minerMiner = registry.get<ee_economy::Miner>(miner);
state_container.capacity = 15.0;
state_container.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
stateContainer.capacity = 15.0;
stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0);
miner_container.capacity = 5.0;
miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL;
miner_enterprise.set_base_efficiency(0.1);
miner_enterprise.is_bankrupt = true;
minerContainer.capacity = 5.0;
minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL;
minerEnterprise.setBaseEfficiency(0.1);
minerEnterprise.isBankrupt = true;
ee_economy::mining(registry);
ASSERT_DOUBLE_EQ(state_container.total, 10.0);
ASSERT_DOUBLE_EQ(state_container.content[ee_economy::RESOURCE_TYPE::COAL], 10.0);
ASSERT_DOUBLE_EQ(miner_container.total, 0.0);
ASSERT_DOUBLE_EQ(miner_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
ASSERT_DOUBLE_EQ(stateContainer.total, 10.0);
ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 10.0);
ASSERT_DOUBLE_EQ(minerContainer.total, 0.0);
ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0);
}

View File

@ -18,25 +18,25 @@ struct SystemsTest : testing::Test
{
// Create state
state = registry.create();
registry.emplace<ee_economy::state>(state);
registry.emplace<ee_economy::container>(state);
registry.emplace<ee_economy::State>(state);
registry.emplace<ee_economy::Container>(state);
// Create miner enterprise
miner = registry.create();
registry.emplace<ee_economy::enterprise>(miner, false, state);
registry.emplace<ee_economy::miner>(miner);
registry.emplace<ee_economy::container>(miner);
registry.emplace<ee_economy::Enterprise>(miner, false, state);
registry.emplace<ee_economy::Miner>(miner);
registry.emplace<ee_economy::Container>(miner);
// Create storage enterprise
storage = registry.create();
registry.emplace<ee_economy::enterprise>(storage, false, state);
registry.emplace<ee_economy::container>(storage);
registry.emplace<ee_economy::Enterprise>(storage, false, state);
registry.emplace<ee_economy::Container>(storage);
// Create delivering enterprise
deliverer = registry.create();
registry.emplace<ee_economy::enterprise>(deliverer, false, state);
registry.emplace<ee_economy::deliverer>(deliverer);
registry.emplace<ee_economy::container>(deliverer);
registry.emplace<ee_economy::Enterprise>(deliverer, false, state);
registry.emplace<ee_economy::Deliverer>(deliverer);
registry.emplace<ee_economy::Container>(deliverer);
}
void TearDown()

View File

@ -1,6 +0,0 @@
{
"dependencies": [
"entt",
"gtest"
]
}

12
frontend/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"configurations": [
{
"type": "cmake",
"request": "launch",
"name": "Debug portfile(s)",
"cmakeDebugType": "external",
"pipeName": "\\\\.\\pipe\\vcpkg_ext_portfile_dbg",
"preLaunchTask": "Debug vcpkg commands"
}
]
}

59
frontend/CMakeLists.txt Normal file
View File

@ -0,0 +1,59 @@
cmake_minimum_required (VERSION 3.8)
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project (EEfrontend)
# List sources
#set(HEADERS "RmlVulkanInterface.hpp")
set(SOURCES "main.cpp")
#list(TRANSFORM HEADERS PREPEND "include/")
list(TRANSFORM SOURCES PREPEND "src/")
# Find dependencies
find_package(SDL2 CONFIG REQUIRED)
find_package(Vulkan REQUIRED)
find_package(RmlUi CONFIG REQUIRED)
# Link library
add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE p7)
target_link_libraries(
${PROJECT_NAME}
PRIVATE
$<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
)
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan)
set(RMLUI_BACKEND_PATH ${RmlUi_SOURCE_DIR}/Backends) # Link SDL Vulkan backend for RmlUi
add_library(rmlui_backend_SDL_VK INTERFACE)
target_sources(rmlui_backend_SDL_VK INTERFACE
${RMLUI_BACKEND_PATH}/RmlUi_Platform_SDL.cpp
${RMLUI_BACKEND_PATH}/RmlUi_Renderer_VK.cpp
)
target_include_directories(rmlui_backend_SDL_VK INTERFACE ${RMLUI_BACKEND_PATH})
target_compile_definitions(rmlui_backend_SDL_VK INTERFACE
RMLUI_SDL_VERSION_MAJOR=2
RMLUI_NUM_MSAA_SAMPLES=4
RMLUI_VK_CUSTOM_LOADER=<vulkan/vulkan.h>
)
target_link_libraries(${PROJECT_NAME} PRIVATE RmlUi::RmlUi)
target_include_directories(${PROJECT_NAME} PUBLIC include/)
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()

120
frontend/src/main.cpp Normal file
View File

@ -0,0 +1,120 @@
#ifdef _DEBUG
#define P7_SINK L"/P7.Sink=Console"
#else
#define P7_SINK L"/P7.Sink=FileTxt"
#endif
#include "P7_Client.h"
#include "P7_Trace.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h>
#include <vulkan/vulkan.h>
#include <RmlUi/Core.h>
int SDL_main(int argc, char **argv)
{
// Setup P7 logger
IP7_Client *p7client = P7_Create_Client(P7_SINK);
P7_Set_Crash_Handler();
IP7_Trace *logger = P7_Create_Trace(p7client, L"TC 1");
logger->Register_Thread(L"MainThread", 0);
// Setup SDL
bool quit = false;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow(
"Etredia Empires",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
800,
600,
SDL_WINDOW_VULKAN
);
if (!window)
{
quit = true;
LOG(logger, CRITICAL, "SDL Window fails: %hs", SDL_GetError());
}
else LOG(logger, INFO, "SDL Window created");
// Setup Vulkan
VkInstance vulkan;
uint32_t sdlExtensionsCount = 0;
if ( !SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionsCount, nullptr) )
LOG(logger, CRITICAL, "Fail to get SDL Vulkan extensions number! %hs", SDL_GetError());
const char **sdlExtentions = new const char*[sdlExtensionsCount]();
if ( !SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionsCount, sdlExtentions) )
LOG(logger, CRITICAL, "Fail to load SDL Vulkan extentions! %hs", SDL_GetError());
else LOG(logger, INFO, "Load %d SDL Vulkan extenstions", sdlExtensionsCount);
VkInstanceCreateInfo vkCreateConfig = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.enabledLayerCount = 0,
.enabledExtensionCount = sdlExtensionsCount,
.ppEnabledExtensionNames = sdlExtentions
};
VkResult vkCreateResult = vkCreateInstance(&vkCreateConfig, nullptr, &vulkan);
if (vkCreateResult != VK_SUCCESS)
LOG(logger, CRITICAL, "Vulkan is not instantiated! Code: %d", vkCreateResult);
else LOG(logger, INFO, "Vulkan is instantiated");
delete[] sdlExtentions;
//Setup RmlUi
if (!Rml::Initialise())
LOG(logger, CRITICAL, "RmlUi initialization failed!");
else LOG(logger, INFO, "RmlUi initialized");
int32_t screenWidth, screenHeight;
SDL_GetWindowSize(window, &screenWidth, &screenHeight);
Rml::Context *uiContext = Rml::CreateContext("default", Rml::Vector2i(screenWidth, screenHeight));
// Process SDL events
while(!quit)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
{
quit = true;
break;
}
case SDL_WINDOWEVENT:
{
switch (event.window.event)
{
case SDL_WINDOWEVENT_RESIZED:
{
uiContext->SetDimensions(Rml::Vector2i(event.window.data1, event.window.data2));
break;
}
}
break;
}
}
}
// Free memory
LOG(logger, INFO, "Exit...");
Rml::Shutdown();
vkDestroyInstance(vulkan, nullptr);
SDL_Quit();
logger->Unregister_Thread(0);
logger->Release();
p7client->Release();
return 0;
}

69
p7lib/CMakeLists.txt Normal file
View File

@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
#project(p7lib)
#>>Build options **********************************************************************
option(P7_TESTS_BUILD "Build test" OFF)
set(P7_BUILD_SHARED OFF CACHE INTERNAL "Build shared library")
#<<Build options **********************************************************************
include(CheckCXXCompilerFlag)
function(enable_cxx_compiler_flag_if_supported flag)
string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_already_set)
if(flag_already_set EQUAL -1)
check_cxx_compiler_flag("${flag}" flag_supported)
if(flag_supported)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
endif()
endif()
endfunction()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
if(NOT DEFINED ROOT_P7_PATH)
set(ROOT_P7_PATH ${PROJECT_SOURCE_DIR} CACHE INTERNAL "")
set(PATH_P7 ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")
set(PATH_P7_API "${PROJECT_SOURCE_DIR}/Headers" CACHE INTERNAL "")
else(expression)
endif(NOT DEFINED ROOT_P7_PATH)
if(MSVC)
add_definitions(-D_UNICODE)
add_definitions(-DUNICODE)
if(NOT COMMAND set_ide_folder)
macro(set_ide_folder _project_name)
string(LENGTH ${ROOT_P7_PATH} ROOT_P7_PATH_LEN)
string(LENGTH ${CMAKE_CURRENT_SOURCE_DIR} CURRENT_SOURCE_DIR_LEN)
MATH(EXPR ROOT_P7_PATH_LEN "${ROOT_P7_PATH_LEN}+1")
MATH(EXPR CURRENT_SOURCE_DIR_LEN "${CURRENT_SOURCE_DIR_LEN} - ${ROOT_P7_PATH_LEN}")
string(SUBSTRING ${CMAKE_CURRENT_SOURCE_DIR} ${ROOT_P7_PATH_LEN} ${CURRENT_SOURCE_DIR_LEN} IDE_SUBFOLDER)
set_property(TARGET ${_project_name} PROPERTY FOLDER ${IDE_SUBFOLDER})
endmacro()
endif()
else()
enable_cxx_compiler_flag_if_supported("-Wall")
enable_cxx_compiler_flag_if_supported("-Wextra")
enable_cxx_compiler_flag_if_supported("-pedantic")
enable_cxx_compiler_flag_if_supported("-D_FILE_OFFSET_BITS=64")
enable_cxx_compiler_flag_if_supported("-D_LARGEFILE64_SOURCE")
enable_cxx_compiler_flag_if_supported("-fvisibility=hidden")
enable_cxx_compiler_flag_if_supported("-Wno-variadic-macros")
enable_cxx_compiler_flag_if_supported("-Wno-long-long")
enable_cxx_compiler_flag_if_supported("-Wno-missing-field-initializers")
enable_cxx_compiler_flag_if_supported("-Wno-unknown-pragmas")
enable_cxx_compiler_flag_if_supported("-fPIC")
macro(set_ide_folder _project_name)
endmacro()
endif()
add_subdirectory(Headers)
add_subdirectory(Shared)
add_subdirectory(Sources)
if(P7_TESTS_BUILD)
add_subdirectory(Tests)
endif()

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
set(PATH_P7_API ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")

151
p7lib/Headers/GTypes.h Normal file
View File

@ -0,0 +1,151 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef GTYPE_H
#define GTYPE_H
#if defined(_M_X64)\
|| defined(__amd64__)\
|| defined(__amd64)\
|| defined(_WIN64)\
|| defined(_WIN64_)\
|| defined(WIN64)\
|| defined(__LP64__)\
|| defined(_LP64)\
|| defined(__x86_64__)\
|| defined(__ppc64__)\
|| defined(__aarch64__)
#define GTX64
#else
#define GTX32
#endif
#define CONCATENATE_DETAIL(x, y) x##y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define MAKE_UNIQUE(x) CONCATENATE(x, __COUNTER__)
////////////////////////////////////////////////////////////////////////////////
//WINDOWS specific definitions & types
#if defined(_WIN32) || defined(_WIN64)
#define G_OS_WINDOWS
#if !defined(_WINSOCKAPI_)
#include <winsock2.h>
#endif
#include <windows.h>
//Text marco, allow to use wchar_t automatically
#define TM(i_pStr) L##i_pStr
#define XCHAR wchar_t
typedef wchar_t tWCHAR;
#define WND_HANDLE HWND
#define SHARED_EXT L"dll"
#define P7_EXPORT __declspec(dllexport)
#define OS_PATH_SEPARATOR TM("\\")
////////////////////////////////////////////////////////////////////////////////
//LINUX specific definitions & types
#elif defined(__linux__)
#define UTF8_ENCODING
#define G_OS_LINUX
//Text marco, allow to use char automatically
#define TM(i_pStr) i_pStr
#define XCHAR char
typedef unsigned short tWCHAR;
#define WND_HANDLE void*
#define SHARED_EXT "so"
typedef struct _GUID
{
unsigned int Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
#define __stdcall
#define __cdecl
#ifndef __forceinline
#if defined(GTX64) || defined(__PIC__)
#define __forceinline
#else
#define __forceinline __attribute__((always_inline))
#endif
#endif
#define P7_EXPORT __attribute__ ((visibility ("default")))
#define OS_PATH_SEPARATOR TM("/")
#endif
#ifdef _MSC_VER
#define PRAGMA_PACK_ENTER(x) __pragma(pack(push, x))
#define PRAGMA_PACK_EXIT() __pragma(pack(pop))
#define ATTR_PACK(x)
#define ATTR_ALIGN(x)
#define UNUSED_FUNC
#else
#define PRAGMA_PACK_ENTER(x)
#define PRAGMA_PACK_EXIT(x)
#define ATTR_PACK(x) __attribute__ ((aligned(x), packed))
#define ATTR_ALIGN(x) __attribute__ ((aligned(x)))
#define UNUSED_FUNC __attribute__ ((unused))
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define UNUSED_ARG(x) (void)(x)
#define STR_HELPER(x) #x
#define TOSTR(x) STR_HELPER(x)
#define TMM(i_pStr) TM(i_pStr)
typedef unsigned long long tUINT64;
typedef long long tINT64;
typedef unsigned int tUINT32;
typedef int tINT32;
typedef unsigned short tUINT16;
typedef short tINT16;
typedef unsigned char tUINT8;
typedef char tINT8;
typedef char tACHAR;
//platfrorm specific char, Windows - wchar_t, Linix - char,
//XCHAR defined in PTypes.hpp specific for each platform or project.
#define tXCHAR XCHAR
//typedef XCHAR tXCHAR;
typedef unsigned int tBOOL;
typedef double tDOUBLE;
#define GASSERT(cond) typedef int assert_type[(cond) ? 1 : -1]
#endif //GTYPE_H

574
p7lib/Headers/P7_Client.h Normal file
View File

@ -0,0 +1,574 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// This header file provide client functionality /
// /
// +-------------------+ /
// | Sink | /
// | * Network (Baical)| /
// | * FileBin | /
// | * FileTxt | /
// | * Console | /
// | * Syslog | /
// | * Auto | /
// | * Null | /
// +---------^---------+ /
// | /
// | /
// +---------+---------+ /
// | P7 Client | /
// | [ Channels ] | /
// | +-+ +-+ +--+ | /
// | |0| |1| ...|31| | /
// | +^+ +^+ +-^+ | /
// +---|---|-------|---+ /
// | | | /
// +-----+ | +----------+ /
// | | | /
// | | | /
// +---+---+ +---+--------+ +---+---+ /
// | Trace | | Telemetry | | Trace | /
// |Channel| | channel | ... |Channel| /
// +-------+ +------------+ +-------+ /
// /
////////////////////////////////////////////////////////////////////////////////
// //
// Documentation is located in <P7>/Documentation/P7.pdf //
// //
////////////////////////////////////////////////////////////////////////////////
#ifndef P7_CLIENT_H
#define P7_CLIENT_H
#include "GTypes.h"
#include "P7_Version.h"
#define CLIENT_DEFAULT_SHARED_NAME TM("P7.Client")
//Values: P7 sink (logs, traces & telemetry destination)
//There are 3 possible values:
// * Baical - over network to Baical server directly
// * File - to file
// * Auto - to Baical if connection is established, otherwise to file
// N.B.: connection timeout is 250 ms.
// * Null - all data will be dropped
// Default value: Baical
#define CLIENT_COMMAND_LINE_SINK TM("/P7.Sink=")
#define CLIENT_SINK_BAICAL TM("Baical")
#define CLIENT_SINK_FILE_BIN TM("FileBin")
#define CLIENT_SINK_FILE_BIN_LEGACY TM("File")
#define CLIENT_SINK_FILE_TXT TM("FileTxt")
#define CLIENT_SINK_CONSOLE TM("Console")
#define CLIENT_SINK_SYSLOG TM("Syslog")
#define CLIENT_SINK_AUTO TM("Auto")
#define CLIENT_SINK_NULL TM("Null")
//Values: P7 client name, max length is about 96 characters, by default it is
//name of the process. Useful in case when P7 is used from script language and
//name of host process isn't usable - for example Python.exe
#define CLIENT_COMMAND_LINE_NAME TM("/P7.Name=")
////////////////////////////////////////////////////////////////////////////////
// Sink=Baical arguments /
////////////////////////////////////////////////////////////////////////////////
//Values: server address
//IPV4 address : XXX.XXX.XXX.XXX
//IPV6 address : ::1, etc.
//NetBios Name : any name
#define CLIENT_COMMAND_LINE_BAICAL_ADDRESS TM("/P7.Addr=")
//Values: server specified port
//default: 9009
#define CLIENT_COMMAND_LINE_BAICAL_PORT TM("/P7.Port=")
//Values: size of the data packet
// Min: 512
// Max: 65535
// Recommended: your network MTU size
// default: 1472
#define CLIENT_COMMAND_PACKET_BAICAL_SIZE TM("/P7.PSize=")
//size of the transmission window in packets. Sometimes is useful to manage it
//if server aggressively loose incoming packets, this parameter is for precise
//tuning, in most of the cases stay untouched and protocol manage it
//Min = 1
//max = ((pool size / packet size) / 2)
#define CLIENT_COMMAND_WINDOW_BAICAL_SIZE TM("/P7.Window=")
//specifies exit timeout in seconds, used to deliver last data chunks to server
//max value is 15 seconds
#define CLIENT_COMMAND_LINE_BAICAL_EXIT_TIMEOUT TM("/P7.Eto=")
////////////////////////////////////////////////////////////////////////////////
// Sink=File arguments /
////////////////////////////////////////////////////////////////////////////////
//Value: path to destination file
//default: <current process dir>/P7logs
#define CLIENT_COMMAND_LINE_DIR TM("/P7.Dir=")
//Value: define rolling type
// Xmb - rolling every X megabytes, for example /P7.Roll=10mb
// Xhr - rolling every X hours, for example /P7.Roll=24hr, max = 1000hr
// HH:MMtm - rolling by time (00:00 -> 23:59), for example:
// * rolling at 12:00 -> P7.Roll=12:00tm
// * rolling at 12:00 and 00:00 -> P7.Roll=00:00,12:00tm
//default: rolling is off
#define CLIENT_COMMAND_LINE_FILE_ROLLING TM("/P7.Roll=")
//Value: define maximum P7 logs files in destination folder /P7.Dir="MyDir"
//in case if count of files is larger than specified value - oldest files will
//be removed
//default : off (0)
//min : 1
//max : 4096
#define CLIENT_COMMAND_LINE_FILES_COUNT_MAX TM("/P7.Files=")
//Value: define maximum P7 logs files cumulative size in MB at destination
//folder /P7.Dir="MyDir" in case if size of files is larger than specified
//value - oldest files will be removed
//default : off (0)
//min : 1
//max : 4294967296
#define CLIENT_COMMAND_LINE_FILES_SIZE_MAX TM("/P7.FSize=")
////////////////////////////////////////////////////////////////////////////////
// general settings /
////////////////////////////////////////////////////////////////////////////////
//Values:
// 0 : Debug
// 1 : Info
// 2 : Warnings
// 3 : Errors
// 4 : Critical
// default: logging is off
#define CLIENT_COMMAND_LOG_VERBOSITY TM("/P7.Verb=")
//Manage internal logging
//Values:
// 0 : Off
// 1 : On
//default: On(1)
#define CLIENT_COMMAND_LOG_ON TM("/P7.On=")
//size of the internal buffers pool in kilobytes. Minimal 16(kb), max is not
//specified
//default value = 1mb
#define CLIENT_COMMAND_POOL_SIZE TM("/P7.Pool=")
//specify do we need to flush channels inside P7_Exceptional_Flush call
//Values: 1 = yes, 0 = no
//default value = 1
#define CLIENT_COMMAND_FLUSH_CHANNELS TM("/P7.FlashChannels=")
//specifies log message format for such sinks like: FileTxt, Console, SysLog
//format example:
// /P7.Format="%cn #%ix [%tf] %lv Tr:#%ti:%tn CPU:%cc Md:%mn {%fs:%fl:%fn} %ms"
#define CLIENT_COMMAND_FORMAT TM("/P7.Format=")
#define CLIENT_FMT_CHANNEL TM("cn")
#define CLIENT_FMT_MSG_ID TM("id")
#define CLIENT_FMT_MSG_INDEX TM("ix")
#define CLIENT_FMT_TIME_FULL TM("tf")
#define CLIENT_FMT_TIME_MEDIUM TM("tm")
#define CLIENT_FMT_TIME_SHORT TM("ts")
#define CLIENT_FMT_TIME_DIFF TM("td")
#define CLIENT_FMT_TIME_COUNT TM("tc")
#define CLIENT_FMT_LEVEL TM("lv")
#define CLIENT_FMT_THREAD_ID TM("ti")
#define CLIENT_FMT_THREAD_NAME TM("tn")
#define CLIENT_FMT_CPU_CORE TM("cc")
#define CLIENT_FMT_MODULE_ID TM("mi")
#define CLIENT_FMT_MODULE_NAME TM("mn")
#define CLIENT_FMT_FILE_FULL TM("ff")
#define CLIENT_FMT_FILE_SHORT TM("fs")
#define CLIENT_FMT_FILE_LINE TM("fl")
#define CLIENT_FMT_FUNCTION TM("fn")
#define CLIENT_FMT_MSG TM("ms")
//Syslog facility digit https://tools.ietf.org/html/rfc3164#page-8
#define CLIENT_COMMAND_SYSLOG_FACILITY TM("/P7.Facility=")
//Values: No values
#define CLIENT_COMMAND_LOG_HELP TM("/P7.Help")
////////////////////////////////////////////////////////////////////////////////
// Trace settings /
////////////////////////////////////////////////////////////////////////////////
//Override verbosity for all trace streams and modules
//Values:
//0 = EP7TRACE_LEVEL_TRACE
//1 = EP7TRACE_LEVEL_DEBUG
//2 = EP7TRACE_LEVEL_INFO
//3 = EP7TRACE_LEVEL_WARNING
//4 = EP7TRACE_LEVEL_ERROR
//5 = EP7TRACE_LEVEL_CRITICAL
//Example: /P7.Trc.Verb=5
#define CLIENT_COMMAND_TRACE_VERBOSITY TM("/P7.Trc.Verb=")
#define CLIENT_HELP_STRING\
TM("P7 arguments:\n")\
TM(" -General arguments: \n")\
TM(" /P7.Sink - Select data flow direction, there are few values:\n")\
TM(" * Baical - to Baical server over network(fast and efficient)\n")\
TM(" * FileBin - to local binary file (fast and efficient)\n")\
TM(" * FileTxt - to local text file (slow comparing to FileBin/Baical)\n")\
TM(" * Syslog - to syslog server (slow comparing to FileBin/Baical)\n")\
TM(" * Console - to console (slow comparing to FileBin/Baical)\n")\
TM(" * Auto - to Baical server if connection is istablished, otherwise to file\n")\
TM(" N.B.: connection timeout is 250 ms !\n")\
TM(" * Null - drop all incoming data\n")\
TM(" Examples:\n")\
TM(" /P7.Sink=Baical\n")\
TM(" /P7.Sink=File\n")\
TM(" /P7.Sink=Null\n")\
TM(" /P7.Name - P7 client name, max length is about 96 characters, by default it is\n")\
TM(" name of the host process. Useful in case when P7 is used from scrip\n")\
TM(" language and name of host process is not suitable - for example Python.exe\n")\
TM(" Example:\n")\
TM(" /P7.Name=Client\n")\
TM(" /P7.On - Enable/Disable P7 network engine, By default P7 is on\n")\
TM(" Examples:\n")\
TM(" /P7.On=1\n")\
TM(" /P7.On=0\n")\
TM(" /P7.Verb - Set logging verbosity level. This option allow to write\n")\
TM(" to text log file or stdout all internal engine messages.\n")\
TM(" Do not specify /P7.Verb parameter to switch off the logging\n")\
TM(" P7 internal logging has next verbosity levels:\n")\
TM(" 0 : Info\n")\
TM(" 1 : Debug\n")\
TM(" 2 : Warnings\n")\
TM(" 3 : Errors\n")\
TM(" 4 : Critical\n")\
TM(" Example: /P7.Verb=4\n")\
TM(" /P7.Trc.Verb- Set verbosity level for all trace streams and associated modules\n")\
TM(" Has next verbosity levels:\n")\
TM(" 0 : Trace\n")\
TM(" 1 : Debug\n")\
TM(" 2 : Info\n")\
TM(" 3 : Warnings\n")\
TM(" 4 : Errors\n")\
TM(" 5 : Critical\n")\
TM(" Example: /P7.Trc.Verb=4\n")\
TM(" /P7.Pool - Set size of the internal buffers pool in kilobytes. Minimal 16(kb)\n")\
TM(" maximal is limited by your OS and HW. Default value = 4mb\n")\
TM(" Example, 1 Mb allocation: /P7.Pool=1024\n")\
TM(" -Sink=Baical, -Sink=Syslog : \n")\
TM(" /P7.Addr - Set server address (IPV4, IPV6, NetBios name)\n")\
TM(" Examples:\n")\
TM(" /P7.Addr=127.0.0.1\n")\
TM(" /P7.Addr=::1\n")\
TM(" /P7.Addr=MyPC\n")\
TM(" Default address is 127.0.0.1\n")\
TM(" /P7.Port - Set server port, default port is 9009\n")\
TM(" Example: /P7.Port=9010\n")\
TM(" /P7.PSize - Set packet size. Min value 512 bytes, Max - 65535, Default - 512\n")\
TM(" You should specify optimum packet size\n")\
TM(" for your network, usually it is MTU.\n")\
TM(" Example: /P7.PSize=1476\n")\
TM(" -Sink=FileBin, -Sink=FileTxt: \n")\
TM(" /P7.Dir - Directory where P7 files will be created, if it is not specified\n")\
TM(" process directory will be used.\n")\
TM(" Examples:\n")\
TM(" /P7.Dir=/home/user/logs/\n")\
TM(" /P7.Dir=C:\\Logs\\\n")\
TM(" /P7.Files - defines maximum P7 logs files in destination folder\n")\
TM(" in case if count of files is larger than specified value\n")\
TM(" oldest files will be removed\n")\
TM(" /P7.Roll - use it to specify files rolling value & type. There are 2 rolling types:\n")\
TM(" * Rolling by file size, measured in megabytes\n")\
TM(" * Rolling by time, measured in hours, 1000 hours max\n")\
TM(" Rolling value consists of 2 parts:\n")\
TM(" * digit\n")\
TM(" * postfix: hr, mb\n")\
TM(" Examples:\n")\
TM(" /P7.Roll=100mb\n")\
TM(" /P7.Roll=24hr\n")\
TM(" -Sink=FileTxt, -Sink=Console, -Sink=Syslog: \n")\
TM(" /P7.Format - log message format sting, example: /P7.Format=\"{%%cn} [%%tf] %%lv %%ms\"\n")\
TM(" * cn - channel name \n")\
TM(" * id - message ID\n")\
TM(" * ix - message index\n")\
TM(" * tf - full time YY.MM.DD HH.MM.SS.mils.mics.nans\n")\
TM(" * tm - time medium HH.MM.SS.mils.mics.nans\n")\
TM(" * ts - time short MM.SS.mils.mics.nans\n")\
TM(" * td - time difference between current and prev. one +SS.mils.mics.nans\n")\
TM(" * tc - time stamp in 100 nanoseconds intervals\n")\
TM(" * lv - level (error, warning, etc)\n")\
TM(" * ti - thread ID\n")\
TM(" * tn - thread name\n")\
TM(" * cc - CPU core\n")\
TM(" * mi - module ID\n")\
TM(" * mn - module name\n")\
TM(" * ff - file path + name\n")\
TM(" * fs - file name\n")\
TM(" * fl - file line\n")\
TM(" * fn - function name\n")\
TM(" * ms - message\n")\
TM(" -Sink=Null: \n")\
TM(" there is no arguments\n")\
//Error codes of P7 library, if you want to get extended information about error code please activate internal
//console(Linux)/file(Windows) logging. To activate it add parameter to client "/P7.Verb=0"
enum eP7_Error
{
eP7_Error_None = 0,
eP7_Error_SharedObjectInvalid,
eP7_Error_MemoryAllocation,
eP7_Error_Network,
eP7_Error_OS,
eP7_Error_UserSettings,
eP7_Error_FolderCreation,
eP7_Error_FileCreation,
eP7_Error_NoClient,
eP7_Error_NoFreeChannels,
eP7_Error_Max
};
enum eClient_Status
{
//Regular statuses
ECLIENT_STATUS_OK = 0,
ECLIENT_STATUS_OFF ,
ECLIENT_STATUS_INTERNAL_ERROR ,
//Temporary statuses
ECLIENT_STATUS_DISCONNECTED ,
ECLIENT_STATUS_NO_FREE_BUFFERS ,
ECLIENT_STATUS_NOT_ALLOWED ,
ECLIENT_STATUS_WRONG_PARAMETERS ,
ECLIENT_STATUS_WRONG_FORMAT
};
PRAGMA_PACK_ENTER(4) //alignment is now 4, MS Only//////////////////////////////
struct sP7C_Status
{
tBOOL bConnected;
//count of the connection drops, when connection has been reinitialized
tUINT32 dwResets;
}ATTR_PACK(4);
struct sP7C_Data_Chunk
{
void *pData;
tUINT32 dwSize;
}ATTR_PACK(4);
struct sP7C_Channel_Info
{
tUINT32 dwID;
}ATTR_PACK(4);
struct sP7C_Info
{
//sockaddr_storage sServer;
tUINT32 dwMem_Used;
tUINT32 dwMem_Free;
tUINT32 dwMem_Alloc;
tUINT32 dwReject_Mem; //chunks rejected counter - no memory
tUINT32 dwReject_Con; //chunks rejected counter - no connection
tUINT32 dwReject_Int; //chunks rejected counter - internal errors
}ATTR_PACK(4);
PRAGMA_PACK_EXIT()//4///////////////////////////////////////////////////////////
class /*__declspec(novtable)*/ IP7C_Channel
{
public:
enum eType
{
eTrace,
eTelemetry,
eCount
};
////////////////////////////////////////////////////////////////////////////
//Get_Type - get channel type, depending on type cast to IP7_Telemetry or
// IP7_Trace is available
virtual IP7C_Channel::eType Get_Type() = 0;
////////////////////////////////////////////////////////////////////////////
//Add_Ref - increase object's reference count
// See documentation for details.
virtual tINT32 Add_Ref() = 0;
////////////////////////////////////////////////////////////////////////////
//Release - decrease object's reference count. If reference count less or
// equal to 0 - object will be destroyed
// See documentation for details.
virtual tINT32 Release() = 0;
virtual void On_Init(sP7C_Channel_Info *i_pInfo) = 0;
virtual void On_Receive(tUINT32 i_dwChannel,
tUINT8 *i_pBuffer,
tUINT32 i_dwSize,
tBOOL i_bBigEndian
) = 0;
virtual void On_Status(tUINT32 i_dwChannel, const sP7C_Status *i_pStatus)=0;
virtual void On_Flush(tUINT32 i_dwChannel, tBOOL *io_pCrash) = 0;
};
//Define the max channels count, and max packet size for IP7_Client::Sent(...)
#define USER_PACKET_CHANNEL_ID_BITS_COUNT (5)
#define USER_PACKET_SIZE_BITS_COUNT (32-USER_PACKET_CHANNEL_ID_BITS_COUNT)
#define USER_PACKET_MAX_SIZE (1 << USER_PACKET_SIZE_BITS_COUNT)
#define USER_PACKET_CHANNEL_ID_MAX_SIZE (1 << USER_PACKET_CHANNEL_ID_BITS_COUNT)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class IP7_Client
{
public:
enum eType
{
eBaical,
eFileBin,
eAuto,
eNull,
eText,
eCount
};
virtual IP7_Client::eType Get_Type() = 0;
virtual tINT32 Add_Ref() = 0;
virtual tINT32 Release() = 0;
virtual eClient_Status Get_Status() = 0;
virtual tBOOL Get_Status(sP7C_Status *o_pStatus) = 0;
virtual tBOOL Get_Info(sP7C_Info *o_pInfo) = 0;
//N.B. If you use Baikal server to receive data - please do not mix
// different packets formats (Trace + Telemetry for example) on the same
// channel, in this case one data format will be dropped by server
virtual eClient_Status Register_Channel(IP7C_Channel *i_pChannel) = 0;
virtual eClient_Status Unregister_Channel(tUINT32 i_dwID) = 0;
virtual eClient_Status Sent(tUINT32 i_dwChannel_ID,
sP7C_Data_Chunk *i_pChunks,
tUINT32 i_dwCount,
tUINT32 i_dwSize) = 0;
////////////////////////////////////////////////////////////////////////////
//Share - function to share current P7 object in address space of
// the current process, see documentation for details
virtual tBOOL Share(const tXCHAR *i_pName) = 0;
virtual const tXCHAR *Get_Argument(const tXCHAR *i_pName) = 0;
virtual size_t Get_Channels_Count() = 0;
virtual IP7C_Channel *Get_Channel(size_t i_szIndex) = 0;
virtual void Flush() = 0;
};
////////////////////////////////////////////////////////////////////////////////
//P7_Create_Client - function creates new P7 client.
//See documentation for details
////////////////////////////////////////////////////////////////////////////////
//N.B: P7 client in addition will analyze your application command line and
// arguments specified through command line will have higher priority then
// i_sArgs arguments
extern "C" P7_EXPORT IP7_Client * __cdecl P7_Create_Client(const tXCHAR *i_pArgs);
////////////////////////////////////////////////////////////////////////////////
//This functions allows you to get P7 instance if it was created by someone else
//inside current process.
//See documentation for details.
extern "C" P7_EXPORT IP7_Client * __cdecl P7_Get_Shared(const tXCHAR *i_pName);
////////////////////////////////////////////////////////////////////////////////
//Retrieves the calling thread's last-error code value. The last-error code is
//maintained on a per-thread basis. Multiple threads do not overwrite each other's
//last-error code.
//N.B.: Error code will be reset after function call
extern "C" P7_EXPORT eP7_Error __cdecl P7_Last_Error();
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// P7 Crash processor //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//This function setup crash handler to catch and process exceptions like
// * access violation/segmentation fault
// * division by zero
// * pure virtual call
// * etc.
//When crash occurs handler will call P7_Exceptional_Flush function automatically
extern "C" P7_EXPORT void __cdecl P7_Set_Crash_Handler();
////////////////////////////////////////////////////////////////////////////////
//This function clears crash handler
extern "C" P7_EXPORT void __cdecl P7_Clr_Crash_Handler();
////////////////////////////////////////////////////////////////////////////////
//Function allows to flush (deliver) not delivered/saved P7 buffers for all
//opened clients and related channels owned by process in CASE OF your app/proc.
//crash.
//This function do not call system memory allocation functions only writes to
//file/socket.
//Classical scenario: your application has been crushed, you catch the moment of
//crush and call this function once.
//Has to be used if integrator implements own crash handling mechanism.
//N.B.: DO NOT USE OTHER P7 FUNCTION AFTER CALLING OF THIS FUNCTION
//See documentation for details.
extern "C" P7_EXPORT void __cdecl P7_Exceptional_Flush();
////////////////////////////////////////////////////////////////////////////////
//Function allows to flush (deliver) not delivered/saved P7 buffers for all
//opened clients and related channels owned by process. Please do not use this
//function often, it may reduce performance.
extern "C" P7_EXPORT void __cdecl P7_Flush();
#endif //P7_CLIENT_H

641
p7lib/Headers/P7_Cproxy.h Normal file
View File

@ -0,0 +1,641 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// This header file provides access to P7 library functionality from C language/
// or from any other language using dll/so interface /
// /
// +-------------------+ /
// | Sink | /
// | * Network (Baical)| /
// | * FileBin | /
// | * FileTxt | /
// | * Console | /
// | * Syslog | /
// | * Auto | /
// | * Null | /
// +---------^---------+ /
// | /
// | /
// +---------+---------+ /
// | P7 Client | /
// | [ Channels ] | /
// | +-+ +-+ +--+ | /
// | |0| |1| ...|31| | /
// | +^+ +^+ +-^+ | /
// +---|---|-------|---+ /
// | | | /
// +-----+ | +----------+ /
// | | | /
// | | | /
// +---+---+ +---+--------+ +---+---+ /
// | Trace | | Telemetry | | Trace | /
// |Channel| | channel | ... |Channel| /
// +-------+ +------------+ +-------+ /
// /
////////////////////////////////////////////////////////////////////////////////
// //
// Documentation is located in <P7>/Documentation/P7.pdf //
// //
////////////////////////////////////////////////////////////////////////////////
#ifndef P7_PROXY_H
#define P7_PROXY_H
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// //
// P7 client //
// //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
typedef void* hP7_Client;
typedef tUINT64 (__cdecl *fnGet_Time_Stamp)(void *i_pContext);
typedef void (__cdecl *fnConnect)(void *i_pContext, tBOOL i_bConnected);
////////////////////////////////////////////////////////////////////////////////
//P7_Client_Create - function creates new P7 client, client is used as transport
//engine for telemetry & trace channels, every client can handle up to 32
//channels.
//See documentation for details.
////////////////////////////////////////////////////////////////////////////////
//N.B: P7 client in addition will analyze your application command line and
// arguments specified through command line will have higher priority then
// i_sArgs arguments
extern P7_EXPORT hP7_Client __cdecl P7_Client_Create(const tXCHAR *i_pArgs);
//dll/so function prototype
typedef hP7_Client (__cdecl *fnP7_Client_Create)(const tXCHAR *i_pArgs);
////////////////////////////////////////////////////////////////////////////////
//This functions allows you to get P7 client instance if it was created by
//someone else inside current process and shared using P7_Client_Share() func.
//If no instance was registered inside current process - function will return
//NULL. Do not forget to call P7_Client_Free() when you finish your work.
//See documentation for details.
extern P7_EXPORT hP7_Client __cdecl P7_Client_Get_Shared(const tXCHAR *i_pName);
//dll/so function prototype
typedef hP7_Client (__cdecl *fnP7_Client_Get_Shared)(const tXCHAR *i_pName);
////////////////////////////////////////////////////////////////////////////////
//P7_Client_Share - function to share current P7 client object in address space
//of the current process, to get shared client use function P7_Client_Get_Shared
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Client_Share(hP7_Client i_hClient,
const tXCHAR *i_pName
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Client_Share)(hP7_Client i_hClient,
const tXCHAR *i_pName
);
////////////////////////////////////////////////////////////////////////////////
//P7_Client_Flush - function allows to flush (deliver) not delivered/saved P7
//buffers for current client. Please do not use this function often, it may
//reduce performance.
extern P7_EXPORT void __cdecl P7_Client_Flush(hP7_Client i_hClient);
//dll/so function prototype
typedef void (__cdecl *fnP7_Client_Flush)(hP7_Client i_hClient);
////////////////////////////////////////////////////////////////////////////////
//P7_Client_Add_Ref - increase reference counter for the client
//See documentation for details.
extern P7_EXPORT tINT32 __cdecl P7_Client_Add_Ref(hP7_Client i_hClient);
//dll/so function prototype
typedef tINT32 (__cdecl *fnP7_Client_Add_Ref)(hP7_Client i_hClient);
////////////////////////////////////////////////////////////////////////////////
//P7_Client_Release - function release the client, reference counter technology
//See documentation for details.
extern P7_EXPORT tINT32 __cdecl P7_Client_Release(hP7_Client i_hClient);
//dll/so function prototype
typedef tINT32 (__cdecl *fnP7_Client_Release)(hP7_Client i_hClient);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// P7 Crash processor //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//This function setup crash handler to catch and process exceptions like
// * access violation/segmentation fault
// * division by zero
// * pure virtual call
// * etc.
//When crash occurs handler will call P7_Exceptional_Flush function automatically
extern P7_EXPORT void __cdecl P7_Set_Crash_Handler();
//dll/so function prototype
typedef void (__cdecl *fnP7_Set_Crash_Handler)();
////////////////////////////////////////////////////////////////////////////////
//This function clears crash handler
extern P7_EXPORT void __cdecl P7_Clr_Crash_Handler();
//dll/so function prototype
typedef void (__cdecl *fnP7_Clr_Crash_Handler)();
////////////////////////////////////////////////////////////////////////////////
//Function allows to flush (deliver) not delivered/saved P7 buffers for all
//opened clients and related channels owned by process in CASE OF your app/proc.
//crash.
//This function do not call system memory allocation functions only writes to
//file/socket.
//Classical scenario: your application has been crushed, you catch the moment of
//crush and call this function once.
//Has to be used if integrator implements own crash handling mechanism.
//N.B.: DO NOT USE OTHER P7 FUNCTION AFTER CALLING OF THIS FUNCTION
//See documentation for details.
extern P7_EXPORT void __cdecl P7_Exceptional_Flush();
//dll/so function prototype
typedef void (__cdecl *fnP7_Exceptional_Flush)();
////////////////////////////////////////////////////////////////////////////////
//Function allows to flush (deliver) not delivered/saved P7 buffers for all
//opened clients and related channels owned by process. Please do not use this
//function offten, it may reduce performance.
extern P7_EXPORT void __cdecl P7_Flush();
//dll/so function prototype
typedef void (__cdecl *fnP7_Flush)();
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// //
// P7 Telemetry //
// //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
typedef void* hP7_Telemetry;
typedef void (__cdecl *fnTelemetry_Enable)(void *i_pContext, tUINT16 i_wId, tBOOL i_bEnable);
typedef struct
{
void *pContext; //context to be passed back to callbacks
tUINT64 qwTimestamp_Frequency; //count ticks per second, works in cooperation with pTimestamp_Callback
fnGet_Time_Stamp pTimestamp_Callback; //callback for getting user timestamps, works in cooperation with qwTimestamp_Frequency
fnTelemetry_Enable pEnable_Callback; //Callback to notify user when counter has been enables/disabled remotely
fnConnect pConnect_Callback; //Callback notifies user when connection with Baical is established/closed
} stTelemetry_Conf;
////////////////////////////////////////////////////////////////////////////////
//P7_Telemetry_Create - function create new instance of IP7_Telemetry object
//See documentation for details.
extern P7_EXPORT hP7_Telemetry __cdecl P7_Telemetry_Create(hP7_Client i_hClient,
const tXCHAR *i_pName,
const stTelemetry_Conf *i_pConf
);
//dll/so function prototype
typedef hP7_Telemetry (__cdecl *fnP7_Telemetry_Create)(hP7_Client i_hClient,
const tXCHAR *i_pName,
const stTelemetry_Conf *i_pConf
);
////////////////////////////////////////////////////////////////////////////////
//P7_Telemetry_Share - function to share current P7 telemetry object in address
//space of the current process, to get shared client use function
//P7_Telemetry_Get_Shared
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Telemetry_Share(hP7_Telemetry i_hTelemetry,
const tXCHAR *i_pName
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Telemetry_Share)(hP7_Telemetry i_hTelemetry,
const tXCHAR *i_pName
);
////////////////////////////////////////////////////////////////////////////////
//This functions allow you to get P7 telemetry instance if it was created by
//someone other inside current process. If no instance was registered inside
//current process - function will return NULL. Do not forget to call Release
//on interface when you finish your work
//See documentation for details.
extern P7_EXPORT hP7_Telemetry __cdecl P7_Telemetry_Get_Shared(const tXCHAR *i_pName);
//dll/so function prototype
typedef hP7_Telemetry (__cdecl *fnP7_Telemetry_Get_Shared)(const tXCHAR *i_pName);
////////////////////////////////////////////////////////////////////////////////
//P7_Telemetry_Create_Counter - create new telemetry counter, max amount of
//counters - 256, if you need more - we recommends you to create another telem.
//channel using P7_Telemetry_Create() function
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Telemetry_Create_Counter(hP7_Telemetry i_hTelemetry,
const tXCHAR *i_pName,
tDOUBLE i_dbMin,
tDOUBLE i_dbAlarmMin,
tDOUBLE i_dbMax,
tDOUBLE i_dbAlarmMax,
tBOOL i_bOn,
tUINT16 *o_pID
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Telemetry_Create_Counter)(hP7_Telemetry i_hTelemetry,
const tXCHAR *i_pName,
tDOUBLE i_dbMin,
tDOUBLE i_dbAlarmMin,
tDOUBLE i_dbMax,
tDOUBLE i_dbAlarmMax,
tBOOL i_bOn,
tUINT16 *o_pID
);
////////////////////////////////////////////////////////////////////////////////
//P7_Telemetry_Put_Value - add counter smaple value
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Telemetry_Put_Value(hP7_Telemetry i_hTelemetry,
tUINT16 i_wCounter_ID,
tDOUBLE i_dbValue
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Telemetry_Put_Value)(hP7_Telemetry i_hTelemetry,
tUINT16 i_wCounter_ID,
tDOUBLE i_dbValue
);
////////////////////////////////////////////////////////////////////////////
//P7_Telemetry_Find_Counter - find counter ID by name
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Telemetry_Find_Counter(hP7_Telemetry i_hTelemetry,
const tXCHAR *i_pName,
tUINT16 *o_pCounter_ID
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Telemetry_Find_Counter)(hP7_Telemetry i_hTelemetry,
const tXCHAR *i_pName,
tUINT16 *o_pCounter_ID
);
////////////////////////////////////////////////////////////////////////////////
//P7_Telemetry_Add_Ref - increase reference counter for the telemetry channel
//See documentation for details.
extern P7_EXPORT tINT32 __cdecl P7_Telemetry_Add_Ref(hP7_Telemetry i_hTelemetry);
//dll/so function prototype
typedef tINT32 (__cdecl *fnP7_Telemetry_Add_Ref)(hP7_Telemetry i_hTelemetry);
////////////////////////////////////////////////////////////////////////////////
//P7_Telemetry_Release - function releases the telemetry, reference counter
//technology is used, it mean the same client instance can be used from few
//program parts, and every instance has to be released to completely destroy the
//P7 telemetry object
//See documentation for details.
extern P7_EXPORT tINT32 __cdecl P7_Telemetry_Release(hP7_Telemetry i_hTelemetry);
//dll/so function prototype
typedef tINT32 (__cdecl *fnP7_Telemetry_Release)(hP7_Telemetry i_hTelemetry);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// //
// P7 Trace //
// //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
typedef void* hP7_Trace;
typedef void* hP7_Trace_Module;
////////////////////////////////////////////////////////////////////////////////
//Trace levels:
#define P7_TRACE_LEVEL_TRACE 0
#define P7_TRACE_LEVEL_DEBUG 1
#define P7_TRACE_LEVEL_INFO 2
#define P7_TRACE_LEVEL_WARNING 3
#define P7_TRACE_LEVEL_ERROR 4
#define P7_TRACE_LEVEL_CRITICAL 5
typedef void (__cdecl *fnTrace_Verbosity)(void *i_pContext,
hP7_Trace_Module i_hModule,
tUINT32 i_dwVerbosity);
typedef struct
{
void *pContext; //context to be passed back to callbacks
tUINT64 qwTimestamp_Frequency; //count ticks per second, works in cooperation with pTimestamp_Callback
fnGet_Time_Stamp pTimestamp_Callback; //callback for getting user timestamps, works in cooperation with qwTimestamp_Frequency
fnTrace_Verbosity pVerbosity_Callback; //Callback to notify user when verbosity has been changed
fnConnect pConnect_Callback; //Callback notifies user when connection with Baical is established/closed
} stTrace_Conf;
////////////////////////////////////////////////////////////////////////////////
//P7_TRACE_ADD macro for trace function calling simplification
#define P7_TRACE_ADD(i_hTrace,\
i_wID,\
i_eLevel,\
i_dwModuleID,\
i_pFormat,\
...)\
P7_Trace_Add(i_hTrace,\
i_wID,\
i_eLevel,\
i_dwModuleID,\
(tUINT16)__LINE__,\
__FILE__,\
__FUNCTION__,\
i_pFormat,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Create_Trace - function create new instance of IP7_Trace object
//See documentation for details.
extern P7_EXPORT hP7_Trace __cdecl P7_Trace_Create(hP7_Client i_hClient,
const tXCHAR *i_pName,
const stTrace_Conf *i_pConf
);
//dll/so function prototype
typedef hP7_Trace (__cdecl *fnP7_Trace_Create)(hP7_Client i_hClient,
const tXCHAR *i_pName,
const stTrace_Conf *i_pConf
);
////////////////////////////////////////////////////////////////////////////////
//This functions allow you to get P7 trace instance if it was created by someone
//other inside current process. If no instance was registered inside current
//process - function will return NULL. Do not forget to call Release
//on interface when you finish your work
//See documentation for details.
extern P7_EXPORT hP7_Trace __cdecl P7_Trace_Get_Shared(const tXCHAR *i_pName);
//dll/so function prototype
typedef hP7_Trace (__cdecl *fnP7_Trace_Get_Shared)(const tXCHAR *i_pName);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Share - function to share current P7 trace object in address space of
//the current process, to get shared trace channel use function
//P7_Trace_Get_Shared()
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Trace_Share(hP7_Trace i_hTrace,
const tXCHAR *i_pName
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Trace_Share)(hP7_Trace i_hTrace,
const tXCHAR *i_pName
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Set_Verbosity - function to set minimal trace verbosity, all traces
//with less priority will be rejected by channel. You may set verbosity online
//from Baical server
//See documentation for details.
extern P7_EXPORT void __cdecl P7_Trace_Set_Verbosity(hP7_Trace i_hTrace,
hP7_Trace_Module i_hModule,
tUINT32 i_dwVerbosity
);
//dll/so function prototype
typedef void (__cdecl *fnP7_Trace_Set_Verbosity)(hP7_Trace i_hTrace,
hP7_Trace_Module i_hModule,
tUINT32 i_dwVerbosity
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Get_Verbosity - function to get minimal trace verbosity
//See documentation for details.
extern P7_EXPORT tUINT32 __cdecl P7_Trace_Get_Verbosity(hP7_Trace i_hTrace,
hP7_Trace_Module i_hModule
);
//dll/so function prototype
typedef tUINT32 (__cdecl *fnP7_Trace_Get_Verbosity)(hP7_Trace i_hTrace,
hP7_Trace_Module i_hModule);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Register_Thread - function used to specify name for current/special
//thread.
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Trace_Register_Thread(hP7_Trace i_hTrace,
const tXCHAR *i_pName,
tUINT32 i_dwThreadId
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Trace_Register_Thread)(hP7_Trace i_hTrace,
const tXCHAR *i_pName,
tUINT32 i_dwThreadId
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Unregister_Thread - function used to unregister current/special thread.
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Trace_Unregister_Thread(hP7_Trace i_hTrace,
tUINT32 i_dwThreadId
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Trace_Unregister_Thread)(hP7_Trace i_hTrace,
tUINT32 i_dwThreadId
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Register_Module - function used to register module for following usage
//by P7_Trace_Add/P7_Trace_Embedded/P7_Trace_Managed functions
//See documentation for details.
extern P7_EXPORT hP7_Trace_Module __cdecl P7_Trace_Register_Module(hP7_Trace i_hTrace,
const tXCHAR *i_pName
);
//dll/so function prototype
typedef hP7_Trace_Module (__cdecl *fnP7_Trace_Register_Module)(hP7_Trace i_hTrace,
const tXCHAR *i_pName
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Add - send trace message to Baical server.
//You may use macro P7_TRACE_ADD to simplify calling of this function
////////////////////////////////////////////////////////////////////////////////
//N.B.: DO NOT USE VARIABLE for format string! You should always use CONSTANT
// TEXT like L"My Format %d, %s"
// USE THIS FUNCTION ONLY FROM C/C++ LANGUAGES! If you want to use trace
// functionality from other languages please call Trace_Managed() function
////////////////////////////////////////////////////////////////////////////////
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Trace_Add(hP7_Trace i_hTrace,
tUINT16 i_wTrace_ID,
tUINT32 i_dwLevel,
hP7_Trace_Module i_hModule,
tUINT16 i_wLine,
const char *i_pFile,
const char *i_pFunction,
const tXCHAR *i_pFormat,
...
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Trace_Add)(hP7_Trace i_hTrace,
tUINT16 i_wTrace_ID,
tUINT32 i_dwLevel,
hP7_Trace_Module i_hModule,
tUINT16 i_wLine,
const char *i_pFile,
const char *i_pFunction,
const tXCHAR *i_pFormat,
...
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Embedded - send trace message to Baical server.
//this function is a copy of P7_Trace_Add function, but it is dedicated for
//embedding into your log function with variable arguments list:
//Usage scenario: you already have function with variable arguments, but body of
//your function may be replaced by Trace_Embedded.
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Trace_Embedded(hP7_Trace i_hTrace,
tUINT16 i_wTrace_ID,
tUINT32 i_dwLevel,
hP7_Trace_Module i_hModule,
tUINT16 i_wLine,
const char *i_pFile,
const char *i_pFunction,
const tXCHAR **i_ppFormat,
va_list *i_pVa_List
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Trace_Embedded)(hP7_Trace i_hTrace,
tUINT16 i_wTrace_ID,
tUINT32 i_dwLevel,
hP7_Trace_Module i_hModule,
tUINT16 i_wLine,
const char *i_pFile,
const char *i_pFunction,
const tXCHAR **i_ppFormat,
va_list *i_pVa_List
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Managed - send trace message to Baical server.
//This function is intended for use by MANAGED languages like C#, Python, etc
//It is slightly slower than P7_Trace_Add.
//See documentation for details.
extern P7_EXPORT tBOOL __cdecl P7_Trace_Managed(hP7_Trace i_hTrace,
tUINT16 i_wTrace_ID,
tUINT32 i_dwLevel,
hP7_Trace_Module i_hModule,
tUINT16 i_wLine,
const tXCHAR *i_pFile,
const tXCHAR *i_pFunction,
const tXCHAR *i_pMessage
);
//dll/so function prototype
typedef tBOOL (__cdecl *fnP7_Trace_Managed)(hP7_Trace i_hTrace,
tUINT16 i_wTrace_ID,
tUINT32 i_dwLevel,
hP7_Trace_Module i_hModule,
tUINT16 i_wLine,
const tXCHAR *i_pFile,
const tXCHAR *i_pFunction,
const tXCHAR *i_pMessage
);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Add_Ref - increase reference counter for the telemetry channel
//See documentation for details.
extern P7_EXPORT tINT32 __cdecl P7_Trace_Add_Ref(hP7_Trace i_hTrace);
//dll/so function prototype
typedef tINT32 (__cdecl *fnP7_Trace_Add_Ref)(hP7_Trace i_hTrace);
////////////////////////////////////////////////////////////////////////////////
//P7_Trace_Release - function releases the trace object, reference counter
//technology is used, it mean the same trace instance can be used from few
//program parts, and every instance has to be released to completely destroy the
//P7 trace object
//See documentation for details.
extern P7_EXPORT tINT32 __cdecl P7_Trace_Release(hP7_Trace i_hTrace);
//dll/so function prototype
typedef tINT32 (__cdecl *fnP7_Trace_Release)(hP7_Trace i_hTrace);
#ifdef __cplusplus
}
#endif
#endif //P7_PROXY_H

View File

@ -0,0 +1,490 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// P7 extensions - interfaces to some additional functionality /
// - IP7_Trace : traces formatting and delivery to Baical server /
////////////////////////////////////////////////////////////////////////////////
#ifndef P7_EXTENSIONS_H
#define P7_EXTENSIONS_H
#define P7_EXTENSION_TYPE_BITS_COUNT (5)
#define P7_EXTENSION_SUB_TYPE_BITS_COUNT (5)
#define P7_EXTENSION_PACKET_SIZE_BITS_COUNT (22)
#define P7_EXTENSION_MAX_TYPES (1 << P7_EXTENSION_TYPE_BITS_COUNT)
#define P7TRACE_NAME_LENGTH (64)
#define P7TRACE_THREAD_NAME_LENGTH (48)
#define P7TRACE_MODULE_NAME_LENGTH (54)
#define P7TELEMETRY_NAME_LENGTH (64)
#define P7TELEMETRY_COUNTER_NAME_LENGTH_V1 (64)
#define P7TELEMETRY_COUNTERS_MAX_COUNT_V1 ((tUINT8)~((tUINT8)0))
#define P7TELEMETRY_INVALID_ID_V1 (P7TELEMETRY_COUNTERS_MAX_COUNT_V1 - 1)
#define P7TELEMETRY_INVALID_ID_V2 ((tUINT16)~((tUINT16)0))
#define P7TELEMETRY_COUNTERS_MAX_COUNT_V2 ((tUINT16)~((tUINT16)0))
#define P7TELEMETRY_COUNTER_NAME_MIN_LENGTH_V2 (2)
#define P7TRACE_INFO_FLAG_BIG_ENDIAN (0x0001)
#define P7TRACE_INFO_FLAG_UNSORTED (0x0002)
#define P7TRACE_INFO_FLAG_EXTENTION (0x0004)
#define P7TRACE_INFO_FLAG_TIME_ZONE (0x0008)
#define P7TELEMETRY_FLAG_EXTENTION (0x0001)
#define P7TELEMETRY_FLAG_TIME_ZONE (0x0002)
enum eTrace_Arg_Type
{
P7TRACE_ARG_TYPE_UNK = 0x00,
P7TRACE_ARG_TYPE_CHAR = 0x01,
P7TRACE_ARG_TYPE_INT8 = 0x01,
P7TRACE_ARG_TYPE_CHAR16 ,//(0x02)
P7TRACE_ARG_TYPE_INT16 ,//(0x03)
P7TRACE_ARG_TYPE_INT32 ,//(0x04)
P7TRACE_ARG_TYPE_INT64 ,//(0x05)
P7TRACE_ARG_TYPE_DOUBLE ,//(0x06)
P7TRACE_ARG_TYPE_PVOID ,//(0x07)
P7TRACE_ARG_TYPE_USTR16 ,//(0x08) //unicode - UTF16 string
P7TRACE_ARG_TYPE_STRA ,//(0x09) //ASCII string
P7TRACE_ARG_TYPE_USTR8 ,//(0x0A) //unicode - UTF8 string
P7TRACE_ARG_TYPE_USTR32 ,//(0x0B) //unicode - UTF32 string
P7TRACE_ARG_TYPE_CHAR32 ,//(0x0C)
P7TRACE_ARG_TYPE_INTMAX ,//(0x0D)
P7TRACE_ARGS_COUNT
};
#if defined(GTX64)
#define SIZE_OF_ARG(t) ( (sizeof(t) + 8 - 1) & ~(8 - 1) )
typedef tUINT64 tKeyType;
#else
#define SIZE_OF_ARG(t) ( (sizeof(t) + 4 - 1) & ~(4 - 1) )
typedef tUINT32 tKeyType;
#endif
////////////////////////////////////////////////////////////////////////////////
// Data types, we can transmit different packets types, here are the list
// of all supported for the moment packet types
enum eP7User_Type
{
EP7USER_TYPE_TRACE = 0,
EP7USER_TYPE_TELEMETRY_V1 ,
EP7USER_TYPE_TELEMETRY_V2 ,
EP7USER_TYPE_MAX = P7_EXTENSION_MAX_TYPES
};
////////////////////////////////////////////////////////////////////////////////
enum eP7Trace_Type
{
EP7TRACE_TYPE_INFO = 0, //Client->Server
EP7TRACE_TYPE_DESC , //Client->Server
EP7TRACE_TYPE_DATA , //Client->Server
EP7TRACE_TYPE_VERB , //Client->Server->Client
EP7TRACE_TYPE_CLOSE , //Client->Server
EP7TRACE_TYPE_THREAD_START , //Client->Server
EP7TRACE_TYPE_THREAD_STOP , //Client->Server
EP7TRACE_TYPE_MODULE , //Client->Server
EP7TRACE_TYPE_DELETE , //Server->Client
EP7TRACE_TYPE_UTC_OFFS , //Client->Server
EP7TRACE_TYPE_MAX = 32
};
////////////////////////////////////////////////////////////////////////////////
enum eP7Trace_Ext
{
EP7TRACE_EXT_MODULE_ID = 0,
EP7TRACE_EXT_MAX = 256
};
////////////////////////////////////////////////////////////////////////////////
enum eP7Tel_Type
{
EP7TEL_TYPE_INFO = 0, //Client->Server
EP7TEL_TYPE_COUNTER , //Client->Server
EP7TEL_TYPE_VALUE , //Client->Server
EP7TEL_TYPE_ENABLE , //Server->Client
EP7TEL_TYPE_CLOSE , //Client->Server
EP7TEL_TYPE_DELETE , //Server->Client
EP7TEL_TYPE_UTC_OFFS , //Client->Server
EP7TEL_TYPE_MAX = 32
};
PRAGMA_PACK_ENTER(4) //alignment is now 4, MS Only//////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// common user header for extensions (like trace or telemetry)
#define INIT_EXT_HEADER(iHeaderRaw, iType, iSubType, iSize)\
iHeaderRaw.dwBits = \
(((iType) & ((1 << P7_EXTENSION_TYPE_BITS_COUNT) - 1)) |\
(((iSubType) & ((1 << P7_EXTENSION_SUB_TYPE_BITS_COUNT) - 1)) << P7_EXTENSION_TYPE_BITS_COUNT) |\
(((iSize) & ((1 << P7_EXTENSION_PACKET_SIZE_BITS_COUNT) - 1)) << (P7_EXTENSION_TYPE_BITS_COUNT + P7_EXTENSION_SUB_TYPE_BITS_COUNT)))
#define GET_EXT_HEADER_SIZE(iHeaderRaw)\
(iHeaderRaw.dwBits >> (P7_EXTENSION_TYPE_BITS_COUNT + P7_EXTENSION_SUB_TYPE_BITS_COUNT))
#define GET_EXT_HEADER_TYPE(iHeaderRaw)\
(iHeaderRaw.dwBits & ((1 << P7_EXTENSION_TYPE_BITS_COUNT) - 1))
#define GET_EXT_HEADER_SUBTYPE(iHeaderRaw)\
((iHeaderRaw.dwBits >> P7_EXTENSION_TYPE_BITS_COUNT) & ((1 << P7_EXTENSION_SUB_TYPE_BITS_COUNT) - 1))
#define SET_EXT_HEADER_SIZE(iHeaderRaw, iSize)\
iHeaderRaw.dwBits = \
(iHeaderRaw.dwBits & ((1 << (P7_EXTENSION_TYPE_BITS_COUNT + P7_EXTENSION_SUB_TYPE_BITS_COUNT)) - 1)) |\
(((iSize) & ((1 << P7_EXTENSION_PACKET_SIZE_BITS_COUNT) - 1)) << (P7_EXTENSION_TYPE_BITS_COUNT + P7_EXTENSION_SUB_TYPE_BITS_COUNT))
struct sP7Ext_Header
{
tUINT32 dwType :P7_EXTENSION_TYPE_BITS_COUNT; //eP7User_Type
tUINT32 dwSubType:P7_EXTENSION_SUB_TYPE_BITS_COUNT;
//max 4 mb, value should include size of this header
tUINT32 dwSize :P7_EXTENSION_PACKET_SIZE_BITS_COUNT;
//At the end of structure we put serialized data
} ATTR_PACK(4);
struct sP7Ext_Raw //mapping of sP7Ext_Header
{
tUINT32 dwBits;
} ATTR_PACK(4);
GASSERT(sizeof(sP7Ext_Header) == sizeof(sP7Ext_Raw));
//N.B.: extension packets can follow one by one in data packets.
PRAGMA_PACK_EXIT()//4///////////////////////////////////////////////////////////
PRAGMA_PACK_ENTER(2) //alignment is now 2, MS Only//////////////////////////////
#define P7_DAMP_FILE_MARKER_V1 (0x45D2AC71ECF32CA6ULL)
#define P7_DAMP_FILE_HOST_LENGTH (256)
#define P7_DAMP_FILE_PROCESS_LENGTH (256)
//P7 damp file header
struct sP7File_Header
{
tUINT64 qwMarker;
tUINT32 dwProcess_ID;
tUINT32 dwProcess_Start_Time_Hi;
tUINT32 dwProcess_Start_Time_Lo;
tWCHAR pProcess_Name[P7_DAMP_FILE_PROCESS_LENGTH];
tWCHAR pHost_Name[P7_DAMP_FILE_HOST_LENGTH];
} ATTR_PACK(2);
////////////////////////////////////////////////////////////////////////////////
// Trace //
////////////////////////////////////////////////////////////////////////////////
//trace info header
struct sP7Trace_Info
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
//Contains a 64-bit value representing the number of 100-nanosecond intervals
//since January 1, 1601 (UTC). In windows we use FILETIME structure for
//representing
tUINT32 dwTime_Hi;
tUINT32 dwTime_Lo;
//Hi resolution timer value, we get this value when we retrieve current time.
//using difference between this value and timer value for every trace we can
//calculate time of the trace event with hi resolution
tUINT64 qwTimer_Value;
//timer's count heartbeats in second
tUINT64 qwTimer_Frequency;
tUINT64 qwFlags;
tWCHAR pName[P7TRACE_NAME_LENGTH];
} ATTR_PACK(2);
//this structure describe each argument inside variable arguments list
//all arguments are serialized data block
struct sP7Trace_Arg
{
//argument's type - one of P7TRACE_ARG_TYPE_XXX
tUINT8 bType;
//Size - how many bytes is used by argument inside block, this value is not
// directly depend on type, usually it depend on processor architecture
// for example "char" on WIN32 this is 4 bytes, but for EventTrace
// engine this is only 1 byte.
// N.B.: All strings has 0 size.
tUINT8 bSize;
} ATTR_PACK(2);
//trace description header
struct sP7Trace_Format
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT16 wID;
tUINT16 wLine;
tUINT16 wModuleID; //Module ID, who send trace
tUINT16 wArgs_Len; //arguments count
//At the end of structure we put serialized data:
//sP7Trace_Arg [dwArgs_Len] - array of arguments
//wchar_t Format[] - null terminated string
//char FileName[] - null terminated string
//char FunctionName[] - null terminated string
} ATTR_PACK(2);
//trace data header
struct sP7Trace_Data
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT16 wID; //trace ID
tUINT8 bLevel; //eP7Trace_Level
tUINT8 bProcessor; //Processor number
tUINT32 dwThreadID; //Thread ID
tUINT32 dwSequence; //sequence number
tUINT64 qwTimer; //High resolution timer value
//At the end of structure we put serialized data:
// - trace variable arguments values
// - extensions [data X bits][type 8 bits], [data X bits][type 8 bits], ... [count 8 bits]
} ATTR_PACK(2);
//trace ext header for Module ID
struct sP7Trace_Ext_Mid
{
tUINT16 wMID;
} ATTR_PACK(2);
//trace verbosity header
struct sP7Trace_Verb
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
eP7Trace_Level eVerbosity;
tUINT16 wModuleID;
} ATTR_PACK(2);
//Thread start info
struct sP7Trace_Thread_Start
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT32 dwThreadID; //Thread ID
tUINT64 qwTimer; //High resolution timer value
char pName[P7TRACE_THREAD_NAME_LENGTH]; //Thread name (UTF-8)
} ATTR_PACK(2);
//Thread stop info
struct sP7Trace_Thread_Stop
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT32 dwThreadID; //Thread ID
tUINT64 qwTimer; //High resolution timer value
} ATTR_PACK(2);
//Module info
struct sP7Trace_Module
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT16 wModuleID;
eP7Trace_Level eVerbosity;
char pName[P7TRACE_MODULE_NAME_LENGTH]; //name (UTF-8)
} ATTR_PACK(2);
//Time zone description
struct sP7Trace_Utc_Offs
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tINT32 iUtcOffsetSec;
} ATTR_PACK(2);
////////////////////////////////////////////////////////////////////////////////
// Telemetry //
////////////////////////////////////////////////////////////////////////////////
//telemetry info header
struct sP7Tel_Info
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
//Contains a 64-bit value representing the number of 100-nanosecond intervals
//since January 1, 1601 (UTC). In windows we use FILETIME structure for
//representing
tUINT32 dwTime_Hi;
tUINT32 dwTime_Lo;
//Hi resolution timer value, we get this value when we retrieve current time.
//using difference between this value and timer value for every trace we can
//calculate time of the trace event with hi resolution
tUINT64 qwTimer_Value;
//timer's count heartbeats in second
tUINT64 qwTimer_Frequency;
tUINT64 qwFlags;
tWCHAR pName[P7TELEMETRY_NAME_LENGTH];
} ATTR_PACK(2);
//Telemetry counter description
struct sP7Tel_Counter_v1
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT8 bID;
tUINT8 bOn;
tINT64 llMin;
tINT64 llMax;
tINT64 llAlarm;
tWCHAR pName[P7TELEMETRY_COUNTER_NAME_LENGTH_V1];
} ATTR_PACK(2);
//Telemetry counter description
struct sP7Tel_Counter_v2
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT16 wID;
tUINT16 bOn;
tDOUBLE dbMin;
tDOUBLE dbAlarmMin;
tDOUBLE dbMax;
tDOUBLE dbAlarmMax;
tWCHAR pName[P7TELEMETRY_COUNTER_NAME_MIN_LENGTH_V2];
} ATTR_PACK(2);
//telemetry counter On/Off verbosity header
struct sP7Tel_Enable_v1
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT8 bID;
tUINT8 bOn;
} ATTR_PACK(2);
//telemetry counter On/Off verbosity header
struct sP7Tel_Enable_v2
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT16 wID;
tUINT16 bOn;
} ATTR_PACK(2);
//Telemetry counter value
struct sP7Tel_Value_v1
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT8 bID;
tUINT8 bSeqN;
tUINT64 qwTimer; //High resolution timer value
tINT64 llValue;
} ATTR_PACK(2);
//Telemetry counter value
struct sP7Tel_Value_v2
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tUINT16 wID;
tUINT16 wSeqN;
tUINT64 qwTimer; //High resolution timer value
tDOUBLE dbValue;
} ATTR_PACK(2);
//Time zone description
struct sP7Tel_Utc_Offs_V2
{
union
{
sP7Ext_Header sCommon;
sP7Ext_Raw sCommonRaw;
};
tINT32 iUtcOffsetSec;
} ATTR_PACK(2);
PRAGMA_PACK_EXIT()//2///////////////////////////////////////////////////////////
#endif //P7_EXTENSIONS_H

View File

@ -0,0 +1,118 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// //
// P7.Telemetry //
// //
////////////////////////////////////////////////////////////////////////////////
// //
// Documentation is located in <P7>/Documentation/P7.pdf //
// //
////////////////////////////////////////////////////////////////////////////////
#ifndef P7_TELEMETRY_H
#define P7_TELEMETRY_H
#include "P7_Client.h"
#include "P7_Cproxy.h"
#define TELEMETRY_DEFAULT_SHARED_NAME TM("P7.Telemetry")
////////////////////////////////////////////////////////////////////////////////
///////////////////////////IP7_Telemetry////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class IP7_Telemetry
: public IP7C_Channel
{
public:
////////////////////////////////////////////////////////////////////////////
//Create - creates new telemetry counter, max amount of counters per
// telemetry instance - 256
// See documentation for details.
virtual tBOOL Create(const tXCHAR *i_pName,
tDOUBLE i_dbMin,
tDOUBLE i_dbAlarmMin,
tDOUBLE i_dbMax,
tDOUBLE i_dbAlarmMax,
tBOOL i_bOn,
tUINT16 *o_pID
) = 0;
////////////////////////////////////////////////////////////////////////////
//Add - add counter sample
// See documentation for details.
virtual tBOOL Add(tUINT16 i_bID, tDOUBLE i_llValue) = 0;
////////////////////////////////////////////////////////////////////////////
//Find - find counter ID by name (case sensitive)
// See documentation for details.
virtual tBOOL Find(const tXCHAR *i_pName, tUINT16 *o_pID) = 0;
////////////////////////////////////////////////////////////////////////////
//Set_Enable - enable or disable counter
virtual tBOOL Set_Enable(tUINT16 i_wID, tBOOL i_bEnable) = 0;
////////////////////////////////////////////////////////////////////////////
//Get_Enable - get enable flag
virtual tBOOL Get_Enable(tUINT16 i_wID) = 0;
////////////////////////////////////////////////////////////////////////////
//Get_Min - get min value
virtual tDOUBLE Get_Min(tUINT16 i_wID) = 0;
////////////////////////////////////////////////////////////////////////////
//Get_Max - get max value
virtual tDOUBLE Get_Max(tUINT16 i_wID) = 0;
////////////////////////////////////////////////////////////////////////////
//Get_Name - get name
virtual const tXCHAR *Get_Name(tUINT16 i_wID) = 0;
////////////////////////////////////////////////////////////////////////////
//Get_Count - get amount of counters
virtual tUINT16 Get_Count() = 0;
////////////////////////////////////////////////////////////////////////////
//Share - function to share current P7.Telemetry object in address space of
// the current process, to get shared instance use function
// P7_Get_Shared_Telemetry(tXCHAR *i_pName)
// See documentation for details.
virtual tBOOL Share(const tXCHAR *i_pName) = 0;
};
////////////////////////////////////////////////////////////////////////////////
//P7_Create_Telemetry - function creates new instance of IP7_Telemetry object
// See documentation for details.
extern "C" P7_EXPORT IP7_Telemetry* __cdecl P7_Create_Telemetry(IP7_Client *i_pClient,
const tXCHAR *i_pName,
const stTelemetry_Conf *i_pConf = NULL
);
////////////////////////////////////////////////////////////////////////////////
//This functions allows you to get P7 telemetry instance if it was created by
//someone else inside current process. If no instance was registered inside
//current process - function will return NULL. Do not forget to call Release on
//interface when you finish your work
//See documentation for details.
extern "C" P7_EXPORT IP7_Telemetry* __cdecl P7_Get_Shared_Telemetry(const tXCHAR *i_pName);
#endif //P7_TELEMETRY_H

281
p7lib/Headers/P7_Trace.h Normal file
View File

@ -0,0 +1,281 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// //
// P7.Tace //
// //
////////////////////////////////////////////////////////////////////////////////
// //
// Documentation is located in <P7>/Documentation/P7.pdf //
// //
////////////////////////////////////////////////////////////////////////////////
#ifndef P7_TRACE_H
#define P7_TRACE_H
#include "P7_Client.h"
#include "P7_Cproxy.h"
#include <stdarg.h>
#define TRACE_DEFAULT_SHARED_NAME TM("P7.Trace")
////////////////////////////////////////////////////////////////////////////////
//P7.Trace uses optimization to read variable arguments directly from the stack/
//but some systems optimizes storing of var.args and uses processor resistors/
//stack re-ordering, extra-padding and other techniques, so if you detect than /
//library print wrong values - please activate this macro manually for your /
//platform/project /
////////////////////////////////////////////////////////////////////////////////
//#define P7TRACE_NO_VA_ARG_OPTIMIZATION
//disable va_arg optimization for Linux, too many ways how GCC + Linux uses
//stack and registers to store va_arg
#if defined(__linux__)
#define P7TRACE_NO_VA_ARG_OPTIMIZATION
#endif
////////////////////////////////////////////////////////////////////////////////
//in some platforms access to 64 not aligned variable is illegal, if it the/
//case please active the macro /
////////////////////////////////////////////////////////////////////////////////
//#define P7TRACE_64BITS_ALIGNED_ACCESS
////////////////////////////////////////////////////////////////////////////////
enum eP7Trace_Level
{
EP7TRACE_LEVEL_TRACE = 0,
EP7TRACE_LEVEL_DEBUG ,
EP7TRACE_LEVEL_INFO ,
EP7TRACE_LEVEL_WARNING ,
EP7TRACE_LEVEL_ERROR ,
EP7TRACE_LEVEL_CRITICAL ,
EP7TRACE_LEVEL_COUNT
};
////////////////////////////////////////////////////////////////////////////////
#define P7_DELIVER(i_wID, i_eLevel, i_hModule, ...) Trace(i_wID,\
i_eLevel,\
i_hModule,\
(tUINT16)__LINE__,\
__FILE__,\
__FUNCTION__,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
#define P7_QTRACE(i_wID, i_hModule, ...) P7_DELIVER(i_wID,\
EP7TRACE_LEVEL_TRACE,\
i_hModule,\
__VA_ARGS__)
#define P7_TRACE(i_hModule, ...) P7_QTRACE(0,\
i_hModule,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
#define P7_QDEBUG(i_wID, i_hModule, ...) P7_DELIVER(i_wID,\
EP7TRACE_LEVEL_DEBUG,\
i_hModule,\
__VA_ARGS__)
#define P7_DEBUG(i_hModule, ...) P7_QDEBUG(0,\
i_hModule,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
#define P7_QINFO(i_wID, i_hModule, ...) P7_DELIVER(i_wID,\
EP7TRACE_LEVEL_INFO,\
i_hModule,\
__VA_ARGS__)
#define P7_INFO(i_hModule, ...) P7_QINFO(0,\
i_hModule,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
#define P7_QWARNING(i_wID, i_hModule, ...) P7_DELIVER(i_wID,\
EP7TRACE_LEVEL_WARNING,\
i_hModule,\
__VA_ARGS__)
#define P7_WARNING(i_hModule, ...) P7_QWARNING(0,\
i_hModule,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
#define P7_QERROR(i_wID, i_hModule, ...) P7_DELIVER(i_wID,\
EP7TRACE_LEVEL_ERROR,\
i_hModule,\
__VA_ARGS__)
#define P7_ERROR(i_hModule, ...) P7_QERROR(0,\
i_hModule,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
#define P7_QCRITICAL(i_wID, i_hModule, ...) P7_DELIVER(i_wID,\
EP7TRACE_LEVEL_CRITICAL,\
i_hModule,\
__VA_ARGS__)
#define P7_CRITICAL(i_hModule, ...) P7_QCRITICAL(0,\
i_hModule,\
__VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
#define LOG(logger, level, format, ...) logger->P7_DELIVER(0, EP7TRACE_LEVEL_##level, NULL, TM(format), __VA_ARGS__)
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////IP7_Trace//////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class IP7_Trace
: public IP7C_Channel
{
public:
typedef void* hModule;
////////////////////////////////////////////////////////////////////////////
//Set_Verbosity - function to set trace verbosity, traces with less priority
// will be rejected. You may set verbosity online from Baical
// server. See documentation for details.
virtual void Set_Verbosity(IP7_Trace::hModule i_hModule,
eP7Trace_Level i_eVerbosity
) = 0;
////////////////////////////////////////////////////////////////////////////
//Get_Verbosity - function to get trace verbosity.
// See documentation for details.
virtual eP7Trace_Level Get_Verbosity(IP7_Trace::hModule i_hModule) = 0;
////////////////////////////////////////////////////////////////////////////
//Register_Thread - function used to specify name for current thread. Allows
// you to have nice trace message formatting on Baical side
// and in addition to ThreadId get Thread Name.
// Call the function from the newly created thread & call
// Unregister_Thread() right before exiting from thread
// body function.
//N.B.: If internally your application creates & destroys thousands of
// threads - usage of this functions is not good choice due to server
// overhead to store & manage this information - all threads info will
// be stored in RAM and may consume CPU to organize them in RB tree.
virtual tBOOL Register_Thread(const tXCHAR *i_pName,
tUINT32 i_dwThreadId
) = 0;
virtual tBOOL Unregister_Thread(tUINT32 i_dwThreadId) = 0;
////////////////////////////////////////////////////////////////////////////
//Register_Module - function is used register application module for using
// it by trace messages, if module with such name is
// already registered - existing handle will be returned
virtual tBOOL Register_Module(const tXCHAR *i_pName,
IP7_Trace::hModule *o_hModule
) = 0;
////////////////////////////////////////////////////////////////////////////
//Share - function to share current P7.Trace object in address space of the
// current process, to get shared instance use function
// P7_Get_Shared_Trace(tXCHAR *i_pName).
// See documentation for details.
virtual tBOOL Share(const tXCHAR *i_pName) = 0;
////////////////////////////////////////////////////////////////////////////
//Trace - send trace message to Baical server. See documentation for details
//N.B.: USE THIS FUNCTION ONLY FROM C/C++ LANGUAGES ! if you want to use
// trace functionality from other languages please call Trace_Managed()
virtual tBOOL Trace(tUINT16 i_wTrace_ID,
eP7Trace_Level i_eLevel,
IP7_Trace::hModule i_hModule,
tUINT16 i_wLine,
const char *i_pFile,
const char *i_pFunction,
const tXCHAR *i_pFormat,
...
) = 0;
////////////////////////////////////////////////////////////////////////////
//N.B: FUNCTION IS OBSOLETE, //
// Please use instead function Trace_Embedded(..., va_list*) //
////////////////////////////////////////////////////////////////////////////
//Trace_Embedded - send trace message
//this function is a copy of Trace function, but it is dedicated to embedded
//usage (you already have function with variable arguments, but body of your
//function may be replaced by Trace_Embedded).
//See documentation for details.
virtual tBOOL Trace_Embedded(tUINT16 i_wTrace_ID,
eP7Trace_Level i_eLevel,
IP7_Trace::hModule i_hModule,
tUINT16 i_wLine,
const char *i_pFile,
const char *i_pFunction,
const tXCHAR **i_ppFormat
) = 0;
////////////////////////////////////////////////////////////////////////////
//Trace_Embedded - send trace message
//this function is a copy of Trace function, but it is dedicated to embedded
//usage (you already have function with variable arguments, but body of your
//function may be replaced by Trace_Embedded).
//See documentation for details.
virtual tBOOL Trace_Embedded(tUINT16 i_wTrace_ID,
eP7Trace_Level i_eLevel,
IP7_Trace::hModule i_hModule,
tUINT16 i_wLine,
const char *i_pFile,
const char *i_pFunction,
const tXCHAR **i_ppFormat,
va_list *i_pVa_List
) = 0;
////////////////////////////////////////////////////////////////////////////
//Trace_Managed - send trace message
//this function is intended for use by MANAGED languages like C#,python, etc
//See documentation for details.
virtual tBOOL Trace_Managed(tUINT16 i_wTrace_ID,
eP7Trace_Level i_eLevel,
IP7_Trace::hModule i_hModule,
tUINT16 i_wLine,
const tXCHAR *i_pFile,
const tXCHAR *i_pFunction,
const tXCHAR *i_pMessage
) = 0;
};
////////////////////////////////////////////////////////////////////////////////
//P7_Create_Trace - function create new instance of IP7_Trace object
//See documentation for details.
extern "C" P7_EXPORT IP7_Trace * __cdecl P7_Create_Trace(IP7_Client *i_pClient,
const tXCHAR *i_pName,
const stTrace_Conf *i_pConf = 0
);
////////////////////////////////////////////////////////////////////////////////
//This functions allow you to get P7 trace instance if it was created by
//someone other inside current process. If no instance was registered inside
//current process - function will return NULL. Do not forget to call Release
//on interface when you finish your work.
//See documentation for details.
extern "C" P7_EXPORT IP7_Trace * __cdecl P7_Get_Shared_Trace(const tXCHAR *i_pName);
#endif //P7_TRACE_H

View File

@ -0,0 +1,26 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef P7_VERSION_H
#define P7_VERSION_H
//-----------------------------------------
#define P7_VERSION 00050006
#define P7_VERSION_MAJOR 5
#define P7_VERSION_MINOR 6
//-----------------------------------------
#endif //P7_VERSION_H

57
p7lib/License.txt Normal file
View File

@ -0,0 +1,57 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License.
“The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.
An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.
A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”.
The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.
The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:
a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:
a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.
e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.

826
p7lib/Shared/AList.h Normal file
View File

@ -0,0 +1,826 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
//******************************************************************************
// This header file contains simple template lists *
// 1. List with customizable memory manager (CListBase) *
// 2. List with pooling of internal elements (CListPool) *
//******************************************************************************
#ifndef ALIST_H
#define ALIST_H
typedef void *pAList_Cell;
////////////////////////////////////////////////////////////////////////////////
//CListBase
template <typename tData_Type>
class CListBase
{
protected:
struct tCell
{
tData_Type m_pData;
tCell *m_pNext;
tCell *m_pPrev;
};
typedef tCell* pIndex_Cell;
tCell *m_pFirst;
tCell *m_pLast;
tUINT32 m_dwCount;
//HANDLE m_hLock_Mutex;
pIndex_Cell *m_pIndex;
tBOOL m_bBrokenIndex;
tUINT32 m_dwIndexCount;
tBOOL m_bInitialized;
public:
////////////////////////////////////////////////////////////////////////////
//CListBase::CListBase
CListBase()
{
m_bInitialized = TRUE;
m_pFirst = NULL;
m_pLast = NULL;
m_dwCount = 0;
m_pIndex = NULL;
m_bBrokenIndex = TRUE;
m_dwIndexCount = 0;
//m_hLock_Mutex = CreateMutex(NULL, FALSE, NULL);
//if (NULL == m_hLock_Mutex)
//{
// m_bInitialized = FALSE;
//}
}//CListBase::AList
////////////////////////////////////////////////////////////////////////////
//CListBase::~CListBase
virtual ~CListBase()
{
Index_Release();
//if (m_hLock_Mutex)
//{
// CloseHandle(m_hLock_Mutex);
// m_hLock_Mutex = NULL;
//}
if (m_dwCount)
{
#ifdef _DEBUG
#if defined(_WIN32) || defined(_WIN64)
OutputDebugStringW(L"Warning: List is not empty\n");
#endif
#endif
}
}//CListBase::~CListBase
////////////////////////////////////////////////////////////////////////////
//CListBase::Get_Initialized
inline tBOOL Get_Initialized()
{
return m_bInitialized;
}//CListBase::Get_Initialized
////////////////////////////////////////////////////////////////////////////
//CListBase::Del
inline tBOOL Del(pAList_Cell i_pCell, tBOOL i_bFree_Data)
{
tCell *l_pCell = static_cast<tCell*>(i_pCell);
tBOOL l_bResult = TRUE;
if (l_pCell)
{
l_bResult = Cell_Release(l_pCell, TRUE, i_bFree_Data);
}
return l_bResult;
}//CListBase::Del
////////////////////////////////////////////////////////////////////////////
//CListBase::Extract
inline tBOOL Extract(pAList_Cell i_pCell)
{
tCell *l_pCell = static_cast<tCell*>(i_pCell);
tBOOL l_bResult = TRUE;
if (l_pCell)
{
l_bResult = Cell_Release(l_pCell, FALSE, FALSE);
l_pCell->m_pNext = NULL;
l_pCell->m_pPrev = NULL;
}
return l_bResult;
}//CListBase::Extract
////////////////////////////////////////////////////////////////////////////
//CListBase::Pull_First
inline tData_Type Pull_First()
{
tData_Type l_pReturn = m_pFirst->m_pData;
Cell_Release(m_pFirst, TRUE, FALSE);
return l_pReturn;
}
////////////////////////////////////////////////////////////////////////////
//CListBase::Pull_Last
inline tData_Type Pull_Last()
{
tData_Type l_pReturn = m_pLast->m_pData;
Cell_Release(m_pLast, TRUE, FALSE);
return l_pReturn;
}
////////////////////////////////////////////////////////////////////////////
//CListBase::Push_First
inline pAList_Cell Push_First(tData_Type i_pData)
{
return Add_After(NULL, i_pData);
}
////////////////////////////////////////////////////////////////////////////
//CListBase::Push_Last
inline pAList_Cell Push_Last(tData_Type i_pData)
{
return Add_After(m_pLast, i_pData);
}
////////////////////////////////////////////////////////////////////////////
//CListBase::Add_After
inline pAList_Cell Add_After(pAList_Cell i_pCell, tData_Type i_pData)
{
tCell *l_pNew_Cell = NULL;
tCell *l_pList_Cell = static_cast<tCell *>(i_pCell);
l_pNew_Cell = Cell_Allocate();
if (l_pNew_Cell)
{
memset(l_pNew_Cell, 0, sizeof(tCell));
l_pNew_Cell->m_pData = i_pData;
l_pNew_Cell->m_pNext = NULL;
l_pNew_Cell->m_pPrev = NULL;
Put_After(l_pList_Cell, l_pNew_Cell);
}
return static_cast<pAList_Cell>(l_pNew_Cell);
}//CListBase::Add_After
////////////////////////////////////////////////////////////////////////////
//CListBase::Put_After
inline tBOOL Put_After(pAList_Cell i_pList_Cell, pAList_Cell i_pExt_Cell)
{
tCell *l_pList_Cell = static_cast<tCell*>(i_pList_Cell);
tCell *l_pExt_Cell = static_cast<tCell*>(i_pExt_Cell);
tBOOL l_bResult = TRUE;
if (NULL == l_pExt_Cell)
{
return FALSE;
}
m_dwCount++;
if (l_pList_Cell)
{
l_pExt_Cell->m_pNext = l_pList_Cell->m_pNext;
l_pExt_Cell->m_pPrev = l_pList_Cell;
if (l_pList_Cell->m_pNext)
{
l_pList_Cell->m_pNext->m_pPrev = l_pExt_Cell;
}
l_pList_Cell->m_pNext = l_pExt_Cell;
}
if ((NULL == l_pList_Cell) && (m_pFirst))
{
m_pFirst->m_pPrev = l_pExt_Cell;
l_pExt_Cell->m_pNext = m_pFirst;
m_pFirst = l_pExt_Cell;
}
if ((m_pLast) && (m_pLast == l_pList_Cell))
{
m_pLast = l_pExt_Cell;
}
if (!m_pFirst)
{
m_pFirst = l_pExt_Cell;
m_pLast = l_pExt_Cell;
}
m_bBrokenIndex = TRUE;
return l_bResult;
}//CListBase::Put_After
////////////////////////////////////////////////////////////////////////////
//CListBase::Get_Prev
inline pAList_Cell Get_Prev(pAList_Cell i_pCell)
{
tCell *l_pCell = static_cast<tCell*>(i_pCell);
pAList_Cell l_pResult = NULL;
if (l_pCell)
{
l_pResult = static_cast<pAList_Cell>(l_pCell->m_pPrev);
}
else
{
l_pResult = static_cast<pAList_Cell>(m_pLast);
}
return l_pResult;
}//CListBase::Get_Prev
////////////////////////////////////////////////////////////////////////////
//CListBase::Get_Next
inline pAList_Cell Get_Next(pAList_Cell i_pCell)
{
tCell *l_pCell = static_cast<tCell *>(i_pCell);
pAList_Cell l_pResult = NULL;
if (l_pCell)
{
l_pResult = static_cast<pAList_Cell>(l_pCell->m_pNext);
}
else
{
l_pResult = static_cast<pAList_Cell>(m_pFirst);
}
return l_pResult;
}//CListBase::Get_Next
////////////////////////////////////////////////////////////////////////////
//CListBase::Get_Data
inline tData_Type Get_Data(pAList_Cell i_pCell)
{
tCell *l_pCell = static_cast<tCell*>(i_pCell);
tData_Type l_pResult = 0;
if (l_pCell)
{
l_pResult = l_pCell->m_pData;
}
return l_pResult;
}//CListBase::Get_Data
////////////////////////////////////////////////////////////////////////////
//CListBase::Set_Data
inline tBOOL Set_Data(pAList_Cell i_pCell, tBOOL i_bFree_Old_Data, tData_Type i_pData)
{
tCell *l_pCell = static_cast<tCell*>(i_pCell);
tData_Type l_pResult = NULL;
if (l_pCell)
{
if (i_bFree_Old_Data)
{
Data_Release(l_pCell->m_pData);
}
l_pCell->m_pData = i_pData;
}
return TRUE;
}//CListBase::Set_Data
////////////////////////////////////////////////////////////////////////////
//CListBase::Get_ByIndex
inline pAList_Cell Get_ByIndex(tUINT32 i_dwIDX)
{
tCell *l_pReturn = NULL;
tUINT32 l_dwI;
if (m_bBrokenIndex)
{
Index_Build();
}
if (i_dwIDX < m_dwCount)
{
if ( (FALSE == m_bBrokenIndex)
&& (m_pIndex)
)
{
l_pReturn = m_pIndex[i_dwIDX];
}
else
{
l_pReturn = m_pFirst;
for (l_dwI = 0; l_dwI < i_dwIDX; l_dwI++)
{
if (l_pReturn)
{
l_pReturn = l_pReturn->m_pNext;
}
else
{
break;
}
}
}
}
return l_pReturn;
}//CListBase::Get_ByIndex
////////////////////////////////////////////////////////////////////////////
//CListBase::operator[]
inline tData_Type operator[](tUINT32 i_dwIDX)
{
tCell *l_pReturn = static_cast<tCell*>(Get_ByIndex(i_dwIDX));
return (l_pReturn) ? l_pReturn->m_pData : NULL;
}//CListBase::operator[]
////////////////////////////////////////////////////////////////////////////
//CListBase::Put_Data
inline tBOOL Put_Data(pAList_Cell i_pCell, tData_Type i_pData, tBOOL i_bFree_Old_Data)
{
tBOOL l_bResult = TRUE;
tCell *l_pCell = static_cast<tCell*>(i_pCell);
if (l_pCell)
{
if ( i_bFree_Old_Data )
{
Data_Release(l_pCell->m_pData);
l_pCell->m_pData = NULL;
}
l_pCell->m_pData = i_pData;
}
else
{
l_bResult = FALSE;
}
return l_bResult;
}//CListBase::Put_Data
////////////////////////////////////////////////////////////////////////////
//CListBase::Lock
//void Lock()
//{
// WaitForSingleObject(m_hLock_Mutex, INFINITE);
//}//CListBase::Lock
////////////////////////////////////////////////////////////////////////////
//CListBase::UnLock
//void UnLock()
//{
// ReleaseMutex(m_hLock_Mutex);
//}//CListBase::UnLock
////////////////////////////////////////////////////////////////////////////
//CListBase::Clear
inline void Clear(tBOOL i_bClearData)
{
while (NULL != m_pFirst)
{
if (TRUE != Cell_Release(m_pFirst, TRUE, i_bClearData))
{
break;
}
}
}//CListBase::Clear
////////////////////////////////////////////////////////////////////////////
//CListBase::Get_First
inline pAList_Cell Get_First()
{
return static_cast<pAList_Cell>(m_pFirst);
}//CListBase::Get_First
////////////////////////////////////////////////////////////////////////////
//CListBase::Get_Last
inline pAList_Cell Get_Last()
{
return static_cast<pAList_Cell>(m_pLast);
}//CListBase::Get_Last
////////////////////////////////////////////////////////////////////////////
//CListBase::Count
inline tUINT32 Count()
{
return m_dwCount;
}//CListBase::Count
private:
////////////////////////////////////////////////////////////////////////////
//CListBase::Cell_Release
inline tBOOL Cell_Release(tCell *i_pCell, tBOOL i_bFree_Cell, tBOOL i_bFree_Data)
{
tBOOL l_bResult = TRUE;
if (NULL == i_pCell)
{
return FALSE;
}
if ((NULL != i_pCell->m_pPrev) && (NULL != i_pCell->m_pNext))
{
i_pCell->m_pPrev->m_pNext = i_pCell->m_pNext;
i_pCell->m_pNext->m_pPrev = i_pCell->m_pPrev;
}
else
{
l_bResult = FALSE;
if (i_pCell == m_pFirst)
{
m_pFirst = i_pCell->m_pNext;
if (m_pFirst != 0)
{
m_pFirst->m_pPrev = 0;
}
l_bResult = TRUE;
}
if (i_pCell == m_pLast)
{
m_pLast = i_pCell->m_pPrev;
if (m_pLast != 0)
{
m_pLast->m_pNext = 0;
}
l_bResult = TRUE;
}
}
if (TRUE == l_bResult)
{
if (i_bFree_Data)
{
Data_Release(i_pCell->m_pData);
i_pCell->m_pData = 0;
}
if (i_bFree_Cell)
{
Cell_Free(i_pCell);
}
}
m_bBrokenIndex = TRUE;
m_dwCount--;
return l_bResult;
}//CListBase::Cell_Release
////////////////////////////////////////////////////////////////////////////
//CListBase::Index_Build
inline tBOOL Index_Build()
{
tBOOL l_bResult = TRUE;
if ( (m_pIndex) && (m_dwCount > m_dwIndexCount) )
{
Index_Release();
}
if (NULL == m_pIndex)
{
m_dwIndexCount = m_dwCount + 128;
m_pIndex = (pIndex_Cell*)this->MemAlloc(sizeof(pIndex_Cell) * m_dwIndexCount);
}
if (NULL == m_pIndex)
{
l_bResult = FALSE;
m_dwIndexCount = 0;
}
if (TRUE == l_bResult)
{
pAList_Cell l_pEl = NULL;
memset(m_pIndex, 0, m_dwIndexCount * sizeof(pIndex_Cell));
pIndex_Cell *l_pIndexLocal = m_pIndex;
while ((l_pEl = Get_Next(l_pEl)) != NULL)
{
*l_pIndexLocal = static_cast<tCell*>(l_pEl);
l_pIndexLocal ++;
}
m_bBrokenIndex = FALSE;
}
return l_bResult;
}//CListBase::Index_Build
////////////////////////////////////////////////////////////////////////////
//CListBase::Index_Release
inline tBOOL Index_Release()
{
if (m_pIndex)
{
this->MemFree(m_pIndex);
m_pIndex = NULL;
}
m_dwIndexCount = 0;
m_bBrokenIndex = TRUE;
return TRUE;
}//CListBase::Index_Release
protected:
////////////////////////////////////////////////////////////////////////////
//CListBase::Data_Release
// override this function in derived class to implement specific data
// destructor(structures as example)
virtual tBOOL Data_Release(tData_Type i_pData) = 0;
////////////////////////////////////////////////////////////////////////////
//CListBase::MemAlloc
//override this function in derived class to implement own memory allocation
//mechanism, it will be used everywhere in this class
virtual void *MemAlloc(size_t i_szSize)
{
return new tUINT8[i_szSize];
}//CListBase::MemAlloc
////////////////////////////////////////////////////////////////////////////
//CListBase::MemFree
//override this function in derived class to implement own memory deallocation
//mechanism, it will be used everywhere in this class
virtual void MemFree(void * i_pMemory)
{
delete [] ((tUINT8*)i_pMemory);
}//CListBase::MemFree
////////////////////////////////////////////////////////////////////////////
//CListBase::Cell_Allocate
virtual tCell *Cell_Allocate()
{
return (tCell*)this->MemAlloc(sizeof(tCell));
}//Cell_Allocate
////////////////////////////////////////////////////////////////////////////
//CListBase::Cell_Free
virtual void Cell_Free(tCell *i_pCell)
{
this->MemFree(i_pCell);
}//Cell_Free
};
////////////////////////////////////////////////////////////////////////////////
//CAList
template <typename tData_Type>
class CAList
: public CListBase<tData_Type>
{
protected:
////////////////////////////////////////////////////////////////////////////
//CListBase::Data_Release
// override this function in derived class to implement specific data
// destructor(structures as example)
virtual tBOOL Data_Release(tData_Type i_pData)
{
if (NULL == i_pData)
{
return FALSE;
}
delete i_pData;
return TRUE;
}//CListBase::Data_Release
};
////////////////////////////////////////////////////////////////////////////////
//This list has pool for list's cells, this technology speedup allocation and
//deallocation of new list's elements (6-10 times).
//List intended for situation when you has very intensive adding & deleting
//process, but it will use a lot of memory if you will add 1 million items and
//then delete 999 thousands, after that all 999 thousands internal list cells
//will be stored in internal pool, for the time being mechanism of pool packing
//is not developed.
//N.B.: be careful with list, use it only when you absolutely sure in what are
// you doing.
template <typename tData_Type>
class CListPool:
public CListBase<tData_Type>
{
private:
#define TCELL typename CListBase<tData_Type>::tCell
struct tPool_Segment
{
TCELL *m_pCells;
tUINT32 m_dwCount;
tPool_Segment *m_pNext;
};
tPool_Segment *m_pPool_First;
TCELL *m_pPool_Cell_First;
//count of cell allocated for every pool segment
tUINT32 m_dwPool_Size;
public:
////////////////////////////////////////////////////////////////////////////
//CListPool::CListPool
CListPool(tUINT32 i_dwPool_Size = 128)
: CListBase<tData_Type>()
, m_dwPool_Size(i_dwPool_Size)
{
m_pPool_First = NULL;
m_pPool_Cell_First = NULL;
}//CListPool::CListPool
////////////////////////////////////////////////////////////////////////////
//CListPool::~CListPool
virtual ~CListPool()
{
tPool_Segment *l_pPool_Tmp = NULL;
while (m_pPool_First)
{
l_pPool_Tmp = m_pPool_First;
m_pPool_First = m_pPool_First->m_pNext;
Free_Pool_Segment(l_pPool_Tmp);
}
}//CListPool::~CListPool
private:
////////////////////////////////////////////////////////////////////////////
//CListPool::Create_Pool_Segment
inline tBOOL Create_Pool_Segment()
{
tBOOL l_bReturn = FALSE;
tPool_Segment *l_pPool = (tPool_Segment*)CListBase<tData_Type>::MemAlloc(sizeof(tPool_Segment));
if (l_pPool)
{
memset(l_pPool, 0, sizeof(tPool_Segment));
l_pPool->m_dwCount = m_dwPool_Size;
l_pPool->m_pCells = (TCELL*)this->MemAlloc(sizeof(TCELL) * l_pPool->m_dwCount);
if (l_pPool->m_pCells)
{
TCELL *l_pCell = NULL;
memset(l_pPool->m_pCells,
0,
sizeof(tPool_Segment) * l_pPool->m_dwCount
);
l_pCell = l_pPool->m_pCells;
for (tUINT32 l_dwIDX = 1; l_dwIDX < l_pPool->m_dwCount; l_dwIDX++)
{
l_pCell->m_pNext = (l_pCell + 1);
l_pCell ++;
}
l_bReturn = TRUE;
l_pPool->m_pNext = m_pPool_First;
m_pPool_First = l_pPool;
l_pCell->m_pNext = m_pPool_Cell_First;
m_pPool_Cell_First = l_pPool->m_pCells;
}
}
if (FALSE == l_bReturn)
{
Free_Pool_Segment(l_pPool);
}
return l_bReturn;
}//CListPool::Create_Pool_Segment
////////////////////////////////////////////////////////////////////////////
//CListPool::Free_Pool_Segment
inline void Free_Pool_Segment(tPool_Segment *io_pPool)
{
if (io_pPool)
{
if (io_pPool->m_pCells)
{
this->MemFree(io_pPool->m_pCells);
io_pPool->m_pCells = NULL;
}
this->MemFree(io_pPool);
}
}//CListPool::Free_Pool_Segment
protected:
////////////////////////////////////////////////////////////////////////////
//CListPool::Cell_Allocate
virtual TCELL *Cell_Allocate()
{
TCELL *l_pReturn = NULL;
if (NULL == m_pPool_Cell_First)
{
Create_Pool_Segment();
}
l_pReturn = m_pPool_Cell_First;
if (m_pPool_Cell_First)
{
m_pPool_Cell_First = m_pPool_Cell_First->m_pNext;
}
return l_pReturn;
}//CListPool::Cell_Allocate
////////////////////////////////////////////////////////////////////////////
//CListPool::Cell_Free
virtual void Cell_Free(TCELL *i_pCell)
{
memset(i_pCell, 0, sizeof(TCELL));
i_pCell->m_pNext = m_pPool_Cell_First;
m_pPool_Cell_First = i_pCell;
}//CListPool::Cell_Free
};
////////////////////////////////////////////////////////////////////////////////
//CBList
template <typename tData_Type>
class CBList
: public CListPool<tData_Type>
{
public:
////////////////////////////////////////////////////////////////////////////
//CListPool::CListPool
CBList(tUINT32 i_dwPool_Size = 128)
: CListPool<tData_Type>(i_dwPool_Size)
{
}//CBList::CBList
protected:
////////////////////////////////////////////////////////////////////////////
//CListBase::Data_Release
// override this function in derived class to implement specific data
// destructor(structures as example)
virtual tBOOL Data_Release(tData_Type i_pData)
{
if (NULL == i_pData)
{
return FALSE;
}
delete i_pData;
return TRUE;
}//CListBase::Data_Release
};
#endif //ALIST_H

View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
set(PATH_SHARED ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")
set(PATH_SHARED_CRYPTO ${CMAKE_CURRENT_SOURCE_DIR}/Crypto CACHE INTERNAL "")
set(PATH_SHARED_XML ${CMAKE_CURRENT_SOURCE_DIR}/XML CACHE INTERNAL "")
if(WIN32)
set(PATH_SHARED_PLATFORM ${CMAKE_CURRENT_SOURCE_DIR}/Platforms/Windows_x86 CACHE INTERNAL "")
else()
set(PATH_SHARED_PLATFORM ${CMAKE_CURRENT_SOURCE_DIR}/Platforms/Linux_x86 CACHE INTERNAL "")
endif()

122
p7lib/Shared/CRC32.h Normal file
View File

@ -0,0 +1,122 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
//******************************************************************************
// This header file provide CRC32 functions *
//******************************************************************************
#ifndef CRC32_H
#define CRC32_H
#include <stddef.h>
#include "GTypes.h"
static tUINT32 g_pCRC32_Table[] =
{
0x00000000L, 0x77073096L, 0xee0e612cL,
0x990951baL, 0x076dc419L, 0x706af48fL,
0xe963a535L, 0x9e6495a3L, 0x0edb8832L,
0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L,
0xf3b97148L, 0x84be41deL, 0x1adad47dL,
0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
0x136c9856L, 0x646ba8c0L, 0xfd62f97aL,
0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L,
0x4c69105eL, 0xd56041e4L, 0xa2677172L,
0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL,
0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL,
0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
0x26d930acL, 0x51de003aL, 0xc8d75180L,
0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L,
0xcfba9599L, 0xb8bda50fL, 0x2802b89eL,
0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL,
0xb6662d3dL, 0x76dc4190L, 0x01db7106L,
0x98d220bcL, 0xefd5102aL, 0x71b18589L,
0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL,
0x91646c97L, 0xe6635c01L, 0x6b6b51f4L,
0x1c6c6162L, 0x856530d8L, 0xf262004eL,
0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L,
0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL,
0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
0x4db26158L, 0x3ab551ceL, 0xa3bc0074L,
0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L,
0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
0x44042d73L, 0x33031de5L, 0xaa0a4c5fL,
0xdd0d7cc9L, 0x5005713cL, 0x270241aaL,
0xbe0b1010L, 0xc90c2086L, 0x5768b525L,
0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L,
0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L,
0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L,
0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L,
0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL,
0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
0xf00f9344L, 0x8708a3d2L, 0x1e01f268L,
0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L,
0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L,
0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL,
0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L,
0x41047a60L, 0xdf60efc3L, 0xa867df55L,
0x316e8eefL, 0x4669be79L, 0xcb61b38cL,
0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L,
0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L,
0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L,
0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL,
0x72076785L, 0x05005713L, 0x95bf4a82L,
0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L,
0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL,
0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
0x88085ae6L, 0xff0f6a70L, 0x66063bcaL,
0x11010b5cL, 0x8f659effL, 0xf862ae69L,
0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
0xa7672661L, 0xd06016f7L, 0x4969474dL,
0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL,
0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L,
0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L,
0x24b4a3a6L, 0xbad03605L, 0xcdd70693L,
0x54de5729L, 0x23d967bfL, 0xb3667a2eL,
0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
static tUINT32 *g_ppCRC32_Table = &g_pCRC32_Table[0];
#include "PCRC32.h"
#endif //CRC32_H

519
p7lib/Shared/DnsResolver.h Normal file
View File

@ -0,0 +1,519 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H
#include "AList.h"
#include "RBTree.h"
#include "PSocket.h"
#include "PAtomic.h"
#include "PLock.h"
#include "IMEvent.h"
#include "PMEvent.h"
#include "PThreadShell.h"
#include "PTime.h"
#if !defined(NI_MAXHOST)
#define NI_MAXHOST 1025 /* Max size of a fully-qualified domain name */
#endif
#define DNS_RESOLVE_TIME_OUT_MIN (50)
#define DNS_RESOLVE_TIME_OUT_MAX (500)
#define DNS_RESOLVER_EXIT_EVENT (MEVENT_SIGNAL_0)
#define DNS_RESOLVER_EVENT (MEVENT_SIGNAL_0 + 1)
#define DNS_NAME_EVENT (MEVENT_SIGNAL_0)
////////////////////////////////////////////////////////////////////////////////
//CDNS_Item
class CDNS_Item
{
tXCHAR *m_pName; //host name
tXCHAR m_pIP[96];
size_t m_szName_Max; //host name max length
size_t m_szName; //host name current length
sockaddr_storage m_sSAS; //host Socket address V4/V6
CMEvent m_cEvent;
public:
////////////////////////////////////////////////////////////////////////////
//CDNS_Item
CDNS_Item(sockaddr *i_pSA)
: m_pName(NULL)
, m_szName_Max(0)
, m_szName(0)
{
if (AF_INET == i_pSA->sa_family)
{
memcpy(&m_sSAS, i_pSA, sizeof(sockaddr_in));
((sockaddr_in*)&m_sSAS)->sin_port = 0;
}
else if (AF_INET6 == i_pSA->sa_family)
{
memcpy(&m_sSAS, i_pSA, sizeof(sockaddr_in6));
((sockaddr_in6*)&m_sSAS)->sin6_port = 0;
}
if (Print_SAddr((sockaddr*)&m_sSAS, m_pIP, LENGTH(m_pIP)))
{
size_t l_szIP = PStrLen(m_pIP);
for (size_t l_szI = 0; l_szI < l_szIP; l_szI ++)
{
if (TM(':') == m_pIP[l_szI])
{
m_pIP[l_szI] = TM('x');
}
}
}
else
{
PStrCpy(m_pIP, LENGTH(m_pIP), TM("Unknown"));
}
m_cEvent.Init(1, EMEVENT_SINGLE_AUTO);
}//CDNS_Item
////////////////////////////////////////////////////////////////////////////
//~CDNS_Item
~CDNS_Item()
{
if (m_pName)
{
delete [] m_pName;
m_pName = NULL;
}
}
////////////////////////////////////////////////////////////////////////////
//Get_SA
const sockaddr *Get_SA()
{
return (sockaddr*)&m_sSAS;
}//Get_SA
////////////////////////////////////////////////////////////////////////////
//Get_Event
CMEvent *Get_Event()
{
return &m_cEvent;
}//Get_Event
////////////////////////////////////////////////////////////////////////////
//Update
tBOOL Update(tXCHAR *i_pName)
{
tXCHAR *l_pName = (i_pName) ? i_pName : m_pIP;
size_t l_szName = PStrLen(l_pName);
if (l_szName > m_szName_Max)
{
if (m_pName)
{
delete [] m_pName;
m_pName = NULL;
}
m_szName_Max = (l_szName + 1 + 15) & (~15UL);
m_pName = new tXCHAR[m_szName_Max];
}
if (NULL != m_pName)
{
m_szName = l_szName;
PStrCpy(m_pName, m_szName_Max, l_pName);
}
else
{
m_szName = 0;
m_szName_Max = 0;
}
return (m_pName) ? TRUE : FALSE;
}//Update
////////////////////////////////////////////////////////////////////////////
//Get_Name()
tBOOL Get_Name(tXCHAR *o_pName, size_t i_szLength_Max)
{
if ( (o_pName)
&& (1 < i_szLength_Max)
)
{
if (m_szName >= i_szLength_Max)
{
PStrNCpy(o_pName, i_szLength_Max, m_pName, i_szLength_Max - 1);
}
else
{
PStrCpy(o_pName, i_szLength_Max, m_pName);
}
return TRUE;
}
return FALSE;
}//Get_Name()
////////////////////////////////////////////////////////////////////////////
//Is_Greater -> (m_sSA > i_pSA) == TRUE
tBOOL Is_Greater(sockaddr *i_pSA)
{
if (m_sSAS.ss_family > i_pSA->sa_family)
{
return TRUE;
}
else if (m_sSAS.ss_family < i_pSA->sa_family)
{
return FALSE;
}
if (AF_INET == i_pSA->sa_family)
{
return (((sockaddr_in*)&m_sSAS)->sin_addr.s_addr > ((sockaddr_in*)i_pSA)->sin_addr.s_addr);
}
else if (AF_INET6 == i_pSA->sa_family)
{
return (0 < memcmp(((sockaddr_in6*)&m_sSAS)->sin6_addr.s6_addr,
((sockaddr_in6*)i_pSA)->sin6_addr.s6_addr,
sizeof(in6_addr)
)
);
}
return FALSE;
}//Is_Greater
////////////////////////////////////////////////////////////////////////////
//Is_Equal
tBOOL Is_Equal(sockaddr *i_pSA)
{
if (m_sSAS.ss_family == i_pSA->sa_family)
{
if (AF_INET == i_pSA->sa_family)
{
return (((sockaddr_in*)&m_sSAS)->sin_addr.s_addr == ((sockaddr_in*)i_pSA)->sin_addr.s_addr);
}
else if (AF_INET6 == i_pSA->sa_family)
{
return (0 == memcmp(((sockaddr_in6*)&m_sSAS)->sin6_addr.s6_addr,
((sockaddr_in6*)i_pSA)->sin6_addr.s6_addr,
sizeof(in6_addr)
)
);
}
}
return FALSE;
}//Is_Equal
};
////////////////////////////////////////////////////////////////////////////////
//CDNS_Resolver
class CDNS_Resolver:
public CRBTree<CDNS_Item*, sockaddr*>
{
volatile tINT32 m_lTimeOut;
tLOCK m_sCS;
CThShell::tTHREAD m_hThread;
tBOOL m_bIsThread;
CMEvent m_cEvent;
CBList<CDNS_Item*> m_cRecords;
CBList<CDNS_Item*> m_cResolving;
public:
////////////////////////////////////////////////////////////////////////////
//CDNS_Resolver()
CDNS_Resolver()
: CRBTree<CDNS_Item*, sockaddr*>(32, FALSE)
, m_lTimeOut(DNS_RESOLVE_TIME_OUT_MAX)
, m_bIsThread(FALSE)
, m_cRecords(32)
{
LOCK_CREATE(m_sCS);
m_cEvent.Init(2, EMEVENT_SINGLE_AUTO, EMEVENT_MULTI);
if (CThShell::Create(&Static_Routine, this, &m_hThread, TM("DNSR")))
{
m_bIsThread = TRUE;
}
}//~CDNS_Resolver()
////////////////////////////////////////////////////////////////////////////
//~CDNS_Resolver()
~CDNS_Resolver()
{
if (m_bIsThread)
{
m_cEvent.Set(DNS_RESOLVER_EXIT_EVENT);
if (TRUE == CThShell::Close(m_hThread, 90000))
{
m_hThread = 0;//NULL;
m_bIsThread = FALSE;
}
}
m_cResolving.Clear(FALSE);
m_cRecords.Clear(TRUE);
LOCK_DESTROY(m_sCS);
}//~CDNS_Resolver()
////////////////////////////////////////////////////////////////////////////
//Get_Name()
tBOOL Get_Name(sockaddr *i_pKey, tXCHAR *o_pName, size_t i_szName, tBOOL *o_pNew)
{
CDNS_Item *l_pRec = NULL;
tBOOL l_bAdd = FALSE;
if ( (NULL == i_pKey)
|| ( (AF_INET != i_pKey->sa_family)
&& (AF_INET6 != i_pKey->sa_family)
)
|| (NULL == o_pName)
|| (16 > i_szName)
)
{
return FALSE;
}
LOCK_ENTER(m_sCS);
l_pRec = this->Find(i_pKey);
if (NULL == l_pRec)
{
l_pRec = new CDNS_Item(i_pKey);
if (l_pRec)
{
this->Push(l_pRec, i_pKey);
m_cRecords.Add_After(m_cRecords.Get_Last(), l_pRec);
l_pRec->Update(NULL);
l_bAdd = TRUE;
}
if (o_pNew)
{
*o_pNew = 1;
}
}
LOCK_EXIT(m_sCS);
if (l_bAdd)
{
LOCK_ENTER(m_sCS);
m_cResolving.Add_After(m_cResolving.Get_Last(), l_pRec);
m_cEvent.Set(DNS_RESOLVER_EVENT);
LOCK_EXIT(m_sCS);
l_pRec->Get_Event()->Wait((tUINT32)m_lTimeOut);
}//if (NULL == l_pRec)
LOCK_ENTER(m_sCS);
if (l_pRec)
{
l_pRec->Get_Name(o_pName, i_szName);
}
LOCK_EXIT(m_sCS);
return (NULL != l_pRec);
}//Get_Name()
protected:
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey < i_pData::key)
//FALSE - otherwise
tBOOL Is_Key_Less(sockaddr *i_pKey, CDNS_Item *i_pData)
{
return i_pData->Is_Greater(i_pKey);
}
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey == i_pData::key)
//FALSE - otherwise
tBOOL Is_Qual(sockaddr *i_pKey, CDNS_Item *i_pData)
{
return i_pData->Is_Equal(i_pKey);
}
private:
////////////////////////////////////////////////////////////////////////////
//Routine_Static
static THSHELL_RET_TYPE THSHELL_CALL_TYPE Static_Routine(void *i_pContext)
{
CDNS_Resolver * l_pRoutine = (CDNS_Resolver *)i_pContext;
if (l_pRoutine)
{
l_pRoutine->Routine();
}
CThShell::Cleanup();
return THSHELL_RET_OK;
}
////////////////////////////////////////////////////////////////////////////
//Routine
void Routine()
{
tXCHAR l_pName[NI_MAXHOST];
tBOOL l_bExit = FALSE;
pAList_Cell l_pEl = NULL;
CDNS_Item *l_pRec = NULL;
tUINT32 l_dwWFMOR = 0;
tINT32 l_lWaitMax = -1;
tUINT32 l_dwTick = 0;
while (FALSE == l_bExit)
{
l_dwWFMOR = m_cEvent.Wait(1000);
if (DNS_RESOLVER_EXIT_EVENT == l_dwWFMOR)
{
l_bExit = TRUE;
}
else if (DNS_RESOLVER_EVENT == l_dwWFMOR)
{
LOCK_ENTER(m_sCS);
l_pRec = m_cResolving.Get_Data(m_cResolving.Get_First());
m_cResolving.Del(m_cResolving.Get_First(), FALSE);
LOCK_EXIT(m_sCS);
if (l_pRec)
{
l_dwTick = GetTickCount();
if (Resolve_SA(l_pRec->Get_SA(), l_pName, LENGTH(l_pName)))
{
l_dwTick = CTicks::Difference(GetTickCount(), l_dwTick);
LOCK_ENTER(m_sCS);
l_pRec->Update(l_pName);
LOCK_EXIT(m_sCS);
}
else
{
l_dwTick = 0;
LOCK_ENTER(m_sCS);
l_pRec->Update(NULL);
LOCK_EXIT(m_sCS);
}
l_pRec->Get_Event()->Set(DNS_NAME_EVENT);
}
//Update waiting timeout based on maximum waiting of response
//from DNS server
if ((tINT32)l_dwTick > l_lWaitMax)
{
//set timeout with max limit of DNS_RESOLVE_TIME_OUT
if (l_dwTick > DNS_RESOLVE_TIME_OUT_MAX)
{
l_lWaitMax = DNS_RESOLVE_TIME_OUT_MAX;
}
else if (l_dwTick < DNS_RESOLVE_TIME_OUT_MIN)
{
l_lWaitMax = DNS_RESOLVE_TIME_OUT_MIN;
}
else
{
l_lWaitMax = (tINT32)l_dwTick;
}
if (l_lWaitMax != m_lTimeOut)
{
ATOMIC_SET(&m_lTimeOut, l_lWaitMax);
}
}
}
else if (MEVENT_TIME_OUT == l_dwWFMOR)
{
LOCK_ENTER(m_sCS);
l_pEl = m_cRecords.Get_Next(l_pEl);
l_pRec = m_cRecords.Get_Data(l_pEl);
LOCK_EXIT(m_sCS);
if (l_pRec)
{
if (Resolve_SA(l_pRec->Get_SA(), l_pName, LENGTH(l_pName)))
{
LOCK_ENTER(m_sCS);
l_pRec->Update(l_pName);
LOCK_EXIT(m_sCS);
}
else
{
LOCK_ENTER(m_sCS);
l_pRec->Update(NULL);
LOCK_EXIT(m_sCS);
}
}
}
}
}//Routine
////////////////////////////////////////////////////////////////////////////
//Resolve_SA
tBOOL Resolve_SA(const sockaddr *i_pSA, tXCHAR *o_pName, tUINT32 i_dwLength)
{
tUINT32 l_dwIP_Size = 0;
tBOOL l_bReturn = FALSE;
if (NULL == i_pSA)
{
return l_bReturn;
}
if (AF_INET == i_pSA->sa_family)
{
l_dwIP_Size = sizeof(sockaddr_in);
}
else if (AF_INET6 == i_pSA->sa_family)
{
l_dwIP_Size = sizeof(sockaddr_in6);
}
#ifdef UTF8_ENCODING
int l_iRes = getnameinfo(i_pSA, l_dwIP_Size,
o_pName, i_dwLength,
NULL, 0,
NI_NAMEREQD
);
#else
int l_iRes = GetNameInfoW(i_pSA, l_dwIP_Size,
o_pName, i_dwLength,
NULL, 0,
NI_NAMEREQD
);
#endif
if (0 == l_iRes)
{
l_bReturn = TRUE;
}
return l_bReturn;
}//Resolve_SA
};//CDNS_Resolver
#endif //DNS_RESOLVER_H

929
p7lib/Shared/IConsole.h Normal file
View File

@ -0,0 +1,929 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef ICONSOLE_H
#define ICONSOLE_H
#define CON_RIGHT_ALT_PRESSED 0x0001 // the right alt key is pressed.
#define CON_LEFT_ALT_PRESSED 0x0002 // the left alt key is pressed.
#define CON_RIGHT_CTRL_PRESSED 0x0004 // the right ctrl key is pressed.
#define CON_LEFT_CTRL_PRESSED 0x0008 // the left ctrl key is pressed.
#define CON_SHIFT_PRESSED 0x0010 // the shift key is pressed.
#define CON_NUMLOCK_ON 0x0020 // the numlock light is on.
#define CON_SCROLLLOCK_ON 0x0040 // the scrolllock light is on.
#define CON_CAPSLOCK_ON 0x0080 // the capslock light is on.
#define CON_ENHANCED_KEY 0x0100 // the key is enhanced.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class IConsole
{
public:
enum eColor
{
eBlack = 0,
eBlue,
eGreen,
eCyan,
eRed,
eMagenta,
eBrown,
eLightGray,
eDarkGray,
eLightBlue,
eLightGreen,
eLightCyan,
eLightRed,
eLightMagenta,
eYellow,
eWhite,
eColorsMax
};
enum eEvent
{
eSize = 0,
eMouse,
eKey,
eFocus,
eEventsMax
};
enum eKey
{
eKeyEsc = 27,
eKeyEnter = 13,
eKeySpace = 32,
eKeyExtra = 0x100,
eKeyArrowLeft,
eKeyArrowRight,
eKeyArrowDown,
eKeyArrowUp,
eKeyPageUp,
eKeyPageDown,
eKeyHome,
eKeyEnd,
eKeyF1,
eKeyF2,
eKeyF3,
eKeyF4,
eKeyF5,
eKeyF6,
eKeyF7,
eKeyF8,
eKeyF9,
eKeyF10,
eKeyF11,
eKeyF12,
eKeyDel,
eKeyInsert,
eKeyTab,
eKeyBackSpace,
eKeyMax
};
struct sSize
{
tUINT32 uW;
tUINT32 uH;
};
struct sMouse
{
tUINT32 uX;
tUINT32 uY;
tUINT32 uButton;
};
struct sKey
{
tBOOL bDown;
tUINT16 wKey;
tUINT16 wCount;
tUINT32 uControls;
};
struct sFocus
{
tBOOL bFocus;
};
struct sInput
{
IConsole::eEvent eEvent;
union
{
sSize stSize;
sMouse stMouse;
sKey stKey;
sFocus stFocus;
};
};
virtual tBOOL SetCursor(tUINT32 i_uX, tUINT32 i_uY) = 0;
virtual tUINT32 GetCursorX() = 0;
virtual tUINT32 GetCursorY() = 0;
virtual tUINT32 GetWidth() = 0;
virtual tUINT32 GetHeight() = 0;
virtual tBOOL SetTextAttr(IConsole::eColor i_eFg, IConsole::eColor i_eBg) = 0;
virtual tBOOL GetInput(IConsole::sInput &o_rInput) = 0;
virtual tBOOL Clear() = 0;
virtual tBOOL Clear(tUINT32 i_uX, tUINT32 i_uY, tUINT32 i_uW, tUINT32 i_uH, IConsole::eColor i_eBg) = 0;
virtual size_t WriteTextB(const tXCHAR *i_pText, size_t i_szText) = 0;
virtual size_t WriteTextB(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
size_t i_szOffset,
tXCHAR *i_pText,
size_t i_szText,
size_t i_szTextMax
) = 0;
virtual size_t WriteTextO(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
size_t i_szOffset,
const tXCHAR *i_pFormat,
...
)
{
va_list l_pVA;
size_t l_szReturn = 0;
va_start(l_pVA, i_pFormat);
l_szReturn = WriteTextF(i_eFg, i_eBg, i_szLenMin, i_szLenMax, i_szOffset, i_pFormat, l_pVA);
va_end(l_pVA);
return l_szReturn;
}
virtual size_t WriteText(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
const tXCHAR *i_pFormat,
...
)
{
va_list l_pVA;
size_t l_szReturn = 0;
va_start(l_pVA, i_pFormat);
l_szReturn = WriteTextF(i_eFg, i_eBg, i_szLenMin, i_szLenMax, 0, i_pFormat, l_pVA);
va_end(l_pVA);
return l_szReturn;
}
virtual size_t WriteTextF(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
size_t i_szOffset,
const tXCHAR *i_pFormat,
va_list i_pVA
) = 0;
virtual tBOOL Present() = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CConsoleWnd
{
struct stHelp
{
tXCHAR *pString;
IConsole::eColor eBgColor;
IConsole::eColor eFgColor;
stHelp(const tXCHAR *i_pString, IConsole::eColor i_eBgColor, IConsole::eColor i_eFgColor)
{
pString = PStrDub(i_pString);
eBgColor = i_eBgColor;
eFgColor = i_eFgColor;
}
~stHelp()
{
if (pString)
{
free(pString);
pString = NULL;
}
}
};
public:
struct stColumn
{
tUINT32 uId;
tBOOL bVisible;
tXCHAR *pCaption;
size_t szCaption;
stColumn(tUINT32 i_uId, tBOOL i_bVisible, const tXCHAR *i_pCaption)
: pCaption(NULL)
{
uId = i_uId;
bVisible = i_bVisible;
SetCaption(i_pCaption);
}
~stColumn()
{
if (pCaption)
{
PStrFreeDub(pCaption);
pCaption = NULL;
}
uId = 0;
bVisible = FALSE;
szCaption = 0;
}
void SetCaption(const tXCHAR *i_pCaption)
{
if (pCaption)
{
PStrFreeDub(pCaption);
}
pCaption = PStrDub(i_pCaption);
szCaption = PStrLen(pCaption);
}
};
protected:
tUINT32 m_uX;
tUINT32 m_uY;
tUINT32 m_uW;
tUINT32 m_uH;
size_t m_szLinesPerItem;
size_t m_szItemsPerWnd;
tUINT64 m_qwItemsCount;
IConsole *m_pConsole;
IConsole::eColor m_eWindowBgColor;
IConsole::eColor m_eItemBgColor;
IConsole::eColor m_eItemFgColor;
IConsole::eColor m_eItemSlFgColor;
IConsole::eColor m_eItemSlBgColor;
IConsole::eColor m_eItemClFgColor;
IConsole::eColor m_eItemClBgColor;
tBOOL m_bError;
tXCHAR *m_pCaption;
size_t m_szOffsetX;
size_t m_szOffsetY;
tUINT64 m_qwOffsetWnd;
tBOOL m_bHelp;
CBList<stHelp*> m_cHelp;
CBList<stColumn*>m_cColumns;
tBOOL m_bColumns;
tBOOL m_bUpdateColumns;
tXCHAR *m_pColumnsText;
size_t m_szColumnsTextMax;
size_t m_szColumnsText;
public:
struct sCfg
{
tUINT32 uX;
tUINT32 uY;
tUINT32 uW;
tUINT32 uH;
size_t uLinesPerItem;
size_t szItemsCount;
IConsole *pConsole;
IConsole::eColor eWindowBgColor;
IConsole::eColor eItemBgColor;
IConsole::eColor eItemFgColor;
IConsole::eColor eItemSlFgColor;
IConsole::eColor eItemSlBgColor;
IConsole::eColor eItemClFgColor;
IConsole::eColor eItemClBgColor;
const tXCHAR *pCaption;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CConsoleWnd()
: m_uX(0)
, m_uY(0)
, m_uW(0)
, m_uH(0)
, m_szLinesPerItem(0)
, m_szItemsPerWnd(0)
, m_qwItemsCount(0ull)
, m_pConsole(NULL)
, m_eWindowBgColor(IConsole::eBlack)
, m_eItemBgColor(IConsole::eBlack)
, m_eItemFgColor(IConsole::eGreen)
, m_eItemSlFgColor(IConsole::eBlue)
, m_eItemSlBgColor(IConsole::eBlack)
, m_eItemClFgColor(IConsole::eWhite)
, m_eItemClBgColor(IConsole::eDarkGray)
, m_bError(FALSE)
, m_pCaption(NULL)
, m_szOffsetX(0)
, m_szOffsetY(0)
, m_qwOffsetWnd(0)
, m_bHelp(FALSE)
, m_bColumns(FALSE)
, m_bUpdateColumns(FALSE)
, m_pColumnsText(NULL)
, m_szColumnsTextMax(0)
, m_szColumnsText(0)
{
CConsoleWnd::PushHelpString(TM(" Navigation keys mapping:"), IConsole::eBlue, IConsole::eWhite);
CConsoleWnd::PushHelpString(TM(" * Arrow Up, Down, Page Up, Page down - move cursor"), IConsole::eBlack, IConsole::eGreen);
CConsoleWnd::PushHelpString(TM(" * Arrow Left, Right - horizontal scroll"), IConsole::eBlack, IConsole::eGreen);
CConsoleWnd::PushHelpString(TM(" * Home - goto top"), IConsole::eBlack, IConsole::eGreen);
CConsoleWnd::PushHelpString(TM(" * End - goto bottom"), IConsole::eBlack, IConsole::eGreen);
CConsoleWnd::PushHelpString(TM(" * Esc - exit to upper level or quit"), IConsole::eBlack, IConsole::eGreen);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual tBOOL Init(const CConsoleWnd::sCfg &i_rConfig)
{
m_pConsole = i_rConfig.pConsole;
m_eWindowBgColor = i_rConfig.eWindowBgColor;
m_eItemBgColor = i_rConfig.eItemBgColor;
m_eItemFgColor = i_rConfig.eItemFgColor;
m_eItemSlFgColor = i_rConfig.eItemSlFgColor;
m_eItemSlBgColor = i_rConfig.eItemSlBgColor;
m_eItemClFgColor = i_rConfig.eItemClFgColor;
m_eItemClBgColor = i_rConfig.eItemClBgColor;
m_szLinesPerItem = i_rConfig.uLinesPerItem;
m_qwItemsCount = i_rConfig.szItemsCount;
SetCaption(i_rConfig.pCaption);
m_pConsole->SetCursor(i_rConfig.uX, i_rConfig.uY);
m_pConsole->Clear(i_rConfig.uX, i_rConfig.uY, i_rConfig.uW, i_rConfig.uH, m_eWindowBgColor);
return Resize(i_rConfig.uX, i_rConfig.uY, i_rConfig.uW, i_rConfig.uH);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void SetContext(void *i_pContext)
{
UNUSED_ARG(i_pContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual ~CConsoleWnd()
{
m_cHelp.Clear(TRUE);
m_cColumns.Clear(TRUE);
if (m_pCaption)
{
PStrFreeDub(m_pCaption);
m_pCaption = NULL;
}
if (m_pColumnsText)
{
free(m_pColumnsText);
m_pColumnsText = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetCaption(const tXCHAR *i_pCaption)
{
if (m_pCaption)
{
PStrFreeDub(m_pCaption);
m_pCaption = NULL;
}
m_pCaption = i_pCaption ? PStrDub(i_pCaption) : PStrDub(TM("?"));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void PushHelpString(const tXCHAR *i_pString, IConsole::eColor i_eBgColor, IConsole::eColor i_eFgColor)
{
if (i_pString)
{
m_cHelp.Add_After(m_cHelp.Get_Last(), new stHelp(i_pString, i_eBgColor, i_eFgColor));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void PushColumn(tUINT32 i_uId, tBOOL i_bVisible, const tXCHAR *i_pCaption)
{
if (i_pCaption)
{
m_cColumns.Add_After(m_cColumns.Get_Last(), new stColumn(i_uId, i_bVisible, i_pCaption));
m_bUpdateColumns = TRUE;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void EnableColumns(tBOOL i_bEnable)
{
m_bUpdateColumns = TRUE;
m_bColumns = i_bEnable;
UpdateItemsPerWindow();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual CConsoleWnd::stColumn *GetColumn(tUINT32 i_uIndex)
{
return m_cColumns[i_uIndex];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void EnableColumn(tUINT32 i_uIndex, tBOOL i_bEnable)
{
stColumn *l_pCol = m_cColumns[i_uIndex];
if (!l_pCol)
{
return;
}
l_pCol->bVisible = i_bEnable;
m_bUpdateColumns = TRUE;
if (m_bColumns)
{
Redraw();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void SetColumnCaption(tUINT32 i_uIndex, const tXCHAR *i_pCation)
{
stColumn *l_pCol = m_cColumns[i_uIndex];
if (!l_pCol)
{
return;
}
l_pCol->SetCaption(i_pCation);
m_bUpdateColumns = TRUE;
if (m_bColumns)
{
Redraw();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void SetItemsCount(tUINT64 i_qwItems)
{
m_qwItemsCount = i_qwItems;
UpdateItemsPerWindow();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void Redraw()
{
if (m_bHelp)
{
return;
}
tUINT32 l_uiOffset = 1;
if (m_bColumns)
{
l_uiOffset = 2;
}
UpdateHeader();
m_pConsole->SetCursor(m_uX, m_uY + l_uiOffset);
size_t l_szCount = Print() + l_uiOffset;
if (l_szCount < (size_t)m_uH)
{
m_pConsole->Clear(m_uX, m_uY + (tUINT32)l_szCount, m_uW, m_uH - (tUINT32)l_szCount, m_eWindowBgColor);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual tBOOL Resize(tUINT32 i_uX, tUINT32 i_uY, tUINT32 i_uW, tUINT32 i_uH)
{
m_uX = i_uX;
m_uY = i_uY;
m_uW = i_uW;
m_uH = i_uH;
UpdateItemsPerWindow();
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual tBOOL ProcessKey(tUINT16 i_wChar)
{
if (m_bError)
{
return FALSE;
}
tBOOL l_bReturn = FALSE;
size_t l_szCount = (size_t)m_uH;
tUINT32 l_uiOffset = 1;
if (m_bColumns)
{
l_uiOffset = 2;
}
if (m_bHelp)
{
if ((tUINT16)IConsole::eKeyEsc == i_wChar)
{
m_bHelp = FALSE;
l_bReturn = TRUE;
}
}
else if ( ((tUINT16)IConsole::eKeyF1 == i_wChar)
|| ((tUINT16)IConsole::eKeyF2 == i_wChar)
)
{
m_bHelp = TRUE;
l_szCount = m_cHelp.Count() - l_uiOffset;
m_pConsole->SetCursor(m_uX, m_uY);
pAList_Cell l_pEl = NULL;
while (NULL != (l_pEl = m_cHelp.Get_Next(l_pEl)))
{
stHelp *l_pHelp = m_cHelp.Get_Data(l_pEl);
if (l_pHelp)
{
m_pConsole->WriteText(l_pHelp->eFgColor, l_pHelp->eBgColor, m_uW, m_uW, l_pHelp->pString);
}
else
{
l_szCount --;
}
}
}
else if ((tUINT16)IConsole::eKeyArrowLeft == i_wChar)
{
if (m_szOffsetX)
{
m_szOffsetX--;
l_bReturn = TRUE;
m_bUpdateColumns = TRUE;
}
}
else if ((tUINT16)IConsole::eKeyArrowRight == i_wChar)
{
m_szOffsetX++;
m_bUpdateColumns = TRUE;
l_bReturn = TRUE;
}
else if ((tUINT16)IConsole::eKeyArrowUp == i_wChar)
{
if (m_szOffsetY)
{
m_szOffsetY--;
l_bReturn = TRUE;
}
else if (m_qwOffsetWnd)
{
m_qwOffsetWnd--;
l_bReturn = TRUE;
}
}
else if ((tUINT16)IConsole::eKeyArrowDown == i_wChar)
{
if ((m_szOffsetY + 1) < m_szItemsPerWnd)
{
m_szOffsetY++;
l_bReturn = TRUE;
}
else if ((m_qwOffsetWnd + (tUINT64)m_szItemsPerWnd + 1ull) <= m_qwItemsCount)
{
m_qwOffsetWnd++;
l_bReturn = TRUE;
}
}
else if ((tUINT16)IConsole::eKeyPageUp == i_wChar)
{
if (m_qwOffsetWnd > (tUINT64)m_szItemsPerWnd)
{
m_qwOffsetWnd -= (tUINT64)m_szItemsPerWnd;
l_bReturn = TRUE;
}
else if (m_qwOffsetWnd)
{
m_qwOffsetWnd = 0;
m_szOffsetY = 0;
l_bReturn = TRUE;
}
else if (m_szOffsetY)
{
m_szOffsetY = 0;
l_bReturn = TRUE;
}
}
else if ((tUINT16)IConsole::eKeyPageDown == i_wChar)
{
if ((m_qwOffsetWnd + 2ull*(tUINT64)m_szItemsPerWnd) <= m_qwItemsCount)
{
m_qwOffsetWnd += (tUINT64)m_szItemsPerWnd;
l_bReturn = TRUE;
}
else if ((tUINT64)m_szItemsPerWnd <= m_qwItemsCount)
{
m_qwOffsetWnd = m_qwItemsCount - (tUINT64)m_szItemsPerWnd;
m_szOffsetY = m_szItemsPerWnd - 1;
l_bReturn = TRUE;
}
else if (m_qwItemsCount)
{
m_szOffsetY = (size_t)m_qwItemsCount - 1;
l_bReturn = TRUE;
}
}
else if ((tUINT16)IConsole::eKeyHome == i_wChar)
{
m_qwOffsetWnd = 0;
m_szOffsetY = 0;
l_bReturn = TRUE;
}
else if ((tUINT16)IConsole::eKeyEnd == i_wChar)
{
if ((tUINT64)m_szItemsPerWnd <= m_qwItemsCount)
{
m_qwOffsetWnd = m_qwItemsCount - (tUINT64)m_szItemsPerWnd;
m_szOffsetY = m_szItemsPerWnd - 1;
l_bReturn = TRUE;
}
else if (m_qwItemsCount)
{
m_szOffsetY = (size_t)m_qwItemsCount - 1;
l_bReturn = TRUE;
}
}
if (l_bReturn)
{
UpdateHeader();
m_pConsole->SetCursor(m_uX, m_uY + l_uiOffset);
l_szCount = Print();
}
l_szCount += l_uiOffset;
if (l_szCount < (size_t)m_uH)
{
m_pConsole->Clear(m_uX, m_uY + (tUINT32)l_szCount, m_uW, m_uH - (tUINT32)l_szCount, m_eWindowBgColor);
}
return l_bReturn;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual size_t Print() = 0;
protected:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UpdateItemsPerWindow()
{
tUINT32 l_uiH = m_uH - 1;
if (!m_szLinesPerItem)
{
return;
}
if ( (m_bColumns)
&& (l_uiH)
)
{
l_uiH --;
}
m_szItemsPerWnd = l_uiH / m_szLinesPerItem;
if (m_szItemsPerWnd > m_qwItemsCount)
{
m_szItemsPerWnd = (size_t)m_qwItemsCount;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void UpdateHeader()
{
tUINT32 l_uPos = 100;
tUINT64 l_qwOffsY = (tUINT64)m_szOffsetY;
if ( (l_qwOffsY)
|| (1ull == m_qwItemsCount)
)
{
l_qwOffsY++;
}
if (m_qwItemsCount)
{
l_uPos = (tUINT32)((100ull * (m_qwOffsetWnd + l_qwOffsY)) / m_qwItemsCount);
}
m_pConsole->SetCursor(m_uX, m_uY);
m_pConsole->WriteText(IConsole::eBlack,
IConsole::eDarkGray,
m_uW,
m_uW,
TM("{%s} % 3u%% [Help = F1/F2]"),
m_pCaption,
l_uPos
);
if (m_bColumns)
{
if (m_bUpdateColumns)
{
pAList_Cell l_pEl = NULL;
size_t l_szLen = 0;
while ((l_pEl = m_cColumns.Get_Next(l_pEl))) { l_szLen += m_cColumns.Get_Data(l_pEl)->szCaption;}
if (l_szLen >= m_szColumnsTextMax)
{
if (m_pColumnsText) free(m_pColumnsText);
m_szColumnsTextMax = l_szLen + 16;
m_pColumnsText = (tXCHAR*)malloc(m_szColumnsTextMax * sizeof(tXCHAR));
}
m_szColumnsText = 0;
l_pEl = NULL;
while ((l_pEl = m_cColumns.Get_Next(l_pEl)))
{
stColumn *l_pCol = m_cColumns.Get_Data(l_pEl);
if ( (l_pCol)
&& (l_pCol->bVisible)
)
{
PStrCpy(m_pColumnsText + m_szColumnsText, m_szColumnsTextMax - m_szColumnsText, l_pCol->pCaption);
m_szColumnsText += l_pCol->szCaption;
}
}
m_bUpdateColumns = FALSE;
if (!m_szColumnsText)
{
m_pColumnsText[0] = TM(' ');
m_pColumnsText[1] = 0;
m_szColumnsText = 1;
}
}
m_pConsole->WriteTextB(m_eItemClFgColor,
m_eItemClBgColor,
m_uW,
m_uW,
m_szOffsetX,
m_pColumnsText,
m_szColumnsText,
m_szColumnsTextMax
);
}
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CConsoleInput
{
protected:
tXCHAR *m_pText;
size_t m_szText;
size_t m_szCursor;
tXCHAR *m_pCaption;
tUINT32 m_uX;
tUINT32 m_uY;
tUINT32 m_uW;
tUINT32 m_uH;
IConsole *m_pConsole;
IConsole::eColor m_eWndFgColor;
IConsole::eColor m_eWndBgColor;
IConsole::eColor m_eInpFgColor;
IConsole::eColor m_eInpBgColor;
IConsole::eColor m_eCurFgColor;
IConsole::eColor m_eCurBgColor;
public:
struct sCfg
{
tUINT32 uX;
tUINT32 uY;
tUINT32 uW;
tUINT32 uH;
IConsole *pConsole;
IConsole::eColor eWndFgColor;
IConsole::eColor eWndBgColor;
IConsole::eColor eInpFgColor;
IConsole::eColor eInpBgColor;
IConsole::eColor eCurFgColor;
IConsole::eColor eCurBgColor;
const tXCHAR *pCaption;
sCfg(tUINT32 i_uX,
tUINT32 i_uY,
tUINT32 i_uW,
tUINT32 i_uH,
IConsole *i_pConsole,
const tXCHAR *i_pCaption
)
: uX(i_uX)
, uY(i_uY)
, uW(i_uW)
, uH(i_uH)
, pConsole(i_pConsole)
, eWndFgColor(IConsole::eWhite)
, eWndBgColor(IConsole::eDarkGray)
, eInpFgColor(IConsole::eGreen)
, eInpBgColor(IConsole::eLightGray)
, eCurFgColor(IConsole::eWhite)
, eCurBgColor(IConsole::eBlue)
, pCaption(i_pCaption)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CConsoleInput(CConsoleInput::sCfg &i_rConfig)
{
UNUSED_ARG(i_rConfig);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual ~CConsoleInput()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void Redraw()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetCaption(const tXCHAR *i_pCaption)
{
if (m_pCaption)
{
PStrFreeDub(m_pCaption);
m_pCaption = NULL;
}
m_pCaption = i_pCaption ? PStrDub(i_pCaption) : PStrDub(TM("?"));
}
virtual tBOOL ProcessKey(tUINT16 i_wChar)
{
UNUSED_ARG(i_wChar);
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual tBOOL Apply(const tXCHAR *i_pText) = 0;
};
#endif //ICONSOLE_H

56
p7lib/Shared/IFile.h Normal file
View File

@ -0,0 +1,56 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef IFILE_H
#define IFILE_H
////////////////////////////////////////////////////////////////////////////////
class IFile
{
public:
enum eFlags
{
EOPEN = 0x00000001UL,
ECREATE = 0x00000002UL,
EACCESS_WRITE = 0x00000004UL,
EACCESS_READ = 0x00000008UL,
ESHARE_WRITE = 0x00000010UL,
ESHARE_READ = 0x00000020UL
};
public:
virtual tBOOL IsOpened() = 0;
virtual tBOOL Open(const tXCHAR *i_pName, tUINT32 i_dwFlags) = 0;
virtual tBOOL Close(tBOOL i_bFlush) = 0;
virtual tBOOL Set_Position(tUINT64 i_qwOffset) = 0;
virtual tUINT64 Get_Position() = 0;
virtual tUINT64 Get_Size() = 0;
virtual size_t Write(const tUINT8 *i_pBuffer,
size_t i_szBuffer,
tBOOL i_bFlush
) = 0;
virtual size_t Read(tUINT8 *o_pBuffer, size_t i_szBuffer) = 0;
virtual tINT32 Add_Ref() = 0;
virtual tINT32 Release() = 0;
};
#endif //IFILE_H

100
p7lib/Shared/IJournal.h Normal file
View File

@ -0,0 +1,100 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Simple logger to file/stdout /
// Each start it create new file and delete old files if count of files is more/
// than allowed /
// It works in different thread /
////////////////////////////////////////////////////////////////////////////////
#ifndef IJOURNAL_H
#define IJOURNAL_H
#if !defined(JOURNAL_MODULE)
#define JOURNAL_MODULE NULL
#endif
#define JADD(i_pLogger, i_eVerb, ...) if (i_pLogger) (i_pLogger)->Log(i_eVerb,\
JOURNAL_MODULE,\
__FILE__,\
__FUNCTION__,\
__LINE__,\
__VA_ARGS__);
#define JOURNAL_TRACE(i_pLogger, ...) JADD(i_pLogger, IJournal::eLEVEL_TRACE, __VA_ARGS__);
#define JOURNAL_DEBUG(i_pLogger, ...) JADD(i_pLogger, IJournal::eLEVEL_DEBUG, __VA_ARGS__);
#define JOURNAL_INFO(i_pLogger, ...) JADD(i_pLogger, IJournal::eLEVEL_INFO, __VA_ARGS__);
#define JOURNAL_WARNING(i_pLogger, ...) JADD(i_pLogger, IJournal::eLEVEL_WARNING, __VA_ARGS__);
#define JOURNAL_ERROR(i_pLogger, ...) JADD(i_pLogger, IJournal::eLEVEL_ERROR, __VA_ARGS__);
#define JOURNAL_CRITICAL(i_pLogger, ...) JADD(i_pLogger, IJournal::eLEVEL_CRITICAL, __VA_ARGS__);
////////////////////////////////////////////////////////////////////////////////
class IJournal
{
public:
typedef void* hModule;
enum eTime
{
eTIME_YYYYMMDDHHMMSSMS = 0,
eTIME_YYYYMMDDHHMMSS ,
eTIME_HHMMSSMS ,
eTIME_HHMMSS
};
enum eLevel
{
eLEVEL_TRACE = 0,
eLEVEL_DEBUG ,
eLEVEL_INFO ,
eLEVEL_WARNING ,
eLEVEL_ERROR ,
eLEVEL_CRITICAL ,
eLEVEL_COUNT
};
virtual tBOOL Initialize(const tXCHAR *i_pName) = 0;
virtual void Set_Verbosity(IJournal::eLevel i_eVerbosity) = 0;
virtual IJournal::eLevel Get_Verbosity() = 0;
virtual tBOOL Register_Thread(const tXCHAR *i_pName,
tUINT32 i_dwThreadId
) = 0;
virtual tBOOL Unregister_Thread(tUINT32 i_dwThreadId) = 0;
virtual tBOOL Register_Module(const tXCHAR *i_pName,
IJournal::hModule *o_hModule
) = 0;
virtual tBOOL Log(IJournal::eLevel i_eType,
IJournal::hModule i_hModule,
const char *i_pFile,
const char *i_pFunction,
tUINT32 i_dwLine,
const tXCHAR *i_pFormat,
...
) = 0;
virtual tUINT64 Get_Count(IJournal::eLevel i_eType) = 0;
virtual tINT32 Add_Ref() = 0;
virtual tINT32 Release() = 0;
};
#endif //IJOURNAL_H

49
p7lib/Shared/IMEvent.h Normal file
View File

@ -0,0 +1,49 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef IMEVENT_H
#define IMEVENT_H
////////////////////////////////////////////////////////////////////////////////
enum eMEvent_Type
{
EMEVENT_SINGLE_AUTO = 0,
EMEVENT_SINGLE_MANUAL ,
EMEVENT_MULTI
};
#define MEVENT_TIME_OUT (0xFFFFFFF)
#define MEVENT_SIGNAL_0 (0)
////////////////////////////////////////////////////////////////////////////////
class IMEvent
{
public:
//For example
//Init(3, EMEVENT_SINGLE_AUTO, EMEVENT_SINGLE_MANUAL, EMEVENT_MULTI);
virtual tBOOL Init(tUINT8 i_bCount, ...) = 0;
virtual tBOOL Set(tUINT32 i_dwID) = 0;
virtual tBOOL Clr(tUINT32 i_dwID) = 0;
virtual tUINT32 Wait() = 0;
virtual tUINT32 Wait(tUINT32 i_dwMSec) = 0;
};
#endif //IMEVENT_H

View File

@ -0,0 +1,46 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef IPERFORMANCE_INFO_H
#define IPERFORMANCE_INFO_H
////////////////////////////////////////////////////////////////////////////////
class IPerformanceInfo
{
public:
enum eCounter
{
eCounterSystemCpu = 0,
eCounterProcessCpu,
eCounterProcessHandles,
eCounterProcessThreads,
eCounterProcessMemory,
eCounterTotal
};
public:
virtual tBOOL Refresh() = 0;
virtual tINT64 Get(IPerformanceInfo::eCounter i_eCounter) = 0;
virtual tINT32 Add_Ref() = 0;
virtual tINT32 Release() = 0;
};
#endif //IPERFORMANCE_INFO_H

41
p7lib/Shared/ISignal.h Normal file
View File

@ -0,0 +1,41 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef ISIGNAL_H
#define ISIGNAL_H
enum eCrashCode
{
eCrashException,
eCrashPureCall,
eCrashMemAlloc,
eCrashInvalidParameter,
eCrashSignal
};
typedef void (__cdecl *fnCrashHandler)(eCrashCode i_eCode, const void *i_pCrashContext, void *i_pUserContext);
struct stChContext
{
volatile int iInstalled;
volatile int iProcessed;
void *pUserContext;
fnCrashHandler pUserHandler;
};
#endif //ISIGNAL_H

28
p7lib/Shared/Length.h Normal file
View File

@ -0,0 +1,28 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef LENGTH_H
#define LENGTH_H
template <typename Type, size_t i_szLength>
char (&GetCharArray(Type (&i_pArray)[i_szLength]))[i_szLength];
#define LENGTH(i_pArray) (sizeof(GetCharArray(i_pArray)))
#define MEMBER_SIZE(Structure, Memeber) sizeof(((Structure*)0)->Memeber)
#endif //LENGTH_H

71
p7lib/Shared/Lock.h Normal file
View File

@ -0,0 +1,71 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef LOCK_H
#define LOCK_H
///////////////////////////////////////////////////////////////////////////////
#include "PLock.h"
class CLock
{
tLOCK m_hCS;
CLock *m_pLock;
public:
CLock()
: m_pLock(NULL)
{
LOCK_CREATE(m_hCS);
}
CLock(CLock *i_pLock)
: m_pLock(i_pLock)
{
m_pLock->Lock();
}
virtual ~CLock()
{
if (NULL == m_pLock)
{
LOCK_DESTROY(m_hCS);
}
else
{
m_pLock->Unlock();
m_pLock = NULL;
}
}
inline void Lock()
{
LOCK_ENTER(m_hCS);
}
inline tBOOL Try()
{
return LOCK_TRY(m_hCS);
}
inline void Unlock()
{
LOCK_EXIT(m_hCS);
}
};
#endif //LOCK_H

View File

@ -0,0 +1,144 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PATOMIC_H
#define PATOMIC_H
#ifdef __ARM_ARCH_5TEJ__
//Source:
//http://svn.dd-wrt.com/browser/src/linux/xscale/linux-2.6.23/arch/arm/kernel/entry-armv.S?rev=8329
// Reference prototype:
//
// int __kernel_cmpxchg(int oldval, int newval, int *ptr)
//
// Input:
//
// r0 = oldval
// r1 = newval
// r2 = ptr
// lr = return address
//
// Output:
//
// r0 = returned value (zero or non-zero)
// C flag = set if r0 == 0, clear if r0 != 0
//
// Clobbered:
//
// r3, ip, flags
//
// Definition and user space usage example:
//
// typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
// #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
//
// Atomically store newval in *ptr if *ptr is equal to oldval for user space.
// Return zero if *ptr was changed or non-zero if no exchange happened.
// The C flag is also set if *ptr was changed to allow for assembly
// optimization in the calling code.
//
// Notes:
//
// - This routine already includes memory barriers as needed.
//
// - A failure might be transient, i.e. it is possible, although unlikely,
// that "failure" be returned even if *ptr == oldval.
//
//Another implementations:
//http://upc.lbl.gov/web-translator/2.8.0/runtime/inst/opt/include/gasnet_atomic_bits.h
//http://upc.lbl.gov/web-translator/ - in last versions very interesting
// For arm 6 & 7:
//http://lxr.free-electrons.com/source/arch/arm/include/asm/atomic.h
#define ATOMIC_ADD(ptr, val) \
__extension__ ({ volatile register tINT32 *__ptr asm("r2") = (ptr); \
register tINT32 __result asm("r1"); \
asm volatile ( \
"1: @ atomic_add\n\t" \
"ldr r0, [r2]\n\t" \
"mov r3, #0xffff0fff\n\t" \
"add lr, pc, #4\n\t" \
"add r1, r0, %2\n\t" \
"add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
"bcc 1b" \
: "=&r" (__result) \
: "r" (__ptr), "rIL" (val) \
: "r0","r3","ip","lr","cc","memory" ); \
__result; })
#define ATOMIC_SUB(ptr, val) \
__extension__ ({ volatile register tINT32 *__ptr asm("r2") = (ptr); \
register tINT32 __result asm("r1"); \
asm volatile ( \
"1: @ atomic_add\n\t" \
"ldr r0, [r2]\n\t" \
"mov r3, #0xffff0fff\n\t" \
"add lr, pc, #4\n\t" \
"sub r1, r0, %2\n\t" \
"add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
"bcc 1b" \
: "=&r" (__result) \
: "r" (__ptr), "rIL" (val) \
: "r0","r3","ip","lr","cc","memory" ); \
__result; })
//#ifdef __ARM_ARCH_5TEJ__
#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_6__)
#define ATOMIC_ADD(ptr, val) \
__extension__ ({ int32_t tmp; \
int result; \
__asm__ __volatile__("@ atomic_add\n" \
"1: ldrex %0, [%3]\n" \
" add %0, %0, %4\n" \
" strex %1, %0, [%3]\n" \
" teq %1, #0\n" \
" bne 1b" \
: "=&r" (result), "=&r" (tmp), "+Qo" (*ptr) \
: "r" (ptr), "Ir" (val) \
: "cc"); \
result;})
#define ATOMIC_SUB(ptr, val) \
__extension__ ({ unsigned long tmp; \
int result; \
__asm__ __volatile__("@ atomic_sub\n" \
"1: ldrex %0, [%3]\n" \
" sub %0, %0, %4\n" \
" strex %1, %0, [%3]\n" \
" teq %1, #0\n" \
" bne 1b" \
: "=&r" (result), "=&r" (tmp), "+Qo" (*ptr) \
: "r" (ptr), "Ir" (val) \
: "cc"); \
result;})
#else //#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_6__)
#define ATOMIC_ADD(io_Val, i_Add) __sync_add_and_fetch(io_Val, i_Add)
#define ATOMIC_SUB(io_Val, i_Add) __sync_sub_and_fetch(io_Val, i_Add)
#define ATOMIC_SET(io_Var, i_Val) __sync_lock_test_and_set(io_Var, i_Val)
#endif //#ifdef __ARM_ARCH_5TEJ__
#define ATOMIC_INC(io_Val) ATOMIC_ADD(io_Val, 1)
#define ATOMIC_DEC(io_Val) ATOMIC_SUB(io_Val, 1)
#endif //PATOMIC_H

View File

@ -0,0 +1,85 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PCRC32_H
#define PCRC32_H
////////////////////////////////////////////////////////////////////////////////
//Get_CRC32
//This function implement 2 calculation kinds:
// * AT&T assembler for X86 architecture for GNU C compiler
// * standard C function for all other cases like X64 or ARM
//Assembler code if faster than generated by GCC (o2) up to 1% it is not a lot
//but for big amount of data and often calculation is enough to use it.
static UNUSED_FUNC tUINT32 Get_CRC32(tUINT8 *i_pData, size_t i_szCount)
{
tUINT32 l_dwResult = 0xFFFFFFFF;
if ( (NULL == i_pData)
|| (0 >= i_szCount)
)
{
return l_dwResult;
}
#if defined(__i386__) && defined(__GNUC__) && !defined(__PIC__)
// Register use:
// eax - CRC32 value
// ebx - a lot of things
// ecx - CRC32 value
// edx - address of end of buffer
// esi - address of start of buffer
// edi - CRC32 table
__asm__("push %%esi;" // Save the esi and edi registers
"push %%edi;"
//"movl l_dwResult, %%ecx;" do it already by constraints
//"movl g_ppCRC32_Table, %%edi;"
"leal (%%esi,%%ebx),%%edx;" // Calculate the end of the buffer
"crc32loop:;"
"xorl %%eax, %%eax;" // Clear the eax register"
"movb (%%esi), %%bl;"
"movb %%cl, %%al;" // Copy crc value into eax
"incl %%esi;" // Advance the source pointer
"xorb %%bl, %%al;" // Create the index into the CRC32 table
"shr $8, %%ecx;"
"movl (%%edi, %%eax, 4), %%ebx;" // Get the value out of the table
"xorl %%ebx, %%ecx;" // xor with the current byte
"cmpl %%edx, %%esi;" // Have we reached the end of the buffer?
"jne crc32loop;"
"pop %%edi;"
"pop %%esi;"
//output
:"=c"(l_dwResult)
//input
:"D"(g_ppCRC32_Table), "c"(l_dwResult), "S"(i_pData), "b"(i_szCount)
);
#else
for (size_t l_szI = 0; l_szI < i_szCount; l_szI ++)
{
l_dwResult = g_ppCRC32_Table[(l_dwResult ^ i_pData[l_szI]) & 0xFF ] ^ (l_dwResult >> 8);
}
/* Suppress warning that this is not used */
(void)g_ppCRC32_Table;
#endif
return l_dwResult;
}
#endif //PCRC32_H

View File

@ -0,0 +1,712 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PCONSOLE_H
#define PCONSOLE_H
#include <sys/ioctl.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include "IConsole.h"
#include "RBTree.h"
#include "AList.h"
////////////////////////////////////////////////////////////////////////////////
//Is_Key_Hit
static __attribute__ ((unused)) tBOOL Is_Key_Hit(void)
{
struct termios oldt, newt;
int ch;
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch, stdin);
return TRUE;
}
return FALSE;
}//Is_Key_Hit
////////////////////////////////////////////////////////////////////////////////
//Get_Char
static __attribute__ ((unused)) tXCHAR Get_Char()
{
return getchar();
}//Get_Char
////////////////////////////////////////////////////////////////////////////////
//SetEchoOff
static __attribute__ ((unused)) void Set_EchoOff(tBOOL i_bOff)
{
struct termios termInfo;
if (-1 == tcgetattr(0,&termInfo))
{
return;
}
if (i_bOff)
{
termInfo.c_lflag &= ~ECHO; //turn off ECHO
}
else
{
termInfo.c_lflag |= ECHO; //turn on ECHO
}
tcsetattr(0, 0, &termInfo);
}//Get_Char
////////////////////////////////////////////////////////////////////////////////
struct stKeyMap
{
tUINT16 wKey;
tUINT64 qwHash;
stKeyMap(tUINT16 i_wKey,
tUINT8 i_pv7,
tUINT8 i_pv6,
tUINT8 i_pv5,
tUINT8 i_pv4,
tUINT8 i_pv3,
tUINT8 i_pv2,
tUINT8 i_pv1,
tUINT8 i_pv0
)
: wKey(i_wKey), qwHash(0)
{
qwHash = ((tUINT64)i_pv7 << 56)
| ((tUINT64)i_pv6 << 48)
| ((tUINT64)i_pv5 << 40)
| ((tUINT64)i_pv4 << 32)
| ((tUINT64)i_pv3 << 24)
| ((tUINT64)i_pv2 << 16)
| ((tUINT64)i_pv1 << 8)
| (tUINT64)i_pv0;
}
stKeyMap(tUINT16 i_wKey,
tUINT8 i_pv4,
tUINT8 i_pv3,
tUINT8 i_pv2,
tUINT8 i_pv1,
tUINT8 i_pv0
)
: wKey(i_wKey), qwHash(0)
{
qwHash = ((tUINT64)i_pv4 << 32)
| ((tUINT64)i_pv3 << 24)
| ((tUINT64)i_pv2 << 16)
| ((tUINT64)i_pv1 << 8)
| (tUINT64)i_pv0;
}
stKeyMap(tUINT16 i_wKey,
tUINT8 i_pv3,
tUINT8 i_pv2,
tUINT8 i_pv1,
tUINT8 i_pv0
)
: wKey(i_wKey), qwHash(0)
{
qwHash = ((tUINT64)i_pv3 << 24)
| ((tUINT64)i_pv2 << 16)
| ((tUINT64)i_pv1 << 8)
| (tUINT64)i_pv0;
}
stKeyMap(tUINT16 i_wKey,
tUINT8 i_pv2,
tUINT8 i_pv1,
tUINT8 i_pv0
)
: wKey(i_wKey), qwHash(0)
{
qwHash = ((tUINT64)i_pv2 << 16)
| ((tUINT64)i_pv1 << 8)
| (tUINT64)i_pv0;
}
stKeyMap(tUINT16 i_wKey,
tUINT8 i_pv1,
tUINT8 i_pv0
)
: wKey(i_wKey), qwHash(0)
{
qwHash = ((tUINT64)i_pv1 << 8)
| (tUINT64)i_pv0;
}
};
////////////////////////////////////////////////////////////////////////////////
//CKeysTree
class CKeysList
: public CListPool<char>
{
protected:
virtual tBOOL Data_Release(char i_pData)
{
UNUSED_ARG(i_pData);
return TRUE;
}
};
////////////////////////////////////////////////////////////////////////////////
//CKeysTree
class CKeysTree:
public CRBTree<stKeyMap*, tUINT64>
{
public:
////////////////////////////////////////////////////////////////////////////
//~CKeysTree
virtual ~CKeysTree()
{
Clear();
}//~CRBTree
protected:
////////////////////////////////////////////////////////////////////////////
virtual tBOOL Data_Release(stKeyMap* i_pData)
{
delete i_pData;
return TRUE; //memory used from pool, not necessary to return
}// Data_Release
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey < i_pData::key)
//FALSE - otherwise
tBOOL Is_Key_Less(tUINT64 i_pKey, stKeyMap *i_pData)
{
return (i_pKey < i_pData->qwHash);
}
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey == i_pData::key)
//FALSE - otherwise
tBOOL Is_Qual(tUINT64 i_pKey, stKeyMap *i_pData)
{
return (i_pKey == i_pData->qwHash);
}
};//CDesc_Tree
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CConsole
: public IConsole
{
tUINT32 m_pCl[IConsole::eColorsMax];
size_t m_szText;
tXCHAR *m_pText;
tXCHAR *m_pEmpty;
size_t m_szEmpty;
CKeysTree m_pKeys;
CKeysList m_cKeysList;
public:
CConsole()
{
m_szText = 32768;
m_pText = (tXCHAR*)malloc(m_szText * sizeof(tXCHAR));
m_szEmpty = 0;
m_pEmpty = NULL;
AllocEmptyString(1024);
Set_EchoOff(TRUE);
//https://en.wikipedia.org/wiki/ANSI_escape_code
m_pCl[IConsole::eBlack] = 0;
m_pCl[IConsole::eBlue] = 12;
m_pCl[IConsole::eGreen] = 40;
m_pCl[IConsole::eCyan] = 51;
m_pCl[IConsole::eRed] = 124;
m_pCl[IConsole::eMagenta] = 129;
m_pCl[IConsole::eBrown] = 94;
m_pCl[IConsole::eLightGray] = 252;
m_pCl[IConsole::eDarkGray] = 244;
m_pCl[IConsole::eLightBlue] = 33;
m_pCl[IConsole::eLightGreen] = 48;
m_pCl[IConsole::eLightCyan] = 195;
m_pCl[IConsole::eLightRed] = 196;
m_pCl[IConsole::eLightMagenta] = 201;
m_pCl[IConsole::eYellow] = 11;
m_pCl[IConsole::eWhite] = 15;
stKeyMap *l_pKey = new stKeyMap(eKeyArrowLeft, 27,91,68);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyArrowRight, 27,91,67);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyArrowDown, 27,91,66);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyArrowUp, 27,91,65);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyPageUp, 27,91,53,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyPageDown, 27,91,54,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyHome, 27,79,72);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyEnd, 27,79,70);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyDel, 27,91,51,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyInsert, 27,91,50,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF1, 27,79,80);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF2, 27,79,81);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF3, 27,79,82);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF4, 27,79,83);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF5, 27,91,49,53,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF6, 27,91,49,55,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF7, 27,91,49,56,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF8, 27,91,49,57,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF9, 27,91,50,48,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF10, 27,91,50,49,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF11, 27,91,50,51,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
l_pKey = new stKeyMap(eKeyF12, 27,91,50,52,126);
m_pKeys.Push(l_pKey, l_pKey->qwHash);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual ~CConsole()
{
if (m_pText)
{
free(m_pText);
m_pText = NULL;
}
if (m_pEmpty)
{
free(m_pEmpty);
m_pEmpty = NULL;
}
m_pKeys.Clear();
m_cKeysList.Clear(TRUE);
Set_EchoOff(FALSE);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL SetCursor(tUINT32 i_uX, tUINT32 i_uY)
{
printf("\033[%d;%dH", i_uY+1, i_uX+1);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetCursorX()
{
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL GetInput(IConsole::sInput &o_rInput)
{
while (Is_Key_Hit())
{
m_cKeysList.Add_After(m_cKeysList.Get_Last(), Get_Char());
}
if (!m_cKeysList.Count())
{
return FALSE;
}
char l_cVal = m_cKeysList.Get_Data(m_cKeysList.Get_First());
tBOOL l_bReturn = FALSE;
o_rInput.eEvent = IConsole::eKey;
o_rInput.stKey.bDown = TRUE;
o_rInput.stKey.uControls = 0;
o_rInput.stKey.wCount = 1;
o_rInput.stKey.wKey = l_cVal;
if ( (27 == l_cVal) //escape sequence
&& (m_cKeysList.Count())
)
{
tUINT64 l_qwHash = 0;
pAList_Cell l_pEl = m_cKeysList.Get_First();
stKeyMap *l_pKey = NULL;
tUINT32 l_uiCount = 0;
while ( (l_pEl)
&& (8 > l_uiCount)
)
{
l_uiCount++;
l_qwHash = (l_qwHash << 8) | m_cKeysList.Get_Data(l_pEl);
l_pKey = m_pKeys.Find(l_qwHash);
if (l_pKey)
{
o_rInput.stKey.wKey = l_pKey->wKey;
l_bReturn = TRUE;
while (l_pEl) //clear esc sequence used to identefy key
{
pAList_Cell l_pPrevEl = m_cKeysList.Get_Prev(l_pEl);
m_cKeysList.Del(l_pEl, TRUE);
l_pEl = l_pPrevEl;
}
break;
}
else
{
l_pEl = m_cKeysList.Get_Next(l_pEl);
}
}
}
if (!l_bReturn) //if it is not esc sequence - get first char and return it
{
if (10 == l_cVal)
{
o_rInput.stKey.wKey = (tUINT16)IConsole::eKeyEnter;
}
else if (9 == l_cVal)
{
o_rInput.stKey.wKey = (tUINT16)IConsole::eKeyTab;
}
else if (8 == l_cVal)
{
o_rInput.stKey.wKey = (tUINT16)IConsole::eKeyBackSpace;
}
l_bReturn = TRUE;
m_cKeysList.Del(m_cKeysList.Get_First(), TRUE);
}
return l_bReturn;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetCursorY()
{
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetWidth()
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return w.ws_col;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetHeight()
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return w.ws_row;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL SetTextAttr(IConsole::eColor i_eFg, IConsole::eColor i_eBg)
{
if ( (i_eFg < 0)
|| (i_eFg >= IConsole::eColorsMax)
|| (i_eBg < 0)
|| (i_eBg >= IConsole::eColorsMax)
)
{
return FALSE;
}
printf("\x1b[38;5;%dm\x1b[48;5;%dm", m_pCl[i_eFg], m_pCl[i_eBg]);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL Clear()
{
printf("\033[H\033[J");
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL Clear(tUINT32 i_uX, tUINT32 i_uY, tUINT32 i_uW, tUINT32 i_uH, IConsole::eColor i_eBg)
{
tUINT32 l_uiW = GetWidth();
tUINT32 l_uiH = GetHeight();
if ( (i_uX > l_uiW)
|| (i_uY > l_uiH)
|| (!i_uW)
|| (!i_uH)
|| (i_uW >= m_szEmpty)
)
{
return FALSE;
}
if ((i_uX + i_uW) > l_uiW)
{
i_uW = l_uiW - i_uX;
}
if ((i_uY + i_uH) > l_uiH)
{
i_uH = l_uiH - i_uY;
}
if (i_uW > m_szEmpty)
{
if (!AllocEmptyString((size_t)i_uW))
{
return FALSE;
}
}
if (!SetTextAttr(IConsole::eBlack, i_eBg))
{
return FALSE;
}
SetCursor(i_uX, i_uY);
tUINT32 l_uiXOld = i_uX;
tUINT32 l_uiYOld = i_uY;
while (i_uH--)
{
SetCursor(i_uX, i_uY++);
m_pEmpty[i_uW] = 0;
WriteTextB(m_pEmpty, i_uW);
m_pEmpty[i_uW] = ' ';
}
SetCursor(l_uiXOld, l_uiYOld);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
size_t WriteTextB(const tXCHAR *i_pText, size_t i_szText)
{
UNUSED_ARG(i_szText);
return (size_t)printf("%s", i_pText);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
size_t WriteTextB(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
size_t i_szOffset,
tXCHAR *i_pText,
size_t i_szText,
size_t i_szTextMax
)
{
if ( (i_szLenMin > i_szLenMax)
|| (!i_pText)
|| (8 >= i_szTextMax)
|| (i_szText >= i_szTextMax)
)
{
return 0;
}
if (!SetTextAttr(i_eFg, i_eBg))
{
return 0;
}
tXCHAR *l_pText = i_pText;
if (!i_szText)
{
i_szText = PStrLen(i_pText);
}
//if there is offset, recalculate all inputs
if (i_szOffset)
{
if (i_szOffset < i_szText) //set sext offset and recalculate all
{
l_pText = l_pText + i_szOffset;
i_szText -= i_szOffset;
i_szTextMax -= i_szOffset;
i_szOffset = 0;
*l_pText = TM('<');
}
else //if (i_szOffset >= i_szText)
{
l_pText = m_pText;
*l_pText = TM('<');
i_szText = 1;
i_szTextMax= m_szText;
}
}
if (i_szText > i_szLenMax)
{
i_szText = i_szLenMax;
l_pText[i_szText-1] = TM('>');
}
else if (i_szText < i_szLenMin)
{
if (i_szTextMax < (i_szLenMin + 1))
{
PStrNCpy(m_pText, m_szText, l_pText, i_szText);
l_pText = m_pText;
i_szTextMax = m_szText;
}
tXCHAR *l_pIter = l_pText + i_szText;
while (i_szText < i_szLenMin)
{
*l_pIter = TM(' ');
l_pIter ++;
i_szText++;
}
}
if (i_szText < i_szTextMax)
{
l_pText[i_szText] = 0;
}
else
{
l_pText[i_szText-1] = 0;
}
return (size_t)printf("%s", l_pText);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
size_t WriteTextF(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
size_t i_szOffset,
const tXCHAR *i_pFormat,
va_list i_pVA
)
{
int l_iReturn = PVsnprintf(m_pText, m_szText, i_pFormat, i_pVA);
if (0 > l_iReturn)
{
return 0;
}
return WriteTextB(i_eFg, i_eBg, i_szLenMin, i_szLenMax, i_szOffset, m_pText, (size_t)l_iReturn, m_szText);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL Present()
{
return TRUE;
}
protected:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL AllocEmptyString(size_t i_szEmpty)
{
if (m_pEmpty)
{
free(m_pEmpty);
}
if (i_szEmpty > 4096)
{
i_szEmpty = 4096;
}
m_szEmpty = i_szEmpty;
m_pEmpty = (tXCHAR*)malloc(m_szEmpty * sizeof(tXCHAR));
if (!m_pEmpty)
{
return FALSE;
}
tXCHAR *l_pEmpty = m_pEmpty;
size_t l_szIterator = m_szEmpty;
while (l_szIterator--)
{
*l_pEmpty = TM(' ');
l_pEmpty++;
}
return TRUE;
}
};
#endif //PCONSOLE_H

View File

@ -0,0 +1,229 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
//http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus
#ifndef PCRASH_DUMP_H
#define PCRASH_DUMP_H
#include "GTypes.h"
#include "Length.h"
#include "PString.h"
#include "WString.h"
#include "AList.h"
#include "PAtomic.h"
#include "ISignal.h"
#define CH_DESC_FILE_EXT TM("dsc")
struct sCdContext
{
char *pBuffer;
size_t szBuffer;
size_t szPathMax;
char *pDescFileName;
};
////////////////////////////////////////////////////////////////////////////////
//CdCreateDumpTxt
static __attribute__ ((unused)) void CdCreateDumpTxt(sCdContext *i_pCdContext, const char *i_pText, tUINT64 i_qwCode)
{
UNUSED_ARG(i_pCdContext);
UNUSED_ARG(i_pText);
UNUSED_ARG(i_qwCode);
}//CdCreateDumpTxt
////////////////////////////////////////////////////////////////////////////////
//CdWrite
static __attribute__ ((unused)) void CdWrite(void *i_pCdInfo, eCrashCode i_eCode, const void *i_pContext)
{
UNUSED_ARG(i_pCdInfo);
UNUSED_ARG(i_eCode);
UNUSED_ARG(i_pContext);
//sCdContext *l_pCrush = (sCdContext*)i_pCdInfo;
//
//if ( IBreakdownNotify::eException == i_eCode )
//{
// if (i_pContext)
// {
// _EXCEPTION_POINTERS l_sException = *(_EXCEPTION_POINTERS*)(i_pContext);
//
// char l_pText[128];
// sprintf_s(l_pText,
// _countof(l_pText),
// "Exception 0x%08X",
// l_sException.ExceptionRecord->ExceptionCode
// );
//
// tUINT64 l_qwCode = CdCreateDumpBin(&l_sException);
// CdCreateDumpTxt(l_pCrush, l_pText, l_qwCode);
//
// }
//}
//else if (IBreakdownNotify::ePureCall == i_eCode)
//{
// CdCreateDumpTxt(l_pCrush, (const char*)i_pContext, i_eCode);
//}
//else if (IBreakdownNotify::eMemAlloc == i_eCode)
//{
// CdCreateDumpTxt(l_pCrush, (const char*)i_pContext, i_eCode);
//}
//else if (IBreakdownNotify::eInvalidParameter == i_eCode)
//{
// CdCreateDumpTxt(l_pCrush, (const char*)i_pContext, i_eCode);
//}
//else if ( IBreakdownNotify::eSignal >= i_eCode)
//{
// CdCreateDumpTxt(l_pCrush, (const char*)i_pContext, i_eCode);
//}
}//CdWrite
////////////////////////////////////////////////////////////////////////////////
//CdCleanUp
static __attribute__ ((unused)) void CdCleanUp(const tXCHAR *i_pDir, unsigned int i_dwMax_Count)
{
CBList<CWString*> l_cFiles;
CWString l_cDir;
l_cDir.Set(i_pDir);
CFSYS::Enumerate_Files(&l_cFiles, &l_cDir, TM("*.") CH_DESC_FILE_EXT, 0);
//sort files - first is oldest, last is newest !
pAList_Cell l_pStart = NULL;
tUINT32 l_dwDirLen = l_cDir.Length();
while ((l_pStart = l_cFiles.Get_Next(l_pStart)))
{
pAList_Cell l_pMin = l_pStart;
pAList_Cell l_pIter = l_pStart;
while ((l_pIter = l_cFiles.Get_Next(l_pIter)))
{
CWString *l_pPathM = l_cFiles.Get_Data(l_pMin);
CWString *l_pPathI = l_cFiles.Get_Data(l_pIter);
tXCHAR *l_pNameM = l_pPathM->Get() + l_dwDirLen;
tXCHAR *l_pNameI = l_pPathI->Get() + l_dwDirLen;
if (0 < PStrICmp(l_pNameM, l_pNameI))
{
l_pMin = l_pIter;
}
}
if (l_pMin != l_pStart)
{
l_cFiles.Extract(l_pMin);
l_cFiles.Put_After(l_cFiles.Get_Prev(l_pStart), l_pMin);
l_pStart = l_pMin;
}
} //while (l_pStart = m_cFiles.Get_Next(l_pStart))
//delete oldest files
while (l_cFiles.Count() > i_dwMax_Count)
{
l_pStart = l_cFiles.Get_First();
if (l_pStart)
{
CWString *l_pPath = l_cFiles.Get_Data(l_pStart);
//delete description file
CFSYS::Delete_File(l_pPath->Get());
l_cFiles.Del(l_pStart, TRUE);
}
}//while (l_cFiles.Count() > i_dwMax_Count)
}//CdCleanUp
////////////////////////////////////////////////////////////////////////////////
//CdAlloc
static __attribute__ ((unused)) void *CdAlloc(const tXCHAR *i_pFolder)
{
sCdContext *l_pCrush = (sCdContext*)malloc(sizeof(sCdContext));
tBOOL l_bError = FALSE;
if ( !l_pCrush )
{
return NULL;
}
////////////////////////////////////////////////////////////////////////////
//initialize parameters
memset(l_pCrush, 0, sizeof(sCdContext));
l_pCrush->szBuffer = 32768;
l_pCrush->pBuffer = (char*)malloc(l_pCrush->szBuffer * sizeof(char));
l_pCrush->szPathMax = 16384;
l_pCrush->pDescFileName = (tXCHAR*)malloc(l_pCrush->szPathMax * sizeof(tXCHAR));
if ( (NULL == l_pCrush->pBuffer)
|| (NULL == l_pCrush->pDescFileName)
)
{
l_bError = TRUE;
goto l_lblExit;
}
CdCleanUp(i_pFolder, 5);
l_lblExit:
if ( (l_bError)
&& (l_pCrush)
)
{
free(l_pCrush);
l_pCrush = NULL;
}
return l_pCrush;
}//CH_Install
////////////////////////////////////////////////////////////////////////////////
//CdFree
static __attribute__ ((unused)) void CdFree(void *i_pCdInfo)
{
sCdContext *l_pCrush = (sCdContext*)i_pCdInfo;
if ( !l_pCrush )
{
return;
}
if (l_pCrush->pBuffer)
{
free(l_pCrush->pBuffer);
l_pCrush->pBuffer = NULL;
}
if (l_pCrush->pDescFileName)
{
free(l_pCrush->pDescFileName);
l_pCrush->pDescFileName = NULL;
}
}//CdFree
#endif //PCRASH_DUMP_H

View File

@ -0,0 +1,89 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#include <netinet/in.h>
//#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
#include "GTypes.h"
#include "AList.h"
class CDnsTxt: public CAList<tACHAR*>
{
protected:
virtual tBOOL Data_Release(tACHAR *i_pStr)
{
if (NULL == i_pStr)
{
return FALSE;
}
free(i_pStr);
return TRUE;
}//CListBase::Data_Release
};
tBOOL static inline GetDnsTxtRecords(const tACHAR *i_pDomain, CDnsTxt &io_rList)
{
const size_t l_szTxtBuf = 2048;
u_char l_pTxtBuf[l_szTxtBuf];
int l_iResult = -1;
int l_iLen = 0;
ns_msg l_stMsg = {0};
ns_rr l_stRr = {0};
tUINT16 l_sMsgCount= 0;
l_iLen = res_query(i_pDomain, ns_c_in, ns_t_txt, l_pTxtBuf, (int)l_szTxtBuf);
if (l_iLen < 0)
{
return FALSE;
}
l_iResult = ns_initparse(l_pTxtBuf, l_iLen, &l_stMsg);
if (l_iResult < 0)
{
return FALSE;
}
l_sMsgCount = ns_msg_count(l_stMsg, ns_s_an);
for (tUINT16 i = 0; i < l_sMsgCount; i++)
{
if ( (0 == ns_parserr(&l_stMsg, ns_s_an, i, &l_stRr))
&& (l_stRr.rdlength)
)
{
tACHAR *l_pText = (tACHAR*)malloc(l_stRr.rdlength-1);
if (l_pText)
{
//TXT record RDATA format is:
// length, 1 byte
// string, <length bytes>
// length2, 1 byte
// string2, <length2 bytes>
// etc.
memcpy(l_pText, (tACHAR *)l_stRr.rdata + 1, l_stRr.rdlength - 1);
l_pText[l_stRr.rdlength - 1] = 0;
io_rList.Push_Last(l_pText);
}
}
}
return (io_rList.Count() != 0);
}

View File

@ -0,0 +1,291 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PFILE_H
#define PFILE_H
#define PFILE_INVALID_HANDLE (-1)
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
//Headers have to be included in application source files
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define GetLastError() errno
//UTF-8 text file header - {0xEF, 0xBB, 0xBF}
////////////////////////////////////////////////////////////////////////////////
class CPFile
: public IFile //virtual
{
volatile tINT32 m_iRCnt;
//tLOCK m_hCS;
int m_iFile;
public:
////////////////////////////////////////////////////////////////////////////
CPFile()
: m_iRCnt(1)
, m_iFile(-1)
{
//LOCK_CREATE(m_hCS);
}
////////////////////////////////////////////////////////////////////////////
virtual ~CPFile()
{
//LOCK_DESTROY(m_hCS);
Close(FALSE);
}
////////////////////////////////////////////////////////////////////////////
tBOOL IsOpened()
{
return (PFILE_INVALID_HANDLE != m_iFile);
}
////////////////////////////////////////////////////////////////////////////
tBOOL Open(const tXCHAR *i_pName, tUINT32 i_dwFlags)
{
//create file if it is not exists, else - open, heh ... engineers
//friendly POSIX API :-(
int l_iFlags = O_CREAT;
mode_t l_tMode = 0;
if (PFILE_INVALID_HANDLE != m_iFile)
{
Close(TRUE);
}
l_iFlags |= O_RDWR;
if (ECREATE & i_dwFlags)
{
l_iFlags |= O_TRUNC;
if (EACCESS_WRITE & i_dwFlags)
{
l_tMode = S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH;
}
else if (EACCESS_READ & i_dwFlags)
{
l_tMode = S_IRUSR | S_IRGRP | S_IROTH;
}
}
m_iFile = open(i_pName, l_iFlags, l_tMode);
return (PFILE_INVALID_HANDLE != m_iFile) ? TRUE : FALSE;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Close(tBOOL i_bFlush)
{
tBOOL l_bReturn = TRUE;
int l_iTemp = PFILE_INVALID_HANDLE;
if (PFILE_INVALID_HANDLE == m_iFile)
{
return TRUE;
}
if (i_bFlush)
{
if (-1 == fsync(m_iFile))
{
l_bReturn = FALSE;
goto l_lExit;
}
}
l_iTemp = m_iFile;
m_iFile = PFILE_INVALID_HANDLE;
if (-1 == close(l_iTemp))
{
l_bReturn = FALSE;
goto l_lExit;
}
l_lExit:
return l_bReturn;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Set_Position(tUINT64 i_qwOffset)
{
if (PFILE_INVALID_HANDLE == m_iFile)
{
return FALSE;
}
if ((off64_t)i_qwOffset != lseek64(m_iFile, (off64_t)i_qwOffset, SEEK_SET))
{
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
tUINT64 Get_Position()
{
if (PFILE_INVALID_HANDLE == m_iFile)
{
return 0ULL;
}
return (off64_t)lseek64(m_iFile, 0LL, SEEK_CUR);
}
////////////////////////////////////////////////////////////////////////////
tUINT64 Get_Size()
{
if (PFILE_INVALID_HANDLE == m_iFile)
{
return 0ULL;
}
off64_t l_llPos = lseek64(m_iFile, 0LL, SEEK_CUR);
off64_t l_llSize = lseek64(m_iFile, 0LL, SEEK_END);
lseek64(m_iFile, l_llPos, SEEK_SET);
return l_llSize;
}
////////////////////////////////////////////////////////////////////////////
size_t Write(const tUINT8 *i_pBuffer, size_t i_szBuffer, tBOOL i_bFlush)
{
if ( (PFILE_INVALID_HANDLE == m_iFile)
|| (NULL == i_pBuffer)
|| (0 == i_szBuffer)
)
{
return 0ULL;
}
ssize_t l_szRes = 0;
size_t l_szWritten = 0;
int l_iError = 0;
while (l_szWritten < i_szBuffer)
{
l_szRes = write(m_iFile, i_pBuffer + l_szWritten, i_szBuffer - l_szWritten);
if (0 < l_szRes)
{
l_szWritten += (size_t)l_szRes;
}
else
{
l_iError = errno;
printf("%d", l_iError);
break;
}
}
if ( (i_bFlush)
&& (l_szWritten)
)
{
fsync(m_iFile);
}
return l_szWritten;
}
////////////////////////////////////////////////////////////////////////////
size_t Read(tUINT8 *o_pBuffer, size_t i_szBuffer)
{
if ( (PFILE_INVALID_HANDLE == m_iFile)
|| (NULL == o_pBuffer)
|| (0 == i_szBuffer)
)
{
return 0ULL;
}
size_t l_szRead = 0;
ssize_t l_szRes = 0;
while (l_szRead < i_szBuffer)
{
l_szRes = read(m_iFile, o_pBuffer + l_szRead, i_szBuffer - l_szRead);
if (0 < l_szRes)
{
l_szRead += (size_t)l_szRes;
}
else
{
break;
}
}
return l_szRead;
}
////////////////////////////////////////////////////////////////////////////
tINT32 Add_Ref()
{
return ATOMIC_INC(&m_iRCnt);
}
////////////////////////////////////////////////////////////////////////////
tINT32 Release()
{
volatile tINT32 l_iReturn = ATOMIC_DEC(&m_iRCnt);
if (0 >= l_iReturn)
{
delete this;
}
return l_iReturn;
}
};
#endif //PFILE_H
/*
CPFile l_cFile;
const tUINT8 l_pHeader[] = {0xEF, 0xBB, 0xBF};
const char l_pText[] = "Some Text For me !\xD\xA Another Text\xD\xA Third Text";
tUINT64 l_qwCount = 0;
tUINT8 l_pBuffer[256] = {0};
l_cFile.Open("./ABC.txt", IFile::ECREATE | IFile::ESHARE_WRITE);
l_qwCount = l_cFile.Write(l_pHeader, LENGTH(l_pHeader), FALSE);
l_qwCount = l_cFile.Write((tUINT8*)l_pText, LENGTH(l_pText) - 1, TRUE);
l_qwCount = l_cFile.Get_Size();
l_cFile.Set_Position(0);
l_qwCount = l_cFile.Read(l_pBuffer, LENGTH(l_pBuffer));
l_cFile.Close(TRUE);
*/

View File

@ -0,0 +1,362 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PFILESYSTEM_H
#define PFILESYSTEM_H
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fnmatch.h>
#include <pwd.h>
class CFSYS
{
public:
////////////////////////////////////////////////////////////////////////////
//Directory_Exists
static tBOOL Directory_Exists(const tACHAR *i_pPath)
{
struct stat l_sStat;
l_sStat.st_mode = 0;
if (0 == stat(i_pPath, &l_sStat))
{
if (0 != (l_sStat.st_mode & S_IFDIR))
{
return TRUE;
}
}
return FALSE;
}//Directory_Exists
////////////////////////////////////////////////////////////////////////////
//Directory_Create
static tBOOL Directory_Create(const tACHAR *i_pDir)
{
if (NULL == i_pDir)
{
return FALSE;
}
char *l_pDir = (char *)malloc(strlen(i_pDir) + 1);
char *l_pIter = l_pDir;
if (NULL == l_pDir)
{
return FALSE;
}
strcpy(l_pDir, i_pDir);
while (*l_pIter)
{
if ('/' == (*l_pIter))
{
*l_pIter = 0;
if ( (FALSE == CFSYS::Directory_Exists(l_pDir))
&& (l_pIter != l_pDir)
)
{
mkdir(l_pDir, S_IRWXU | S_IRWXG | S_IROTH);
}
*l_pIter = '/';
}
l_pIter++;
}
free(l_pDir);
l_pDir = NULL;
mkdir(i_pDir, S_IRWXU | S_IRWXG | S_IROTH);
return Directory_Exists((tACHAR*)i_pDir);
}//Directory_Create
////////////////////////////////////////////////////////////////////////////
//Directory_Delete
static tBOOL Directory_Delete(const tACHAR *i_pDir)
{
if (NULL == i_pDir)
{
return FALSE;
}
return (0 == rmdir(i_pDir));
}//Directory_Delete
////////////////////////////////////////////////////////////////////////////
//File_Exists
static tBOOL File_Exists(const tACHAR * i_pFileName)
{
struct stat l_sStat;
l_sStat.st_mode = 0;
if (0 == stat(i_pFileName, &l_sStat))
{
if (0 != (l_sStat.st_mode & S_IFREG))
{
return TRUE;
}
}
return FALSE;
}//File_Exists
////////////////////////////////////////////////////////////////////////////
// Enumerate_Files
static void Enumerate_Files(CBList<CWString*> *i_pDll_List,
CWString *i_pDirectory,
const char *i_pMask, //for example L"*.so"
tUINT32 i_dwDepth = 0xFFFFFFul
)
{
tUINT32 l_dwLength = i_pDirectory->Length();
if ( (NULL == i_pDll_List)
|| (NULL == i_pDirectory)
|| (NULL == i_pMask)
)
{
return;
}
DIR *l_pDir = opendir(i_pDirectory->Get());
dirent *l_pDir_Entry = 0;
if (!l_pDir)
{
return;
}
while ((l_pDir_Entry = readdir(l_pDir)) != 0)
{
if (DT_REG == l_pDir_Entry->d_type)
{
if (0 == fnmatch(i_pMask, l_pDir_Entry->d_name, FNM_NOESCAPE | FNM_CASEFOLD))
{
CWString *i_pFile = new CWString();
if (i_pFile)
{
i_pFile->Set(i_pDirectory->Get());
i_pFile->Append(2, L"/", l_pDir_Entry->d_name);
i_pDll_List->Add_After(i_pDll_List->Get_Last(), i_pFile);
}
}
}
else if ( (DT_DIR == l_pDir_Entry->d_type)
&& (0 != PStrCmp(l_pDir_Entry->d_name, "."))
&& (0 != PStrCmp(l_pDir_Entry->d_name, ".."))
&& (i_dwDepth)
)
{
i_pDirectory->Append(2, L"/", l_pDir_Entry->d_name);
Enumerate_Files(i_pDll_List, i_pDirectory, i_pMask, i_dwDepth - 1);
i_pDirectory->Trim(l_dwLength);
}
}
closedir(l_pDir);
l_pDir = 0;
}// Enumerate_Files
////////////////////////////////////////////////////////////////////////////
// Enumerate_Dirs
static void Enumerate_Dirs(CBList<CWString*> *io_pList, const tXCHAR *i_pRoot)
{
if (NULL == io_pList)
{
return;
}
if (!i_pRoot)
{
i_pRoot = "/";
}
DIR *l_pDir = opendir(i_pRoot);
dirent *l_pDir_Entry = 0;
if (!l_pDir)
{
return;
}
while ((l_pDir_Entry = readdir(l_pDir)) != 0)
{
if ( (DT_DIR == l_pDir_Entry->d_type)
&& (0 != PStrCmp(l_pDir_Entry->d_name, "."))
&& (0 != PStrCmp(l_pDir_Entry->d_name, ".."))
)
{
CWString *i_pFile = new CWString();
if (i_pFile)
{
i_pFile->Set(i_pRoot);
i_pFile->Append(2, "/", l_pDir_Entry->d_name);
io_pList->Add_After(io_pList->Get_Last(), i_pFile);
}
}
}
closedir(l_pDir);
l_pDir = 0;
}// Enumerate_Dirs
////////////////////////////////////////////////////////////////////////////
//Get_File_Size
static tUINT64 Get_File_Size(const tACHAR *i_pFile)
{
struct stat l_sStat;
l_sStat.st_size = 0;
if (0 == stat(i_pFile, &l_sStat))
{
return (tUINT64)l_sStat.st_size;
}
return 0;
}//Get_File_Size
////////////////////////////////////////////////////////////////////////////
//Get_Version
static tUINT64 Get_Version(const char *i_pFile)
{
UNUSED_ARG(i_pFile);
return 0ull;
}//Get_Version
// ////////////////////////////////////////////////////////////////////////////
// //Get_Process_Directory
// static BOOL Get_Process_Directory(CWString *o_pDirectory)
// {
// BOOL l_bReturn = FALSE;
// DWORD l_dwLength = 4096;
// if ( (NULL == o_pDirectory)
// || (FALSE == o_pDirectory->Realloc(l_dwLength))
// )
// {
// return l_bReturn;
// }
// if (0 != GetModuleFileNameW(GetModuleHandleW(NULL),
// o_pDirectory->Get(),
// o_pDirectory->Max_Length())
// )
// {
// wchar_t *l_pExe_Name = NULL;
// if ( (l_pExe_Name = wcsrchr(o_pDirectory->Get(), L'\\'))
// || (l_pExe_Name = wcsrchr(o_pDirectory->Get(), L'/'))
// )
// {
// o_pDirectory->Trim((DWORD)(l_pExe_Name - o_pDirectory->Get()));
// l_bReturn = TRUE;
// }
// }
// return l_bReturn;
// }//Get_Process_Directory
////////////////////////////////////////////////////////////////////////////
//Delete_File
static tBOOL Delete_File(const char *i_pFile_Name)
{
if (NULL == i_pFile_Name)
{
return FALSE;
}
return (0 == remove(i_pFile_Name));
}//Delete_File
////////////////////////////////////////////////////////////////////////////
//GetUserDirectory
static tBOOL GetUserDirectory(CWString *o_pPath)
{
if ( (NULL == o_pPath)
|| (FALSE == o_pPath->Realloc(4096))
)
{
return TRUE;
}
struct passwd *pw = getpwuid(getuid());
if (!pw)
{
return FALSE;
}
o_pPath->Set(pw->pw_dir);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
//GetUserDirectory
static tBOOL GetDirectoryParent(CWString &i_rChild, CWString &o_rParent)
{
o_rParent.Set(i_rChild.Get());
size_t l_szDir = o_rParent.Length();
tXCHAR *l_pDir = o_rParent.Get();
//cut trailing '/' or '\'
while ( (l_szDir > 1)
&& (TM('/') == l_pDir[l_szDir - 1])
)
{
l_pDir[--l_szDir] = 0;
}
tXCHAR *l_pTemp = strrchr(l_pDir, TM('/'));
if (!l_pTemp)
{
o_rParent.Set(TM(""));
return TRUE;
}
l_pTemp++;
*l_pTemp = 0;
l_pTemp--;
//removing duplicates of '/'
while ( (TM('/') == *l_pTemp)
&& (l_pTemp > l_pDir)
)
{
*l_pTemp = 0;
l_pTemp--;
}
return (*l_pDir) ? TRUE : FALSE;
}
};
#endif //PFILESYSTEM_H

View File

@ -0,0 +1,266 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PJOURNAL_H
#define PJOURNAL_H
//#include <stdio.h>
//#include <string.h>
//#include <stdarg.h>
//#include <iostream>
//#include <pthread.h> //-pthread
//#include <time.h>
//#include "Atomic.hpp"
//#include "Lock.hpp"
//#include "PTypes.hpp"
//#include "GTypes.hpp"
//#include "IJournal.hpp"
////////////////////////////////////////////////////////////////////////////////
class CJournal
: public IJournal //virtual
{
volatile tINT32 m_iRCnt;
tLOCK m_hCS;
tUINT64 m_pCount[IJournal::eLEVEL_COUNT];
IJournal::eLevel m_eVerbosity;
tUINT32 m_pLength;
tXCHAR *m_pBuffer;
tXCHAR m_pName[IJournal::eLEVEL_COUNT][16];
public:
////////////////////////////////////////////////////////////////////////////
CJournal()
: m_iRCnt(1)
, m_eVerbosity(IJournal::eLEVEL_WARNING)
, m_pLength(8192)
{
LOCK_CREATE(m_hCS);
for (tUINT32 l_dwI = 0; l_dwI < IJournal::eLEVEL_COUNT; l_dwI++)
{
m_pName[l_dwI][0] = 0;
m_pCount[l_dwI] = 0ULL;
}
strcpy(m_pName[IJournal::eLEVEL_TRACE], "TRACE: ");
strcpy(m_pName[IJournal::eLEVEL_DEBUG], "DEBUG: ");
strcpy(m_pName[IJournal::eLEVEL_INFO], "INFO : ");
strcpy(m_pName[IJournal::eLEVEL_WARNING], "WARN.: ");
strcpy(m_pName[IJournal::eLEVEL_ERROR], "ERROR: ");
strcpy(m_pName[IJournal::eLEVEL_CRITICAL], "CRIT.: ");
}
////////////////////////////////////////////////////////////////////////////
virtual ~CJournal()
{
if (m_pBuffer)
{
delete [] m_pBuffer;
m_pBuffer = NULL;
}
//if (m_iRCnt)
//{
// printf("Error: CJournal reference counter is not 0");
//}
LOCK_DESTROY(m_hCS);
}
////////////////////////////////////////////////////////////////////////////
tBOOL Initialize(const tXCHAR *i_pName)
{
UNUSED_ARG(i_pName);
if (m_pBuffer)
{
return TRUE;
}
m_pBuffer = new tXCHAR[m_pLength];
return m_pBuffer ? TRUE : FALSE;
}
////////////////////////////////////////////////////////////////////////////
void Set_Verbosity(IJournal::eLevel i_eVerbosity)
{
LOCK_ENTER(m_hCS);
m_eVerbosity = i_eVerbosity;
LOCK_EXIT(m_hCS);
}
////////////////////////////////////////////////////////////////////////////
IJournal::eLevel Get_Verbosity()
{
IJournal::eLevel l_eReturn;
LOCK_ENTER(m_hCS);
l_eReturn = m_eVerbosity;
LOCK_EXIT(m_hCS);
return l_eReturn;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Log(IJournal::eLevel i_eType,
IJournal::hModule i_hModule,
const char *i_pFile,
const char *i_pFunction,
tUINT32 i_dwLine,
const tXCHAR *i_pFormat,
...
)
{
UNUSED_ARG(i_hModule);
UNUSED_ARG(i_pFile);
tBOOL l_bReturn = TRUE;
time_t l_tNow = time(NULL);
struct tm *l_pTime = localtime(&l_tNow);
struct timespec l_sTime = {0, 0};
int l_iRes = 0;
int l_iOffs = 0;
tUINT64 l_qwMSec = 0;
LOCK_ENTER(m_hCS);
if ( (i_eType < m_eVerbosity)
|| (NULL == m_pBuffer)
|| (i_eType >= IJournal::eLEVEL_COUNT)
)
{
l_bReturn = FALSE;
goto l_lExit;
}
m_pCount[i_eType] ++;
l_iRes = snprintf(m_pBuffer + l_iOffs,
m_pLength - l_iOffs,
"[%s] : [%d]\n",
i_pFunction,
(int)i_dwLine
);
if (0 <= l_iRes)
{
l_iOffs += l_iRes;
}
clock_gettime(CLOCK_MONOTONIC, &l_sTime);
l_qwMSec = l_sTime.tv_sec;
l_qwMSec *= 1000;
l_qwMSec += l_sTime.tv_nsec/1000000;
l_iRes = snprintf(m_pBuffer + l_iOffs,
m_pLength - l_iOffs,
"%04d.%02d.%02d %02d:%02d:%02d.%03d: %s: ",
l_pTime->tm_year + 1900,
l_pTime->tm_mon + 1,
l_pTime->tm_mday,
l_pTime->tm_hour,
l_pTime->tm_min,
l_pTime->tm_sec,
(int)(l_qwMSec % 1000),
m_pName[i_eType]
);
if (0 <= l_iRes)
{
l_iOffs += l_iRes;
}
va_list l_pVA;
va_start(l_pVA, i_pFormat);
vsnprintf(m_pBuffer + l_iOffs, m_pLength - l_iOffs, i_pFormat, l_pVA);
va_end(l_pVA);
//std::cout << m_pBuffer << "\n";
printf(m_pBuffer, 0); //0 to close warning from G++
printf("\n");
l_lExit:
LOCK_EXIT(m_hCS);
return l_bReturn;
}
////////////////////////////////////////////////////////////////////////////
tUINT64 Get_Count(IJournal::eLevel i_eType)
{
tUINT64 l_qwReturn = 0ULL;
if (i_eType >= IJournal::eLEVEL_COUNT)
{
return 0ULL;
}
LOCK_ENTER(m_hCS);
l_qwReturn = m_pCount[i_eType];
LOCK_EXIT(m_hCS);
return l_qwReturn;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Register_Thread(const tXCHAR *i_pName, tUINT32 i_dwThreadId)
{
UNUSED_ARG(i_pName);
UNUSED_ARG(i_dwThreadId);
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Unregister_Thread(tUINT32 i_dwThreadId)
{
UNUSED_ARG(i_dwThreadId);
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Register_Module(const tXCHAR *i_pName, IJournal::hModule *o_hModule)
{
UNUSED_ARG(i_pName);
if (o_hModule)
{
*o_hModule = NULL;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
tINT32 Add_Ref()
{
return ATOMIC_INC(&m_iRCnt);
}
////////////////////////////////////////////////////////////////////////////
tINT32 Release()
{
volatile tINT32 l_iReturn = ATOMIC_DEC(&m_iRCnt);
if (0 >= l_iReturn)
{
delete this;
}
return l_iReturn;
}
};
#endif //PJOURNAL_H

View File

@ -0,0 +1,45 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PLOCK_H
#define PLOCK_H
#include <pthread.h>
///////////////////////////////////////////////////////////////////////////////
typedef pthread_mutex_t tLOCK;
#define LOCK_CREATE(i_Lock) {\
pthread_mutexattr_t l_sAttr;\
memset(&l_sAttr, 0, sizeof(pthread_mutexattr_t));\
pthread_mutexattr_init(&l_sAttr);\
pthread_mutexattr_settype(&l_sAttr,\
PTHREAD_MUTEX_RECURSIVE);\
pthread_mutex_init(&i_Lock, &l_sAttr);\
pthread_mutexattr_destroy(&l_sAttr);\
}\
#define LOCK_DESTROY(i_Lock) pthread_mutex_destroy(&i_Lock)
#define LOCK_ENTER(i_Lock) pthread_mutex_lock(&i_Lock)
#define LOCK_EXIT(i_Lock) pthread_mutex_unlock(&i_Lock)
#define LOCK_TRY(i_Lock) ((0 == pthread_mutex_trylock(&i_Lock)) ? TRUE : FALSE)
#endif //PLOCK_H

View File

@ -0,0 +1,469 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PMEVENT_H
#define PMEVENT_H
#include <semaphore.h>
// Infinite timeout
#define INFINITE 0xFFFFFFFF
//#define PMEVENT_COND_VARIABLE
////////////////////////////////////////////////////////////////////////////////
//CMEvent - class designed to avoid problem of "wait" POSIX functions. They are
// based on abs. time and they are affected by system time changes.
class CMEvent
: public IMEvent //virtual
{
struct sEvent
{
volatile tINT32 iCounter;
eMEvent_Type eType;
tUINT32 dwIdx;
sEvent *pNext;
};
pthread_mutex_t m_sMutex;
#ifdef PMEVENT_COND_VARIABLE
pthread_cond_t m_sCV;
#else
sem_t m_sSem;
#endif
tUINT8 m_bCount;
tBOOL m_bInit;
tBOOL m_bError;
sEvent *m_pEvents;
sEvent *m_pEvent_Cur;
tINT32 m_iSignals;
public:
////////////////////////////////////////////////////////////////////////////
//CMEvent
CMEvent()
: m_bCount(0)
, m_bInit(FALSE)
, m_bError(FALSE)
, m_pEvents(NULL)
, m_pEvent_Cur(NULL)
, m_iSignals(0)
{
}//CMEvent
////////////////////////////////////////////////////////////////////////////
//~CMEvent
virtual ~CMEvent()
{
if (m_bInit)
{
pthread_mutex_destroy(&m_sMutex);
#ifdef PMEVENT_COND_VARIABLE
pthread_cond_destroy(&m_sCV);
#else
sem_destroy(&m_sSem);
#endif
}
Cleanup();
m_bCount = 0;
}//~CMEvent
////////////////////////////////////////////////////////////////////////////
//Init
tBOOL Init(tUINT8 i_bCount, ...)
{
va_list l_pVA;
tUINT8 l_bIDX = 0;
tBOOL l_bCA = FALSE;
tBOOL l_bSig = FALSE;
tBOOL l_bMutex = FALSE;
pthread_condattr_t l_sCA;
if ( (TRUE == m_bInit)
|| (TRUE == m_bError)
|| (0 >= i_bCount)
)
{
return FALSE;
}
#ifdef PMEVENT_COND_VARIABLE
////////////////////////////////////////////////////////////////////////
//initialize Cond.Variable
clockid_t l_iClock = CLOCK_REALTIME;
if (0 != pthread_condattr_init(&l_sCA))
{
goto l_lExit; //error
}
else
{
l_bCA = TRUE;
}
//#ifdef __USE_XOPEN2K
if (0 != pthread_condattr_setclock(&l_sCA, CLOCK_MONOTONIC))
{
goto l_lExit; //error
}
if ( (0 != pthread_condattr_getclock(&l_sCA, &l_iClock))
|| (CLOCK_MONOTONIC != l_iClock)
)
{
goto l_lExit; //error
}
//#else
//#endif
if (0 != pthread_cond_init(&m_sCV, &l_sCA))
{
goto l_lExit; //error
}
else
{
l_bSig = TRUE;
}
#else
////////////////////////////////////////////////////////////////////////
//initialize semaphore
if (0 != sem_init(&m_sSem, 0, 0))
{
goto l_lExit; //error
}
else
{
l_bSig = TRUE;
}
#endif
////////////////////////////////////////////////////////////////////////
//initialize mutex
if (0 != pthread_mutex_init(&m_sMutex, NULL))
{
m_bError = TRUE;
goto l_lExit;
}
else
{
l_bMutex = TRUE;
}
////////////////////////////////////////////////////////////////////////
//initialize events structure
m_pEvents = new sEvent[i_bCount];
if (NULL == m_pEvents)
{
goto l_lExit;
}
memset(m_pEvents, 0, sizeof(sEvent) * i_bCount);
m_pEvent_Cur = &m_pEvents[0];
va_start(l_pVA, i_bCount);
while (l_bIDX < i_bCount)
{
m_pEvents[l_bIDX].eType = (eMEvent_Type)va_arg(l_pVA, /*eMEvent_Type*/int);
m_pEvents[l_bIDX].iCounter = 0;
m_pEvents[l_bIDX].dwIdx = l_bIDX;
//make round trip links
if ((l_bIDX + 1) < i_bCount)
{
m_pEvents[l_bIDX].pNext = &m_pEvents[l_bIDX + 1];
}
else
{
m_pEvents[l_bIDX].pNext = &m_pEvents[0];
}
l_bIDX++;
}
va_end(l_pVA);
m_bInit = TRUE;
m_bCount = i_bCount;
l_lExit:
if (l_bCA)
{
pthread_condattr_destroy(&l_sCA);
}
if (FALSE == m_bInit)
{
m_bError = TRUE;
if (l_bMutex)
{
pthread_mutex_destroy(&m_sMutex);
}
if (l_bSig)
{
#ifdef PMEVENT_COND_VARIABLE
pthread_cond_destroy(&m_sCV);
#else
sem_destroy(&m_sSem);
#endif
}
Cleanup();
}
return m_bInit;
}//Init
////////////////////////////////////////////////////////////////////////////
//Set
tBOOL Set(tUINT32 i_dwID)
{
if ( (i_dwID >= m_bCount)
|| (FALSE == m_bInit)
)
{
return FALSE;
}
pthread_mutex_lock(&m_sMutex);
m_iSignals++;
m_pEvents[i_dwID].iCounter ++;
#ifdef PMEVENT_COND_VARIABLE
pthread_cond_signal(&m_sCV);
#else
sem_post(&m_sSem);
#endif
pthread_mutex_unlock(&m_sMutex);
return TRUE;
}//Set
////////////////////////////////////////////////////////////////////////////
//Clr
tBOOL Clr(tUINT32 i_dwID)
{
tBOOL l_bReturn = FALSE;
if ( (i_dwID >= m_bCount)
|| (EMEVENT_SINGLE_MANUAL != m_pEvents[i_dwID].eType)
)
{
return l_bReturn;
}
pthread_mutex_lock(&m_sMutex);
if (m_pEvents[i_dwID].iCounter)
{
m_iSignals --;
m_pEvents[i_dwID].iCounter --;
sem_trywait(&m_sSem); //decrease semaphore
l_bReturn = TRUE;
}
pthread_mutex_unlock(&m_sMutex);
return l_bReturn;
}//Clr
////////////////////////////////////////////////////////////////////////////
//Wait
tUINT32 Wait()
{
tUINT32 l_dwReturn = MEVENT_TIME_OUT;
////////////////////////////////////////////////////////////////////////
//LOCK
#ifdef PMEVENT_COND_VARIABLE
int l_iCV_Res = 0;
pthread_mutex_lock(&m_sMutex);
while (0 == m_iSignals)
{
l_iCV_Res = pthread_cond_wait(&m_sCV, &m_sMutex);
if (0 != l_iCV_Res)
{
break;
}
}
l_dwReturn = Get_Signal();
pthread_mutex_unlock(&m_sMutex);
#else
sem_wait(&m_sSem);
pthread_mutex_lock(&m_sMutex);
l_dwReturn = Get_Signal();
pthread_mutex_unlock(&m_sMutex);
#endif
//UNLOCK
////////////////////////////////////////////////////////////////////////
return l_dwReturn;
}//Wait
////////////////////////////////////////////////////////////////////////////
//Wait
tUINT32 Wait(tUINT32 i_dwMSec)
{
tUINT64 l_qwNano = (tUINT64)i_dwMSec * 1000000ULL;
tUINT32 l_dwReturn = MEVENT_TIME_OUT;
struct timespec l_sTime = {0, 0};
////////////////////////////////////////////////////////////////////////
//LOCK
#ifdef PMEVENT_COND_VARIABLE
int l_iRes = 0;
pthread_mutex_lock(&m_sMutex);
clock_gettime(CLOCK_MONOTONIC, &l_sTime);
l_qwNano += l_sTime.tv_nsec;
l_sTime.tv_sec += static_cast<__time_t>(l_qwNano / 1000000000ULL);
l_sTime.tv_nsec = static_cast<long int>(l_qwNano % 1000000000ULL);
while (0 == m_iSignals)
{
//ETIMEDOUT
l_iRes = pthread_cond_timedwait(&m_sCV, &m_sMutex, &l_sTime);
if (0 != l_iRes)
{
break;
}
}
l_dwReturn = Get_Signal();
pthread_mutex_unlock(&m_sMutex);
#else
if (0 == i_dwMSec)
{
if (0 == sem_trywait(&m_sSem))
{
pthread_mutex_lock(&m_sMutex);
l_dwReturn = Get_Signal();
pthread_mutex_unlock(&m_sMutex);
}
}
else
{
clock_gettime(CLOCK_REALTIME, &l_sTime);
l_qwNano += l_sTime.tv_nsec;
l_sTime.tv_sec += static_cast<time_t>(l_qwNano/1000000000ULL);
l_sTime.tv_nsec = static_cast<long>(l_qwNano%1000000000ULL);
if (0 == sem_timedwait(&m_sSem, &l_sTime))
{
pthread_mutex_lock(&m_sMutex);
l_dwReturn = Get_Signal();
pthread_mutex_unlock(&m_sMutex);
}
}
#endif
//UNLOCK
////////////////////////////////////////////////////////////////////////
return l_dwReturn;
}//Wait
private:
////////////////////////////////////////////////////////////////////////////
//Get_Signal
tUINT32 Get_Signal()
{
tUINT32 l_dwReturn = MEVENT_TIME_OUT;
if (0 == m_iSignals) //if we register some signal
{
return l_dwReturn;
}
sEvent *l_pStart = m_pEvent_Cur;
//we will walk through all events in attempt to find signal
do
{
m_pEvent_Cur = m_pEvent_Cur->pNext;
if (m_pEvent_Cur->iCounter)
{
l_dwReturn = m_pEvent_Cur->dwIdx;
if (EMEVENT_SINGLE_MANUAL == m_pEvent_Cur->eType)
{
sem_post(&m_sSem); //return sem value to signal again
}
else
{
m_pEvent_Cur->iCounter --;
m_iSignals --;
}
break;
}
//if we do round trip
} while (l_pStart != m_pEvent_Cur);
if (MEVENT_TIME_OUT == l_dwReturn)
{
//error: signal event wasn't found !
m_iSignals --;
}
return l_dwReturn;
}//Get_Signal
////////////////////////////////////////////////////////////////////////////
//Cleanup
void Cleanup()
{
if (m_pEvents)
{
delete [] m_pEvents;
m_pEvents = NULL;
}
}//Cleanup
};
#endif //PMEVENT_H

View File

@ -0,0 +1,72 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PPERFORMANCE_INFO_H
#define PPERFORMANCE_INFO_H
#include "IPerformanceInfo.h"
////////////////////////////////////////////////////////////////////////////////
class CPerformanceInfo
: public IPerformanceInfo
{
volatile tINT32 m_iRCnt;
public:
////////////////////////////////////////////////////////////////////////////
CPerformanceInfo(const tXCHAR *i_pProcessName)
: m_iRCnt(1)
{
UNUSED_ARG(i_pProcessName);
}
virtual ~CPerformanceInfo()
{
}
tBOOL Refresh()
{
return TRUE;
}
tINT64 Get(IPerformanceInfo::eCounter i_eCounter)
{
UNUSED_ARG(i_eCounter);
return 0;
}
////////////////////////////////////////////////////////////////////////////
tINT32 Add_Ref()
{
return ATOMIC_INC(&m_iRCnt);
}
////////////////////////////////////////////////////////////////////////////
tINT32 Release()
{
volatile tINT32 l_iReturn = ATOMIC_DEC(&m_iRCnt);
if (0 >= l_iReturn)
{
delete this;
}
return l_iReturn;
}
};
#endif //PPERFORMANCE_INFO_H

View File

@ -0,0 +1,575 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PPROCESS_H
#define PPROCESS_H
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <asm/param.h> //HZ macro !
#include <sched.h>
class CProc
{
public:
///////////////////////////////////////////////////////////////////////////////
//Get_ArgV
static tXCHAR **Get_ArgV(tINT32 *o_pCount)
{
const tUINT16 l_wLen = 4096;
tXCHAR *l_pBuffer = new tXCHAR[l_wLen];
tXCHAR **l_pReturn = NULL;
int l_pFile = -1;
tINT32 l_iRead = -1;
tBOOL l_bNew = TRUE;
tINT32 l_iIDX = 0;
if ( (NULL == l_pBuffer)
|| (NULL == o_pCount)
)
{
goto l_lblExit;
}
l_pFile = open("/proc/self/cmdline", O_RDONLY);
if (-1 == l_pFile)
{
goto l_lblExit;
}
l_iRead = read(l_pFile, l_pBuffer, l_wLen * sizeof(tXCHAR));
if (0 >= l_iRead)
{
goto l_lblExit;
}
//calculate count of items//////////////////////////////////////////////////
*o_pCount = 0;
for (tINT32 l_iI = 0; l_iI < l_iRead; l_iI++)
{
if ( (0 == l_pBuffer[l_iI])
|| ((l_iI + 1) == l_iRead)
)
{
(*o_pCount) ++;
}
}
if (0 >= *o_pCount)
{
goto l_lblExit;
}
//allocate result///////////////////////////////////////////////////////////
l_pReturn = new tXCHAR*[*o_pCount];
if (NULL == l_pReturn)
{
goto l_lblExit;
}
//fill result///////////////////////////////////////////////////////////////
l_bNew = TRUE;
for (tINT32 l_iI = 0; l_iI < l_iRead; l_iI++)
{
if (l_bNew)
{
l_pReturn[l_iIDX++] = &l_pBuffer[l_iI];
l_bNew = FALSE;
}
if (0 == l_pBuffer[l_iI])
{
l_bNew = TRUE;
}
}
l_lblExit:
if (-1 != l_pFile)
{
close(l_pFile);
}
if (NULL == l_pReturn)
{
if (l_pBuffer)
{
delete [] l_pBuffer;
l_pBuffer = NULL;
}
}
return l_pReturn;
// return = CommandLineToArgvW(GetCommandLineW(), o_pCount);
}//Get_ArgV
///////////////////////////////////////////////////////////////////////////////
//Get_ArgV
static tXCHAR **Get_ArgV(const tXCHAR *i_pCmdLine, tINT32 *o_pCount)
{
tINT32 l_iLen = 0;//strlen(i_pCmdLine);
tXCHAR *l_pBuffer = NULL;//new tXCHAR[l_iLen];
tXCHAR **l_pReturn = NULL;
tBOOL l_bNew = TRUE;
tBOOL l_bStr = FALSE;
tINT32 l_iIDX = 0;
if ( (NULL == i_pCmdLine)
|| (NULL == o_pCount)
)
{
goto l_lblExit;
}
l_iLen = (tINT32)strlen(i_pCmdLine) + 1;
l_pBuffer = new tXCHAR[l_iLen];
if (NULL == l_pBuffer)
{
goto l_lblExit;
}
for (tINT32 l_iI = 0; l_iI < l_iLen; l_iI++)
{
if (TM('\"') == i_pCmdLine[l_iI])
{
l_bStr = ! l_bStr;
}
else
{
if ( (TM(' ') == i_pCmdLine[l_iI])
&& (!l_bStr)
)
{
l_pBuffer[l_iIDX++] = 0;
}
else
{
l_pBuffer[l_iIDX++] = i_pCmdLine[l_iI];
}
}
}
l_iLen = l_iIDX;
//calculate count of items//////////////////////////////////////////////////
*o_pCount = 0;
for (tINT32 l_iI = 0; l_iI < l_iLen; l_iI++)
{
if ( (0 == l_pBuffer[l_iI])
|| ((l_iI + 1) == l_iLen)
)
{
(*o_pCount) ++;
}
}
if (0 >= *o_pCount)
{
goto l_lblExit;
}
//allocate result///////////////////////////////////////////////////////////
l_pReturn = new tXCHAR*[*o_pCount];
if (NULL == l_pReturn)
{
goto l_lblExit;
}
//fill result///////////////////////////////////////////////////////////////
l_bNew = TRUE;
l_iIDX = 0;
for (tINT32 l_iI = 0; l_iI < l_iLen; l_iI++)
{
if (l_bNew)
{
l_pReturn[l_iIDX++] = &l_pBuffer[l_iI];
l_bNew = FALSE;
}
if (0 == l_pBuffer[l_iI])
{
l_bNew = TRUE;
}
}
l_lblExit:
return l_pReturn;
}//Get_ArgV
///////////////////////////////////////////////////////////////////////////////
//Free_ArgV
static void Free_ArgV(tXCHAR **i_pArgV)
{
if (NULL == i_pArgV)
{
return;
}
if (i_pArgV[0])
{
delete [] i_pArgV[0];
}
delete [] i_pArgV;
//LocalFree(i_pArgV);
}//Free_ArgV
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Time()
//return a 64-bit value divided into 2 parts representing the number of
//100-nanosecond intervals since January 1, 1601 (UTC).
static tBOOL Get_Process_Time(tUINT32 *o_pHTime, tUINT32 *o_pLTime)
{
const int l_iLen = 8192;
char *l_pBuffer = new char[l_iLen];
int l_iRead = 0;
int l_pFile = -1;
char *l_pIter = NULL;
long long l_llBtime = 0;
long long l_llStime = 0;
int l_iSscanf = 0;
tBOOL l_bResult = FALSE;
if ( (NULL == l_pBuffer)
|| (NULL == o_pHTime)
|| (NULL == o_pLTime)
)
{
goto l_lblExit;
}
*o_pHTime = 0;
*o_pLTime = 0;
//read global stat//////////////////////////////////////////////////////////
l_pFile = open("/proc/stat", O_RDONLY);
if (-1 == l_pFile)
{
goto l_lblExit;
}
l_iRead = read(l_pFile, l_pBuffer, l_iLen);
close(l_pFile);
if (0 >= l_iRead)
{
goto l_lblExit;
}
if (l_iRead < l_iLen)
{
l_pBuffer[l_iRead -1] = 0;
}
else
{
l_pBuffer[l_iLen -1] = 0;
}
//printf((char*)l_pBuffer, 0);
//printf("\nLen = %d\n", l_iRead);
//get "btime" value/////////////////////////////////////////////////////////
{
const char l_pBtime[] = "btime ";
int l_iBLen = strlen(l_pBtime);
l_pIter = l_pBuffer;
for (int l_iI = 0; l_iI < l_iRead; l_iI++)
{
if (0 == strncmp(l_pBtime, l_pIter, l_iBLen))
{
l_iSscanf = sscanf(l_pIter + l_iBLen, "%lld", &l_llBtime);
break;
}
else
{
l_pIter++;
}
}
}
if (0 >= l_iSscanf)
{
goto l_lblExit;
}
//read process statistics///////////////////////////////////////////////////
l_pFile = open("/proc/self/stat", O_RDONLY);
if (-1 == l_pFile)
{
goto l_lblExit;
}
l_iRead = read(l_pFile, l_pBuffer, l_iLen);
close(l_pFile);
if (0 >= l_iRead)
{
goto l_lblExit;
}
if (l_iRead < l_iLen)
{
l_pBuffer[l_iRead -1] = 0;
}
else
{
l_pBuffer[l_iLen -1] = 0;
}
//get process start time////////////////////////////////////////////////////
{
int l_iItem = 1;
l_pIter = l_pBuffer;
for (int l_iI = 0; l_iI < l_iRead; l_iI++)
{
if (' ' == *l_pIter)
{
if (21 == l_iItem)
{
l_iSscanf = sscanf(l_pIter, " %lld", &l_llStime);
break;
}
else
{
l_iItem ++;
}
}
l_pIter++;
}
}
if (0 >= l_iSscanf)
{
goto l_lblExit;
}
//HZ defined in #include <asm/param.h>
l_llStime = l_llBtime * 10000000ull + (l_llStime * 10000000ull / HZ);
l_llStime += TIME_OFFSET_1601_1970; //defined in "PTime.h"
*o_pHTime = (l_llStime >> 32);
*o_pLTime = (l_llStime & 0xFFFFFFFF);
l_bResult = TRUE;
l_lblExit:
if (l_pBuffer)
{
delete [] l_pBuffer;
l_pBuffer = NULL;
}
return l_bResult;
}//Get_Process_Time()
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Name
static tBOOL Get_Process_Name(tACHAR *o_pName, tINT32 i_iMax_Len)
{
int l_iRead = 0;
char *l_pName = NULL;
char *l_pDst = o_pName;
tBOOL l_bReturn = FALSE;
if ( (NULL == o_pName)
|| (32 >= i_iMax_Len)
|| (NULL == o_pName)
)
{
goto l_lblExit;
}
l_iRead = readlink("/proc/self/exe", o_pName, i_iMax_Len - 1);
if (0 >= l_iRead)
{
// I guess we're not running on the right version of unix
goto l_lblExit;
}
if (l_iRead >= i_iMax_Len)
{
l_iRead = i_iMax_Len - 1;
}
o_pName[l_iRead] = '\0';
l_pName = o_pName + l_iRead;
while (l_pName != o_pName)
{
if ( ('/' == *l_pName)
|| ('\\' == *l_pName)
)
{
l_pName ++;
break;
}
else
{
l_pName --;
}
}
while (*l_pName)
{
*l_pDst++=*l_pName++;
}
*l_pDst = 0;
l_bReturn = TRUE;
l_lblExit:
return l_bReturn;
}//Get_Process_Name
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Name
static tBOOL Get_Process_Name(tWCHAR *o_pName, tINT32 i_iMax_Len)
{
int l_iLen = 4096;
char *l_pBuffer = new char[l_iLen];
tBOOL l_bReturn = FALSE;
if ( (l_pBuffer)
&& (Get_Process_Name(l_pBuffer, l_iLen))
)
{
l_bReturn = TRUE;
Convert_UTF8_To_UTF16(l_pBuffer, o_pName, i_iMax_Len);
}
else
{
Convert_UTF8_To_UTF16("Unknown", o_pName, i_iMax_Len);
}
if (l_pBuffer)
{
delete [] l_pBuffer;
l_pBuffer = NULL;
}
return l_bReturn;
}//Get_Process_Name
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Path
static tBOOL Get_Process_Path(tXCHAR *o_pPath, tINT32 i_iMax_Len)
{
int l_iRead = 0;
tBOOL l_bReturn = FALSE;
if ( (NULL == o_pPath)
|| (32 >= i_iMax_Len)
)
{
goto l_lblExit;
}
l_iRead = readlink("/proc/self/exe", o_pPath, i_iMax_Len - 4);
if (0 >= l_iRead)
{
// I guess we're not running on the right version of unix
goto l_lblExit;
}
if (l_iRead >= i_iMax_Len)
{
// buffer is too small
goto l_lblExit;
}
o_pPath[l_iRead] = '\0';
while (l_iRead)
{
if ( ('/' == o_pPath[l_iRead])
|| ('\\' == o_pPath[l_iRead])
)
{
break;
}
else
{
o_pPath[l_iRead--] = 0;
}
}
l_bReturn = TRUE;
l_lblExit:
if (TRUE != l_bReturn)
{
strcpy(o_pPath, "./");
}
return l_bReturn;
}//Get_Process_Path
////////////////////////////////////////////////////////////////////////////////
//Get_Process_ID
static tUINT32 Get_Process_ID()
{
return getpid();
//return GetCurrentProcessId();
}//Get_Process_ID
////////////////////////////////////////////////////////////////////////////////
//Get_Thread_Id
static tUINT32 Get_Thread_Id()
{
return (int32_t)syscall(SYS_gettid);
//return pthread_self();
//return gettid();
}//Get_Thread_Id
////////////////////////////////////////////////////////////////////////////////
//Get_Processor
static __forceinline tUINT32 Get_Processor()
{
#ifdef __ARM_ARCH_5TEJ__
return 0;
#else
return sched_getcpu();
#endif
}//Get_Processor
};
#endif //PPROCESS_H

View File

@ -0,0 +1,99 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "PTime.h"
#include "Ticks.h"
class CTickHi
{
tUINT64 m_qwCounter;
tUINT64 m_qwMarkIn;
tUINT64 m_qwMarkOut;
tUINT64 m_qwResolution;
public:
CTickHi()
{
m_qwMarkIn = 0ull;
m_qwMarkOut = 0ull;
m_qwCounter = 0ull;
m_qwResolution = GetPerformanceFrequency();
Reset();
Start();
}
void Start()
{
m_qwMarkIn = GetPerformanceCounter();
}
void Stop()
{
m_qwMarkOut = GetPerformanceCounter();
m_qwCounter += m_qwMarkOut - m_qwMarkIn;
}
void Reset()
{
m_qwCounter = 0;
}
//Second == 100 000;
tUINT32 Get()
{
return (tUINT32)(m_qwCounter * 100000ULL / m_qwResolution);
}
};
class CTickLow
{
tUINT32 m_dwStart;
tUINT32 m_dwStop;
public:
CTickLow()
{
m_dwStart = 0;
m_dwStop = 0;
Reset();
Start();
}
void Start()
{
m_dwStart = GetTickCount();
}
void Stop()
{
m_dwStop = GetTickCount();
}
void Reset()
{
m_dwStop = 0;
}
//frequency 1 000 per second
tUINT32 Get()
{
return CTicks::Difference(m_dwStop, m_dwStart);
}
};

View File

@ -0,0 +1,639 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PSHARED_H
#define PSHARED_H
////////////////////////////////////////////////////////////////////////////////
//Headers dependencies:
#include <unistd.h>
#include <fcntl.h> // For O_* constants
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h> // For mode constants
#define SHARED_NAME_FORMAT_STRING "/P7_Type%d_PID%d_Text%s"
#define SHARED_NAME_LEN (strlen(SHARED_NAME_FORMAT_STRING) + 64)
#define SHARED_SEM_NULL SEM_FAILED
////////////////////////////////////////////////////////////////////////////////
//CShared
class CShared
{
struct sShared
{
int iMFD;
sem_t *hSemaphore;
size_t szName;
char *pName;
char *pSemName;
char *pMemName;
};
enum eType
{
ETYPE_MUTEX = 0,
ETYPE_FILE ,
ETYPE_MAX
};
public:
typedef sShared *hShared;
typedef sem_t *hSem;
enum eLock
{
E_OK ,
E_TIMEOUT ,
E_ERROR ,
E_NOT_EXISTS
};
////////////////////////////////////////////////////////////////////////////
//CShared::Create
static tBOOL Create(CShared::hShared *o_pHandle,
const tXCHAR *i_pName,
const tUINT8 *i_pData,
tUINT16 i_wSize
)
{
hShared l_pShared = NULL;
tBOOL l_bResult = TRUE;
tBOOL l_bRelease = FALSE;
void *l_pBuffer = NULL;
if ( (NULL == i_pName)
|| (NULL == i_pData)
|| (0 >= i_wSize)
|| (NULL == o_pHandle)
)
{
l_bResult = FALSE;
goto l_lblExit;
}
l_pShared = (hShared)malloc(sizeof(sShared));
if (NULL == l_pShared)
{
l_bResult = FALSE;
goto l_lblExit;
}
memset(l_pShared, 0, sizeof(sShared));
l_pShared->hSemaphore = SHARED_SEM_NULL;
l_pShared->iMFD = -1;
l_pShared->szName = strlen(i_pName) + SHARED_NAME_LEN;
l_pShared->pName = strdup(i_pName);
l_pShared->pSemName = (char*)malloc(l_pShared->szName);
l_pShared->pMemName = (char*)malloc(l_pShared->szName);
if ( (NULL == l_pShared->pSemName)
|| (NULL == l_pShared->pMemName)
|| (NULL == l_pShared->pName)
)
{
l_bResult = FALSE;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////
//create ssemaphore and own it
Create_Name(l_pShared->pSemName, l_pShared->szName, ETYPE_MUTEX, i_pName);
l_pShared->hSemaphore = sem_open(l_pShared->pSemName, O_CREAT | O_EXCL, 0666, 0);
if (SHARED_SEM_NULL == l_pShared->hSemaphore)
{
l_bResult = FALSE;
goto l_lblExit;
}
l_bRelease = TRUE;
////////////////////////////////////////////////////////////////////////
//share memory
Create_Name(l_pShared->pMemName, l_pShared->szName, ETYPE_FILE, i_pName);
l_pShared->iMFD = shm_open(l_pShared->pMemName,
O_RDWR | O_CREAT | O_EXCL,
0666
);
if (0 > l_pShared->iMFD)
{
l_bResult = FALSE;
goto l_lblExit;
}
if (0 != ftruncate(l_pShared->iMFD, (off_t)i_wSize))
{
l_bResult = FALSE;
goto l_lblExit;
}
l_pBuffer = mmap(0,
(size_t)i_wSize,
PROT_READ | PROT_WRITE,
MAP_SHARED,
l_pShared->iMFD,
0
);
if ( (NULL == l_pBuffer)
|| (MAP_FAILED == l_pBuffer)
)
{
l_bResult = FALSE;
goto l_lblExit;
}
*o_pHandle = (CShared::hShared)l_pShared;
memcpy(l_pBuffer, i_pData, (size_t)i_wSize);
if (0 != munmap(l_pBuffer, (size_t)i_wSize))
{
}
l_lblExit:
if (l_bRelease)
{
sem_post(l_pShared->hSemaphore);
}
if (FALSE == l_bResult)
{
Close(l_pShared);
l_pShared = NULL;
if (o_pHandle)
{
*o_pHandle = NULL;
}
}
return l_bResult;
}//CShared::Create
////////////////////////////////////////////////////////////////////////////
//Read
static tBOOL Read(const tXCHAR *i_pName,
void *o_pData,
tUINT16 i_wSize
)
{
tBOOL l_bResult = TRUE;
size_t l_szName = 0;
char *l_pName = NULL;
void *l_pBuffer = NULL;
int l_iMFD = -1;
struct stat l_sStat;
if ( (NULL == i_pName)
|| (NULL == o_pData)
|| (0 >= i_wSize)
)
{
l_bResult = FALSE;
goto l_lblExit;
}
l_szName = strlen(i_pName) + SHARED_NAME_LEN;
l_pName = (char*)malloc(l_szName);
if (NULL == l_pName)
{
l_bResult = FALSE;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////////
//open shared memory object
Create_Name(l_pName, l_szName, ETYPE_FILE, i_pName);
l_iMFD = shm_open(l_pName, O_RDONLY, 0444);
if (0 > l_iMFD)
{
l_bResult = FALSE;
goto l_lblExit;
}
memset(&l_sStat, 0, sizeof(l_sStat));
if (-1 == fstat(l_iMFD, &l_sStat))
{
l_bResult = FALSE;
goto l_lblExit;
}
if ((size_t)l_sStat.st_size > (size_t)i_wSize)
{
l_bResult = FALSE;
goto l_lblExit;
}
l_pBuffer = mmap(0,
(size_t)l_sStat.st_size,
PROT_READ,
MAP_SHARED,
l_iMFD,
0
);
if ( (NULL == l_pBuffer)
|| (MAP_FAILED == l_pBuffer)
)
{
l_bResult = FALSE;
goto l_lblExit;
}
memcpy(o_pData, l_pBuffer, (size_t)l_sStat.st_size);
if (0 == munmap(l_pBuffer, (size_t)l_sStat.st_size))
{
l_pBuffer = NULL;
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
if (0 <= l_iMFD)
{
close(l_iMFD);
l_iMFD = -1;
}
return l_bResult;
}//Read
////////////////////////////////////////////////////////////////////////////
//Write
static tBOOL Write(const tXCHAR *i_pName,
const tUINT8 *i_pData,
tUINT16 i_wSize
)
{
tBOOL l_bResult = TRUE;
size_t l_szName = 0;
char *l_pName = NULL;
void *l_pBuffer = NULL;
int l_iMFD = -1;
struct stat l_sStat;
if ( (NULL == i_pName)
|| (NULL == i_pData)
|| (0 >= i_wSize)
)
{
l_bResult = FALSE;
goto l_lblExit;
}
l_szName = strlen(i_pName) + SHARED_NAME_LEN;
l_pName = (char*)malloc(l_szName);
if (NULL == l_pName)
{
l_bResult = FALSE;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////////
//open shared memory object
Create_Name(l_pName, l_szName, ETYPE_FILE, i_pName);
l_iMFD = shm_open(l_pName, O_RDWR, 0666);
if (0 > l_iMFD)
{
l_bResult = FALSE;
goto l_lblExit;
}
memset(&l_sStat, 0, sizeof(l_sStat));
if (-1 == fstat(l_iMFD, &l_sStat))
{
l_bResult = FALSE;
goto l_lblExit;
}
if ((size_t)l_sStat.st_size < (size_t)i_wSize)
{
l_bResult = FALSE;
goto l_lblExit;
}
l_pBuffer = mmap(0,
(size_t)l_sStat.st_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
l_iMFD,
0
);
if ( (NULL == l_pBuffer)
|| (MAP_FAILED == l_pBuffer)
)
{
l_bResult = FALSE;
goto l_lblExit;
}
memcpy(l_pBuffer, i_pData, (size_t)i_wSize);
if (0 == munmap(l_pBuffer, (size_t)l_sStat.st_size))
{
l_pBuffer = NULL;
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
if (0 <= l_iMFD)
{
close(l_iMFD);
l_iMFD = -1;
}
return l_bResult;
}//Write
////////////////////////////////////////////////////////////////////////////
//Lock
static eLock Lock(const tXCHAR *i_pName, CShared::hSem &o_rSem, tUINT32 i_dwTimeout_ms)
{
eLock l_eReturn = CShared::E_TIMEOUT;
size_t l_szName = 0;
char *l_pName = NULL;
const int l_i1ms = 1000;
tINT64 l_llWait = (tINT64)i_dwTimeout_ms * 1000LL;
sem_t *l_hSem = SHARED_SEM_NULL;
o_rSem = SHARED_SEM_NULL;
if (NULL == i_pName)
{
l_eReturn = CShared::E_ERROR;
goto l_lblExit;
}
l_szName = strlen(i_pName) + SHARED_NAME_LEN;
l_pName = (char*)malloc(l_szName);
if (NULL == l_pName)
{
l_eReturn = CShared::E_ERROR;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////
//open semaphore
Create_Name(l_pName, l_szName, ETYPE_MUTEX, i_pName);
l_hSem = sem_open(l_pName, 0);
if (SHARED_SEM_NULL == l_hSem)
{
l_eReturn = CShared::E_NOT_EXISTS;
goto l_lblExit;
}
l_eReturn = CShared::E_TIMEOUT;
while (0 < l_llWait)
{
if (0 == sem_trywait(l_hSem))
{
l_eReturn = CShared::E_OK;
break;
}
else
{
usleep(l_i1ms); //10 ms
l_llWait -= l_i1ms;
}
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
if (SHARED_SEM_NULL != l_hSem)
{
if (CShared::E_OK == l_eReturn)
{
o_rSem = l_hSem;
}
else
{
sem_close(l_hSem);
l_hSem = SHARED_SEM_NULL;
}
}
return l_eReturn;
}//Lock
////////////////////////////////////////////////////////////////////////////
//UnLock
static eLock UnLock(CShared::hSem &io_rSem)
{
eLock l_eReturn = CShared::E_ERROR;
if (SHARED_SEM_NULL == io_rSem)
{
l_eReturn = CShared::E_NOT_EXISTS;
goto l_lblExit;
}
if (0 == sem_post(io_rSem))
{
l_eReturn = CShared::E_OK;
}
sem_close(io_rSem);
io_rSem = SHARED_SEM_NULL;
l_lblExit:
return l_eReturn;
}//UnLock
////////////////////////////////////////////////////////////////////////////
//GetSemName
static const tXCHAR* GetName(hShared i_pShared)
{
if (NULL == i_pShared)
{
return FALSE;
}
return i_pShared->pName;
}
////////////////////////////////////////////////////////////////////////////
//Close
static tBOOL Close(hShared i_pShared)
{
if (NULL == i_pShared)
{
return FALSE;
}
//if (SHARED_SEM_NULL != i_pShared->hSemaphore)
//{
// sem_wait(i_pShared->hSemaphore);
//}
if (0 <= i_pShared->iMFD)
{
close(i_pShared->iMFD);
i_pShared->iMFD = -1;
}
if (i_pShared->pMemName)
{
shm_unlink(i_pShared->pMemName);
}
if (SHARED_SEM_NULL != i_pShared->hSemaphore)
{
int l_iRes = -1;
l_iRes = sem_close(i_pShared->hSemaphore);
i_pShared->hSemaphore = SHARED_SEM_NULL;
UNUSED_ARG(l_iRes);
}
if (i_pShared->pSemName)
{
sem_unlink(i_pShared->pSemName);
free(i_pShared->pSemName);
i_pShared->pSemName = NULL;
}
if (i_pShared->pMemName)
{
free(i_pShared->pMemName);
i_pShared->pMemName = NULL;
}
if (i_pShared->pName)
{
free(i_pShared->pName);
i_pShared->pName = NULL;
}
i_pShared->szName = 0;
free(i_pShared);
i_pShared = NULL;
return TRUE;
}//Close
////////////////////////////////////////////////////////////////////////////
//UnLink
static tBOOL UnLink(const tXCHAR *i_pName)
{
tBOOL l_bReturn = TRUE;
size_t l_szName = 0;
char *l_pName = NULL;
if (NULL == i_pName)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_szName = strlen(i_pName) + SHARED_NAME_LEN;
l_pName = (char*)malloc(l_szName);
if (NULL == l_pName)
{
l_bReturn = FALSE;
goto l_lblExit;
}
Create_Name(l_pName, l_szName, ETYPE_MUTEX, i_pName);
if (0 != sem_unlink(l_pName))
{
l_bReturn = FALSE;
}
Create_Name(l_pName, l_szName, ETYPE_FILE, i_pName);
if (0 != shm_unlink(l_pName))
{
l_bReturn = FALSE;
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
return l_bReturn;
}//UnLink
private:
////////////////////////////////////////////////////////////////////////////
//Create_Name
static tBOOL Create_Name(tXCHAR *o_pName,
size_t i_szName,
eType i_eType,
const tXCHAR *i_pPostfix
)
{
if ( (NULL == o_pName)
|| (16 >= i_szName)
|| (ETYPE_MAX <= i_eType)
|| (NULL == i_pPostfix)
)
{
return FALSE;
}
snprintf(o_pName, i_szName, SHARED_NAME_FORMAT_STRING, i_eType, getpid(), i_pPostfix);
return TRUE;
}//Create_Name
};
#endif //PSHARED_H

View File

@ -0,0 +1,75 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef IPSHARED_LIB_H
#define IPSHARED_LIB_H
#include "GTypes.h"
#include "Length.h"
#include "PString.h"
#include "WString.h"
#include "SharedLib.h"
#include "PAtomic.h"
#include <dlfcn.h>
class CPSharedLib
: public CSharedLib
{
protected:
void *m_pSo;
public:
CPSharedLib(const tXCHAR *i_pPath)
: CSharedLib(i_pPath)
, m_pSo(NULL)
{
m_pSo = dlopen(i_pPath, RTLD_LAZY);
if (m_pSo)
{
m_bState = TRUE;
}
}
void *GetFunction(const tACHAR *i_pName)
{
dlerror(); /* Clear any existing error */
void* l_pReturn = (void*) (dlsym(m_pSo, i_pName));
if (NULL != dlerror())
{
return NULL;
}
return l_pReturn;
}
virtual ~CPSharedLib()
{
if (m_pSo)
{
dlclose(m_pSo);
m_pSo = NULL;
}
}
};
#endif //IPSHARED_LIB_H

View File

@ -0,0 +1,217 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PSIGNAL_H
#define PSIGNAL_H
#include <stdio.h>
#include <stdlib.h>
#include "signal.h"
#include <time.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <features.h>
#include "ISignal.h"
//Linux signal handling article:
//http://www.linuxprogrammingblog.com/all-about-linux-signals?page=show
static stChContext g_stContext = {0};
////////////////////////////////////////////////////////////////////////////////
//Get_Signal_Text
static __attribute__ ((unused)) const char *ChGetSignalText(int i_iSignal, siginfo_t* i_pSigInfo)
{
if (i_iSignal == SIGBUS)
{
if (i_pSigInfo->si_code == BUS_ADRALN) { return "SIGBUS::BUS_ADRALN"; }
else if (i_pSigInfo->si_code == BUS_ADRERR) { return "SIGBUS::BUS_ADRERR"; }
else if (i_pSigInfo->si_code == BUS_OBJERR) { return "SIGBUS::BUS_OBJERR"; }
else { return "SIGBUS::<unknown>"; }
}
else if (i_iSignal == SIGFPE)
{
if (i_pSigInfo->si_code == FPE_FLTDIV) { return "SIGFPE::FPE_FLTDIV"; }
else if (i_pSigInfo->si_code == FPE_FLTINV) { return "SIGFPE::FPE_FLTINV"; }
else if (i_pSigInfo->si_code == FPE_FLTOVF) { return "SIGFPE::FPE_FLTOVF"; }
else if (i_pSigInfo->si_code == FPE_FLTRES) { return "SIGFPE::FPE_FLTRES"; }
else if (i_pSigInfo->si_code == FPE_FLTSUB) { return "SIGFPE::FPE_FLTSUB"; }
else if (i_pSigInfo->si_code == FPE_FLTUND) { return "SIGFPE::FPE_FLTUND"; }
else if (i_pSigInfo->si_code == FPE_INTDIV) { return "SIGFPE::FPE_INTDIV"; }
else if (i_pSigInfo->si_code == FPE_INTOVF) { return "SIGFPE::FPE_INTOVF"; }
else { return "SIGFPE::<unknown>"; }
}
else if (i_iSignal == SIGILL)
{
if (i_pSigInfo->si_code == ILL_BADSTK) { return "SIGILL::ILL_BADSTK"; }
else if (i_pSigInfo->si_code == ILL_COPROC) { return "SIGILL::ILL_COPROC"; }
else if (i_pSigInfo->si_code == ILL_ILLOPN) { return "SIGILL::ILL_ILLOPN"; }
else if (i_pSigInfo->si_code == ILL_ILLADR) { return "SIGILL::ILL_ILLADR"; }
else if (i_pSigInfo->si_code == ILL_ILLTRP) { return "SIGILL::ILL_ILLTRP"; }
else if (i_pSigInfo->si_code == ILL_PRVOPC) { return "SIGILL::ILL_PRVOPC"; }
else if (i_pSigInfo->si_code == ILL_PRVREG) { return "SIGILL::ILL_PRVREG"; }
else { return "SIGILL::<unknown>"; }
}
else if (i_iSignal == SIGSEGV)
{
if (i_pSigInfo->si_code == SEGV_MAPERR) { return "SIGSEGV::SEGV_MAPERR"; }
else if (i_pSigInfo->si_code == SEGV_ACCERR){ return "SIGSEGV::SEGV_ACCERR"; }
else { return "SIGSEGV::<unknown>"; }
}
return "<unknown>::<unknown>";
}//Get_Signal_Text
////////////////////////////////////////////////////////////////////////////////
//ChHandler
static __attribute__ ((unused)) void ChHandler(int i_iSignal,
siginfo_t *i_pSigInfo,
void *i_pContext
)
{
UNUSED_ARG(i_pContext);
if (g_stContext.iProcessed)
{
return;
}
g_stContext.iProcessed = 1;
const char *l_pText = ChGetSignalText(i_iSignal, i_pSigInfo);
if (g_stContext.pUserHandler)
{
g_stContext.pUserHandler((eCrashCode)(eCrashSignal + i_iSignal), l_pText, g_stContext.pUserContext);
}
printf("Process has been terminated by signal {%s}\n", l_pText);
}//ChHandler
////////////////////////////////////////////////////////////////////////////////
//ChInstall
static __attribute__ ((unused)) tBOOL ChInstallPrivate()
{
struct sigaction l_sSignal;
struct sigaction l_sSignalPipe;
tBOOL l_bReturn = TRUE;
////////////////////////////////////////////////////////////////////////////
// installing signal handling ...
memset(&l_sSignalPipe, 0, sizeof(l_sSignalPipe));
memset(&l_sSignal, 0, sizeof(l_sSignal));
//remove SIGPIPE signal, should be ignored
l_sSignalPipe.sa_handler = SIG_IGN;
sigemptyset(&l_sSignalPipe.sa_mask);
l_bReturn = (sigaction(SIGPIPE, &l_sSignalPipe, NULL) == 0);
l_sSignal.sa_flags = SA_RESETHAND | SA_SIGINFO;
l_sSignal.sa_sigaction = &ChHandler;
sigemptyset(&l_sSignal.sa_mask);
l_bReturn &= (sigaction(SIGILL, &l_sSignal, NULL) == 0);
l_bReturn &= (sigaction(SIGABRT, &l_sSignal, NULL) == 0);
l_bReturn &= (sigaction(SIGFPE, &l_sSignal, NULL) == 0);
l_bReturn &= (sigaction(SIGBUS, &l_sSignal, NULL) == 0);
l_bReturn &= (sigaction(SIGSEGV, &l_sSignal, NULL) == 0);
if (!l_bReturn)
{
printf("ERROR: can't initialize signal handler");
}
return l_bReturn;
}//ChInstall
////////////////////////////////////////////////////////////////////////////////
//ChInstall
static __attribute__ ((unused)) tBOOL ChInstall()
{
tBOOL l_bReturn = TRUE;
if (g_stContext.iInstalled)
{
return FALSE;
}
memset(&g_stContext, 0, sizeof(g_stContext));
g_stContext.iProcessed = 0;
l_bReturn = ChInstallPrivate();
if (l_bReturn)
{
g_stContext.iInstalled = 1;
}
else
{
printf("ERROR: can't initialize signal handler");
}
return l_bReturn;
}//ChInstall
////////////////////////////////////////////////////////////////////////////////
//ChSetHandler
static __attribute__ ((unused)) tBOOL ChSetHandler(fnCrashHandler i_fnHandler)
{
if (!g_stContext.iInstalled)
{
return FALSE;
}
g_stContext.pUserHandler = i_fnHandler;
return TRUE;
}//ChSetHandler
////////////////////////////////////////////////////////////////////////////////
//ChSetContext
static __attribute__ ((unused)) tBOOL ChSetContext(void *i_pContext)
{
if (!g_stContext.iInstalled)
{
return FALSE;
}
g_stContext.pUserContext = i_pContext;
return TRUE;
}//ChSetContext
////////////////////////////////////////////////////////////////////////////////
//ChUnInstall
static __attribute__ ((unused)) tBOOL ChUnInstall()
{
return TRUE;
}//ChUnInstall
#endif //PSIGNAL_H

View File

@ -0,0 +1,237 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PSOCKET_H
#define PSOCKET_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <ifaddrs.h>
#include "AList.h"
#include <string.h>
#ifdef __ARM_ARCH_5TEJ__
#define SERVER_RECV_BUFFER_SIZE (0x200000) //2mb
#define SERVER_SEND_BUFFER_SIZE (0x40000) //256kb
#define CLIENT_RECV_BUFFER_SIZE (0x4000) //16 kb
#define CLIENT_SEND_BUFFER_SIZE (0x10000) //64 kb
#else
#define SERVER_RECV_BUFFER_SIZE (0x200000) //2mb
#define SERVER_SEND_BUFFER_SIZE (0x40000) //256kb
#define CLIENT_RECV_BUFFER_SIZE (0x40000) //256 kb
#define CLIENT_SEND_BUFFER_SIZE (0x40000) //256 kb
#endif
typedef int tSOCKET;
//typedef SOCKET tSOCKET;
typedef socklen_t tADDR_LEN;
//typedef int tADDR_LEN;
typedef addrinfo tADDR_INFO;
//typedef addrinfoW tADDR_INFO;
#define INVALID_SOCKET_VAL (-1)
//(INVALID_SOCKET)
#define CONNECTION_IN_PROGRESS (EINPROGRESS)
//(WSAEWOULDBLOCK)
#define CLOSE_SOCKET(i_Socket) close(i_Socket)
//closesocket(m_hSocket);
#define GET_SOCKET_ERROR() errno
//WSAGetLastError();
#define SOCKET_ERROR (-1)
#define GET_ADDR_INFO(i_Node, i_Service, i_Hints, o_Res) getaddrinfo(i_Node,\
i_Service,\
i_Hints,\
o_Res)
//GetAddrInfoW
#define FREE_ADDR_INFO(i_Info) freeaddrinfo(i_Info)
//FreeAddrInfoW
////////////////////////////////////////////////////////////////////////////////
//WSA_Init
static __attribute__ ((unused)) tBOOL WSA_Init()
{
return TRUE;
//WSADATA l_tWSA;
//
//if (0 != WSAStartup(MAKEWORD(1,1), &l_tWSA))
//{
// return FALSE;
//}
//return TRUE;
}//WSA_Init
////////////////////////////////////////////////////////////////////////////////
//WSA_UnInit
static __attribute__ ((unused)) void WSA_UnInit()
{
//WSACleanup();
}//WSA_UnInit
////////////////////////////////////////////////////////////////////////////////
//PEnumIps
static __attribute__ ((unused)) tBOOL PEnumIps(CBList<sockaddr_storage*> *io_pList)
{
if (!io_pList)
{
return FALSE;
}
io_pList->Clear(TRUE);
struct ifaddrs *l_pIfAddr = NULL;
if (-1 == getifaddrs(&l_pIfAddr))
{
return FALSE;
}
for (struct ifaddrs *l_pAddr = l_pIfAddr; l_pAddr != NULL; l_pAddr = l_pAddr->ifa_next)
{
if ( (l_pAddr->ifa_addr == NULL)
|| ( (AF_INET != l_pAddr->ifa_addr->sa_family)
&& (AF_INET6 != l_pAddr->ifa_addr->sa_family)
)
)
{
continue;
}
sockaddr_storage *l_pNew = new sockaddr_storage;
if (AF_INET == l_pAddr->ifa_addr->sa_family)
{
memcpy(l_pNew, l_pAddr->ifa_addr, sizeof(sockaddr_in));
}
else if (AF_INET6 == l_pAddr->ifa_addr->sa_family)
{
memcpy(l_pNew, l_pAddr->ifa_addr, sizeof(sockaddr_in6));
}
else
{
memset(l_pNew, 0, sizeof(sockaddr_storage));
}
io_pList->Add_After(NULL, l_pNew);
}
freeifaddrs(l_pIfAddr);
return TRUE;
}//PEnumIps
////////////////////////////////////////////////////////////////////////////////
//Print_SAddr
static __attribute__ ((unused)) tBOOL Print_SAddr(sockaddr *i_pAddress, XCHAR *o_pIP, tUINT32 i_dwLen)
{
tBOOL l_bReturn = FALSE;
if ( (NULL == i_pAddress)
|| (NULL == o_pIP)
|| (15 >= i_dwLen)
)
{
return l_bReturn;
}
if (AF_INET6 == i_pAddress->sa_family)
{
if (NULL != inet_ntop(i_pAddress->sa_family,
&((sockaddr_in6*)i_pAddress)->sin6_addr,
o_pIP,
i_dwLen
)
)
{
l_bReturn = TRUE;
}
}
else if (AF_INET == i_pAddress->sa_family)
{
if (NULL != inet_ntop(i_pAddress->sa_family,
&((sockaddr_in*)i_pAddress)->sin_addr,
o_pIP,
i_dwLen
)
)
{
l_bReturn = TRUE;
}
}
//WSAAddressToString(i_pAddress,
// m_dwAddress_Size,
// NULL,
// l_pIP,
// &l_dwSize);
return l_bReturn;
}//Print_SAddr
////////////////////////////////////////////////////////////////////////////////
//Disable_PortUnreachable_ICMP
static __attribute__ ((unused)) tBOOL Disable_PortUnreachable_ICMP(tSOCKET i_hSocket)
{
UNUSED_ARG(i_hSocket);
//tUINT32 l_dwBytesReturned = 0;
//tBOOL l_bNewBehavior = FALSE;
//tUINT32 l_dwStatus = 0;
//
//
//l_dwStatus = WSAIoctl(m_hSocket,
// SIO_UDP_CONNRESET,
// &l_bNewBehavior,
// sizeof(l_bNewBehavior),
// NULL,
// 0,
// &l_dwBytesReturned,
// NULL,
// NULL
// );
//return (SOCKET_ERROR == l_dwStatus) ? FALSE : TRUE;
//don't know how to do it under Linux yet.
return TRUE;
}//Disable_PortUnreachable_ICMP
#endif //PSOCKET_H

View File

@ -0,0 +1,245 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PSTRING_H
#define PSTRING_H
#if !defined(PRINTF)
#if defined(UTF8_ENCODING)
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...) wprintf(__VA_ARGS__)
#endif
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "UTF.h"
////////////////////////////////////////////////////////////////////////////////
//PStrLen
static __attribute__ ((unused)) tUINT32 PStrLen(const tXCHAR *i_pText)
{
return strlen(i_pText);
}//PStrLen
////////////////////////////////////////////////////////////////////////////////
//PStrCpy
static __attribute__ ((unused)) tXCHAR* PStrCpy(tXCHAR *i_pDst,
size_t i_szDst,
const tXCHAR *i_pSrc)
{
UNUSED_ARG(i_szDst);
return strcpy(i_pDst, i_pSrc);
}//PStrLen
////////////////////////////////////////////////////////////////////////////////
//PWStrCpy
static inline tWCHAR *PWStrCpy(tWCHAR *i_pDst,
size_t i_szDst,
const tWCHAR *i_pSrc
)
{
while ( (*i_pSrc)
&& (1 < i_szDst)
)
{
*i_pDst = *i_pSrc;
i_pDst++; i_pSrc++;
i_szDst--;
}
*i_pDst = 0;
return i_pDst;
}//PStrLen
////////////////////////////////////////////////////////////////////////////////
//PStrCpy
static __attribute__ ((unused)) tXCHAR* PStrNCpy(tXCHAR *i_pDst,
size_t i_szDst,
const tXCHAR *i_pSrc,
size_t i_pSrcMaxCount
)
{
UNUSED_ARG(i_szDst);
strncpy((char*)i_pDst, (char*)i_pSrc, i_pSrcMaxCount);
return i_pDst;
}//PStrLen
////////////////////////////////////////////////////////////////////////////////
//PStrNCmp
static __attribute__ ((unused)) tINT32 PStrNCmp(const tXCHAR *i_pS1,
const tXCHAR *i_pS2,
size_t i_szLen
)
{
return strncmp(i_pS1, i_pS2, i_szLen);
}//PStrNCmp
////////////////////////////////////////////////////////////////////////////////
//PStrNCmp
static __attribute__ ((unused)) tINT32 PStrNiCmp(const tXCHAR *i_pS1,
const tXCHAR *i_pS2,
size_t i_szLen
)
{
return strncasecmp(i_pS1, i_pS2, i_szLen);
}//PStrNCmp
////////////////////////////////////////////////////////////////////////////////
//PStrNCmp
static __attribute__ ((unused)) tINT32 PStrICmp(const tXCHAR *i_pS1,
const tXCHAR *i_pS2
)
{
return strcasecmp(i_pS1, i_pS2);
}//PStrNCmp
////////////////////////////////////////////////////////////////////////////////
//PStrCmp
static __attribute__ ((unused)) tINT32 PStrCmp(const tXCHAR *i_pS1,
const tXCHAR *i_pS2
)
{
return strcmp(i_pS1, i_pS2);
}//PStrCmp
////////////////////////////////////////////////////////////////////////////////
//PStrToInt
static __attribute__ ((unused)) tINT32 PStrToInt(const tXCHAR *i_pS1)
{
return atoi(i_pS1);
}//PStrToInt
////////////////////////////////////////////////////////////////////////////////
//PUStrLen
static __attribute__ ((unused)) tUINT32 PUStrLen(const tXCHAR *i_pText)
{
return Get_UTF8_Length(i_pText);
}//PUStrLen
////////////////////////////////////////////////////////////////////////////////
//PUStrCpy
static __attribute__ ((unused)) void PUStrCpy(tWCHAR *i_pDst,
tUINT32 i_dwMax_Len,
const tXCHAR *i_pSrc)
{
Convert_UTF8_To_UTF16(i_pSrc, i_pDst, i_dwMax_Len);
//wcscpy_s(i_pDst, i_dwMax_Len, i_pSrc);
}//PUStrCpy
///////////////////////////////////////////////////////////////////////////////
//PSPrint
static __attribute__ ((unused)) tINT32 PSPrint(tXCHAR *o_pBuffer,
size_t i_szBuffer,
const tXCHAR *i_pFormat,
...
)
{
va_list l_pVA;
int l_iReturn = 0;
va_start(l_pVA, i_pFormat);
l_iReturn = vsnprintf((char*)o_pBuffer,
i_szBuffer,
(char*)i_pFormat,
l_pVA);
va_end(l_pVA);
return (tINT32)l_iReturn;
}//PSPrint
///////////////////////////////////////////////////////////////////////////////
//PStrDub
static __attribute__ ((unused)) tXCHAR *PStrDub(const tXCHAR *i_pStr)
{
return strdup(i_pStr);
}//PStrDub
///////////////////////////////////////////////////////////////////////////////
//PStrFreeDub
static __attribute__ ((unused)) void PStrFreeDub(tXCHAR *i_pStr)
{
free(i_pStr);
}//PStrFreeDub
///////////////////////////////////////////////////////////////////////////////
//PStrChr
static const __attribute__ ((unused)) tXCHAR *PStrChr(const tXCHAR * i_pStr, tXCHAR i_cCh)
{
return strchr(i_pStr, i_cCh);
}//PStrChr
///////////////////////////////////////////////////////////////////////////////
//PStrChr
static __attribute__ ((unused)) tXCHAR *PStrChr(tXCHAR * i_pStr, tXCHAR i_cCh)
{
return strchr(i_pStr, i_cCh);
}//PStrChr
///////////////////////////////////////////////////////////////////////////////
//PStrrChr
static const __attribute__ ((unused)) tXCHAR *PStrrChr(const tXCHAR * i_pStr, const tXCHAR i_cCh)
{
return strrchr(i_pStr, i_cCh);
}//PStrrChr
///////////////////////////////////////////////////////////////////////////////
//PStrrChr
static __attribute__ ((unused)) tXCHAR *PStrrChr(tXCHAR * i_pStr, tXCHAR i_cCh)
{
return strrchr(i_pStr, i_cCh);
}//PStrrChr
///////////////////////////////////////////////////////////////////////////////
//PVsnprintf
static __attribute__ ((unused)) int PVsnprintf(tXCHAR *o_pBuffer,
size_t i_szBuffer,
const tXCHAR *i_pFormat,
va_list i_pArgs)
{
return vsnprintf(o_pBuffer, i_szBuffer, i_pFormat, i_pArgs);
}//PVsnprintf
///////////////////////////////////////////////////////////////////////////////
//PStrScan
#define PStrScan(i_pBuffer, i_pFormat, ...) sscanf(i_pBuffer, i_pFormat, __VA_ARGS__)
#endif //PSTRING_H

View File

@ -0,0 +1,100 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PSYSTEM_H
#define PSYSTEM_H
#include <unistd.h>
class CSys
{
public:
///////////////////////////////////////////////////////////////////////////////
//Get_Host_Name
static tBOOL Get_Host_Name(tWCHAR *o_pName, size_t i_szName)
{
const size_t l_szName = 256;
char l_pName[l_szName];
if (0 == gethostname(l_pName, l_szName))
{
//If the null-terminated hostname is too large to fit, then the name
//is truncated, and no error is returned (but see NOTES below).
//POSIX.1-2001 says that if such truncation occurs, then it is
//unspecified whether the returned buffer includes a terminating
//null byte.
l_pName[l_szName-1] = 0;
}
else
{
strcpy(l_pName, "Unknown:Error");
}
Convert_UTF8_To_UTF16(l_pName, o_pName, i_szName);
return TRUE;
}//Get_Host_Name
///////////////////////////////////////////////////////////////////////////////
//Get_Host_Name
static tBOOL Get_Host_Name(tACHAR *o_pName, size_t i_szName)
{
if (0 == gethostname(o_pName, i_szName))
{
//If the null-terminated hostname is too large to fit, then the name
//is truncated, and no error is returned (but see NOTES below).
//POSIX.1-2001 says that if such truncation occurs, then it is
//unspecified whether the returned buffer includes a terminating
//null byte.
o_pName[i_szName-1] = 0;
}
else
{
strcpy(o_pName, "Unknown:Error");
}
return TRUE;
}//Get_Host_Name
///////////////////////////////////////////////////////////////////////////////
//Get_DateTime
static tBOOL Get_DateTime(tUINT32 &o_rYear,
tUINT32 &o_rMonth,
tUINT32 &o_rDay,
tUINT32 &o_rHour,
tUINT32 &o_rMinute,
tUINT32 &o_rSecond,
tUINT32 &o_rmSec
)
{
time_t l_sTime = time(NULL);
struct tm l_sTM = *localtime(&l_sTime);
o_rYear = (uint32_t)(l_sTM.tm_year + 1900);
o_rMonth = (uint32_t)(l_sTM.tm_mon + 1);
o_rDay = (uint32_t)l_sTM.tm_mday;
o_rHour = (uint32_t)l_sTM.tm_hour;
o_rMinute = (uint32_t)l_sTM.tm_min;
o_rSecond = (uint32_t)l_sTM.tm_sec;
o_rmSec = 0;
return TRUE;
}//Get_Host_Name
};
#endif //PSYSTEM_H

View File

@ -0,0 +1,110 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PTHREADSHELL_H
#define PTHREADSHELL_H
#define THSHELL_CALL_TYPE
#define THSHELL_RET_TYPE void*
#define THSHELL_RET_OK NULL
#define THSHELL_RET_NOK 0xDEAD
#include <unistd.h>
////////////////////////////////////////////////////////////////////////////////
class CThShell
{
public:
////////////////////////////////////////////////////////////////////////////
//Base types
typedef pthread_t tTHREAD;
typedef THSHELL_RET_TYPE (THSHELL_CALL_TYPE *tpThreadProc)(void *i_pParameter);
////////////////////////////////////////////////////////////////////////////
//Create
static tBOOL Create(tpThreadProc i_pThread_Proc,
void *i_pPrm,
tTHREAD *o_pThread,
const tXCHAR *i_pName
)
{
UNUSED_ARG(i_pName);
if ( ( NULL == i_pThread_Proc )
|| ( NULL == o_pThread )
)
{
return FALSE;
}
*o_pThread = 0;
pthread_attr_t l_sAttr;
int l_iResult = -1;
pthread_attr_init(&l_sAttr);
pthread_attr_setdetachstate(&l_sAttr, PTHREAD_CREATE_JOINABLE);
l_iResult = pthread_create(o_pThread, &l_sAttr, i_pThread_Proc, i_pPrm);
pthread_attr_destroy(&l_sAttr);
#ifdef __USE_GNU
//if ( (0 == l_iResult)
// && (i_pName)
// )
//{
// pthread_setname_np(pthread_self(), i_pName);
//}
#endif
return (0 == l_iResult) ? TRUE : FALSE;
}//Create
////////////////////////////////////////////////////////////////////////////
//Cleanup
static void Cleanup()
{
}//Thread_Cleanup
////////////////////////////////////////////////////////////////////////////
//Close
static tBOOL Close(tTHREAD i_hThread, tUINT32 i_dwTimeOut)
{
UNUSED_ARG(i_dwTimeOut);
void *l_pRet = THSHELL_RET_OK;
tUINT32 l_iResult = pthread_join(i_hThread, &l_pRet);
return (( 0 == l_iResult ) && (THSHELL_RET_OK == l_pRet)) ? TRUE : FALSE;
}//Close
////////////////////////////////////////////////////////////////////////////
//Sleep
static void Sleep(tUINT32 i_dwTimeOut)
{
usleep(1000 * i_dwTimeOut);
}//Sleep
};
#endif //PTHREADSHELL_H

View File

@ -0,0 +1,241 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PTIME_H
#define PTIME_H
#include <sys/time.h>
#include <time.h>
//time offset from January 1, 1601 to January 1, 1970, resolution 100ns
#define TIME_OFFSET_1601_1970 (116444736000000000ULL)
#define TIME_HRS_100NS 36000000000ull
#define TIME_MIN_100NS 600000000ull
#define TIME_SEC_100NS 10000000ull
#define TIME_MLSC_100NS 10000ull
#define TIME_MCSC_100NS 10ull
#define TIME_ZONE_AVALIABLE
////////////////////////////////////////////////////////////////////////////////
//GetTickCount
static __attribute__ ((unused)) tUINT32 GetTickCount()
{
tUINT64 l_qwReturn; //Warn:without initialization !
//timeval l_sTime;
//gettimeofday(&l_sTime, NULL);
struct timespec l_sTime = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &l_sTime);
l_qwReturn = l_sTime.tv_sec;
l_qwReturn *= 1000;
l_qwReturn += l_sTime.tv_nsec/1000000;
return (tUINT32)l_qwReturn;
}//GetTickCount
////////////////////////////////////////////////////////////////////////////////
//GetPerformanceCounter
static __attribute__ ((unused)) tUINT64 GetPerformanceCounter()
{
tUINT64 l_qwReturn = 0;
struct timespec l_sTime = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &l_sTime);
l_qwReturn = (tUINT64)(l_sTime.tv_sec) * 10000000;
l_qwReturn += (tUINT64)(l_sTime.tv_nsec) / 100;
return l_qwReturn;
}//GetPerformanceCounter
////////////////////////////////////////////////////////////////////////////////
//GetPerformanceFrequency
static __attribute__ ((unused)) tUINT64 GetPerformanceFrequency()
{
return 10000000; //100 nano second
}//GetPerformanceFrequency
////////////////////////////////////////////////////////////////////////////////
//UnpackLocalTime
//convert a 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC)
//to readable form
static __attribute__ ((unused)) void UnpackLocalTime(tUINT64 i_qwTime,
tUINT32 &o_rYear,
tUINT32 &o_rMonth,
tUINT32 &o_rDay,
tUINT32 &o_rHour,
tUINT32 &o_rMinutes,
tUINT32 &o_rSeconds,
tUINT32 &o_rMilliseconds,
tUINT32 &o_rMicroseconds,
tUINT32 &o_rNanoseconds
)
{
tUINT32 l_dwReminder = i_qwTime % TIME_MLSC_100NS; //micro & 100xNanoseconds
tUINT32 l_dwNano = i_qwTime % 10;
tUINT32 l_dwMicro = l_dwReminder / 10;
i_qwTime -= l_dwReminder;
tUINT32 l_dwMilli = (i_qwTime % TIME_SEC_100NS) / TIME_MLSC_100NS;
i_qwTime -= TIME_OFFSET_1601_1970;
time_t l_llTime = i_qwTime / TIME_SEC_100NS;
tm *l_pTime = localtime(&l_llTime);
if (l_pTime)
{
o_rYear = 1900 + l_pTime->tm_year;
o_rMonth = 1 + l_pTime->tm_mon;
o_rDay = l_pTime->tm_mday;
o_rHour = l_pTime->tm_hour;
o_rMinutes = l_pTime->tm_min;
o_rSeconds = l_pTime->tm_sec;
o_rMilliseconds = l_dwMilli;
o_rMicroseconds = l_dwMicro;
o_rNanoseconds = l_dwNano;
}
else
{
o_rYear = 0;
o_rMonth = 0;
o_rDay = 0;
o_rHour = 0;
o_rMinutes = 0;
o_rSeconds = 0;
o_rMilliseconds = l_dwMilli;
o_rMicroseconds = l_dwMicro;
o_rNanoseconds = l_dwNano;
}
}//UnpackLocalTime
////////////////////////////////////////////////////////////////////////////////
//PackLocalTime
//convert date & time to 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC)
static __attribute__ ((unused)) tUINT64 PackLocalTime(tUINT32 i_uiYear,
tUINT32 i_uiMonth,
tUINT32 i_uiDay,
tUINT32 i_uiHour,
tUINT32 i_uiMinutes,
tUINT32 i_uiSeconds,
tUINT32 i_uiMilliseconds,
tUINT32 i_uiMicroseconds,
tUINT32 i_uiNanoseconds
)
{
tm l_stTime = {0};
l_stTime.tm_year = (int)i_uiYear - 1900;
l_stTime.tm_mon = (int)i_uiMonth - 1;
l_stTime.tm_mday = (int)i_uiDay;
l_stTime.tm_hour = (int)i_uiHour;
l_stTime.tm_min = (int)i_uiMinutes;
l_stTime.tm_sec = (int)i_uiSeconds;
l_stTime.tm_isdst = -1;
time_t l_qwTimeT = mktime(&l_stTime);
tUINT64 l_qwReturn = l_qwTimeT * TIME_SEC_100NS;
l_qwReturn += TIME_OFFSET_1601_1970;
l_qwReturn += (i_uiMilliseconds * TIME_MLSC_100NS) + (i_uiMicroseconds * 10ull) + (i_uiNanoseconds / 100ull);
return l_qwReturn;
}//PackLocalTime
////////////////////////////////////////////////////////////////////////////////
//GetSecondOfDay
static inline tUINT32 GetSecondOfDay()
{
time_t l_llRawtime;
time(&l_llRawtime);
tm *l_pTime = localtime(&l_llRawtime);
if (l_pTime)
{
return 3600 * (tUINT32)l_pTime->tm_hour + (tUINT32)l_pTime->tm_min * 60 + l_pTime->tm_sec;
}
return 0;
}//GetSecondOfDay
////////////////////////////////////////////////////////////////////////////////
//GetEpochTime
//return a 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC).
static __attribute__ ((unused)) void GetEpochTime(tUINT32 *o_pHi, tUINT32 *o_pLow)
{
tUINT64 l_qwResult = 0;
struct timeval l_sTime = {0, 0};
gettimeofday(&l_sTime, NULL);
l_qwResult = (tUINT64)(l_sTime.tv_sec) * TIME_SEC_100NS;
l_qwResult += (tUINT64)(l_sTime.tv_usec) * TIME_MCSC_100NS;
l_qwResult += TIME_OFFSET_1601_1970;
if (o_pHi)
{
*o_pHi = (tUINT32)(l_qwResult >> 32);
}
if (o_pLow)
{
*o_pLow = (tUINT32)(l_qwResult & 0xFFFFFFFF);
}
}//GetEpochTime
////////////////////////////////////////////////////////////////////////////////
//GetEpochTime
//return a 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC).
static inline tUINT64 GetEpochTime()
{
tUINT32 dwHighDateTime = 0, dwLowDateTime = 0;
GetEpochTime(&dwHighDateTime, &dwLowDateTime);
return (((tUINT64)dwHighDateTime) << 32ull) + (tUINT64)dwLowDateTime;
}//GetEpochTime
////////////////////////////////////////////////////////////////////////////////
//GetUtcOffsetSeconds
//return UTC0 offset in seconds
static inline tINT32 GetUtcOffsetSeconds()
{
#if defined(TIME_ZONE_AVALIABLE)
time_t l_sTime = time(NULL);
struct tm l_stLocal = {0};
tzset();
localtime_r(&l_sTime, &l_stLocal);
return l_stLocal.tm_gmtoff;
#else
return 0;
#endif
}
#endif //PTIME_H

View File

@ -0,0 +1,27 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
///////////////////////////////////////////////////////////////////////////////
#define ATOMIC_ADD(io_Val, i_Add) InterlockedExchangeAdd((LONG volatile *)io_Val, i_Add)
#define ATOMIC_SUB(io_Val, i_Sub) InterlockedExchangeAdd((LONG volatile *)io_Val, -((tINT32)i_Sub))
#define ATOMIC_SET(io_Var, i_Val) InterlockedExchange((LONG volatile *)io_Var, (LONG)i_Val)
#define ATOMIC_INC(io_Val) InterlockedIncrement((LONG volatile *)io_Val)
#define ATOMIC_DEC(io_Val) InterlockedDecrement((LONG volatile *)io_Val)

View File

@ -0,0 +1,118 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
static inline tUINT32 Get_CRC32(tUINT8 *i_pData, size_t i_szCount)
{
tUINT32 l_dwResult = 0xFFFFFFFF;
if ( (NULL == i_pData)
|| (0 >= i_szCount)
)
{
return l_dwResult;
}
#if defined(GTX64) || defined(__linux__) || !defined(_MSC_VER)
for (size_t l_szI = 0; l_szI < i_szCount; l_szI ++)
{
l_dwResult = g_pCRC32_Table[(l_dwResult ^ i_pData[l_szI]) & 0xFF ] ^ (l_dwResult >> 8);
}
//Suppress warning that this is not used
(void)g_ppCRC32_Table;
#else
// Register use:
// eax - CRC32 value
// ebx - a lot of things
// ecx - CRC32 value
// edx - address of end of buffer
// esi - address of start of buffer
// edi - CRC32 table
__asm
{
// Save the esi and edi registers
push esi
push edi
mov ecx, l_dwResult // load dwCrc32
mov edi, g_ppCRC32_Table // Load the CRC32 table
mov esi, i_pData // Load buffer
mov ebx, i_szCount // Load dwBytesRead
lea edx, [esi + ebx] // Calculate the end of the buffer
crc32loop:
xor eax, eax // Clear the eax register
mov bl, byte ptr [esi] // Load the current source byte
mov al, cl // Copy crc value into eax
inc esi // Advance the source pointer
xor al, bl // Create the index into the CRC32 table
shr ecx, 8
mov ebx, [edi + eax * 4] // Get the value out of the table
xor ecx, ebx // xor with the current byte
cmp edx, esi // Have we reached the end of the buffer?
jne crc32loop
// Restore the edi and esi registers
pop edi
pop esi
lea eax, l_dwResult // Load the pointer to dwCrc32
mov [eax], ecx // Write the result
}
#endif
return l_dwResult;
}
// #if defined(_WIN32) || defined(_WIN64)
// tUINT32 Get_CRC32_SSE4(tUINT8 *i_pData, tUINT32 i_szCount)
// {
// tUINT32 l_dwCount = i_szCount >> 2; //count of DWORDs
// tUINT32 l_dwResult = 0x0;
//
// while (l_dwCount--)
// {
// l_dwResult = _mm_crc32_u32(l_dwResult, *(DWORD*)i_pData);
// i_pData += 4;
// }
//
// l_dwCount = i_szCount & 0x3; //bytes count at the tail
//
// while (l_dwCount--)
// {
// l_dwResult = _mm_crc32_u8(l_dwResult, *i_pData);
// i_pData ++;
// }
//
// return l_dwResult;
// }
// #endif

View File

@ -0,0 +1,598 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <conio.h>
#include "AList.h"
#include "PString.h"
#include "IConsole.h"
#include "RBTree.h"
#pragma warning( disable : 4482 )
//http://invisible-island.net/ncurses/
//https://github.com/fffaraz/awesome-cpp
//http://www.leonerd.org.uk/code/libtickit/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Is_Key_Hit
static tBOOL Is_Key_Hit(void)
{
return (_kbhit()) ? TRUE : FALSE;
}//Is_Key_Hit
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Get_Char
static tXCHAR Get_Char()
{
return _getwch();
}//Get_Char
////////////////////////////////////////////////////////////////////////////////
struct stKeyMap
{
tUINT16 wKey;
tUINT16 wValue;
stKeyMap(tUINT16 i_wKey, tUINT16 i_wValue) : wKey(i_wKey), wValue(i_wValue) {}
};
////////////////////////////////////////////////////////////////////////////////
//CDesc_Tree
class CKeysTree:
public CRBTree<stKeyMap*, tUINT16>
{
public:
////////////////////////////////////////////////////////////////////////////
//~CKeysTree
virtual ~CKeysTree()
{
Clear();
}//~CRBTree
protected:
////////////////////////////////////////////////////////////////////////////
virtual tBOOL Data_Release(stKeyMap* i_pData)
{
delete i_pData;
return TRUE; //memory used from pool, not necessary to return
}// Data_Release
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey < i_pData::key)
//FALSE - otherwise
tBOOL Is_Key_Less(tUINT16 i_pKey, stKeyMap *i_pData)
{
return (i_pKey < i_pData->wKey);
}
////////////////////////////////////////////////////////////////////////////
//Return
//TRUE - if (i_pKey == i_pData::key)
//FALSE - otherwise
tBOOL Is_Qual(tUINT16 i_pKey, stKeyMap *i_pData)
{
return (i_pKey == i_pData->wKey);
}
};//CDesc_Tree
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CConsole
: public IConsole
{
tUINT16 m_pFg[IConsole::eColorsMax];
tUINT16 m_pBg[IConsole::eColorsMax];
size_t m_szText;
tXCHAR *m_pText;
HANDLE m_hStdOut;
HANDLE m_hStdIn;
tXCHAR *m_pEmpty;
size_t m_szEmpty;
CKeysTree m_pKeys;
public:
CConsole()
{
m_szText = 32768;
m_pText = (tXCHAR*)malloc(m_szText * sizeof(tXCHAR));
m_szEmpty = 0;
m_pEmpty = NULL;
AllocEmptyString(1024);
m_pFg[IConsole::eBlack] = 0;
m_pFg[IConsole::eBlue] = FOREGROUND_BLUE;
m_pFg[IConsole::eGreen] = FOREGROUND_GREEN;
m_pFg[IConsole::eCyan] = FOREGROUND_BLUE|FOREGROUND_GREEN;
m_pFg[IConsole::eRed] = FOREGROUND_RED;
m_pFg[IConsole::eMagenta] = FOREGROUND_BLUE|FOREGROUND_RED;
m_pFg[IConsole::eBrown] = FOREGROUND_GREEN|FOREGROUND_RED;
m_pFg[IConsole::eLightGray] = FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED;
m_pFg[IConsole::eDarkGray] = FOREGROUND_INTENSITY;
m_pFg[IConsole::eLightBlue] = FOREGROUND_BLUE|FOREGROUND_INTENSITY;
m_pFg[IConsole::eLightGreen] = FOREGROUND_GREEN|FOREGROUND_INTENSITY;
m_pFg[IConsole::eLightCyan] = FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY;
m_pFg[IConsole::eLightRed] = FOREGROUND_RED|FOREGROUND_INTENSITY;
m_pFg[IConsole::eLightMagenta] = FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY;
m_pFg[IConsole::eYellow] = FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;
m_pFg[IConsole::eWhite] = FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;
m_pBg[IConsole::eBlack] = 0;
m_pBg[IConsole::eBlue] = BACKGROUND_BLUE;
m_pBg[IConsole::eGreen] = BACKGROUND_GREEN;
m_pBg[IConsole::eCyan] = BACKGROUND_BLUE|BACKGROUND_GREEN;
m_pBg[IConsole::eRed] = BACKGROUND_RED;
m_pBg[IConsole::eMagenta] = BACKGROUND_BLUE|BACKGROUND_RED;
m_pBg[IConsole::eBrown] = BACKGROUND_GREEN|BACKGROUND_RED;
m_pBg[IConsole::eLightGray] = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED;
m_pBg[IConsole::eDarkGray] = BACKGROUND_INTENSITY;
m_pBg[IConsole::eLightBlue] = BACKGROUND_BLUE|BACKGROUND_INTENSITY;
m_pBg[IConsole::eLightGreen] = BACKGROUND_GREEN|BACKGROUND_INTENSITY;
m_pBg[IConsole::eLightCyan] = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_INTENSITY;
m_pBg[IConsole::eLightRed] = BACKGROUND_RED|BACKGROUND_INTENSITY;
m_pBg[IConsole::eLightMagenta] = BACKGROUND_BLUE|BACKGROUND_RED|BACKGROUND_INTENSITY;
m_pBg[IConsole::eYellow] = BACKGROUND_GREEN|BACKGROUND_RED|BACKGROUND_INTENSITY;
m_pBg[IConsole::eWhite] = BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED|BACKGROUND_INTENSITY;
m_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
m_hStdIn = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(m_hStdIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
m_pKeys.Push(new stKeyMap(38, IConsole::eKeyArrowUp), 38);
m_pKeys.Push(new stKeyMap(40, IConsole::eKeyArrowDown), 40);
m_pKeys.Push(new stKeyMap(37, IConsole::eKeyArrowLeft), 37);
m_pKeys.Push(new stKeyMap(39, IConsole::eKeyArrowRight), 39);
m_pKeys.Push(new stKeyMap(35, IConsole::eKeyEnd), 35);
m_pKeys.Push(new stKeyMap(36, IConsole::eKeyHome), 36);
m_pKeys.Push(new stKeyMap(33, IConsole::eKeyPageUp), 33);
m_pKeys.Push(new stKeyMap(34, IConsole::eKeyPageDown), 34);
m_pKeys.Push(new stKeyMap(112, IConsole::eKeyF1), 112);
m_pKeys.Push(new stKeyMap(113, IConsole::eKeyF2), 113);
m_pKeys.Push(new stKeyMap(114, IConsole::eKeyF3), 114);
m_pKeys.Push(new stKeyMap(115, IConsole::eKeyF4), 115);
m_pKeys.Push(new stKeyMap(116, IConsole::eKeyF5), 116);
m_pKeys.Push(new stKeyMap(117, IConsole::eKeyF6), 117);
m_pKeys.Push(new stKeyMap(118, IConsole::eKeyF7), 118);
m_pKeys.Push(new stKeyMap(119, IConsole::eKeyF8), 119);
m_pKeys.Push(new stKeyMap(120, IConsole::eKeyF9), 120);
m_pKeys.Push(new stKeyMap(121, IConsole::eKeyF10), 121);
m_pKeys.Push(new stKeyMap(122, IConsole::eKeyF11), 122);
m_pKeys.Push(new stKeyMap(123, IConsole::eKeyF12), 123);
m_pKeys.Push(new stKeyMap(45, IConsole::eKeyInsert), 45);
m_pKeys.Push(new stKeyMap(46, IConsole::eKeyDel), 46);
m_pKeys.Push(new stKeyMap(9, IConsole::eKeyTab), 9);
m_pKeys.Push(new stKeyMap(8, IConsole::eKeyBackSpace), 8);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual ~CConsole()
{
if (m_pText)
{
free(m_pText);
m_pText = NULL;
}
if (m_pEmpty)
{
free(m_pEmpty);
m_pEmpty = NULL;
}
m_pKeys.Clear();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL SetCursor(tUINT32 i_uX, tUINT32 i_uY)
{
COORD l_cCoord = {(SHORT)i_uX, (SHORT)i_uY};
return SetConsoleCursorPosition(m_hStdOut, l_cCoord);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetCursorX()
{
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
{
return l_sCsbi.dwCursorPosition.X;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL GetInput(IConsole::sInput &o_rInput)
{
INPUT_RECORD l_stRecord = {};
DWORD l_dwRead = 0;
GetNumberOfConsoleInputEvents(m_hStdIn, &l_dwRead);
if (!l_dwRead)
{
return FALSE;
}
ReadConsoleInput(m_hStdIn, &l_stRecord, 1, &l_dwRead);
if (!l_dwRead)
{
return FALSE;
}
if (FOCUS_EVENT == l_stRecord.EventType)
{
o_rInput.eEvent = IConsole::eEvent::eFocus;
o_rInput.stFocus.bFocus = l_stRecord.Event.FocusEvent.bSetFocus;
}
else if (KEY_EVENT == l_stRecord.EventType)
{
o_rInput.eEvent = IConsole::eEvent::eKey;
o_rInput.stKey.bDown = l_stRecord.Event.KeyEvent.bKeyDown;
o_rInput.stKey.uControls = l_stRecord.Event.KeyEvent.dwControlKeyState;
o_rInput.stKey.wCount = l_stRecord.Event.KeyEvent.wRepeatCount;
stKeyMap *l_pKey = m_pKeys.Find(l_stRecord.Event.KeyEvent.wVirtualKeyCode);
if (l_pKey)
{
o_rInput.stKey.wKey = l_pKey->wValue;
}
else
{
o_rInput.stKey.wKey = l_stRecord.Event.KeyEvent.wVirtualKeyCode;
}
}
else if (MOUSE_EVENT == l_stRecord.EventType)
{
o_rInput.eEvent = IConsole::eEvent::eMouse;
o_rInput.stMouse.uButton = l_stRecord.Event.MouseEvent.dwButtonState;
o_rInput.stMouse.uX = l_stRecord.Event.MouseEvent.dwMousePosition.X;
o_rInput.stMouse.uY = l_stRecord.Event.MouseEvent.dwMousePosition.Y;
}
else if (WINDOW_BUFFER_SIZE_EVENT == l_stRecord.EventType)
{
o_rInput.eEvent = IConsole::eEvent::eSize;
o_rInput.stSize.uW = l_stRecord.Event.WindowBufferSizeEvent.dwSize.X;
o_rInput.stSize.uH = l_stRecord.Event.WindowBufferSizeEvent.dwSize.Y;
}
else
{
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetCursorY()
{
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
{
return l_sCsbi.dwCursorPosition.Y;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetWidth()
{
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
{
return l_sCsbi.srWindow.Right - l_sCsbi.srWindow.Left + 1;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tUINT32 GetHeight()
{
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
if (GetConsoleScreenBufferInfo(m_hStdOut, &l_sCsbi))
{
return l_sCsbi.srWindow.Bottom - l_sCsbi.srWindow.Top + 1;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL SetTextAttr(IConsole::eColor i_eFg, IConsole::eColor i_eBg)
{
if ( (i_eFg < 0)
|| (i_eFg >= IConsole::eColorsMax)
|| (i_eBg < 0)
|| (i_eBg >= IConsole::eColorsMax)
)
{
return FALSE;
}
return SetConsoleTextAttribute(m_hStdOut, m_pFg[i_eFg] | m_pBg[i_eBg]);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL Clear()
{
COORD l_sCoordScreen = { 0, 0 }; // home for the cursor
DWORD l_dwCharsWritten = 0;
DWORD l_dwConSize = 0;
CONSOLE_SCREEN_BUFFER_INFO l_sCsbi = {0};
// Get the number of character cells in the current buffer.
if( !GetConsoleScreenBufferInfo( m_hStdOut, &l_sCsbi ))
{
return FALSE;
}
l_dwConSize = l_sCsbi.dwSize.X * l_sCsbi.dwSize.Y;
// Fill the entire screen with blanks.
if( !FillConsoleOutputCharacterW( m_hStdOut, // Handle to console screen buffer
L' ', // Character to write to the buffer
l_dwConSize, // Number of cells to write
l_sCoordScreen, // Coordinates of first cell
&l_dwCharsWritten )) // Receive number of characters written
{
return FALSE;
}
// Get the current text attribute.
if( !GetConsoleScreenBufferInfo( m_hStdOut, &l_sCsbi ))
{
return FALSE;
}
// Set the buffer's attributes accordingly.
if( !FillConsoleOutputAttribute( m_hStdOut, // Handle to console screen buffer
l_sCsbi.wAttributes, // Character attributes to use
l_dwConSize, // Number of cells to set attribute
l_sCoordScreen, // Coordinates of first cell
&l_dwCharsWritten )) // Receive number of characters written
{
return FALSE;
}
// Put the cursor at its home coordinates.
return SetConsoleCursorPosition( m_hStdOut, l_sCoordScreen );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL Clear(tUINT32 i_uX, tUINT32 i_uY, tUINT32 i_uW, tUINT32 i_uH, IConsole::eColor i_eBg)
{
tUINT32 l_uiW = GetWidth();
tUINT32 l_uiH = GetHeight();
if ( (i_uX > l_uiW)
|| (i_uY > l_uiH)
|| (!i_uW)
|| (!i_uH)
)
{
return FALSE;
}
if ((i_uX + i_uW) > l_uiW)
{
i_uW = l_uiW - i_uX;
}
if ((i_uY + i_uH) > l_uiH)
{
i_uH = l_uiH - i_uY;
}
if (i_uW > m_szEmpty)
{
if (!AllocEmptyString((size_t)i_uW))
{
return FALSE;
}
}
if (!SetTextAttr(IConsole::eBlack, i_eBg))
{
return FALSE;
}
tUINT32 l_uiX = GetCursorX();
tUINT32 l_uiY = GetCursorY();
tUINT32 l_uiYOld = l_uiY;
while (i_uH--)
{
SetCursor(i_uX, i_uY++);
WriteTextB(m_pEmpty, i_uW);
}
SetCursor(l_uiX, l_uiYOld);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
size_t WriteTextB(const tXCHAR *i_pText, size_t i_szText)
{
DWORD l_dwWritten = 0;
return WriteConsole(m_hStdOut, i_pText, (DWORD)i_szText, &l_dwWritten, NULL);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
size_t WriteTextB(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
size_t i_szOffset,
tXCHAR *i_pText,
size_t i_szText,
size_t i_szTextMax
)
{
if ( (i_szLenMin > i_szLenMax)
|| (!i_pText)
|| (8 >= i_szTextMax)
|| (i_szText >= i_szTextMax)
)
{
return 0;
}
if (!SetTextAttr(i_eFg, i_eBg))
{
return 0;
}
tXCHAR *l_pText = i_pText;
if (!i_szText)
{
i_szText = PStrLen(i_pText);
}
//if there is offset, recalculate all inputs
if (i_szOffset)
{
if (i_szOffset < i_szText) //set sext offset and recalculate all
{
l_pText = l_pText + i_szOffset;
i_szText -= i_szOffset;
i_szTextMax -= i_szOffset;
i_szOffset = 0;
*l_pText = TM('<');
}
else //if (i_szOffset >= i_szText)
{
l_pText = m_pText;
*l_pText = TM('<');
i_szText = 1;
i_szTextMax= m_szText;
}
}
if (i_szText > i_szLenMax)
{
i_szText = i_szLenMax;
l_pText[i_szText-1] = TM('>');
}
else if (i_szText < i_szLenMin)
{
if (i_szTextMax < (i_szLenMin + 1))
{
PStrNCpy(m_pText, m_szText, l_pText, i_szText);
l_pText = m_pText;
i_szTextMax = m_szText;
}
tXCHAR *l_pIter = l_pText + i_szText;
while (i_szText < i_szLenMin)
{
*l_pIter = TM(' ');
l_pIter ++;
i_szText++;
}
}
if (i_szText < i_szTextMax)
{
l_pText[i_szText] = 0;
}
else
{
l_pText[i_szText-1] = 0;
}
DWORD l_dwWritten = 0;
if (!WriteConsole(m_hStdOut, l_pText, (DWORD)i_szText, &l_dwWritten, NULL))
{
return 0;
}
return (size_t)l_dwWritten;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
size_t WriteTextF(IConsole::eColor i_eFg,
IConsole::eColor i_eBg,
size_t i_szLenMin,
size_t i_szLenMax,
size_t i_szOffset,
const tXCHAR *i_pFormat,
va_list i_pVA
)
{
int l_iReturn = PVsnprintf(m_pText, m_szText, i_pFormat, i_pVA);
if (0 > l_iReturn)
{
return 0;
}
return WriteTextB(i_eFg, i_eBg, i_szLenMin, i_szLenMax, i_szOffset, m_pText, (size_t)l_iReturn, m_szText);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL Present()
{
return TRUE;
}
protected:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL AllocEmptyString(size_t i_szEmpty)
{
if (m_pEmpty)
{
free(m_pEmpty);
}
if (i_szEmpty > 4096)
{
i_szEmpty = 4096;
}
m_szEmpty = i_szEmpty;
m_pEmpty = (tXCHAR*)malloc(m_szEmpty * sizeof(tXCHAR));
if (!m_pEmpty)
{
return FALSE;
}
tXCHAR *l_pEmpty = m_pEmpty;
size_t l_szIterator = m_szEmpty;
while (l_szIterator--)
{
*l_pEmpty = TM(' ');
l_pEmpty++;
}
return TRUE;
}
};

View File

@ -0,0 +1,97 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#include <Windns.h>
#include <time.h>
#include "GTypes.h"
#include "AList.h"
class CDnsTxt: public CAList<tACHAR*>
{
protected:
virtual tBOOL Data_Release(tACHAR *i_pStr)
{
if (NULL == i_pStr)
{
return FALSE;
}
free(i_pStr);
return TRUE;
}//CListBase::Data_Release
};
tBOOL static inline GetDnsTxtRecords(const tACHAR *i_pDomain, CDnsTxt &io_rList)
{
DNS_RECORDA *l_pRecord = NULL;
DNS_RECORDA *l_pIter = NULL;
DNS_STATUS l_lStatus = 0;
tACHAR *l_pReturn = NULL;
io_rList.Clear(TRUE);
l_lStatus = DnsQuery_A(i_pDomain,
DNS_TYPE_TEXT,
DNS_QUERY_STANDARD
| DNS_QUERY_WIRE_ONLY
| DNS_QUERY_NO_LOCAL_NAME
| DNS_QUERY_BYPASS_CACHE
//| DNS_QUERY_USE_TCP_ONLY
| DNS_QUERY_NO_HOSTS_FILE,
NULL,
(DNS_RECORD**)&l_pRecord,
NULL
);
if ( (0 == l_lStatus)
&& (l_pRecord)
)
{
l_pIter = l_pRecord;
while (l_pIter)
{
if (DNS_TYPE_TEXT == l_pIter->wType)
{
if (l_pIter->Data.Txt.dwStringCount)
{
for (DWORD l_dwI = 0; l_dwI < l_pIter->Data.Txt.dwStringCount; l_dwI++)
{
if (l_pIter->Data.Txt.pStringArray[l_dwI])
{
io_rList.Push_Last(strdup(l_pIter->Data.Txt.pStringArray[l_dwI]));
}
}
}
}
if (!l_pReturn)
{
l_pIter = l_pIter->pNext;
}
else
{
l_pIter = NULL;
}
}
DnsRecordListFree(l_pRecord, DnsFreeRecordList);
}
return (io_rList.Count() != 0);
}

View File

@ -0,0 +1,331 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PFILE_H
#define PFILE_H
//UTF-8 text file header - {0xEF, 0xBB, 0xBF}
////////////////////////////////////////////////////////////////////////////////
class CPFile
: public IFile //virtual
{
volatile tINT32 m_iRCnt;
HANDLE m_hFile;
public:
////////////////////////////////////////////////////////////////////////////
CPFile()
: m_iRCnt(1)
, m_hFile(NULL)
{
}
////////////////////////////////////////////////////////////////////////////
virtual ~CPFile()
{
Close(FALSE);
}
////////////////////////////////////////////////////////////////////////////
tBOOL IsOpened()
{
return (NULL != m_hFile);
}
////////////////////////////////////////////////////////////////////////////
tBOOL Open(const tXCHAR *i_pName, tUINT32 i_dwFlags)
{
DWORD l_dwAccess = GENERIC_READ;
DWORD l_dwShare = 0;
if (EACCESS_WRITE & i_dwFlags)
{
l_dwAccess |= GENERIC_WRITE;
}
if (ESHARE_READ & i_dwFlags)
{
l_dwShare |= FILE_SHARE_READ;
}
if (ESHARE_WRITE & i_dwFlags)
{
l_dwShare |= FILE_SHARE_WRITE;
}
Close(TRUE);
m_hFile = CreateFileW(i_pName,
l_dwAccess,
l_dwShare,
NULL,
(i_dwFlags & EOPEN) ? OPEN_EXISTING : CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if ( (NULL == m_hFile)
|| (INVALID_HANDLE_VALUE == m_hFile)
)
{
m_hFile = NULL;
}
return (NULL != m_hFile);
}
////////////////////////////////////////////////////////////////////////////
tBOOL Close(tBOOL i_bFlush)
{
tBOOL l_bReturn = TRUE;
HANDLE l_hTemp = NULL;
if (NULL == m_hFile)
{
return TRUE;
}
if (i_bFlush)
{
if (FALSE == FlushFileBuffers(m_hFile))
{
l_bReturn = FALSE;
goto l_lExit;
}
}
l_hTemp = m_hFile;
m_hFile = NULL;
if (FALSE == CloseHandle(l_hTemp))
{
l_bReturn = FALSE;
goto l_lExit;
}
l_lExit:
return l_bReturn;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Set_Position(tUINT64 i_qwOffset)
{
if (NULL == m_hFile)
{
return FALSE;
}
LONG l_lOffsetHi = (LONG)(i_qwOffset >> 32);
if ( (INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile,
(LONG)i_qwOffset,
&l_lOffsetHi,
FILE_BEGIN
)
)
&& (NO_ERROR != GetLastError())
)
{
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
tUINT64 Get_Position()
{
if (INVALID_HANDLE_VALUE == m_hFile)
{
return 0ULL;
}
if (NULL == m_hFile)
{
return FALSE;
}
LONG l_lOffsetHi = 0;
DWORD l_dwOffsetLow = SetFilePointer(m_hFile,
0,
&l_lOffsetHi,
FILE_CURRENT
);
if ( (INVALID_SET_FILE_POINTER != l_dwOffsetLow)
|| (NO_ERROR == GetLastError())
)
{
return (((tUINT64)l_lOffsetHi) << 32) + (tUINT64)l_dwOffsetLow;
}
return 0ULL;
}
////////////////////////////////////////////////////////////////////////////
tUINT64 Get_Size()
{
if (INVALID_HANDLE_VALUE == m_hFile)
{
return 0ULL;
}
LARGE_INTEGER l_qwSize;
if (FALSE == GetFileSizeEx(m_hFile, &l_qwSize))
{
l_qwSize.QuadPart = 0LL;
}
return (tUINT64)l_qwSize.QuadPart;
}
////////////////////////////////////////////////////////////////////////////
size_t Write(const tUINT8 *i_pBuffer, size_t i_szBuffer, tBOOL i_bFlush)
{
if ( (INVALID_HANDLE_VALUE == m_hFile)
|| (NULL == i_pBuffer)
|| (0 == i_szBuffer)
)
{
return 0ULL;
}
size_t l_szReturn = 0;
DWORD l_dwWritten = 0;
while (l_szReturn < i_szBuffer)
{
l_dwWritten = 0;
if (!WriteFile(m_hFile,
i_pBuffer + l_szReturn,
(DWORD)(i_szBuffer - l_szReturn),
&l_dwWritten,
NULL
)
)
{
l_szReturn += (size_t)l_dwWritten;
break;
}
else
{
l_szReturn += (size_t)l_dwWritten;
}
}
if ( (i_bFlush)
&& (l_szReturn)
)
{
FlushFileBuffers(m_hFile);
}
return l_szReturn;
}
////////////////////////////////////////////////////////////////////////////
size_t Read(tUINT8 *o_pBuffer, size_t i_szBuffer)
{
if ( (INVALID_HANDLE_VALUE == m_hFile)
|| (NULL == o_pBuffer)
|| (0 == i_szBuffer)
)
{
return 0ULL;
}
size_t l_szReturn = 0;
DWORD l_dwRead = 0;
while (l_szReturn < i_szBuffer)
{
l_dwRead = 0;
if (ReadFile(m_hFile,
o_pBuffer + l_szReturn,
(DWORD)(i_szBuffer - l_szReturn),
&l_dwRead,
NULL
)
)
{
l_szReturn += (size_t)l_dwRead;
}
else
{
l_szReturn += (size_t)l_dwRead;
break;
}
if (0 >= l_dwRead)
{
break;
}
}
return l_szReturn;
}
////////////////////////////////////////////////////////////////////////////
tINT32 Add_Ref()
{
return ATOMIC_INC(&m_iRCnt);
}
////////////////////////////////////////////////////////////////////////////
tINT32 Release()
{
volatile tINT32 l_iReturn = ATOMIC_DEC(&m_iRCnt);
if (0 >= l_iReturn)
{
delete this;
}
return l_iReturn;
}
};
#endif //PFILE_H
/*
CPFile l_cFile;
const tUINT8 l_pHeader[] = {0xEF, 0xBB, 0xBF};
const char l_pText[] = "Some Text For me !\xD\xA Another Text\xD\xA Third Text";
tUINT64 l_qwCount = 0;
tUINT8 l_pBuffer[256] = {0};
l_cFile.Open("./ABC.txt", IFile::ECREATE | IFile::ESHARE_WRITE);
l_qwCount = l_cFile.Write(l_pHeader, LENGTH(l_pHeader), FALSE);
l_qwCount = l_cFile.Write((tUINT8*)l_pText, LENGTH(l_pText) - 1, TRUE);
l_qwCount = l_cFile.Get_Size();
l_cFile.Set_Position(0);
l_qwCount = l_cFile.Read(l_pBuffer, LENGTH(l_pBuffer));
l_cFile.Close(TRUE);
*/

View File

@ -0,0 +1,618 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#pragma warning(disable : 4091)
#include "Shlobj.h"
class CFSYS
{
public:
////////////////////////////////////////////////////////////////////////////
//Directory_Exists
static BOOL Directory_Exists(const wchar_t * i_pPath)
{
DWORD l_dwFile_Attr = 0;
BOOL l_bRes = FALSE;
if (NULL == i_pPath)
{
return l_bRes;
}
l_dwFile_Attr = GetFileAttributesW(i_pPath);
//check if that directory is exist ...
if ((FILE_ATTRIBUTE_DIRECTORY & l_dwFile_Attr) &&
( ((DWORD)-1) != l_dwFile_Attr)
)
{
l_bRes = TRUE;
}
return l_bRes;
}//Directory_Exists
////////////////////////////////////////////////////////////////////////////
//Directory_Create
static BOOL Directory_Create(const wchar_t *i_pDirectory)
{
if (NULL == i_pDirectory)
{
return FALSE;
}
wchar_t *l_pDirectory = _wcsdup(i_pDirectory);
tBOOL l_bReturn = FALSE;
if (NULL == l_pDirectory)
{
return FALSE;
}
size_t l_szLength = wcslen(l_pDirectory);
for (size_t l_dwI = 3; /*wcslen(L"C:\\")*/ l_dwI < l_szLength; l_dwI++)
{
if ( (L'\\' == l_pDirectory[l_dwI])
|| (L'/' == l_pDirectory[l_dwI])
)
{
l_pDirectory[l_dwI] = 0;
if (FALSE == Directory_Exists(l_pDirectory))
{
CreateDirectoryW(l_pDirectory, NULL);
}
l_pDirectory[l_dwI] = L'\\';
}
}
CreateDirectoryW(l_pDirectory, NULL);
l_bReturn = Directory_Exists(l_pDirectory);
free(l_pDirectory);
l_pDirectory = NULL;
return l_bReturn;
}//Directory_Create
////////////////////////////////////////////////////////////////////////////
//Directory_Delete
static BOOL Directory_Delete(const wchar_t *i_pDirectory)
{
if (NULL == i_pDirectory)
{
return FALSE;
}
return RemoveDirectoryW(i_pDirectory);
}
////////////////////////////////////////////////////////////////////////////
//File_Exists
static BOOL File_Exists(const wchar_t * i_pFileName)
{
HANDLE l_hFind_Handle = NULL;
WIN32_FIND_DATAW l_tFind_Data;
BOOL l_bRes = FALSE;
if (NULL == i_pFileName)
{
return l_bRes;
}
memset(&l_tFind_Data, 0, sizeof(WIN32_FIND_DATAW));
l_hFind_Handle = FindFirstFileW(i_pFileName, &l_tFind_Data);
if (INVALID_HANDLE_VALUE != l_hFind_Handle)
{
l_bRes = (0 == (l_tFind_Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
FindClose(l_hFind_Handle);
l_hFind_Handle = NULL;
}
return l_bRes;
}//File_Exists
////////////////////////////////////////////////////////////////////////////
// Enumerate_Files
static void Enumerate_Files(CBList<CWString*> *io_pFilesList,
CWString *i_pDirectory,
const wchar_t *i_pMask, //for example L"*.dll"
DWORD i_dwDepth = 0xFFFFFF
)
{
WIN32_FIND_DATAW l_sFind_Info = {0};
HANDLE l_hFind = INVALID_HANDLE_VALUE;
DWORD l_dwLength = i_pDirectory->Length();
CWString l_cSearch_Path;
//**************************************************************************
// Enumerate all files in current directory
l_cSearch_Path.Set(i_pDirectory->Get());
l_cSearch_Path.Append(2, L"\\", i_pMask);
l_hFind = FindFirstFileW(l_cSearch_Path.Get(), &l_sFind_Info);
while(INVALID_HANDLE_VALUE != l_hFind)
{
if (0 == (l_sFind_Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
CWString *l_pFile = new CWString();
if (l_pFile)
{
l_pFile->Set(i_pDirectory->Get());
l_pFile->Append(2, L"\\", l_sFind_Info.cFileName);
io_pFilesList->Add_After(io_pFilesList->Get_Last(), l_pFile);
}
}
if (! FindNextFileW(l_hFind, &l_sFind_Info))
{
FindClose(l_hFind);
l_hFind = INVALID_HANDLE_VALUE;
}
} //while(INVALID_HANDLE_VALUE != hFind)
//**************************************************************************
// Enumerate all sub directories in current directory ....
if (i_dwDepth)
{
l_cSearch_Path.Set(i_pDirectory->Get());
l_cSearch_Path.Append(1, L"\\*");
l_hFind = FindFirstFileW(l_cSearch_Path.Get(), &l_sFind_Info);
while(INVALID_HANDLE_VALUE != l_hFind)
{
if ( (0 != (l_sFind_Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
&& (0 != wcscmp(l_sFind_Info.cFileName, L"."))
&& (0 != wcscmp(l_sFind_Info.cFileName, L".."))
)
{
i_pDirectory->Append(2, L"\\", l_sFind_Info.cFileName);
Enumerate_Files(io_pFilesList, i_pDirectory, i_pMask, i_dwDepth - 1);
i_pDirectory->Trim(l_dwLength);
}
if (! FindNextFileW(l_hFind, &l_sFind_Info))
{
FindClose(l_hFind);
l_hFind = INVALID_HANDLE_VALUE;
}
} //while(INVALID_HANDLE_VALUE != hFind)
}
}// Enumerate_Files
////////////////////////////////////////////////////////////////////////////
// Enumerate_Dirs
static void Enumerate_Dirs(CBList<CWString*> *io_pFilesList, const tXCHAR *i_pRoot)
{
WIN32_FIND_DATAW l_sFind_Info = {0};
HANDLE l_hFind = INVALID_HANDLE_VALUE;
if (!io_pFilesList)
{
return;
}
if ( (i_pRoot)
&& (*i_pRoot)
)
{
CWString l_cSearch_Path;
//**************************************************************************
// Enumerate all files in current directory
l_cSearch_Path.Set(i_pRoot);
l_cSearch_Path.Append(1, L"\\*");
l_hFind = FindFirstFileW(l_cSearch_Path.Get(), &l_sFind_Info);
while(INVALID_HANDLE_VALUE != l_hFind)
{
if ( (0 != (l_sFind_Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
&& (0 != wcscmp(l_sFind_Info.cFileName, L"."))
&& (0 != wcscmp(l_sFind_Info.cFileName, L".."))
)
{
CWString *l_pFile = new CWString();
if (l_pFile)
{
l_pFile->Set(i_pRoot);
l_pFile->Append(2, L"\\", l_sFind_Info.cFileName);
io_pFilesList->Add_After(io_pFilesList->Get_Last(), l_pFile);
}
}
if (! FindNextFileW(l_hFind, &l_sFind_Info))
{
FindClose(l_hFind);
l_hFind = INVALID_HANDLE_VALUE;
}
} //while(INVALID_HANDLE_VALUE != hFind)
}
else
{
DWORD l_dwDrives = GetLogicalDrives();
DWORD l_dwBit = 0;
tXCHAR l_pDrive[4];
l_pDrive[0] = TM('A');
l_pDrive[1] = TM(':');
l_pDrive[2] = TM('\\');
l_pDrive[3] = 0;
while (l_dwDrives)
{
if (l_dwDrives & 1)
{
l_pDrive[0] = (tXCHAR)(l_dwBit + TM('A'));
UINT l_uiType = GetDriveTypeW(l_pDrive);
if ( (DRIVE_UNKNOWN != l_uiType)
&& (DRIVE_NO_ROOT_DIR != l_uiType)
)
{
CWString *l_pFile = new CWString();
if (l_pFile)
{
l_pFile->Set(l_pDrive);
io_pFilesList->Add_After(io_pFilesList->Get_Last(), l_pFile);
}
}
}
l_dwDrives = l_dwDrives >> 1;
l_dwBit ++;
}
}
}// Enumerate_Dirs
////////////////////////////////////////////////////////////////////////////
//Get_Version
static UINT64 Get_Version(const wchar_t *i_pFile)
{
DWORD l_dwUnknown = 0;
DWORD l_dwFileInfoSize = 0;
UINT64 l_qwReturn = 0;
CWString l_cPath;
if (!i_pFile)
{
l_cPath.Realloc(4096);
if (GetModuleFileNameW(GetModuleHandleW(NULL),
l_cPath.Get(),
l_cPath.Max_Length()
)
)
{
i_pFile = l_cPath.Get();
}
else
{
return 0ull;
}
}
l_dwFileInfoSize = GetFileVersionInfoSizeW(i_pFile, &l_dwUnknown);
if (l_dwFileInfoSize)
{
BYTE * l_pFileInfo = new BYTE[l_dwFileInfoSize];
if (l_pFileInfo)
{
memset(l_pFileInfo, 0, l_dwFileInfoSize);
if (GetFileVersionInfoW(i_pFile, 0, l_dwFileInfoSize, l_pFileInfo) )
{
VS_FIXEDFILEINFO * l_tVersion = NULL;
UINT l_dwSize = 0;
if (VerQueryValueW(l_pFileInfo, L"\\", (LPVOID *)&l_tVersion, &l_dwSize))
{
l_qwReturn = (((UINT64)l_tVersion->dwProductVersionMS) << 32) +
l_tVersion->dwProductVersionLS;
}
}
if (l_pFileInfo)
{
delete [ ] l_pFileInfo;
l_pFileInfo = NULL;
}
} //if (l_pFileInfo)
} //if (l_dwFileInfoSize)
return l_qwReturn;
}//Get_Version
////////////////////////////////////////////////////////////////////////////
//Get_TextResource
static tBOOL Get_TextResource(const tXCHAR *i_pFile,
const tXCHAR *i_pName,
tXCHAR *o_pBuffer,
size_t i_szBuffer
)
{
tBOOL l_bReturn = FALSE;
tUINT32 l_dwUnknown = 0;
DWORD l_dwFileInfoSize = 0;
tUINT32 *l_pCodePage = NULL;
tUINT8 *l_pFileInfo = NULL;
tUINT32 l_dwSize = 0;
wchar_t *l_pValue = NULL;
const size_t l_szName = 256;
wchar_t l_pName[l_szName];
CWString l_cPath;
if ( (!i_pName)
|| (!o_pBuffer)
|| (32 > i_szBuffer)
|| ((l_szName / 2) < wcslen(i_pName))
)
{
goto l_lblExit;
}
if (!i_pFile)
{
l_cPath.Realloc(4096);
if (GetModuleFileNameW(GetModuleHandleW(NULL),
l_cPath.Get(),
l_cPath.Max_Length()
)
)
{
i_pFile = l_cPath.Get();
}
else
{
goto l_lblExit;
}
}
l_dwFileInfoSize = GetFileVersionInfoSizeW(i_pFile, (LPDWORD)&l_dwUnknown);
if (!l_dwFileInfoSize)
{
goto l_lblExit;
}
l_pFileInfo = (tUINT8*)malloc(l_dwFileInfoSize);
if (!l_pFileInfo)
{
goto l_lblExit;
}
memset(l_pFileInfo, 0, l_dwFileInfoSize);
if (!GetFileVersionInfoW(i_pFile, 0, l_dwFileInfoSize, l_pFileInfo) )
{
goto l_lblExit;
}
if (!VerQueryValueW(l_pFileInfo, L"\\VarFileInfo\\Translation", (LPVOID*) &l_pCodePage, &l_dwSize))
{
goto l_lblExit;
}
swprintf_s(l_pName, l_szName,
L"\\StringFileInfo\\%08x\\%s",
(tUINT32)((*l_pCodePage) << 16 | (*l_pCodePage) >> 16),
i_pName
);
if (!VerQueryValueW(l_pFileInfo, l_pName, (LPVOID *)&l_pValue, &l_dwSize))
{
goto l_lblExit;
}
wcsncpy_s(o_pBuffer, i_szBuffer, l_pValue, (l_dwSize > i_szBuffer) ? i_szBuffer : l_dwSize);
o_pBuffer[i_szBuffer-1] = 0;
l_bReturn = TRUE;
l_lblExit:
if (l_pFileInfo)
{
free(l_pFileInfo);
l_pFileInfo = NULL;
}
return l_bReturn;
}//Get_TextResource
////////////////////////////////////////////////////////////////////////////
//Get_Process_Directory
static BOOL Get_Process_Directory(CWString *o_pDirectory)
{
BOOL l_bReturn = FALSE;
DWORD l_dwLength = 4096;
if ( (NULL == o_pDirectory)
|| (FALSE == o_pDirectory->Realloc(l_dwLength))
)
{
return l_bReturn;
}
if (0 != GetModuleFileNameW(GetModuleHandleW(NULL),
o_pDirectory->Get(),
o_pDirectory->Max_Length())
)
{
wchar_t *l_pExe_Name = NULL;
if ( (l_pExe_Name = wcsrchr(o_pDirectory->Get(), L'\\'))
|| (l_pExe_Name = wcsrchr(o_pDirectory->Get(), L'/'))
)
{
o_pDirectory->Trim((DWORD)(l_pExe_Name - o_pDirectory->Get()));
l_bReturn = TRUE;
}
}
return l_bReturn;
}//Get_Process_Directory
////////////////////////////////////////////////////////////////////////////
//Get_Process_Path
static BOOL Get_Process_Path(CWString *o_pPath)
{
BOOL l_bReturn = FALSE;
DWORD l_dwLength = 4096;
if ( (NULL == o_pPath)
|| (FALSE == o_pPath->Realloc(l_dwLength))
)
{
return l_bReturn;
}
if (0 != GetModuleFileNameW(GetModuleHandleW(NULL),
o_pPath->Get(),
o_pPath->Max_Length())
)
{
l_bReturn = TRUE;
}
return l_bReturn;
}//Get_Process_Path
////////////////////////////////////////////////////////////////////////////
//Get_File_Size
static tUINT64 Get_File_Size(const wchar_t *i_pFile)
{
WIN32_FILE_ATTRIBUTE_DATA l_sFAD = {0};
LARGE_INTEGER l_sSize = {0};
if (!GetFileAttributesExW(i_pFile, GetFileExInfoStandard, &l_sFAD))
{
return 0; // error condition, could call GetLastError to find out more
}
l_sSize.HighPart = l_sFAD.nFileSizeHigh;
l_sSize.LowPart = l_sFAD.nFileSizeLow;
return l_sSize.QuadPart;
}//Get_File_Size
////////////////////////////////////////////////////////////////////////////
//Delete_File
static BOOL Delete_File(const wchar_t *i_pFile_Name)
{
if (NULL == i_pFile_Name)
{
return FALSE;
}
DWORD l_dwFAttr = GetFileAttributesW(i_pFile_Name);
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_ARCHIVE);
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_READONLY);
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_SYSTEM);
SetFileAttributesW(i_pFile_Name, l_dwFAttr);
return DeleteFileW(i_pFile_Name);
}//Delete_File
////////////////////////////////////////////////////////////////////////////
//GetUserDirectory
static tBOOL GetUserDirectory(CWString *o_pPath)
{
if ( (NULL == o_pPath)
|| (FALSE == o_pPath->Realloc(4096))
)
{
return TRUE;
}
if ( S_OK != SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, o_pPath->Get()))
{
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
//GetUserDirectory
static tBOOL GetDirectoryParent(CWString &i_rChild, CWString &o_rParent)
{
o_rParent.Set(i_rChild.Get());
size_t l_szDir = o_rParent.Length();
tXCHAR *l_pDir = o_rParent.Get();
//cut trailing '/' or '\'
while ( (l_szDir)
&& ( (TM('\\') == l_pDir[l_szDir - 1])
|| (TM('/') == l_pDir[l_szDir - 1])
)
)
{
l_pDir[--l_szDir] = 0;
}
tXCHAR *l_pTemp = wcsrchr(l_pDir, TM('\\'));
if (!l_pTemp)
{
l_pTemp = wcsrchr(l_pDir, TM('/'));
}
if (!l_pTemp)
{
o_rParent.Set(TM(""));
return TRUE;
}
*l_pTemp = 0;
l_pTemp--;
//removing duplicates of '\' '/'
while ( (TM('\\') == *l_pTemp)
|| (TM('/') == *l_pTemp)
)
{
*l_pTemp = 0;
l_pTemp--;
if (l_pDir > l_pTemp)
{
break;
}
}
return TRUE;
}
};

View File

@ -0,0 +1,699 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#define FJOURNAL_FILE_BUFFER_LENGTH (0x20000)
#define FJOURNAL_FILE_BUFFER_MINIMUM_REMAINDER (0x2000)
#define FJOURNAL_THREAD_WAKEUP_INTERVAL (2500)
#define FJOURNAL_FILE_EXTENSION L"log"
#define FJOURNAL_DESCRIPTION_MAX_LENGTH (64)
#define FJOURNAL_MAX_FILES (7)
void __cdecl FJournal_Routine(void *i_pContext);
// 1. Dump to the file
// 2. must have parameters and possibility to export them
// 3. should have own thread to notify about writing, every 1-5 seconds.
class CJournal
: virtual public IJournal
{
private:
//put volatile variables at the top, to obtain 32 bit alignment.
//Project has 8 bytes alignment by default
volatile LONG m_lReference_Counter;
HANDLE m_hLog_File;
wchar_t *m_pJournal_Buffer;
wchar_t *m_pWrite_Buffer;
DWORD m_dwBuffer_Used;
HANDLE m_hThread;
HANDLE m_hEvent_Exit;
HANDLE m_hEvent_Write;
CRITICAL_SECTION m_tCS;
SYSTEMTIME m_tTime;
wchar_t m_pTypes_Description[IJournal::eLEVEL_COUNT][FJOURNAL_DESCRIPTION_MAX_LENGTH];
CWString m_cFile_Name;
UINT64 m_pCount[IJournal::eLEVEL_COUNT];
IJournal::eLevel m_eVerbosity;
IJournal::eTime m_eTime; //ignored for a while
tBOOL m_bFunction;
tBOOL m_bType;
BOOL m_bInitialized;
BOOL m_bError;
DWORD m_dwMax_Files;
public:
////////////////////////////////////////////////////////////////////////////
CJournal()
: m_lReference_Counter(1)
, m_hLog_File(INVALID_HANDLE_VALUE)
, m_pJournal_Buffer(NULL)
, m_pWrite_Buffer(NULL)
, m_dwBuffer_Used(0)
, m_hThread(NULL)
, m_hEvent_Exit(NULL)
, m_hEvent_Write(NULL)
, m_eVerbosity(IJournal::eLEVEL_TRACE)
, m_eTime(IJournal::eTIME_YYYYMMDDHHMMSSMS)
, m_bFunction(TRUE)
, m_bType(TRUE)
, m_bInitialized(FALSE)
, m_bError(FALSE)
, m_dwMax_Files(FJOURNAL_MAX_FILES)
{
memset(&m_tCS, 0, sizeof(CRITICAL_SECTION));
memset(&m_pCount, 0, sizeof(m_pCount));
InitializeCriticalSection(&m_tCS);
wcscpy_s(m_pTypes_Description[IJournal::eLEVEL_TRACE], FJOURNAL_DESCRIPTION_MAX_LENGTH, L"INFO : ");
wcscpy_s(m_pTypes_Description[IJournal::eLEVEL_DEBUG], FJOURNAL_DESCRIPTION_MAX_LENGTH, L"DEBUG: ");
wcscpy_s(m_pTypes_Description[IJournal::eLEVEL_INFO], FJOURNAL_DESCRIPTION_MAX_LENGTH, L"INFO : ");
wcscpy_s(m_pTypes_Description[IJournal::eLEVEL_WARNING], FJOURNAL_DESCRIPTION_MAX_LENGTH, L"WARN.: ");
wcscpy_s(m_pTypes_Description[IJournal::eLEVEL_ERROR], FJOURNAL_DESCRIPTION_MAX_LENGTH, L"ERROR: ");
wcscpy_s(m_pTypes_Description[IJournal::eLEVEL_CRITICAL], FJOURNAL_DESCRIPTION_MAX_LENGTH, L"CRIT.: ");
}
////////////////////////////////////////////////////////////////////////////
void Set_Files_Max_Count(DWORD i_dwVal)
{
m_dwMax_Files = i_dwVal;
}//Set_Files_Max_Count
////////////////////////////////////////////////////////////////////////////
tBOOL Initialize(const tXCHAR *i_pName)
{
if (TRUE == m_bInitialized)
{
return TRUE;
}
if ( (NULL == i_pName)
|| (TRUE == m_bError)
)
{
return FALSE;
}
CWString l_sDirectory;
if (FALSE == m_bError)
{
m_pJournal_Buffer = new wchar_t[FJOURNAL_FILE_BUFFER_LENGTH];
m_pWrite_Buffer = new wchar_t[FJOURNAL_FILE_BUFFER_LENGTH];
if ( (NULL == m_pJournal_Buffer) || (NULL == m_pWrite_Buffer) )
{
m_bError = TRUE;
}
}
if (FALSE == m_bError)
{
CFSYS::Get_Process_Directory(&l_sDirectory);
l_sDirectory.Append(2, L"\\", i_pName);
if (FALSE == CFSYS::Directory_Exists(l_sDirectory.Get()))
{
m_bError = (! CFSYS::Directory_Create(l_sDirectory.Get()));
}
}
if (FALSE == m_bError)
{
Remove_Old_Journals(l_sDirectory.Get(),
m_dwMax_Files,
FJOURNAL_FILE_EXTENSION
);
DWORD l_dwIterator = 0;
SYSTEMTIME l_tTime;
GetLocalTime(&l_tTime);
do
{
swprintf_s(m_pJournal_Buffer,
FJOURNAL_FILE_BUFFER_LENGTH,
L"%s\\%04d_%02d_%02d-%02d_%02d_%02d-%d.%s",
l_sDirectory.Get(),
(int)l_tTime.wYear,
(int)l_tTime.wMonth,
(int)l_tTime.wDay,
(int)l_tTime.wHour,
(int)l_tTime.wMinute,
(int)l_tTime.wSecond,
(int)l_dwIterator++,
FJOURNAL_FILE_EXTENSION
);
} while (CFSYS::File_Exists(m_pJournal_Buffer));
m_cFile_Name.Set((wchar_t*)m_pJournal_Buffer);
m_hLog_File = CreateFileW(m_pJournal_Buffer,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if ( (NULL == m_hLog_File)
|| (INVALID_HANDLE_VALUE == m_hLog_File)
)
{
m_hLog_File = INVALID_HANDLE_VALUE;
m_bError = TRUE;
}
}
if (FALSE == m_bError)
{
m_hEvent_Exit = CreateEventW(NULL, FALSE, FALSE, NULL);
m_hEvent_Write = CreateEventW(NULL, TRUE, FALSE, NULL);
if ( (NULL == m_hEvent_Exit) || (NULL == m_hEvent_Write) )
{
m_bError = TRUE;
}
}
if (FALSE == m_bError)
{
m_pJournal_Buffer[0] = 0xFEFF;
m_dwBuffer_Used = 1;
m_hThread = (void*)_beginthread(&Routine_Entry_Point, 0, this);
if (NULL == m_hThread)
{
m_bError = TRUE;
}
}
if (FALSE == m_bError)
{
m_bInitialized = TRUE;
}
return (! m_bError);
}
////////////////////////////////////////////////////////////////////////////
void Set_Verbosity(IJournal::eLevel i_eVerbosity)
{
EnterCriticalSection(&m_tCS);
m_eVerbosity = i_eVerbosity;
LeaveCriticalSection(&m_tCS);
}
////////////////////////////////////////////////////////////////////////////
void Set_Format(IJournal::eTime i_eTime, tBOOL i_bFunction, tBOOL i_bType)
{
EnterCriticalSection(&m_tCS);
m_eTime = i_eTime;
m_bFunction = i_bFunction;
m_bType = i_bType;
LeaveCriticalSection(&m_tCS);
}
////////////////////////////////////////////////////////////////////////////
IJournal::eLevel Get_Verbosity()
{
IJournal::eLevel l_eResult;
EnterCriticalSection(&m_tCS);
l_eResult = m_eVerbosity;
LeaveCriticalSection(&m_tCS);
return l_eResult;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Log(IJournal::eLevel i_eType,
IJournal::hModule i_hModule,
const char *i_pFile,
const char *i_pFunction,
tUINT32 i_dwLine,
const tXCHAR *i_pFormat,
...
)
{
tBOOL l_bResult = TRUE;
int l_iCount = 0;
wchar_t *l_pBuffer = NULL;
if ( (FALSE == m_bInitialized)
|| (NULL == i_pFormat)
|| (i_eType >= IJournal::eLEVEL_COUNT)
)
{
return FALSE;
}
EnterCriticalSection(&m_tCS);
m_pCount[i_eType]++;
if (i_eType < m_eVerbosity)
{
l_bResult = FALSE;
goto l_lExit;
}
if ( (m_dwBuffer_Used >= FJOURNAL_FILE_BUFFER_LENGTH)
|| (FJOURNAL_FILE_BUFFER_MINIMUM_REMAINDER >= (FJOURNAL_FILE_BUFFER_LENGTH - m_dwBuffer_Used) )
)
{
SetEvent(m_hEvent_Write);
while (WAIT_OBJECT_0 == WaitForSingleObject(m_hEvent_Write, 0))
{
Sleep(5);
}
}
if ( (l_bResult)
&& (i_pFunction)
&& (m_bFunction)
)
{
l_pBuffer = m_pJournal_Buffer + m_dwBuffer_Used;
while (*i_pFunction)
{
(*l_pBuffer++) = (*i_pFunction++);
m_dwBuffer_Used ++;
}
l_iCount = swprintf_s(m_pJournal_Buffer + m_dwBuffer_Used,
FJOURNAL_FILE_BUFFER_LENGTH - m_dwBuffer_Used,
L"() Ln %04d : ", (int)i_dwLine
);
if (0 > l_iCount)
{
l_bResult = FALSE;
}
else
{
m_dwBuffer_Used += l_iCount;
}
l_pBuffer = m_pJournal_Buffer + m_dwBuffer_Used;
(*l_pBuffer++) = 13;
(*l_pBuffer++) = 10;
m_dwBuffer_Used += 2;
}
if (l_bResult)
{
GetLocalTime(&m_tTime);
l_iCount = swprintf_s(m_pJournal_Buffer + m_dwBuffer_Used,
FJOURNAL_FILE_BUFFER_LENGTH - m_dwBuffer_Used,
L"[%04d.%02d.%02d %02d:%02d:%02d.%03d] %s ",
(int)m_tTime.wYear, (int)m_tTime.wMonth, (int)m_tTime.wDay,
(int)m_tTime.wHour, (int)m_tTime.wMinute, (int)m_tTime.wSecond, (int)m_tTime.wMilliseconds,
m_bType ? m_pTypes_Description[i_eType] : L""
);
if (0 > l_iCount)
{
l_bResult = FALSE;
}
else
{
m_dwBuffer_Used += l_iCount;
}
}
if (l_bResult)
{
va_list l_pArgList;
va_start(l_pArgList, i_pFormat);
size_t l_stRemaining = 0;
if (S_OK == StringCbVPrintfExW(m_pJournal_Buffer + m_dwBuffer_Used,
(FJOURNAL_FILE_BUFFER_LENGTH - m_dwBuffer_Used) * sizeof(wchar_t),
NULL,
&l_stRemaining,
STRSAFE_IGNORE_NULLS,
i_pFormat,
l_pArgList
)
)
{
m_dwBuffer_Used = FJOURNAL_FILE_BUFFER_LENGTH - (DWORD)(l_stRemaining / sizeof(wchar_t));
}
else
{
l_bResult = FALSE;
}
va_end(l_pArgList);
}
if (l_bResult)
{
l_pBuffer = m_pJournal_Buffer + m_dwBuffer_Used;
(*l_pBuffer++) = 13;
(*l_pBuffer++) = 10;
m_dwBuffer_Used += 2;
}
l_lExit:
LeaveCriticalSection(&m_tCS);
return l_bResult;
}
////////////////////////////////////////////////////////////////////////////
wchar_t *Get_File_Name()
{
if (FALSE == m_bInitialized)
{
return NULL;
}
return m_cFile_Name.Get();
}
////////////////////////////////////////////////////////////////////////////
tUINT64 Get_Count(IJournal::eLevel i_eType)
{
UINT64 l_qwReturn = 0ULL;
if (i_eType >= IJournal::eLEVEL_COUNT)
{
return 0ULL;
}
EnterCriticalSection(&m_tCS);
l_qwReturn = m_pCount[i_eType];
LeaveCriticalSection(&m_tCS);
return l_qwReturn;
}
////////////////////////////////////////////////////////////////////////////
tINT32 Add_Ref()
{
return InterlockedIncrement(&m_lReference_Counter);
}
////////////////////////////////////////////////////////////////////////////
tINT32 Release()
{
volatile tINT32 l_iRCnt = InterlockedDecrement(&m_lReference_Counter);
if ( 0 >= l_iRCnt)
{
delete this;
}
return l_iRCnt;
}
////////////////////////////////////////////////////////////////////////////
BOOL Get_Initialized()
{
return m_bInitialized;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Register_Thread(const tXCHAR *i_pName, tUINT32 i_dwThreadId)
{
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Unregister_Thread(tUINT32 i_dwThreadId)
{
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
tBOOL Register_Module(const tXCHAR *i_pName, IJournal::hModule *o_hModule)
{
if (o_hModule)
{
*o_hModule = NULL;
}
return FALSE;
}
protected:
////////////////////////////////////////////////////////////////////////////
static void __cdecl Routine_Entry_Point(void *i_pContext)
{
CJournal * l_pFJournal = (CJournal *)i_pContext;
if (l_pFJournal)
{
l_pFJournal->Routine();
}
_endthread();
}
////////////////////////////////////////////////////////////////////////////
void Routine()
{
BOOL l_bExit = FALSE;
HANDLE l_pEvents[] = {m_hEvent_Exit, m_hEvent_Write};
DWORD l_dwWFMO_result = 0;
DWORD l_dwSize = 0;
while (FALSE == l_bExit)
{
l_dwWFMO_result = WaitForMultipleObjects(sizeof(l_pEvents)/sizeof(l_pEvents[0]),
l_pEvents,
FALSE,
FJOURNAL_THREAD_WAKEUP_INTERVAL
); //Process events
// Exit signal
if (WAIT_OBJECT_0 == l_dwWFMO_result)
{
l_dwSize = Copy_Bufer(TRUE);
if (l_dwSize)
{
Write((BYTE*)m_pWrite_Buffer, l_dwSize);
}
l_bExit = TRUE;
}
else if ( (WAIT_OBJECT_0 + 1) == l_dwWFMO_result)// we have received signal for write
{
l_dwSize = Copy_Bufer(FALSE);
ResetEvent(m_hEvent_Write);
if ( (l_dwSize) && (FALSE == Write((BYTE*)m_pWrite_Buffer, l_dwSize)) )
{
l_bExit = TRUE;
}
}
else if (WAIT_TIMEOUT == l_dwWFMO_result)
{
l_dwSize = Copy_Bufer(TRUE);
if ( (l_dwSize) && (FALSE == Write((BYTE*)m_pWrite_Buffer, l_dwSize)) )
{
l_bExit = TRUE;
}
}
}
m_hThread = NULL;
}
private:
////////////////////////////////////////////////////////////////////////////
DWORD Copy_Bufer(BOOL i_bLock)
{
DWORD l_dwResult = 0;
if (i_bLock)
{
EnterCriticalSection(&m_tCS);
}
if (m_dwBuffer_Used)
{
l_dwResult = m_dwBuffer_Used * sizeof(wchar_t);
memcpy_s(m_pWrite_Buffer, FJOURNAL_FILE_BUFFER_LENGTH * sizeof(wchar_t), m_pJournal_Buffer, l_dwResult);
m_dwBuffer_Used = 0;
}
if (i_bLock)
{
LeaveCriticalSection(&m_tCS);
}
return l_dwResult;
}
////////////////////////////////////////////////////////////////////////////
BOOL Write(BYTE *i_pBuffer, DWORD i_dwSize)
{
BOOL l_bResult = TRUE;
DWORD l_dwReturned = 0;
DWORD l_dwWriten = 0;
if ( (0 >= i_dwSize) || (NULL == i_pBuffer) )
{
return FALSE;
}
while ( l_dwWriten != i_dwSize )
{
l_dwReturned = 0;
if ( 0 == WriteFile(m_hLog_File,
i_pBuffer + l_dwWriten,
i_dwSize - l_dwWriten,
&l_dwReturned,
NULL)
)
{
i_dwSize = 0;
l_dwWriten = 0;
l_bResult = FALSE;
}
else
{
l_dwWriten += l_dwReturned;
}
} //while
return l_bResult;
}
////////////////////////////////////////////////////////////////////////////
BOOL Remove_Old_Journals(wchar_t *i_pFolder, DWORD i_dwMax_Files, const wchar_t *i_pExtension)
{
wchar_t l_pFileName[ MAX_PATH ] = L"9999";
DWORD l_dwPrev_Error_Mode = 0;
WIN32_FIND_DATAW l_tFind_Info;
HANDLE l_hFind = INVALID_HANDLE_VALUE;
DWORD l_dwCount = 0;
BOOL l_bResult = TRUE;
if ( (NULL == i_pFolder) || (NULL == i_pExtension) )
{
return FALSE;
}
l_dwPrev_Error_Mode = SetErrorMode(SEM_FAILCRITICALERRORS);
l_dwCount = i_dwMax_Files + 1;
while ( (l_dwCount > i_dwMax_Files) && (l_bResult) )
{
l_dwCount = 0;
swprintf_s(m_pJournal_Buffer, FJOURNAL_FILE_BUFFER_LENGTH, L"%s\\*.%s", i_pFolder, i_pExtension);
l_hFind = FindFirstFileW(m_pJournal_Buffer, &l_tFind_Info);
while(INVALID_HANDLE_VALUE != l_hFind)
{
if (0 == (l_tFind_Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
l_dwCount ++;
if (0 <= _wcsicmp(l_pFileName, l_tFind_Info.cFileName))
{
wcscpy_s(l_pFileName, MAX_PATH, l_tFind_Info.cFileName);
}
if ( ! FindNextFileW(l_hFind, &l_tFind_Info))
{
FindClose(l_hFind);
l_hFind = INVALID_HANDLE_VALUE;
}
}
} //while(INVALID_HANDLE_VALUE != hFind)
SetErrorMode(l_dwPrev_Error_Mode);
if (l_dwCount > i_dwMax_Files)
{
swprintf_s(m_pJournal_Buffer, FJOURNAL_FILE_BUFFER_LENGTH, L"%s\\%s", i_pFolder, l_pFileName);
DWORD l_dwFAttr = GetFileAttributesW(m_pJournal_Buffer);
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_ARCHIVE);
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_READONLY);
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_SYSTEM);
SetFileAttributesW(m_pJournal_Buffer, l_dwFAttr);
l_bResult = DeleteFileW(m_pJournal_Buffer);
l_dwCount --;
wcscpy_s(l_pFileName, MAX_PATH, L"9999");
}
}
return l_bResult;
}
////////////////////////////////////////////////////////////////////////////
virtual ~CJournal() //use Release() instead
{
if (m_hThread)
{
if (m_hEvent_Exit)
{
SetEvent(m_hEvent_Exit);
if (WAIT_TIMEOUT == WaitForSingleObject(m_hThread, 150000))
{
OutputDebugStringW(L"~CFJournal::Thread exit failed !\n");
}
CloseHandle(m_hEvent_Exit);
m_hEvent_Exit = NULL;
}
}
if (m_hEvent_Write)
{
CloseHandle(m_hEvent_Write);
m_hEvent_Write = NULL;
}
if (INVALID_HANDLE_VALUE != m_hLog_File)
{
CloseHandle(m_hLog_File);
m_hLog_File = INVALID_HANDLE_VALUE;
}
if (m_pJournal_Buffer)
{
delete [] m_pJournal_Buffer;
m_pJournal_Buffer = NULL;
}
if (m_pWrite_Buffer)
{
delete [] m_pWrite_Buffer;
m_pWrite_Buffer = NULL;
}
DeleteCriticalSection(&m_tCS);
}
};

View File

@ -0,0 +1,30 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
///////////////////////////////////////////////////////////////////////////////
typedef CRITICAL_SECTION tLOCK;
#define LOCK_CREATE(i_Lock) InitializeCriticalSection(&i_Lock)
#define LOCK_DESTROY(i_Lock) DeleteCriticalSection(&i_Lock)
#define LOCK_ENTER(i_Lock) EnterCriticalSection(&i_Lock)
#define LOCK_EXIT(i_Lock) LeaveCriticalSection(&i_Lock)
#define LOCK_TRY(i_Lock) TryEnterCriticalSection(&i_Lock)

View File

@ -0,0 +1,216 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
////////////////////////////////////////////////////////////////////////////////
class CMEvent
: virtual public IMEvent
{
struct sMEvent
{
eMEvent_Type eType;
HANDLE hEvent;
};
tUINT8 m_bCount;
sMEvent *m_pEvents;
tBOOL m_bInit;
HANDLE *m_pHandles;
public:
////////////////////////////////////////////////////////////////////////////
//CMEvent
CMEvent()
: m_bCount(0)
, m_pEvents(NULL)
, m_bInit(FALSE)
, m_pHandles(NULL)
{
}//CMEvent
////////////////////////////////////////////////////////////////////////////
//~CMEvent
virtual ~CMEvent()
{
Cleanup();
m_bCount = 0;
}//~CMEvent
////////////////////////////////////////////////////////////////////////////
//Init
tBOOL Init(tUINT8 i_bCount, ...)
{
if ( (TRUE == m_bInit)
|| (0 >= i_bCount)
)
{
return FALSE;
}
va_list l_pVA;
tUINT8 l_bIDX = 0;
m_pEvents = new sMEvent[i_bCount];
if (NULL == m_pEvents)
{
goto l_lExit;
}
m_pHandles = new HANDLE[i_bCount];
if (NULL == m_pHandles)
{
goto l_lExit;
}
memset(m_pEvents, 0, sizeof(sMEvent) * i_bCount);
va_start(l_pVA, i_bCount);
while (l_bIDX < i_bCount)
{
m_pEvents[l_bIDX].eType = (eMEvent_Type)va_arg(l_pVA, int); //Real type is "eMEvent_Type", MinGW warning
if (EMEVENT_SINGLE_AUTO == m_pEvents[l_bIDX].eType)
{
m_pEvents[l_bIDX].hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
else if (EMEVENT_SINGLE_MANUAL == m_pEvents[l_bIDX].eType)
{
m_pEvents[l_bIDX].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
}
else if (EMEVENT_MULTI == m_pEvents[l_bIDX].eType)
{
m_pEvents[l_bIDX].hEvent = CreateSemaphore(NULL, 0, 0xFFFFFF, NULL);
}
m_pHandles[l_bIDX] = m_pEvents[l_bIDX].hEvent;
l_bIDX++;
}
va_end(l_pVA);
m_bInit = TRUE;
m_bCount = i_bCount;
l_lExit:
if (FALSE == m_bInit)
{
Cleanup();
}
return m_bInit;
}//Init
////////////////////////////////////////////////////////////////////////////
//Set
tBOOL Set(tUINT32 i_dwID)
{
if (i_dwID >= m_bCount)
{
return FALSE;
}
if (EMEVENT_MULTI == m_pEvents[i_dwID].eType)
{
ReleaseSemaphore(m_pEvents[i_dwID].hEvent, 1, NULL);
}
else
{
SetEvent(m_pEvents[i_dwID].hEvent);
}
return TRUE;
}//Set
////////////////////////////////////////////////////////////////////////////
//Clr
tBOOL Clr(tUINT32 i_dwID)
{
if ( (i_dwID >= m_bCount)
|| (EMEVENT_SINGLE_MANUAL != m_pEvents[i_dwID].eType)
)
{
return FALSE;
}
ResetEvent(m_pEvents[i_dwID].hEvent);
return TRUE;
}//Clr
////////////////////////////////////////////////////////////////////////////
//Wait
tUINT32 Wait()
{
return Wait(INFINITE);
}//Wait
////////////////////////////////////////////////////////////////////////////
//Wait
tUINT32 Wait(tUINT32 i_dwMSec)
{
DWORD l_dwRes = WaitForMultipleObjects(m_bCount,
m_pHandles,
FALSE,
i_dwMSec
);
if ( (WAIT_TIMEOUT == l_dwRes)
|| (WAIT_FAILED == l_dwRes)
)
{
return MEVENT_TIME_OUT;
}
return (MEVENT_SIGNAL_0 + (l_dwRes - WAIT_OBJECT_0));
}//Wait
private:
////////////////////////////////////////////////////////////////////////////
//Cleanup
void Cleanup()
{
if (m_pHandles)
{
delete [] m_pHandles;
m_pHandles = NULL;
}
if (m_pEvents)
{
for (tUINT32 l_dwI = 0; l_dwI < m_bCount; l_dwI++)
{
if (m_pEvents[l_dwI].hEvent)
{
CloseHandle(m_pEvents[l_dwI].hEvent);
m_pEvents[l_dwI].hEvent = NULL;
}
}
delete [] m_pEvents;
m_pEvents = NULL;
}
}//Cleanup
};

View File

@ -0,0 +1,215 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PPERFORMANCE_INFO_H
#define PPERFORMANCE_INFO_H
#include "IPerformanceInfo.h"
#include <Pdh.h>
#include <pdhmsg.h>
#include <Psapi.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CPerformanceInfo
: public IPerformanceInfo
{
volatile tINT32 m_iRCnt;
PDH_STATUS m_hPdhStatus;
HQUERY m_hPdhQuery;
HCOUNTER m_hPdhCounter[IPerformanceInfo::eCounterTotal];
SYSTEM_INFO m_sSysInfo;
public:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CPerformanceInfo(const tXCHAR *i_pProcessName)
: m_iRCnt(1)
, m_hPdhStatus(ERROR_SUCCESS)
, m_hPdhQuery(NULL)
{
tXCHAR l_pExeName[256];
CWString l_cPhdPath;
GetSystemInfo( &m_sSysInfo );
memset(m_hPdhCounter, 0, sizeof(m_hPdhCounter));
if (!m_sSysInfo.dwNumberOfProcessors)
{
m_sSysInfo.dwNumberOfProcessors = 1;
}
if (GetModuleBaseNameW(GetCurrentProcess(), NULL, l_pExeName, LENGTH(l_pExeName)))
{
tXCHAR *l_pExt = wcsrchr(l_pExeName, TM('.'));
if (l_pExt)
{
*l_pExt = 0;
}
}
else
{
PStrCpy(l_pExeName, LENGTH(l_pExeName), i_pProcessName);
}
l_cPhdPath.Realloc(4096);
////////////////////////////////////////////////////////////////////////////
//create PHD counters
//If counters is missing == PDH_CSTATUS_NO_OBJECT
//http://blogs.msdn.com/b/martinv/archive/2008/11/18/missing-performance-counters.aspx
//C:\Windows\System32> lodctr /R
//After that all Performance Counters were available again!
if (ERROR_SUCCESS == PdhOpenQuery(NULL, NULL, &m_hPdhQuery))
{
m_hPdhStatus = PdhAddEnglishCounterW(m_hPdhQuery,
TM("\\Processor(_Total)\\% Processor Time"),
0,
&m_hPdhCounter[IPerformanceInfo::eCounterSystemCpu]);
if (ERROR_SUCCESS != m_hPdhStatus)
{
m_hPdhCounter[IPerformanceInfo::eCounterSystemCpu] = NULL;
}
l_cPhdPath.Set(TM(""));
swprintf_s(l_cPhdPath.Get(), l_cPhdPath.Max_Length(), TM("\\Process(%s)\\%% Processor Time"), l_pExeName);
if (ERROR_SUCCESS != PdhAddEnglishCounterW(m_hPdhQuery, l_cPhdPath.Get(), 0, &m_hPdhCounter[IPerformanceInfo::eCounterProcessCpu]))
{
m_hPdhCounter[IPerformanceInfo::eCounterProcessCpu] = NULL;
}
l_cPhdPath.Set(TM(""));
swprintf_s(l_cPhdPath.Get(), l_cPhdPath.Max_Length(), TM("\\Process(%s)\\Handle Count"), l_pExeName);
if (ERROR_SUCCESS != PdhAddEnglishCounterW(m_hPdhQuery, l_cPhdPath.Get(), 0, &m_hPdhCounter[IPerformanceInfo::eCounterProcessHandles]))
{
m_hPdhCounter[IPerformanceInfo::eCounterProcessHandles] = NULL;
}
l_cPhdPath.Set(TM(""));
swprintf_s(l_cPhdPath.Get(), l_cPhdPath.Max_Length(), TM("\\Process(%s)\\Thread Count"), l_pExeName);
if (ERROR_SUCCESS != PdhAddEnglishCounterW(m_hPdhQuery, l_cPhdPath.Get(), 0, &m_hPdhCounter[IPerformanceInfo::eCounterProcessThreads]))
{
m_hPdhCounter[IPerformanceInfo::eCounterProcessThreads] = NULL;
}
l_cPhdPath.Set(TM(""));
swprintf_s(l_cPhdPath.Get(), l_cPhdPath.Max_Length(), TM("\\Process(%s)\\Working Set"), l_pExeName);
if (ERROR_SUCCESS != PdhAddEnglishCounterW(m_hPdhQuery, l_cPhdPath.Get(), 0, &m_hPdhCounter[IPerformanceInfo::eCounterProcessMemory]))
{
m_hPdhCounter[IPerformanceInfo::eCounterProcessMemory] = NULL;
}
}//if (ERROR_SUCCESS == PdhOpenQuery(NULL, NULL, &m_hPdhQuery))
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual ~CPerformanceInfo()
{
if (m_hPdhCounter[IPerformanceInfo::eCounterProcessCpu])
{
PdhRemoveCounter(m_hPdhCounter[IPerformanceInfo::eCounterProcessCpu]);
m_hPdhCounter[IPerformanceInfo::eCounterProcessCpu] = NULL;
}
if (m_hPdhCounter[IPerformanceInfo::eCounterSystemCpu])
{
PdhRemoveCounter(m_hPdhCounter[IPerformanceInfo::eCounterSystemCpu]);
m_hPdhCounter[IPerformanceInfo::eCounterSystemCpu] = NULL;
}
if (m_hPdhCounter[IPerformanceInfo::eCounterProcessHandles])
{
PdhRemoveCounter(m_hPdhCounter[IPerformanceInfo::eCounterProcessHandles]);
m_hPdhCounter[IPerformanceInfo::eCounterProcessHandles] = NULL;
}
if (m_hPdhCounter[IPerformanceInfo::eCounterProcessThreads])
{
PdhRemoveCounter(m_hPdhCounter[IPerformanceInfo::eCounterProcessThreads]);
m_hPdhCounter[IPerformanceInfo::eCounterProcessThreads] = NULL;
}
if (m_hPdhCounter[IPerformanceInfo::eCounterProcessMemory])
{
PdhRemoveCounter(m_hPdhCounter[IPerformanceInfo::eCounterProcessMemory]);
m_hPdhCounter[IPerformanceInfo::eCounterProcessMemory] = NULL;
}
if (m_hPdhQuery)
{
PdhCloseQuery(m_hPdhQuery);
m_hPdhQuery = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tBOOL Refresh()
{
if ( (m_hPdhQuery)
&& (ERROR_SUCCESS == PdhCollectQueryData(m_hPdhQuery))
)
{
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tINT64 Get(IPerformanceInfo::eCounter i_eCounter)
{
PDH_FMT_COUNTERVALUE l_tPdhValue = {0};
if ( (i_eCounter >= IPerformanceInfo::eCounterTotal)
|| (!m_hPdhCounter[i_eCounter])
)
{
return 0;
}
if (ERROR_SUCCESS == PdhGetFormattedCounterValue(m_hPdhCounter[i_eCounter], PDH_FMT_LARGE, NULL, &l_tPdhValue))
{
if (IPerformanceInfo::eCounterProcessCpu == i_eCounter)
{
l_tPdhValue.largeValue /= m_sSysInfo.dwNumberOfProcessors;
}
}
return l_tPdhValue.largeValue;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tINT32 Add_Ref()
{
return ATOMIC_INC(&m_iRCnt);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tINT32 Release()
{
volatile tINT32 l_iReturn = ATOMIC_DEC(&m_iRCnt);
if (0 >= l_iReturn)
{
delete this;
}
return l_iReturn;
}
};
#endif //PPERFORMANCE_INFO_H

View File

@ -0,0 +1,312 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
class CProc
{
public:
///////////////////////////////////////////////////////////////////////////////
//Get_ArgV
static tXCHAR **Get_ArgV(tINT32 *o_pCount)
{
return Get_ArgV(GetCommandLineW(), o_pCount);
}//Get_ArgV
///////////////////////////////////////////////////////////////////////////////
//Get_ArgV
static tXCHAR **Get_ArgV(const tXCHAR *i_pCmdLine, tINT32 *o_pCount)
{
tINT32 l_iLen = 0;//strlen(i_pCmdLine);
tXCHAR *l_pBuffer = NULL;//new tXCHAR[l_iLen];
tXCHAR **l_pReturn = NULL;
tBOOL l_bNew = TRUE;
tBOOL l_bStr = FALSE;
tINT32 l_iIDX = 0;
if ( (NULL == i_pCmdLine)
|| (NULL == o_pCount)
)
{
goto l_lblExit;
}
l_iLen = (tINT32)wcslen(i_pCmdLine) + 1;
l_pBuffer = new tXCHAR[l_iLen];
if (NULL == l_pBuffer)
{
goto l_lblExit;
}
for (tINT32 l_iI = 0; l_iI < l_iLen; l_iI++)
{
if (TM('\"') == i_pCmdLine[l_iI])
{
l_bStr = ! l_bStr;
}
else
{
if ( (TM(' ') == i_pCmdLine[l_iI])
&& (!l_bStr)
)
{
l_pBuffer[l_iIDX++] = 0;
}
else
{
l_pBuffer[l_iIDX++] = i_pCmdLine[l_iI];
}
}
}
l_iLen = l_iIDX;
//calculate count of items//////////////////////////////////////////////////
*o_pCount = 0;
for (tINT32 l_iI = 0; l_iI < l_iLen; l_iI++)
{
if ( (0 == l_pBuffer[l_iI])
|| ((l_iI + 1) == l_iLen)
)
{
(*o_pCount) ++;
}
}
if (0 >= *o_pCount)
{
goto l_lblExit;
}
//allocate result///////////////////////////////////////////////////////////
l_pReturn = new tXCHAR*[*o_pCount];
if (NULL == l_pReturn)
{
goto l_lblExit;
}
//fill result///////////////////////////////////////////////////////////////
l_bNew = TRUE;
l_iIDX = 0;
for (tINT32 l_iI = 0; l_iI < l_iLen; l_iI++)
{
if (l_bNew)
{
l_pReturn[l_iIDX++] = &l_pBuffer[l_iI];
l_bNew = FALSE;
}
if (0 == l_pBuffer[l_iI])
{
l_bNew = TRUE;
}
}
l_lblExit:
return l_pReturn;
// return = CommandLineToArgvW(i_pCmdLine, o_pCount);
}//Get_ArgV
///////////////////////////////////////////////////////////////////////////////
//Free_ArgV
static void Free_ArgV(tXCHAR **i_pArgV)
{
if (NULL == i_pArgV)
{
return;
}
if (i_pArgV[0])
{
delete [] i_pArgV[0];
}
delete [] i_pArgV;
//LocalFree(i_pArgV);
}//Free_ArgV
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Time()
//return a 64-bit value divided into 2 parts representing the number of
//100-nanosecond intervals since January 1, 1601 (UTC).
static tBOOL Get_Process_Time(tUINT32 *o_pHTime, tUINT32 *o_pLTime)
{
FILETIME l_tProcess_Time = {0};
FILETIME l_tStub_01 = {0};
FILETIME l_tStub_02 = {0};
FILETIME l_tStub_03 = {0};
GetProcessTimes(GetCurrentProcess(),
&l_tProcess_Time,
&l_tStub_01,
&l_tStub_02,
&l_tStub_03
);
*o_pHTime = l_tProcess_Time.dwHighDateTime;
*o_pLTime = l_tProcess_Time.dwLowDateTime;
return TRUE;
}//Get_Process_Time()
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Name
static tBOOL Get_Process_Name(tWCHAR *o_pName, tINT32 i_iMax_Len)
{
BOOL l_bReturn = FALSE;
const tUINT32 l_dwMax_Len = 32768;
wchar_t *l_pProcess_Path = NULL;
wchar_t *l_pProcess_Name = NULL;
if ( (NULL == o_pName)
|| (64 >= i_iMax_Len)
)
{
return FALSE;
}
l_pProcess_Path = new wchar_t[l_dwMax_Len];
if (NULL == l_pProcess_Path)
{
return FALSE;
}
if (GetModuleFileNameW(GetModuleHandleW(NULL),
l_pProcess_Path,
l_dwMax_Len
)
)
{
if ( (l_pProcess_Name = wcsrchr(l_pProcess_Path, L'\\'))
|| (l_pProcess_Name = wcsrchr(l_pProcess_Path, L'/'))
)
{
l_pProcess_Name ++;
l_bReturn = TRUE;
}
}
if (l_bReturn)
{
wcscpy_s((wchar_t*)o_pName, i_iMax_Len, l_pProcess_Name);
}
delete [] l_pProcess_Path;
return l_bReturn;
}//Get_Process_Name
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Name
static tBOOL Get_Process_Name(tACHAR *o_pName, tINT32 i_iMax_Len)
{
const tINT32 l_iSize = 128;
tWCHAR l_pName[l_iSize];
if (Get_Process_Name(l_pName, l_iSize))
{
Convert_UTF16_To_UTF8(l_pName, o_pName, (tUINT32)i_iMax_Len);
}
else
{
strcpy_s(o_pName, (rsize_t)i_iMax_Len, "Unknown:Error");
}
return true;
}//Get_Process_Name
////////////////////////////////////////////////////////////////////////////////
//Get_Process_Path
static tBOOL Get_Process_Path(tXCHAR *o_pPath, size_t i_szName)
{
BOOL l_bReturn = FALSE;
wchar_t *l_pName = NULL;
if ( (NULL == o_pPath)
|| (256 >= i_szName)
)
{
return FALSE;
}
if (GetModuleFileNameW(GetModuleHandleW(NULL),
o_pPath,
(DWORD)i_szName
)
)
{
if ( (l_pName = wcsrchr(o_pPath, L'\\'))
|| (l_pName = wcsrchr(o_pPath, L'/'))
)
{
l_pName ++;
l_pName[0] = 0;
l_bReturn = TRUE;
}
}
return l_bReturn;
}//Get_Process_Path
////////////////////////////////////////////////////////////////////////////////
//Get_Process_ID
static tUINT32 Get_Process_ID()
{
return GetCurrentProcessId();
}//Get_Process_ID
////////////////////////////////////////////////////////////////////////////////
//Get_Thread_Id
static tUINT32 Get_Thread_Id()
{
return GetCurrentThreadId();
}//Get_Thread_Id
////////////////////////////////////////////////////////////////////////////////
//Get_Processor
static __forceinline tUINT32 Get_Processor()
{
#if defined(GTX64) || !defined(_MSC_VER)
//return 0xFFFF; //don't know how to get processor number ... yet.
return GetCurrentProcessorNumber();
#else
_asm
{
mov eax, 1
cpuid
shr ebx, 24
mov eax, ebx
}
#endif
}//Get_Processor
};

View File

@ -0,0 +1,607 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#define SHARED_SEM_NULL NULL
////////////////////////////////////////////////////////////////////////////////
//CShared
class CShared
{
struct sShared
{
HANDLE hMemory;
HANDLE hMutex;
tXCHAR *pName;
};
enum eType
{
ETYPE_MUTEX = 0,
ETYPE_FILE ,
ETYPE_MAX
};
public:
typedef sShared *hShared;
typedef HANDLE hSem;
enum eLock
{
E_OK,
E_TIMEOUT,
E_ERROR,
E_NOT_EXISTS
};
////////////////////////////////////////////////////////////////////////////
//CShared::Create
static tBOOL Create(CShared::hShared *o_pHandle,
const tXCHAR *i_pName,
const tUINT8 *i_pData,
tUINT16 i_wSize
)
{
sShared *l_pShared = NULL;
tBOOL l_bReturn = TRUE;
DWORD l_dwLen = 0;
wchar_t *l_pName = NULL;
BOOL l_bRelease = FALSE;
tUINT8 *l_pBuffer = NULL;
if ( (NULL == i_pName)
|| (NULL == i_pData)
|| (0 >= i_wSize)
|| (NULL == o_pHandle)
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_pShared = new sShared;
if (NULL == l_pShared)
{
l_bReturn = FALSE;
goto l_lblExit;
}
memset(l_pShared, 0, sizeof(sShared));
l_dwLen = (DWORD)wcslen(i_pName) + 128;
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
l_pShared->pName = PStrDub(i_pName);
if ( (NULL == l_pName)
|| (NULL == l_pShared->pName)
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////////
//create mutex and own it
Create_Name(l_pName, l_dwLen, ETYPE_MUTEX, i_pName);
l_pShared->hMutex = CreateMutexW(NULL, TRUE, l_pName);
if ( (NULL == l_pShared->hMutex)
|| (ERROR_ALREADY_EXISTS == GetLastError())
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_bRelease = TRUE;
////////////////////////////////////////////////////////////////////////////
//create shared memory object
Create_Name(l_pName, l_dwLen, ETYPE_FILE, i_pName);
l_pShared->hMemory = CreateFileMappingW(INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order tUINT32)
i_wSize, // maximum object size (low-order tUINT32)
l_pName // name of mapping object
);
if ( (NULL == l_pShared->hMemory)
|| (ERROR_ALREADY_EXISTS == GetLastError())
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_pBuffer = (tUINT8*)MapViewOfFile(l_pShared->hMemory,
FILE_MAP_ALL_ACCESS,
0,
0,
i_wSize
);
if (NULL == l_pBuffer)
{
l_bReturn = FALSE;
goto l_lblExit;
}
*o_pHandle = (CShared::hShared)l_pShared;
__try
{
memcpy(l_pBuffer, i_pData, i_wSize);
}
__except ( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
if (l_pBuffer)
{
UnmapViewOfFile(l_pBuffer);
l_pBuffer = NULL;
}
if (l_bRelease)
{
ReleaseMutex(l_pShared->hMutex);
}
if (FALSE == l_bReturn)
{
Close((hShared)l_pShared);
l_pShared = NULL;
if (o_pHandle)
{
*o_pHandle = NULL;
}
}
return l_bReturn;
}//Shared_Create
////////////////////////////////////////////////////////////////////////////
//Read
static tBOOL Read(const tXCHAR *i_pName,
tUINT8 *o_pData,
tUINT16 i_wSize
)
{
HANDLE l_hMemory = NULL;
tBOOL l_bReturn = TRUE;
DWORD l_dwLen = 0;
wchar_t *l_pName = NULL;
tUINT8 *l_pBuffer = NULL;
if ( (NULL == i_pName)
|| (NULL == o_pData)
|| (0 >= i_wSize)
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_dwLen = (DWORD)wcslen(i_pName) + 128;
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
if (NULL == l_pName)
{
l_bReturn = FALSE;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////
//open shared memory object
Create_Name(l_pName, l_dwLen, ETYPE_FILE, i_pName);
l_hMemory = OpenFileMappingW(FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
l_pName // name of mapping object
);
if (NULL == l_hMemory)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_pBuffer = (tUINT8*)MapViewOfFile(l_hMemory,
FILE_MAP_READ,
0,
0,
i_wSize
);
if (NULL == l_pBuffer)
{
l_bReturn = FALSE;
goto l_lblExit;
}
__try
{
memcpy(o_pData, l_pBuffer, i_wSize);
}
__except ( (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR)
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
if (l_pBuffer)
{
UnmapViewOfFile(l_pBuffer);
l_pBuffer = NULL;
}
if (l_hMemory)
{
CloseHandle(l_hMemory);
l_hMemory = NULL;
}
return l_bReturn;
}//Read
////////////////////////////////////////////////////////////////////////////
//Write
static tBOOL Write(const tXCHAR *i_pName,
const tUINT8 *i_pData,
tUINT16 i_wSize
)
{
HANDLE l_hMemory = NULL;
tBOOL l_bReturn = TRUE;
DWORD l_dwLen = 0;
wchar_t *l_pName = NULL;
tUINT8 *l_pBuffer = NULL;
if ( (NULL == i_pName)
|| (NULL == i_pData)
|| (0 >= i_wSize)
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_dwLen = (DWORD)wcslen(i_pName) + 128;
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
if (NULL == l_pName)
{
l_bReturn = FALSE;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////
//open shared memory object
Create_Name(l_pName, l_dwLen, ETYPE_FILE, i_pName);
l_hMemory = OpenFileMappingW(FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
l_pName // name of mapping object
);
if (NULL == l_hMemory)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_pBuffer = (tUINT8*)MapViewOfFile(l_hMemory,
FILE_MAP_WRITE,
0,
0,
i_wSize
);
if (NULL == l_pBuffer)
{
l_bReturn = FALSE;
goto l_lblExit;
}
__try
{
memcpy(l_pBuffer, i_pData, i_wSize);
}
__except ( (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR)
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
)
{
l_bReturn = FALSE;
goto l_lblExit;
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
if (l_pBuffer)
{
UnmapViewOfFile(l_pBuffer);
l_pBuffer = NULL;
}
if (l_hMemory)
{
CloseHandle(l_hMemory);
l_hMemory = NULL;
}
return l_bReturn;
}//Write
////////////////////////////////////////////////////////////////////////////
//Lock
static eLock Lock(const tXCHAR *i_pName, CShared::hSem &o_rSem, tUINT32 i_dwTimeout_ms)
{
HANDLE l_hMutex = NULL;
eLock l_eReturn = CShared::E_OK;
DWORD l_dwLen = 0;
wchar_t *l_pName = NULL;
o_rSem = SHARED_SEM_NULL;
if (NULL == i_pName)
{
l_eReturn = CShared::E_ERROR;
goto l_lblExit;
}
l_dwLen = (DWORD)wcslen(i_pName) + 128;
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
if (NULL == l_pName)
{
l_eReturn = CShared::E_ERROR;
goto l_lblExit;
}
////////////////////////////////////////////////////////////////////////
//open mutex and own it
Create_Name(l_pName, l_dwLen, ETYPE_MUTEX, i_pName);
l_hMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, l_pName);
if (NULL == l_hMutex)
{
l_eReturn = CShared::E_NOT_EXISTS;
goto l_lblExit;
}
if (WAIT_OBJECT_0 != WaitForSingleObject(l_hMutex, i_dwTimeout_ms))
{
l_eReturn = CShared::E_TIMEOUT;
goto l_lblExit;
}
l_lblExit:
if (l_pName)
{
free(l_pName);
l_pName = NULL;
}
if (SHARED_SEM_NULL != l_hMutex)
{
if (CShared::E_OK == l_eReturn)
{
o_rSem = l_hMutex;
}
else
{
CloseHandle(l_hMutex);
l_hMutex = SHARED_SEM_NULL;
}
}
return l_eReturn;
}//Lock
////////////////////////////////////////////////////////////////////////////
//UnLock
static eLock UnLock(CShared::hSem &io_rSem)
{
HANDLE l_hMutex = NULL;
eLock l_eReturn = CShared::E_ERROR;
if (SHARED_SEM_NULL == io_rSem)
{
l_eReturn = CShared::E_NOT_EXISTS;
goto l_lblExit;
}
ReleaseMutex(io_rSem);
l_lblExit:
if (io_rSem)
{
CloseHandle(io_rSem);
io_rSem = SHARED_SEM_NULL;
}
return l_eReturn;
}//UnLock
////////////////////////////////////////////////////////////////////////////
//GetSemName
static const tXCHAR* GetName(hShared i_pShared)
{
if (NULL == i_pShared)
{
return FALSE;
}
return i_pShared->pName;
}
////////////////////////////////////////////////////////////////////////////
//Close
static tBOOL Close(hShared i_hShared)
{
if (NULL == i_hShared)
{
return FALSE;
}
//if (i_hShared->hMutex)
//{
// WaitForSingleObject(i_hShared->hMutex, 3000);
//}
if (i_hShared->hMemory)
{
CloseHandle(i_hShared->hMemory);
i_hShared->hMemory = NULL;
}
if (i_hShared->hMutex)
{
CloseHandle(i_hShared->hMutex);
i_hShared->hMutex = NULL;
}
if (i_hShared->pName)
{
PStrFreeDub(i_hShared->pName);
i_hShared->pName = NULL;
}
delete i_hShared;
return TRUE;
}//Shared_Close
////////////////////////////////////////////////////////////////////////////
//UnLink - linux required it due to fact that life time of shared object is
//almost infinit, and cleanup should be done manually
static tBOOL UnLink(const tXCHAR *i_pName)
{
UNUSED_ARG(i_pName);
return TRUE;
}//UnLink
private:
////////////////////////////////////////////////////////////////////////////
//Create_Name
static tBOOL Create_Name(tXCHAR *o_pName,
size_t i_szName,
eType i_eType,
const tXCHAR *i_pPostfix
)
{
if ( (NULL == o_pName)
|| (16 >= i_szName)
|| (ETYPE_MAX <= i_eType)
|| (NULL == i_pPostfix)
)
{
return FALSE;
}
FILETIME l_tProcess_Time = {0};
FILETIME l_tStub_01 = {0};
FILETIME l_tStub_02 = {0};
FILETIME l_tStub_03 = {0};
GetProcessTimes(GetCurrentProcess(),
&l_tProcess_Time,
&l_tStub_01,
&l_tStub_02,
&l_tStub_03
);
if (ETYPE_MUTEX == i_eType)
{
swprintf_s(o_pName,
i_szName,
L"Local\\m%d%d%d%s",
GetCurrentProcessId(),
l_tProcess_Time.dwHighDateTime,
l_tProcess_Time.dwLowDateTime,
i_pPostfix
);
}
else if (ETYPE_FILE == i_eType)
{
swprintf_s(o_pName,
i_szName,
L"Local\\f%d%d%d%s",
GetCurrentProcessId(),
l_tProcess_Time.dwHighDateTime,
l_tProcess_Time.dwLowDateTime,
i_pPostfix
);
}
return TRUE;
}//Create_Name
};

View File

@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef IPSHARED_LIB_H
#define IPSHARED_LIB_H
#include "GTypes.h"
#include "Length.h"
#include "PString.h"
#include "WString.h"
#include "SharedLib.h"
#include "PAtomic.h"
class CPSharedLib
: public CSharedLib
{
protected:
HMODULE m_pDll;
public:
CPSharedLib(const tXCHAR *i_pPath)
: CSharedLib(i_pPath)
, m_pDll(NULL)
{
m_pDll = LoadLibraryW(i_pPath);
if (m_pDll)
{
m_bState = TRUE;
}
}
void *GetFunction(const tACHAR *i_pName)
{
return (void*)(GetProcAddress(m_pDll, i_pName));
}
virtual ~CPSharedLib()
{
if (m_pDll)
{
FreeLibrary(m_pDll);
m_pDll = NULL;
}
}
};
#endif //IPSHARED_LIB_H

View File

@ -0,0 +1,294 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
//http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus
#ifndef PSIGNAL_H
#define PSIGNAL_H
#include <new.h>
#include <crtdbg.h>
#include "signal.h"
#include "ISignal.h"
static stChContext g_stContext = {0};
////////////////////////////////////////////////////////////////////////////////
//ChSignalHandler
static void __cdecl ChSignalHandler(int i_iSignal)
{
if (g_stContext.iProcessed)
{
return;
}
g_stContext.iProcessed ++;
const char *l_pText = "unknown signal";
if (SIGABRT == i_iSignal)
{
l_pText = "SIGABRT";
}
else if (SIGFPE == i_iSignal)
{
l_pText = "SIGFPE";
}
else if (SIGILL == i_iSignal)
{
l_pText = "SIGILL";
}
else if (SIGINT == i_iSignal)
{
l_pText = "SIGINT";
}
else if (SIGSEGV == i_iSignal)
{
l_pText = "SIGSEGV";
}
else if (SIGTERM == i_iSignal)
{
l_pText = "SIGTERM";
}
if (g_stContext.pUserHandler)
{
g_stContext.pUserHandler((eCrashCode)(eCrashSignal + i_iSignal), l_pText, g_stContext.pUserContext);
}
exit(1);
}//ChSignalHandler
////////////////////////////////////////////////////////////////////////////////
//ChUnhandledExceptionFilter
static LONG WINAPI ChUnhandledExceptionFilter(__in struct _EXCEPTION_POINTERS *i_pException)
{
if (g_stContext.iProcessed)
{
return EXCEPTION_CONTINUE_SEARCH;
}
if ( (STATUS_ACCESS_VIOLATION == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_ARRAY_BOUNDS_EXCEEDED == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_DATATYPE_MISALIGNMENT == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_FLT_DIVIDE_BY_ZERO == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_FLT_STACK_CHECK == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_ILLEGAL_INSTRUCTION == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_INT_DIVIDE_BY_ZERO == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_NONCONTINUABLE_EXCEPTION == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_PRIV_INSTRUCTION == i_pException->ExceptionRecord->ExceptionCode)
|| (EXCEPTION_STACK_OVERFLOW == i_pException->ExceptionRecord->ExceptionCode)
//|| ( == i_pException->ExceptionRecord.ExceptionCode)
)
{
g_stContext.iProcessed ++;
if (g_stContext.pUserHandler)
{
g_stContext.pUserHandler(eCrashException, i_pException, g_stContext.pUserContext);
}
exit(1);
}
return EXCEPTION_CONTINUE_SEARCH;
}//ChUnhandledExceptionFilter
////////////////////////////////////////////////////////////////////////////////
//ChPurecallHandler
static void ChPurecallHandler(void)
{
if (g_stContext.iProcessed)
{
return;
}
g_stContext.iProcessed ++;
if (g_stContext.pUserHandler)
{
g_stContext.pUserHandler(eCrashPureCall, "Pure call", g_stContext.pUserContext);
}
exit(1);
}//ChPurecallHandler
////////////////////////////////////////////////////////////////////////////////
//ChMemoryAllocationHandler
static int ChMemoryAllocationHandler(size_t i_szSize)
{
if (g_stContext.iProcessed)
{
return 0;
}
g_stContext.iProcessed ++;
char l_pText[32];
sprintf_s(l_pText, "%lld", (tINT64)i_szSize);
if (g_stContext.pUserHandler)
{
g_stContext.pUserHandler(eCrashMemAlloc, l_pText, g_stContext.pUserContext);
}
exit(1);
return 0;
}//ChMemoryAllocationHandler
////////////////////////////////////////////////////////////////////////////////
//ChInvalidParameterHandler
static void ChInvalidParameterHandler(const wchar_t* i_pExpression,
const wchar_t* i_pFunction,
const wchar_t* i_pFile,
unsigned int i_dwLine,
uintptr_t i_pReserved
)
{
if (g_stContext.iProcessed)
{
return;
}
g_stContext.iProcessed ++;
char l_pText[148];
const wchar_t *l_pFunction = i_pFunction ? i_pFunction : L"Func:Unk";
const wchar_t *l_pFile = i_pFile ? i_pFile : L"File:Unk";
size_t l_szFile = i_pFile ? wcslen(i_pFile) : 0;
size_t l_szFunc = i_pFunction ? wcslen(i_pFunction) : 0;
if ( l_szFile > 64 )
{
l_szFile -= 64;
}
if ( l_szFunc > 64 )
{
l_szFunc -= 64;
}
sprintf_s(l_pText, "{%S}{%S}{%d}", l_pFunction + l_szFunc, l_pFile + l_szFile, (int)i_dwLine);
if (g_stContext.pUserHandler)
{
g_stContext.pUserHandler(eCrashInvalidParameter, l_pText, g_stContext.pUserContext);
}
exit(1);
}//ChInvalidParameterHandler
////////////////////////////////////////////////////////////////////////////////
//ChInstallPrivate
static tBOOL ChInstallPrivate()
{
////////////////////////////////////////////////////////////////////////////
//initialize handlers for all possible cases
signal(SIGABRT, ChSignalHandler);
signal(SIGFPE, ChSignalHandler);
signal(SIGILL, ChSignalHandler);
signal(SIGINT, ChSignalHandler);
signal(SIGSEGV, ChSignalHandler);
signal(SIGTERM, ChSignalHandler);
//SetUnhandledExceptionFilter(ChUnhandledExceptionFilter);
AddVectoredExceptionHandler(1, ChUnhandledExceptionFilter);
_set_purecall_handler(ChPurecallHandler);
_set_new_mode(1);
_set_new_handler(ChMemoryAllocationHandler);
_set_invalid_parameter_handler(ChInvalidParameterHandler);
_CrtSetReportMode(_CRT_ERROR, 0);
_CrtSetReportMode(_CRT_ASSERT, 0);
return TRUE;
}//ChInstallPrivate
////////////////////////////////////////////////////////////////////////////////
//ChInstall
static tBOOL ChInstall()
{
if (g_stContext.iInstalled)
{
return FALSE;
}
////////////////////////////////////////////////////////////////////////////
//initialize parameters
memset(&g_stContext, 0, sizeof(g_stContext));
g_stContext.iInstalled = 1;
g_stContext.iProcessed = 0;
ChInstallPrivate();
return TRUE;
}//ChInstall
////////////////////////////////////////////////////////////////////////////////
//ChSetHandler
static tBOOL ChSetHandler(fnCrashHandler i_fnHandler)
{
if (!g_stContext.iInstalled)
{
return FALSE;
}
g_stContext.pUserHandler = i_fnHandler;
return TRUE;
}//ChSetHandler
////////////////////////////////////////////////////////////////////////////////
//ChSetContext
static tBOOL ChSetContext(void *i_pContext)
{
if (!g_stContext.iInstalled)
{
return FALSE;
}
g_stContext.pUserContext = i_pContext;
return TRUE;
}//ChSetContext
////////////////////////////////////////////////////////////////////////////////
//ChUnInstall
static tBOOL ChUnInstall()
{
return TRUE;
}//ChUnInstall
#endif //PSIGNAL_H

View File

@ -0,0 +1,220 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#include "GTypes.h"
#include "AList.h"
//256k
#define CLIENT_RECV_BUFFER_SIZE (0x40000)
//2m
#define CLIENT_SEND_BUFFER_SIZE (0x200000)
//2m
#define SERVER_RECV_BUFFER_SIZE (0x200000)
//256k
#define SERVER_SEND_BUFFER_SIZE (0x40000)
typedef SOCKET tSOCKET;
typedef int tADDR_LEN;
typedef addrinfoW tADDR_INFO;
#define INVALID_SOCKET_VAL (INVALID_SOCKET)
#define CONNECTION_IN_PROGRESS (WSAEWOULDBLOCK)
#define CLOSE_SOCKET(i_Socket) closesocket(m_hSocket)
#define GET_SOCKET_ERROR() WSAGetLastError()
//#define SOCKET_ERROR (-1)
#define GET_ADDR_INFO(i_Node, i_Service, i_Hints, o_Res) GetAddrInfoW(i_Node,\
i_Service,\
i_Hints,\
o_Res)
#define FREE_ADDR_INFO(i_Info) FreeAddrInfoW(i_Info)
////////////////////////////////////////////////////////////////////////////////
//WSA_Init
static inline tBOOL WSA_Init()
{
WSADATA l_tWSA;
if (0 != WSAStartup(MAKEWORD(1,1), &l_tWSA))
{
return FALSE;
}
return TRUE;
}//WSA_Init
////////////////////////////////////////////////////////////////////////////////
//WSA_UnInit
static inline void WSA_UnInit()
{
WSACleanup();
}//WSA_UnInit
////////////////////////////////////////////////////////////////////////////////
//Print_SAddr
static tBOOL Print_SAddr(sockaddr *i_pAddress, XCHAR *o_pIP, tUINT32 i_dwLen)
{
tBOOL l_bReturn = FALSE;
tUINT32 l_dwSize = 0;
if (NULL == i_pAddress)
{
return l_bReturn;
}
if (AF_INET6 == i_pAddress->sa_family)
{
l_dwSize = sizeof(sockaddr_in6);
}
else if (AF_INET == i_pAddress->sa_family)
{
l_dwSize = sizeof(sockaddr_in);
}
if (0 == WSAAddressToStringW(i_pAddress,
l_dwSize,
NULL,
o_pIP,
(LPDWORD)&i_dwLen
)
)
{
l_bReturn = TRUE;
}
return l_bReturn;
}//Print_SAddr
////////////////////////////////////////////////////////////////////////////////
//PEnumIpsHlp
static tBOOL PEnumIpsHlp(const char *i_pHost, CBList<sockaddr_storage*> *io_pList)
{
char l_pPort[16]= TOSTR(9009);
addrinfo *l_pInfo = NULL;
addrinfo *l_pNext = NULL;
addrinfo l_tHint = {0};
l_tHint.ai_family = AF_UNSPEC;
l_tHint.ai_socktype = SOCK_DGRAM;
l_tHint.ai_protocol = IPPROTO_UDP;
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
if (0 == getaddrinfo(i_pHost, l_pPort, &l_tHint, &l_pInfo))
{
for(l_pNext = l_pInfo; l_pNext != NULL; l_pNext = l_pNext->ai_next)
{
if ( ( (AF_INET == l_pNext->ai_family)
|| (AF_INET6 == l_pNext->ai_family)
)
&& (SOCK_DGRAM == l_pNext->ai_socktype)
&& (IPPROTO_UDP == l_pNext->ai_protocol)
)
{
sockaddr_storage *l_pNew = new sockaddr_storage;
if (AF_INET == l_pNext->ai_family)
{
memcpy(l_pNew, l_pNext->ai_addr, sizeof(sockaddr_in));
}
else if (AF_INET6 == l_pNext->ai_family)
{
memcpy(l_pNew, l_pNext->ai_addr, sizeof(sockaddr_in6));
}
else
{
memset(l_pNew, 0, sizeof(sockaddr_storage));
}
io_pList->Add_After(NULL, l_pNew);
}
}
freeaddrinfo(l_pInfo);
}
else
{
return FALSE;
}
return TRUE;
}//PEnumIpsHlp
////////////////////////////////////////////////////////////////////////////////
//PEnumIps
static tBOOL PEnumIps(CBList<sockaddr_storage*> *io_pList)
{
if (!io_pList)
{
return FALSE;
}
io_pList->Clear(TRUE);
const size_t l_szHost = 256;
char l_pHost[l_szHost];
if (0 == gethostname(l_pHost, l_szHost))
{
PEnumIpsHlp(l_pHost, io_pList);
}
PEnumIpsHlp("127.0.0.1", io_pList);
PEnumIpsHlp("::1", io_pList);
return TRUE;
}//PEnumIps
////////////////////////////////////////////////////////////////////////////////
//Disable_PortUnreachable_ICMP
static tBOOL Disable_PortUnreachable_ICMP(tSOCKET i_hSocket)
{
tUINT32 l_dwBytesReturned = 0;
tBOOL l_bNewBehavior = FALSE;
tINT32 l_iStatus = 0;
l_iStatus = WSAIoctl(i_hSocket,
SIO_UDP_CONNRESET,
&l_bNewBehavior,
sizeof(l_bNewBehavior),
NULL,
0,
(LPDWORD)&l_dwBytesReturned,
NULL,
NULL
);
return (SOCKET_ERROR == l_iStatus) ? FALSE : TRUE;
}//Disable_PortUnreachable_ICMP

View File

@ -0,0 +1,232 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <strsafe.h>
#define PRINTF(...) wprintf(__VA_ARGS__)
///////////////////////////////////////////////////////////////////////////////
//PStrLen
static inline tUINT32 PStrLen(const tXCHAR *i_pText)
{
return (tUINT32)wcslen(i_pText);
}//PStrLen
///////////////////////////////////////////////////////////////////////////////
//PUStrLen
static inline tUINT32 PUStrLen(const tXCHAR *i_pText)
{
return (tUINT32)wcslen(i_pText);
}//PUStrLen
////////////////////////////////////////////////////////////////////////////////
//PStrCpy
static inline tXCHAR* PStrCpy(tXCHAR *i_pDst,
size_t i_szDst,
const tXCHAR *i_pSrc
)
{
wcscpy_s((wchar_t*)i_pDst, i_szDst, (wchar_t*)i_pSrc);
return i_pDst;
}//PStrLen
////////////////////////////////////////////////////////////////////////////////
//PWStrCpy
static inline tXCHAR* PWStrCpy(tWCHAR *i_pDst,
size_t i_szDst,
const tWCHAR *i_pSrc
)
{
wcscpy_s((wchar_t*)i_pDst, i_szDst, (wchar_t*)i_pSrc);
return i_pDst;
}//PWStrCpy
////////////////////////////////////////////////////////////////////////////////
//PStrCpy
static inline tXCHAR* PStrNCpy(tXCHAR *i_pDst,
size_t i_szDst,
const tXCHAR *i_pSrc,
size_t i_pSrcMaxCount
)
{
wcsncpy_s((wchar_t*)i_pDst, i_szDst, (wchar_t*)i_pSrc, i_pSrcMaxCount);
return i_pDst;
}//PStrLen
///////////////////////////////////////////////////////////////////////////////
//PStrNCmp
static inline tINT32 PStrNCmp(const tXCHAR *i_pS1, const tXCHAR *i_pS2, size_t i_szLen)
{
return wcsncmp(i_pS1, i_pS2, i_szLen);
}//PStrNCmp
////////////////////////////////////////////////////////////////////////////////
//PStrNCmp
static inline tINT32 PStrNiCmp(const tXCHAR *i_pS1,
const tXCHAR *i_pS2,
size_t i_szLen
)
{
return _wcsnicmp(i_pS1, i_pS2, i_szLen);
}//PStrNCmp
////////////////////////////////////////////////////////////////////////////////
//PStrNCmp
static inline tINT32 PStrICmp(const tXCHAR *i_pS1, const tXCHAR *i_pS2)
{
return _wcsicmp(i_pS1, i_pS2);
}//PStrNCmp
////////////////////////////////////////////////////////////////////////////////
//PStrCmp
static inline tINT32 PStrCmp(const tXCHAR *i_pS1, const tXCHAR *i_pS2)
{
return wcscmp(i_pS1, i_pS2);
}//PStrCmp
///////////////////////////////////////////////////////////////////////////////
//PStrToInt
static inline tINT32 PStrToInt(const tXCHAR *i_pS1)
{
return _wtoi(i_pS1);
}//PStrToInt
///////////////////////////////////////////////////////////////////////////////
//PStrCpy
static inline void PUStrCpy(tWCHAR *i_pDst, tUINT32 i_dwMax_Len, const tXCHAR *i_pSrc)
{
wcscpy_s((wchar_t *)i_pDst, i_dwMax_Len, i_pSrc);
}//PStrCpy
///////////////////////////////////////////////////////////////////////////////
//PSPrint
static inline tINT32 PSPrint(tXCHAR *o_pBuffer,
size_t i_szBuffer,
const tXCHAR *i_pFormat,
...
)
{
va_list l_pVA;
int l_iReturn = 0;
va_start(l_pVA, i_pFormat);
l_iReturn = _vsnwprintf_s(o_pBuffer, i_szBuffer, _TRUNCATE, i_pFormat, l_pVA);
va_end(l_pVA);
return (tINT32)l_iReturn;
}//PSPrint
///////////////////////////////////////////////////////////////////////////////
//PSPrint
static inline tINT32 PSPrint(tACHAR *o_pBuffer,
size_t i_szBuffer,
const tACHAR *i_pFormat,
...
)
{
va_list l_pVA;
int l_iReturn = 0;
va_start(l_pVA, i_pFormat);
l_iReturn = _vsnprintf_s(o_pBuffer, i_szBuffer, _TRUNCATE, i_pFormat, l_pVA);
va_end(l_pVA);
return (tINT32)l_iReturn;
}//PSPrint
///////////////////////////////////////////////////////////////////////////////
//PVsnprintf
static inline int PVsnprintf(tXCHAR *o_pBuffer, size_t i_szBuffer, const tXCHAR *i_pFormat, va_list i_pArgs)
{
//size_t l_szRem = 0;
//StringCbVPrintfExW(o_pBuffer,
// i_szBuffer,
// NULL,
// &l_szRem,
// STRSAFE_IGNORE_NULLS,
// i_pFormat,
// i_pArgs
// );
//return (int)i_szBuffer - (int)l_szRem;
return _vsnwprintf_s(o_pBuffer, i_szBuffer, _TRUNCATE, i_pFormat, i_pArgs);
}//PVsnprintf
///////////////////////////////////////////////////////////////////////////////
//PStrDub
static inline tXCHAR *PStrDub(const tXCHAR *i_pStr)
{
return _wcsdup(i_pStr);
}//PStrDub
///////////////////////////////////////////////////////////////////////////////
//PStrFreeDub
static inline void PStrFreeDub(tXCHAR *i_pStr)
{
free(i_pStr);
}//PStrFreeDub
///////////////////////////////////////////////////////////////////////////////
//PStrChr
static inline const tXCHAR *PStrChr(const tXCHAR * i_pStr, tXCHAR i_cCh)
{
return wcschr(i_pStr, i_cCh);
}//PStrChr
///////////////////////////////////////////////////////////////////////////////
//PStrChr
static inline tXCHAR *PStrChr(tXCHAR * i_pStr, tXCHAR i_cCh)
{
return wcschr(i_pStr, i_cCh);
}//PStrChr
///////////////////////////////////////////////////////////////////////////////
//PStrrChr
static inline tXCHAR *PStrrChr(tXCHAR * i_pStr, tXCHAR i_cCh)
{
return wcsrchr(i_pStr, i_cCh);
}//PStrrChr
///////////////////////////////////////////////////////////////////////////////
//PStrrChr
static inline const tXCHAR *PStrrChr(const tXCHAR * i_pStr, const tXCHAR i_cCh)
{
return wcsrchr(i_pStr, i_cCh);
}//PStrrChr
///////////////////////////////////////////////////////////////////////////////
//PStrScan
#define PStrScan(i_pBuffer, i_pFormat, ...) swscanf_s(i_pBuffer, i_pFormat, __VA_ARGS__)

View File

@ -0,0 +1,90 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef PSYSTEM_H
#define PSYSTEM_H
class CSys
{
public:
///////////////////////////////////////////////////////////////////////////////
//Get_Host_Name
static tBOOL Get_Host_Name(tWCHAR *o_pName, size_t i_szName)
{
if ( (NULL == o_pName)
|| (32 >= i_szName)
)
{
return FALSE;
}
DWORD l_dwMax_Len = (DWORD)i_szName;
return GetComputerNameW((wchar_t*)o_pName, &l_dwMax_Len);
}//Get_Host_Name
///////////////////////////////////////////////////////////////////////////////
//Get_Host_Name
static tBOOL Get_Host_Name(tACHAR *o_pName, size_t i_szName)
{
const size_t l_szName = 256;
DWORD l_dwSize = (DWORD)l_szName;
wchar_t l_pName[l_szName];
if (GetComputerNameW((wchar_t*)l_pName, &l_dwSize))
{
Convert_UTF16_To_UTF8(l_pName, o_pName, (tUINT32)i_szName);
}
else
{
strcpy_s(o_pName, i_szName, "Unknown:Error");
}
return TRUE;
}//Get_Host_Name
///////////////////////////////////////////////////////////////////////////////
//Get_DateTime
static tBOOL Get_DateTime(tUINT32 &o_rYear,
tUINT32 &o_rMonth,
tUINT32 &o_rDay,
tUINT32 &o_rHour,
tUINT32 &o_rMinute,
tUINT32 &o_rSecond,
tUINT32 &o_rmSec
)
{
SYSTEMTIME l_sTitem = {0};
GetLocalTime(&l_sTitem);
o_rYear = (tUINT32)l_sTitem.wYear;
o_rMonth = (tUINT32)l_sTitem.wMonth;
o_rDay = (tUINT32)l_sTitem.wDay;
o_rHour = (tUINT32)l_sTitem.wHour;
o_rMinute = (tUINT32)l_sTitem.wMinute;
o_rSecond = (tUINT32)l_sTitem.wSecond;
o_rmSec = (tUINT32)l_sTitem.wMilliseconds;
return TRUE;
}//Get_Host_Name
};
#endif //PSYSTEM_H

View File

@ -0,0 +1,103 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <process.h>
#define THSHELL_CALL_TYPE __stdcall
#define THSHELL_RET_TYPE tUINT32
#define THSHELL_RET_OK 0
#define THSHELL_RET_NOK 1
////////////////////////////////////////////////////////////////////////////////
class CThShell
{
public:
////////////////////////////////////////////////////////////////////////////
//Base types
typedef HANDLE tTHREAD;
typedef THSHELL_RET_TYPE (THSHELL_CALL_TYPE *tpThreadProc)(void *i_pParameter);
////////////////////////////////////////////////////////////////////////////
//Create
static tBOOL Create(tpThreadProc i_pThread_Proc,
void *i_pPrm,
tTHREAD *o_pThread,
const tXCHAR *i_pName
)
{
if ( ( NULL == i_pThread_Proc )
|| ( NULL == o_pThread )
)
{
return FALSE;
}
*o_pThread = (tTHREAD)_beginthreadex( NULL,
0,
i_pThread_Proc,
i_pPrm,
0,
NULL
);
//SetThreadName( *pThread_id, thread_name);
return (*o_pThread) ? TRUE : FALSE;
}//Create
////////////////////////////////////////////////////////////////////////////
//Cleanup
static void Cleanup()
{
_endthreadex( 0 );
}//Thread_Cleanup
////////////////////////////////////////////////////////////////////////////
//Close
static tBOOL Close(tTHREAD i_hThread, tUINT32 i_dwTimeOut)
{
if (NULL == i_hThread)
{
return TRUE;
}
if ( WAIT_OBJECT_0 == WaitForSingleObject( i_hThread, i_dwTimeOut ) )
{
CloseHandle(i_hThread);
return TRUE;
}
return FALSE;
}//Close
////////////////////////////////////////////////////////////////////////////
//Sleep
static void Sleep(tUINT32 i_dwTimeOut)
{
::Sleep(i_dwTimeOut);
}//Sleep
};

View File

@ -0,0 +1,204 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#define TIME_HRS_100NS 36000000000ull
#define TIME_MIN_100NS 600000000ull
#define TIME_SEC_100NS 10000000ull
#define TIME_MSC_100NS 10000ull
////////////////////////////////////////////////////////////////////////////////
//GetTickCount - exist in OS
//tUINT32 GetTickCount()
//{
//}//GetTickCount
////////////////////////////////////////////////////////////////////////////////
//GetPerformanceCounter
static inline tUINT64 GetPerformanceCounter()
{
LARGE_INTEGER l_qwValue;
l_qwValue.QuadPart = 0;
QueryPerformanceCounter(&l_qwValue);
return l_qwValue.QuadPart;
}//GetPerformanceCounter
////////////////////////////////////////////////////////////////////////////////
//GetPerformanceFrequency
static inline tUINT64 GetPerformanceFrequency()
{
LARGE_INTEGER l_qwValue;
l_qwValue.QuadPart = 0;
QueryPerformanceFrequency(&l_qwValue);
return l_qwValue.QuadPart;
}//GetPerformanceFrequency
////////////////////////////////////////////////////////////////////////////////
//GetEpochTime
//return a 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC).
static inline void GetEpochTime(tUINT32 *o_pHi, tUINT32 *o_pLow)
{
SYSTEMTIME l_sSTime = {0};
FILETIME l_sFTime = {0};
GetSystemTime(&l_sSTime);
SystemTimeToFileTime(&l_sSTime, &l_sFTime);
if (o_pHi)
{
*o_pHi = l_sFTime.dwHighDateTime;
}
if (o_pLow)
{
*o_pLow = l_sFTime.dwLowDateTime;
}
}//GetEpochTime
////////////////////////////////////////////////////////////////////////////////
//UnpackLocalTime
//convert a 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC)
//to readable form
static inline void UnpackLocalTime(tUINT64 i_qwTime,
tUINT32 &o_rYear,
tUINT32 &o_rMonth,
tUINT32 &o_rDay,
tUINT32 &o_rHour,
tUINT32 &o_rMinutes,
tUINT32 &o_rSeconds,
tUINT32 &o_rMilliseconds,
tUINT32 &o_rMicroseconds,
tUINT32 &o_rNanoseconds
)
{
tUINT32 l_dwReminder = i_qwTime % TIME_MSC_100NS; //micro & 100xNanoseconds
tUINT32 l_dwNano = i_qwTime % 10;
tUINT32 l_dwMicro = l_dwReminder / 10;
i_qwTime -= l_dwReminder;
SYSTEMTIME l_sTime = {0};
FILETIME l_sLocalTime = {0};
FileTimeToLocalFileTime((FILETIME*)&i_qwTime, &l_sLocalTime);
FileTimeToSystemTime(&l_sLocalTime, &l_sTime);
o_rYear = l_sTime.wYear;
o_rMonth = l_sTime.wMonth;
o_rDay = l_sTime.wDay;
o_rHour = l_sTime.wHour;
o_rMinutes = l_sTime.wMinute;
o_rSeconds = l_sTime.wSecond;
o_rMilliseconds = l_sTime.wMilliseconds;
o_rMicroseconds = l_dwMicro;
o_rNanoseconds = l_dwNano;
}//UnpackLocalTime
////////////////////////////////////////////////////////////////////////////////
//PackLocalTime
//convert date & time to 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC)
tUINT64 static inline PackLocalTime(tUINT32 i_uiYear,
tUINT32 i_uiMonth,
tUINT32 i_uiDay,
tUINT32 i_uiHour,
tUINT32 i_uiMinutes,
tUINT32 i_uiSeconds,
tUINT32 i_uiMilliseconds,
tUINT32 i_uiMicroseconds,
tUINT32 i_uiNanoseconds
)
{
FILETIME l_sLocal = {0};
FILETIME l_sSystem = {0};
SYSTEMTIME l_sTime = {0};
l_sTime.wYear = (WORD)i_uiYear;
l_sTime.wMonth = (WORD)i_uiMonth;
l_sTime.wDay = (WORD)i_uiDay;
l_sTime.wHour = (WORD)i_uiHour;
l_sTime.wMinute = (WORD)i_uiMinutes;
l_sTime.wSecond = (WORD)i_uiSeconds;
l_sTime.wMilliseconds = (WORD)i_uiMilliseconds;
SystemTimeToFileTime(&l_sTime, &l_sLocal);
LocalFileTimeToFileTime(&l_sLocal, &l_sSystem);
tUINT64 l_qwReturn = ((tUINT64)(l_sSystem.dwHighDateTime) << 32) + (tUINT64)(l_sSystem.dwLowDateTime);
l_qwReturn += (i_uiMicroseconds * 10ull) + (i_uiNanoseconds / 100ull);
return l_qwReturn;
}//PackLocalTime
////////////////////////////////////////////////////////////////////////////////
//GetSecondOfDay
static inline tUINT32 GetSecondOfDay()
{
SYSTEMTIME l_sTime = {0};
GetLocalTime(&l_sTime);
return 3600 * (tUINT32)l_sTime.wHour + (tUINT32)l_sTime.wMinute * 60 + (tUINT32)l_sTime.wSecond;
}//GetSecondOfDay
////////////////////////////////////////////////////////////////////////////////
//GetEpochTime
//return a 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC).
static inline tUINT64 GetEpochTime()
{
SYSTEMTIME l_sSTime = {0};
FILETIME l_sFTime = {0};
GetSystemTime(&l_sSTime);
SystemTimeToFileTime(&l_sSTime, &l_sFTime);
return (((tUINT64)l_sFTime.dwHighDateTime) << 32ull) + (tUINT64)l_sFTime.dwLowDateTime;
}//GetEpochTime
////////////////////////////////////////////////////////////////////////////////
//GetEpochLocalTime
//return a 64-bit value of 100-nanosecond intervals since January 1, 1601 (UTC).
static inline tUINT64 GetEpochLocalTime()
{
SYSTEMTIME l_sSTime = {0};
FILETIME l_sFTime = {0};
GetLocalTime(&l_sSTime);
SystemTimeToFileTime(&l_sSTime, &l_sFTime);
return (((tUINT64)l_sFTime.dwHighDateTime) << 32ull) + (tUINT64)l_sFTime.dwLowDateTime;
}//GetEpochTime
////////////////////////////////////////////////////////////////////////////////
//GetUtcOffsetSeconds
//return UTC0 offset in seconds
static inline tINT32 GetUtcOffsetSeconds()
{
TIME_ZONE_INFORMATION l_sTZ = {};
GetTimeZoneInformation(&l_sTZ);
return (tINT32)l_sTZ.Bias * -60;
}

421
p7lib/Shared/Predicate.h Normal file
View File

@ -0,0 +1,421 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#pragma once
#define PR_USE_REGEXP
#if defined(PR_USE_REGEXP)
#pragma warning(disable : 4995 )
#include <QRegExp>
#include <QString>
#endif
////////////////////////////////////////////////////////////////////////////////
enum ePr_VType
{
EPR_VTYPE_UNK = -1,
EPR_VTYPE_INT = 0,
EPR_VTYPE_FLOAT ,
EPR_VTYPE_DATE ,
EPR_VTYPE_WTEXT ,
EPR_VTYPE_ENUM //user enumes +1, +2, +3, ... etc
};
////////////////////////////////////////////////////////////////////////////////
enum ePr_Op
{
EPR_OP_UNK = -1, //
EPR_OP_EQUAL = 0, //=
EPR_OP_NOT_EQUAL , //!=
EPR_OP_GREATER , //>
EPR_OP_GREATER_OR_EQUAL , //>=
EPR_OP_LESS , //<
EPR_OP_LESS_OR_EQUAL , //<=
EPR_OP_LEFT_INCLUDE , //<<
EPR_OP_RIGHT_INCLUDE , //>>
EPR_OP_LEFT_NOT_INCLUDE , //<!
EPR_OP_RIGHT_NOT_INCLUDE , //!>
#if defined(PR_USE_REGEXP)
EPR_OP_REG_EXP , //r=
EPR_OP_WILD_CARD //w=
#endif
};
////////////////////////////////////////////////////////////////////////////////
struct sPr_Op_Text
{
const tXCHAR *pText;
tUINT32 dwLen;
ePr_Op eType;
ePr_Op eRevers;
tBOOL bDigit;
};
static const sPr_Op_Text g_pOperators[] =
{
{ TM("<="), 2, EPR_OP_LESS_OR_EQUAL, EPR_OP_GREATER_OR_EQUAL, TRUE },
{ TM("<<"), 2, EPR_OP_LEFT_INCLUDE, EPR_OP_RIGHT_INCLUDE, FALSE},
{ TM(">>"), 2, EPR_OP_RIGHT_INCLUDE, EPR_OP_LEFT_INCLUDE, FALSE},
{ TM("<!"), 2, EPR_OP_LEFT_NOT_INCLUDE, EPR_OP_RIGHT_NOT_INCLUDE, FALSE},
{ TM("!>"), 2, EPR_OP_RIGHT_NOT_INCLUDE,EPR_OP_LEFT_NOT_INCLUDE, FALSE},
{ TM("!="), 2, EPR_OP_NOT_EQUAL, EPR_OP_NOT_EQUAL, TRUE },
{ TM(">="), 2, EPR_OP_GREATER_OR_EQUAL, EPR_OP_LESS_OR_EQUAL, TRUE },
{ TM("="), 1, EPR_OP_EQUAL, EPR_OP_EQUAL, TRUE },
{ TM(">"), 1, EPR_OP_GREATER, EPR_OP_LESS, TRUE },
{ TM("<"), 1, EPR_OP_LESS, EPR_OP_GREATER, TRUE },
#if defined(PR_USE_REGEXP)
{ TM("r="), 2, EPR_OP_REG_EXP, EPR_OP_REG_EXP, FALSE},
{ TM("w="), 2, EPR_OP_WILD_CARD, EPR_OP_WILD_CARD, FALSE},
#endif
};
////////////////////////////////////////////////////////////////////////////////
struct sPr_Var
{
tXCHAR *m_pName;
ePr_VType m_eType;
tUINT32 m_dwLength; //length of the text if it is
tBOOL m_bUsed;
union
{
tXCHAR *m_pValue;
tUINT64 m_qwValue;
double m_dbValue;
};
sPr_Var(tXCHAR *i_pName, ePr_VType i_eType)
: m_pName(NULL)
, m_eType(i_eType)
, m_dwLength(0)
, m_bUsed(FALSE)
, m_qwValue(0) //the largest value in union
{
tUINT32 l_dwLen = (i_pName) ? PStrLen(i_pName) : 0;
if (l_dwLen)
{
m_pName = new tXCHAR[l_dwLen + 1];
if (m_pName)
{
PStrCpy(m_pName, l_dwLen + 1, i_pName);
}
}
}
~sPr_Var()
{
if (m_pName)
{
delete [] m_pName;
m_pName = NULL;
}
}
};
////////////////////////////////////////////////////////////////////////////////
struct sPr_Enum_Item
{
tXCHAR *m_pName;
int m_iValue;
sPr_Enum_Item(tXCHAR *i_pName, int i_iValue)
: m_pName(NULL)
, m_iValue(i_iValue)
{
tUINT32 l_dwLen = (i_pName) ? PStrLen(i_pName) : 0;
if (l_dwLen)
{
m_pName = new tXCHAR[l_dwLen + 1];
if (m_pName)
{
PStrCpy(m_pName, l_dwLen + 1, i_pName);
}
}
}
~sPr_Enum_Item()
{
if (m_pName)
{
delete [] m_pName;
m_pName = NULL;
}
}
};
////////////////////////////////////////////////////////////////////////////////
struct sPr_Enum
{
tUINT32 m_dwID;
CBList<sPr_Enum_Item*> m_cItems;
sPr_Enum(tUINT32 i_dwID) : m_dwID(i_dwID) {}
~sPr_Enum()
{
m_cItems.Clear(TRUE);
}
};
////////////////////////////////////////////////////////////////////////////////
struct sPr_Group;
struct sPr_Node
{
union
{
sPr_Group *m_pGroup;
tXCHAR *m_pValue;
tUINT64 m_qwValue;
double m_dbValue;
};
tBOOL m_bLink; //if TRUE we use m_pGroup, otherwise - values
ePr_Op m_eOperator;
tUINT32 m_dwLength; //length of the text if it is
sPr_Var *m_pVariable;
#if defined(PR_USE_REGEXP)
QRegExp *m_pRE;
#endif
sPr_Node();
~sPr_Node();
};
////////////////////////////////////////////////////////////////////////////////
struct sPr_OrGroup
{
CBList<sPr_Node*> m_cNodes;
~sPr_OrGroup()
{
m_cNodes.Clear(TRUE);
}
};
////////////////////////////////////////////////////////////////////////////////
struct sPr_Group
{
CBList<sPr_OrGroup*> m_cOrGroups;
~sPr_Group()
{
m_cOrGroups.Clear(TRUE);
}
};
////////////////////////////////////////////////////////////////////////////////
//Normal class usage
//1. Create child class with yours structure
//2. Implement abstract function Set_Data()
//3. Set variables list using Set_Variables()
//4. If you are using enums - use Set_Enum()
//5. Set predicate string - Set_Predicate()
//6. Use Compare() to compare you structure using predicate
//
//See usage example at the end of this header file
class CPredicate
{
protected:
tXCHAR *m_pPr;
tUINT32 m_dwPr_Max;
tUINT32 m_dwPr_Len;
CBList<sPr_Var*> m_cVars;
CBList<sPr_Enum*> m_cEnums;
sPr_Group m_cGroup;
tXCHAR m_cError[512];
public:
CPredicate();
virtual ~CPredicate();
////////////////////////////////////////////////////////////////////////////
//Predicate (i_pPr) consist of next part
//Variables - %MyVariable%
//Constants - "0x20" possible values Int, Float, Date, String, Enum. Date
// has simple format "DD.MM.YYYY HH:MM:SS.MS"
//Atoms - atom is working block, you compare variable and constant. It
// is not possible to compare 2 variables, only variable and
// constant, next operators are available: "<=", "<<", ">>", "<!"
// "!>", "!=", ">=", "=", ">", "<". Operators "<<", ">>" used
// only for text ("T1 << T2" - T1 contains T2)
//Grouping - "(" and ")"
//Operators - "&", "|"
//Examples:
//$Var1$ >="0x10" & "Text" >> $Var2$
//$Var1$ >="500" & ("Text" >> $Var2$ | "Text1" >> $Var2$)
virtual tBOOL Set_Predicate(const tXCHAR *i_pPr);
tXCHAR *Get_Error();
////////////////////////////////////////////////////////////////////////////
//Set_Variables()
// i_dwCount - count of the variables, each variable has 2 values
// tXCHAR - name of the variable, allowed any characters
// ePr_VType - type of the variable
// ... - variables (2 value: name & type)
tBOOL Set_Variables(tUINT32 i_dwCount, ...);
////////////////////////////////////////////////////////////////////////////
//Set_Enum()
// i_dwEnum_ID - ID of the enum, EPR_VTYPE_ENUM, EPR_VTYPE_ENUM + 1, ... etc
// i_dwCount - count of the enum values. Each value has 2 fields
// tXCHAR - text value representation
// int - int value representation
// ... - enum values (2 fields: text & int)
tBOOL Set_Enum(tUINT32 i_dwEnum_ID, tUINT32 i_dwCount, ...);
tBOOL Check(const void *i_pData);
protected:
tBOOL Check(sPr_Group *i_pGroup);
tBOOL Build(sPr_Group *i_pGroup, tUINT32 *io_pOffset);
tBOOL Add_Node(CBList<sPr_Node*> *i_pNodes, tUINT32 *io_pOffset);
tBOOL Fill_Node(sPr_Node *i_pNode,
tXCHAR *i_pVariable,
tXCHAR *i_pConst
);
tBOOL Is_True(sPr_Node *i_pNode);
tBOOL Is_Sub(tXCHAR *i_pString,
tUINT32 i_dwLenght,
tXCHAR *i_pSearch,
tUINT32 i_dwSub_Len
);
//re-implement this function, you should get yours input structure and
//every field put to the m_cVars list.
virtual tBOOL Fill_Variables(const void *i_pData) = 0;
};
////////////////////////////////////////////////////////////////////////////////
// Predicate Example
////////////////////////////////////////////////////////////////////////////////
//
//
// enum eTest1
// {
// ETEST1_ENUM0 = 0,
// ETEST1_ENUM1 = 1,
// ETEST1_ENUM2 = 2,
// ETEST1_ENUM3 = 3
// };
//
// struct sTest1
// {
// tUINT32 m_dwInt;
// eTest1 m_eEnum;
// tXCHAR *m_pText;
// };
//
////////////////////////////////////////////////////////////////////////////////
// class CMy_Pred:
// public CPredicate
// {
// public:
// CMy_Pred():
// CPredicate()
// {
// Set_Variables(3,
// TM("Int"), EPR_VTYPE_INT, //Index = 0;
// TM("Enum"), EPR_VTYPE_ENUM + 0, //Index = 1;
// TM("Text"), EPR_VTYPE_WTEXT //Index = 2;
// );
//
// Set_Enum(EPR_VTYPE_ENUM + 0,
// 4,
// TM("ENUM0"), 0, //ETEST1_ENUM0 = 0,
// TM("ENUM1"), 1, //ETEST1_ENUM1 = 1,
// TM("ENUM2"), 2, //ETEST1_ENUM2 = 2,
// TM("ENUM3"), 3 //ETEST1_ENUM3 = 3
// );
// }
//
// protected:
// BOOL Fill_Variables(void *i_pData)
// {
// sPr_Var *l_pVar = m_cVars[0];//Index = 0, first declared variable "Int"
// if (l_pVar->m_bUsed)
// {
// l_pVar->m_qwValue = ((sTest1*)i_pData)->m_dwInt;
// }
//
// l_pVar = m_cVars[1]; //Index = 1, second declared variable "Enum"
// if (l_pVar->m_bUsed)
// {
// l_pVar->m_qwValue = ((sTest1*)i_pData)->m_eEnum;
// }
//
// l_pVar = m_cVars[2]; //Index = 2, third declared variable "Text"
// if (l_pVar->m_bUsed)
// {
// l_pVar->m_pValue = ((sTest1*)i_pData)->m_pText;
//
// //Very important to set Text length !!!!
// if (l_pVar->m_pValue)
// {
// l_pVar->m_dwLength = PStrLen(l_pVar->m_pValue);
// }
// else
// {
// l_pVar->m_dwLength = 0;
// }
// }
// return TRUE;
// }
// };
//
////////////////////////////////////////////////////////////////////////////////
// int wmain(int i_iArgC, tXCHAR* i_pArgV[])
// {
// CMy_Pred l_cPred;
// sTest1 l_sTest = {10, ETEST1_ENUM2, TM("My Name")};
//
// if (FALSE == l_cPred.Set_Predicate(TM("$Enum$ <= \"ENUM2\" & ($Int$ >= \"0x9\" | $Text$ >> \"Andrey is My Name\")")))
// {
// wprintf(l_cPred.Get_Error());
// }
//
// if (l_cPred.Check(&l_sTest))
// {
// wprintf(TM("TRUE\n"));
// }
// else
// {
// wprintf(TM("FALSE\n"));
// }
//
// return 0;
// }

View File

@ -0,0 +1,41 @@
////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
#ifndef QSTRING_HELPER_H
#define QSTRING_HELPER_H
#if defined(UTF8_ENCODING)
#define XCHAR_TO_QSTRING(X) QString::fromUtf8(X)
#else
#define XCHAR_TO_QSTRING(X) QString::fromWCharArray(X)
#endif
#if defined(UTF8_ENCODING)
#define QSTRING_TO_XCHAR_TRANSLATE(QbAUniq, QStr, XChar)\
QByteArray QbAUniq = QStr.toUtf8();\
XChar = (const tXCHAR*)QbAUniq.constData()
#define QSTRING_TO_XCHAR(QStr, XChar) QSTRING_TO_XCHAR_TRANSLATE(MAKE_UNIQUE(QbA), QStr, XChar)
#else
#define QSTRING_TO_XCHAR_TRANSLATE(QbAUniq, QStr, XChar)\
QString QbAUniq = QStr;\
XChar = (const tXCHAR*)QbAUniq.utf16()
#define QSTRING_TO_XCHAR(QStr, XChar) QSTRING_TO_XCHAR_TRANSLATE(MAKE_UNIQUE(QbA), QStr, XChar)
#endif
#endif //QSTRING_HELPER_H

Some files were not shown because too many files have changed in this diff Show More