From d81e943590c81c73a876cadb0a72dcbbeb9cb79b Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Wed, 9 Aug 2017 12:13:29 -0500 Subject: [PATCH 001/212] Delete medical litter on building explosion --- addons/medical/XEH_postInit.sqf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/addons/medical/XEH_postInit.sqf b/addons/medical/XEH_postInit.sqf index 979f3c47bc..33119c870a 100644 --- a/addons/medical/XEH_postInit.sqf +++ b/addons/medical/XEH_postInit.sqf @@ -31,6 +31,20 @@ GVAR(heartBeatSounds_Slow) = ["ACE_heartbeat_slow_1", "ACE_heartbeat_slow_2"]; if (isServer) then { ["ace_placedInBodyBag", FUNC(serverRemoveBody)] call CBA_fnc_addEventHandler; [QGVAR(createLitterServer), FUNC(handleCreateLitter)] call CBA_fnc_addEventHandler; + addMissionEventHandler ["BuildingChanged", { + if (isNil QGVAR(allCreatedLitter)) exitWith {}; + params ["_buildingOld", "_buildingNew", "_isRuin"]; + TRACE_3("BuildingChanged",_buildingOld,_buildingNew,_isRuin); + private _radius = ((0.75 * getNumber (configFile >> "CfgVehicles" >> (typeOf _buildingOld) >> "mapsize")) max 5) min 50; + TRACE_1("",_radius); + { + _x params ["", "_objects"]; + if (({(_x distance2d _buildingOld) < _radius} count _objects) > 0) then { + GVAR(allCreatedLitter) deleteAt (GVAR(allCreatedLitter) find _x); + { TRACE_1("deleting",_x); deleteVehicle _x } forEach _objects; + }; + } forEach (+GVAR(allCreatedLitter)); + }]; }; ["ace_unconscious", { From 154d56a0e4a24c149abd2df5cd14e87d8a0b504b Mon Sep 17 00:00:00 2001 From: shukari Date: Wed, 25 Oct 2017 03:49:51 +0200 Subject: [PATCH 002/212] Ability for ace engineer to configure pylons (#5672) * let ace engineer configure pylons * fix double usage --- addons/pylons/functions/fnc_canConfigurePylons.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/pylons/functions/fnc_canConfigurePylons.sqf b/addons/pylons/functions/fnc_canConfigurePylons.sqf index 9582c69bd3..d4ee2d9684 100644 --- a/addons/pylons/functions/fnc_canConfigurePylons.sqf +++ b/addons/pylons/functions/fnc_canConfigurePylons.sqf @@ -18,7 +18,7 @@ params ["_unit", "_aircraft"]; -if (GVAR(requireEngineer) && {!(_unit getUnitTrait "engineer")}) exitWith {false}; +if (GVAR(requireEngineer) && {!([_unit] call EFUNC(common,isEngineer))}) exitWith {false}; if (GVAR(requireToolkit) && {!([_unit, "ToolKit"] call EFUNC(common,hasItem))}) exitWith {false}; From 8c1952d15f4a53e928fe4b8b11655945ae0b824f Mon Sep 17 00:00:00 2001 From: Dedmen Miller Date: Thu, 26 Oct 2017 06:11:13 +0200 Subject: [PATCH 003/212] Fix ACE_ItemCore order (#5675) * Fix ACE_ItemCore order * Commy is forcing me --- addons/trenches/CfgWeapons.hpp | 2 +- addons/vehiclelock/CfgWeapons.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/trenches/CfgWeapons.hpp b/addons/trenches/CfgWeapons.hpp index b7946d0d98..de79bc277f 100644 --- a/addons/trenches/CfgWeapons.hpp +++ b/addons/trenches/CfgWeapons.hpp @@ -1,6 +1,6 @@ class CfgWeapons { - class CBA_MiscItem_ItemInfo; class ACE_ItemCore; + class CBA_MiscItem_ItemInfo; class ACE_EntrenchingTool: ACE_ItemCore { author = ECSTRING(common,ACETeam); diff --git a/addons/vehiclelock/CfgWeapons.hpp b/addons/vehiclelock/CfgWeapons.hpp index 9fe53d8760..8c7f7b137a 100644 --- a/addons/vehiclelock/CfgWeapons.hpp +++ b/addons/vehiclelock/CfgWeapons.hpp @@ -1,6 +1,6 @@ class CfgWeapons { - class CBA_MiscItem_ItemInfo; class ACE_ItemCore; + class CBA_MiscItem_ItemInfo; class ACE_key_master: ACE_ItemCore { scopeArsenal = 0; From 1a2e2848ad8f75685b4075ca9ce77c8dc54f9fab Mon Sep 17 00:00:00 2001 From: Tim Beswick Date: Thu, 26 Oct 2017 05:11:35 +0100 Subject: [PATCH 004/212] Added collision lights keybind (#5646) --- addons/weaponselect/XEH_postInit.sqf | 12 ++++++++++++ addons/weaponselect/stringtable.xml | 3 +++ 2 files changed, 15 insertions(+) diff --git a/addons/weaponselect/XEH_postInit.sqf b/addons/weaponselect/XEH_postInit.sqf index b19059cff1..4706363271 100644 --- a/addons/weaponselect/XEH_postInit.sqf +++ b/addons/weaponselect/XEH_postInit.sqf @@ -196,6 +196,18 @@ if (!hasInterface) exitWith {}; {false}, [10, [false, false, false]], false] call CBA_fnc_addKeybind; //9 Key +["ACE3 Vehicles", QGVAR(CollisionLights), localize LSTRING(CollisionLights), { + // Conditions: canInteract + if (!([ACE_player, vehicle ACE_player, []] call EFUNC(common,canInteractWith))) exitWith {false}; + // Conditions: specific + if ((ACE_player isEqualTo (vehicle ACE_player)) || {ACE_player != (driver (vehicle ACE_player))}) exitWith {false}; + + // Statement + (vehicle ACE_player) setCollisionLight !(isCollisionLightOn (vehicle ACE_player)); + true +}, +{false}, +[0, [false, false, false]]] call CBA_fnc_addKeybind; // Register fire event handler ["ace_firedPlayer", DFUNC(throwGrenade)] call CBA_fnc_addEventHandler; diff --git a/addons/weaponselect/stringtable.xml b/addons/weaponselect/stringtable.xml index 0d1f63d112..054a0f94e7 100644 --- a/addons/weaponselect/stringtable.xml +++ b/addons/weaponselect/stringtable.xml @@ -369,5 +369,8 @@ 发射烟雾发射器 發射煙霧發射器 + + Toggle Collision Lights + From c9f1719f5a447ad98fca0fcbe5936fd6c9c70e1e Mon Sep 17 00:00:00 2001 From: Tim Beswick Date: Thu, 26 Oct 2017 05:13:44 +0100 Subject: [PATCH 005/212] Hot Resupply (#5639) Allow rearm, refuel and pylons to function while vehicle engine is running --- addons/pylons/XEH_postInit.sqf | 2 ++ addons/pylons/functions/fnc_canConfigurePylons.sqf | 4 +++- addons/pylons/functions/fnc_configurePylons.sqf | 2 +- addons/pylons/functions/fnc_handleDisconnect.sqf | 1 - addons/pylons/functions/fnc_onButtonClose.sqf | 1 - addons/pylons/functions/fnc_showDialog.sqf | 11 ++++++++++- addons/pylons/stringtable.xml | 3 +++ addons/rearm/functions/fnc_rearm.sqf | 5 ++++- addons/rearm/functions/fnc_rearmEntireVehicle.sqf | 9 ++++++--- addons/rearm/script_component.hpp | 1 + addons/refuel/functions/fnc_canTurnOn.sqf | 3 +-- addons/refuel/functions/fnc_refuel.sqf | 4 ---- 12 files changed, 31 insertions(+), 15 deletions(-) diff --git a/addons/pylons/XEH_postInit.sqf b/addons/pylons/XEH_postInit.sqf index ff3d4f83d6..cee9eda0fd 100644 --- a/addons/pylons/XEH_postInit.sqf +++ b/addons/pylons/XEH_postInit.sqf @@ -43,4 +43,6 @@ addMissionEventHandler ["HandleDisconnect", LINKFUNC(handleDisconnect)]; }; + + GVAR(searchDistanceSqr) = GVAR(searchDistance) ^ 2; }] call CBA_fnc_addEventHandler; diff --git a/addons/pylons/functions/fnc_canConfigurePylons.sqf b/addons/pylons/functions/fnc_canConfigurePylons.sqf index d4ee2d9684..c679b9592d 100644 --- a/addons/pylons/functions/fnc_canConfigurePylons.sqf +++ b/addons/pylons/functions/fnc_canConfigurePylons.sqf @@ -22,4 +22,6 @@ if (GVAR(requireEngineer) && {!([_unit] call EFUNC(common,isEngineer))}) exitWit if (GVAR(requireToolkit) && {!([_unit, "ToolKit"] call EFUNC(common,hasItem))}) exitWith {false}; -(!isEngineOn _aircraft && {[_unit, _aircraft] call EFUNC(common,canInteractWith)}) +if ((_unit distanceSqr _aircraft) > GVAR(searchDistanceSqr)) exitWith {false}; + +[_unit, _aircraft] call EFUNC(common,canInteractWith) diff --git a/addons/pylons/functions/fnc_configurePylons.sqf b/addons/pylons/functions/fnc_configurePylons.sqf index 665f7ccdbc..2fbc91e949 100644 --- a/addons/pylons/functions/fnc_configurePylons.sqf +++ b/addons/pylons/functions/fnc_configurePylons.sqf @@ -69,6 +69,6 @@ if (_currentPylon == count _pylonsToConfigure) exitWith {}; [format [localize LSTRING(Stopped), _currentPylon + 1], false, 5] call EFUNC(common,displayText); }, format [localize LSTRING(ReplacingPylon), _currentPylon + 1, count _pylonsToConfigure], - {true}, + {GVAR(isCurator) || {(ace_player distanceSqr GVAR(currentAircraft)) <= GVAR(searchDistanceSqr)}}, ["isNotInZeus"] ] call EFUNC(common,progressBar); diff --git a/addons/pylons/functions/fnc_handleDisconnect.sqf b/addons/pylons/functions/fnc_handleDisconnect.sqf index c53d0ada17..f255b36535 100644 --- a/addons/pylons/functions/fnc_handleDisconnect.sqf +++ b/addons/pylons/functions/fnc_handleDisconnect.sqf @@ -20,7 +20,6 @@ params ["", "", "_uid"]; private _aircraft = GVAR(currentAircraftNamespace) getVariable ["_uid", objNull]; if (!isNull _aircraft) then { _aircraft setVariable [QGVAR(currentUser), objNull, true]; - [_aircraft, "blockEngine", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set); GVAR(currentAircraftNamespace) setVariable [_uid, nil, true]; // Remove var from namespace, no need to keep objNull }; diff --git a/addons/pylons/functions/fnc_onButtonClose.sqf b/addons/pylons/functions/fnc_onButtonClose.sqf index ef93f3f1bf..fa06f3d506 100644 --- a/addons/pylons/functions/fnc_onButtonClose.sqf +++ b/addons/pylons/functions/fnc_onButtonClose.sqf @@ -17,5 +17,4 @@ GVAR(currentAircraft) setVariable [QGVAR(currentUser), objNull, true]; GVAR(currentAircraftNamespace) setVariable [getPlayerUID ace_player, nil, true]; // Remove var from namespace, no need to keep objNull -[GVAR(currentAircraft), "blockEngine", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set); closeDialog 2; diff --git a/addons/pylons/functions/fnc_showDialog.sqf b/addons/pylons/functions/fnc_showDialog.sqf index 3e2cf8a4a8..b0f9b6c271 100644 --- a/addons/pylons/functions/fnc_showDialog.sqf +++ b/addons/pylons/functions/fnc_showDialog.sqf @@ -26,7 +26,6 @@ if (!isNull _currentUser) exitWith { }; _aircraft setVariable [QGVAR(currentUser), ace_player, true]; GVAR(currentAircraftNamespace) setVariable [getPlayerUID ace_player, _aircraft, true]; -[_aircraft, "blockEngine", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set); GVAR(isCurator) = _isCurator; GVAR(currentAircraft) = _aircraft; @@ -138,3 +137,13 @@ _edit ctrlAddEventHandler ["KeyDown", LINKFUNC(onNameChange)]; private _checkbox = _display displayCtrl ID_CHECKBOX_MIRROR; _checkbox ctrlAddEventHandler ["CheckedChanged", {[(_this select 1) == 1] call FUNC(onPylonMirror)}]; + +if (!GVAR(isCurator)) then { + [{ + isNull (GVAR(currentAircraft) getVariable [QGVAR(currentUser), objNull]) || + {(ace_player distanceSqr GVAR(currentAircraft)) > GVAR(searchDistanceSqr)} + }, { + [localize LSTRING(TooFar), false, 5] call EFUNC(common,displayText); + call FUNC(onButtonClose); + }] call CBA_fnc_waitUntilAndExecute; +}; diff --git a/addons/pylons/stringtable.xml b/addons/pylons/stringtable.xml index dbb42f3734..241b358b04 100644 --- a/addons/pylons/stringtable.xml +++ b/addons/pylons/stringtable.xml @@ -64,6 +64,9 @@ 已停止在%1號派龍架! 已停止在%1号派龙架! + + Vehicle too far + Enable Pylons Menu パイロン メニューを有効化 diff --git a/addons/rearm/functions/fnc_rearm.sqf b/addons/rearm/functions/fnc_rearm.sqf index bca193f621..e9d65c43b4 100644 --- a/addons/rearm/functions/fnc_rearm.sqf +++ b/addons/rearm/functions/fnc_rearm.sqf @@ -48,6 +48,9 @@ if (_magazineDisplayName == "") then { {(_this select 0) call FUNC(rearmSuccess)}, "", format [localize LSTRING(RearmAction), getText(configFile >> "CfgVehicles" >> (typeOf _target) >> "displayName"), _magazineDisplayName], - {true}, + { + param [0] params ["_target", "_unit"]; + (_unit distanceSqr _target) <= REARM_ACTION_DISTANCE_SQR + }, ["isnotinside"] ] call EFUNC(common,progressBar); diff --git a/addons/rearm/functions/fnc_rearmEntireVehicle.sqf b/addons/rearm/functions/fnc_rearmEntireVehicle.sqf index b0fe9f7ccf..47dde150e6 100644 --- a/addons/rearm/functions/fnc_rearmEntireVehicle.sqf +++ b/addons/rearm/functions/fnc_rearmEntireVehicle.sqf @@ -17,14 +17,17 @@ */ #include "script_component.hpp" -params ["_truck", "", "_vehicle"]; +params ["_truck", "_player", "_vehicle"]; [ TIME_PROGRESSBAR(10), - [_truck, _vehicle], + [_truck, _player, _vehicle], FUNC(rearmEntireVehicleSuccess), "", format [localize LSTRING(BasicRearmAction), getText(configFile >> "CfgVehicles" >> (typeOf _vehicle) >> "displayName")], - {true}, + { + param [0] params ["", "_player", "_vehicle"]; + (_player distanceSqr _vehicle) <= REARM_ACTION_DISTANCE_SQR + }, ["isnotinside"] ] call EFUNC(common,progressBar); diff --git a/addons/rearm/script_component.hpp b/addons/rearm/script_component.hpp index 92e279950c..a80dab55b2 100644 --- a/addons/rearm/script_component.hpp +++ b/addons/rearm/script_component.hpp @@ -19,6 +19,7 @@ #define REARM_ACTION_DISTANCE 7 +#define REARM_ACTION_DISTANCE_SQR 49 #define REARM_CALIBERS [ 6, 7, 8, 13, 19, 20, 25, 30, 35, 39, 40, 60, 70, 80, 82, 100, 105, 120, 122, 125, 155, 230, 250] #define REARM_DURATION_TAKE [ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 13, 10] diff --git a/addons/refuel/functions/fnc_canTurnOn.sqf b/addons/refuel/functions/fnc_canTurnOn.sqf index e9de5c205c..98173e0fa4 100644 --- a/addons/refuel/functions/fnc_canTurnOn.sqf +++ b/addons/refuel/functions/fnc_canTurnOn.sqf @@ -27,5 +27,4 @@ if (isNull _unit || !(_nozzle getVariable [QGVAR(isRefueling), false]) && {[_nozzle getVariable QGVAR(source)] call FUNC(getFuel) != 0} && {!isNull (_nozzle getVariable [QGVAR(sink), objNull])} && - {(fuel (_nozzle getVariable QGVAR(sink))) < 1} && - {!(isEngineOn (_nozzle getVariable QGVAR(sink)))} + {(fuel (_nozzle getVariable QGVAR(sink))) < 1} diff --git a/addons/refuel/functions/fnc_refuel.sqf b/addons/refuel/functions/fnc_refuel.sqf index e294a43497..f23e0aae5b 100644 --- a/addons/refuel/functions/fnc_refuel.sqf +++ b/addons/refuel/functions/fnc_refuel.sqf @@ -64,10 +64,6 @@ if (_maxFuel == 0) then { private _finished = false; private _fueling = _nozzle getVariable [QGVAR(isRefueling), false]; if (_fueling) then { - if (isEngineOn _sink) exitWith { - _nozzle setVariable [QGVAR(lastTickMissionTime), nil]; - _nozzle setVariable [QGVAR(isRefueling), false, true]; - }; private _fuelInSource = [_source] call FUNC(getFuel); if (_fuelInSource == 0) exitWith { [LSTRING(Hint_SourceEmpty), 2, _unit] call EFUNC(common,displayTextStructured); From 0fe25b3c9c263668f676909e31d8f5733775d26b Mon Sep 17 00:00:00 2001 From: commy2 Date: Thu, 26 Oct 2017 09:05:30 +0200 Subject: [PATCH 006/212] fix wiki suggesting activatedAddon to export addon list --- docs/wiki/framework/checkPBOs-framework.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/wiki/framework/checkPBOs-framework.md b/docs/wiki/framework/checkPBOs-framework.md index d17b8d20c7..5f7df59e66 100644 --- a/docs/wiki/framework/checkPBOs-framework.md +++ b/docs/wiki/framework/checkPBOs-framework.md @@ -24,7 +24,13 @@ If you are worried that players haven't updated ACE3 or other mods to the versio You can make a whitelist of mods that don't have to be on the server or are optional for clients. If you want to use the "Check all addons" option of this module and allow the usage of client side modifications like Blastcore or JSRS, you have to list them here. -The list must be in the following format: `["ADDON1","ADDON2",...]` where the strings are `CfgPatches` classes to all PBOs of the optional mod. To figure these out, you can use the scripting command `activatedAddons` in the editor while those mods are enabled. +The list must be in the following format: `["ADDON1","ADDON2",...]` where the strings are `CfgPatches` classes to all PBOs of the optional mod. To figure these out, you can use the script: + +```sqf +copyToClipboard str ("true" configClasses (configFile >> "CfgPatches") apply {configName _x}); +``` + +in the editor while those mods are enabled. #### 1.1.1 Example 1 From f1ca76669f385eda6cd405055766e26e1bb69d24 Mon Sep 17 00:00:00 2001 From: Tittoffer Date: Thu, 26 Oct 2017 18:22:31 +0200 Subject: [PATCH 007/212] Fortify Documentation (#5676) * Added featurex documentation for fortify. * Updated to correct version. * Correct version (3.3.0) Not released yet. Will be released in 3.3.0. * Grammar and phrasing fix. * Updated dependencies. changed dependencies_list to dependenciesx_list. Also switched out components to "acex_fortify". * Removed acex_ before component. * Fixed syntax. * Added fortify-framework.md. Redirect sitting.md from framework to frameworkx. * Minor syntax fixes to fortify-framework.md and fortify.md. Deleted old sitting-framework.md * Corrected header numbering. * Added fortify to dependenciesx_list.md * Fixed syntax errors. Added func. args. for adding custom presets. * Minor fix to args. * Fixed fnc. args. * Removed public part. * Removed public part. * Finalizing fortify-framework.md. Removed outdated note from sitting-framework.md. --- docs/_includes/dependenciesx_list.md | 5 +- docs/wiki/featurex/fortify.md | 41 ++++++++++++ docs/wiki/frameworkx/fortify-framework.md | 66 +++++++++++++++++++ .../sitting-framework.md | 7 +- 4 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 docs/wiki/featurex/fortify.md create mode 100644 docs/wiki/frameworkx/fortify-framework.md rename docs/wiki/{framework => frameworkx}/sitting-framework.md (85%) diff --git a/docs/_includes/dependenciesx_list.md b/docs/_includes/dependenciesx_list.md index 8f387be41d..1526c3e12c 100644 --- a/docs/_includes/dependenciesx_list.md +++ b/docs/_includes/dependenciesx_list.md @@ -1,3 +1,7 @@ +{% if include.component == "fortify" %} +`acex_main`, `ace_interaction` +{% endif %} + {% if include.component == "headless" %} `acex_main` {% endif %} @@ -9,4 +13,3 @@ {% if include.component == "viewrestriction" %} `acex_main` {% endif %} - diff --git a/docs/wiki/featurex/fortify.md b/docs/wiki/featurex/fortify.md new file mode 100644 index 0000000000..0a66f93acd --- /dev/null +++ b/docs/wiki/featurex/fortify.md @@ -0,0 +1,41 @@ +--- +layout: wiki +title: fortify +description: Enables player to build fortifications. +group: feature +category: interaction +parent: wiki +mod: acex +version: + major: 3 + minor: 3 + patch: 0 +--- + +## 1. Overview + +Enable players to place down fortifications. Budget enables mission makers / admin to restrict the amount of resources available. + +## 2. Usage + +Please note that to use this function the Fortify module needs to be placed down and `Fortify Tool` equipped by player. + +### 2.1 Placing fortification + +- Open self-interaction menu with Ctrl + ⊞ Win (ACE3 default). +- Select `Equipment` -> `Fortify`. +- Choose your fortification object and follow the instructions on the screen. + +### 2.1 Removing fortification + +- Use interaction ⊞ Win on object. + +## 3. Tips + +- Using Alt / Ctrl / Shift + Scroll Wheel you can rotate object on different axis. +- You can use planks to get up on rooftops. +- Holding Ctrl while placing allows for placing multiple objects of the same type. + +## 4. Dependencies + +{% include dependenciesx_list.md component="fortify" %} diff --git a/docs/wiki/frameworkx/fortify-framework.md b/docs/wiki/frameworkx/fortify-framework.md new file mode 100644 index 0000000000..eaf30f628f --- /dev/null +++ b/docs/wiki/frameworkx/fortify-framework.md @@ -0,0 +1,66 @@ +--- +layout: wiki +title: Fortify Framework +description: Explains how to set-up the Fortify component. +group: framework +order: 6 +parent: wiki +mod: acex +version: + major: 3 + minor: 3 + patch: 0 +--- + +## 1. Overview + +The Fortify framework allows server admins or mission makers to give players the ability to place fortifications through self-interaction, using the `Fortify Tool`. + + +### 1.1 Chat commands + +If the Fortify module is present in the mission, server admins can use chat commands to set-up or change the different parameters. Useful to give players additional resources based on progress on the mission for example. + +- `#ace-fortify on` turns fortify mode on +- `#ace-fortify off` turns fortify mode off +- `#ace-fortify west small 500` registers the "small" preset for the west side with a budget of 500 +- `#ace-fortify west medium` registers the "medium" preset for the west side with no budget +- `#ace-fortify o big` registers the "big" preset for the east side with no budget + +## 1.2 Adding custom presets + +There are two ways of adding custom presets to your mission, either via code or through desciption.ext. + +To add a preset via code you use the function `call acex_fortify_fnc_registerObjects`. Also enables Fortify. + +``` +* Registers the given objects in the given side's player interaction menu. +* Players on that side must have the `Fortify Tool` item in their inventory to access the menu. +* Classnames must be in the format [, ] +* MUST BE CALLED ON SERVER! +* +* Arguments: +* 0: Side +* 1: Budget +* 2: Object Classnames +* +* Return Value: +* None +* +* Example: +* [west, 5000, [["Sandbag", 5], ["Bunker", 50]]] call acex_fortify_fnc_registerObjects +``` + +Adding it through `description.ext` you use: + +```c++ +class ACEX_Fortify_Presets { + class myMissionObjects { + objects[] = { + {"Sandbag", 5}, + {"Bunker", 50} + }; + }; + ``` + + Then you will have to set the mission preset to `myMissionObjects` with `#fortify blufor myMissionObjects` to enable it. diff --git a/docs/wiki/framework/sitting-framework.md b/docs/wiki/frameworkx/sitting-framework.md similarity index 85% rename from docs/wiki/framework/sitting-framework.md rename to docs/wiki/frameworkx/sitting-framework.md index e3634c01c7..639b68db1a 100644 --- a/docs/wiki/framework/sitting-framework.md +++ b/docs/wiki/frameworkx/sitting-framework.md @@ -10,12 +10,11 @@ version: major: 3 minor: 2 patch: 0 +redirect_from: "/wiki/framework/sitting-framework.md" --- -
-
Note:
-

ACE3 Sitting has been deprecated in favour of ACEX Sitting and will be removed in a future version.

-
+_Sitting has been moved from ACE3 (in v3.8.0) to ACEX._ + ## 1. Requirements From a24b095b6af22c1eaf3172f9739d7af30239b800 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Thu, 26 Oct 2017 12:31:34 -0500 Subject: [PATCH 008/212] Add more sources for pylon (Taru and Huron pods) (#5682) Close #5677 --- addons/pylons/XEH_postInit.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/pylons/XEH_postInit.sqf b/addons/pylons/XEH_postInit.sqf index cee9eda0fd..8dae8d4552 100644 --- a/addons/pylons/XEH_postInit.sqf +++ b/addons/pylons/XEH_postInit.sqf @@ -15,7 +15,7 @@ "", {[_target] call FUNC(showDialog)}, { - private _vehicles = _target nearObjects ["LandVehicle", GVAR(searchDistance) + 10]; + private _vehicles = nearestObjects [_target, ["Air", "LandVehicle", "Slingload_base_F", "ReammoBox_F"], GVAR(searchDistance) + 10]; private _filter = ["transportAmmo", QEGVAR(rearm,defaultSupply)] select (["ace_rearm"] call EFUNC(common,isModLoaded)); private _rearmVehicles = {(getNumber (configFile >> "CfgVehicles" >> typeOf _x >> _filter)) > 0} count _vehicles; From 7acff1848bd8bc4d73eeb098237fd2c7c32c18fb Mon Sep 17 00:00:00 2001 From: Cuel Date: Fri, 27 Oct 2017 00:40:06 +0200 Subject: [PATCH 009/212] Set correct state (#5684) --- addons/spectator/functions/fnc_setSpectator.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/spectator/functions/fnc_setSpectator.sqf b/addons/spectator/functions/fnc_setSpectator.sqf index 3d8a6ab5bf..b995a16648 100644 --- a/addons/spectator/functions/fnc_setSpectator.sqf +++ b/addons/spectator/functions/fnc_setSpectator.sqf @@ -119,6 +119,6 @@ GVAR(interrupts) = []; // Mark spectator state for reference GVAR(isSet) = _set; -player setVariable [QGVAR(isSet), true, true]; +player setVariable [QGVAR(isSet), _set, true]; ["ace_spectatorSet", [_set, player]] call CBA_fnc_globalEvent; From cda060d3e004313b27ef8582123bb755cc6f28b9 Mon Sep 17 00:00:00 2001 From: ulteq Date: Fri, 27 Oct 2017 12:39:48 +0200 Subject: [PATCH 010/212] Weather - Properly sync overcast value (#5688) * Makes sure that all clients share the same (numeric) overcast value * Only affects the barometric pressure calculation * Does not affect the actual weather on the clients --- .../advanced_ballistics/functions/fnc_handleFired.sqf | 2 +- addons/weather/XEH_postInit.sqf | 11 ++++++----- .../functions/fnc_calculateBarometricPressure.sqf | 2 +- addons/weather/functions/fnc_getMapData.sqf | 1 + addons/weather/functions/fnc_serverController.sqf | 2 +- addons/weather/functions/fnc_updateAceWeather.sqf | 2 +- addons/weather/functions/fnc_updateHumidity.sqf | 2 +- addons/weather/functions/fnc_updateTemperature.sqf | 2 +- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/addons/advanced_ballistics/functions/fnc_handleFired.sqf b/addons/advanced_ballistics/functions/fnc_handleFired.sqf index 51d6629acc..f9145ddc37 100644 --- a/addons/advanced_ballistics/functions/fnc_handleFired.sqf +++ b/addons/advanced_ballistics/functions/fnc_handleFired.sqf @@ -112,7 +112,7 @@ if (_caliber > 0 && _bulletLength > 0 && _bulletMass > 0 && _barrelTwist > 0) th GVAR(currentbulletID) = (GVAR(currentbulletID) + 1) % 10000; -"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17", GVAR(currentbulletID), _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _muzzleVelocity, _transonicStabilityCoef, getPosASL _projectile, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), overcast, CBA_missionTime toFixed 6]; +"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17", GVAR(currentbulletID), _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _muzzleVelocity, _transonicStabilityCoef, getPosASL _projectile, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), EGVAR(weather,currentOvercast), CBA_missionTime toFixed 6]; GVAR(allBullets) pushBack [_projectile, _caliber, _bulletTraceVisible, GVAR(currentbulletID)]; diff --git a/addons/weather/XEH_postInit.sqf b/addons/weather/XEH_postInit.sqf index 09fc2909e3..0e72fc4748 100644 --- a/addons/weather/XEH_postInit.sqf +++ b/addons/weather/XEH_postInit.sqf @@ -11,13 +11,14 @@ GVAR(wind_period_start_time) = CBA_missionTime; if (!isServer) then { "ACE_MISC_PARAMS" addPublicVariableEventHandler { TRACE_1("MISC PARAMS PVEH",ACE_MISC_PARAMS); + GVAR(currentOvercast) = (ACE_MISC_PARAMS select 0); if (GVAR(syncMisc)) then { - 30 setRainbow (ACE_MISC_PARAMS select 0); - 30 setFog (ACE_MISC_PARAMS select 1); + 30 setRainbow (ACE_MISC_PARAMS select 1); + 30 setFog (ACE_MISC_PARAMS select 2); }; - GVAR(temperatureShift) = (ACE_MISC_PARAMS select 2); - GVAR(badWeatherShift) = (ACE_MISC_PARAMS select 3); - GVAR(humidityShift) = (ACE_MISC_PARAMS select 4); + GVAR(temperatureShift) = (ACE_MISC_PARAMS select 3); + GVAR(badWeatherShift) = (ACE_MISC_PARAMS select 4); + GVAR(humidityShift) = (ACE_MISC_PARAMS select 5); call FUNC(updateTemperature); call FUNC(updateHumidity); }; diff --git a/addons/weather/functions/fnc_calculateBarometricPressure.sqf b/addons/weather/functions/fnc_calculateBarometricPressure.sqf index 29b8fa7877..0749004c21 100644 --- a/addons/weather/functions/fnc_calculateBarometricPressure.sqf +++ b/addons/weather/functions/fnc_calculateBarometricPressure.sqf @@ -15,4 +15,4 @@ */ #include "script_component.hpp" -((1013.25 - 10 * overcast) * (1 - (0.0065 * (EGVAR(common,mapAltitude) + _this)) / (KELVIN(GVAR(currentTemperature)) + 0.0065 * EGVAR(common,mapAltitude))) ^ 5.255754495); +((1013.25 - 10 * GVAR(currentOvercast)) * (1 - (0.0065 * (EGVAR(common,mapAltitude) + _this)) / (KELVIN(GVAR(currentTemperature)) + 0.0065 * EGVAR(common,mapAltitude))) ^ 5.255754495); diff --git a/addons/weather/functions/fnc_getMapData.sqf b/addons/weather/functions/fnc_getMapData.sqf index 2b222c2d8b..1d27386574 100644 --- a/addons/weather/functions/fnc_getMapData.sqf +++ b/addons/weather/functions/fnc_getMapData.sqf @@ -45,6 +45,7 @@ GVAR(Humidity) = [82, 80, 78, 70, 71, 72, 70, 73, 78, 80, 83, 82]; GVAR(currentTemperature) = 20; GVAR(currentHumidity) = 0.5; +GVAR(currentOvercast) = 0; // Get all non inherited arrays to filter maps that inherit from Stratis/Altis/Tanoa private _nonInheritedArrays = configProperties [configFile >> "CfgWorlds" >> _worldName, "isArray _x", false]; diff --git a/addons/weather/functions/fnc_serverController.sqf b/addons/weather/functions/fnc_serverController.sqf index 96470aa3bb..684dc37e49 100644 --- a/addons/weather/functions/fnc_serverController.sqf +++ b/addons/weather/functions/fnc_serverController.sqf @@ -27,7 +27,7 @@ if (GVAR(useACEWeather)) then { publicVariable "ACE_WIND_PARAMS"; }; if (GVAR(syncMisc)) then { - ACE_MISC_PARAMS = [rainbow, fogParams, GVAR(temperatureShift), GVAR(badWeatherShift), GVAR(humidityShift)]; + ACE_MISC_PARAMS = [overcast, rainbow, fogParams, GVAR(temperatureShift), GVAR(badWeatherShift), GVAR(humidityShift)]; publicVariable "ACE_MISC_PARAMS"; }; }; diff --git a/addons/weather/functions/fnc_updateAceWeather.sqf b/addons/weather/functions/fnc_updateAceWeather.sqf index 337ee8db00..0e340a447d 100644 --- a/addons/weather/functions/fnc_updateAceWeather.sqf +++ b/addons/weather/functions/fnc_updateAceWeather.sqf @@ -99,7 +99,7 @@ if (GVAR(syncWind) && {GVAR(wind_period_count) > GVAR(wind_next_period)}) then { if (GVAR(syncMisc)) then { - ACE_MISC_PARAMS = [rainbow, fogParams, GVAR(temperatureShift), GVAR(badWeatherShift), GVAR(humidityShift)]; + ACE_MISC_PARAMS = [overcast, rainbow, fogParams, GVAR(temperatureShift), GVAR(badWeatherShift), GVAR(humidityShift)]; publicVariable "ACE_MISC_PARAMS"; }; diff --git a/addons/weather/functions/fnc_updateHumidity.sqf b/addons/weather/functions/fnc_updateHumidity.sqf index 79569e7367..31945d4fb2 100644 --- a/addons/weather/functions/fnc_updateHumidity.sqf +++ b/addons/weather/functions/fnc_updateHumidity.sqf @@ -19,7 +19,7 @@ private _month = date select 1; GVAR(currentHumidity) = (GVAR(Humidity) select (_month - 1)) / 100; -if ((rain > 0) && {overcast > 0.7}) then { +if ((rain > 0) && {GVAR(currentOvercast) > 0.7}) then { GVAR(currentHumidity) = 1; } else { private _avgTemperature = ((GVAR(TempDay) select (_month - 1)) + (GVAR(TempNight) select (_month - 1))) / 2; diff --git a/addons/weather/functions/fnc_updateTemperature.sqf b/addons/weather/functions/fnc_updateTemperature.sqf index 879e061574..847d594b9b 100644 --- a/addons/weather/functions/fnc_updateTemperature.sqf +++ b/addons/weather/functions/fnc_updateTemperature.sqf @@ -21,7 +21,7 @@ private _month = date select 1; private _timeRatio = abs(_time - 12) / 12; GVAR(currentTemperature) = (GVAR(TempDay) select (_month - 1)) * (1 - _timeRatio) + (GVAR(TempNight) select (_month - 1)) * _timeRatio; -GVAR(currentTemperature) = GVAR(currentTemperature) + GVAR(temperatureShift) - GVAR(badWeatherShift) * overcast; +GVAR(currentTemperature) = GVAR(currentTemperature) + GVAR(temperatureShift) - GVAR(badWeatherShift) * GVAR(currentOvercast); GVAR(currentTemperature) = round(GVAR(currentTemperature) * 10) / 10; TRACE_2("temperatureShift/badWeatherShift",GVAR(temperatureShift),GVAR(badWeatherShift)); From 4c2348cff53dceffd3444341debca7ff3d23b07d Mon Sep 17 00:00:00 2001 From: ulteq Date: Fri, 27 Oct 2017 22:53:15 +0200 Subject: [PATCH 011/212] Scopes - Fixes zero on three vanilla weapons (#5696) * Manually fix rail heights where the automated gathering failed * Affects: Noreen "Bad News" ULR, Vector SMG and ASP-1 Kir --- addons/scopes/CfgWeapons.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/scopes/CfgWeapons.hpp b/addons/scopes/CfgWeapons.hpp index 555cd94ab6..5b36c59e9f 100644 --- a/addons/scopes/CfgWeapons.hpp +++ b/addons/scopes/CfgWeapons.hpp @@ -306,7 +306,7 @@ class CfgWeapons { }; class SMG_01_Base: Rifle_Short_Base_F { - ACE_RailHeightAboveBore = 4.85355; + ACE_RailHeightAboveBore = 8.85355; }; class SMG_02_base_F: Rifle_Short_Base_F { ACE_RailHeightAboveBore = 4.41831; @@ -362,13 +362,13 @@ class CfgWeapons { ACE_RailHeightAboveBore = 2.83284; }; class srifle_DMR_02_F: DMR_02_base_F { - ACE_RailHeightAboveBore = 3.43913; + ACE_RailHeightAboveBore = 4.43913; }; class srifle_DMR_03_F: DMR_03_base_F { ACE_RailHeightAboveBore = 4.0795; }; class srifle_DMR_04_F: DMR_04_base_F { - ACE_RailHeightAboveBore = 2.38022; + ACE_RailHeightAboveBore = 5.38022; }; class srifle_DMR_05_blk_F: DMR_05_base_F { ACE_RailHeightAboveBore = 3.91334; From 4a1653c292511d59a60bd6ce474f1f86819c90a5 Mon Sep 17 00:00:00 2001 From: Tittoffer Date: Sat, 28 Oct 2017 18:18:46 +0200 Subject: [PATCH 012/212] Pylons documentation (#5690) * First draft for pylons documentation. * First draft for pylons documentation. * Minor phrasing changes. * Fix link to Rearm page --- docs/wiki/feature/pylons.md | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/wiki/feature/pylons.md diff --git a/docs/wiki/feature/pylons.md b/docs/wiki/feature/pylons.md new file mode 100644 index 0000000000..c490b33fb2 --- /dev/null +++ b/docs/wiki/feature/pylons.md @@ -0,0 +1,41 @@ +--- +layout: wiki +title: Pylons +description: Adds an interface that allow players to configure aircraft pylons in-game. +group: feature +category: interaction +parent: wiki +mod: ace +version: + major: 3 + minor: 11 + patch: 0 +--- + +## 1. Overview + +Adds an interface that allow players to configure aircraft pylons in-game. Loadouts can be saved and loaded through interface. + +## 2. Usage + +### 2.1 Configure Pylons + +To configure pylons you need a `Toolkit` equipped, a rearm vehicle nearby and be an engineer (Note: these requirements can be disabled) + +- Interact with aircraft using ⊞ Win (ACE3 default key bind `Interaction Key`). +- Select `Configure Pylons`. +- Configure your loadout in the menu that appears. +- Press `APPLY` when done. +- Rearm the aircraft (see [Rearm](rearm.html) page). + +### 2.2 Managing loadouts + +To save a custom loadout you first configure it. In the text box above `SAVE`, `LOAD` and `DELETE` you type the loadout name, then press `SAVE`. + +To load a custom loadout you select it in the preset pane and press `LOAD` followed by `APPLY`. + +To delete a custom loadout you select it in the preset pane and press `DELETE`. + +## 3. Dependencies + +{% include dependencies_list.md component="pylons" %} From c815a9cae874649e2e9c9a0bbdd551c94ecbb2d9 Mon Sep 17 00:00:00 2001 From: Cuel Date: Sat, 28 Oct 2017 18:23:18 +0200 Subject: [PATCH 013/212] (spectator) unhide/unmute unit on exiting (#5699) * unhide/unmute unit on exiting * Update fnc_setSpectator.sqf --- addons/spectator/functions/fnc_setSpectator.sqf | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/spectator/functions/fnc_setSpectator.sqf b/addons/spectator/functions/fnc_setSpectator.sqf index b995a16648..c7087d6d5b 100644 --- a/addons/spectator/functions/fnc_setSpectator.sqf +++ b/addons/spectator/functions/fnc_setSpectator.sqf @@ -110,8 +110,13 @@ if (alive player) then { [player, _hidden, QGVAR(isSet), side group player] call EFUNC(common,switchToGroupSide); // Ghosts can't talk - [player, QGVAR(isSet)] call EFUNC(common,hideUnit); - [player, QGVAR(isSet)] call EFUNC(common,muteUnit); + if (_hidden) then { + [player, QGVAR(isSet)] call EFUNC(common,hideUnit); + [player, QGVAR(isSet)] call EFUNC(common,muteUnit); + } else { + [player, QGVAR(isSet)] call EFUNC(common,unhideUnit); + [player, QGVAR(isSet)] call EFUNC(common,unmuteUnit); + }; }; // Reset interruptions From 9d6b77266109c33331d7d6674a063edec69b0114 Mon Sep 17 00:00:00 2001 From: ulteq Date: Sat, 28 Oct 2017 19:46:13 +0200 Subject: [PATCH 014/212] Ballistics - Automatic MOA -> RAD conversion --- addons/ballistics/CfgWeapons.hpp | 36 +++++++++++++------------- addons/ballistics/script_component.hpp | 2 ++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/addons/ballistics/CfgWeapons.hpp b/addons/ballistics/CfgWeapons.hpp index f95408d6a6..88572e6d8f 100644 --- a/addons/ballistics/CfgWeapons.hpp +++ b/addons/ballistics/CfgWeapons.hpp @@ -17,13 +17,13 @@ class CfgWeapons { class GM6_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; }; class LRR_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.00020; // radians. Equal to 0.70 MOA. + dispersion = MOA_TO_RAD(0.7); }; }; @@ -40,59 +40,59 @@ class CfgWeapons { class DMR_06_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; class FullAuto: Mode_FullAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; }; class DMR_05_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; class FullAuto: Mode_FullAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; }; class DMR_04_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; }; class DMR_03_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.00032; // radians. Equal to 1.10 MOA. + dispersion = MOA_TO_RAD(1.1); }; class FullAuto: Mode_FullAuto { - dispersion = 0.00032; // radians. Equal to 1.10 MOA. + dispersion = MOA_TO_RAD(1.1); }; }; class DMR_02_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.000262; // radians. Equal to 0.90 MOA. + dispersion = MOA_TO_RAD(0.9); }; }; class DMR_01_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.0004; // radians. Equal to 1.375 MOA. + dispersion = MOA_TO_RAD(1.375); }; }; class EBR_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; class FullAuto: Mode_FullAuto { - dispersion = 0.00029; // radians. Equal to 1.00 MOA. + dispersion = MOA_TO_RAD(1.0); }; }; @@ -127,11 +127,11 @@ class CfgWeapons { ACE_barrelTwist = 228.6; ACE_barrelLength = 457.2; class Single: Single { - dispersion = 0.000436; // radians. Equal to 1.50 MOA. + dispersion = MOA_TO_RAD(1.5); }; class FullAuto: FullAuto { - dispersion = 0.000436; // radians. Equal to 1.50 MOA. + dispersion = MOA_TO_RAD(1.5); }; }; @@ -206,15 +206,15 @@ class CfgWeapons { class SDAR_base_F: Rifle_Base_F { initSpeed = -1.211; class Single: Mode_SemiAuto { - dispersion = 0.0008727; // radians. Equal to 3 MOA. + dispersion = MOA_TO_RAD(3.0); }; class Burst: Mode_Burst { - dispersion = 0.0008727; // radians. Equal to 3 MOA. + dispersion = MOA_TO_RAD(3.0); }; class FullAuto: Mode_FullAuto { - dispersion = 0.0008727; // radians. Equal to 3 MOA. + dispersion = MOA_TO_RAD(3.0); }; }; diff --git a/addons/ballistics/script_component.hpp b/addons/ballistics/script_component.hpp index a1b54b53b4..969f340063 100644 --- a/addons/ballistics/script_component.hpp +++ b/addons/ballistics/script_component.hpp @@ -15,3 +15,5 @@ #endif #include "\z\ace\addons\main\script_macros.hpp" + +#define MOA_TO_RAD(d) (d * 0.00029088) // Conversion factor: PI / 10800 From 916d5ee6c054bf399eb8e798cc0738e113ea236e Mon Sep 17 00:00:00 2001 From: ulteq Date: Sat, 28 Oct 2017 20:26:59 +0200 Subject: [PATCH 015/212] Ballistics - Added comments with actual the weapon names --- addons/ballistics/CfgWeapons.hpp | 148 ++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 43 deletions(-) diff --git a/addons/ballistics/CfgWeapons.hpp b/addons/ballistics/CfgWeapons.hpp index 88572e6d8f..9c18579276 100644 --- a/addons/ballistics/CfgWeapons.hpp +++ b/addons/ballistics/CfgWeapons.hpp @@ -11,22 +11,22 @@ class CfgWeapons { class Rifle_Base_F; class Rifle_Short_Base_F: Rifle_Base_F {}; class Rifle_Long_Base_F: Rifle_Base_F {}; - class MuzzleSlot; - - /* Long Rifles */ + // GM6 Lynx class GM6_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(1.0); }; }; + // M200 Intervention class LRR_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(0.7); }; }; + // QBU-88 class DMR_07_base_F: Rifle_Long_Base_F { initSpeed = -1.06051; ACE_barrelTwist = 228.6; @@ -38,6 +38,7 @@ class CfgWeapons { }; }; + // M14 class DMR_06_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(1.0); @@ -48,6 +49,7 @@ class CfgWeapons { }; }; + // Cyrus class DMR_05_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(1.0); @@ -58,12 +60,14 @@ class CfgWeapons { }; }; + // ASP-1 Kir class DMR_04_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(1.0); }; }; + // SIG 556 class DMR_03_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(1.1); @@ -74,18 +78,21 @@ class CfgWeapons { }; }; + // Noreen "Bad News" ULR class DMR_02_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(0.9); }; }; + // VS-121 class DMR_01_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(1.375); }; }; + // Mk14 Mod 1 EBR class EBR_base_F: Rifle_Long_Base_F { class Single: Mode_SemiAuto { dispersion = MOA_TO_RAD(1.0); @@ -96,12 +103,13 @@ class CfgWeapons { }; }; - /* MX */ - + // MX class arifle_MX_Base_F: Rifle_Base_F { class Single: Mode_SemiAuto {}; class FullAuto: Mode_FullAuto {}; }; + + // MX LSW class arifle_MX_SW_F: arifle_MX_Base_F { magazines[] = { "100Rnd_65x39_caseless_mag_Tracer", @@ -115,6 +123,8 @@ class CfgWeapons { ACE_barrelTwist = 228.6; ACE_barrelLength = 406.4; }; + + // MXM class arifle_MXM_F: arifle_MX_Base_F { magazines[] = { "30Rnd_65x39_caseless_mag", @@ -134,12 +144,8 @@ class CfgWeapons { dispersion = MOA_TO_RAD(1.5); }; }; - - - /* Katiba */ - class arifle_katiba_Base_F: Rifle_Base_F {}; - - /* SPAR */ + + // HK416A5 11" class arifle_SPAR_01_base_F: Rifle_Base_F { magazines[] = { "30Rnd_556x45_Stanag", @@ -157,11 +163,15 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 264.0; }; + + // HK416A5 14.5" class arifle_SPAR_02_base_F: Rifle_Base_F { initSpeed = -0.934282; ACE_barrelTwist = 177.8; ACE_barrelLength = 368.0; }; + + // HK417A2 20" class arifle_SPAR_03_base_F: Rifle_Base_F { magazines[] = { "20Rnd_762x51_Mag", @@ -178,7 +188,7 @@ class CfgWeapons { ACE_barrelLength = 508.0; }; - /* Other */ + // Stoner 99 LMG class LMG_Mk200_F: Rifle_Long_Base_F { magazines[] = { "200Rnd_65x39_cased_Box", @@ -189,20 +199,22 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 317.5; }; + + // Negev NG7 class LMG_Zafir_F: Rifle_Long_Base_F { initSpeed = -1.00333; ACE_barrelTwist = 304.8; ACE_barrelLength = 459.74; }; + + // M249 SPW class LMG_03_base_F: Rifle_Long_Base_F { initSpeed = -1.02002; ACE_barrelTwist = 177.8; ACE_barrelLength = 414.02; }; - class Tavor_base_F: Rifle_Base_F {}; - class mk20_base_F: Rifle_Base_F {}; - /* SMGs */ + // RFB SDAR class SDAR_base_F: Rifle_Base_F { initSpeed = -1.211; class Single: Mode_SemiAuto { @@ -218,84 +230,103 @@ class CfgWeapons { }; }; - /* Pistols */ - class Pistol; class Pistol_Base_F: Pistol {}; + // P99 class hgun_P07_F: Pistol_Base_F { initSpeed = -1.0; ACE_barrelTwist = 254.0; ACE_barrelLength = 101.6; }; + // MP-443 Grach class hgun_Rook40_F: Pistol_Base_F { initSpeed = -1.03077; ACE_barrelTwist = 254.0; ACE_barrelLength = 111.76; }; + // Custom Covert II class hgun_ACPC2_F: Pistol_Base_F { initSpeed = -1.0; ACE_barrelTwist = 406.4; ACE_barrelLength = 127.0; }; + // FNX-45 Tactical class hgun_Pistol_heavy_01_F: Pistol_Base_F { initSpeed = -0.96; ACE_barrelTwist = 406.4; ACE_barrelLength = 114.3; }; + // Chiappa Rhino 60DS class hgun_Pistol_heavy_02_F: Pistol_Base_F { initSpeed = -0.92; ACE_barrelTwist = 406.4; ACE_barrelLength = 76.2; }; + // Makarov PM class hgun_Pistol_01_F: Pistol_Base_F { initSpeed = -0.974359; ACE_barrelTwist = 254.0; ACE_barrelLength = 93.5; }; + // CPW class pdw2000_base_F: Rifle_Short_Base_F { initSpeed = -1.09615; ACE_barrelTwist = 228.6; ACE_barrelLength = 177.8; }; - /* Rifles */ + // AKS class arifle_AKS_base_F: Rifle_Base_F { initSpeed = -1.0; ACE_barrelTwist = 160.02; ACE_barrelLength = 206.5; }; + + // AKM class arifle_AKM_base_F: Rifle_Base_F { initSpeed = -1.0014; ACE_barrelTwist = 199.898; ACE_barrelLength = 414.02; }; + + // AK12 class arifle_AK12_base_F: Rifle_Base_F { initSpeed = -1.0014; ACE_barrelTwist = 199.898; ACE_barrelLength = 414.02; }; + + // QBZ-95-1 class arifle_CTAR_base_F: Rifle_Base_F { initSpeed = -1.0; ACE_barrelTwist = 244.0; ACE_barrelLength = 463.0; }; + + // QBZ-95-1 LSW class arifle_CTARS_base_F: Rifle_Base_F { initSpeed = -1.04301; ACE_barrelTwist = 244.0; ACE_barrelLength = 600.0; }; + + // Type 115 class arifle_ARX_base_F: Rifle_Base_F { initSpeed = -1.02052; ACE_barrelTwist = 228.6; ACE_barrelLength = 463.0; }; + + class arifle_katiba_Base_F: Rifle_Base_F {}; + + // KH2002 Sama class arifle_Katiba_F: arifle_katiba_Base_F { magazines[] = { "30Rnd_65x39_caseless_green", @@ -306,6 +337,8 @@ class CfgWeapons { ACE_barrelTwist = 203.2; ACE_barrelLength = 508.0; }; + + // KH2002C Sama class arifle_Katiba_C_F: arifle_katiba_Base_F { magazines[] = { "30Rnd_65x39_caseless_green", @@ -316,6 +349,8 @@ class CfgWeapons { ACE_barrelTwist = 203.2; ACE_barrelLength = 393.7; }; + + // KH2002 Sama KGL class arifle_Katiba_GL_F: arifle_katiba_Base_F { magazines[] = { "30Rnd_65x39_caseless_green", @@ -326,6 +361,8 @@ class CfgWeapons { ACE_barrelTwist = 203.2; ACE_barrelLength = 508.0; }; + + // MX class arifle_MX_F: arifle_MX_Base_F { magazines[] = { "30Rnd_65x39_caseless_mag", @@ -336,6 +373,8 @@ class CfgWeapons { ACE_barrelTwist = 228.6; ACE_barrelLength = 368.3; }; + + // MX 3GL class arifle_MX_GL_F: arifle_MX_Base_F { magazines[] = { "30Rnd_65x39_caseless_mag", @@ -346,12 +385,8 @@ class CfgWeapons { ACE_barrelTwist = 228.6; ACE_barrelLength = 368.3; }; - /* - class arifle_MX_SW_F: arifle_MX_Base_F { - ACE_barrelTwist=228.6; - ACE_barrelLength=406.4; - }; - */ + + // MXC class arifle_MXC_F: arifle_MX_Base_F { magazines[] = { "30Rnd_65x39_caseless_mag", @@ -362,12 +397,8 @@ class CfgWeapons { ACE_barrelTwist = 203.2; ACE_barrelLength = 266.7; }; - /* - class arifle_MXM_F: arifle_MX_Base_F { - ACE_barrelTwist=228.6; - ACE_barrelLength=457.2; - }; - */ + + // RFB SDAR class arifle_SDAR_F: SDAR_base_F { magazines[] = { "20Rnd_556x45_UW_mag", @@ -386,16 +417,24 @@ class CfgWeapons { ACE_barrelTwist = 285.75; ACE_barrelLength = 457.2; }; + + // Scorpion Evo 3 A1 class SMG_02_base_F: Rifle_Short_Base_F { initSpeed = -1.10288; ACE_barrelTwist = 254.0; ACE_barrelLength = 195.58; }; + + // MP5K class SMG_05_base_F: Rifle_Short_Base_F { initSpeed = -1.04058; ACE_barrelTwist = 254.0; ACE_barrelLength = 115.0; }; + + class Tavor_base_F: Rifle_Base_F {}; + + // CTAR-21 class arifle_TRG20_F: Tavor_base_F { magazines[] = { "30Rnd_556x45_Stanag", @@ -413,6 +452,8 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 381.0; }; + + // TAR-21 class arifle_TRG21_F: Tavor_base_F { magazines[] = { "30Rnd_556x45_Stanag", @@ -430,6 +471,8 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 459.74; }; + + // TAR-21 EGLM class arifle_TRG21_GL_F: arifle_TRG21_F { magazines[] = { "30Rnd_556x45_Stanag", @@ -447,12 +490,10 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 459.74; }; - /* - class LMG_Zafir_F: Rifle_Long_Base_F { - ACE_barrelTwist=304.8; - ACE_barrelLength=459.74; - }; - */ + + class mk20_base_F: Rifle_Base_F {}; + + // F2000 class arifle_Mk20_F: mk20_base_F { magazines[] = { "30Rnd_556x45_Stanag", @@ -470,6 +511,8 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 441.96; }; + + // F2000 Tactical class arifle_Mk20C_F: mk20_base_F { magazines[] = { "30Rnd_556x45_Stanag", @@ -487,6 +530,8 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 406.4; }; + + // F2000 EGLM class arifle_Mk20_GL_F: mk20_base_F { magazines[] = { "30Rnd_556x45_Stanag", @@ -504,11 +549,15 @@ class CfgWeapons { ACE_barrelTwist = 177.8; ACE_barrelLength = 406.4; }; + + // Vector SMG class SMG_01_Base: Rifle_Short_Base_F { initSpeed = -1.0175; ACE_barrelTwist = 406.4; ACE_barrelLength = 139.7; }; + + // VS-121 class srifle_DMR_01_F: DMR_01_base_F { magazines[] = { "10Rnd_762x54_Mag", @@ -518,6 +567,8 @@ class CfgWeapons { ACE_barrelTwist = 241.3; ACE_barrelLength = 609.6; }; + + // Mk14 Mod 1 EBR class srifle_EBR_F: EBR_base_F { magazines[] = { "20Rnd_762x51_Mag", @@ -533,13 +584,8 @@ class CfgWeapons { ACE_barrelTwist = 304.8; ACE_barrelLength = 457.2; }; - /* - class LMG_Mk200_F: Rifle_Long_Base_F { - initSpeed = -1.0; - ACE_barrelTwist=177.8; - ACE_barrelLength=317.5; - }; - */ + + // M200 Intervention class srifle_LRR_F: LRR_base_F { magazines[] = { "7Rnd_408_Mag", @@ -549,6 +595,8 @@ class CfgWeapons { ACE_barrelTwist = 330.2; ACE_barrelLength = 736.6; }; + + // GM6 Lynx class srifle_GM6_F: GM6_base_F { magazines[] = { "5Rnd_127x108_Mag", @@ -561,6 +609,8 @@ class CfgWeapons { ACE_barrelTwist = 381.0; ACE_barrelLength = 730; }; + + // Noreen "Bad News" ULR class srifle_DMR_02_F: DMR_02_base_F { magazines[] = { "10Rnd_338_Mag", @@ -574,6 +624,8 @@ class CfgWeapons { ACE_barrelTwist = 254.0; ACE_barrelLength = 508.0; }; + + // SIG 556 class srifle_DMR_03_F: DMR_03_base_F { magazines[] = { "20Rnd_762x51_Mag", @@ -589,16 +641,22 @@ class CfgWeapons { ACE_barrelTwist = 254.0; ACE_barrelLength = 508.0; }; + + // ASP-1 Kir class srifle_DMR_04_F: DMR_04_base_F { initSpeed = -1.0; ACE_barrelTwist = 203.2; ACE_barrelLength = 450.088; }; + + // Cyrus class srifle_DMR_05_blk_F: DMR_05_base_F { initSpeed = -1.0; ACE_barrelTwist = 359.918; ACE_barrelLength = 620.014; }; + + // M14 class srifle_DMR_06_camo_F: DMR_06_base_F { magazines[] = { "20Rnd_762x51_Mag", @@ -614,11 +672,15 @@ class CfgWeapons { ACE_barrelTwist = 304.8; ACE_barrelLength = 558.8; }; + + // HK121 class MMG_01_hex_F: MMG_01_base_F { initSpeed = -0.997073; ACE_barrelTwist = 359.918; ACE_barrelLength = 549.91; }; + + // LWMMG class MMG_02_camo_F: MMG_02_base_F { initSpeed = -1.0; ACE_barrelTwist = 234.95; From c4f9b6c19bcb605bb04a82e03aa1461909271faa Mon Sep 17 00:00:00 2001 From: Dedmen Miller Date: Sat, 28 Oct 2017 21:39:46 +0200 Subject: [PATCH 016/212] Removed/disable unused stuff (#5694) C++17 compat by removing stuff that was deprecated in C++14 --- .../AdvancedBallistics.cpp | 1 + extensions/common/CMakeLists.txt | 20 +- extensions/common/easyloggingc++.hpp | 6718 ----------------- extensions/common/logging.hpp | 6 - extensions/common/shared.cpp | 21 +- extensions/common/shared.hpp | 15 +- extensions/common/simplepipe_win32.cpp | 183 - extensions/common/simplepipe_win32.hpp | 60 - 8 files changed, 17 insertions(+), 7007 deletions(-) delete mode 100644 extensions/common/easyloggingc++.hpp delete mode 100644 extensions/common/logging.hpp delete mode 100644 extensions/common/simplepipe_win32.cpp delete mode 100644 extensions/common/simplepipe_win32.hpp diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index 1caf0783db..4abe35b8fd 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #define DELTA_T 0.02f #define GRAVITY 9.80665f diff --git a/extensions/common/CMakeLists.txt b/extensions/common/CMakeLists.txt index b9291e3dc4..92abaa8f6b 100644 --- a/extensions/common/CMakeLists.txt +++ b/extensions/common/CMakeLists.txt @@ -2,17 +2,17 @@ file(GLOB_RECURSE ACE_COMMON_SOURCES *.h *.hpp *.c *.cpp) file(GLOB ACE_BASE_COMMON_SOURCES *.h *.hpp *.c *.cpp) -file(GLOB ACE_P3D_SOURCES p3d/*.h p3d/*.hpp p3d/*.c p3d/*.cpp) -file(GLOB ACE_PBO_SOURCES pbo/*.h pbo/*.hpp pbo/*.c pbo/*.cpp) -file(GLOB ACE_SIMULATION_SOURCES simulation/*.h simulation/*.hpp simulation/*.c simulation/*.cpp) -file(GLOB ACE_DIRECTX_SOURCES directx/*.h directx/*.hpp directx/*.c directx/*.cpp) -file(GLOB ACE_GLM_SOURCES glm/*.h glm/*.hpp glm/*.c glm/*.cpp) +#file(GLOB ACE_P3D_SOURCES p3d/*.h p3d/*.hpp p3d/*.c p3d/*.cpp) +#file(GLOB ACE_PBO_SOURCES pbo/*.h pbo/*.hpp pbo/*.c pbo/*.cpp) +#file(GLOB ACE_SIMULATION_SOURCES simulation/*.h simulation/*.hpp simulation/*.c simulation/*.cpp) +#file(GLOB ACE_DIRECTX_SOURCES directx/*.h directx/*.hpp directx/*.c directx/*.cpp) +#file(GLOB ACE_GLM_SOURCES glm/*.h glm/*.hpp glm/*.c glm/*.cpp) SOURCE_GROUP("common" FILES ${ACE_BASE_COMMON_SOURCES}) -SOURCE_GROUP("p3d" FILES ${ACE_P3D_SOURCES}) -SOURCE_GROUP("pbo" FILES ${ACE_PBO_SOURCES}) -SOURCE_GROUP("simulation" FILES ${ACE_SIMULATION_SOURCES}) -SOURCE_GROUP("directx" FILES ${ACE_DIRECTX_SOURCES}) -SOURCE_GROUP("glm" FILES ${ACE_GLM_SOURCES}) +#SOURCE_GROUP("p3d" FILES ${ACE_P3D_SOURCES}) +#SOURCE_GROUP("pbo" FILES ${ACE_PBO_SOURCES}) +#SOURCE_GROUP("simulation" FILES ${ACE_SIMULATION_SOURCES}) +#SOURCE_GROUP("directx" FILES ${ACE_DIRECTX_SOURCES}) +#SOURCE_GROUP("glm" FILES ${ACE_GLM_SOURCES}) add_library(ace_common STATIC ${ACE_GLM_SOURCES} ${ACE_BASE_COMMON_SOURCES} ${ACE_P3D_SOURCES} ${ACE_PBO_SOURCES} ${ACE_SIMULATION_SOURCES} ${ACE_DIRECTX_SOURCES}) diff --git a/extensions/common/easyloggingc++.hpp b/extensions/common/easyloggingc++.hpp deleted file mode 100644 index 962c61be84..0000000000 --- a/extensions/common/easyloggingc++.hpp +++ /dev/null @@ -1,6718 +0,0 @@ -// -// Easylogging++ v9.80 -// Single-header only, cross-platform logging library for C++ applications -// -// Copyright (c) 2015 muflihun.com -// -// This library is released under the MIT Licence. -// http://easylogging.muflihun.com/licence.php -// -// easylogging@muflihun.com -// -// https://github.com/easylogging/easyloggingpp -// http://easylogging.muflihun.com -// http://muflihun.com -// -#ifndef EASYLOGGINGPP_H -#define EASYLOGGINGPP_H -// Compilers and C++0x/C++11 Evaluation -#if defined(__GNUC__) -# define ELPP_COMPILER_GCC 1 -# define ELPP_GCC_VERSION (__GNUC__ * 10000 \ - + __GNUC_MINOR__ * 100 \ - + __GNUC_PATCHLEVEL__) -# if defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ELPP_CXX0X 1 -# elif(ELPP_GCC_VERSION >= 40801) -# define ELPP_CXX11 1 -# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) -#endif // defined(__GNUC__) -// Visual C++ -#if defined(_MSC_VER) -# define ELPP_COMPILER_MSVC 1 -# define ELPP_CRT_DBG_WARNINGS 1 -# if (_MSC_VER == 1600) -# define ELPP_CXX0X 1 -# elif(_MSC_VER >= 1700) -# define ELPP_CXX11 1 -# endif // (_MSC_VER == 1600) -#endif // defined(_MSC_VER) -// Clang++ -#if defined(__clang__) && (__clang__ == 1) -# define ELPP_COMPILER_CLANG 1 -# define ELPP_CLANG_VERSION (__clang_major__ * 10000 \ - + __clang_minor__ * 100 \ - + __clang_patchlevel__) -# if (ELPP_CLANG_VERSION >= 30300) -# define ELPP_CXX11 1 -# endif // (ELPP_CLANG_VERSION >= 30300) -#endif // defined(__clang__) && (__clang__ == 1) -// MinGW -#if defined(__MINGW32__) || defined(__MINGW64__) -# define ELPP_MINGW 1 -#endif // defined(__MINGW32__) || defined(__MINGW64__) -// Cygwin -#if defined(__CYGWIN__) && (__CYGWIN__ == 1) -# define ELPP_CYGWIN 1 -#endif // defined(__CYGWIN__) && (__CYGWIN__ == 1) -// Intel C++ -#if defined(__INTEL_COMPILER) -# define ELPP_COMPILER_INTEL 1 -#endif -// Operating System Evaluation -// Windows -#if defined(_WIN32) || defined(_WIN64) -# define ELPP_OS_WINDOWS 1 -#endif // defined(_WIN32) || defined(_WIN64) -// Linux -#if (defined(__linux) || defined(__linux__)) -# define ELPP_OS_LINUX 1 -#endif // (defined(__linux) || defined(__linux__)) -// Mac -#if defined(__APPLE__) -# define ELPP_OS_MAC 1 -#endif // defined(__APPLE__) -// FreeBSD -#if defined(__FreeBSD__) -# define ELPP_OS_FREEBSD 1 -#endif -// Solaris -#if defined(__sun) -# define ELPP_OS_SOLARIS 1 -#endif -// Unix -#if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS)) -# define ELPP_OS_UNIX 1 -#endif // ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS)) -// Android -#if defined(__ANDROID__) -# define ELPP_OS_ANDROID 1 -#endif // defined(__ANDROID__) -// Evaluating Cygwin as *nix OS -#if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN -# undef ELPP_OS_UNIX -# undef ELPP_OS_LINUX -# define ELPP_OS_UNIX 1 -# define ELPP_OS_LINUX 1 -#endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN -#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO) -# define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR) -# define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_ENDL) -# define ELPP_INTERNAL_DEBUGGING_ENDL std::endl -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_MSG) -# define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -// Internal Assertions and errors -#if !defined(ELPP_DISABLE_ASSERT) -# if (defined(ELPP_DEBUG_ASSERT_FAILURE)) -# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ - std::stringstream internalInfoStream; internalInfoStream << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ - << "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \ - << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \ - "ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); } -# else -# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ - std::stringstream internalInfoStream; internalInfoStream << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR\ - << "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \ - << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \ - << ELPP_INTERNAL_DEBUGGING_ENDL; } -# endif // (defined(ELPP_DEBUG_ASSERT_FAILURE)) -#else -# define ELPP_ASSERT(x, y) -#endif //(!defined(ELPP_DISABLE_ASSERT) -#if ELPP_COMPILER_MSVC -# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ - { char buff[256]; strerror_s(buff, 256, errno); \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0 -#else -# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0 -#endif // ELPP_COMPILER_MSVC -#if defined(ELPP_DEBUG_ERRORS) -# if !defined(ELPP_INTERNAL_ERROR) -# define ELPP_INTERNAL_ERROR(msg, pe) { \ - std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ - << "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \ - << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \ - if (pe) { ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0 -# endif -#else -# undef ELPP_INTERNAL_INFO -# define ELPP_INTERNAL_ERROR(msg, pe) -#endif // defined(ELPP_DEBUG_ERRORS) -#if (defined(ELPP_DEBUG_INFO)) -# if !(defined(ELPP_INTERNAL_INFO_LEVEL)) -# define ELPP_INTERNAL_INFO_LEVEL 9 -# endif // !(defined(ELPP_INTERNAL_INFO_LEVEL)) -# if !defined(ELPP_INTERNAL_INFO) -# define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= ELPP_INTERNAL_INFO_LEVEL) { \ - std::stringstream internalInfoStream; internalInfoStream << " " << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \ - << ELPP_INTERNAL_DEBUGGING_ENDL; }} -# endif -#else -# undef ELPP_INTERNAL_INFO -# define ELPP_INTERNAL_INFO(lvl, msg) -#endif // (defined(ELPP_DEBUG_INFO)) -#if defined(ELPP_STACKTRACE_ON_CRASH) -# if (ELPP_COMPILER_GCC && !ELPP_MINGW) -# define ELPP_STACKTRACE 1 -# else -# if ELPP_COMPILER_MSVC -# pragma message("Stack trace not available for this compiler") -# else -# warning "Stack trace not available for this compiler"; -# endif // ELPP_COMPILER_MSVC -# endif // ELPP_COMPILER_GCC -#endif // (defined(ELPP_STACKTRACE_ON_CRASH)) -// Miscellaneous macros -#define ELPP_UNUSED(x) (void)x -#if ELPP_OS_UNIX -// Log file permissions for unix-based systems -# define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH -#endif // ELPP_OS_UNIX -#if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC -# if defined(ELPP_EXPORT_SYMBOLS) -# define ELPP_EXPORT __declspec(dllexport) -# else -# define ELPP_EXPORT __declspec(dllimport) -# endif // defined(ELPP_EXPORT_SYMBOLS) -#else -# define ELPP_EXPORT -#endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC -// Some special functions that are VC++ specific -#undef STRTOK -#undef STRERROR -#undef STRCAT -#undef STRCPY -#if ELPP_CRT_DBG_WARNINGS -# define STRTOK(a, b, c) strtok_s(a, b, c) -# define STRERROR(a, b, c) strerror_s(a, b, c) -# define STRCAT(a, b, len) strcat_s(a, len, b) -# define STRCPY(a, b, len) strcpy_s(a, len, b) -#else -# define STRTOK(a, b, c) strtok(a, b) -# define STRERROR(a, b, c) strerror(c) -# define STRCAT(a, b, len) strcat(a, b) -# define STRCPY(a, b, len) strcpy(a, b) -#endif -// Compiler specific support evaluations -#if (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD) -# define ELPP_USE_STD_THREADING 1 -#endif // (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD) -#undef ELPP_FINAL -#if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) -# define ELPP_FINAL -#else -# define ELPP_FINAL final -#endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) -#if defined(ELPP_EXPERIMENTAL_ASYNC) -# define ELPP_ASYNC_LOGGING 1 -#else -# define ELPP_ASYNC_LOGGING 0 -#endif // defined(ELPP_EXPERIMENTAL_ASYNC) -#if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING -# define ELPP_THREADING_ENABLED 1 -#endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING -// Function macro ELPP_FUNC -#undef ELPP_FUNC -#if ELPP_COMPILER_MSVC // Visual C++ -# define ELPP_FUNC __FUNCSIG__ -#elif ELPP_COMPILER_GCC // GCC -# define ELPP_FUNC __PRETTY_FUNCTION__ -#elif ELPP_COMPILER_INTEL // Intel C++ -# define ELPP_FUNC __PRETTY_FUNCTION__ -#elif ELPP_COMPILER_CLANG // Clang++ -# define ELPP_FUNC __PRETTY_FUNCTION__ -#else -# if defined(__func__) -# define ELPP_FUNC __func__ -# else -# define ELPP_FUNC "" -# endif // defined(__func__) -#endif // defined(_MSC_VER) -#undef ELPP_VARIADIC_TEMPLATES_SUPPORTED -// Keep following line commented until features are fixed -#if ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800) -# define ELPP_VARIADIC_TEMPLATES_SUPPORTED 1 -#endif // ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800) -// Logging Enable/Disable macros -#if (!defined(ELPP_DISABLE_LOGS)) -# define ELPP_LOGGING_ENABLED 1 -#endif // (!defined(ELPP_DISABLE_LOGS)) -#if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG)))) -# define ELPP_DEBUG_LOG 1 -#else -# define ELPP_DEBUG_LOG 0 -#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG)))) -#if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_INFO_LOG 1 -#else -# define ELPP_INFO_LOG 0 -#endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_WARNING_LOG 1 -#else -# define ELPP_WARNING_LOG 0 -#endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_ERROR_LOG 1 -#else -# define ELPP_ERROR_LOG 0 -#endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_FATAL_LOG 1 -#else -# define ELPP_FATAL_LOG 0 -#endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_TRACE_LOG 1 -#else -# define ELPP_TRACE_LOG 0 -#endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) -# define ELPP_VERBOSE_LOG 1 -#else -# define ELPP_VERBOSE_LOG 0 -#endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) -#if (!(ELPP_CXX0X || ELPP_CXX11)) -# error "Easylogging++ 9.0+ is only compatible with C++0x (or higher) compliant compiler" -#endif // (!(ELPP_CXX0X || ELPP_CXX11)) -// Headers -#if defined(ELPP_SYSLOG) -# include -#endif // defined(ELPP_SYSLOG) -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(ELPP_UNICODE) -# include -# if ELPP_OS_WINDOWS -# include -# endif // ELPP_OS_WINDOWS -#endif // defined(ELPP_UNICODE) -#if ELPP_STACKTRACE -# include -# include -#endif // ELPP_STACKTRACE -#if ELPP_OS_ANDROID -# include -#endif // ELPP_OS_ANDROID -#if ELPP_OS_UNIX -# include -# include -#elif ELPP_OS_WINDOWS -# include -# include -# if defined(WIN32_LEAN_AND_MEAN) -# if defined(ELPP_WINSOCK2) -# include -# else -# include -# endif // defined(ELPP_WINSOCK2) -# endif // defined(WIN32_LEAN_AND_MEAN) -#endif // ELPP_OS_UNIX -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if ELPP_THREADING_ENABLED -# if ELPP_USE_STD_THREADING -# include -# include -# else -# if ELPP_OS_UNIX -# include -# endif // ELPP_OS_UNIX -# endif // ELPP_USE_STD_THREADING -#endif // ELPP_THREADING_ENABLED -#if ELPP_ASYNC_LOGGING -# include -# include -# include -#endif // ELPP_ASYNC_LOGGING -#if defined(ELPP_STL_LOGGING) -// For logging STL based templates -# include -# include -# include -# include -# include -# include -# if defined(ELPP_LOG_STD_ARRAY) -# include -# endif // defined(ELPP_LOG_STD_ARRAY) -# if defined(ELPP_LOG_UNORDERED_MAP) -# include -# endif // defined(ELPP_LOG_UNORDERED_MAP) -# if defined(ELPP_LOG_UNORDERED_SET) -# include -# endif // defined(ELPP_UNORDERED_SET) -#endif // defined(ELPP_STL_LOGGING) -#if defined(ELPP_QT_LOGGING) -// For logging Qt based classes & templates -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif // defined(ELPP_QT_LOGGING) -#if defined(ELPP_BOOST_LOGGING) -// For logging boost based classes & templates -# include -# include -# include -# include -# include -# include -# include -# include -#endif // defined(ELPP_BOOST_LOGGING) -#if defined(ELPP_WXWIDGETS_LOGGING) -// For logging wxWidgets based classes & templates -# include -#endif // defined(ELPP_WXWIDGETS_LOGGING) -// Forward declarations -namespace el { - class Logger; - class LogMessage; - class PerformanceTrackingData; - class Loggers; - class Helpers; - template class Callback; - class LogDispatchCallback; - class PerformanceTrackingCallback; - class LogDispatchData; - namespace base { - class Storage; - class RegisteredLoggers; - class PerformanceTracker; - class MessageBuilder; - class Writer; - class PErrorWriter; - class LogDispatcher; - class DefaultLogBuilder; - class DefaultLogDispatchCallback; -#if ELPP_ASYNC_LOGGING - class AsyncLogDispatchCallback; - class AsyncDispatchWorker; -#endif // ELPP_ASYNC_LOGGING - class DefaultPerformanceTrackingCallback; - } // namespace base -} // namespace el - /// @brief Easylogging++ entry namespace -namespace el { - /// @brief Namespace containing base/internal functionality used by Easylogging++ - namespace base { - /// @brief Data types used by Easylogging++ - namespace type { -#undef ELPP_LITERAL -#undef ELPP_STRLEN -#undef ELPP_COUT -#if defined(ELPP_UNICODE) -# define ELPP_LITERAL(txt) L##txt -# define ELPP_STRLEN wcslen -# if defined ELPP_CUSTOM_COUT -# define ELPP_COUT ELPP_CUSTOM_COUT -# else -# define ELPP_COUT std::wcout -# endif // defined ELPP_CUSTOM_COUT - typedef wchar_t char_t; - typedef std::wstring string_t; - typedef std::wstringstream stringstream_t; - typedef std::wfstream fstream_t; - typedef std::wostream ostream_t; -#else -# define ELPP_LITERAL(txt) txt -# define ELPP_STRLEN strlen -# if defined ELPP_CUSTOM_COUT -# define ELPP_COUT ELPP_CUSTOM_COUT -# else -# define ELPP_COUT std::cout -# endif // defined ELPP_CUSTOM_COUT - typedef char char_t; - typedef std::string string_t; - typedef std::stringstream stringstream_t; - typedef std::fstream fstream_t; - typedef std::ostream ostream_t; -#endif // defined(ELPP_UNICODE) -#if defined(ELPP_CUSTOM_COUT_LINE) -# define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine) -#else -# define ELPP_COUT_LINE(logLine) logLine << std::flush -#endif // defined(ELPP_CUSTOM_COUT_LINE) - typedef unsigned short EnumType; - typedef std::shared_ptr StoragePointer; - typedef int VerboseLevel; - typedef std::shared_ptr LogDispatchCallbackPtr; - typedef std::shared_ptr PerformanceTrackingCallbackPtr; - } // namespace type - /// @brief Internal helper class that prevent copy constructor for class - /// - /// @detail When using this class simply inherit it privately - class NoCopy { - protected: - NoCopy(void) {} - private: - NoCopy(const NoCopy&); - NoCopy& operator=(const NoCopy&); - }; - /// @brief Internal helper class that makes all default constructors private. - /// - /// @detail This prevents initializing class making it static unless an explicit constructor is declared. - /// When using this class simply inherit it privately - class StaticClass { - private: - StaticClass(void); - StaticClass(const StaticClass&); - StaticClass& operator=(const StaticClass&); - }; - } // namespace base - /// @brief Represents enumeration for severity level used to determine level of logging - /// - /// @detail With Easylogging++, developers may disable or enable any level regardless of - /// what the severity is. Or they can choose to log using hierarchical logging flag - enum class Level : base::type::EnumType { - /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels - Global = 1, - /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs. - Trace = 2, - /// @brief Informational events most useful for developers to debug application - Debug = 4, - /// @brief Severe error information that will presumably abort application - Fatal = 8, - /// @brief Information representing errors in application but application will keep running - Error = 16, - /// @brief Useful when application has potentially harmful situtaions - Warning = 32, - /// @brief Information that can be highly useful and vary with verbose logging level. - Verbose = 64, - /// @brief Mainly useful to represent current progress of application - Info = 128, - /// @brief Represents unknown level - Unknown = 1010 - }; - /// @brief Static class that contains helper functions for el::Level - class LevelHelper : base::StaticClass { - public: - /// @brief Represents minimum valid level. Useful when iterating through enum. - static const base::type::EnumType kMinValid = static_cast(Level::Trace); - /// @brief Represents maximum valid level. This is used internally and you should not need it. - static const base::type::EnumType kMaxValid = static_cast(Level::Info); - /// @brief Casts level to int, useful for iterating through enum. - static base::type::EnumType castToInt(Level level) { - return static_cast(level); - } - /// @brief Casts int(ushort) to level, useful for iterating through enum. - static Level castFromInt(base::type::EnumType l) { - return static_cast(l); - } - /// @brief Converts level to associated const char* - /// @return Upper case string based level. - static const char* convertToString(Level level) { - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if (level == Level::Global) return "GLOBAL"; - if (level == Level::Debug) return "DEBUG"; - if (level == Level::Info) return "INFO"; - if (level == Level::Warning) return "WARNING"; - if (level == Level::Error) return "ERROR"; - if (level == Level::Fatal) return "FATAL"; - if (level == Level::Verbose) return "VERBOSE"; - if (level == Level::Trace) return "TRACE"; - return "UNKNOWN"; - } - /// @brief Converts from levelStr to Level - /// @param levelStr Upper case string based level. - /// Lower case is also valid but providing upper case is recommended. - static Level convertFromString(const char* levelStr) { - if ((strcmp(levelStr, "GLOBAL") == 0) || (strcmp(levelStr, "global") == 0)) - return Level::Global; - if ((strcmp(levelStr, "DEBUG") == 0) || (strcmp(levelStr, "debug") == 0)) - return Level::Debug; - if ((strcmp(levelStr, "INFO") == 0) || (strcmp(levelStr, "info") == 0)) - return Level::Info; - if ((strcmp(levelStr, "WARNING") == 0) || (strcmp(levelStr, "warning") == 0)) - return Level::Warning; - if ((strcmp(levelStr, "ERROR") == 0) || (strcmp(levelStr, "error") == 0)) - return Level::Error; - if ((strcmp(levelStr, "FATAL") == 0) || (strcmp(levelStr, "fatal") == 0)) - return Level::Fatal; - if ((strcmp(levelStr, "VERBOSE") == 0) || (strcmp(levelStr, "verbose") == 0)) - return Level::Verbose; - if ((strcmp(levelStr, "TRACE") == 0) || (strcmp(levelStr, "trace") == 0)) - return Level::Trace; - return Level::Unknown; - } - /// @brief Applies specified function to each level starting from startIndex - /// @param startIndex initial value to start the iteration from. This is passed as pointer and - /// is left-shifted so this can be used inside function (fn) to represent current level. - /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels. - static inline void forEachLevel(base::type::EnumType* startIndex, const std::function& fn) { - base::type::EnumType lIndexMax = LevelHelper::kMaxValid; - do { - if (fn()) { - break; - } - *startIndex = static_cast(*startIndex << 1); - } while (*startIndex <= lIndexMax); - } - }; - /// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect - /// of logging - enum class ConfigurationType : base::type::EnumType { - /// @brief Determines whether or not corresponding level and logger of logging is enabled - /// You may disable all logs by using el::Level::Global - Enabled = 1, - /// @brief Whether or not to write corresponding log to log file - ToFile = 2, - /// @brief Whether or not to write corresponding level and logger log to standard output. - /// By standard output meaning termnal, command prompt etc - ToStandardOutput = 4, - /// @brief Determines format of logging corresponding level and logger. - Format = 8, - /// @brief Determines log file (full path) to write logs to for correponding level and logger - Filename = 16, - /// @brief Specifies milliseconds width. Width can be within range (1-6) - MillisecondsWidth = 32, - /// @brief Determines whether or not performance tracking is enabled. - /// - /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger - PerformanceTracking = 64, - /// @brief Specifies log file max size. - /// - /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will - /// be truncated and re-initiated. - MaxLogFileSize = 128, - /// @brief Specifies number of log entries to hold until we flush pending log data - LogFlushThreshold = 256, - /// @brief Represents unknown configuration - Unknown = 1010 - }; - /// @brief Static class that contains helper functions for el::ConfigurationType - class ConfigurationTypeHelper : base::StaticClass { - public: - /// @brief Represents minimum valid configuration type. Useful when iterating through enum. - static const base::type::EnumType kMinValid = static_cast(ConfigurationType::Enabled); - /// @brief Represents maximum valid configuration type. This is used internally and you should not need it. - static const base::type::EnumType kMaxValid = static_cast(ConfigurationType::MaxLogFileSize); - /// @brief Casts configuration type to int, useful for iterating through enum. - static base::type::EnumType castToInt(ConfigurationType configurationType) { - return static_cast(configurationType); - } - /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum. - static ConfigurationType castFromInt(base::type::EnumType c) { - return static_cast(c); - } - /// @brief Converts configuration type to associated const char* - /// @returns Upper case string based configuration type. - static const char* convertToString(ConfigurationType configurationType) { - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if (configurationType == ConfigurationType::Enabled) return "ENABLED"; - if (configurationType == ConfigurationType::Filename) return "FILENAME"; - if (configurationType == ConfigurationType::Format) return "FORMAT"; - if (configurationType == ConfigurationType::ToFile) return "TO_FILE"; - if (configurationType == ConfigurationType::ToStandardOutput) return "TO_STANDARD_OUTPUT"; - if (configurationType == ConfigurationType::MillisecondsWidth) return "MILLISECONDS_WIDTH"; - if (configurationType == ConfigurationType::PerformanceTracking) return "PERFORMANCE_TRACKING"; - if (configurationType == ConfigurationType::MaxLogFileSize) return "MAX_LOG_FILE_SIZE"; - if (configurationType == ConfigurationType::LogFlushThreshold) return "LOG_FLUSH_THRESHOLD"; - return "UNKNOWN"; - } - /// @brief Converts from configStr to ConfigurationType - /// @param configStr Upper case string based configuration type. - /// Lower case is also valid but providing upper case is recommended. - static ConfigurationType convertFromString(const char* configStr) { - if ((strcmp(configStr, "ENABLED") == 0) || (strcmp(configStr, "enabled") == 0)) - return ConfigurationType::Enabled; - if ((strcmp(configStr, "TO_FILE") == 0) || (strcmp(configStr, "to_file") == 0)) - return ConfigurationType::ToFile; - if ((strcmp(configStr, "TO_STANDARD_OUTPUT") == 0) || (strcmp(configStr, "to_standard_output") == 0)) - return ConfigurationType::ToStandardOutput; - if ((strcmp(configStr, "FORMAT") == 0) || (strcmp(configStr, "format") == 0)) - return ConfigurationType::Format; - if ((strcmp(configStr, "FILENAME") == 0) || (strcmp(configStr, "filename") == 0)) - return ConfigurationType::Filename; - if ((strcmp(configStr, "MILLISECONDS_WIDTH") == 0) || (strcmp(configStr, "milliseconds_width") == 0)) - return ConfigurationType::MillisecondsWidth; - if ((strcmp(configStr, "PERFORMANCE_TRACKING") == 0) || (strcmp(configStr, "performance_tracking") == 0)) - return ConfigurationType::PerformanceTracking; - if ((strcmp(configStr, "MAX_LOG_FILE_SIZE") == 0) || (strcmp(configStr, "max_log_file_size") == 0)) - return ConfigurationType::MaxLogFileSize; - if ((strcmp(configStr, "LOG_FLUSH_THRESHOLD") == 0) || (strcmp(configStr, "log_flush_threshold") == 0)) - return ConfigurationType::LogFlushThreshold; - return ConfigurationType::Unknown; - } - /// @brief Applies specified function to each configuration type starting from startIndex - /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted - /// so this can be used inside function (fn) to represent current configuration type. - /// @param fn function to apply with each configuration type. - /// This bool represent whether or not to stop iterating through configurations. - static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function& fn) { - base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid; - do { - if (fn()) { - break; - } - *startIndex = static_cast(*startIndex << 1); - } while (*startIndex <= cIndexMax); - } - }; - /// @brief Flags used while writing logs. This flags are set by user - enum class LoggingFlag : base::type::EnumType { - /// @brief Makes sure we have new line for each container log entry - NewLineForContainer = 1, - /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose - /// logging is allowed via that module. - AllowVerboseIfModuleNotSpecified = 2, - /// @brief When handling crashes by default, detailed crash reason will be logged as well - LogDetailedCrashReason = 4, - /// @brief Allows to disable application abortion when logged using FATAL level - DisableApplicationAbortOnFatalLog = 8, - /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default - ImmediateFlush = 16, - /// @brief Enables strict file rolling - StrictLogFileSizeCheck = 32, - /// @brief Make terminal output colorful for supported terminals - ColoredTerminalOutput = 64, - /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network") - MultiLoggerSupport = 128, - /// @brief Disables comparing performance tracker's checkpoints - DisablePerformanceTrackingCheckpointComparison = 256, - /// @brief Disable VModules - DisableVModules = 512, - /// @brief Disable VModules extensions - DisableVModulesExtensions = 1024, - /// @brief Enables hierarchical logging - HierarchicalLogging = 2048, - /// @brief Creates logger automatically when not available - CreateLoggerAutomatically = 4096, - /// @brief Adds spaces b/w logs that separated by left-shift operator - AutoSpacing = 8192, - /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) - FixedTimeFormat = 16384 - }; - namespace base { - /// @brief Namespace containing constants used internally. - namespace consts { - // Level log values - These are values that are replaced in place of %level format specifier - static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO "); - static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); - static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARN "); - static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR"); - static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL"); - static const base::type::char_t* kVerboseLevelLogValue = ELPP_LITERAL("VER"); - static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE"); - static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I"); - static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D"); - static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W"); - static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E"); - static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F"); - static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V"); - static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T"); - // Format specifiers - These are used to define log format - static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app"); - static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); - static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); - static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); - static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); - static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); - static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file"); - static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); - static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line"); - static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); - static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); - static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); - static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); - static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg"); - static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); - static const char* kDateTimeFormatSpecifierForFilename = "%datetime"; - // Date/time - static const char* kDays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; - static const char* kDaysAbbrev[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - static const char* kMonths[12] = { "January", "February", "March", "Apri", "May", "June", "July", "August", - "September", "October", "November", "December" }; - static const char* kMonthsAbbrev[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; - static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; - static const int kYearBase = 1900; - static const char* kAm = "AM"; - static const char* kPm = "PM"; - // Miscellaneous constants - static const char* kDefaultLoggerId = "default"; - static const char* kPerformanceLoggerId = "performance"; - static const char* kSysLogLoggerId = "syslog"; - static const char* kNullPointer = "nullptr"; - static const char kFormatSpecifierChar = '%'; -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED - static const char kFormatSpecifierCharValue = 'v'; -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED - static const unsigned int kMaxLogPerContainer = 100; - static const unsigned int kMaxLogPerCounter = 100000; - static const unsigned int kDefaultMillisecondsWidth = 3; - static const base::type::VerboseLevel kMaxVerboseLevel = 9; - static const char* kUnknownUser = "user"; - static const char* kUnknownHost = "unknown-host"; -#if defined(ELPP_DEFAULT_LOG_FILE) - static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; -#else -# if ELPP_OS_UNIX -# if ELPP_OS_ANDROID - static const char* kDefaultLogFile = "logs/ace.log"; -# else - static const char* kDefaultLogFile = "logs/ace.log"; -# endif // ELPP_OS_ANDROID -# elif ELPP_OS_WINDOWS - static const char* kDefaultLogFile = "logs\\ace.log"; -# endif // ELPP_OS_UNIX -#endif // defined(ELPP_DEFAULT_LOG_FILE) -#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) - static const char* kDefaultLogFileParam = "--default-log-file"; -#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) - static const char* kLoggingFlagsParam = "--logging-flags"; -#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) -#if ELPP_OS_WINDOWS - static const char* kFilePathSeperator = "\\"; -#else - static const char* kFilePathSeperator = "/"; -#endif // ELPP_OS_WINDOWS - static const char* kValidLoggerIdSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; - static const char* kConfigurationComment = "##"; - static const char* kConfigurationLevel = "*"; - static const char* kConfigurationLoggerId = "--"; - static const std::size_t kSourceFilenameMaxLength = 100; - static const std::size_t kSourceLineMaxLength = 10; - static const Level kPerformanceTrackerDefaultLevel = Level::Info; - const struct { - double value; - const base::type::char_t* unit; - } kTimeFormats[] = { - { 1000.0f, ELPP_LITERAL("mis") }, - { 1000.0f, ELPP_LITERAL("ms") }, - { 60.0f, ELPP_LITERAL("seconds") }, - { 60.0f, ELPP_LITERAL("minutes") }, - { 24.0f, ELPP_LITERAL("hours") }, - { 7.0f, ELPP_LITERAL("days") } - }; - static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]); - const struct { - int numb; - const char* name; - const char* brief; - const char* detail; - } kCrashSignals[] = { - // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..) - { SIGABRT, "SIGABRT", "Abnormal termination", - "Program was abnormally terminated." }, - { SIGFPE, "SIGFPE", "Erroneous arithmetic operation", - "Arithemetic operation issue such as division by zero or operation resulting in overflow." }, - { SIGILL, "SIGILL", "Illegal instruction", - "Generally due to a corruption in the code or to an attempt to execute data." }, - { SIGSEGV, "SIGSEGV", "Invalid access to memory", - "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory." }, - { SIGINT, "SIGINT", "Interactive attention signal", - "Interruption generated (generally) by user or operating system." }, - }; - static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); - } // namespace consts - } // namespace base - typedef std::function PreRollOutCallback; - namespace base { - static inline void defaultPreRollOutCallback(const char*, std::size_t) {} - /// @brief Enum to represent timestamp unit - enum class TimestampUnit : base::type::EnumType { - Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5 - }; - /// @brief Format flags used to determine specifiers that are active for performance improvements. - enum class FormatFlags : base::type::EnumType { - DateTime = 1 << 1, LoggerId = 1 << 2, File = 1 << 3, Line = 1 << 4, Location = 1 << 5, Function = 1 << 6, - User = 1 << 7, Host = 1 << 8, LogMessage = 1 << 9, VerboseLevel = 1 << 10, AppName = 1 << 11, ThreadId = 1 << 12, - Level = 1 << 13, FileBase = 1 << 14, LevelShort = 1 << 15 - }; - /// @brief A milliseconds width class containing actual width and offset for date/time - class MillisecondsWidth { - public: - MillisecondsWidth(void) { init(base::consts::kDefaultMillisecondsWidth); } - explicit MillisecondsWidth(int width) { init(width); } - bool operator==(const MillisecondsWidth& msWidth) { return m_width == msWidth.m_width && m_offset == msWidth.m_offset; } - int m_width; unsigned int m_offset; - private: - void init(int width) { - if (width < 1 || width > 6) { - width = base::consts::kDefaultMillisecondsWidth; - } - m_width = width; - switch (m_width) { - case 3: m_offset = 1000; break; - case 4: m_offset = 100; break; - case 5: m_offset = 10; break; - case 6: m_offset = 1; break; - default: m_offset = 1000; break; - } - } - }; - /// @brief Namespace containing utility functions/static classes used internally - namespace utils { - /// @brief Deletes memory safely and points to null - template - static inline - typename std::enable_if::value, void>::type - safeDelete(T*& pointer) { - if (pointer == nullptr) - return; - delete pointer; - pointer = nullptr; - } - /// @brief Gets value of const char* but if it is nullptr, a string nullptr is returned - static inline const char* charPtrVal(const char* pointer) { - return pointer == nullptr ? base::consts::kNullPointer : pointer; - } - /// @brief Aborts application due with user-defined status - static inline void abort(int status, const std::string& reason = std::string()) { - // Both status and reason params are there for debugging with tools like gdb etc - ELPP_UNUSED(status); - ELPP_UNUSED(reason); -#if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) - // Ignore msvc critical error dialog - break instead (on debug mode) - _asm int 3 -#else - ::abort(); -#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) - } - /// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation - /// Use these function as
flag = bitwise::Or(MyEnum::val1, flag);
- namespace bitwise { - template - static inline base::type::EnumType And(Enum e, base::type::EnumType flag) { - return static_cast(flag) & static_cast(e); - } - template - static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) { - return static_cast(flag) & ~(static_cast(e)); - } - template - static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) { - return static_cast(flag) | static_cast(e); - } - } // namespace bitwise - template - static inline void addFlag(Enum e, base::type::EnumType* flag) { - *flag = base::utils::bitwise::Or(e, *flag); - } - template - static inline void removeFlag(Enum e, base::type::EnumType* flag) { - *flag = base::utils::bitwise::Not(e, *flag); - } - template - static inline bool hasFlag(Enum e, base::type::EnumType flag) { - return base::utils::bitwise::And(e, flag) > 0x0; - } - } // namespace utils - namespace threading { -#if ELPP_THREADING_ENABLED -# if !ELPP_USE_STD_THREADING - namespace internal { - /// @brief A mutex wrapper for compiler that dont yet support std::mutex - class Mutex : base::NoCopy { - public: - Mutex(void) { -# if ELPP_OS_UNIX - pthread_mutex_init(&m_underlyingMutex, nullptr); -# elif ELPP_OS_WINDOWS - InitializeCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - virtual ~Mutex(void) { -# if ELPP_OS_UNIX - pthread_mutex_destroy(&m_underlyingMutex); -# elif ELPP_OS_WINDOWS - DeleteCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - inline void lock(void) { -# if ELPP_OS_UNIX - pthread_mutex_lock(&m_underlyingMutex); -# elif ELPP_OS_WINDOWS - EnterCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - inline bool try_lock(void) { -# if ELPP_OS_UNIX - return (pthread_mutex_trylock(&m_underlyingMutex) == 0); -# elif ELPP_OS_WINDOWS - return TryEnterCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - inline void unlock(void) { -# if ELPP_OS_UNIX - pthread_mutex_unlock(&m_underlyingMutex); -# elif ELPP_OS_WINDOWS - LeaveCriticalSection(&m_underlyingMutex); -# endif // ELPP_OS_UNIX - } - - private: -# if ELPP_OS_UNIX - pthread_mutex_t m_underlyingMutex; -# elif ELPP_OS_WINDOWS - CRITICAL_SECTION m_underlyingMutex; -# endif // ELPP_OS_UNIX - }; - /// @brief Scoped lock for compiler that dont yet support std::lock_guard - template - class ScopedLock : base::NoCopy { - public: - explicit ScopedLock(M& mutex) { - m_mutex = &mutex; - m_mutex->lock(); - } - - virtual ~ScopedLock(void) { - m_mutex->unlock(); - } - private: - M* m_mutex; - ScopedLock(void); - }; - } // namespace internal - /// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned. - static inline std::string getCurrentThreadId(void) { - std::stringstream ss; -# if (ELPP_OS_WINDOWS) - ss << GetCurrentThreadId(); -# endif // (ELPP_OS_WINDOWS) - return ss.str(); - } - static inline void msleep(int) { - // No implementation for non std::thread version - } - typedef base::threading::internal::Mutex Mutex; - typedef base::threading::internal::ScopedLock ScopedLock; -# else - /// @brief Gets ID of currently running threading using std::this_thread::get_id() - static inline std::string getCurrentThreadId(void) { - std::stringstream ss; - ss << std::this_thread::get_id(); - return ss.str(); - } - static inline void msleep(int ms) { - // Only when async logging enabled - this is because async is strict on compiler -#if ELPP_ASYNC_LOGGING - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); -#endif // ELPP_ASYNC_LOGGING - } - typedef std::mutex Mutex; - typedef std::lock_guard ScopedLock; -# endif // !ELPP_USE_STD_THREADING -#else - namespace internal { - /// @brief Mutex wrapper used when multi-threading is disabled. - class NoMutex : base::NoCopy { - public: - NoMutex(void) {} - inline void lock(void) {} - inline bool try_lock(void) { return true; } - inline void unlock(void) {} - }; - /// @brief Lock guard wrapper used when multi-threading is disabled. - template - class NoScopedLock : base::NoCopy { - public: - explicit NoScopedLock(Mutex&) { - } - virtual ~NoScopedLock(void) { - } - private: - NoScopedLock(void); - }; - } // namespace internal - static inline std::string getCurrentThreadId(void) { - return std::string(); - } - static inline void msleep(int) { - // No custom implementation - } - typedef base::threading::internal::NoMutex Mutex; - typedef base::threading::internal::NoScopedLock ScopedLock; -#endif // ELPP_THREADING_ENABLED - /// @brief Base of thread safe class, this class is inheritable-only - class ThreadSafe { - public: - virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); } - virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); } - virtual inline base::threading::Mutex& lock(void) ELPP_FINAL { return m_mutex; } - protected: - ThreadSafe(void) {} - virtual ~ThreadSafe(void) {} - private: - base::threading::Mutex m_mutex; - }; - } // namespace threading - namespace utils { - class File : base::StaticClass { - public: - /// @brief Creates new out file stream for specified filename. - /// @return Pointer to newly created fstream or nullptr - static base::type::fstream_t* newFileStream(const std::string& filename) { - base::type::fstream_t *fs = new base::type::fstream_t(filename.c_str(), - base::type::fstream_t::out | base::type::fstream_t::app); -#if defined(ELPP_UNICODE) - std::locale elppUnicodeLocale(""); -#if ELPP_OS_WINDOWS - std::locale elppUnicodeLocaleWindows(elppUnicodeLocale, new std::codecvt_utf8_utf16); - elppUnicodeLocale = elppUnicodeLocaleWindows; -#endif - fs->imbue(elppUnicodeLocale); -#endif // defined(ELPP_UNICODE) - if (fs->is_open()) { - fs->flush(); - } - else { - base::utils::safeDelete(fs); - ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true); - } - return fs; - } - - /// @brief Gets size of file provided in stream - static std::size_t getSizeOfFile(base::type::fstream_t* fs) { - if (fs == nullptr) { - return 0; - } - std::streampos currPos = fs->tellg(); - fs->seekg(0, fs->end); - std::size_t size = static_cast(fs->tellg()); - fs->seekg(currPos); - return size; - } - - /// @brief Determines whether or not provided path exist in current file system - static inline bool pathExists(const char* path, bool considerFile = false) { - if (path == nullptr) { - return false; - } -#if ELPP_OS_UNIX - ELPP_UNUSED(considerFile); - struct stat st; - return (stat(path, &st) == 0); -#elif ELPP_OS_WINDOWS - DWORD fileType = GetFileAttributesA(path); - if (fileType == INVALID_FILE_ATTRIBUTES) { - return false; - } - return considerFile ? true : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true); -#endif // ELPP_OS_UNIX - } - - /// @brief Creates specified path on file system - /// @param path Path to create. - static bool createPath(const std::string& path) { - if (path.empty()) { - return false; - } - if (base::utils::File::pathExists(path.c_str())) { - return true; - } - int status = -1; - - char* currPath = const_cast(path.c_str()); - std::string builtPath = std::string(); -#if ELPP_OS_UNIX - if (path[0] == '/') { - builtPath = "/"; - } - currPath = STRTOK(currPath, base::consts::kFilePathSeperator, 0); -#elif ELPP_OS_WINDOWS - // Use secure functions API - char* nextTok_ = nullptr; - currPath = STRTOK(currPath, base::consts::kFilePathSeperator, &nextTok_); - ELPP_UNUSED(nextTok_); -#endif // ELPP_OS_UNIX - while (currPath != nullptr) { - builtPath.append(currPath); - builtPath.append(base::consts::kFilePathSeperator); -#if ELPP_OS_UNIX - status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS); - currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, 0); -#elif ELPP_OS_WINDOWS - status = _mkdir(builtPath.c_str()); - currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, &nextTok_); -#endif // ELPP_OS_UNIX - } - if (status == -1) { - ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true); - return false; - } - return true; - } - /// @brief Extracts path of filename with leading slash - static std::string extractPathFromFilename(const std::string& fullPath, - const char* seperator = base::consts::kFilePathSeperator) { - if ((fullPath == "") || (fullPath.find(seperator) == std::string::npos)) { - return fullPath; - } - std::size_t lastSlashAt = fullPath.find_last_of(seperator); - if (lastSlashAt == 0) { - return std::string(seperator); - } - return fullPath.substr(0, lastSlashAt + 1); - } - /// @brief builds stripped filename and puts it in buff - static void buildStrippedFilename(const char* filename, char buff[], - std::size_t limit = base::consts::kSourceFilenameMaxLength) { - std::size_t sizeOfFilename = strlen(filename); - if (sizeOfFilename >= limit) { - filename += (sizeOfFilename - limit); - if (filename[0] != '.' && filename[1] != '.') { // prepend if not already - filename += 3; // 3 = '..' - STRCAT(buff, "..", limit); - } - } - STRCAT(buff, filename, limit); - } - /// @brief builds base filename and puts it in buff - static void buildBaseFilename(const std::string& fullPath, char buff[], - std::size_t limit = base::consts::kSourceFilenameMaxLength, - const char* seperator = base::consts::kFilePathSeperator) { - const char *filename = fullPath.c_str(); - std::size_t lastSlashAt = fullPath.find_last_of(seperator); - filename += lastSlashAt ? lastSlashAt + 1 : 0; - std::size_t sizeOfFilename = strlen(filename); - if (sizeOfFilename >= limit) { - filename += (sizeOfFilename - limit); - if (filename[0] != '.' && filename[1] != '.') { // prepend if not already - filename += 3; // 3 = '..' - STRCAT(buff, "..", limit); - } - } - STRCAT(buff, filename, limit); - } - }; - /// @brief String utilities helper class used internally. You should not use it. - class Str : base::StaticClass { - public: - /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues. - static inline bool isDigit(char c) { - return c >= '0' && c <= '9'; - } - - /// @brief Matches wildcards, '*' and '?' only supported. - static bool wildCardMatch(const char* str, const char* pattern) { - while (*pattern) { - switch (*pattern) { - case '?': - if (!*str) - return false; - ++str; - ++pattern; - break; - case '*': - if (wildCardMatch(str, pattern + 1)) - return true; - if (*str && wildCardMatch(str + 1, pattern)) - return true; - return false; - break; - default: - if (*str++ != *pattern++) - return false; - break; - } - } - return !*str && !*pattern; - } - - /// @brief Trims string from start - /// @param [in,out] str String to trim - static inline std::string& ltrim(std::string& str) { - str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::not1(std::ptr_fun(&std::isspace)))); - return str; - } - - /// @brief Trim string from end - /// @param [in,out] str String to trim - static inline std::string& rtrim(std::string& str) { - str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(std::ptr_fun(&std::isspace))).base(), str.end()); - return str; - } - - /// @brief Trims string from left and right - /// @param [in,out] str String to trim - static inline std::string& trim(std::string& str) { - return ltrim(rtrim(str)); - } - - /// @brief Determines whether or not str starts with specified string - /// @param str String to check - /// @param start String to check against - /// @return Returns true if starts with specified string, false otherwise - static inline bool startsWith(const std::string& str, const std::string& start) { - return (str.length() >= start.length()) && (str.compare(0, start.length(), start) == 0); - } - - /// @brief Determines whether or not str ends with specified string - /// @param str String to check - /// @param end String to check against - /// @return Returns true if ends with specified string, false otherwise - static inline bool endsWith(const std::string& str, const std::string& end) { - return (str.length() >= end.length()) && (str.compare(str.length() - end.length(), end.length(), end) == 0); - } - - /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance. - /// @param [in,out] str String to replace from - /// @param replaceWhat Character to replace - /// @param replaceWith Character to replace with - /// @return Modified version of str - static inline std::string& replaceAll(std::string& str, char replaceWhat, char replaceWith) { - std::replace(str.begin(), str.end(), replaceWhat, replaceWith); - return str; - } - - /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place - /// @param str String to replace from - /// @param replaceWhat Character to replace - /// @param replaceWith Character to replace with - /// @return Modified (original) str - static inline std::string& replaceAll(std::string& str, const std::string& replaceWhat, // NOLINT - const std::string& replaceWith) { - if (replaceWhat == replaceWith) - return str; - std::size_t foundAt = std::string::npos; - while ((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos) { - str.replace(foundAt, replaceWhat.length(), replaceWith); - } - return str; - } - - static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT - const base::type::string_t& replaceWith) { - std::size_t foundAt = base::type::string_t::npos; - while ((foundAt = str.find(replaceWhat, foundAt + 1)) != base::type::string_t::npos) { - if (foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar) { - str.erase(foundAt > 0 ? foundAt - 1 : 0, 1); - ++foundAt; - } - else { - str.replace(foundAt, replaceWhat.length(), replaceWith); - return; - } - } - } -#if defined(ELPP_UNICODE) - static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT - const std::string& replaceWith) { - replaceFirstWithEscape(str, replaceWhat, base::type::string_t(replaceWith.begin(), replaceWith.end())); - } -#endif // defined(ELPP_UNICODE) - /// @brief Converts string to uppercase - /// @param str String to convert - /// @return Uppercase string - static inline std::string& toUpper(std::string& str) { - std::transform(str.begin(), str.end(), str.begin(), ::toupper); - return str; - } - - /// @brief Compares cstring equality - uses strcmp - static inline bool cStringEq(const char* s1, const char* s2) { - if (s1 == nullptr && s2 == nullptr) return true; - if (s1 == nullptr || s2 == nullptr) return false; - return strcmp(s1, s2) == 0; - } - - /// @brief Compares cstring equality (case-insensitive) - uses toupper(char) - /// Dont use strcasecmp because of CRT (VC++) - static bool cStringCaseEq(const char* s1, const char* s2) { - if (s1 == nullptr && s2 == nullptr) return true; - if (s1 == nullptr || s2 == nullptr) return false; - if (strlen(s1) != strlen(s2)) return false; - while (*s1 != '\0' && *s2 != '\0') { - if (::toupper(*s1) != ::toupper(*s2)) return false; - ++s1; - ++s2; - } - return true; - } - - /// @brief Returns true if c exist in str - static inline bool contains(const char* str, char c) { - for (; *str; ++str) { - if (*str == c) - return true; - } - return false; - } - - static inline char* convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded = true) { - char localBuff[10] = ""; - char* p = localBuff + sizeof(localBuff) - 2; - if (n > 0) { - for (; n > 0 && p > localBuff && len > 0; n /= 10, --len) - *--p = static_cast(n % 10 + '0'); - } - else { - *--p = '0'; - --len; - } - if (zeroPadded) - while (p > localBuff && len-- > 0) *--p = static_cast('0'); - return addToBuff(p, buf, bufLim); - } - - static inline char* addToBuff(const char* str, char* buf, const char* bufLim) { - while ((buf < bufLim) && ((*buf = *str++) != '\0')) - ++buf; - return buf; - } - - static inline char* clearBuff(char buff[], std::size_t lim) { - STRCPY(buff, "", lim); - ELPP_UNUSED(lim); // For *nix we dont have anything using lim in above STRCPY macro - return buff; - } - - /// @brief Converst wchar* to char* - /// NOTE: Need to free return value after use! - static char* wcharPtrToCharPtr(const wchar_t* line) { - std::size_t len_ = wcslen(line) + 1; - char* buff_ = static_cast(malloc(len_ + 1)); -# if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) - std::wcstombs(buff_, line, len_); -# elif ELPP_OS_WINDOWS - std::size_t convCount_ = 0; - mbstate_t mbState_; - ::memset(static_cast(&mbState_), 0, sizeof(mbState_)); - wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_); -# endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) - return buff_; - } - }; - /// @brief Operating System helper static class used internally. You should not use it. - class OS : base::StaticClass { - public: -#if ELPP_OS_WINDOWS - /// @brief Gets environment variables for Windows based OS. - /// We are not using getenv(const char*) because of CRT deprecation - /// @param varname Variable name to get environment variable value for - /// @return If variable exist the value of it otherwise nullptr - static const char* getWindowsEnvironmentVariable(const char* varname) { - const DWORD bufferLen = 50; - static char buffer[bufferLen]; - if (GetEnvironmentVariableA(varname, buffer, bufferLen)) { - return buffer; - } - return nullptr; - } -#endif // ELPP_OS_WINDOWS -#if ELPP_OS_ANDROID - /// @brief Reads android property value - static inline std::string getProperty(const char* prop) { - char propVal[PROP_VALUE_MAX + 1]; - int ret = __system_property_get(prop, propVal); - return ret == 0 ? std::string() : std::string(propVal); - } - - /// @brief Reads android device name - static std::string getDeviceName(void) { - std::stringstream ss; - std::string manufacturer = getProperty("ro.product.manufacturer"); - std::string model = getProperty("ro.product.model"); - if (manufacturer.empty() || model.empty()) { - return std::string(); - } - ss << manufacturer << "-" << model; - return ss.str(); - } -#endif // ELPP_OS_ANDROID - - /// @brief Runs command on terminal and returns the output. - /// - /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned. - /// @param command Bash command - /// @return Result of bash output or empty string if no result found. - static const std::string getBashOutput(const char* command) { -#if (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) - if (command == nullptr) { - return std::string(); - } - FILE* proc = nullptr; - if ((proc = popen(command, "r")) == nullptr) { - ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true); - return std::string(); - } - char hBuff[4096]; - if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) { - pclose(proc); - if (hBuff[strlen(hBuff) - 1] == '\n') { - hBuff[strlen(hBuff) - 1] = '\0'; - } - return std::string(hBuff); - } - return std::string(); -#else - ELPP_UNUSED(command); - return std::string(); -#endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) - } - - /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++) - /// @param variableName Environment variable name - /// @param defaultVal If no environment variable or value found the value to return by default - /// @param alternativeBashCommand If environment variable not found what would be alternative bash command - /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami' - static std::string getEnvironmentVariable(const char* variableName, const char* defaultVal, const char* alternativeBashCommand = nullptr) { -#if ELPP_OS_UNIX - const char* val = getenv(variableName); -#elif ELPP_OS_WINDOWS - const char* val = getWindowsEnvironmentVariable(variableName); -#endif // ELPP_OS_UNIX - if ((val == nullptr) || ((strcmp(val, "") == 0))) { -#if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) - // Try harder on unix-based systems - std::string valBash = base::utils::OS::getBashOutput(alternativeBashCommand); - if (valBash.empty()) { - return std::string(defaultVal); - } - else { - return valBash; - } -#elif ELPP_OS_WINDOWS || ELPP_OS_UNIX - ELPP_UNUSED(alternativeBashCommand); - return std::string(defaultVal); -#endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) - } - return std::string(val); - } - /// @brief Gets current username. - static inline std::string currentUser(void) { -#if ELPP_OS_UNIX && !ELPP_OS_ANDROID - return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami"); -#elif ELPP_OS_WINDOWS - return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser); -#elif ELPP_OS_ANDROID - ELPP_UNUSED(base::consts::kUnknownUser); - return std::string("android"); -#else - return std::string(); -#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID - } - - /// @brief Gets current host name or computer name. - /// - /// @detail For android systems this is device name with its manufacturer and model seperated by hyphen - static inline std::string currentHost(void) { -#if ELPP_OS_UNIX && !ELPP_OS_ANDROID - return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost, "hostname"); -#elif ELPP_OS_WINDOWS - return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost); -#elif ELPP_OS_ANDROID - ELPP_UNUSED(base::consts::kUnknownHost); - return getDeviceName(); -#else - return std::string(); -#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID - } - /// @brief Whether or not terminal supports colors - static inline bool termSupportsColor(void) { - std::string term = getEnvironmentVariable("TERM", ""); - return term == "xterm" || term == "xterm-color" || term == "xterm-256color" || - term == "screen" || term == "linux" || term == "cygwin"; - } - }; - extern std::string s_currentUser; - extern std::string s_currentHost; - extern bool s_termSupportsColor; -#define ELPP_INITI_BASIC_DECLR \ - namespace el {\ - namespace base {\ - namespace utils {\ - std::string s_currentUser = el::base::utils::OS::currentUser(); \ - std::string s_currentHost = el::base::utils::OS::currentHost(); \ - bool s_termSupportsColor = el::base::utils::OS::termSupportsColor(); \ - }\ - }\ - } - /// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str - class DateTime : base::StaticClass { - public: - /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current millisecond. - /// - /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a seperate implementation is provided - /// @param [in,out] tv Pointer that gets updated - static void gettimeofday(struct timeval* tv) { -#if ELPP_OS_WINDOWS - if (tv != nullptr) { -# if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) - const unsigned __int64 delta_ = 11644473600000000Ui64; -# else - const unsigned __int64 delta_ = 11644473600000000ULL; -# endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) - const double secOffSet = 0.000001; - const unsigned long usecOffSet = 1000000; - FILETIME fileTime; - GetSystemTimeAsFileTime(&fileTime); - unsigned __int64 present = 0; - present |= fileTime.dwHighDateTime; - present = present << 32; - present |= fileTime.dwLowDateTime; - present /= 10; // mic-sec - // Subtract the difference - present -= delta_; - tv->tv_sec = static_cast(present * secOffSet); - tv->tv_usec = static_cast(present % usecOffSet); - } -#else - ::gettimeofday(tv, nullptr); -#endif // ELPP_OS_WINDOWS - } - - /// @brief Gets current date and time with milliseconds. - /// @param format User provided date/time format - /// @param msWidth A pointer to base::MillisecondsWidth from configuration (non-null) - /// @returns string based date time in specified format. - static inline std::string getDateTime(const char* format, const base::MillisecondsWidth* msWidth) { - struct timeval currTime; - gettimeofday(&currTime); - struct ::tm timeInfo; - buildTimeInfo(&currTime, &timeInfo); - const int kBuffSize = 30; - char buff_[kBuffSize] = ""; - parseFormat(buff_, kBuffSize, format, &timeInfo, static_cast(currTime.tv_usec / msWidth->m_offset), msWidth); - return std::string(buff_); - } - - /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc - static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit) { - double result = static_cast(time); - base::type::EnumType start = static_cast(timestampUnit); - const base::type::char_t* unit = base::consts::kTimeFormats[start].unit; - for (base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1; ++i) { - if (result <= base::consts::kTimeFormats[i].value) { - break; - } - result /= base::consts::kTimeFormats[i].value; - unit = base::consts::kTimeFormats[i + 1].unit; - } - base::type::stringstream_t ss; - ss << result << " " << unit; - return ss.str(); - } - - /// @brief Gets time difference in milli/micro second depending on timestampUnit - static inline unsigned long long getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, base::TimestampUnit timestampUnit) { - if (timestampUnit == base::TimestampUnit::Microsecond) { - return static_cast(static_cast(1000000 * endTime.tv_sec + endTime.tv_usec) - - static_cast(1000000 * startTime.tv_sec + startTime.tv_usec)); - } - else { - return static_cast((((endTime.tv_sec - startTime.tv_sec) * 1000000) + (endTime.tv_usec - startTime.tv_usec)) / 1000); - } - } - - private: - static inline struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo) { -#if ELPP_OS_UNIX - time_t rawTime = currTime->tv_sec; - ::localtime_r(&rawTime, timeInfo); - return timeInfo; -#else -# if ELPP_COMPILER_MSVC - ELPP_UNUSED(currTime); - time_t t; - _time64(&t); - localtime_s(timeInfo, &t); - return timeInfo; -# else - // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method - time_t rawTime = currTime->tv_sec; - struct tm* tmInf = localtime(&rawTime); - *timeInfo = *tmInf; - return timeInfo; -# endif // ELPP_COMPILER_MSVC -#endif // ELPP_OS_UNIX - } - static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, - std::size_t msec, const base::MillisecondsWidth* msWidth) { - const char* bufLim = buf + bufSz; - for (; *format; ++format) { - if (*format == base::consts::kFormatSpecifierChar) { - switch (*++format) { - case base::consts::kFormatSpecifierChar: // Escape - break; - case '\0': // End - --format; - break; - case 'd': // Day - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf, bufLim); - continue; - case 'a': // Day of week (short) - buf = base::utils::Str::addToBuff(base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim); - continue; - case 'A': // Day of week (long) - buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday], buf, bufLim); - continue; - case 'M': // month - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf, bufLim); - continue; - case 'b': // month (short) - buf = base::utils::Str::addToBuff(base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim); - continue; - case 'B': // month (long) - buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon], buf, bufLim); - continue; - case 'y': // year (two digits) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim); - continue; - case 'Y': // year (four digits) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim); - continue; - case 'h': // hour (12-hour) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf, bufLim); - continue; - case 'H': // hour (24-hour) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf, bufLim); - continue; - case 'm': // minute - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf, bufLim); - continue; - case 's': // second - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf, bufLim); - continue; - case 'z': // milliseconds - case 'g': - buf = base::utils::Str::convertAndAddToBuff(msec, msWidth->m_width, buf, bufLim); - continue; - case 'F': // AM/PM - buf = base::utils::Str::addToBuff((tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf, bufLim); - continue; - default: - continue; - } - } - if (buf == bufLim) break; - *buf++ = *format; - } - return buf; - } - }; - /// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..) - class CommandLineArgs { - public: - CommandLineArgs(void) { - setArgs(0, static_cast(nullptr)); - } - CommandLineArgs(int argc, const char** argv) { - setArgs(argc, argv); - } - CommandLineArgs(int argc, char** argv) { - setArgs(argc, argv); - } - virtual ~CommandLineArgs(void) {} - /// @brief Sets arguments and parses them - inline void setArgs(int argc, const char** argv) { - setArgs(argc, const_cast(argv)); - } - /// @brief Sets arguments and parses them - inline void setArgs(int argc, char** argv) { - m_params.clear(); - m_paramsWithValue.clear(); - if (argc == 0 || argv == nullptr) { - return; - } - m_argc = argc; - m_argv = argv; - for (int i = 1; i < m_argc; ++i) { - const char* v = (strstr(m_argv[i], "=")); - if (v != nullptr && strlen(v) > 0) { - std::string key = std::string(m_argv[i]); - key = key.substr(0, key.find_first_of('=')); - if (hasParamWithValue(key.c_str())) { - ELPP_INTERNAL_INFO(1, "Skipping [" << key << "] arg since it already has value [" - << getParamValue(key.c_str()) << "]"); - } - else { - m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1))); - } - } - if (v == nullptr) { - if (hasParam(m_argv[i])) { - ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i] << "] arg since it already exists"); - } - else { - m_params.push_back(std::string(m_argv[i])); - } - } - } - } - /// @brief Returns true if arguments contain paramKey with a value (seperated by '=') - inline bool hasParamWithValue(const char* paramKey) const { - return m_paramsWithValue.find(std::string(paramKey)) != m_paramsWithValue.end(); - } - /// @brief Returns value of arguments - /// @see hasParamWithValue(const char*) - inline const char* getParamValue(const char* paramKey) const { - return m_paramsWithValue.find(std::string(paramKey))->second.c_str(); - } - /// @brief Return true if arguments has a param (not having a value) i,e without '=' - inline bool hasParam(const char* paramKey) const { - return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) != m_params.end(); - } - /// @brief Returns true if no params available. This exclude argv[0] - inline bool empty(void) const { - return m_params.empty() && m_paramsWithValue.empty(); - } - /// @brief Returns total number of arguments. This exclude argv[0] - inline std::size_t size(void) const { - return m_params.size() + m_paramsWithValue.size(); - } - inline friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c) { - for (int i = 1; i < c.m_argc; ++i) { - os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]"); - if (i < c.m_argc - 1) { - os << ELPP_LITERAL(" "); - } - } - return os; - } - - private: - int m_argc; - char** m_argv; - std::map m_paramsWithValue; - std::vector m_params; - }; - /// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. - /// - /// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement - /// unregisterAll() and deepCopy(const AbstractRegistry&) and write registerNew() method according to container - /// and few more methods; get() to find element, unregister() to unregister single entry. - /// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation. - template - class AbstractRegistry : public base::threading::ThreadSafe { - public: - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - - /// @brief Default constructor - AbstractRegistry(void) {} - - /// @brief Move constructor that is useful for base classes - AbstractRegistry(AbstractRegistry&& sr) { - if (this == &sr) { - return; - } - unregisterAll(); - m_list = std::move(sr.m_list); - } - - bool operator==(const AbstractRegistry& other) { - if (size() != other.size()) { - return false; - } - for (std::size_t i = 0; i < m_list.size(); ++i) { - if (m_list.at(i) != other.m_list.at(i)) { - return false; - } - } - return true; - } - - bool operator!=(const AbstractRegistry& other) { - if (size() != other.size()) { - return true; - } - for (std::size_t i = 0; i < m_list.size(); ++i) { - if (m_list.at(i) != other.m_list.at(i)) { - return true; - } - } - return false; - } - - /// @brief Assignment move operator - AbstractRegistry& operator=(AbstractRegistry&& sr) { - if (this == &sr) { - return *this; - } - unregisterAll(); - m_list = std::move(sr.m_list); - return *this; - } - - virtual ~AbstractRegistry(void) { - } - - /// @return Iterator pointer from start of repository - virtual inline iterator begin(void) ELPP_FINAL { - return m_list.begin(); - } - - /// @return Iterator pointer from end of repository - virtual inline iterator end(void) ELPP_FINAL { - return m_list.end(); - } - - - /// @return Constant iterator pointer from start of repository - virtual inline const_iterator cbegin(void) const ELPP_FINAL { - return m_list.cbegin(); - } - - /// @return End of repository - virtual inline const_iterator cend(void) const ELPP_FINAL { - return m_list.cend(); - } - - /// @return Whether or not repository is empty - virtual inline bool empty(void) const ELPP_FINAL { - return m_list.empty(); - } - - /// @return Size of repository - virtual inline std::size_t size(void) const ELPP_FINAL { - return m_list.size(); - } - - /// @brief Returns underlying container by reference - virtual inline Container& list(void) ELPP_FINAL { - return m_list; - } - - /// @brief Returns underlying container by constant reference. - virtual inline const Container& list(void) const ELPP_FINAL { - return m_list; - } - - /// @brief Unregisters all the pointers from current repository. - virtual void unregisterAll(void) = 0; - - protected: - virtual void deepCopy(const AbstractRegistry&) = 0; - void reinitDeepCopy(const AbstractRegistry& sr) { - unregisterAll(); - deepCopy(sr); - } - - private: - Container m_list; - }; - - /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version) - /// - /// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions) - /// of AbstractRegistry. Any implementation of this class should be - /// explicitly (by using lock functions) - template - class Registry : public AbstractRegistry> { - public: - typedef typename Registry::iterator iterator; - typedef typename Registry::const_iterator const_iterator; - - Registry(void) {} - - /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. - Registry(const Registry& sr) : AbstractRegistry>() { - if (this == &sr) { - return; - } - this->reinitDeepCopy(sr); - } - - /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element - /// @see unregisterAll() - /// @see deepCopy(const AbstractRegistry&) - Registry& operator=(const Registry& sr) { - if (this == &sr) { - return *this; - } - this->reinitDeepCopy(sr); - return *this; - } - - virtual ~Registry(void) { - unregisterAll(); - } - - protected: - virtual inline void unregisterAll(void) ELPP_FINAL { - if (!this->empty()) { - for (auto&& curr : this->list()) { - base::utils::safeDelete(curr.second); - } - this->list().clear(); - } - } - - /// @brief Registers new registry to repository. - virtual inline void registerNew(const T_Key& uniqKey, T_Ptr* ptr) ELPP_FINAL { - unregister(uniqKey); - this->list().insert(std::make_pair(uniqKey, ptr)); - } - - /// @brief Unregisters single entry mapped to specified unique key - inline void unregister(const T_Key& uniqKey) { - T_Ptr* existing = get(uniqKey); - if (existing != nullptr) { - base::utils::safeDelete(existing); - this->list().erase(uniqKey); - } - } - - /// @brief Gets pointer from repository. If none found, nullptr is returned. - inline T_Ptr* get(const T_Key& uniqKey) { - iterator it = this->list().find(uniqKey); - return it == this->list().end() - ? nullptr - : it->second; - } - - private: - virtual inline void deepCopy(const AbstractRegistry>& sr) ELPP_FINAL { - for (const_iterator it = sr.cbegin(); it != sr.cend(); ++it) { - registerNew(it->first, new T_Ptr(*it->second)); - } - } - }; - - /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version) - /// - /// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry. Any implementation of this class - /// should be made thread-safe explicitly - template - class RegistryWithPred : public AbstractRegistry> { - public: - typedef typename RegistryWithPred::iterator iterator; - typedef typename RegistryWithPred::const_iterator const_iterator; - - RegistryWithPred(void) { - } - - virtual ~RegistryWithPred(void) { - unregisterAll(); - } - - /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. - RegistryWithPred(const RegistryWithPred& sr) : AbstractRegistry>() { - if (this == &sr) { - return; - } - this->reinitDeepCopy(sr); - } - - /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element - /// @see unregisterAll() - /// @see deepCopy(const AbstractRegistry&) - RegistryWithPred& operator=(const RegistryWithPred& sr) { - if (this == &sr) { - return *this; - } - this->reinitDeepCopy(sr); - return *this; - } - - friend inline base::type::ostream_t& operator<<(base::type::ostream_t& os, const RegistryWithPred& sr) { - for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { - os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n"); - } - return os; - } - - protected: - virtual inline void unregisterAll(void) ELPP_FINAL { - if (!this->empty()) { - for (auto&& curr : this->list()) { - base::utils::safeDelete(curr); - } - this->list().clear(); - } - } - - virtual void unregister(T_Ptr*& ptr) ELPP_FINAL { - if (ptr) { - iterator iter = this->begin(); - for (; iter != this->end(); ++iter) { - if (ptr == *iter) { - break; - } - } - if (iter != this->end() && *iter != nullptr) { - this->list().erase(iter); - base::utils::safeDelete(*iter); - } - } - } - - virtual inline void registerNew(T_Ptr* ptr) ELPP_FINAL { - this->list().push_back(ptr); - } - - /// @brief Gets pointer from repository with speicifed arguments. Arguments are passed to predicate - /// in order to validate pointer. - template - inline T_Ptr* get(const T& arg1, const T2 arg2) { - iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2)); - if (iter != this->list().end() && *iter != nullptr) { - return *iter; - } - return nullptr; - } - - private: - virtual inline void deepCopy(const AbstractRegistry>& sr) { - for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { - registerNew(new T_Ptr(**it)); - } - } - }; - - } // namespace utils - } // namespace base - /// @brief Base of Easylogging++ friendly class - /// - /// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const` - class Loggable { - public: - virtual ~Loggable(void) {} - virtual void log(el::base::type::ostream_t&) const = 0; - private: - friend inline el::base::type::ostream_t& operator<<(el::base::type::ostream_t& os, const Loggable& loggable) { - loggable.log(os); - return os; - } - }; - namespace base { - /// @brief Represents log format containing flags and date format. This is used internally to start initial log - class LogFormat : public Loggable { - public: - LogFormat(void) : - m_level(Level::Unknown), - m_userFormat(base::type::string_t()), - m_format(base::type::string_t()), - m_dateTimeFormat(std::string()), - m_flags(0x0) { - } - - LogFormat(Level level, const base::type::string_t& format) - : m_level(level), m_userFormat(format) { - parseFromFormat(m_userFormat); - } - - LogFormat(const LogFormat& logFormat) { - m_level = logFormat.m_level; - m_userFormat = logFormat.m_userFormat; - m_format = logFormat.m_format; - m_dateTimeFormat = logFormat.m_dateTimeFormat; - m_flags = logFormat.m_flags; - } - - LogFormat(LogFormat&& logFormat) { - m_level = std::move(logFormat.m_level); - m_userFormat = std::move(logFormat.m_userFormat); - m_format = std::move(logFormat.m_format); - m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat); - m_flags = std::move(logFormat.m_flags); - } - - LogFormat& operator=(const LogFormat& logFormat) { - m_level = logFormat.m_level; - m_userFormat = logFormat.m_userFormat; - m_dateTimeFormat = logFormat.m_dateTimeFormat; - m_flags = logFormat.m_flags; - return *this; - } - - virtual ~LogFormat(void) { - } - - inline bool operator==(const LogFormat& other) { - return m_level == other.m_level && m_userFormat == other.m_userFormat && m_format == other.m_format && - m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags; - } - - /// @brief Updates format to be used while logging. - /// @param userFormat User provided format - void parseFromFormat(const base::type::string_t& userFormat) { - // We make copy because we will be changing the format - // i.e, removing user provided date format from original format - // and then storing it. - base::type::string_t formatCopy = userFormat; - m_flags = 0x0; - auto conditionalAddFlag = [&](const base::type::char_t* specifier, base::FormatFlags flag) { - std::size_t foundAt = base::type::string_t::npos; - while ((foundAt = formatCopy.find(specifier, foundAt + 1)) != base::type::string_t::npos) { - if (foundAt > 0 && formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar) { - if (hasFlag(flag)) { - // If we already have flag we remove the escape chars so that '%%' is turned to '%' - // even after specifier resolution - this is because we only replaceFirst specifier - formatCopy.erase(foundAt > 0 ? foundAt - 1 : 0, 1); - ++foundAt; - } - } - else { - if (!hasFlag(flag)) addFlag(flag); - } - } - }; - conditionalAddFlag(base::consts::kAppNameFormatSpecifier, base::FormatFlags::AppName); - conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier, base::FormatFlags::Level); - conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier, base::FormatFlags::LevelShort); - conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier, base::FormatFlags::LoggerId); - conditionalAddFlag(base::consts::kThreadIdFormatSpecifier, base::FormatFlags::ThreadId); - conditionalAddFlag(base::consts::kLogFileFormatSpecifier, base::FormatFlags::File); - conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier, base::FormatFlags::FileBase); - conditionalAddFlag(base::consts::kLogLineFormatSpecifier, base::FormatFlags::Line); - conditionalAddFlag(base::consts::kLogLocationFormatSpecifier, base::FormatFlags::Location); - conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier, base::FormatFlags::Function); - conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier, base::FormatFlags::User); - conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier, base::FormatFlags::Host); - conditionalAddFlag(base::consts::kMessageFormatSpecifier, base::FormatFlags::LogMessage); - conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier, base::FormatFlags::VerboseLevel); - // For date/time we need to extract user's date format first - std::size_t dateIndex = std::string::npos; - if ((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) != std::string::npos) { - while (dateIndex > 0 && formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar) { - dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier, dateIndex + 1); - } - if (dateIndex != std::string::npos) { - addFlag(base::FormatFlags::DateTime); - updateDateFormat(dateIndex, formatCopy); - } - } - m_format = formatCopy; - updateFormatSpec(); - } - - inline Level level(void) const { - return m_level; - } - - inline const base::type::string_t& userFormat(void) const { - return m_userFormat; - } - - inline const base::type::string_t& format(void) const { - return m_format; - } - - inline const std::string& dateTimeFormat(void) const { - return m_dateTimeFormat; - } - - inline base::type::EnumType flags(void) const { - return m_flags; - } - - inline bool hasFlag(base::FormatFlags flag) const { - return base::utils::hasFlag(flag, m_flags); - } - - virtual void log(el::base::type::ostream_t& os) const { - os << m_format; - } - - protected: - /// @brief Updates date time format if available in currFormat. - /// @param index Index where %datetime, %date or %time was found - /// @param [in,out] currFormat current format that is being used to format - virtual void updateDateFormat(std::size_t index, base::type::string_t& currFormat) ELPP_FINAL { - if (hasFlag(base::FormatFlags::DateTime)) { - index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier); - } - const base::type::char_t* ptr = currFormat.c_str() + index; - if ((currFormat.size() > index) && (ptr[0] == '{')) { - // User has provided format for date/time - ++ptr; - int count = 1; // Start by 1 in order to remove starting brace - std::stringstream ss; - for (; *ptr; ++ptr, ++count) { - if (*ptr == '}') { - ++count; // In order to remove ending brace - break; - } - ss << *ptr; - } - currFormat.erase(index, count); - m_dateTimeFormat = ss.str(); - } - else { - // No format provided, use default - if (hasFlag(base::FormatFlags::DateTime)) { - m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat); - } - } - } - - /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level - virtual void updateFormatSpec(void) ELPP_FINAL { - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if (m_level == Level::Debug) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kDebugLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kDebugLevelShortLogValue); - } - else if (m_level == Level::Info) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kInfoLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kInfoLevelShortLogValue); - } - else if (m_level == Level::Warning) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kWarningLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kWarningLevelShortLogValue); - } - else if (m_level == Level::Error) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kErrorLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kErrorLevelShortLogValue); - } - else if (m_level == Level::Fatal) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kFatalLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kFatalLevelShortLogValue); - } - else if (m_level == Level::Verbose) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kVerboseLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kVerboseLevelShortLogValue); - } - else if (m_level == Level::Trace) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kTraceLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kTraceLevelShortLogValue); - } - if (hasFlag(base::FormatFlags::User)) { - std::string s = base::utils::s_currentUser; - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentUserFormatSpecifier, - base::utils::s_currentUser); - } - if (hasFlag(base::FormatFlags::Host)) { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentHostFormatSpecifier, - base::utils::s_currentHost); - } - // Ignore Level::Global and Level::Unknown - } - - inline void addFlag(base::FormatFlags flag) { - base::utils::addFlag(flag, &m_flags); - } - - private: - Level m_level; - base::type::string_t m_userFormat; - base::type::string_t m_format; - std::string m_dateTimeFormat; - base::type::EnumType m_flags; - friend class el::Logger; // To resolve loggerId format specifier easily - }; - } // namespace base - /// @brief Resolving function for format specifier - typedef std::function FormatSpecifierValueResolver; - /// @brief User-provided custom format specifier - /// @see el::Helpers::installCustomFormatSpecifier - /// @see FormatSpecifierValueResolver - class CustomFormatSpecifier { - public: - CustomFormatSpecifier(const char* formatSpecifier, const FormatSpecifierValueResolver& resolver) : - m_formatSpecifier(formatSpecifier), m_resolver(resolver) {} - inline const char* formatSpecifier(void) const { return m_formatSpecifier; } - inline const FormatSpecifierValueResolver& resolver(void) const { return m_resolver; } - inline bool operator==(const char* formatSpecifier) { - return strcmp(m_formatSpecifier, formatSpecifier) == 0; - } - - private: - const char* m_formatSpecifier; - FormatSpecifierValueResolver m_resolver; - }; - /// @brief Represents single configuration that has representing level, configuration type and a string based value. - /// - /// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes - /// and will be parsed later. - /// - /// Consider some examples below: - /// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true"); - /// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048"); - /// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log"); - class Configuration : public Loggable { - public: - Configuration(const Configuration& c) : - m_level(c.m_level), - m_configurationType(c.m_configurationType), - m_value(c.m_value) { - } - - Configuration& operator=(const Configuration& c) { - m_level = c.m_level; - m_configurationType = c.m_configurationType; - m_value = c.m_value; - return *this; - } - - virtual ~Configuration(void) { - } - - /// @brief Full constructor used to sets value of configuration - Configuration(Level level, ConfigurationType configurationType, const std::string& value) : - m_level(level), - m_configurationType(configurationType), - m_value(value) { - } - - /// @brief Gets level of current configuration - inline Level level(void) const { - return m_level; - } - - /// @brief Gets configuration type of current configuration - inline ConfigurationType configurationType(void) const { - return m_configurationType; - } - - /// @brief Gets string based configuration value - inline const std::string& value(void) const { - return m_value; - } - - /// @brief Set string based configuration value - /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values - /// use them in quotes. They will be parsed when configuring - inline void setValue(const std::string& value) { - m_value = value; - } - - virtual inline void log(el::base::type::ostream_t& os) const { - os << LevelHelper::convertToString(m_level) - << ELPP_LITERAL(" ") << ConfigurationTypeHelper::convertToString(m_configurationType) - << ELPP_LITERAL(" = ") << m_value.c_str(); - } - - /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. - class Predicate { - public: - Predicate(Level level, ConfigurationType configurationType) : - m_level(level), - m_configurationType(configurationType) { - } - - inline bool operator()(const Configuration* conf) const { - return ((conf != nullptr) && (conf->level() == m_level) && (conf->configurationType() == m_configurationType)); - } - - private: - Level m_level; - ConfigurationType m_configurationType; - }; - - private: - Level m_level; - ConfigurationType m_configurationType; - std::string m_value; - }; - - /// @brief Thread-safe Configuration repository - /// - /// @detail This repository represents configurations for all the levels and configuration type mapped to a value. - class Configurations : public base::utils::RegistryWithPred { - public: - /// @brief Default constructor with empty repository - Configurations(void) : - m_configurationFile(std::string()), - m_isFromFile(false) { - } - - /// @brief Constructor used to set configurations using configuration file. - /// @param configurationFile Full path to configuration file - /// @param useDefaultsForRemaining Lets you set the remaining configurations to default. - /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. - /// @see parseFromFile(const std::string&, Configurations* base) - /// @see setRemainingToDefault() - Configurations(const std::string& configurationFile, bool useDefaultsForRemaining = true, Configurations* base = nullptr) : - m_configurationFile(configurationFile), - m_isFromFile(false) { - parseFromFile(configurationFile, base); - if (useDefaultsForRemaining) { - setRemainingToDefault(); - } - } - - virtual ~Configurations(void) { - } - - /// @brief Parses configuration from file. - /// @param configurationFile Full path to configuration file - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration file. - /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you - /// do not proceed without successful parse. - inline bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr) { - // We initial assertion with true because if we have assertion diabled, we want to pass this - // check and if assertion is enabled we will have values re-assigned any way. - bool assertionPassed = true; - ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(configurationFile.c_str(), true)), - "Configuration file [" << configurationFile << "] does not exist!"); - if (!assertionPassed) { - return false; - } - bool success = Parser::parseFromFile(configurationFile, this, base); - m_isFromFile = success; - return success; - } - - /// @brief Parse configurations from configuration string. - /// - /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary - /// new line characters are provided. - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration text. - /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you - /// do not proceed without successful parse. - inline bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr) { - bool success = Parser::parseFromText(configurationsString, this, base); - if (success) { - m_isFromFile = false; - } - return success; - } - - /// @brief Sets configuration based-off an existing configurations. - /// @param base Pointer to existing configurations. - inline void setFromBase(Configurations* base) { - if (base == nullptr || base == this) { - return; - } - base::threading::ScopedLock scopedLock(base->lock()); - for (Configuration*& conf : base->list()) { - set(conf); - } - } - - /// @brief Determines whether or not specified configuration type exists in the repository. - /// - /// @detail Returns as soon as first level is found. - /// @param configurationType Type of configuration to check existence for. - bool hasConfiguration(ConfigurationType configurationType) { - base::type::EnumType lIndex = LevelHelper::kMinValid; - bool result = false; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - if (hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType)) { - result = true; - } - return result; - }); - return result; - } - - /// @brief Determines whether or not specified configuration type exists for specified level - /// @param level Level to check - /// @param configurationType Type of configuration to check existence for. - inline bool hasConfiguration(Level level, ConfigurationType configurationType) { - base::threading::ScopedLock scopedLock(lock()); -#if ELPP_COMPILER_INTEL - // We cant specify template types here, Intel C++ throws compilation error - // "error: type name is not allowed" - return RegistryWithPred::get(level, configurationType) != nullptr; -#else - return RegistryWithPred::get(level, configurationType) != nullptr; -#endif // ELPP_COMPILER_INTEL - } - - /// @brief Sets value of configuration for specified level. - /// - /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types - /// ConfigurationType::MillisecondsWidth and ConfigurationType::PerformanceTracking will be ignored if not set for - /// Level::Global because these configurations are not dependant on level. - /// @param level Level to set configuration for (el::Level). - /// @param configurationType Type of configuration (el::ConfigurationType) - /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string - /// from users' point of view. This is then parsed later to be used internally. - /// @see Configuration::setValue(const std::string& value) - /// @see el::Level - /// @see el::ConfigurationType - inline void set(Level level, ConfigurationType configurationType, const std::string& value) { - base::threading::ScopedLock scopedLock(lock()); - unsafeSet(level, configurationType, value); // This is not unsafe anymore as we have locked mutex - if (level == Level::Global) { - unsafeSetGlobally(configurationType, value, false); // Again this is not unsafe either - } - } - - /// @brief Sets single configuration based on other single configuration. - /// @see set(Level level, ConfigurationType configurationType, const std::string& value) - inline void set(Configuration* conf) { - if (conf == nullptr) { - return; - } - set(conf->level(), conf->configurationType(), conf->value()); - } - - inline Configuration* get(Level level, ConfigurationType configurationType) { - base::threading::ScopedLock scopedLock(lock()); - return RegistryWithPred::get(level, configurationType); - } - - /// @brief Sets configuration for all levels. - /// @param configurationType Type of configuration - /// @param value String based value - /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) - inline void setGlobally(ConfigurationType configurationType, const std::string& value) { - setGlobally(configurationType, value, false); - } - - /// @brief Clears repository so that all the configurations are unset - inline void clear(void) { - base::threading::ScopedLock scopedLock(lock()); - unregisterAll(); - } - - /// @brief Gets configuration file used in parsing this configurations. - /// - /// @detail If this repository was set manually or by text this returns empty string. - inline const std::string& configurationFile(void) const { - return m_configurationFile; - } - - /// @brief Sets configurations to "factory based" configurations. - void setToDefault(void) { - setGlobally(ConfigurationType::Enabled, std::string("true"), true); -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) - setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true); -#else - ELPP_UNUSED(base::consts::kDefaultLogFile); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) - setGlobally(ConfigurationType::ToFile, std::string("true"), true); - setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true); - setGlobally(ConfigurationType::MillisecondsWidth, std::string("3"), true); - setGlobally(ConfigurationType::PerformanceTracking, std::string("true"), true); - setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true); - setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true); - - setGlobally(ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"), true); - set(Level::Debug, ConfigurationType::Format, std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); - // INFO and WARNING are set to default by Level::Global - set(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - set(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - set(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); - set(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); - } - - /// @brief Lets you set the remaining configurations to default. - /// - /// @detail By remaining, it means that the level/type a configuration does not exist for. - /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets - /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, - /// true. If you dont do this explicitley (either by calling this function or by using second param in Constructor - /// and try to access a value, an error is thrown - void setRemainingToDefault(void) { - base::threading::ScopedLock scopedLock(lock()); - unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true")); -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) - unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile)); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) - unsafeSetIfNotExist(Level::Global, ConfigurationType::ToFile, std::string("true")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::MillisecondsWidth, std::string("3")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize, std::string("0")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Debug, ConfigurationType::Format, - std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); - // INFO and WARNING are set to default by Level::Global - unsafeSetIfNotExist(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); - unsafeSetIfNotExist(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); - } - - /// @brief Parser used internally to parse configurations from file or text. - /// - /// @detail This class makes use of base::utils::Str. - /// You should not need this unless you are working on some tool for Easylogging++ - class Parser : base::StaticClass { - public: - /// @brief Parses configuration from file. - /// @param configurationFile Full path to configuration file - /// @param sender Sender configurations pointer. Usually 'this' is used from calling class - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration file. - /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you - /// do not proceed without successful parse. - static bool parseFromFile(const std::string& configurationFile, Configurations* sender, Configurations* base = nullptr) { - sender->setFromBase(base); - std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in); - ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file [" << configurationFile << "] for parsing."); - bool parsedSuccessfully = false; - std::string line = std::string(); - Level currLevel = Level::Unknown; - std::string currConfigStr = std::string(); - std::string currLevelStr = std::string(); - while (fileStream_.good()) { - std::getline(fileStream_, line); - parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); - ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); - } - return parsedSuccessfully; - } - - /// @brief Parse configurations from configuration string. - /// - /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary - /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you - /// do not proceed without successful parse (This is recommended) - /// @param configurationsString - /// @param sender Sender configurations pointer. Usually 'this' is used from calling class - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration text. - /// @return True if successfully parsed, false otherwise. - static bool parseFromText(const std::string& configurationsString, Configurations* sender, Configurations* base = nullptr) { - sender->setFromBase(base); - bool parsedSuccessfully = false; - std::stringstream ss(configurationsString); - std::string line = std::string(); - Level currLevel = Level::Unknown; - std::string currConfigStr = std::string(); - std::string currLevelStr = std::string(); - while (std::getline(ss, line)) { - parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); - ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); - } - return parsedSuccessfully; - } - - private: - friend class el::Loggers; - static void ignoreComments(std::string* line) { - std::size_t foundAt = 0; - std::size_t quotesStart = line->find("\""); - std::size_t quotesEnd = std::string::npos; - if (quotesStart != std::string::npos) { - quotesEnd = line->find("\"", quotesStart + 1); - while (quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\') { - // Do not erase slash yet - we will erase it in parseLine(..) while loop - quotesEnd = line->find("\"", quotesEnd + 2); - } - } - if ((foundAt = line->find(base::consts::kConfigurationComment)) != std::string::npos) { - if (foundAt < quotesEnd) { - foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1); - } - *line = line->substr(0, foundAt); - } - } - static inline bool isLevel(const std::string& line) { - return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLevel)); - } - - static inline bool isComment(const std::string& line) { - return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationComment)); - } - - static inline bool isConfig(const std::string& line) { - std::size_t assignment = line.find('='); - return line != "" && - (line[0] >= 65 || line[0] <= 90 || line[0] >= 97 || line[0] <= 122) && - (assignment != std::string::npos) && - (line.size() > assignment); - } - - static bool parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, Level* currLevel, Configurations* conf) { - ConfigurationType currConfig = ConfigurationType::Unknown; - std::string currValue = std::string(); - *line = base::utils::Str::trim(*line); - if (isComment(*line)) return true; - ignoreComments(line); - *line = base::utils::Str::trim(*line); - if (line->empty()) { - // Comment ignored - return true; - } - if (isLevel(*line)) { - if (line->size() <= 2) { - return true; - } - *currLevelStr = line->substr(1, line->size() - 2); - *currLevelStr = base::utils::Str::toUpper(*currLevelStr); - *currLevelStr = base::utils::Str::trim(*currLevelStr); - *currLevel = LevelHelper::convertFromString(currLevelStr->c_str()); - return true; - } - if (isConfig(*line)) { - std::size_t assignment = line->find('='); - *currConfigStr = line->substr(0, assignment); - *currConfigStr = base::utils::Str::toUpper(*currConfigStr); - *currConfigStr = base::utils::Str::trim(*currConfigStr); - currConfig = ConfigurationTypeHelper::convertFromString(currConfigStr->c_str()); - currValue = line->substr(assignment + 1); - currValue = base::utils::Str::trim(currValue); - std::size_t quotesStart = currValue.find("\"", 0); - std::size_t quotesEnd = std::string::npos; - if (quotesStart != std::string::npos) { - quotesEnd = currValue.find("\"", quotesStart + 1); - while (quotesEnd != std::string::npos && currValue.at(quotesEnd - 1) == '\\') { - currValue = currValue.erase(quotesEnd - 1, 1); - quotesEnd = currValue.find("\"", quotesEnd + 2); - } - } - if (quotesStart != std::string::npos && quotesEnd != std::string::npos) { - // Quote provided - check and strip if valid - ELPP_ASSERT((quotesStart < quotesEnd), "Configuration error - No ending quote found in [" - << currConfigStr << "]"); - ELPP_ASSERT((quotesStart + 1 != quotesEnd), "Empty configuration value for [" << currConfigStr << "]"); - if ((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd)) { - // Explicit check in case if assertion is disabled - currValue = currValue.substr(quotesStart + 1, quotesEnd - 1); - } - } - } - ELPP_ASSERT(*currLevel != Level::Unknown, "Unrecognized severity level [" << *currLevelStr << "]"); - ELPP_ASSERT(currConfig != ConfigurationType::Unknown, "Unrecognized configuration [" << *currConfigStr << "]"); - if (*currLevel == Level::Unknown || currConfig == ConfigurationType::Unknown) { - return false; // unrecognizable level or config - } - conf->set(*currLevel, currConfig, currValue); - return true; - } - }; - - private: - std::string m_configurationFile; - bool m_isFromFile; - friend class el::Loggers; - - /// @brief Unsafely sets configuration if does not already exist - void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value) { - Configuration* conf = RegistryWithPred::get(level, configurationType); - if (conf == nullptr) { - unsafeSet(level, configurationType, value); - } - } - - /// @brief Thread unsafe set - void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value) { - Configuration* conf = RegistryWithPred::get(level, configurationType); - if (conf == nullptr) { - registerNew(new Configuration(level, configurationType, value)); - } - else { - conf->setValue(value); - } - if (level == Level::Global) { - unsafeSetGlobally(configurationType, value, false); - } - } - - /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true - /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) - void setGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel) { - if (includeGlobalLevel) { - set(Level::Global, configurationType, value); - } - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - set(LevelHelper::castFromInt(lIndex), configurationType, value); - return false; // Do not break lambda function yet as we need to set all levels regardless - }); - } - - /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true - /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) - void unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel) { - if (includeGlobalLevel) { - unsafeSet(Level::Global, configurationType, value); - } - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value); - return false; // Do not break lambda function yet as we need to set all levels regardless - }); - } - }; - - namespace base { - typedef std::shared_ptr FileStreamPtr; - typedef std::map LogStreamsReferenceMap; - /// @brief Configurations with data types. - /// - /// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. - /// This is to perform faster while writing logs using correct configurations. - /// - /// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class) - class TypedConfigurations : public base::threading::ThreadSafe { - public: - /// @brief Constructor to initialize (construct) the object off el::Configurations - /// @param configurations Configurations pointer/reference to base this typed configurations off. - /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference() - TypedConfigurations(Configurations* configurations, base::LogStreamsReferenceMap* logStreamsReference) { - m_configurations = configurations; - m_logStreamsReference = logStreamsReference; - build(m_configurations); - } - - TypedConfigurations(const TypedConfigurations& other) { - this->m_configurations = other.m_configurations; - this->m_logStreamsReference = other.m_logStreamsReference; - build(m_configurations); - } - - virtual ~TypedConfigurations(void) { - } - - const Configurations* configurations(void) const { - return m_configurations; - } - - inline bool enabled(Level level) { - return getConfigByVal(level, &m_enabledMap, "enabled"); - } - - inline bool toFile(Level level) { - return getConfigByVal(level, &m_toFileMap, "toFile"); - } - - inline const std::string& filename(Level level) { - return getConfigByRef(level, &m_filenameMap, "filename"); - } - - inline bool toStandardOutput(Level level) { - return getConfigByVal(level, &m_toStandardOutputMap, "toStandardOutput"); - } - - inline const base::LogFormat& logFormat(Level level) { - return getConfigByRef(level, &m_logFormatMap, "logFormat"); - } - - inline const base::MillisecondsWidth& millisecondsWidth(Level level = Level::Global) { - return getConfigByRef(level, &m_millisecondsWidthMap, "millisecondsWidth"); - } - - inline bool performanceTracking(Level level = Level::Global) { - return getConfigByVal(level, &m_performanceTrackingMap, "performanceTracking"); - } - - inline base::type::fstream_t* fileStream(Level level) { - return getConfigByRef(level, &m_fileStreamMap, "fileStream").get(); - } - - inline std::size_t maxLogFileSize(Level level) { - return getConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); - } - - inline std::size_t logFlushThreshold(Level level) { - return getConfigByVal(level, &m_logFlushThresholdMap, "logFlushThreshold"); - } - - private: - Configurations* m_configurations; - std::map m_enabledMap; - std::map m_toFileMap; - std::map m_filenameMap; - std::map m_toStandardOutputMap; - std::map m_logFormatMap; - std::map m_millisecondsWidthMap; - std::map m_performanceTrackingMap; - std::map m_fileStreamMap; - std::map m_maxLogFileSizeMap; - std::map m_logFlushThresholdMap; - base::LogStreamsReferenceMap* m_logStreamsReference; - - friend class el::Helpers; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::DefaultLogDispatchCallback; - friend class el::base::LogDispatcher; - - template - inline Conf_T getConfigByVal(Level level, const std::map* confMap, const char* confName) { - base::threading::ScopedLock scopedLock(lock()); - return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope - } - - template - inline Conf_T& getConfigByRef(Level level, std::map* confMap, const char* confName) { - base::threading::ScopedLock scopedLock(lock()); - return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope - } - - template - inline Conf_T unsafeGetConfigByVal(Level level, const std::map* confMap, const char* confName) { - ELPP_UNUSED(confName); - typename std::map::const_iterator it = confMap->find(level); - if (it == confMap->end()) { - try { - return confMap->at(Level::Global); - } - catch (...) { - ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" - << LevelHelper::convertToString(level) << "]" - << std::endl << "Please ensure you have properly configured logger.", false); - return Conf_T(); - } - } - return it->second; - } - - template - inline Conf_T& unsafeGetConfigByRef(Level level, std::map* confMap, const char* confName) { - ELPP_UNUSED(confName); - typename std::map::iterator it = confMap->find(level); - if (it == confMap->end()) { - try { - return confMap->at(Level::Global); - } - catch (...) { - ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" - << LevelHelper::convertToString(level) << "]" - << std::endl << "Please ensure you have properly configured logger.", false); - } - } - return it->second; - } - - template - void setValue(Level level, const Conf_T& value, std::map* confMap, bool includeGlobalLevel = true) { - // If map is empty and we are allowed to add into generic level (Level::Global), do it! - if (confMap->empty() && includeGlobalLevel) { - confMap->insert(std::make_pair(Level::Global, value)); - return; - } - // If same value exist in generic level already, dont add it to explicit level - typename std::map::iterator it = confMap->find(Level::Global); - if (it != confMap->end() && it->second == value) { - return; - } - // Now make sure we dont double up values if we really need to add it to explicit level - it = confMap->find(level); - if (it == confMap->end()) { - // Value not found for level, add new - confMap->insert(std::make_pair(level, value)); - } - else { - // Value found, just update value - confMap->at(level) = value; - } - } - - void build(Configurations* configurations) { - base::threading::ScopedLock scopedLock(lock()); - auto getBool = [](std::string boolStr) -> bool { // Pass by value for trimming - base::utils::Str::trim(boolStr); - return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1"); - }; - std::vector withFileSizeLimit; - for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { - Configuration* conf = *it; - // We cannot use switch on strong enums because Intel C++ dont support them yet - if (conf->configurationType() == ConfigurationType::Enabled) { - setValue(conf->level(), getBool(conf->value()), &m_enabledMap); - } - else if (conf->configurationType() == ConfigurationType::ToFile) { - setValue(conf->level(), getBool(conf->value()), &m_toFileMap); - } - else if (conf->configurationType() == ConfigurationType::ToStandardOutput) { - setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap); - } - else if (conf->configurationType() == ConfigurationType::Filename) { - // We do not yet configure filename but we will configure in another - // loop. This is because if file cannot be created, we will force ToFile - // to be false. Because configuring logger is not necessarily performance - // sensative operation, we can live with another loop; (by the way this loop - // is not very heavy either) - } - else if (conf->configurationType() == ConfigurationType::Format) { - setValue(conf->level(), base::LogFormat(conf->level(), - base::type::string_t(conf->value().begin(), conf->value().end())), &m_logFormatMap); - } - else if (conf->configurationType() == ConfigurationType::MillisecondsWidth) { - setValue(Level::Global, - base::MillisecondsWidth(static_cast(getULong(conf->value()))), &m_millisecondsWidthMap); - } - else if (conf->configurationType() == ConfigurationType::PerformanceTracking) { - setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap); - } - else if (conf->configurationType() == ConfigurationType::MaxLogFileSize) { - setValue(conf->level(), static_cast(getULong(conf->value())), &m_maxLogFileSizeMap); -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) - withFileSizeLimit.push_back(conf); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) - } - else if (conf->configurationType() == ConfigurationType::LogFlushThreshold) { - setValue(conf->level(), static_cast(getULong(conf->value())), &m_logFlushThresholdMap); - } - } - // As mentioned early, we will now set filename configuration in separate loop to deal with non-existent files - for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { - Configuration* conf = *it; - if (conf->configurationType() == ConfigurationType::Filename) { - insertFile(conf->level(), conf->value()); - } - } - for (std::vector::iterator conf = withFileSizeLimit.begin(); - conf != withFileSizeLimit.end(); ++conf) { - // This is not unsafe as mutex is locked in currect scope - unsafeValidateFileRolling((*conf)->level(), base::defaultPreRollOutCallback); - } - } - - unsigned long getULong(std::string confVal) { - bool valid = true; - base::utils::Str::trim(confVal); - valid = !confVal.empty() && std::find_if(confVal.begin(), confVal.end(), - [](char c) { return !base::utils::Str::isDigit(c); }) == confVal.end(); - if (!valid) { - valid = false; - ELPP_ASSERT(valid, "Configuration value not a valid integer [" << confVal << "]"); - return 0; - } - return atol(confVal.c_str()); - } - - std::string resolveFilename(const std::string& filename) { - std::string resultingFilename = filename; - std::size_t dateIndex = std::string::npos; - std::string dateTimeFormatSpecifierStr = std::string(base::consts::kDateTimeFormatSpecifierForFilename); - if ((dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str())) != std::string::npos) { - while (dateIndex > 0 && resultingFilename[dateIndex - 1] == base::consts::kFormatSpecifierChar) { - dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(), dateIndex + 1); - } - if (dateIndex != std::string::npos) { - const char* ptr = resultingFilename.c_str() + dateIndex; - // Goto end of specifier - ptr += dateTimeFormatSpecifierStr.size(); - std::string fmt; - if ((resultingFilename.size() > dateIndex) && (ptr[0] == '{')) { - // User has provided format for date/time - ++ptr; - int count = 1; // Start by 1 in order to remove starting brace - std::stringstream ss; - for (; *ptr; ++ptr, ++count) { - if (*ptr == '}') { - ++count; // In order to remove ending brace - break; - } - ss << *ptr; - } - resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(), count); - fmt = ss.str(); - } - else { - fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename); - } - base::MillisecondsWidth msWidth(3); - std::string now = base::utils::DateTime::getDateTime(fmt.c_str(), &msWidth); - base::utils::Str::replaceAll(now, '/', '-'); // Replace path element since we are dealing with filename - base::utils::Str::replaceAll(resultingFilename, dateTimeFormatSpecifierStr, now); - } - } - return resultingFilename; - } - - void insertFile(Level level, const std::string& fullFilename) { - std::string resolvedFilename = resolveFilename(fullFilename); - if (resolvedFilename.empty()) { - std::cerr << "Could not load empty file for logging, please re-check your configurations for level [" - << LevelHelper::convertToString(level) << "]"; - } - std::string filePath = base::utils::File::extractPathFromFilename(resolvedFilename, base::consts::kFilePathSeperator); - if (filePath.size() < resolvedFilename.size()) { - base::utils::File::createPath(filePath); - } - auto create = [&](Level level) { - base::LogStreamsReferenceMap::iterator filestreamIter = m_logStreamsReference->find(resolvedFilename); - base::type::fstream_t* fs = nullptr; - if (filestreamIter == m_logStreamsReference->end()) { - // We need a completely new stream, nothing to share with - fs = base::utils::File::newFileStream(resolvedFilename); - m_filenameMap.insert(std::make_pair(level, resolvedFilename)); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs))); - m_logStreamsReference->insert(std::make_pair(resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level)))); - } - else { - // Woops! we have an existing one, share it! - m_filenameMap.insert(std::make_pair(level, filestreamIter->first)); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(filestreamIter->second))); - fs = filestreamIter->second.get(); - } - if (fs == nullptr) { - // We display bad file error from newFileStream() - ELPP_INTERNAL_ERROR("Setting [TO_FILE] of [" - << LevelHelper::convertToString(level) << "] to FALSE", false); - setValue(level, false, &m_toFileMap); - } - }; - // If we dont have file conf for any level, create it for Level::Global first - // otherwise create for specified level - create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global : level); - } - - bool unsafeValidateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback) { - base::type::fstream_t* fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get(); - if (fs == nullptr) { - return true; - } - std::size_t maxLogFileSize = unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); - std::size_t currFileSize = base::utils::File::getSizeOfFile(fs); - if (maxLogFileSize != 0 && currFileSize >= maxLogFileSize) { - std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename"); - ELPP_INTERNAL_INFO(1, "Truncating log file [" << fname << "] as a result of configurations for level [" - << LevelHelper::convertToString(level) << "]"); - fs->close(); - PreRollOutCallback(fname.c_str(), currFileSize); - fs->open(fname, std::fstream::out | std::fstream::trunc); - return true; - } - return false; - } - - bool validateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback) { - base::threading::ScopedLock scopedLock(lock()); - return unsafeValidateFileRolling(level, PreRollOutCallback); - } - }; - /// @brief Class that keeps record of current line hit for occasional logging - class HitCounter { - public: - HitCounter(void) : - m_filename(""), - m_lineNumber(0), - m_hitCounts(0) { - } - - HitCounter(const char* filename, unsigned long int lineNumber) : - m_filename(filename), - m_lineNumber(lineNumber), - m_hitCounts(0) { - } - - HitCounter(const HitCounter& hitCounter) : - m_filename(hitCounter.m_filename), - m_lineNumber(hitCounter.m_lineNumber), - m_hitCounts(hitCounter.m_hitCounts) { - } - - HitCounter& operator=(const HitCounter& hitCounter) { - m_filename = hitCounter.m_filename; - m_lineNumber = hitCounter.m_lineNumber; - m_hitCounts = hitCounter.m_hitCounts; - return *this; - } - - virtual ~HitCounter(void) { - } - - /// @brief Resets location of current hit counter - inline void resetLocation(const char* filename, unsigned long int lineNumber) { - m_filename = filename; - m_lineNumber = lineNumber; - } - - /// @brief Validates hit counts and resets it if necessary - inline void validateHitCounts(std::size_t n) { - if (m_hitCounts >= base::consts::kMaxLogPerCounter) { - m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); - } - ++m_hitCounts; - } - - inline const char* filename(void) const { - return m_filename; - } - - inline unsigned long int lineNumber(void) const { - return m_lineNumber; - } - - inline std::size_t hitCounts(void) const { - return m_hitCounts; - } - - inline void increment(void) { - ++m_hitCounts; - } - - class Predicate { - public: - Predicate(const char* filename, unsigned long int lineNumber) - : m_filename(filename), - m_lineNumber(lineNumber) { - } - inline bool operator()(const HitCounter* counter) { - return ((counter != nullptr) && - (strcmp(counter->m_filename, m_filename) == 0) && - (counter->m_lineNumber == m_lineNumber)); - } - - private: - const char* m_filename; - unsigned long int m_lineNumber; - }; - - private: - const char* m_filename; - unsigned long int m_lineNumber; - std::size_t m_hitCounts; - }; - /// @brief Repository for hit counters used across the application - class RegisteredHitCounters : public base::utils::RegistryWithPred { - public: - /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateEveryN(const char* filename, unsigned long int lineNumber, std::size_t n) { - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter* counter = get(filename, lineNumber); - if (counter == nullptr) { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - counter->validateHitCounts(n); - bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0); - return result; - } - - /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateAfterN(const char* filename, unsigned long int lineNumber, std::size_t n) { - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter* counter = get(filename, lineNumber); - if (counter == nullptr) { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - // Do not use validateHitCounts here since we do not want to reset counter here - // Note the >= instead of > because we are incrementing - // after this check - if (counter->hitCounts() >= n) - return true; - counter->increment(); - return false; - } - - /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateNTimes(const char* filename, unsigned long int lineNumber, std::size_t n) { - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter* counter = get(filename, lineNumber); - if (counter == nullptr) { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - counter->increment(); - // Do not use validateHitCounts here since we do not want to reset counter here - if (counter->hitCounts() <= n) - return true; - return false; - } - - /// @brief Gets hit counter registered at specified position - inline const base::HitCounter* getCounter(const char* filename, unsigned long int lineNumber) { - base::threading::ScopedLock scopedLock(lock()); - return get(filename, lineNumber); - } - }; - /// @brief Action to be taken for dispatching - enum class DispatchAction : base::type::EnumType { - None = 1, NormalLog = 2, SysLog = 4 - }; - } // namespace base - template - class Callback : protected base::threading::ThreadSafe { - public: - Callback(void) : m_enabled(true) {} - inline bool enabled(void) const { return m_enabled; } - inline void setEnabled(bool enabled) { - base::threading::ScopedLock scopedLock(lock()); - m_enabled = enabled; - } - protected: - virtual void handle(const T* handlePtr) = 0; - private: - bool m_enabled; - }; - class LogDispatchData { - public: - LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None) {} - inline const LogMessage* logMessage(void) const { return m_logMessage; } - inline base::DispatchAction dispatchAction(void) const { return m_dispatchAction; } - private: - LogMessage* m_logMessage; - base::DispatchAction m_dispatchAction; - friend class base::LogDispatcher; - - inline void setLogMessage(LogMessage* logMessage) { m_logMessage = logMessage; } - inline void setDispatchAction(base::DispatchAction dispatchAction) { m_dispatchAction = dispatchAction; } - }; - class LogDispatchCallback : public Callback { - private: - friend class base::LogDispatcher; - }; - class PerformanceTrackingCallback : public Callback { - private: - friend class base::PerformanceTracker; - }; - class LogBuilder : base::NoCopy { - public: - virtual ~LogBuilder(void) { ELPP_INTERNAL_INFO(3, "Destroying log builder...") } - virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0; - void convertToColoredOutput(base::type::string_t* logLine, Level level) { - if (!base::utils::s_termSupportsColor) return; - const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m"); - if (level == Level::Error || level == Level::Fatal) - *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor; - else if (level == Level::Warning) - *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor; - } - private: - friend class el::base::DefaultLogDispatchCallback; - }; - typedef std::shared_ptr LogBuilderPtr; - /// @brief Represents a logger holding ID and configurations we need to write logs - /// - /// @detail This class does not write logs itself instead its used by writer to read configuations from. - class Logger : public base::threading::ThreadSafe, public Loggable { - public: - Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference) : - m_id(id), - m_typedConfigurations(nullptr), - m_parentApplicationName(std::string()), - m_isConfigured(false), - m_logStreamsReference(logStreamsReference) { - initUnflushedCount(); - } - - Logger(const std::string& id, const Configurations& configurations, base::LogStreamsReferenceMap* logStreamsReference) : - m_id(id), - m_typedConfigurations(nullptr), - m_parentApplicationName(std::string()), - m_isConfigured(false), - m_logStreamsReference(logStreamsReference) { - initUnflushedCount(); - configure(configurations); - } - - Logger(const Logger& logger) { - base::utils::safeDelete(m_typedConfigurations); - m_id = logger.m_id; - m_typedConfigurations = logger.m_typedConfigurations; - m_parentApplicationName = logger.m_parentApplicationName; - m_isConfigured = logger.m_isConfigured; - m_configurations = logger.m_configurations; - m_unflushedCount = logger.m_unflushedCount; - m_logStreamsReference = logger.m_logStreamsReference; - } - - Logger& operator=(const Logger& logger) { - base::utils::safeDelete(m_typedConfigurations); - m_id = logger.m_id; - m_typedConfigurations = logger.m_typedConfigurations; - m_parentApplicationName = logger.m_parentApplicationName; - m_isConfigured = logger.m_isConfigured; - m_configurations = logger.m_configurations; - m_unflushedCount = logger.m_unflushedCount; - m_logStreamsReference = logger.m_logStreamsReference; - return *this; - } - - virtual ~Logger(void) { - base::utils::safeDelete(m_typedConfigurations); - } - - virtual inline void log(el::base::type::ostream_t& os) const { - os << m_id.c_str(); - } - - /// @brief Configures the logger using specified configurations. - void configure(const Configurations& configurations) { - m_isConfigured = false; // we set it to false in case if we fail - initUnflushedCount(); - if (m_typedConfigurations != nullptr) { - Configurations* c = const_cast(m_typedConfigurations->configurations()); - if (c->hasConfiguration(Level::Global, ConfigurationType::Filename)) { - // This check is definitely needed for cases like ELPP_NO_DEFAULT_LOG_FILE - flush(); - } - } - base::threading::ScopedLock scopedLock(lock()); - if (m_configurations != configurations) { - m_configurations.setFromBase(const_cast(&configurations)); - } - base::utils::safeDelete(m_typedConfigurations); - m_typedConfigurations = new base::TypedConfigurations(&m_configurations, m_logStreamsReference); - resolveLoggerFormatSpec(); - m_isConfigured = true; - } - - /// @brief Reconfigures logger using existing configurations - inline void reconfigure(void) { - ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]"); - configure(m_configurations); - } - - inline const std::string& id(void) const { - return m_id; - } - - inline const std::string& parentApplicationName(void) const { - return m_parentApplicationName; - } - - inline void setParentApplicationName(const std::string& parentApplicationName) { - m_parentApplicationName = parentApplicationName; - } - - inline Configurations* configurations(void) { - return &m_configurations; - } - - inline base::TypedConfigurations* typedConfigurations(void) { - return m_typedConfigurations; - } - - static inline bool isValidId(const std::string& id) { - for (std::string::const_iterator it = id.begin(); it != id.end(); ++it) { - if (!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it)) { - return false; - } - } - return true; - } - /// @brief Flushes logger to sync all log files for all levels - inline void flush(void) { - ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels"); - base::threading::ScopedLock scopedLock(lock()); - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - flush(LevelHelper::castFromInt(lIndex), nullptr); - return false; - }); - } - - inline void flush(Level level, base::type::fstream_t* fs) { - if (fs == nullptr && m_typedConfigurations->toFile(level)) { - fs = m_typedConfigurations->fileStream(level); - } - if (fs != nullptr) { - fs->flush(); - m_unflushedCount.find(level)->second = 0; - } - } - - inline bool isFlushNeeded(Level level) { - return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level); - } - - inline LogBuilder* logBuilder(void) const { - return m_logBuilder.get(); - } - - inline void setLogBuilder(const LogBuilderPtr& logBuilder) { - m_logBuilder = logBuilder; - } - - inline bool enabled(Level level) const { - return m_typedConfigurations->enabled(level); - } - -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -# define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME)\ - template \ - inline void FUNCTION_NAME(const char*, const T&, const Args&...);\ - template \ - inline void FUNCTION_NAME(const T&); - - template - inline void verbose(int, const char*, const T&, const Args&...); - - template - inline void verbose(int, const T&); - - LOGGER_LEVEL_WRITERS_SIGNATURES(info) - LOGGER_LEVEL_WRITERS_SIGNATURES(debug) - LOGGER_LEVEL_WRITERS_SIGNATURES(warn) - LOGGER_LEVEL_WRITERS_SIGNATURES(error) - LOGGER_LEVEL_WRITERS_SIGNATURES(fatal) - LOGGER_LEVEL_WRITERS_SIGNATURES(trace) -# undef LOGGER_LEVEL_WRITERS_SIGNATURES -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED - private: - std::string m_id; - base::TypedConfigurations* m_typedConfigurations; - base::type::stringstream_t m_stream; - std::string m_parentApplicationName; - bool m_isConfigured; - Configurations m_configurations; - std::map m_unflushedCount; - base::LogStreamsReferenceMap* m_logStreamsReference; - LogBuilderPtr m_logBuilder; - - friend class el::LogMessage; - friend class el::Loggers; - friend class el::Helpers; - friend class el::base::RegisteredLoggers; - friend class el::base::DefaultLogDispatchCallback; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::PErrorWriter; - friend class el::base::Storage; - friend class el::base::PerformanceTracker; - friend class el::base::LogDispatcher; - - Logger(void); - -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED - template - void log_(Level, int, const char*, const T&, const Args&...); - - template - inline void log_(Level, int, const T&); - - template - void log(Level, const char*, const T&, const Args&...); - - template - inline void log(Level, const T&); -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED - - void initUnflushedCount(void) { - m_unflushedCount.clear(); - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - m_unflushedCount.insert(std::make_pair(LevelHelper::castFromInt(lIndex), 0)); - return false; - }); - } - - inline base::type::stringstream_t& stream(void) { - return m_stream; - } - - void resolveLoggerFormatSpec(void) const { - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - base::LogFormat* logFormat = - const_cast(&m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex))); - base::utils::Str::replaceFirstWithEscape(logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id); - return false; - }); - } - }; - namespace base { - /// @brief Loggers repository - class RegisteredLoggers : public base::utils::Registry { - public: - explicit RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder) : - m_defaultLogBuilder(defaultLogBuilder) { - m_defaultConfigurations.setToDefault(); - } - - virtual ~RegisteredLoggers(void) { - flushAll(); - } - - inline void setDefaultConfigurations(const Configurations& configurations) { - base::threading::ScopedLock scopedLock(lock()); - m_defaultConfigurations.setFromBase(const_cast(&configurations)); - } - - inline Configurations* defaultConfigurations(void) { - return &m_defaultConfigurations; - } - - Logger* get(const std::string& id, bool forceCreation = true) { - base::threading::ScopedLock scopedLock(lock()); - Logger* logger_ = base::utils::Registry::get(id); - if (logger_ == nullptr && forceCreation) { - bool validId = Logger::isValidId(id); - if (!validId) { - ELPP_ASSERT(validId, "Invalid logger ID [" << id << "]. Not registering this logger."); - return nullptr; - } - logger_ = new Logger(id, m_defaultConfigurations, &m_logStreamsReference); - logger_->m_logBuilder = m_defaultLogBuilder; - registerNew(id, logger_); - } - return logger_; - } - - bool remove(const std::string& id) { - if (id == "default") { - return false; - } - Logger* logger = base::utils::Registry::get(id); - if (logger != nullptr) { - unregister(logger); - } - return true; - } - - inline bool has(const std::string& id) { - return get(id, false) != nullptr; - } - - inline void unregister(Logger*& logger) { - base::threading::ScopedLock scopedLock(lock()); - base::utils::Registry::unregister(logger->id()); - } - - inline base::LogStreamsReferenceMap* logStreamsReference(void) { - return &m_logStreamsReference; - } - - inline void flushAll(void) { - ELPP_INTERNAL_INFO(1, "Flushing all log files"); - base::threading::ScopedLock scopedLock(lock()); - for (base::LogStreamsReferenceMap::iterator it = m_logStreamsReference.begin(); - it != m_logStreamsReference.end(); ++it) { - if (it->second.get() == nullptr) continue; - it->second->flush(); - } - } - - private: - LogBuilderPtr m_defaultLogBuilder; - Configurations m_defaultConfigurations; - base::LogStreamsReferenceMap m_logStreamsReference; - friend class el::base::Storage; - }; - /// @brief Represents registries for verbose logging - class VRegistry : base::NoCopy, public base::threading::ThreadSafe { - public: - explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags) : m_level(level), m_pFlags(pFlags) { - } - - /// @brief Sets verbose level. Accepted range is 0-9 - inline void setLevel(base::type::VerboseLevel level) { - base::threading::ScopedLock scopedLock(lock()); - if (level < 0) - m_level = 0; - else if (level > 9) - m_level = base::consts::kMaxVerboseLevel; - else - m_level = level; - } - - inline base::type::VerboseLevel level(void) const { - return m_level; - } - - inline void clearModules(void) { - base::threading::ScopedLock scopedLock(lock()); - m_modules.clear(); - } - - void setModules(const char* modules) { - base::threading::ScopedLock scopedLock(lock()); - auto addSuffix = [](std::stringstream& ss, const char* sfx, const char* prev) { - if (prev != nullptr && base::utils::Str::endsWith(ss.str(), std::string(prev))) { - std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev))); - ss.str(std::string("")); - ss << chr; - } - if (base::utils::Str::endsWith(ss.str(), std::string(sfx))) { - std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx))); - ss.str(std::string("")); - ss << chr; - } - ss << sfx; - }; - auto insert = [&](std::stringstream& ss, base::type::VerboseLevel level) { - if (!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions, *m_pFlags)) { - addSuffix(ss, ".h", nullptr); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".c", ".h"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cpp", ".c"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cc", ".cpp"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cxx", ".cc"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".-inl.h", ".cxx"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hxx", ".-inl.h"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hpp", ".hxx"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hh", ".hpp"); - } - m_modules.insert(std::make_pair(ss.str(), level)); - }; - bool isMod = true; - bool isLevel = false; - std::stringstream ss; - int level = -1; - for (; *modules; ++modules) { - switch (*modules) { - case '=': - isLevel = true; - isMod = false; - break; - case ',': - isLevel = false; - isMod = true; - if (!ss.str().empty() && level != -1) { - insert(ss, level); - ss.str(std::string("")); - level = -1; - } - break; - default: - if (isMod) { - ss << *modules; - } - else if (isLevel) { - if (isdigit(*modules)) { - level = static_cast(*modules) - 48; - } - } - break; - } - } - if (!ss.str().empty() && level != -1) { - insert(ss, level); - } - } - - bool allowed(base::type::VerboseLevel vlevel, const char* file) { - base::threading::ScopedLock scopedLock(lock()); - if (m_modules.empty() || file == nullptr) { - return vlevel <= m_level; - } - else { - std::map::iterator it = m_modules.begin(); - for (; it != m_modules.end(); ++it) { - if (base::utils::Str::wildCardMatch(file, it->first.c_str())) { - return vlevel <= it->second; - } - } - if (base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified, *m_pFlags)) { - return true; - } - return false; - } - } - - inline const std::map& modules(void) const { - return m_modules; - } - - void setFromArgs(const base::utils::CommandLineArgs* commandLineArgs) { - if (commandLineArgs->hasParam("-v") || commandLineArgs->hasParam("--verbose") || - commandLineArgs->hasParam("-V") || commandLineArgs->hasParam("--VERBOSE")) { - setLevel(base::consts::kMaxVerboseLevel); - } - else if (commandLineArgs->hasParamWithValue("--v")) { - setLevel(atoi(commandLineArgs->getParamValue("--v"))); - } - else if (commandLineArgs->hasParamWithValue("--V")) { - setLevel(atoi(commandLineArgs->getParamValue("--V"))); - } - else if ((commandLineArgs->hasParamWithValue("-vmodule")) && vModulesEnabled()) { - setModules(commandLineArgs->getParamValue("-vmodule")); - } - else if (commandLineArgs->hasParamWithValue("-VMODULE") && vModulesEnabled()) { - setModules(commandLineArgs->getParamValue("-VMODULE")); - } - } - - /// @brief Whether or not vModules enabled - inline bool vModulesEnabled(void) { - return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags); - } - - private: - base::type::VerboseLevel m_level; - base::type::EnumType* m_pFlags; - std::map m_modules; - }; - } // namespace base - class LogMessage { - public: - LogMessage(Level level, const std::string& file, unsigned long int line, const std::string& func, - base::type::VerboseLevel verboseLevel, Logger* logger) : - m_level(level), m_file(file), m_line(line), m_func(func), - m_verboseLevel(verboseLevel), m_logger(logger), m_message(std::move(logger->stream().str())) { - } - inline Level level(void) const { return m_level; } - inline const std::string& file(void) const { return m_file; } - inline unsigned long int line(void) const { return m_line; } // NOLINT - inline const std::string& func(void) const { return m_func; } - inline base::type::VerboseLevel verboseLevel(void) const { return m_verboseLevel; } - inline Logger* logger(void) const { return m_logger; } - inline const base::type::string_t& message(void) const { return m_message; } - private: - Level m_level; - std::string m_file; - unsigned long int m_line; - std::string m_func; - base::type::VerboseLevel m_verboseLevel; - Logger* m_logger; - base::type::string_t m_message; - }; - namespace base { -#if ELPP_ASYNC_LOGGING - class AsyncLogItem { - public: - explicit AsyncLogItem(const LogMessage& logMessage, const LogDispatchData& data, const base::type::string_t& logLine) - : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine) {} - virtual ~AsyncLogItem() {} - inline LogMessage* logMessage(void) { return &m_logMessage; } - inline LogDispatchData* data(void) { return &m_dispatchData; } - inline base::type::string_t logLine(void) { return m_logLine; } - private: - LogMessage m_logMessage; - LogDispatchData m_dispatchData; - base::type::string_t m_logLine; - }; - class AsyncLogQueue : public base::threading::ThreadSafe { - public: - virtual ~AsyncLogQueue() { - ELPP_INTERNAL_INFO(6, "~AsyncLogQueue"); - } - - inline AsyncLogItem next(void) { - base::threading::ScopedLock scopedLock(lock()); - AsyncLogItem result = m_queue.front(); - m_queue.pop(); - return result; - } - - inline void push(const AsyncLogItem& item) { - base::threading::ScopedLock scopedLock(lock()); - m_queue.push(item); - } - inline void pop(void) { - base::threading::ScopedLock scopedLock(lock()); - m_queue.pop(); - } - inline AsyncLogItem front(void) { - base::threading::ScopedLock scopedLock(lock()); - return m_queue.front(); - } - inline bool empty(void) { - base::threading::ScopedLock scopedLock(lock()); - return m_queue.empty(); - } - private: - std::queue m_queue; - }; - class IWorker { - public: - virtual ~IWorker() {} - virtual void start() = 0; - }; -#endif // ELPP_ASYNC_LOGGING - /// @brief Easylogging++ management storage - class Storage : base::NoCopy, public base::threading::ThreadSafe { - public: -#if ELPP_ASYNC_LOGGING - Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : -#else - explicit Storage(const LogBuilderPtr& defaultLogBuilder) : -#endif // ELPP_ASYNC_LOGGING - m_registeredHitCounters(new base::RegisteredHitCounters()), - m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)), - m_flags(0x0), - m_vRegistry(new base::VRegistry(0, &m_flags)), -#if ELPP_ASYNC_LOGGING - m_asyncLogQueue(new base::AsyncLogQueue()), - m_asyncDispatchWorker(asyncDispatchWorker), -#endif // ELPP_ASYNC_LOGGING - m_preRollOutCallback(base::defaultPreRollOutCallback) { - // Register default logger - m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId)); - // Register performance logger and reconfigure format - Logger* performanceLogger = m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId)); - performanceLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%datetime %level %msg")); - performanceLogger->reconfigure(); -#if defined(ELPP_SYSLOG) - // Register syslog logger and reconfigure format - Logger* sysLogLogger = m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId)); - sysLogLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%level: %msg")); - sysLogLogger->reconfigure(); -#else - ELPP_UNUSED(base::consts::kSysLogLoggerId); -#endif // defined(ELPP_SYSLOG) - addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified); -#if ELPP_ASYNC_LOGGING - installLogDispatchCallback(std::string("AsyncLogDispatchCallback")); -#else - installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); -#endif // ELPP_ASYNC_LOGGING - installPerformanceTrackingCallback(std::string("DefaultPerformanceTrackingCallback")); - ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized"); -#if ELPP_ASYNC_LOGGING - m_asyncDispatchWorker->start(); -#endif // ELPP_ASYNC_LOGGING - } - - virtual ~Storage(void) { - ELPP_INTERNAL_INFO(4, "Destroying storage"); -#if ELPP_ASYNC_LOGGING - ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous"); - uninstallLogDispatchCallback(std::string("AsyncLogDispatchCallback")); - installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); - ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker"); - base::utils::safeDelete(m_asyncDispatchWorker); - ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue"); - base::utils::safeDelete(m_asyncLogQueue); -#endif // ELPP_ASYNC_LOGGING - ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters"); - base::utils::safeDelete(m_registeredHitCounters); - ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers"); - base::utils::safeDelete(m_registeredLoggers); - ELPP_INTERNAL_INFO(5, "Destroying vRegistry"); - base::utils::safeDelete(m_vRegistry); - } - - inline bool validateEveryNCounter(const char* filename, unsigned long int lineNumber, std::size_t occasion) { - return hitCounters()->validateEveryN(filename, lineNumber, occasion); - } - - inline bool validateAfterNCounter(const char* filename, unsigned long int lineNumber, std::size_t n) { // NOLINT - return hitCounters()->validateAfterN(filename, lineNumber, n); - } - - inline bool validateNTimesCounter(const char* filename, unsigned long int lineNumber, std::size_t n) { // NOLINT - return hitCounters()->validateNTimes(filename, lineNumber, n); - } - - inline base::RegisteredHitCounters* hitCounters(void) const { - return m_registeredHitCounters; - } - - inline base::RegisteredLoggers* registeredLoggers(void) const { - return m_registeredLoggers; - } - - inline base::VRegistry* vRegistry(void) const { - return m_vRegistry; - } - -#if ELPP_ASYNC_LOGGING - inline base::AsyncLogQueue* asyncLogQueue(void) const { - return m_asyncLogQueue; - } -#endif // ELPP_ASYNC_LOGGING - - inline const base::utils::CommandLineArgs* commandLineArgs(void) const { - return &m_commandLineArgs; - } - - inline void addFlag(LoggingFlag flag) { - base::utils::addFlag(flag, &m_flags); - } - - inline void removeFlag(LoggingFlag flag) { - base::utils::removeFlag(flag, &m_flags); - } - - inline bool hasFlag(LoggingFlag flag) const { - return base::utils::hasFlag(flag, m_flags); - } - - inline base::type::EnumType flags(void) const { - return m_flags; - } - - inline void setFlags(base::type::EnumType flags) { - m_flags = flags; - } - - inline void setPreRollOutCallback(const PreRollOutCallback& callback) { - m_preRollOutCallback = callback; - } - - inline void unsetPreRollOutCallback(void) { - m_preRollOutCallback = base::defaultPreRollOutCallback; - } - - inline PreRollOutCallback& preRollOutCallback(void) { - return m_preRollOutCallback; - } - - inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { - base::threading::ScopedLock scopedLock(lock()); - return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), - formatSpecifier) != m_customFormatSpecifiers.end(); - } - - inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { - if (hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) { - return; - } - base::threading::ScopedLock scopedLock(lock()); - m_customFormatSpecifiers.push_back(customFormatSpecifier); - } - - inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { - base::threading::ScopedLock scopedLock(lock()); - std::vector::iterator it = std::find(m_customFormatSpecifiers.begin(), - m_customFormatSpecifiers.end(), formatSpecifier); - if (it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0) { - m_customFormatSpecifiers.erase(it); - return true; - } - return false; - } - - const std::vector* customFormatSpecifiers(void) const { - return &m_customFormatSpecifiers; - } - - inline void setLoggingLevel(Level level) { - m_loggingLevel = level; - } - - template - inline bool installLogDispatchCallback(const std::string& id) { - return installCallback(id, &m_logDispatchCallbacks); - } - - template - inline void uninstallLogDispatchCallback(const std::string& id) { - uninstallCallback(id, &m_logDispatchCallbacks); - } - template - inline T* logDispatchCallback(const std::string& id) { - return callback(id, &m_logDispatchCallbacks); - } - - template - inline bool installPerformanceTrackingCallback(const std::string& id) { - return installCallback(id, &m_performanceTrackingCallbacks); - } - - template - inline void uninstallPerformanceTrackingCallback(const std::string& id) { - uninstallCallback(id, &m_performanceTrackingCallbacks); - } - - template - inline T* performanceTrackingCallback(const std::string& id) { - return callback(id, &m_performanceTrackingCallbacks); - } - private: - base::RegisteredHitCounters* m_registeredHitCounters; - base::RegisteredLoggers* m_registeredLoggers; - base::type::EnumType m_flags; - base::VRegistry* m_vRegistry; -#if ELPP_ASYNC_LOGGING - base::AsyncLogQueue* m_asyncLogQueue; - base::IWorker* m_asyncDispatchWorker; -#endif // ELPP_ASYNC_LOGGING - base::utils::CommandLineArgs m_commandLineArgs; - PreRollOutCallback m_preRollOutCallback; - std::map m_logDispatchCallbacks; - std::map m_performanceTrackingCallbacks; - std::vector m_customFormatSpecifiers; - Level m_loggingLevel; - - friend class el::Helpers; - friend class el::base::DefaultLogDispatchCallback; - friend class el::LogBuilder; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::PerformanceTracker; - friend class el::base::LogDispatcher; - - void setApplicationArguments(int argc, char** argv) { - m_commandLineArgs.setArgs(argc, argv); - m_vRegistry->setFromArgs(commandLineArgs()); - // default log file -#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) - if (m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam)) { - Configurations c; - c.setGlobally(ConfigurationType::Filename, std::string(m_commandLineArgs.getParamValue(base::consts::kDefaultLogFileParam))); - registeredLoggers()->setDefaultConfigurations(c); - for (base::RegisteredLoggers::iterator it = registeredLoggers()->begin(); - it != registeredLoggers()->end(); ++it) { - it->second->configure(c); - } - } -#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) - if (m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam)) { - m_flags = atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam)); - } -#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) - } - - inline void setApplicationArguments(int argc, const char** argv) { - setApplicationArguments(argc, const_cast(argv)); - } - - template - inline bool installCallback(const std::string& id, std::map* mapT) { - if (mapT->find(id) == mapT->end()) { - mapT->insert(std::make_pair(id, TPtr(new T()))); - return true; - } - return false; - } - - template - inline void uninstallCallback(const std::string& id, std::map* mapT) { - if (mapT->find(id) != mapT->end()) { - mapT->erase(id); - } - } - - template - inline T* callback(const std::string& id, std::map* mapT) { - typename std::map::iterator iter = mapT->find(id); - if (iter != mapT->end()) { - return static_cast(iter->second.get()); - } - return nullptr; - } - }; - extern ELPP_EXPORT base::type::StoragePointer elStorage; -#define ELPP el::base::elStorage - class DefaultLogDispatchCallback : public LogDispatchCallback { - protected: - void handle(const LogDispatchData* data) { - m_data = data; - dispatch(std::move(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(), - m_data->dispatchAction() == base::DispatchAction::NormalLog))); - } - private: - const LogDispatchData* m_data; - void dispatch(base::type::string_t&& logLine) { - if (m_data->dispatchAction() == base::DispatchAction::NormalLog) { - if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) { - base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream(m_data->logMessage()->level()); - if (fs != nullptr) { - fs->write(logLine.c_str(), logLine.size()); - if (fs->fail()) { - ELPP_INTERNAL_ERROR("Unable to write log to file [" - << m_data->logMessage()->logger()->m_typedConfigurations->filename(m_data->logMessage()->level()) << "].\n" - << "Few possible reasons (could be something else):\n" << " * Permission denied\n" - << " * Disk full\n" << " * Disk is not writable", true); - } - else { - if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (m_data->logMessage()->logger()->isFlushNeeded(m_data->logMessage()->level()))) { - m_data->logMessage()->logger()->flush(m_data->logMessage()->level(), fs); - } - } - } - else { - ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(m_data->logMessage()->level()) << "] " - << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " - << m_data->logMessage()->logger()->id() << "]", false); - } - } - if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) { - if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) - m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level()); - ELPP_COUT << ELPP_COUT_LINE(logLine); - } - } -#if defined(ELPP_SYSLOG) - else if (m_data->dispatchAction() == base::DispatchAction::SysLog) { - // Determine syslog priority - int sysLogPriority = 0; - if (m_data->logMessage()->level() == Level::Fatal) - sysLogPriority = LOG_EMERG; - else if (m_data->logMessage()->level() == Level::Error) - sysLogPriority = LOG_ERR; - else if (m_data->logMessage()->level() == Level::Warning) - sysLogPriority = LOG_WARNING; - else if (m_data->logMessage()->level() == Level::Info) - sysLogPriority = LOG_INFO; - else if (m_data->logMessage()->level() == Level::Debug) - sysLogPriority = LOG_DEBUG; - else - sysLogPriority = LOG_NOTICE; -# if defined(ELPP_UNICODE) - char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); - syslog(sysLogPriority, "%s", line); - free(line); -# else - syslog(sysLogPriority, "%s", logLine.c_str()); -# endif - } -#endif // defined(ELPP_SYSLOG) - } - }; -#if ELPP_ASYNC_LOGGING - class AsyncLogDispatchCallback : public LogDispatchCallback { - protected: - void handle(const LogDispatchData* data) { - base::type::string_t logLine = data->logMessage()->logger()->logBuilder()->build(data->logMessage(), data->dispatchAction() == base::DispatchAction::NormalLog); - if (data->dispatchAction() == base::DispatchAction::NormalLog && data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) { - if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) - data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level()); - ELPP_COUT << ELPP_COUT_LINE(logLine); - } - // Save resources and only queue if we want to write to file otherwise just ignore handler - if (data->logMessage()->logger()->typedConfigurations()->toFile(data->logMessage()->level())) { - ELPP->asyncLogQueue()->push(AsyncLogItem(*(data->logMessage()), *data, logLine)); - } - } - }; - class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe { - public: - AsyncDispatchWorker() { - setContinueRunning(false); - } - - virtual ~AsyncDispatchWorker() { - setContinueRunning(false); - ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue"); - clean(); - ELPP_INTERNAL_INFO(6, "Log queue cleaned"); - } - - inline bool clean() { - std::mutex m; - std::unique_lock lk(m); - cv.wait(lk, [] { return !ELPP->asyncLogQueue()->empty(); }); - emptyQueue(); - lk.unlock(); - cv.notify_one(); - return ELPP->asyncLogQueue()->empty(); - } - - inline void emptyQueue() { - while (!ELPP->asyncLogQueue()->empty()) { - AsyncLogItem data = ELPP->asyncLogQueue()->next(); - handle(&data); - base::threading::msleep(100); - } - } - - virtual inline void start() { - base::threading::msleep(5000); // Wait extra few seconds - setContinueRunning(true); - std::thread t1(&AsyncDispatchWorker::runner, this); - t1.join(); - } - - void handle(AsyncLogItem* logItem) { - LogDispatchData* data = logItem->data(); - LogMessage* logMessage = logItem->logMessage(); - Logger* logger = logMessage->logger(); - base::TypedConfigurations* conf = logger->typedConfigurations(); - base::type::string_t logLine = logItem->logLine(); - if (data->dispatchAction() == base::DispatchAction::NormalLog) { - if (conf->toFile(logMessage->level())) { - base::type::fstream_t* fs = conf->fileStream(logMessage->level()); - if (fs != nullptr) { - fs->write(logLine.c_str(), logLine.size()); - if (fs->fail()) { - ELPP_INTERNAL_ERROR("Unable to write log to file [" - << conf->filename(logMessage->level()) << "].\n" - << "Few possible reasons (could be something else):\n" << " * Permission denied\n" - << " * Disk full\n" << " * Disk is not writable", true); - } - else { - if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (logger->isFlushNeeded(logMessage->level()))) { - logger->flush(logMessage->level(), fs); - } - } - } - else { - ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(logMessage->level()) << "] " - << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " << logger->id() << "]", false); - } - } - } -# if defined(ELPP_SYSLOG) - else if (data->dispatchAction() == base::DispatchAction::SysLog) { - // Determine syslog priority - int sysLogPriority = 0; - if (logMessage->level() == Level::Fatal) - sysLogPriority = LOG_EMERG; - else if (logMessage->level() == Level::Error) - sysLogPriority = LOG_ERR; - else if (logMessage->level() == Level::Warning) - sysLogPriority = LOG_WARNING; - else if (logMessage->level() == Level::Info) - sysLogPriority = LOG_INFO; - else if (logMessage->level() == Level::Debug) - sysLogPriority = LOG_DEBUG; - else - sysLogPriority = LOG_NOTICE; -# if defined(ELPP_UNICODE) - char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); - syslog(sysLogPriority, "%s", line); - free(line); -# else - syslog(sysLogPriority, "%s", logLine.c_str()); -# endif - } -# endif // defined(ELPP_SYSLOG) - } - - void run() { - while (continueRunning()) { - emptyQueue(); - base::threading::msleep(10); // 10ms - } - } - - static void* runner(void *context) { - static_cast(context)->run(); - return NULL; - } - - void setContinueRunning(bool value) { - base::threading::ScopedLock scopedLock(m_continueRunningMutex); - m_continueRunning = value; - } - bool continueRunning(void) { - return m_continueRunning; - } - private: - std::condition_variable cv; - bool m_continueRunning; - base::threading::Mutex m_continueRunningMutex; - }; -#endif // ELPP_ASYNC_LOGGING - } // namespace base - namespace base { - class DefaultLogBuilder : public LogBuilder { - public: - base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const { - base::TypedConfigurations* tc = logMessage->logger()->typedConfigurations(); - const base::LogFormat* logFormat = &tc->logFormat(logMessage->level()); - base::type::string_t logLine = logFormat->format(); - char buff[base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength] = ""; - const char* bufLim = buff + sizeof(buff); - if (logFormat->hasFlag(base::FormatFlags::AppName)) { - // App name - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kAppNameFormatSpecifier, - logMessage->logger()->parentApplicationName()); - } - if (logFormat->hasFlag(base::FormatFlags::ThreadId)) { - // Thread ID - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kThreadIdFormatSpecifier, - base::threading::getCurrentThreadId()); - } - if (logFormat->hasFlag(base::FormatFlags::DateTime)) { - // DateTime - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kDateTimeFormatSpecifier, - base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), - &tc->millisecondsWidth(logMessage->level()))); - } - if (logFormat->hasFlag(base::FormatFlags::Function)) { - // Function - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func()); - } - if (logFormat->hasFlag(base::FormatFlags::File)) { - // File - char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); - base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); - buf = base::utils::Str::addToBuff(buff, buf, bufLim); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::FileBase)) { - // FileBase - char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); - base::utils::File::buildBaseFilename(logMessage->file(), buff); - buf = base::utils::Str::addToBuff(buff, buf, bufLim); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::Line)) { - // Line - char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength); - buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), - base::consts::kSourceLineMaxLength, buf, bufLim, false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLineFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::Location)) { - // Location - char* buf = base::utils::Str::clearBuff(buff, - base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength); - base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); - buf = base::utils::Str::addToBuff(buff, buf, bufLim); - buf = base::utils::Str::addToBuff(":", buf, bufLim); - buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), - base::consts::kSourceLineMaxLength, buf, bufLim, false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff)); - } - if (logMessage->level() == Level::Verbose && logFormat->hasFlag(base::FormatFlags::VerboseLevel)) { - // Verbose level - char* buf = base::utils::Str::clearBuff(buff, 1); - buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1, buf, bufLim, false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff)); - } - if (logFormat->hasFlag(base::FormatFlags::LogMessage)) { - // Log message - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message()); - } -#if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) - for (std::vector::const_iterator it = ELPP->customFormatSpecifiers()->begin(); - it != ELPP->customFormatSpecifiers()->end(); ++it) { - std::string fs(it->formatSpecifier()); - base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end()); - base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier, std::string(it->resolver()())); - } -#endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) - if (appendNewLine) logLine += ELPP_LITERAL("\n"); - return logLine; - } - }; - /// @brief Dispatches log messages - class LogDispatcher : base::NoCopy { - public: - LogDispatcher(bool proceed, LogMessage&& logMessage, base::DispatchAction dispatchAction) : - m_proceed(proceed), - m_logMessage(std::move(logMessage)), - m_dispatchAction(std::move(dispatchAction)) { - } - - void dispatch(void) { - if (m_proceed && m_dispatchAction == base::DispatchAction::None) { - m_proceed = false; - } - if (!m_proceed) { - return; - } - // We minimize the time of ELPP's lock - this lock is released after log is written - base::threading::ScopedLock scopedLock(ELPP->lock()); - base::TypedConfigurations* tc = m_logMessage.logger()->m_typedConfigurations; - if (ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) { - tc->validateFileRolling(m_logMessage.level(), ELPP->preRollOutCallback()); - } - LogDispatchCallback* callback = nullptr; - LogDispatchData data; - for (const std::pair& h - : ELPP->m_logDispatchCallbacks) { - callback = h.second.get(); - if (callback != nullptr && callback->enabled()) { - data.setLogMessage(&m_logMessage); - data.setDispatchAction(m_dispatchAction); - callback->acquireLock(); - callback->handle(&data); - callback->releaseLock(); - } - } - } - - private: - bool m_proceed; - LogMessage m_logMessage; - base::DispatchAction m_dispatchAction; - }; -#if defined(ELPP_STL_LOGGING) - /// @brief Workarounds to write some STL logs - /// - /// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers - /// of same type and provide iterator interface and pass it on to writeIterator(). - /// Remember, this is passed by value in constructor so that we dont change original containers. - /// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer)) - namespace workarounds { - /// @brief Abstract IterableContainer template that provides interface for iterable classes of type T - template - class IterableContainer { - public: - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - IterableContainer(void) {} - virtual ~IterableContainer(void) {} - iterator begin(void) { return getContainer().begin(); } - iterator end(void) { return getContainer().end(); } - private: - virtual Container& getContainer(void) = 0; - }; - /// @brief Implements IterableContainer and provides iterable std::priority_queue class - template, typename Comparator = std::less> - class IterablePriorityQueue : public IterableContainer, public std::priority_queue { - public: - IterablePriorityQueue(std::priority_queue queue_) { - std::size_t count_ = 0; - while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { - this->push(queue_.top()); - queue_.pop(); - } - } - private: - inline Container& getContainer(void) { - return this->c; - } - }; - /// @brief Implements IterableContainer and provides iterable std::queue class - template> - class IterableQueue : public IterableContainer, public std::queue { - public: - IterableQueue(std::queue queue_) { - std::size_t count_ = 0; - while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { - this->push(queue_.front()); - queue_.pop(); - } - } - private: - inline Container& getContainer(void) { - return this->c; - } - }; - /// @brief Implements IterableContainer and provides iterable std::stack class - template> - class IterableStack : public IterableContainer, public std::stack { - public: - IterableStack(std::stack stack_) { - std::size_t count_ = 0; - while (++count_ < base::consts::kMaxLogPerContainer && !stack_.empty()) { - this->push(stack_.top()); - stack_.pop(); - } - } - private: - inline Container& getContainer(void) { - return this->c; - } - }; - } // namespace workarounds -#endif // defined(ELPP_STL_LOGGING) - // Log message builder - class MessageBuilder { - public: - MessageBuilder(void) : m_logger(nullptr), m_containerLogSeperator(ELPP_LITERAL("")) {} - void initialize(Logger* logger) { - m_logger = logger; - m_containerLogSeperator = ELPP->hasFlag(LoggingFlag::NewLineForContainer) ? - ELPP_LITERAL("\n ") : ELPP_LITERAL(", "); - } - -# define ELPP_SIMPLE_LOG(LOG_TYPE)\ - inline MessageBuilder& operator<<(LOG_TYPE msg) {\ - m_logger->stream() << msg;\ - if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {\ - m_logger->stream() << " ";\ - }\ - return *this;\ - } - - inline MessageBuilder& operator<<(const std::string& msg) { - return operator<<(msg.c_str()); - } - ELPP_SIMPLE_LOG(char) - ELPP_SIMPLE_LOG(bool) - ELPP_SIMPLE_LOG(signed short) - ELPP_SIMPLE_LOG(unsigned short) - ELPP_SIMPLE_LOG(signed int) - ELPP_SIMPLE_LOG(unsigned int) - ELPP_SIMPLE_LOG(signed long) - ELPP_SIMPLE_LOG(unsigned long) - ELPP_SIMPLE_LOG(float) - ELPP_SIMPLE_LOG(double) - ELPP_SIMPLE_LOG(char*) - ELPP_SIMPLE_LOG(const char*) - ELPP_SIMPLE_LOG(const void*) - ELPP_SIMPLE_LOG(long double) - inline MessageBuilder& operator<<(const std::wstring& msg) { - return operator<<(msg.c_str()); - } - inline MessageBuilder& operator<<(const wchar_t* msg) { - if (msg == nullptr) { - m_logger->stream() << base::consts::kNullPointer; - return *this; - } -# if defined(ELPP_UNICODE) - m_logger->stream() << msg; -# else - char* buff_ = base::utils::Str::wcharPtrToCharPtr(msg); - m_logger->stream() << buff_; - free(buff_); -# endif - if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { - m_logger->stream() << " "; - } - return *this; - } - // ostream manipulators - inline MessageBuilder& operator<<(std::ostream& (*OStreamMani)(std::ostream&)) { - m_logger->stream() << OStreamMani; - return *this; - } -#define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \ - template \ - inline MessageBuilder& operator<<(const temp& template_inst) { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \ - template \ - inline MessageBuilder& operator<<(const temp& template_inst) { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \ - template \ - inline MessageBuilder& operator<<(const temp& template_inst) { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \ - template \ - inline MessageBuilder& operator<<(const temp& template_inst) { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \ - template \ - inline MessageBuilder& operator<<(const temp& template_inst) { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } - -#if defined(ELPP_STL_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap) - template - inline MessageBuilder& operator<<(const std::queue& queue_) { - base::workarounds::IterableQueue iterableQueue_ = - static_cast >(queue_); - return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size()); - } - template - inline MessageBuilder& operator<<(const std::stack& stack_) { - base::workarounds::IterableStack iterableStack_ = - static_cast >(stack_); - return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size()); - } - template - inline MessageBuilder& operator<<(const std::priority_queue& priorityQueue_) { - base::workarounds::IterablePriorityQueue iterablePriorityQueue_ = - static_cast >(priorityQueue_); - return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size()); - } - template - inline MessageBuilder& operator<<(const std::pair& pair_) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(pair_.first)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(pair_.second)); - m_logger->stream() << ELPP_LITERAL(")"); - return *this; - } - template - inline MessageBuilder& operator<<(const std::bitset& bitset_) { - m_logger->stream() << ELPP_LITERAL("["); - operator << (bitset_.to_string()); - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } -# if defined(ELPP_LOG_STD_ARRAY) - template - inline MessageBuilder& operator<<(const std::array& array) { - return writeIterator(array.begin(), array.end(), array.size()); - } -# endif // defined(ELPP_LOG_STD_ARRAY) -# if defined(ELPP_LOG_UNORDERED_MAP) - ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map) - ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap) -# endif // defined(ELPP_LOG_UNORDERED_MAP) -# if defined(ELPP_LOG_UNORDERED_SET) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset) -# endif // defined(ELPP_LOG_UNORDERED_SET) -#endif // defined(ELPP_STL_LOGGING) -#if defined(ELPP_QT_LOGGING) - inline MessageBuilder& operator<<(const QString& msg) { -# if defined(ELPP_UNICODE) - m_logger->stream() << msg.toStdWString(); -# else - m_logger->stream() << msg.toStdString(); -# endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder& operator<<(const QByteArray& msg) { - return operator << (QString(msg)); - } - inline MessageBuilder& operator<<(const QStringRef& msg) { - return operator<<(msg.toString()); - } - inline MessageBuilder& operator<<(qint64 msg) { -# if defined(ELPP_UNICODE) - m_logger->stream() << QString::number(msg).toStdWString(); -# else - m_logger->stream() << QString::number(msg).toStdString(); -# endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder& operator<<(quint64 msg) { -# if defined(ELPP_UNICODE) - m_logger->stream() << QString::number(msg).toStdWString(); -# else - m_logger->stream() << QString::number(msg).toStdString(); -# endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder& operator<<(QChar msg) { - m_logger->stream() << msg.toLatin1(); - return *this; - } - inline MessageBuilder& operator<<(const QLatin1String& msg) { - m_logger->stream() << msg.latin1(); - return *this; - } - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack) - template - inline MessageBuilder& operator<<(const QPair& pair_) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(pair_.first)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(pair_.second)); - m_logger->stream() << ELPP_LITERAL(")"); - return *this; - } - template - inline MessageBuilder& operator<<(const QMap& map_) { - m_logger->stream() << ELPP_LITERAL("["); - QList keys = map_.keys(); - typename QList::const_iterator begin = keys.begin(); - typename QList::const_iterator end = keys.end(); - int max_ = static_cast(base::consts::kMaxLogPerContainer); // to prevent warning - for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(*begin)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(map_.value(*begin))); - m_logger->stream() << ELPP_LITERAL(")"); - m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if (begin != end) { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } - template - inline MessageBuilder& operator<<(const QMultiMap& map_) { - operator << (static_cast>(map_)); - return *this; - } - template - inline MessageBuilder& operator<<(const QHash& hash_) { - m_logger->stream() << ELPP_LITERAL("["); - QList keys = hash_.keys(); - typename QList::const_iterator begin = keys.begin(); - typename QList::const_iterator end = keys.end(); - int max_ = static_cast(base::consts::kMaxLogPerContainer); // prevent type warning - for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { - m_logger->stream() << ELPP_LITERAL("("); - operator << (static_cast(*begin)); - m_logger->stream() << ELPP_LITERAL(", "); - operator << (static_cast(hash_.value(*begin))); - m_logger->stream() << ELPP_LITERAL(")"); - m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if (begin != end) { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } - template - inline MessageBuilder& operator<<(const QMultiHash& multiHash_) { - operator << (static_cast>(multiHash_)); - return *this; - } -#endif // defined(ELPP_QT_LOGGING) -#if defined(ELPP_BOOST_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set) -#endif // defined(ELPP_BOOST_LOGGING) - - /// @brief Macro used internally that can be used externally to make containers easylogging++ friendly - /// - /// @detail This macro expands to write an ostream& operator<< for container. This container is expected to - /// have begin() and end() methods that return respective iterators - /// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets - /// @param SizeMethod Method used to get size of container. - /// @param ElementInstance Instance of element to be fed out. Insance name is "elem". See WXELPP_ENABLED macro - /// for an example usage -#define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \ - el::base::type::ostream_t& operator<<(el::base::type::ostream_t& ss, const ContainerType& container) {\ - const el::base::type::char_t* sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? \ - ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");\ - ContainerType::const_iterator elem = container.begin();\ - ContainerType::const_iterator endElem = container.end();\ - std::size_t size_ = container.SizeMethod; \ - ss << ELPP_LITERAL("[");\ - for (std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) { \ - ss << ElementInstance;\ - ss << ((i < size_ - 1) ? sep : ELPP_LITERAL(""));\ - }\ - if (elem != endElem) {\ - ss << ELPP_LITERAL("...");\ - }\ - ss << ELPP_LITERAL("]");\ - return ss;\ - } -#if defined(ELPP_WXWIDGETS_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector) -# define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem)) -# define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem)) -# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \ - ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")") -#else -# define ELPP_WX_PTR_ENABLED(ContainerType) -# define ELPP_WX_ENABLED(ContainerType) -# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) -#endif // defined(ELPP_WXWIDGETS_LOGGING) - // Other classes - template - ELPP_SIMPLE_LOG(const Class&) -#undef ELPP_SIMPLE_LOG -#undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG - private: - Logger* m_logger; - const base::type::char_t* m_containerLogSeperator; - - template - inline MessageBuilder& writeIterator(Iterator begin_, Iterator end_, std::size_t size_) { - m_logger->stream() << ELPP_LITERAL("["); - for (std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_) { - operator << (*begin_); - m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if (begin_ != end_) { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { - m_logger->stream() << " "; - } - return *this; - } - }; - /// @brief Writes nothing - Used when certain log is disabled - class NullWriter : base::NoCopy { - public: - NullWriter(void) {} - - // Null manipulator - inline NullWriter& operator<<(std::ostream& (*)(std::ostream&)) { - return *this; - } - - template - inline NullWriter& operator<<(const T&) { - return *this; - } - }; - /// @brief Main entry point of each logging - class Writer : base::NoCopy { - public: - Writer(Level level, const char* file, unsigned long int line, - const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, - base::type::VerboseLevel verboseLevel = 0) : - m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), - m_proceed(false), m_dispatchAction(dispatchAction) { - } - - virtual ~Writer(void) { - processDispatch(); - } - - template - inline Writer& operator<<(const T& log) { -#if ELPP_LOGGING_ENABLED - if (m_proceed) { - m_messageBuilder << log; - } -#endif // ELPP_LOGGING_ENABLED - return *this; - } - - inline Writer& operator<<(std::ostream& (*log)(std::ostream&)) { -#if ELPP_LOGGING_ENABLED - if (m_proceed) { - m_messageBuilder << log; - } -#endif // ELPP_LOGGING_ENABLED - return *this; - } - - Writer& construct(Logger* logger, bool needLock = true) { - m_logger = logger; - initializeLogger(logger->id(), false, needLock); - m_messageBuilder.initialize(m_logger); - return *this; - } - - Writer& construct(int count, const char* loggerIds, ...) { - if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { - va_list loggersList; - va_start(loggersList, loggerIds); - const char* id = loggerIds; - for (int i = 0; i < count; ++i) { - m_loggerIds.push_back(std::string(id)); - id = va_arg(loggersList, const char*); - } - va_end(loggersList); - initializeLogger(m_loggerIds.at(0)); - } - else { - initializeLogger(std::string(loggerIds)); - } - m_messageBuilder.initialize(m_logger); - return *this; - } - protected: - Level m_level; - const char* m_file; - const unsigned long int m_line; - const char* m_func; - base::type::VerboseLevel m_verboseLevel; - Logger* m_logger; - bool m_proceed; - base::MessageBuilder m_messageBuilder; - base::DispatchAction m_dispatchAction; - std::vector m_loggerIds; - friend class el::Helpers; - - void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true) { - if (lookup) { - m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); - } - if (m_logger == nullptr) { - ELPP->acquireLock(); - if (!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) { - // Somehow default logger has been unregistered. Not good! Register again - ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); - } - ELPP->releaseLock(); // Need to unlock it for next writer - Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) - << "Logger [" << loggerId << "] is not registered yet!"; - m_proceed = false; - } - else { - if (needLock) { - m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because - // m_proceed can be changed by lines below - } - if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) { - m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) : - LevelHelper::castToInt(m_level) >= LevelHelper::castToInt(ELPP->m_loggingLevel); - } - else { - m_proceed = m_logger->enabled(m_level); - } - } - } - - void processDispatch() { -#if ELPP_LOGGING_ENABLED - if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { - bool firstDispatched = false; - base::type::string_t logMessage; - std::size_t i = 0; - do { - if (m_proceed) { - if (firstDispatched) { - m_logger->stream() << logMessage; - } - else { - firstDispatched = true; - if (m_loggerIds.size() > 1) { - logMessage = m_logger->stream().str(); - } - } - triggerDispatch(); - } - else if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - if (i + 1 < m_loggerIds.size()) { - initializeLogger(m_loggerIds.at(i + 1)); - } - } while (++i < m_loggerIds.size()); - } - else { - if (m_proceed) { - triggerDispatch(); - } - else if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - } -#else - if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } -#endif // ELPP_LOGGING_ENABLED - } - - void triggerDispatch(void) { - if (m_proceed) { - base::LogDispatcher(m_proceed, LogMessage(m_level, m_file, m_line, m_func, m_verboseLevel, - m_logger), m_dispatchAction).dispatch(); - } - if (m_logger != nullptr) { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - if (m_proceed && m_level == Level::Fatal - && !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) { - base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) - << "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]"; - std::stringstream reasonStream; - reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]" - << " If you wish to disable 'abort on fatal log' please use " - << "el::Helpers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; - base::utils::abort(1, reasonStream.str()); - } - m_proceed = false; - } - }; - class PErrorWriter : public base::Writer { - public: - PErrorWriter(Level level, const char* file, unsigned long int line, - const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, - base::type::VerboseLevel verboseLevel = 0) : - base::Writer(level, file, line, func, dispatchAction, verboseLevel) { - } - - virtual ~PErrorWriter(void) { - if (m_proceed) { -#if ELPP_COMPILER_MSVC - char buff[256]; - strerror_s(buff, 256, errno); - m_logger->stream() << ": " << buff << " [" << errno << "]"; -#else - m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]"; -#endif - } - } - }; - } // namespace base - // Logging from Logger class. Why this is here? Because we have Storage and Writer class available -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED - template - void Logger::log_(Level level, int vlevel, const char* s, const T& value, const Args&... args) { - base::MessageBuilder b; - b.initialize(this); - while (*s) { - if (*s == base::consts::kFormatSpecifierChar) { - if (*(s + 1) == base::consts::kFormatSpecifierChar) { - ++s; - } - else { - if (*(s + 1) == base::consts::kFormatSpecifierCharValue) { - ++s; - b << value; - log_(level, vlevel, ++s, args...); - return; - } - } - } - b << *s++; - } - ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false); - } - template - inline void Logger::log_(Level level, int vlevel, const T& log) { - if (level == Level::Verbose) { - if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) { - base::Writer(Level::Verbose, "FILE", 0, "FUNCTION", - base::DispatchAction::NormalLog, vlevel).construct(this, false) << log; - } - else { - stream().str(ELPP_LITERAL("")); - } - } - else { - base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; - } - } - template - void Logger::log(Level level, const char* s, const T& value, const Args&... args) { - base::threading::ScopedLock scopedLock(lock()); - log_(level, 0, s, value, args...); - } - template - inline void Logger::log(Level level, const T& log) { - base::threading::ScopedLock scopedLock(lock()); - log_(level, 0, log); - } -# if ELPP_VERBOSE_LOG - template - inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args) { - base::threading::ScopedLock scopedLock(lock()); - log_(el::Level::Verbose, vlevel, s, value, args...); - } - template - inline void Logger::verbose(int vlevel, const T& log) { - base::threading::ScopedLock scopedLock(lock()); - log_(el::Level::Verbose, vlevel, log); - } -# else - template - inline void Logger::verbose(int, const char*, const T&, const Args&...) { - return; - } - template - inline void Logger::verbose(int, const T&) { - return; - } -# endif // ELPP_VERBOSE_LOG -# define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL)\ - template \ - inline void Logger::FUNCTION_NAME(const char* s, const T& value, const Args&... args) {\ - log(LOG_LEVEL, s, value, args...);\ - }\ - template \ - inline void Logger::FUNCTION_NAME(const T& value) {\ - log(LOG_LEVEL, value);\ - } -# define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL)\ - template \ - inline void Logger::FUNCTION_NAME(const char*, const T&, const Args&...) {\ - return;\ - }\ - template \ - inline void Logger::FUNCTION_NAME(const T&) {\ - return;\ - } - -# if ELPP_INFO_LOG - LOGGER_LEVEL_WRITERS(info, Level::Info) -# else - LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info) -# endif // ELPP_INFO_LOG -# if ELPP_DEBUG_LOG - LOGGER_LEVEL_WRITERS(debug, Level::Debug) -# else - LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug) -# endif // ELPP_DEBUG_LOG -# if ELPP_WARNING_LOG - LOGGER_LEVEL_WRITERS(warn, Level::Warning) -# else - LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning) -# endif // ELPP_WARNING_LOG -# if ELPP_ERROR_LOG - LOGGER_LEVEL_WRITERS(error, Level::Error) -# else - LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error) -# endif // ELPP_ERROR_LOG -# if ELPP_FATAL_LOG - LOGGER_LEVEL_WRITERS(fatal, Level::Fatal) -# else - LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal) -# endif // ELPP_FATAL_LOG -# if ELPP_TRACE_LOG - LOGGER_LEVEL_WRITERS(trace, Level::Trace) -# else - LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace) -# endif // ELPP_TRACE_LOG -# undef LOGGER_LEVEL_WRITERS -# undef LOGGER_LEVEL_WRITERS_DISABLED -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED -#if ELPP_COMPILER_MSVC -# define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs -# define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__)) -# define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ## __VA_ARGS__,\ - 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -#else -# if ELPP_COMPILER_CLANG -# define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -# else -# define el_getVALength(...) el_resolveVALength(0, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -# endif // ELPP_COMPILER_CLANG -#endif // ELPP_COMPILER_MSVC -#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N -#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ - if (ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion)) \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ - if (ELPP->validateAfterNCounter(__FILE__, __LINE__, n)) \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ - if (ELPP->validateNTimesCounter(__FILE__, __LINE__, n)) \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#undef ELPP_CURR_FILE_PERFORMANCE_LOGGER -#if defined(ELPP_PERFORMANCE_LOGGER) -# define ELPP_CURR_FILE_PERFORMANCE_LOGGER ELPP_PERFORMANCE_LOGGER -#else -# define ELPP_CURR_FILE_PERFORMANCE_LOGGER el::base::consts::kPerformanceLoggerId -#endif - class PerformanceTrackingData { - public: - enum class DataType : base::type::EnumType { - Checkpoint = 1, Complete = 2 - }; - // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*) - explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr), - m_dataType(dataType), m_file(""), m_line(0), m_func("") {} - inline const std::string* blockName(void) const; - inline const struct timeval* startTime(void) const; - inline const struct timeval* endTime(void) const; - inline const struct timeval* lastCheckpointTime(void) const; - inline const base::PerformanceTracker* performanceTracker(void) const { return m_performanceTracker; } - inline PerformanceTrackingData::DataType dataType(void) const { return m_dataType; } - inline bool firstCheckpoint(void) const { return m_firstCheckpoint; } - inline std::string checkpointId(void) const { return m_checkpointId; } - inline const char* file(void) const { return m_file; } - inline unsigned long int line(void) const { return m_line; } - inline const char* func(void) const { return m_func; } - inline const base::type::string_t* formattedTimeTaken() const { return &m_formattedTimeTaken; } - inline const std::string& loggerId(void) const; - private: - base::PerformanceTracker* m_performanceTracker; - base::type::string_t m_formattedTimeTaken; - PerformanceTrackingData::DataType m_dataType; - bool m_firstCheckpoint; - std::string m_checkpointId; - const char* m_file; - unsigned long int m_line; - const char* m_func; - inline void init(base::PerformanceTracker* performanceTracker, bool firstCheckpoint = false) { - m_performanceTracker = performanceTracker; - m_firstCheckpoint = firstCheckpoint; - } - - friend class el::base::PerformanceTracker; - }; - namespace base { - /// @brief Represents performanceTracker block of code that conditionally adds performance status to log - /// either when goes outside the scope of when checkpoint() is called - class PerformanceTracker : public base::threading::ThreadSafe, public Loggable { - public: - PerformanceTracker(const std::string& blockName, - base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond, - const std::string& loggerId = std::string(ELPP_CURR_FILE_PERFORMANCE_LOGGER), - bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel) : - m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog), - m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) { -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - // We store it locally so that if user happen to change configuration by the end of scope - // or before calling checkpoint, we still depend on state of configuraton at time of construction - el::Logger* loggerPtr = ELPP->registeredLoggers()->get(loggerId, false); - m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level); - if (m_enabled) { - base::utils::DateTime::gettimeofday(&m_startTime); - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - } - /// @brief Copy constructor - PerformanceTracker(const PerformanceTracker& t) : - m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog), - m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled), - m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime) { - } - virtual ~PerformanceTracker(void) { -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - if (m_enabled) { - base::threading::ScopedLock scopedLock(lock()); - if (m_scopedLog) { - base::utils::DateTime::gettimeofday(&m_endTime); - base::type::string_t formattedTime = getFormattedTimeTaken(); - PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete); - data.init(this); - data.m_formattedTimeTaken = formattedTime; - PerformanceTrackingCallback* callback = nullptr; - for (const std::pair& h - : ELPP->m_performanceTrackingCallbacks) { - callback = h.second.get(); - if (callback != nullptr && callback->enabled()) { - callback->acquireLock(); - callback->handle(&data); - callback->releaseLock(); - } - } - } - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) - } - /// @brief A checkpoint for current performanceTracker block. - void checkpoint(const std::string& id = std::string(), const char* file = __FILE__, unsigned long int line = __LINE__, const char* func = "") { -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - if (m_enabled) { - base::threading::ScopedLock scopedLock(lock()); - base::utils::DateTime::gettimeofday(&m_endTime); - base::type::string_t formattedTime = m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime) : ELPP_LITERAL(""); - PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint); - data.init(this); - data.m_checkpointId = id; - data.m_file = file; - data.m_line = line; - data.m_func = func; - data.m_formattedTimeTaken = formattedTime; - PerformanceTrackingCallback* callback = nullptr; - for (const std::pair& h - : ELPP->m_performanceTrackingCallbacks) { - callback = h.second.get(); - if (callback != nullptr && callback->enabled()) { - callback->acquireLock(); - callback->handle(&data); - callback->releaseLock(); - } - } - base::utils::DateTime::gettimeofday(&m_lastCheckpointTime); - m_hasChecked = true; - m_lastCheckpointId = id; - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - ELPP_UNUSED(id); - ELPP_UNUSED(file); - ELPP_UNUSED(line); - ELPP_UNUSED(func); - } - inline Level level(void) const { return m_level; } - private: - std::string m_blockName; - base::TimestampUnit m_timestampUnit; - std::string m_loggerId; - bool m_scopedLog; - Level m_level; - bool m_hasChecked; - std::string m_lastCheckpointId; - bool m_enabled; - struct timeval m_startTime, m_endTime, m_lastCheckpointTime; - - PerformanceTracker(void); - - friend class el::PerformanceTrackingData; - friend class base::DefaultPerformanceTrackingCallback; - - const inline base::type::string_t getFormattedTimeTaken() const { - return getFormattedTimeTaken(m_startTime); - } - - const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const { - if (ELPP->hasFlag(LoggingFlag::FixedTimeFormat)) { - base::type::stringstream_t ss; - ss << base::utils::DateTime::getTimeDifference(m_endTime, - startTime, m_timestampUnit) << " " << base::consts::kTimeFormats[static_cast(m_timestampUnit)].unit; - return ss.str(); - } - return base::utils::DateTime::formatTime(base::utils::DateTime::getTimeDifference(m_endTime, - startTime, m_timestampUnit), m_timestampUnit); - } - - virtual inline void log(el::base::type::ostream_t& os) const { - os << getFormattedTimeTaken(); - } - }; - class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback { - protected: - void handle(const PerformanceTrackingData* data) { - m_data = data; - base::type::stringstream_t ss; - if (m_data->dataType() == PerformanceTrackingData::DataType::Complete) { - ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << *m_data->formattedTimeTaken() << ELPP_LITERAL("]"); - } - else { - ss << ELPP_LITERAL("Performance checkpoint"); - if (!m_data->checkpointId().empty()) { - ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]"); - } - ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << *m_data->performanceTracker(); - if (!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) && m_data->performanceTracker()->m_hasChecked) { - ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from "); - if (m_data->performanceTracker()->m_lastCheckpointId.empty()) { - ss << ELPP_LITERAL("last checkpoint"); - } - else { - ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'"); - } - ss << ELPP_LITERAL(")]"); - } - else { - ss << ELPP_LITERAL("]"); - } - } - el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, m_data->loggerId().c_str()) << ss.str(); - } - private: - const PerformanceTrackingData* m_data; - }; - } // namespace base - inline const std::string* PerformanceTrackingData::blockName() const { - return const_cast(&m_performanceTracker->m_blockName); - } - inline const struct timeval* PerformanceTrackingData::startTime() const { - return const_cast(&m_performanceTracker->m_startTime); - } - inline const struct timeval* PerformanceTrackingData::endTime() const { - return const_cast(&m_performanceTracker->m_endTime); - } - inline const struct timeval* PerformanceTrackingData::lastCheckpointTime() const { - return const_cast(&m_performanceTracker->m_lastCheckpointTime); - } - inline const std::string& PerformanceTrackingData::loggerId(void) const { return m_performanceTracker->m_loggerId; } - namespace base { - /// @brief Contains some internal debugging tools like crash handler and stack tracer - namespace debug { - class StackTrace : base::NoCopy { - public: - static const std::size_t kMaxStack = 64; - static const std::size_t kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() - class StackTraceEntry { - public: - StackTraceEntry(std::size_t index, const char* loc, const char* demang, const char* hex, const char* addr) { - m_index = index; - m_location = std::string(loc); - m_demangled = std::string(demang); - m_hex = std::string(hex); - m_addr = std::string(addr); - } - StackTraceEntry(std::size_t index, char* loc) { - m_index = index; - m_location = std::string(loc); - } - std::size_t m_index; - std::string m_location; - std::string m_demangled; - std::string m_hex; - std::string m_addr; - friend std::ostream& operator<<(std::ostream& ss, const StackTraceEntry& si) { - ss << "[" << si.m_index << "] " << si.m_location << (si.m_demangled.empty() ? "" : ":") << si.m_demangled - << (si.m_hex.empty() ? "" : "+") << si.m_hex << si.m_addr; - return ss; - } - - private: - StackTraceEntry(void); - }; - - StackTrace(void) { - generateNew(); - } - - virtual ~StackTrace(void) { - } - - inline std::vector& getLatestStack(void) { - return m_stack; - } - - friend inline std::ostream& operator<<(std::ostream& os, const StackTrace& st) { - std::vector::const_iterator it = st.m_stack.begin(); - while (it != st.m_stack.end()) { - os << " " << *it++ << "\n"; - } - return os; - } - - private: - std::vector m_stack; - - void generateNew(void) { -#if ELPP_STACKTRACE - m_stack.clear(); - void* stack[kMaxStack]; - std::size_t size = backtrace(stack, kMaxStack); - char** strings = backtrace_symbols(stack, size); - if (size > kStackStart) { // Skip StackTrace c'tor and generateNew - for (std::size_t i = kStackStart; i < size; ++i) { - char* mangName = nullptr; - char* hex = nullptr; - char* addr = nullptr; - for (char* c = strings[i]; *c; ++c) { - switch (*c) { - case '(': - mangName = c; - break; - case '+': - hex = c; - break; - case ')': - addr = c; - break; - } - } - // Perform demangling if parsed properly - if (mangName != nullptr && hex != nullptr && addr != nullptr && mangName < hex) { - *mangName++ = '\0'; - *hex++ = '\0'; - *addr++ = '\0'; - int status = 0; - char* demangName = abi::__cxa_demangle(mangName, 0, 0, &status); - // if demangling is successful, output the demangled function name - if (status == 0) { - // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html) - StackTraceEntry entry(i - 1, strings[i], demangName, hex, addr); - m_stack.push_back(entry); - } - else { - // Not successful - we will use mangled name - StackTraceEntry entry(i - 1, strings[i], mangName, hex, addr); - m_stack.push_back(entry); - } - free(demangName); - } - else { - StackTraceEntry entry(i - 1, strings[i]); - m_stack.push_back(entry); - } - } - } - free(strings); -#else - ELPP_INTERNAL_INFO(1, "Stacktrace generation not supported for selected compiler"); -#endif // ELPP_STACKTRACE - } - }; - static std::string crashReason(int sig) { - std::stringstream ss; - bool foundReason = false; - for (int i = 0; i < base::consts::kCrashSignalsCount; ++i) { - if (base::consts::kCrashSignals[i].numb == sig) { - ss << "Application has crashed due to [" << base::consts::kCrashSignals[i].name << "] signal"; - if (ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason)) { - ss << std::endl << - " " << base::consts::kCrashSignals[i].brief << std::endl << - " " << base::consts::kCrashSignals[i].detail; - } - foundReason = true; - } - } - if (!foundReason) { - ss << "Application has crashed due to unknown signal [" << sig << "]"; - } - return ss.str(); - } - /// @brief Logs reason of crash from sig - static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { - std::stringstream ss; - ss << "CRASH HANDLED; "; - ss << crashReason(sig); -#if ELPP_STACKTRACE - if (stackTraceIfAvailable) { - ss << std::endl << " ======= Backtrace: =========" << std::endl << base::debug::StackTrace(); - } -#else - ELPP_UNUSED(stackTraceIfAvailable); -#endif // ELPP_STACKTRACE - ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog, logger) << ss.str(); - } - static inline void crashAbort(int sig) { - base::utils::abort(sig); - } - /// @brief Default application crash handler - /// - /// @detail This function writes log using 'default' logger, prints stack trace for GCC based compilers and aborts program. - static inline void defaultCrashHandler(int sig) { - base::debug::logCrashReason(sig, true, Level::Fatal, base::consts::kDefaultLoggerId); - base::debug::crashAbort(sig); - } - /// @brief Handles unexpected crashes - class CrashHandler : base::NoCopy { - public: - typedef void(*Handler)(int); - - explicit CrashHandler(bool useDefault) { - if (useDefault) { - setHandler(defaultCrashHandler); - } - } - explicit CrashHandler(const Handler& cHandler) { - setHandler(cHandler); - } - void setHandler(const Handler& cHandler) { - m_handler = cHandler; -#if defined(ELPP_HANDLE_SIGABRT) - int i = 0; // SIGABRT is at base::consts::kCrashSignals[0] -#else - int i = 1; -#endif // defined(ELPP_HANDLE_SIGABRT) - for (; i < base::consts::kCrashSignalsCount; ++i) { - m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler); - } - } - - private: - Handler m_handler; - }; - } // namespace debug - } // namespace base - extern base::debug::CrashHandler elCrashHandler; -#define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \ - el::base::type::ostream_t& operator<<(el::base::type::ostream_t& OutputStreamInstance, const ClassType& ClassInstance) - /// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor - class SysLogInitializer { - public: - SysLogInitializer(const char* processIdent, int options = 0, int facility = 0) { -#if defined(ELPP_SYSLOG) - openlog(processIdent, options, facility); -#else - ELPP_UNUSED(processIdent); - ELPP_UNUSED(options); - ELPP_UNUSED(facility); -#endif // defined(ELPP_SYSLOG) - } - virtual ~SysLogInitializer(void) { -#if defined(ELPP_SYSLOG) - closelog(); -#endif // defined(ELPP_SYSLOG) - } - }; -#define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac) - /// @brief Static helpers for developers - class Helpers : base::StaticClass { - public: - /// @brief Shares logging repository (base::Storage) - static inline void setStorage(base::type::StoragePointer storage) { - ELPP = storage; - } - /// @return Main storage repository - static inline base::type::StoragePointer storage() { - return ELPP; - } - /// @brief Sets application arguments and figures out whats active for logging and whats not. - static inline void setArgs(int argc, char** argv) { - ELPP->setApplicationArguments(argc, argv); - } - /// @copydoc setArgs(int argc, char** argv) - static inline void setArgs(int argc, const char** argv) { - ELPP->setApplicationArguments(argc, const_cast(argv)); - } - /// @brief Overrides default crash handler and installs custom handler. - /// @param crashHandler A functor with no return type that takes single int argument. - /// Handler is a typedef with specification: void (*Handler)(int) - static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler& crashHandler) { - el::elCrashHandler.setHandler(crashHandler); - } - /// @brief Abort due to crash with signal in parameter - /// @param sig Crash signal - static inline void crashAbort(int sig, const char* sourceFile = "", unsigned int long line = 0) { - std::stringstream ss; - ss << base::debug::crashReason(sig).c_str(); - ss << " - [Called el::Helpers::crashAbort(" << sig << ")]"; - if (sourceFile != nullptr && strlen(sourceFile) > 0) { - ss << " - Source: " << sourceFile; - if (line > 0) - ss << ":" << line; - else - ss << " (line number not specified)"; - } - base::utils::abort(sig, ss.str()); - } - /// @brief Logs reason of crash as per sig - /// @param sig Crash signal - /// @param stackTraceIfAvailable Includes stack trace if available - /// @param level Logging level - /// @param logger Logger to use for logging - static inline void logCrashReason(int sig, bool stackTraceIfAvailable = false, - Level level = Level::Fatal, const char* logger = base::consts::kDefaultLoggerId) { - el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger); - } - /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out - /// (can be useful for backing up) - static inline void installPreRollOutCallback(const PreRollOutCallback& callback) { - ELPP->setPreRollOutCallback(callback); - } - /// @brief Uninstalls pre rollout callback - static inline void uninstallPreRollOutCallback(void) { - ELPP->unsetPreRollOutCallback(); - } - /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched - template - static inline bool installLogDispatchCallback(const std::string& id) { - return ELPP->installLogDispatchCallback(id); - } - /// @brief Uninstalls log dispatch callback - template - static inline void uninstallLogDispatchCallback(const std::string& id) { - ELPP->uninstallLogDispatchCallback(id); - } - template - static inline T* logDispatchCallback(const std::string& id) { - return ELPP->logDispatchCallback(id); - } - /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished - template - static inline bool installPerformanceTrackingCallback(const std::string& id) { - return ELPP->installPerformanceTrackingCallback(id); - } - /// @brief Uninstalls post performance tracking handler - template - static inline void uninstallPerformanceTrackingCallback(const std::string& id) { - ELPP->uninstallPerformanceTrackingCallback(id); - } - template - static inline T* performanceTrackingCallback(const std::string& id) { - return ELPP->performanceTrackingCallback(id); - } - /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const - template - static std::string convertTemplateToStdString(const T& templ) { - el::Logger* logger = - ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId); - if (logger == nullptr) { - return std::string(); - } - base::MessageBuilder b; - b.initialize(logger); - logger->acquireLock(); - b << templ; -#if defined(ELPP_UNICODE) - std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end()); -#else - std::string s = logger->stream().str(); -#endif // defined(ELPP_UNICODE) - logger->stream().str(ELPP_LITERAL("")); - logger->releaseLock(); - return s; - } - /// @brief Returns command line arguments (pointer) provided to easylogging++ - static inline const el::base::utils::CommandLineArgs* commandLineArgs(void) { - return ELPP->commandLineArgs(); - } - /// @brief Installs user defined format specifier and handler - static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { - ELPP->installCustomFormatSpecifier(customFormatSpecifier); - } - /// @brief Uninstalls user defined format specifier and handler - static inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { - return ELPP->uninstallCustomFormatSpecifier(formatSpecifier); - } - /// @brief Returns true if custom format specifier is installed - static inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { - return ELPP->hasCustomFormatSpecifier(formatSpecifier); - } - static inline void validateFileRolling(Logger* logger, Level level) { - if (logger == nullptr) return; - logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback()); - } - }; - /// @brief Static helpers to deal with loggers and their configurations - class Loggers : base::StaticClass { - public: - /// @brief Gets existing or registers new logger - static inline Logger* getLogger(const std::string& identity, bool registerIfNotAvailable = true) { - base::threading::ScopedLock scopedLock(ELPP->lock()); - return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable); - } - /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister - /// loggers initialized / used by third-party libs. - static inline bool unregisterLogger(const std::string& identity) { - base::threading::ScopedLock scopedLock(ELPP->lock()); - return ELPP->registeredLoggers()->remove(identity); - } - /// @brief Whether or not logger with id is registered - static inline bool hasLogger(const std::string& identity) { - base::threading::ScopedLock scopedLock(ELPP->lock()); - return ELPP->registeredLoggers()->has(identity); - } - /// @brief Reconfigures specified logger with new configurations - static inline Logger* reconfigureLogger(Logger* logger, const Configurations& configurations) { - if (!logger) return nullptr; - logger->configure(configurations); - return logger; - } - /// @brief Reconfigures logger with new configurations after looking it up using identity - static inline Logger* reconfigureLogger(const std::string& identity, const Configurations& configurations) { - return Loggers::reconfigureLogger(Loggers::getLogger(identity), configurations); - } - /// @brief Reconfigures logger's single configuration - static inline Logger* reconfigureLogger(const std::string& identity, ConfigurationType configurationType, - const std::string& value) { - Logger* logger = Loggers::getLogger(identity); - if (logger == nullptr) { - return nullptr; - } - logger->configurations()->set(Level::Global, configurationType, value); - logger->reconfigure(); - return logger; - } - /// @brief Reconfigures all the existing loggers with new configurations - static inline void reconfigureAllLoggers(const Configurations& configurations) { - for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); - it != ELPP->registeredLoggers()->end(); ++it) { - Loggers::reconfigureLogger(it->second, configurations); - } - } - /// @brief Reconfigures single configuration for all the loggers - static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string& value) { - reconfigureAllLoggers(Level::Global, configurationType, value); - } - /// @brief Reconfigures single configuration for all the loggers for specified level - static inline void reconfigureAllLoggers(Level level, ConfigurationType configurationType, - const std::string& value) { - for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); - it != ELPP->registeredLoggers()->end(); ++it) { - Logger* logger = it->second; - logger->configurations()->set(level, configurationType, value); - logger->reconfigure(); - } - } - /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers - static inline void setDefaultConfigurations(const Configurations& configurations, bool reconfigureExistingLoggers = false) { - ELPP->registeredLoggers()->setDefaultConfigurations(configurations); - if (reconfigureExistingLoggers) { - Loggers::reconfigureAllLoggers(configurations); - } - } - /// @brief Returns current default - static inline const Configurations* defaultConfigurations(void) { - return ELPP->registeredLoggers()->defaultConfigurations(); - } - /// @brief Returns log stream reference pointer if needed by user - static inline const base::LogStreamsReferenceMap* logStreamsReference(void) { - return ELPP->registeredLoggers()->logStreamsReference(); - } - /// @brief Default typed configuration based on existing defaultConf - static base::TypedConfigurations defaultTypedConfigurations(void) { - return base::TypedConfigurations( - ELPP->registeredLoggers()->defaultConfigurations(), - ELPP->registeredLoggers()->logStreamsReference()); - } - /// @brief Populates all logger IDs in current repository. - /// @param [out] targetList List of fill up. - static inline std::vector* populateAllLoggerIds(std::vector* targetList) { - targetList->clear(); - for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->list().begin(); - it != ELPP->registeredLoggers()->list().end(); ++it) { - targetList->push_back(it->first); - } - return targetList; - } - /// @brief Sets configurations from global configuration file. - static void configureFromGlobal(const char* globalConfigurationFilePath) { - std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in); - ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file [" << globalConfigurationFilePath - << "] for parsing."); - std::string line = std::string(); - std::stringstream ss; - Logger* logger = nullptr; - auto configure = [&](void) { - ELPP_INTERNAL_INFO(8, "Configuring logger: '" << logger->id() << "' with configurations \n" << ss.str() - << "\n--------------"); - Configurations c; - c.parseFromText(ss.str()); - logger->configure(c); - }; - while (gcfStream.good()) { - std::getline(gcfStream, line); - ELPP_INTERNAL_INFO(1, "Parsing line: " << line); - base::utils::Str::trim(line); - if (Configurations::Parser::isComment(line)) continue; - Configurations::Parser::ignoreComments(&line); - base::utils::Str::trim(line); - if (line.size() > 2 && base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLoggerId))) { - if (!ss.str().empty() && logger != nullptr) { - configure(); - } - ss.str(std::string("")); - line = line.substr(2); - base::utils::Str::trim(line); - if (line.size() > 1) { - ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'"); - logger = getLogger(line); - } - } - else { - ss << line << "\n"; - } - } - if (!ss.str().empty() && logger != nullptr) { - configure(); - } - } - /// @brief Configures loggers using command line arg. Ensure you have already set command line args, - /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. - /// If true is returned that does not mean it has been configured successfully, it only means that it - /// has attempeted to configure logger using configuration file provided in argument - static inline bool configureFromArg(const char* argKey) { -#if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) - ELPP_UNUSED(argKey); -#else - if (!Helpers::commandLineArgs()->hasParamWithValue(argKey)) { - return false; - } - configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey)); -#endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) - return true; - } - /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered - static inline void flushAll(void) { - ELPP->registeredLoggers()->flushAll(); - } - /// @brief Adds logging flag used internally. - static inline void addFlag(LoggingFlag flag) { - ELPP->addFlag(flag); - } - /// @brief Removes logging flag used internally. - static inline void removeFlag(LoggingFlag flag) { - ELPP->removeFlag(flag); - } - /// @brief Determines whether or not certain flag is active - static inline bool hasFlag(LoggingFlag flag) { - return ELPP->hasFlag(flag); - } - /// @brief Adds flag and removes it when scope goes out - class ScopedAddFlag { - public: - ScopedAddFlag(LoggingFlag flag) : m_flag(flag) { Loggers::addFlag(m_flag); } - ~ScopedAddFlag(void) { Loggers::removeFlag(m_flag); } - private: - LoggingFlag m_flag; - }; - /// @brief Removes flag and add it when scope goes out - class ScopedRemoveFlag { - public: - ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) { Loggers::removeFlag(m_flag); } - ~ScopedRemoveFlag(void) { Loggers::addFlag(m_flag); } - private: - LoggingFlag m_flag; - }; - /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging) - static inline void setLoggingLevel(Level level) { - ELPP->setLoggingLevel(level); - } - /// @brief Sets verbose level on the fly - static inline void setVerboseLevel(base::type::VerboseLevel level) { - ELPP->vRegistry()->setLevel(level); - } - /// @brief Gets current verbose level - static inline base::type::VerboseLevel verboseLevel(void) { - return ELPP->vRegistry()->level(); - } - /// @brief Sets vmodules as specified (on the fly) - static inline void setVModules(const char* modules) { - if (ELPP->vRegistry()->vModulesEnabled()) { - ELPP->vRegistry()->setModules(modules); - } - } - /// @brief Clears vmodules - static inline void clearVModules(void) { - ELPP->vRegistry()->clearModules(); - } - }; - class VersionInfo : base::StaticClass { - public: - /// @brief Current version number - static inline const std::string version(void) { return std::string("9.80"); } - /// @brief Release date of current version - static inline const std::string releaseDate(void) { return std::string("08-01-2015 0850hrs"); } - }; -} // namespace el -#undef VLOG_IS_ON - /// @brief Determines whether verbose logging is on for specified level current file. -#define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__)) -#undef TIMED_BLOCK -#undef TIMED_SCOPE -#undef TIMED_FUNC -#undef ELPP_MIN_UNIT -#if defined(ELPP_PERFORMANCE_MICROSECONDS) -# define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond -#else -# define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond -#endif // (defined(ELPP_PERFORMANCE_MICROSECONDS)) - /// @brief Performance tracked scope. Performance gets written when goes out of scope using - /// 'performance' logger. - /// - /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint(); - /// @see el::base::PerformanceTracker - /// @see el::base::PerformanceTracker::checkpoint - // Note: Do not surround this definition with null macro because of obj instance -#define TIMED_SCOPE(obj, blockname) el::base::PerformanceTracker obj(blockname, ELPP_MIN_UNIT) -#define TIMED_BLOCK(obj, blockName) for (struct { int i; el::base::PerformanceTracker timer; } obj = { 0, \ - el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT) }; obj.i < 1; ++obj.i) - /// @brief Performance tracked function. Performance gets written when goes out of scope using - /// 'performance' logger. - /// - /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint(); - /// @see el::base::PerformanceTracker - /// @see el::base::PerformanceTracker::checkpoint -#define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC) -#undef PERFORMANCE_CHECKPOINT -#undef PERFORMANCE_CHECKPOINT_WITH_ID -#define PERFORMANCE_CHECKPOINT(obj) obj.checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC) -#define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj.checkpoint(id, __FILE__, __LINE__, ELPP_FUNC) -#undef ELPP_COUNTER -#undef ELPP_COUNTER_POS - /// @brief Gets hit counter for file/line -#define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__)) - /// @brief Gets hit counter position for file/line, -1 if not registered yet -#define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts()) - // Undef levels to support LOG(LEVEL) -#undef INFO -#undef WARNING -#undef DEBUG -#undef ERROR -#undef FATAL -#undef TRACE -#undef VERBOSE - // Undef existing -#undef CINFO -#undef CWARNING -#undef CDEBUG -#undef CFATAL -#undef CERROR -#undef CTRACE -#undef CVERBOSE -#undef CINFO_IF -#undef CWARNING_IF -#undef CDEBUG_IF -#undef CERROR_IF -#undef CFATAL_IF -#undef CTRACE_IF -#undef CVERBOSE_IF -#undef CINFO_EVERY_N -#undef CWARNING_EVERY_N -#undef CDEBUG_EVERY_N -#undef CERROR_EVERY_N -#undef CFATAL_EVERY_N -#undef CTRACE_EVERY_N -#undef CVERBOSE_EVERY_N -#undef CINFO_AFTER_N -#undef CWARNING_AFTER_N -#undef CDEBUG_AFTER_N -#undef CERROR_AFTER_N -#undef CFATAL_AFTER_N -#undef CTRACE_AFTER_N -#undef CVERBOSE_AFTER_N -#undef CINFO_N_TIMES -#undef CWARNING_N_TIMES -#undef CDEBUG_N_TIMES -#undef CERROR_N_TIMES -#undef CFATAL_N_TIMES -#undef CTRACE_N_TIMES -#undef CVERBOSE_N_TIMES - // Normal logs -#if ELPP_INFO_LOG -# define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE(writer, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel)) writer(\ - el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#else -# define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG - // Conditional logs -#if ELPP_INFO_LOG -# define CINFO_IF(writer, condition_, dispatchAction, ...) \ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_IF(writer, condition_, dispatchAction, ...)\ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_IF(writer, condition_, dispatchAction, ...)\ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_IF(writer, condition_, dispatchAction, ...)\ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_IF(writer, condition_, dispatchAction, ...)\ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_IF(writer, condition_, dispatchAction, ...)\ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel) && (condition_)) writer( \ - el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#else -# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG - // Occasional logs -#if ELPP_INFO_LOG -# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...)\ - CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__) -#else -# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG - // After N logs -#if ELPP_INFO_LOG -# define CINFO_AFTER_N(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_AFTER_N(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...)\ - CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) -#else -# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG - // N Times logs -#if ELPP_INFO_LOG -# define CINFO_N_TIMES(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -# define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -# define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -# define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -# define CERROR_N_TIMES(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -# define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -# define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -# define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -# define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -# define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...)\ - CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) -#else -# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG - // - // Custom Loggers - Requires (level, dispatchAction, loggerId/s) - // - // undef existing -#undef CLOG -#undef CLOG_VERBOSE -#undef CVLOG -#undef CLOG_IF -#undef CLOG_VERBOSE_IF -#undef CVLOG_IF -#undef CLOG_EVERY_N -#undef CVLOG_EVERY_N -#undef CLOG_AFTER_N -#undef CVLOG_AFTER_N -#undef CLOG_N_TIMES -#undef CVLOG_N_TIMES - // Normal logs -#define CLOG(LEVEL, ...)\ - C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) - // Conditional logs -#define CLOG_IF(condition, LEVEL, ...)\ - C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_IF(condition, vlevel, ...)\ - CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) - // Hit counts based logs -#define CLOG_EVERY_N(n, LEVEL, ...)\ - C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_EVERY_N(n, vlevel, ...)\ - CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CLOG_AFTER_N(n, LEVEL, ...)\ - C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_AFTER_N(n, vlevel, ...)\ - CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CLOG_N_TIMES(n, LEVEL, ...)\ - C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_N_TIMES(n, vlevel, ...)\ - CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) - // - // Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros - // - // undef existing -#undef LOG -#undef VLOG -#undef LOG_IF -#undef VLOG_IF -#undef LOG_EVERY_N -#undef VLOG_EVERY_N -#undef LOG_AFTER_N -#undef VLOG_AFTER_N -#undef LOG_N_TIMES -#undef VLOG_N_TIMES -#undef ELPP_CURR_FILE_LOGGER_ID -#if defined(ELPP_DEFAULT_LOGGER) -# define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER -#else -# define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId -#endif -#undef ELPP_TRACE -#define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID) - // Normal logs -#define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) - // Conditional logs -#define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) - // Hit counts based logs -#define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) - // Generic PLOG() -#undef CPLOG -#undef CPLOG_IF -#undef PLOG -#undef PLOG_IF -#undef DCPLOG -#undef DCPLOG_IF -#undef DPLOG -#undef DPLOG_IF -#define CPLOG(LEVEL, ...)\ - C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CPLOG_IF(condition, LEVEL, ...)\ - C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define DCPLOG(LEVEL, ...)\ - if (ELPP_DEBUG_LOG) C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define DCPLOG_IF(condition, LEVEL, ...)\ - C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) - // Generic SYSLOG() -#undef CSYSLOG -#undef CSYSLOG_IF -#undef CSYSLOG_EVERY_N -#undef CSYSLOG_AFTER_N -#undef CSYSLOG_N_TIMES -#undef SYSLOG -#undef SYSLOG_IF -#undef SYSLOG_EVERY_N -#undef SYSLOG_AFTER_N -#undef SYSLOG_N_TIMES -#undef DCSYSLOG -#undef DCSYSLOG_IF -#undef DCSYSLOG_EVERY_N -#undef DCSYSLOG_AFTER_N -#undef DCSYSLOG_N_TIMES -#undef DSYSLOG -#undef DSYSLOG_IF -#undef DSYSLOG_EVERY_N -#undef DSYSLOG_AFTER_N -#undef DSYSLOG_N_TIMES -#if defined(ELPP_SYSLOG) -# define CSYSLOG(LEVEL, ...)\ - C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_IF(condition, LEVEL, ...)\ - C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define DCSYSLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_IF(condition, LEVEL, ...)\ - C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_EVERY_N(n, LEVEL, ...)\ - if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_AFTER_N(n, LEVEL, ...)\ - if (ELPP_DEBUG_LOG) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DCSYSLOG_N_TIMES(n, LEVEL, ...)\ - if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -# define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -# define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) -#else -# define CSYSLOG(LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() -# define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() -# define SYSLOG(LEVEL) el::base::NullWriter() -# define SYSLOG_IF(condition, LEVEL) el::base::NullWriter() -# define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() -# define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() -# define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() -# define DCSYSLOG(LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() -# define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() -# define DSYSLOG(LEVEL) el::base::NullWriter() -# define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter() -# define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() -# define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() -# define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() -#endif // defined(ELPP_SYSLOG) - // - // Custom Debug Only Loggers - Requires (level, loggerId/s) - // - // undef existing -#undef DCLOG -#undef DCVLOG -#undef DCLOG_IF -#undef DCVLOG_IF -#undef DCLOG_EVERY_N -#undef DCVLOG_EVERY_N -#undef DCLOG_AFTER_N -#undef DCVLOG_AFTER_N -#undef DCLOG_N_TIMES -#undef DCVLOG_N_TIMES - // Normal logs -#define DCLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG(LEVEL, __VA_ARGS__) -#define DCLOG_VERBOSE(vlevel, ...) if (ELPP_DEBUG_LOG) CLOG_VERBOSE(vlevel, __VA_ARGS__) -#define DCVLOG(vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG(vlevel, __VA_ARGS__) - // Conditional logs -#define DCLOG_IF(condition, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_IF(condition, LEVEL, __VA_ARGS__) -#define DCVLOG_IF(condition, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_IF(condition, vlevel, __VA_ARGS__) - // Hit counts based logs -#define DCLOG_EVERY_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_EVERY_N(n, LEVEL, __VA_ARGS__) -#define DCVLOG_EVERY_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_EVERY_N(n, vlevel, __VA_ARGS__) -#define DCLOG_AFTER_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_AFTER_N(n, LEVEL, __VA_ARGS__) -#define DCVLOG_AFTER_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_AFTER_N(n, vlevel, __VA_ARGS__) -#define DCLOG_N_TIMES(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_N_TIMES(n, LEVEL, __VA_ARGS__) -#define DCVLOG_N_TIMES(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_N_TIMES(n, vlevel, __VA_ARGS__) - // - // Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros - // - // undef existing -#undef DLOG -#undef DVLOG -#undef DLOG_IF -#undef DVLOG_IF -#undef DLOG_EVERY_N -#undef DVLOG_EVERY_N -#undef DLOG_AFTER_N -#undef DVLOG_AFTER_N -#undef DLOG_N_TIMES -#undef DVLOG_N_TIMES - // Normal logs -#define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) - // Conditional logs -#define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) - // Hit counts based logs -#define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) - // Check macros -#undef CCHECK -#undef CPCHECK -#undef CCHECK_EQ -#undef CCHECK_NE -#undef CCHECK_LT -#undef CCHECK_GT -#undef CCHECK_LE -#undef CCHECK_GE -#undef CCHECK_BOUNDS -#undef CCHECK_NOTNULL -#undef CCHECK_STRCASEEQ -#undef CCHECK_STRCASENE -#undef CHECK -#undef PCHECK -#undef CHECK_EQ -#undef CHECK_NE -#undef CHECK_LT -#undef CHECK_GT -#undef CHECK_LE -#undef CHECK_GE -#undef CHECK_BOUNDS -#undef CHECK_NOTNULL -#undef CHECK_STRCASEEQ -#undef CHECK_STRCASENE -#define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " -#define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " -#define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__) -#define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__) -#define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__) -#define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__) -#define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__) -#define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__) -#define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__) -#define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) -namespace el { - namespace base { - namespace utils { - template - static T* checkNotNull(T* ptr, const char* name, const char* loggers, ...) { - CLOG_IF(ptr == nullptr, FATAL, loggers) << "Check failed: [" << name << " != nullptr]"; - return ptr; - } - } // namespace utils - } // namespace base -} // namespace el -#define CCHECK_NOTNULL(ptr, ...) el::base::utils::checkNotNull(ptr, #ptr, __VA_ARGS__) -#define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " == " << #str2 << "] " -#define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " != " << #str2 << "] " -#define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " == " << #str2 << "] " -#define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " != " << #str2 << "] " -#define CHECK_NOTNULL(ptr) CCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#undef DCCHECK -#undef DCCHECK_EQ -#undef DCCHECK_NE -#undef DCCHECK_LT -#undef DCCHECK_GT -#undef DCCHECK_LE -#undef DCCHECK_GE -#undef DCCHECK_BOUNDS -#undef DCCHECK_NOTNULL -#undef DCCHECK_STRCASEEQ -#undef DCCHECK_STRCASENE -#undef DCPCHECK -#undef DCHECK -#undef DCHECK_EQ -#undef DCHECK_NE -#undef DCHECK_LT -#undef DCHECK_GT -#undef DCHECK_LE -#undef DCHECK_GE -#undef DCHECK_BOUNDS_ -#undef DCHECK_NOTNULL -#undef DCHECK_STRCASEEQ -#undef DCHECK_STRCASENE -#undef DPCHECK -#define DCCHECK(condition, ...) if (ELPP_DEBUG_LOG) CCHECK(condition, __VA_ARGS__) -#define DCCHECK_EQ(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_EQ(a, b, __VA_ARGS__) -#define DCCHECK_NE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_NE(a, b, __VA_ARGS__) -#define DCCHECK_LT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LT(a, b, __VA_ARGS__) -#define DCCHECK_GT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GT(a, b, __VA_ARGS__) -#define DCCHECK_LE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LE(a, b, __VA_ARGS__) -#define DCCHECK_GE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GE(a, b, __VA_ARGS__) -#define DCCHECK_BOUNDS(val, min, max, ...) if (ELPP_DEBUG_LOG) CCHECK_BOUNDS(val, min, max, __VA_ARGS__) -#define DCCHECK_NOTNULL(ptr, ...) if (ELPP_DEBUG_LOG) CCHECK_NOTNULL(ptr, __VA_ARGS__) -#define DCCHECK_STREQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STREQ(str1, str2, __VA_ARGS__) -#define DCCHECK_STRNE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRNE(str1, str2, __VA_ARGS__) -#define DCCHECK_STRCASEEQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__) -#define DCCHECK_STRCASENE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASENE(str1, str2, __VA_ARGS__) -#define DCPCHECK(condition, ...) if (ELPP_DEBUG_LOG) CPCHECK(condition, __VA_ARGS__) -#define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) -# define ELPP_USE_DEF_CRASH_HANDLER false -#else -# define ELPP_USE_DEF_CRASH_HANDLER true -#endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) -#define ELPP_CRASH_HANDLER_INIT -#define ELPP_INIT_EASYLOGGINGPP(val)\ - ELPP_INITI_BASIC_DECLR\ - namespace el {\ - namespace base {\ - el::base::type::StoragePointer elStorage(val);\ - }\ - el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ - } - -#if ELPP_ASYNC_LOGGING -# define INITIALIZE_EASYLOGGINGPP\ - ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\ - new el::base::AsyncDispatchWorker()))\ - -#else -# define INITIALIZE_EASYLOGGINGPP\ - ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) -#endif // ELPP_ASYNC_LOGGING -#define INITIALIZE_NULL_EASYLOGGINGPP\ - ELPP_INITI_BASIC_DECLR\ - namespace el {\ - namespace base {\ - el::base::type::StoragePointer elStorage;\ - }\ - el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ - } - // NOTE: no ELPP_INITI_BASIC_DECLR when sharing - causes double free corruption on external symbols -#define SHARE_EASYLOGGINGPP(initializedStorage)\ - namespace el {\ - namespace base {\ - el::base::type::StoragePointer elStorage(initializedStorage);\ - }\ - el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ - } - -#if defined(ELPP_UNICODE) -# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv); std::locale::global(std::locale("")) -#else -# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv) -#endif // defined(ELPP_UNICODE) -#endif // EASYLOGGINGPP_H \ No newline at end of file diff --git a/extensions/common/logging.hpp b/extensions/common/logging.hpp deleted file mode 100644 index fc713d3002..0000000000 --- a/extensions/common/logging.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#define _ELPP_THREAD_SAFE -#define _ELPP_FORCE_USE_STD_THREAD -#define _ELPP_NO_DEFAULT_LOG_FILE -#define _ELPP_DISABLE_DEFAULT_CRASH_HANDLING -#include "easyloggingc++.hpp" \ No newline at end of file diff --git a/extensions/common/shared.cpp b/extensions/common/shared.cpp index 5bee7740aa..8a68566ba9 100644 --- a/extensions/common/shared.cpp +++ b/extensions/common/shared.cpp @@ -1,9 +1,7 @@ #include "shared.hpp" -#include #include -#include -#include +#include int test(int var) { return var; @@ -23,19 +21,4 @@ namespace ace { split(s, delim, elems); return elems; } - - void runtime_assert(bool result) { - assert(result); - if (!result) { - LOG(ERROR) << "ACE Assertion failed, execution cancelling"; - throw exception(-1, "assertion failed"); - } - } - void runtime_assert(bool result, const uint32_t code, const std::string & text) { - assert(result); - if (!result) { - LOG(ERROR) << "ACE Assertion failed, execution cancelling"; - throw exception(code, text); - } - } -} \ No newline at end of file +} diff --git a/extensions/common/shared.hpp b/extensions/common/shared.hpp index aee47902aa..a3cf1d154f 100644 --- a/extensions/common/shared.hpp +++ b/extensions/common/shared.hpp @@ -18,7 +18,8 @@ #include #include #include "ace_version.hpp" -#include "logging.hpp" +#include +#include //std::isspace #ifdef _DEBUG #define ZERO_OUTPUT() { memset(output, 0x00, outputSize); } @@ -55,13 +56,13 @@ namespace ace { // trim from start static inline std::string <rim(std::string &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](const char _char) noexcept {return !std::isspace(_char); })); return s; } // trim from end static inline std::string &rtrim(std::string &s) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + s.erase(std::find_if(s.rbegin(), s.rend(), [](const char _char) noexcept {return !std::isspace(_char); }).base(), s.end()); return s; } @@ -70,8 +71,6 @@ namespace ace { return ltrim(rtrim(s)); } - inline void runtime_assert(bool result); - struct exception { exception(const uint32_t code_, const std::string & text_) : code(code_), text(text_) {} @@ -83,12 +82,6 @@ namespace ace { }; } -#ifdef _DEBUG -#define ACE_ASSERT assert() -#else -#define ACE_ASSERT ace::runtime_assert() -#endif - #ifndef _WIN32 #define __stdcall #endif diff --git a/extensions/common/simplepipe_win32.cpp b/extensions/common/simplepipe_win32.cpp deleted file mode 100644 index 848e77970b..0000000000 --- a/extensions/common/simplepipe_win32.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#ifdef _WIN32 - -#include "simplepipe_win32.hpp" -#include -#include -#include - -namespace ace { - namespace { - const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\"; - const int kPipeBufferSz = 4 * 1024; - } // namespace - - bool checkIntegritySupport() { - OSVERSIONINFO osvi; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - - return osvi.dwMajorVersion > 5; - } - - LONG g_pipe_seq = 0; - - HANDLE pipe_pair::open_pipe_server(const wchar_t* name, bool low_integrity, bool blocking) { - SECURITY_ATTRIBUTES sa = {0}; - SECURITY_ATTRIBUTES *psa = 0; - DWORD wait; - static const bool is_integrity_supported = checkIntegritySupport(); - - if (is_integrity_supported && low_integrity) { - psa = &sa; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE; - if (!ConvertStringSecurityDescriptorToSecurityDescriptor( - TEXT("S:(ML;;NWNR;;;LW)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)) - return INVALID_HANDLE_VALUE; - } - - if (blocking) { - wait = PIPE_WAIT; - } else { - wait = PIPE_NOWAIT; - } - - std::wstring pipename(kPipePrefix); - pipename.append(name); - return ::CreateNamedPipeW(pipename.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | wait, - 1, kPipeBufferSz, kPipeBufferSz, 200, psa); - } - - HANDLE pipe_pair::open_pipe_client(const wchar_t* name, bool inherit, bool impersonate) { - std::wstring pipename(kPipePrefix); - pipename.append(name); - - SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, inherit ? TRUE : FALSE}; - for (;;) { - DWORD attributes = impersonate ? 0 : SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION; - HANDLE pipe = ::CreateFileW(pipename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa, - OPEN_EXISTING, attributes, NULL); - if (INVALID_HANDLE_VALUE == pipe) { - if (ERROR_PIPE_BUSY != ::GetLastError()) { - return pipe; - } - // wait and retry. - if (! ::WaitNamedPipeW(pipename.c_str(), NMPWAIT_USE_DEFAULT_WAIT)) - continue; - } else { - // success. - return pipe; - } - } - } - - - pipe_pair::pipe_pair(bool inherit_fd2, bool blocking) : srv_(NULL), cln_(NULL) { - // Come up with a reasonable unique name. - const wchar_t kPipePattern[] = L"ko.%x.%x.%x"; - wchar_t name[8*3 + sizeof(kPipePattern)]; - ::wsprintfW(name, kPipePattern, ::GetCurrentProcessId(), ::GetTickCount(), - ::InterlockedIncrement(&g_pipe_seq)); - HANDLE server = open_pipe_server(name, blocking); - if (INVALID_HANDLE_VALUE == server) { - return; - } - // Don't allow client impersonation. - HANDLE client = open_pipe_client(name, inherit_fd2, false); - if (INVALID_HANDLE_VALUE == client) { - ::CloseHandle(server); - return; - } - if (!::ConnectNamedPipe(server, NULL)) { - if (ERROR_PIPE_CONNECTED != ::GetLastError()) { - ::CloseHandle(server); - ::CloseHandle(client); - return; - } - } - - srv_ = server; - cln_ = client; - } - - - pipe_win::pipe_win() : pipe_(INVALID_HANDLE_VALUE) { - } - - pipe_win::~pipe_win() { - if (pipe_ != INVALID_HANDLE_VALUE) { - ::DisconnectNamedPipe(pipe_); // $$$ disconect is valid on the server side. - ::CloseHandle(pipe_); - } - } - - bool pipe_win::open_client(HANDLE pipe) { - pipe_ = pipe; - return true; - } - - bool pipe_win::open_server(HANDLE pipe, bool connect) { - pipe_ = pipe; - - if (connect) { - if (!::ConnectNamedPipe(pipe, NULL)) { - if (ERROR_PIPE_CONNECTED != ::GetLastError()) { - return false; - } - } - } - return true; - } - - bool pipe_win::write(const void* buf, size_t sz) { - DWORD written = 0; - return (TRUE == ::WriteFile(pipe_, buf, sz, &written, NULL)); - } - - bool pipe_win::CheckStatus() { - char buf[5]; - uint32_t size = sizeof(buf); - BOOL ret; - ret = ::ReadFile(pipe_, buf, sizeof(buf), reinterpret_cast(&size), NULL); - if (!ret) { - if (GetLastError() == ERROR_NO_DATA) { - return true; - } else { - return false; - } - } else { - return true; - } - } - - bool pipe_win::read(void* buf, size_t* sz) { - BOOL ret; - ret = ::ReadFile(pipe_, buf, *sz, reinterpret_cast(sz), NULL); - if (!ret) { - if (GetLastError() == ERROR_BROKEN_PIPE) { - if (!DisconnectNamedPipe(pipe_)) { - printf("DisconnectNamedPipe() failed. hr=%08x", GetLastError()); - } - if (!::ConnectNamedPipe(pipe_, NULL)) { - } - } - } - return ret; - } - - - char* PipeTransport::receive(size_t* size) { - if (buf_.size() < kBufferSz) - buf_.resize(kBufferSz); - - *size = kBufferSz; - if (!read(&buf_[0], size)) - return NULL; - return &buf_[0]; - } -} - -#endif diff --git a/extensions/common/simplepipe_win32.hpp b/extensions/common/simplepipe_win32.hpp deleted file mode 100644 index 37605da443..0000000000 --- a/extensions/common/simplepipe_win32.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#ifdef _WIN32 - -#include -#include -#include - -#include - -namespace ace { - class pipe_pair { - public: - pipe_pair(bool inherit_fd2 = false, bool blocking = true); - HANDLE fd1() const { return srv_; } - HANDLE fd2() const { return cln_; } - - static HANDLE open_pipe_server(const wchar_t* name, bool low_integrity = true, bool blocking = true); - static HANDLE open_pipe_client(const wchar_t* name, bool inherit, bool impersonate); - - private: - HANDLE srv_; - HANDLE cln_; - }; - - class pipe_win { - public: - pipe_win(); - ~pipe_win(); - - bool open_client(HANDLE pipe); - bool open_server(HANDLE pipe, bool connect = false); - - bool write(const void* buf, size_t sz); - bool read(void* buf, size_t* sz); - - bool CheckStatus(); - bool IsConnected() const { return INVALID_HANDLE_VALUE != pipe_; } - - private: - HANDLE pipe_; - }; - - - class PipeTransport : public pipe_win { - public: - static const size_t kBufferSz = 4096; - - size_t send(const void* buf, size_t sz) { - return write(buf, sz) ? -1 : 0; - } - - char* receive(size_t* size); - - private: - std::vector buf_; - }; -} - -#endif From cd3f2f03a1edeb03db77b3afb50a71d873793d5d Mon Sep 17 00:00:00 2001 From: ulteq Date: Sat, 28 Oct 2017 21:42:03 +0200 Subject: [PATCH 017/212] ATragMX | Scopes - Fixed typo (#5700) --- .../functions/fnc_calculate_truing_drop.sqf | 4 ++-- .../atragmx/functions/fnc_update_range_card.sqf | 8 ++++---- addons/atragmx/functions/fnc_update_result.sqf | 16 ++++++++-------- .../functions/fnc_update_truing_drop_data.sqf | 6 +++--- addons/atragmx/script_component.hpp | 4 ++-- addons/rangecard/script_component.hpp | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/addons/atragmx/functions/fnc_calculate_truing_drop.sqf b/addons/atragmx/functions/fnc_calculate_truing_drop.sqf index fa43ac73c2..b21e3b0cba 100644 --- a/addons/atragmx/functions/fnc_calculate_truing_drop.sqf +++ b/addons/atragmx/functions/fnc_calculate_truing_drop.sqf @@ -46,8 +46,8 @@ if (_parseInput) then { }; switch (_dropUnit) do { case 0: { - _transonicDrop = MRAD_TO_MOA(_transonicDrop); - _subsonicDrop = MRAD_TO_MOA(_subsonicDrop); + _transonicDrop = MOA_TO_MRAD(_transonicDrop); + _subsonicDrop = MOA_TO_MRAD(_subsonicDrop); }; case 2: { _transonicDrop = _transonicDrop / 1.047; diff --git a/addons/atragmx/functions/fnc_update_range_card.sqf b/addons/atragmx/functions/fnc_update_range_card.sqf index 4bcf4c3e42..2f4aa3c7a2 100644 --- a/addons/atragmx/functions/fnc_update_range_card.sqf +++ b/addons/atragmx/functions/fnc_update_range_card.sqf @@ -45,9 +45,9 @@ private _speedOfSound = GVAR(temperature) call EFUNC(weather,calculateSpeedOfSou switch (GVAR(currentScopeUnit)) do { case 0: { - _elevation = MRAD_TO_MOA(_elevation); - _windage1 = MRAD_TO_MOA(_windage1); - _windage2 = MRAD_TO_MOA(_windage2); + _elevation = MOA_TO_MRAD(_elevation); + _windage1 = MOA_TO_MRAD(_windage1); + _windage2 = MOA_TO_MRAD(_windage2); }; case 2: { _elevation = _elevation * 1.047; @@ -55,7 +55,7 @@ private _speedOfSound = GVAR(temperature) call EFUNC(weather,calculateSpeedOfSou _windage2 = _windage2 * 1.047; }; case 3: { - private _clickSize = [1, 1 / 1.047, MOA_TO_MRAD(1)] select (GVAR(workingMemory) select 7); + private _clickSize = [1, 1 / 1.047, MRAD_TO_MOA(1)] select (GVAR(workingMemory) select 7); private _clickNumber = GVAR(workingMemory) select 8; private _clickInterval = _clickSize / _clickNumber; diff --git a/addons/atragmx/functions/fnc_update_result.sqf b/addons/atragmx/functions/fnc_update_result.sqf index 0f69d742dc..1dc2c6204e 100644 --- a/addons/atragmx/functions/fnc_update_result.sqf +++ b/addons/atragmx/functions/fnc_update_result.sqf @@ -41,16 +41,16 @@ private _lead = GVAR(leadOutput) select GVAR(currentTarget); switch (GVAR(currentScopeUnit)) do { case 0: { - _elevationAbs = MRAD_TO_MOA(_elevationAbs); - _windageAbs = MRAD_TO_MOA(_windageAbs); + _elevationAbs = MOA_TO_MRAD(_elevationAbs); + _windageAbs = MOA_TO_MRAD(_windageAbs); - _wind2 = MRAD_TO_MOA(_wind2); + _wind2 = MOA_TO_MRAD(_wind2); - _elevationRel = MRAD_TO_MOA(_elevationRel); - _windageRel = MRAD_TO_MOA(_windageRel); + _elevationRel = MOA_TO_MRAD(_elevationRel); + _windageRel = MOA_TO_MRAD(_windageRel); - _elevationCur = MRAD_TO_MOA(_elevationCur); - _windageCur = MRAD_TO_MOA(_windageCur); + _elevationCur = MOA_TO_MRAD(_elevationCur); + _windageCur = MOA_TO_MRAD(_windageCur); }; case 2: { _elevationAbs = _elevationAbs * 1.047; @@ -65,7 +65,7 @@ switch (GVAR(currentScopeUnit)) do { _windageCur = _windageCur * 1.047; }; case 3: { - private _clickSize = [1, 1 / 1.047, MOA_TO_MRAD(1)] select (GVAR(workingMemory) select 7); + private _clickSize = [1, 1 / 1.047, MRAD_TO_MOA(1)] select (GVAR(workingMemory) select 7); private _clickNumber = GVAR(workingMemory) select 8; private _clickInterval = _clickSize / _clickNumber; diff --git a/addons/atragmx/functions/fnc_update_truing_drop_data.sqf b/addons/atragmx/functions/fnc_update_truing_drop_data.sqf index c546e78d41..cd1fa9de68 100644 --- a/addons/atragmx/functions/fnc_update_truing_drop_data.sqf +++ b/addons/atragmx/functions/fnc_update_truing_drop_data.sqf @@ -42,9 +42,9 @@ private _dropData = +GVAR(truingDropDropData); switch (_dropUnit) do { case 0: { - _dropData set [0, MRAD_TO_MOA(_dropData select 0)]; - _dropData set [1, MRAD_TO_MOA(_dropData select 1)]; - _dropData set [2, MRAD_TO_MOA(_dropData select 2)]; + _dropData set [0, MOA_TO_MRAD(_dropData select 0)]; + _dropData set [1, MOA_TO_MRAD(_dropData select 1)]; + _dropData set [2, MOA_TO_MRAD(_dropData select 2)]; }; case 2: { _dropData set [0, (_dropData select 0) * 1.047]; diff --git a/addons/atragmx/script_component.hpp b/addons/atragmx/script_component.hpp index 7b6aaa74cd..e268999ebf 100644 --- a/addons/atragmx/script_component.hpp +++ b/addons/atragmx/script_component.hpp @@ -16,8 +16,8 @@ #include "\z\ace\addons\main\script_macros.hpp" -#define MOA_TO_MRAD(d) (d * 3.43774677) // Conversion factor: 54 / (5 * PI) -#define MRAD_TO_MOA(d) (d * 0.29088821) // Conversion factor: (5 * PI) / 54 +#define MRAD_TO_MOA(d) (d * 3.43774677) // Conversion factor: 54 / (5 * PI) +#define MOA_TO_MRAD(d) (d * 0.29088821) // Conversion factor: (5 * PI) / 54 #define DEG_TO_MOA(d) (d * 60) // Conversion factor: 60 #define MOA_TO_DEG(d) (d / 60) // Conversion factor: 1 / 60 #define DEG_TO_MRAD(d) (d * 17.45329252) // Conversion factor: (50 * PI) / 9 diff --git a/addons/rangecard/script_component.hpp b/addons/rangecard/script_component.hpp index 76106720bc..8a3f3825a9 100644 --- a/addons/rangecard/script_component.hpp +++ b/addons/rangecard/script_component.hpp @@ -16,8 +16,8 @@ #include "\z\ace\addons\main\script_macros.hpp" -#define MOA_TO_MRAD(d) (d * 3.43774677) // Conversion factor: 54 / (5 * PI) -#define MRAD_TO_MOA(d) (d * 0.29088821) // Conversion factor: (5 * PI) / 54 +#define MRAD_TO_MOA(d) (d * 3.43774677) // Conversion factor: 54 / (5 * PI) +#define MOA_TO_MRAD(d) (d * 0.29088821) // Conversion factor: (5 * PI) / 54 #define DEG_TO_MOA(d) (d * 60) // Conversion factor: 60 #define MOA_TO_DEG(d) (d / 60) // Conversion factor: 1 / 60 #define DEG_TO_MRAD(d) (d * 17.45329252) // Conversion factor: (50 * PI) / 9 From 461c2649a54e7f2b11ca46374899904ca953ed24 Mon Sep 17 00:00:00 2001 From: ulteq Date: Sat, 28 Oct 2017 23:52:35 +0200 Subject: [PATCH 018/212] RangeCard - Increased level of accuracy (#5703) * Accounts for the accuracy improvements of the Advanced Ballistics module * Reduces the expected error at max range down to 0.1 Mil --- addons/rangecard/functions/fnc_updateRangeCard.sqf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/rangecard/functions/fnc_updateRangeCard.sqf b/addons/rangecard/functions/fnc_updateRangeCard.sqf index 064abea6b0..77ec68c0f7 100644 --- a/addons/rangecard/functions/fnc_updateRangeCard.sqf +++ b/addons/rangecard/functions/fnc_updateRangeCard.sqf @@ -167,10 +167,10 @@ if (isNil {_cacheEntry}) then { private _mvShift = [_ammoConfig select 9, _x] call EFUNC(advanced_ballistics,calculateAmmoTemperatureVelocityShift); private _mv = _muzzleVelocity + _mvShift; - [_scopeBaseAngle,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),100,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,_forEachIndex,_useABConfig] call FUNC(calculateRangeCard); + [_scopeBaseAngle,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,_forEachIndex,_useABConfig] call FUNC(calculateRangeCard); } forEach [-15, -5, 5, 10, 15, 20, 25, 30, 35]; } else { - [_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),100,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,3,_useABConfig] call FUNC(calculateRangeCard); + [_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,3,_useABConfig] call FUNC(calculateRangeCard); }; for "_i" from 0 to 9 do { From 0f3639979b64f9d6647ae0f7b3519728c02d2986 Mon Sep 17 00:00:00 2001 From: Tittoffer Date: Sun, 29 Oct 2017 06:53:37 +0100 Subject: [PATCH 019/212] Moveable Map Markers Documentation (#5691) * Updated markers.md to include moveable map markers. * Added documentation for map-gestures and moveable map markers. * Minor phrasing fixes. * Minor phrasing fixes. --- docs/wiki/feature/map-gestures.md | 29 +++++++++++++++++++++++++++++ docs/wiki/feature/markers.md | 17 +++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 docs/wiki/feature/map-gestures.md diff --git a/docs/wiki/feature/map-gestures.md b/docs/wiki/feature/map-gestures.md new file mode 100644 index 0000000000..8defad4e79 --- /dev/null +++ b/docs/wiki/feature/map-gestures.md @@ -0,0 +1,29 @@ +--- +layout: wiki +title: Map Gestures +description: Allow players to gesture on map. +group: feature +category: interaction +parent: wiki +mod: ace +version: + major: 3 + minor: 4 + patch: 0 +--- + +## 1. Overview + +### 1.1 Map gestures + +Allow players to gesture/point on their map. + +## 2. Usage + +### 2.1 Gesturing on map + +- To gesture on map hold Left Mouse Btn. + +## 2. Dependencies + +{% include dependencies_list.md component="map_gestures" %} diff --git a/docs/wiki/feature/markers.md b/docs/wiki/feature/markers.md index 17471bc33d..3336a074bb 100644 --- a/docs/wiki/feature/markers.md +++ b/docs/wiki/feature/markers.md @@ -15,8 +15,25 @@ version: ## 1. Overview ### 1.1 Improved marker placement + Expands the "Insert Marker" menu and allows to rotate map markers. Shows the currently selected channel to prevent misplacement. +### 1.2 Moveable map markers + +Adds the ability to move map markers after they are placed. (Note: Must be enabled in `Markers` module) + + +## 2. Usage + +### 2.1 Moving map markers + +- To move a marker hold down Alt and Left Mouse Btn on marker and move. + +
+
Note:
+

Does not work in Editor Preview! Conflicts with vanilla teleport keybind.

+
+ ## 2. Dependencies {% include dependencies_list.md component="markers" %} From a5b73d2c295913a99ca45c712dd7cc18810d49ff Mon Sep 17 00:00:00 2001 From: Dedmen Miller Date: Sun, 29 Oct 2017 09:43:31 +0100 Subject: [PATCH 020/212] Optimize vector math (#5705) --- extensions/common/vector.hpp | 61 +++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/extensions/common/vector.hpp b/extensions/common/vector.hpp index 14dc5d652a..4830e18ba5 100644 --- a/extensions/common/vector.hpp +++ b/extensions/common/vector.hpp @@ -25,12 +25,12 @@ namespace ace { template class vector3 { public: - vector3() : + constexpr vector3() : _x(0), _y(0), _z(0) { } - vector3(const T x_, const T y_, const T z_) : + constexpr vector3(const T x_, const T y_, const T z_) noexcept : _x(x_), _y(y_), _z(z_) { @@ -47,7 +47,7 @@ namespace ace { _z = buffer[2]; } - vector3 & operator= (const vector3& other) { _x = other.x(); _y = other.y(); _z = other.z(); return *this; } + constexpr vector3& operator= (const vector3& other) noexcept { _x = other.x(); _y = other.y(); _z = other.z(); return *this; } /*#ifdef _WIN32 && _DIRECTX vector3 & operator= (const XMFLOAT3& Float3) { _x = Float3.x; _y = Float3.y; _z = Float3.z; return *this; } #endif @@ -56,33 +56,38 @@ namespace ace { vector3 & operator= (const btVector3& bt_vec) { _x = bt_vec.x(); _y = bt_vec.y(); _z = bt_vec.z(); return *this; } #endif */ - vector3 operator * (const T &val) const { return vector3(_x * val, _y * val, _z * val); } - vector3 operator / (const T &val) const { T invVal = T(1) / val; return vector3(_x * invVal, _y * invVal, _z * invVal); } - vector3 operator + (const vector3 &v) const { return vector3(_x + v.x(), _y + v.y(), _z + v.z()); } - vector3 operator / (const vector3 &v) const { return vector3(_x / v.x(), _y / v.y(), _z / v.z()); } - vector3 operator * (const vector3 &v) const { return vector3(_x * v.x(), _y * v.y(), _z * v.z()); } - vector3 operator - (const vector3 &v) const { return vector3(_x - v.x(), _y - v.y(), _z - v.z()); } - vector3 operator - () const { return vector3(-_x, -_y, -_z); } + constexpr vector3 operator * (const T& val) const { return vector3(_x * val, _y * val, _z * val); } + constexpr vector3 operator / (const T& val) const { T invVal = T(1) / val; return vector3(_x * invVal, _y * invVal, _z * invVal); } + constexpr vector3 operator + (const vector3& v) const { return vector3(_x + v.x(), _y + v.y(), _z + v.z()); } + constexpr vector3 operator / (const vector3& v) const { return vector3(_x / v.x(), _y / v.y(), _z / v.z()); } + constexpr vector3 operator * (const vector3& v) const { return vector3(_x * v.x(), _y * v.y(), _z * v.z()); } + constexpr vector3 operator - (const vector3& v) const { return vector3(_x - v.x(), _y - v.y(), _z - v.z()); } + constexpr vector3 operator - () const { return vector3(-_x, -_y, -_z); } - bool operator == (const vector3 &r) const { return (_x == r.x() && _y == r.y() && _z == r.z()); } - bool operator > (const vector3 &r) const { throw 1; } - bool operator < (const vector3 &r) const { throw 1; } - bool operator <= (const vector3 &r) const { throw 1; } - bool operator >= (const vector3 &r) const { throw 1; } + constexpr vector3& operator *=(const vector3& v) noexcept { _x *= v._x; _y *= v._y; _z *= v._z; return *this; } + constexpr vector3& operator *=(T mag) noexcept { _x *= mag; _y *= mag; _z *= mag; return *this; } + constexpr vector3& operator /=(const vector3& v) noexcept { _x /= v._x; _y /= v._y; _z /= v._z; return *this; } + constexpr vector3& operator /=(T mag) noexcept { _x /= mag; _y /= mag; _y /= mag; return *this; } + constexpr vector3& operator +=(const vector3& v) noexcept { _x += v._x; _y += v._y; _z += v._z; return *this; } + constexpr vector3& operator -=(const vector3& v) noexcept { _x -= v._x; _y -= v._y; _z -= v._z; return *this; } - T magnitude() const { return sqrt(_x * _x + _y * _y + _z * _z); } - T dot(const vector3 &v) const { return (_x * v.x() + _y * v.y() + _z * v.z()); } - T distance(const vector3 &v) const { vector3 dist = (*this - v); dist = dist * dist; return sqrt(dist.x() + dist.y() + dist.z()); } - vector3 cross(const vector3 &v) const { return vector3(_y * v.z() - _z * v.y(), _z * v.x() - _x * v.z(), _x * v.y() - _y * v.x()); } - vector3 normalize(void) const { return (*this / abs(magnitude())); }; - bool zero_distance() { return ((_x == 0.0f && _y == 0.0f && _z == 0.0f) ? true : false ); } + + bool operator == (const vector3 &r) const noexcept { return (_x == r.x() && _y == r.y() && _z == r.z()); } + + constexpr T magnitude() const noexcept { return sqrt(_x * _x + _y * _y + _z * _z); } + constexpr T magnitude_squared() const noexcept { return _x * _x + _y * _y + _z * _z; } + constexpr T dot(const vector3& v) const noexcept { return (_x * v.x() + _y * v.y() + _z * v.z()); } + constexpr T distance(const vector3& v) const noexcept { vector3 dist = (*this - v); dist = dist * dist; return sqrt(dist.x() + dist.y() + dist.z()); } + constexpr vector3 cross(const vector3& v) const noexcept { return vector3(_y * v.z() - _z * v.y(), _z * v.x() - _x * v.z(), _x * v.y() - _y * v.x()); } + constexpr vector3 normalize() const noexcept { return (*this / abs(magnitude())); }; + constexpr bool zero_distance() const noexcept { return ((_x == 0.0f && _y == 0.0f && _z == 0.0f) ? true : false ); } static float clamp(T x, T a, T b) { return x < a ? a : (x > b ? b : x); } - static vector3 lerp(const vector3& A, const vector3& B, const T t) { return A*t + B*(1.f - t); } - vector3 lerp(const vector3& B, const T t) { return vector3::lerp(*this, B, t); } + static vector3 lerp(const vector3& A, const vector3& B, const T t) noexcept { return A*t + B*(1.f - t); } + constexpr vector3 lerp(const vector3& B, const T t) const noexcept { return vector3::lerp(*this, B, t); } - static vector3 slerp(vector3 start, vector3 end, T percent) { + static vector3 slerp(vector3 start, vector3 end, T percent) noexcept { T dot = start.dot(end); dot = vector3::clamp(dot, -1.0f, 1.0f); @@ -91,13 +96,13 @@ namespace ace { relative.normalize(); return ((start * cos(theta)) + (relative*sin(theta))); } - vector3 slerp(const vector3& B, const T p) { + constexpr vector3 slerp(const vector3& B, const T p) const noexcept { return vector3::slerp(*this, B, p); } - const T & x() const { return _x; } - const T & y() const { return _y; } - const T & z() const { return _z; } + const T& x() const noexcept { return _x; } + const T& y() const noexcept { return _y; } + const T& z() const noexcept { return _z; } void x(const T val) { _x = val; } void y(const T val) { _y = val; } From 805d5c8b09067f0bbff0cbe3c05b1bfc5219eda3 Mon Sep 17 00:00:00 2001 From: ulteq Date: Sun, 29 Oct 2017 09:38:45 +0100 Subject: [PATCH 021/212] Extensions - Reduce warning level from /Wall to /W4 --- extensions/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index c10bc85479..14ff1a673c 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -26,7 +26,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(ERROR "SUPPORT NOT COMPLETE") elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall /arch:SSE2 /Qpar-report:2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /arch:SSE2 /Qpar-report:2") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /D _DEBUG /MTd /Zi /Ob0 /Od /RTC1") set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS} /MT /O1 /Ob1 /D NDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /O2 /Ob2 /D NDEBUG") From 0189eb86a1f44723e0c180b6e9f062c65f4e3569 Mon Sep 17 00:00:00 2001 From: Glowbal Date: Sun, 29 Oct 2017 15:16:38 +0100 Subject: [PATCH 022/212] Add circleCI yml file --- circle.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000000..7616e4912c --- /dev/null +++ b/circle.yml @@ -0,0 +1,23 @@ +version: 2 +jobs: + build: + docker: + - image: python:3-alpine + steps: + - checkout + - run: + name: Validate SQF And Config style + command: python tools/sqf_validator.py && python tools/config_style_checker.py + deployment: + docker: + - image: python:3-alpine + branch: master + requires: + - build + steps: + - checkout + - deploy: + name: Deploy + command: | + pip install pygithub pygithub3 + python3 tools/deploy.py From 32e3b643a70cb5cf139633f0cb059565e8d097e7 Mon Sep 17 00:00:00 2001 From: Dystopian Date: Sun, 29 Oct 2017 17:41:26 +0200 Subject: [PATCH 023/212] Fix 5.56 Reload Tracer mags are not tracer (#5660) --- addons/smallarms/CfgMagazines.hpp | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/addons/smallarms/CfgMagazines.hpp b/addons/smallarms/CfgMagazines.hpp index a9cc718258..ac55a86f6b 100644 --- a/addons/smallarms/CfgMagazines.hpp +++ b/addons/smallarms/CfgMagazines.hpp @@ -6,36 +6,6 @@ class CfgMagazines { // 2. Remove tracers at bottom of magazine. // 3. Do string updates. - // 5.56mm //////////////////////////////////// - - class 30Rnd_556x45_Stanag : CA_Magazine { - displayname = "5.56mm 30Rnd Mag"; - displaynameshort = "5.56mm"; - - tracersEvery = 0; - lastRoundsTracer = 0; - }; - - class 30Rnd_556x45_Stanag_Tracer_Red: 30Rnd_556x45_Stanag { - displayname = "5.56mm 30Rnd Tracer Mag"; - displaynameshort = "5.56mm"; - }; - - class 30Rnd_556x45_Stanag_Tracer_Green: 30Rnd_556x45_Stanag { - displayname = "5.56mm 30Rnd Tracer Mag"; - displaynameshort = "5.56mm"; - }; - - class 30Rnd_556x45_Stanag_Tracer_Yellow: 30Rnd_556x45_Stanag { - displayname = "5.56mm 30Rnd Tracer Mag"; - displaynameshort = "5.56mm"; - }; - - class 20Rnd_556x45_UW_mag: 30Rnd_556x45_Stanag { - displayname = "5.56mm 20Rnd MEA Mag"; - displaynameshort = "5.56mm MEA"; - }; - // 6.5mm ////////////////////////////////////////// class 30Rnd_65x39_caseless_mag : CA_Magazine { // MX!! From 4bfc956e1a56534bab0407636ab2eb1fe854d4ff Mon Sep 17 00:00:00 2001 From: ulteq Date: Fri, 27 Oct 2017 21:23:24 +0200 Subject: [PATCH 024/212] Advanced Ballistics - Fixes bug in the vanilla drag removal routine * More accurate bullet drop at extreme long ranges * Fixes Client FPS affecting the trajectory --- ace_advanced_ballistics.dll | Bin 273920 -> 273408 bytes ace_advanced_ballistics_x64.dll | Bin 312832 -> 313856 bytes .../functions/fnc_handleFired.sqf | 2 +- .../AdvancedBallistics.cpp | 57 ++++++++++-------- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/ace_advanced_ballistics.dll b/ace_advanced_ballistics.dll index 43698cf95b2b170e2d75f1847cab5c086a398eb9..f0290f05059f59e235718aafd97e9a18ef9637b6 100644 GIT binary patch delta 113960 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

Cx2nta_UU?X{TFcfw|Uu%1b($6Xu7z0 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 diff --git a/ace_advanced_ballistics_x64.dll b/ace_advanced_ballistics_x64.dll index 83858d86e3f8684f6bf28a6d5134db621a7e8bd5..8c712f8cf30cd57afc02c7cff53b1b24ad0c32ea 100644 GIT binary patch delta 109069 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 CM?J{^ delta 107473 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 BZ6g2x diff --git a/addons/advanced_ballistics/functions/fnc_handleFired.sqf b/addons/advanced_ballistics/functions/fnc_handleFired.sqf index f9145ddc37..806f40c624 100644 --- a/addons/advanced_ballistics/functions/fnc_handleFired.sqf +++ b/addons/advanced_ballistics/functions/fnc_handleFired.sqf @@ -112,7 +112,7 @@ if (_caliber > 0 && _bulletLength > 0 && _bulletMass > 0 && _barrelTwist > 0) th GVAR(currentbulletID) = (GVAR(currentbulletID) + 1) % 10000; -"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17", GVAR(currentbulletID), _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _muzzleVelocity, _transonicStabilityCoef, getPosASL _projectile, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), EGVAR(weather,currentOvercast), CBA_missionTime toFixed 6]; +"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17", GVAR(currentbulletID), _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _transonicStabilityCoef, getPosASL _projectile, _bulletVelocity, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), EGVAR(weather,currentOvercast), CBA_missionTime toFixed 6]; GVAR(allBullets) pushBack [_projectile, _caliber, _bulletTraceVisible, GVAR(currentbulletID)]; diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index 4abe35b8fd..8aac4a6349 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -39,8 +39,7 @@ struct Bullet { double stabilityFactor; double twistDirection; double transonicStabilityCoef; - double muzzleVelocity; - double bulletSpeed; + std::vector bulletVelocity; std::vector origin; double latitude; double temperature; @@ -335,7 +334,9 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) double stabilityFactor = 1.5; int twistDirection = 1; double transonicStabilityCoef = 1; - double muzzleVelocity = 850; + char* bulletVelocityArray; + char* bulletVelocityEntry; + std::vector bulletVelocity; char* originArray; char* originEntry; std::vector origin; @@ -368,7 +369,6 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) dragModel = strtol(strtok_s(NULL, ":", &next_token), NULL, 10); stabilityFactor = strtod(strtok_s(NULL, ":", &next_token), NULL); twistDirection = strtol(strtok_s(NULL, ":", &next_token), NULL, 10); - muzzleVelocity = strtod(strtok_s(NULL, ":", &next_token), NULL); transonicStabilityCoef = strtod(strtok_s(NULL, ":", &next_token), NULL); originArray = strtok_s(NULL, ":", &next_token); originArray++; @@ -378,6 +378,14 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) origin.push_back(strtod(originEntry, NULL)); originEntry = strtok_s(NULL, ",", &token); } + bulletVelocityArray = strtok_s(NULL, ":", &next_token); + bulletVelocityArray++; + bulletVelocityArray[strlen(bulletVelocityArray) - 1] = 0; + bulletVelocityEntry = strtok_s(bulletVelocityArray, ",", &token); + while (bulletVelocityEntry != NULL) { + bulletVelocity.push_back(strtod(bulletVelocityEntry, NULL)); + bulletVelocityEntry = strtok_s(NULL, ",", &token); + } latitude = strtod(strtok_s(NULL, ":", &next_token), NULL); temperature = strtod(strtok_s(NULL, ":", &next_token), NULL); altitude = strtod(strtok_s(NULL, ":", &next_token), NULL); @@ -398,8 +406,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) bulletDatabase[index].stabilityFactor = stabilityFactor; bulletDatabase[index].twistDirection = twistDirection; bulletDatabase[index].transonicStabilityCoef = transonicStabilityCoef; - bulletDatabase[index].muzzleVelocity = muzzleVelocity; - bulletDatabase[index].bulletSpeed = muzzleVelocity; + bulletDatabase[index].bulletVelocity = bulletVelocity; bulletDatabase[index].origin = origin; bulletDatabase[index].latitude = latitude / 180 * M_PI; bulletDatabase[index].temperature = temperature; @@ -477,6 +484,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) double windSpeed = 0.0; double windAttenuation = 1.0; double velocityOffset[3] = { 0.0, 0.0, 0.0 }; + double bulletSpeed = sqrt(pow(bulletDatabase[index].bulletVelocity[0], 2) + pow(bulletDatabase[index].bulletVelocity[1], 2) + pow(bulletDatabase[index].bulletVelocity[2], 2)); bulletDatabase[index].lastFrame = tickTime; @@ -522,9 +530,9 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) windSpeed = sqrt(pow(wind[0], 2) + pow(wind[1], 2) + pow(wind[2], 2)); } - trueVelocity[0] = velocity[0] - wind[0]; - trueVelocity[1] = velocity[1] - wind[1]; - trueVelocity[2] = velocity[2] - wind[2]; + trueVelocity[0] = bulletDatabase[index].bulletVelocity[0] - wind[0]; + trueVelocity[1] = bulletDatabase[index].bulletVelocity[1] - wind[1]; + trueVelocity[2] = bulletDatabase[index].bulletVelocity[2] - wind[2]; trueSpeed = sqrt(pow(trueVelocity[0], 2) + pow(trueVelocity[1], 2) + pow(trueVelocity[2], 2)); if (bulletDatabase[index].transonicStabilityCoef < 1.0f && trueSpeed - 60 < SPEED_OF_SOUND(temperature) && trueSpeed > SPEED_OF_SOUND(temperature)) { @@ -544,11 +552,11 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) }; if (bulletDatabase[index].ballisticCoefficients.size() == bulletDatabase[index].velocityBoundaries.size() + 1) { - dragRef = deltaT * bulletDatabase[index].airFriction * bulletDatabase[index].bulletSpeed * bulletDatabase[index].bulletSpeed; + dragRef = deltaT * bulletDatabase[index].airFriction * bulletSpeed * bulletSpeed; - accelRef[0] = (velocity[0] / bulletDatabase[index].bulletSpeed) * dragRef; - accelRef[1] = (velocity[1] / bulletDatabase[index].bulletSpeed) * dragRef; - accelRef[2] = (velocity[2] / bulletDatabase[index].bulletSpeed) * dragRef; + accelRef[0] = (bulletDatabase[index].bulletVelocity[0] / bulletSpeed) * dragRef; + accelRef[1] = (bulletDatabase[index].bulletVelocity[1] / bulletSpeed) * dragRef; + accelRef[2] = (bulletDatabase[index].bulletVelocity[2] / bulletSpeed) * dragRef; velocityOffset[0] -= accelRef[0]; velocityOffset[1] -= accelRef[1]; @@ -577,11 +585,11 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) double airFriction = bulletDatabase[index].airFriction * airDensity / STD_AIR_DENSITY_ICAO; if (airFriction != bulletDatabase[index].airFriction || windSpeed > 0) { - dragRef = deltaT * bulletDatabase[index].airFriction * bulletDatabase[index].bulletSpeed * bulletDatabase[index].bulletSpeed; + dragRef = deltaT * bulletDatabase[index].airFriction * bulletSpeed * bulletSpeed; - accelRef[0] = (velocity[0] / bulletDatabase[index].bulletSpeed) * dragRef; - accelRef[1] = (velocity[1] / bulletDatabase[index].bulletSpeed) * dragRef; - accelRef[2] = (velocity[2] / bulletDatabase[index].bulletSpeed) * dragRef; + accelRef[0] = (bulletDatabase[index].bulletVelocity[0] / bulletSpeed) * dragRef; + accelRef[1] = (bulletDatabase[index].bulletVelocity[1] / bulletSpeed) * dragRef; + accelRef[2] = (bulletDatabase[index].bulletVelocity[2] / bulletSpeed) * dragRef; velocityOffset[0] -= accelRef[0]; velocityOffset[1] -= accelRef[1]; @@ -599,7 +607,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) } if (TOF > 0) { - double bulletDir = atan2(velocity[0], velocity[1]); + double bulletDir = atan2(bulletDatabase[index].bulletVelocity[0], bulletDatabase[index].bulletVelocity[1]); double driftAccel = bulletDatabase[index].twistDirection * (0.0482251 * (bulletDatabase[index].stabilityFactor + 1.2)) / pow(TOF, 0.17); double driftVelocity = 0.0581025 *(bulletDatabase[index].stabilityFactor + 1.2) * pow(TOF, 0.83); double dragCorrection = (driftVelocity / trueSpeed) * drag; @@ -608,18 +616,17 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) } double lat = bulletDatabase[index].latitude; - accel[0] = 2 * EARTH_ANGULAR_SPEED * +(velocity[1] * sin(lat) - velocity[2] * cos(lat)); - accel[1] = 2 * EARTH_ANGULAR_SPEED * -(velocity[0] * sin(lat)); - accel[2] = 2 * EARTH_ANGULAR_SPEED * +(velocity[0] * cos(lat)); + accel[0] = 2 * EARTH_ANGULAR_SPEED * +(bulletDatabase[index].bulletVelocity[1] * sin(lat) - bulletDatabase[index].bulletVelocity[2] * cos(lat)); + accel[1] = 2 * EARTH_ANGULAR_SPEED * -(bulletDatabase[index].bulletVelocity[0] * sin(lat)); + accel[2] = 2 * EARTH_ANGULAR_SPEED * +(bulletDatabase[index].bulletVelocity[0] * cos(lat)); velocityOffset[0] += accel[0] * deltaT; velocityOffset[1] += accel[1] * deltaT; velocityOffset[2] += accel[2] * deltaT; - velocity[0] += velocityOffset[0]; - velocity[1] += velocityOffset[1]; - velocity[2] += velocityOffset[2]; - bulletDatabase[index].bulletSpeed = sqrt(pow(velocity[0], 2) + pow(velocity[1], 2) + pow(velocity[2], 2)); + bulletDatabase[index].bulletVelocity[0] = velocity[0] + velocityOffset[0]; + bulletDatabase[index].bulletVelocity[1] = velocity[1] + velocityOffset[1]; + bulletDatabase[index].bulletVelocity[2] = velocity[2] + velocityOffset[2]; outputStr << "[" << velocityOffset[0] << "," << velocityOffset[1] << "," << velocityOffset[2] << "]"; strncpy_s(output, outputSize, outputStr.str().c_str(), _TRUNCATE); From 048b076f1d295e106dd8936990dcfc58f085fa85 Mon Sep 17 00:00:00 2001 From: ulteq Date: Fri, 27 Oct 2017 22:01:57 +0200 Subject: [PATCH 025/212] Advanced Ballistics - Removed duplicate code --- .../AdvancedBallistics.cpp | 59 +++++++------------ 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index 8aac4a6349..4f32ddbb1c 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -551,17 +551,17 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) bulletDatabase[index].bcDegradation *= pow(0.993, coef); }; + dragRef = -bulletDatabase[index].airFriction * bulletSpeed * bulletSpeed; + + accelRef[0] = (bulletDatabase[index].bulletVelocity[0] / bulletSpeed) * dragRef; + accelRef[1] = (bulletDatabase[index].bulletVelocity[1] / bulletSpeed) * dragRef; + accelRef[2] = (bulletDatabase[index].bulletVelocity[2] / bulletSpeed) * dragRef; + + velocityOffset[0] += accelRef[0] * deltaT; + velocityOffset[1] += accelRef[1] * deltaT; + velocityOffset[2] += accelRef[2] * deltaT; + if (bulletDatabase[index].ballisticCoefficients.size() == bulletDatabase[index].velocityBoundaries.size() + 1) { - dragRef = deltaT * bulletDatabase[index].airFriction * bulletSpeed * bulletSpeed; - - accelRef[0] = (bulletDatabase[index].bulletVelocity[0] / bulletSpeed) * dragRef; - accelRef[1] = (bulletDatabase[index].bulletVelocity[1] / bulletSpeed) * dragRef; - accelRef[2] = (bulletDatabase[index].bulletVelocity[2] / bulletSpeed) * dragRef; - - velocityOffset[0] -= accelRef[0]; - velocityOffset[1] -= accelRef[1]; - velocityOffset[2] -= accelRef[2]; - ballisticCoefficient = bulletDatabase[index].ballisticCoefficients[0]; for (int i = (int)bulletDatabase[index].velocityBoundaries.size() - 1; i >= 0; i = i - 1) { if (trueSpeed < bulletDatabase[index].velocityBoundaries[i]) { @@ -572,45 +572,28 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, bulletDatabase[index].humidity, bulletDatabase[index].atmosphereModel); ballisticCoefficient *= bulletDatabase[index].bcDegradation; - drag = deltaT * calculateRetard(bulletDatabase[index].dragModel, ballisticCoefficient, trueSpeed, SPEED_OF_SOUND(temperature)); - accel[0] = (trueVelocity[0] / trueSpeed) * drag; - accel[1] = (trueVelocity[1] / trueSpeed) * drag; - accel[2] = (trueVelocity[2] / trueSpeed) * drag; - velocityOffset[0] -= accel[0]; - velocityOffset[1] -= accel[1]; - velocityOffset[2] -= accel[2]; + drag = calculateRetard(bulletDatabase[index].dragModel, ballisticCoefficient, trueSpeed, SPEED_OF_SOUND(temperature)); } else { double airDensity = calculateAirDensity(temperature, pressure, bulletDatabase[index].humidity); double airFriction = bulletDatabase[index].airFriction * airDensity / STD_AIR_DENSITY_ICAO; - if (airFriction != bulletDatabase[index].airFriction || windSpeed > 0) { - dragRef = deltaT * bulletDatabase[index].airFriction * bulletSpeed * bulletSpeed; - - accelRef[0] = (bulletDatabase[index].bulletVelocity[0] / bulletSpeed) * dragRef; - accelRef[1] = (bulletDatabase[index].bulletVelocity[1] / bulletSpeed) * dragRef; - accelRef[2] = (bulletDatabase[index].bulletVelocity[2] / bulletSpeed) * dragRef; - - velocityOffset[0] -= accelRef[0]; - velocityOffset[1] -= accelRef[1]; - velocityOffset[2] -= accelRef[2]; - - drag = deltaT * airFriction * trueSpeed * trueSpeed; - accel[0] = (trueVelocity[0] / trueSpeed) * drag; - accel[1] = (trueVelocity[1] / trueSpeed) * drag; - accel[2] = (trueVelocity[2] / trueSpeed) * drag; - - velocityOffset[0] += accel[0]; - velocityOffset[1] += accel[1]; - velocityOffset[2] += accel[2]; - } + drag = -airFriction * trueSpeed * trueSpeed; } + accel[0] = (trueVelocity[0] / trueSpeed) * drag; + accel[1] = (trueVelocity[1] / trueSpeed) * drag; + accel[2] = (trueVelocity[2] / trueSpeed) * drag; + + velocityOffset[0] -= accel[0] * deltaT; + velocityOffset[1] -= accel[1] * deltaT; + velocityOffset[2] -= accel[2] * deltaT; + if (TOF > 0) { double bulletDir = atan2(bulletDatabase[index].bulletVelocity[0], bulletDatabase[index].bulletVelocity[1]); double driftAccel = bulletDatabase[index].twistDirection * (0.0482251 * (bulletDatabase[index].stabilityFactor + 1.2)) / pow(TOF, 0.17); double driftVelocity = 0.0581025 *(bulletDatabase[index].stabilityFactor + 1.2) * pow(TOF, 0.83); - double dragCorrection = (driftVelocity / trueSpeed) * drag; + double dragCorrection = (driftVelocity / trueSpeed) * drag * deltaT; velocityOffset[0] += sin(bulletDir + M_PI / 2) * (driftAccel * deltaT + dragCorrection); velocityOffset[1] += cos(bulletDir + M_PI / 2) * (driftAccel * deltaT + dragCorrection); } From 8397e1cf4a325795899f3c3c3c71c5fc59714790 Mon Sep 17 00:00:00 2001 From: ulteq Date: Mon, 30 Oct 2017 17:16:21 +0100 Subject: [PATCH 026/212] Tools - Fixed typo (#5712) --- tools/generate_airfriction_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/generate_airfriction_config.py b/tools/generate_airfriction_config.py index 260cdc3df2..c0690f7158 100644 --- a/tools/generate_airfriction_config.py +++ b/tools/generate_airfriction_config.py @@ -235,7 +235,7 @@ def tofTillM2(m, v, dM, bc): def dropAtM(m, v, a): lx = 0 - cly = 0 + ly = 0 dx = 0 dy = 0 vx = v @@ -257,7 +257,7 @@ def dropAtM(m, v, a): def dropAtM2(m, v, dM, bc): lx = 0 - cly = 0 + ly = 0 dx = 0 dy = 0 vx = v From 25344deb8052497f1090deed50d4c39278fe6784 Mon Sep 17 00:00:00 2001 From: ulteq Date: Tue, 31 Oct 2017 10:58:12 +0100 Subject: [PATCH 027/212] Ballistics - 7.62x54R muzzle velocity correction (#5711) * Closes: https://github.com/acemod/ACE3/pull/5470 * Reference: https://github.com/acemod/ACE3/files/1272583/mousin.barrel.experiment.pdf --- addons/atragmx/functions/fnc_initGunList.sqf | 2 +- addons/ballistics/CfgAmmo.hpp | 13 +++++++------ addons/ballistics/CfgMagazines.hpp | 6 +++--- addons/ballistics/CfgWeapons.hpp | 4 ++-- extras/airFrictionAnalysis.txt | 20 ++++++++++---------- tools/generate_airfriction_config.py | 4 ++-- 6 files changed, 25 insertions(+), 24 deletions(-) diff --git a/addons/atragmx/functions/fnc_initGunList.sqf b/addons/atragmx/functions/fnc_initGunList.sqf index 6c61aee16b..c677da3704 100644 --- a/addons/atragmx/functions/fnc_initGunList.sqf +++ b/addons/atragmx/functions/fnc_initGunList.sqf @@ -54,7 +54,7 @@ if (_resetGunList) then { [".300WM Mk248 Mod1" , 839, 100, 0.0841417, -0.00063027, 7.37, 0, 2, 10, 120, 0, 0, 14.26, 7.80, 25.40, 0.619, 1, "ICAO", [[-15,820],[0,827],[10,834],[15,839],[25,853],[30,862],[35,873]] , [[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]], true], [".300WM Berger OTM" , 792, 100, 0.0891300, -0.00055262, 7.37, 0, 2, 10, 120, 0, 0, 14.90, 7.80, 25.40, 0.715, 1, "ICAO", [[-15,773],[0,780],[10,787],[15,792],[25,806],[30,815],[35,826]] , [[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]], true], - ["7.62x54mmR" , 812, 100, 0.0868171, -0.00102329, 7.11, 0, 2, 10, 120, 0, 0, 9.849, 7.92, 24.13, 0.400, 1, "ICAO", [[-15,793],[0,800],[10,807],[15,812],[25,826],[30,835],[35,846]] , [[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]], true], + ["7.62x54mmR" , 828, 100, 0.0853677, -0.00103739, 7.11, 0, 2, 10, 120, 0, 0, 9.849, 7.92, 24.13, 0.400, 1, "ICAO", [[-15,809],[0,816],[10,823],[15,828],[25,842],[30,851],[35,862]] , [[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]], true], ["7.62x51mm M80" , 802, 100, 0.0909184, -0.00103711, 7.62, 0, 2, 10, 120, 0, 0, 9.461, 7.82, 25.40, 0.398, 1, "ICAO", [[-15,783],[0,790],[10,797],[15,802],[25,816],[30,825],[35,836]] , [[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]], true], ["7.62x51mm M118LR" , 757, 100, 0.0958841, -0.00085157, 7.62, 0, 2, 10, 120, 0, 0, 11.34, 7.82, 25.40, 0.482, 1, "ICAO", [[-15,738],[0,745],[10,752],[15,757],[25,771],[30,780],[35,791]] , [[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]], true], diff --git a/addons/ballistics/CfgAmmo.hpp b/addons/ballistics/CfgAmmo.hpp index acbb8a5953..c12fc38e7f 100644 --- a/addons/ballistics/CfgAmmo.hpp +++ b/addons/ballistics/CfgAmmo.hpp @@ -298,7 +298,8 @@ class CfgAmmo { ACE_barrelLengths[]={508.0, 609.6, 660.4}; }; class B_762x54_Ball: B_762x51_Ball { - airFriction=-0.00102329; + airFriction=-0.00101071; + typicalSpeed=835; ACE_caliber=7.925; ACE_bulletLength=28.956; ACE_bulletMass=9.8496; @@ -307,12 +308,12 @@ class CfgAmmo { ACE_velocityBoundaries[]={}; ACE_standardAtmosphere="ICAO"; ACE_dragModel=1; - ACE_muzzleVelocities[]={700, 800, 820, 833}; - ACE_barrelLengths[]={406.4, 508.0, 609.6, 660.4}; + ACE_muzzleVelocities[]={760, 795, 835, 865}; + ACE_barrelLengths[]={406.4, 508.0, 604.5, 736.6}; }; class B_762x54_Tracer_Green; class ACE_762x54_Ball_7T2 : B_762x54_Tracer_Green { - airFriction=-0.00106104; + airFriction=-0.00103739; typicalSpeed=800; tracerStartTime=0.073; // Based on the 7T2 which burns three seconds tracerEndTime=3; @@ -324,8 +325,8 @@ class CfgAmmo { ACE_velocityBoundaries[]={}; ACE_standardAtmosphere="ICAO"; ACE_dragModel=1; - ACE_muzzleVelocities[]={680, 750, 798, 800}; - ACE_barrelLengths[]={406.4, 508.0, 609.6, 660.4}; + ACE_muzzleVelocities[]={735, 770, 809, 838}; + ACE_barrelLengths[]={406.4, 508.0, 604.5, 736.6}; }; class B_762x39_Ball_F : BulletBase { airFriction=-0.00154815; diff --git a/addons/ballistics/CfgMagazines.hpp b/addons/ballistics/CfgMagazines.hpp index 2b9088408b..a90e46429e 100644 --- a/addons/ballistics/CfgMagazines.hpp +++ b/addons/ballistics/CfgMagazines.hpp @@ -381,7 +381,7 @@ class CfgMagazines { }; class 10Rnd_762x54_Mag: 10Rnd_762x51_Mag { - initSpeed = 800; + initSpeed = 836; }; class ACE_10Rnd_762x54_Tracer_mag: 10Rnd_762x54_Mag { author = ECSTRING(common,ACETeam); @@ -389,12 +389,12 @@ class CfgMagazines { displayName = CSTRING(10Rnd_762x54_Tracer_mag_Name); displayNameShort = CSTRING(10Rnd_762x54_Tracer_mag_NameShort); descriptionShort = CSTRING(10Rnd_762x54_Tracer_mag_Description); - initSpeed = 800; + initSpeed = 809; tracersEvery = 1; }; class 150Rnd_762x54_Box: 150Rnd_762x51_Box { - initSpeed = 750; + initSpeed = 836; }; class 150Rnd_93x64_Mag: CA_Magazine { diff --git a/addons/ballistics/CfgWeapons.hpp b/addons/ballistics/CfgWeapons.hpp index 9c18579276..a8bbf61a7f 100644 --- a/addons/ballistics/CfgWeapons.hpp +++ b/addons/ballistics/CfgWeapons.hpp @@ -202,7 +202,7 @@ class CfgWeapons { // Negev NG7 class LMG_Zafir_F: Rifle_Long_Base_F { - initSpeed = -1.00333; + initSpeed = -0.931071; ACE_barrelTwist = 304.8; ACE_barrelLength = 459.74; }; @@ -563,7 +563,7 @@ class CfgWeapons { "10Rnd_762x54_Mag", "ACE_10Rnd_762x54_Tracer_mag" }; - initSpeed = -1.025; + initSpeed = -1.00019; ACE_barrelTwist = 241.3; ACE_barrelLength = 609.6; }; diff --git a/extras/airFrictionAnalysis.txt b/extras/airFrictionAnalysis.txt index 873525af45..ad06f309d2 100644 --- a/extras/airFrictionAnalysis.txt +++ b/extras/airFrictionAnalysis.txt @@ -161,11 +161,11 @@ Optimal airFriction: 0.00055262 ########################################## Ammo Class: B_762x54_Ball MaxRanges (m): [500, 800, 800] -MuzzleVelocities (m/s): [700, 820, 833] -Max. Velocity diff (m/s): 13.84 -Max. Drop diff (cm): 5.42 -Max. Tof diff (ms): 12.5 -Optimal airFriction: 0.00102329 +MuzzleVelocities (m/s): [760, 835, 865] +Max. Velocity diff (m/s): 13.37 +Max. Drop diff (cm): 5.71 +Max. Tof diff (ms): 16.5 +Optimal airFriction: 0.00101071 ########################################## Ammo Class: ACE_762x35_Ball MaxRanges (m): [400, 500] @@ -185,11 +185,11 @@ Optimal airFriction: 0.00154815 ########################################## Ammo Class: ACE_762x54_Ball_7T2 MaxRanges (m): [500, 800, 800] -MuzzleVelocities (m/s): [680, 750, 800] -Max. Velocity diff (m/s): 9.37 -Max. Drop diff (cm): 7.72 -Max. Tof diff (ms): 9.5 -Optimal airFriction: 0.00106104 +MuzzleVelocities (m/s): [735, 809, 838] +Max. Velocity diff (m/s): 12.14 +Max. Drop diff (cm): 5.82 +Max. Tof diff (ms): 14.5 +Optimal airFriction: 0.00103739 ########################################## Ammo Class: ACE_303_Ball MaxRanges (m): [900, 1000] diff --git a/tools/generate_airfriction_config.py b/tools/generate_airfriction_config.py index c0690f7158..ac312c08ba 100644 --- a/tools/generate_airfriction_config.py +++ b/tools/generate_airfriction_config.py @@ -481,10 +481,10 @@ ammoList = [["B_556x45_Ball", [300, 500, 500], [750, 870, 910], 7, 0.151], ["ACE_762x67_Ball_Mk248_Mod_0", [800, 900, 900], [865, 900, 924], 7, 0.268], ["ACE_762x67_Ball_Mk248_Mod_1", [800, 900, 900], [847, 867, 877], 7, 0.310], ["ACE_762x67_Ball_Berger_Hybrid_OTM", [900, 1000, 1000], [800, 853, 884], 7, 0.358], - ["B_762x54_Ball", [500, 800, 800], [700, 820, 833], 1, 0.4], + ["B_762x54_Ball", [500, 800, 800], [760, 835, 865], 1, 0.4], ["ACE_762x35_Ball", [400, 500], [620, 675], 1, 0.330], ["ACE_762x39_Ball", [400, 600], [650, 750], 1, 0.275], - ["ACE_762x54_Ball_7T2", [500, 800, 800], [680, 750, 800], 1, 0.395], + ["ACE_762x54_Ball_7T2", [500, 800, 800], [735, 809, 838], 1, 0.395], ["ACE_303_Ball", [900, 1000], [748, 765], 1, 0.493], ["B_93x64_Ball", [900, 1000], [850, 880], 1, 0.368], ["B_408_Ball", [1600,1600], [862, 872], 7, 0.434], From ba97bb20fe1607c554ac16aad7f9e9fb9061707d Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Tue, 31 Oct 2017 12:13:55 -0500 Subject: [PATCH 028/212] Tagging - For lastUsed use random if not used yet (#5687) --- addons/tagging/functions/fnc_quickTag.sqf | 7 +++++-- addons/tagging/stringtable.xml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/tagging/functions/fnc_quickTag.sqf b/addons/tagging/functions/fnc_quickTag.sqf index 7f0a1d706e..63a93e9946 100644 --- a/addons/tagging/functions/fnc_quickTag.sqf +++ b/addons/tagging/functions/fnc_quickTag.sqf @@ -22,19 +22,22 @@ if (GVAR(quickTag) == 0) exitWith {}; params ["_unit"]; private _possibleTags = []; +private _useRandom = false; // Last Used if (GVAR(quickTag) == 1) then { private _lastUsedTagClass = _unit getVariable [QGVAR(lastUsedTag), nil]; - if (!isNil "_lastUsedTagClass") then { + if (isNil "_lastUsedTagClass") then { + _useRandom = true; + } else { private _lastUsedTag = GVAR(cachedTags) select {(_x select 0) == _lastUsedTagClass}; _possibleTags = _lastUsedTag; }; }; // Random X -if (GVAR(quickTag == 2)) then { +if ((GVAR(quickTag) == 2) || _useRandom) then { private _xTags = GVAR(cachedTags) select {(_x select 0) in ["ACE_XBlack", "ACE_XRed", "ACE_XGreen", "ACE_XBlue"]}; _possibleTags = _xTags; }; diff --git a/addons/tagging/stringtable.xml b/addons/tagging/stringtable.xml index 8b6a9ff638..71da1b6f8e 100644 --- a/addons/tagging/stringtable.xml +++ b/addons/tagging/stringtable.xml @@ -26,7 +26,7 @@ 定義噴漆系統預設設定 - Quick Tag + Spray Paint - Quick Tag Быстрый маркер クイック タグ Szybkie tagowanie From 52450bcb76866e0baa476955557382b10482c682 Mon Sep 17 00:00:00 2001 From: Tittoffer Date: Tue, 31 Oct 2017 18:48:08 +0100 Subject: [PATCH 029/212] Fortify not fortify (#5717) --- docs/wiki/featurex/fortify.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/wiki/featurex/fortify.md b/docs/wiki/featurex/fortify.md index 0a66f93acd..3fe2863ae7 100644 --- a/docs/wiki/featurex/fortify.md +++ b/docs/wiki/featurex/fortify.md @@ -1,6 +1,6 @@ --- layout: wiki -title: fortify +title: Fortify description: Enables player to build fortifications. group: feature category: interaction From 50b569f62cd29d3b43728d529cf78c700da7840f Mon Sep 17 00:00:00 2001 From: Andrea Verano Date: Wed, 1 Nov 2017 21:59:38 +0100 Subject: [PATCH 030/212] Italian Translation Update (#5719) Added: -New string in "pylons" -New string in "weaponselect" --- addons/pylons/stringtable.xml | 1 + addons/weaponselect/stringtable.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/addons/pylons/stringtable.xml b/addons/pylons/stringtable.xml index 241b358b04..74b532c2e2 100644 --- a/addons/pylons/stringtable.xml +++ b/addons/pylons/stringtable.xml @@ -66,6 +66,7 @@ Vehicle too far + Veicolo troppo lontano Enable Pylons Menu diff --git a/addons/weaponselect/stringtable.xml b/addons/weaponselect/stringtable.xml index 054a0f94e7..d79892e49b 100644 --- a/addons/weaponselect/stringtable.xml +++ b/addons/weaponselect/stringtable.xml @@ -371,6 +371,7 @@ Toggle Collision Lights + Attiva Luci di Collisione From de40274d37761bae31e4054180c8d842172102cd Mon Sep 17 00:00:00 2001 From: Jo David Date: Thu, 2 Nov 2017 15:10:14 +0100 Subject: [PATCH 031/212] fix code block styling --- docs/css/app.css | 2 +- docs/js/footer.min.js | 12 +- docs/package-lock.json | 3 + docs/src/package-lock.json | 4465 +++++++++++++++++++++++++++++++++ docs/src/scss/ui/_syntax.scss | 2 +- 5 files changed, 4476 insertions(+), 8 deletions(-) create mode 100644 docs/package-lock.json create mode 100644 docs/src/package-lock.json diff --git a/docs/css/app.css b/docs/css/app.css index 6621799c85..8130470b22 100644 --- a/docs/css/app.css +++ b/docs/css/app.css @@ -1,4 +1,4 @@ /*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}meta.foundation-version{font-family:"/5.5.1/"}meta.foundation-mq-small{font-family:"/only screen/";width:0em}meta.foundation-mq-small-only{font-family:"/only screen and (max-width: 40em)/";width:0em}meta.foundation-mq-medium{font-family:"/only screen and (min-width:40.0625em)/";width:40.0625em}meta.foundation-mq-medium-only{font-family:"/only screen and (min-width:40.0625em) and (max-width:64em)/";width:40.0625em}meta.foundation-mq-large{font-family:"/only screen and (min-width:64.0625em)/";width:64.0625em}meta.foundation-mq-large-only{font-family:"/only screen and (min-width:64.0625em) and (max-width:90em)/";width:64.0625em}meta.foundation-mq-xlarge{font-family:"/only screen and (min-width:90.0625em)/";width:90.0625em}meta.foundation-mq-xlarge-only{font-family:"/only screen and (min-width:90.0625em) and (max-width:120em)/";width:90.0625em}meta.foundation-mq-xxlarge{font-family:"/only screen and (min-width:120.0625em)/";width:120.0625em}meta.foundation-data-attribute-namespace{font-family:false}html,body{height:100%}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html,body{font-size:100%}body{background:#fff;color:#222;padding:0;margin:0;font-family:"Open Sans","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;font-weight:400;font-style:normal;line-height:1.5;position:relative;cursor:auto}a:hover{cursor:pointer}img{max-width:100%;height:auto}img{-ms-interpolation-mode:bicubic}#map_canvas img,#map_canvas embed,#map_canvas object,.map_canvas img,.map_canvas embed,.map_canvas object{max-width:none !important}.left{float:left !important}.right{float:right !important}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.hide{display:none}.invisible{visibility:hidden}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}img{display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px}select{width:100%}[class*="block-grid-"]{display:block;padding:0;margin:0 -.625rem}[class*="block-grid-"]:before,[class*="block-grid-"]:after{content:" ";display:table}[class*="block-grid-"]:after{clear:both}[class*="block-grid-"]>li{display:block;height:auto;float:left;padding:0 .625rem 1.25rem}@media only screen{.small-block-grid-1>li{width:100%;list-style:none}.small-block-grid-1>li:nth-of-type(1n){clear:none}.small-block-grid-1>li:nth-of-type(1n+1){clear:both}.small-block-grid-2>li{width:50%;list-style:none}.small-block-grid-2>li:nth-of-type(1n){clear:none}.small-block-grid-2>li:nth-of-type(2n+1){clear:both}.small-block-grid-3>li{width:33.3333333333%;list-style:none}.small-block-grid-3>li:nth-of-type(1n){clear:none}.small-block-grid-3>li:nth-of-type(3n+1){clear:both}.small-block-grid-4>li{width:25%;list-style:none}.small-block-grid-4>li:nth-of-type(1n){clear:none}.small-block-grid-4>li:nth-of-type(4n+1){clear:both}.small-block-grid-5>li{width:20%;list-style:none}.small-block-grid-5>li:nth-of-type(1n){clear:none}.small-block-grid-5>li:nth-of-type(5n+1){clear:both}.small-block-grid-6>li{width:16.6666666667%;list-style:none}.small-block-grid-6>li:nth-of-type(1n){clear:none}.small-block-grid-6>li:nth-of-type(6n+1){clear:both}.small-block-grid-7>li{width:14.2857142857%;list-style:none}.small-block-grid-7>li:nth-of-type(1n){clear:none}.small-block-grid-7>li:nth-of-type(7n+1){clear:both}.small-block-grid-8>li{width:12.5%;list-style:none}.small-block-grid-8>li:nth-of-type(1n){clear:none}.small-block-grid-8>li:nth-of-type(8n+1){clear:both}.small-block-grid-9>li{width:11.1111111111%;list-style:none}.small-block-grid-9>li:nth-of-type(1n){clear:none}.small-block-grid-9>li:nth-of-type(9n+1){clear:both}.small-block-grid-10>li{width:10%;list-style:none}.small-block-grid-10>li:nth-of-type(1n){clear:none}.small-block-grid-10>li:nth-of-type(10n+1){clear:both}.small-block-grid-11>li{width:9.0909090909%;list-style:none}.small-block-grid-11>li:nth-of-type(1n){clear:none}.small-block-grid-11>li:nth-of-type(11n+1){clear:both}.small-block-grid-12>li{width:8.3333333333%;list-style:none}.small-block-grid-12>li:nth-of-type(1n){clear:none}.small-block-grid-12>li:nth-of-type(12n+1){clear:both}}@media only screen and (min-width: 40.0625em){.medium-block-grid-1>li{width:100%;list-style:none}.medium-block-grid-1>li:nth-of-type(1n){clear:none}.medium-block-grid-1>li:nth-of-type(1n+1){clear:both}.medium-block-grid-2>li{width:50%;list-style:none}.medium-block-grid-2>li:nth-of-type(1n){clear:none}.medium-block-grid-2>li:nth-of-type(2n+1){clear:both}.medium-block-grid-3>li{width:33.3333333333%;list-style:none}.medium-block-grid-3>li:nth-of-type(1n){clear:none}.medium-block-grid-3>li:nth-of-type(3n+1){clear:both}.medium-block-grid-4>li{width:25%;list-style:none}.medium-block-grid-4>li:nth-of-type(1n){clear:none}.medium-block-grid-4>li:nth-of-type(4n+1){clear:both}.medium-block-grid-5>li{width:20%;list-style:none}.medium-block-grid-5>li:nth-of-type(1n){clear:none}.medium-block-grid-5>li:nth-of-type(5n+1){clear:both}.medium-block-grid-6>li{width:16.6666666667%;list-style:none}.medium-block-grid-6>li:nth-of-type(1n){clear:none}.medium-block-grid-6>li:nth-of-type(6n+1){clear:both}.medium-block-grid-7>li{width:14.2857142857%;list-style:none}.medium-block-grid-7>li:nth-of-type(1n){clear:none}.medium-block-grid-7>li:nth-of-type(7n+1){clear:both}.medium-block-grid-8>li{width:12.5%;list-style:none}.medium-block-grid-8>li:nth-of-type(1n){clear:none}.medium-block-grid-8>li:nth-of-type(8n+1){clear:both}.medium-block-grid-9>li{width:11.1111111111%;list-style:none}.medium-block-grid-9>li:nth-of-type(1n){clear:none}.medium-block-grid-9>li:nth-of-type(9n+1){clear:both}.medium-block-grid-10>li{width:10%;list-style:none}.medium-block-grid-10>li:nth-of-type(1n){clear:none}.medium-block-grid-10>li:nth-of-type(10n+1){clear:both}.medium-block-grid-11>li{width:9.0909090909%;list-style:none}.medium-block-grid-11>li:nth-of-type(1n){clear:none}.medium-block-grid-11>li:nth-of-type(11n+1){clear:both}.medium-block-grid-12>li{width:8.3333333333%;list-style:none}.medium-block-grid-12>li:nth-of-type(1n){clear:none}.medium-block-grid-12>li:nth-of-type(12n+1){clear:both}}@media only screen and (min-width: 64.0625em){.large-block-grid-1>li{width:100%;list-style:none}.large-block-grid-1>li:nth-of-type(1n){clear:none}.large-block-grid-1>li:nth-of-type(1n+1){clear:both}.large-block-grid-2>li{width:50%;list-style:none}.large-block-grid-2>li:nth-of-type(1n){clear:none}.large-block-grid-2>li:nth-of-type(2n+1){clear:both}.large-block-grid-3>li{width:33.3333333333%;list-style:none}.large-block-grid-3>li:nth-of-type(1n){clear:none}.large-block-grid-3>li:nth-of-type(3n+1){clear:both}.large-block-grid-4>li{width:25%;list-style:none}.large-block-grid-4>li:nth-of-type(1n){clear:none}.large-block-grid-4>li:nth-of-type(4n+1){clear:both}.large-block-grid-5>li{width:20%;list-style:none}.large-block-grid-5>li:nth-of-type(1n){clear:none}.large-block-grid-5>li:nth-of-type(5n+1){clear:both}.large-block-grid-6>li{width:16.6666666667%;list-style:none}.large-block-grid-6>li:nth-of-type(1n){clear:none}.large-block-grid-6>li:nth-of-type(6n+1){clear:both}.large-block-grid-7>li{width:14.2857142857%;list-style:none}.large-block-grid-7>li:nth-of-type(1n){clear:none}.large-block-grid-7>li:nth-of-type(7n+1){clear:both}.large-block-grid-8>li{width:12.5%;list-style:none}.large-block-grid-8>li:nth-of-type(1n){clear:none}.large-block-grid-8>li:nth-of-type(8n+1){clear:both}.large-block-grid-9>li{width:11.1111111111%;list-style:none}.large-block-grid-9>li:nth-of-type(1n){clear:none}.large-block-grid-9>li:nth-of-type(9n+1){clear:both}.large-block-grid-10>li{width:10%;list-style:none}.large-block-grid-10>li:nth-of-type(1n){clear:none}.large-block-grid-10>li:nth-of-type(10n+1){clear:both}.large-block-grid-11>li{width:9.0909090909%;list-style:none}.large-block-grid-11>li:nth-of-type(1n){clear:none}.large-block-grid-11>li:nth-of-type(11n+1){clear:both}.large-block-grid-12>li{width:8.3333333333%;list-style:none}.large-block-grid-12>li:nth-of-type(1n){clear:none}.large-block-grid-12>li:nth-of-type(12n+1){clear:both}}button,.button{border-style:solid;border-width:0;cursor:pointer;font-family:"Open Sans","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:normal;margin:0 0 1.25rem;position:relative;text-decoration:none;text-align:center;-webkit-appearance:none;-moz-appearance:none;border-radius:0;display:inline-block;padding-top:1rem;padding-right:2rem;padding-bottom:1.0625rem;padding-left:2rem;font-size:1rem;background-color:#ba2619;border-color:#951e14;color:#fff;transition:background-color 300ms ease-out}button:hover,button:focus,.button:hover,.button:focus{background-color:#951e14}button:hover,button:focus,.button:hover,.button:focus{color:#fff}button.secondary,.button.secondary{background-color:#e7e7e7;border-color:#b9b9b9;color:#333}button.secondary:hover,button.secondary:focus,.button.secondary:hover,.button.secondary:focus{background-color:#b9b9b9}button.secondary:hover,button.secondary:focus,.button.secondary:hover,.button.secondary:focus{color:#333}button.success,.button.success{background-color:#43AC6A;border-color:#368a55;color:#fff}button.success:hover,button.success:focus,.button.success:hover,.button.success:focus{background-color:#368a55}button.success:hover,button.success:focus,.button.success:hover,.button.success:focus{color:#fff}button.alert,.button.alert{background-color:#f04124;border-color:#cf2a0e;color:#fff}button.alert:hover,button.alert:focus,.button.alert:hover,.button.alert:focus{background-color:#cf2a0e}button.alert:hover,button.alert:focus,.button.alert:hover,.button.alert:focus{color:#fff}button.warning,.button.warning{background-color:#f08a24;border-color:#cf6e0e;color:#fff}button.warning:hover,button.warning:focus,.button.warning:hover,.button.warning:focus{background-color:#cf6e0e}button.warning:hover,button.warning:focus,.button.warning:hover,.button.warning:focus{color:#fff}button.info,.button.info{background-color:#a0d3e8;border-color:#61b6d9;color:#333}button.info:hover,button.info:focus,.button.info:hover,.button.info:focus{background-color:#61b6d9}button.info:hover,button.info:focus,.button.info:hover,.button.info:focus{color:#fff}button.large,.button.large{padding-top:1.125rem;padding-right:2.25rem;padding-bottom:1.1875rem;padding-left:2.25rem;font-size:1.25rem}button.small,.button.small{padding-top:.875rem;padding-right:1.75rem;padding-bottom:.9375rem;padding-left:1.75rem;font-size:.8125rem}button.tiny,.button.tiny{padding-top:.625rem;padding-right:1.25rem;padding-bottom:.6875rem;padding-left:1.25rem;font-size:.6875rem}button.expand,.button.expand{padding-right:0;padding-left:0;width:100%}button.left-align,.button.left-align{text-align:left;text-indent:.75rem}button.right-align,.button.right-align{text-align:right;padding-right:.75rem}button.radius,.button.radius{border-radius:3px}button.round,.button.round{border-radius:1000px}button.disabled,button[disabled],.button.disabled,.button[disabled]{background-color:#ba2619;border-color:#951e14;color:#fff;cursor:default;opacity:.7;box-shadow:none}button.disabled:hover,button.disabled:focus,button[disabled]:hover,button[disabled]:focus,.button.disabled:hover,.button.disabled:focus,.button[disabled]:hover,.button[disabled]:focus{background-color:#951e14}button.disabled:hover,button.disabled:focus,button[disabled]:hover,button[disabled]:focus,.button.disabled:hover,.button.disabled:focus,.button[disabled]:hover,.button[disabled]:focus{color:#fff}button.disabled:hover,button.disabled:focus,button[disabled]:hover,button[disabled]:focus,.button.disabled:hover,.button.disabled:focus,.button[disabled]:hover,.button[disabled]:focus{background-color:#ba2619}button.disabled.secondary,button[disabled].secondary,.button.disabled.secondary,.button[disabled].secondary{background-color:#e7e7e7;border-color:#b9b9b9;color:#333;cursor:default;opacity:.7;box-shadow:none}button.disabled.secondary:hover,button.disabled.secondary:focus,button[disabled].secondary:hover,button[disabled].secondary:focus,.button.disabled.secondary:hover,.button.disabled.secondary:focus,.button[disabled].secondary:hover,.button[disabled].secondary:focus{background-color:#b9b9b9}button.disabled.secondary:hover,button.disabled.secondary:focus,button[disabled].secondary:hover,button[disabled].secondary:focus,.button.disabled.secondary:hover,.button.disabled.secondary:focus,.button[disabled].secondary:hover,.button[disabled].secondary:focus{color:#333}button.disabled.secondary:hover,button.disabled.secondary:focus,button[disabled].secondary:hover,button[disabled].secondary:focus,.button.disabled.secondary:hover,.button.disabled.secondary:focus,.button[disabled].secondary:hover,.button[disabled].secondary:focus{background-color:#e7e7e7}button.disabled.success,button[disabled].success,.button.disabled.success,.button[disabled].success{background-color:#43AC6A;border-color:#368a55;color:#fff;cursor:default;opacity:.7;box-shadow:none}button.disabled.success:hover,button.disabled.success:focus,button[disabled].success:hover,button[disabled].success:focus,.button.disabled.success:hover,.button.disabled.success:focus,.button[disabled].success:hover,.button[disabled].success:focus{background-color:#368a55}button.disabled.success:hover,button.disabled.success:focus,button[disabled].success:hover,button[disabled].success:focus,.button.disabled.success:hover,.button.disabled.success:focus,.button[disabled].success:hover,.button[disabled].success:focus{color:#fff}button.disabled.success:hover,button.disabled.success:focus,button[disabled].success:hover,button[disabled].success:focus,.button.disabled.success:hover,.button.disabled.success:focus,.button[disabled].success:hover,.button[disabled].success:focus{background-color:#43AC6A}button.disabled.alert,button[disabled].alert,.button.disabled.alert,.button[disabled].alert{background-color:#f04124;border-color:#cf2a0e;color:#fff;cursor:default;opacity:.7;box-shadow:none}button.disabled.alert:hover,button.disabled.alert:focus,button[disabled].alert:hover,button[disabled].alert:focus,.button.disabled.alert:hover,.button.disabled.alert:focus,.button[disabled].alert:hover,.button[disabled].alert:focus{background-color:#cf2a0e}button.disabled.alert:hover,button.disabled.alert:focus,button[disabled].alert:hover,button[disabled].alert:focus,.button.disabled.alert:hover,.button.disabled.alert:focus,.button[disabled].alert:hover,.button[disabled].alert:focus{color:#fff}button.disabled.alert:hover,button.disabled.alert:focus,button[disabled].alert:hover,button[disabled].alert:focus,.button.disabled.alert:hover,.button.disabled.alert:focus,.button[disabled].alert:hover,.button[disabled].alert:focus{background-color:#f04124}button.disabled.warning,button[disabled].warning,.button.disabled.warning,.button[disabled].warning{background-color:#f08a24;border-color:#cf6e0e;color:#fff;cursor:default;opacity:.7;box-shadow:none}button.disabled.warning:hover,button.disabled.warning:focus,button[disabled].warning:hover,button[disabled].warning:focus,.button.disabled.warning:hover,.button.disabled.warning:focus,.button[disabled].warning:hover,.button[disabled].warning:focus{background-color:#cf6e0e}button.disabled.warning:hover,button.disabled.warning:focus,button[disabled].warning:hover,button[disabled].warning:focus,.button.disabled.warning:hover,.button.disabled.warning:focus,.button[disabled].warning:hover,.button[disabled].warning:focus{color:#fff}button.disabled.warning:hover,button.disabled.warning:focus,button[disabled].warning:hover,button[disabled].warning:focus,.button.disabled.warning:hover,.button.disabled.warning:focus,.button[disabled].warning:hover,.button[disabled].warning:focus{background-color:#f08a24}button.disabled.info,button[disabled].info,.button.disabled.info,.button[disabled].info{background-color:#a0d3e8;border-color:#61b6d9;color:#333;cursor:default;opacity:.7;box-shadow:none}button.disabled.info:hover,button.disabled.info:focus,button[disabled].info:hover,button[disabled].info:focus,.button.disabled.info:hover,.button.disabled.info:focus,.button[disabled].info:hover,.button[disabled].info:focus{background-color:#61b6d9}button.disabled.info:hover,button.disabled.info:focus,button[disabled].info:hover,button[disabled].info:focus,.button.disabled.info:hover,.button.disabled.info:focus,.button[disabled].info:hover,.button[disabled].info:focus{color:#fff}button.disabled.info:hover,button.disabled.info:focus,button[disabled].info:hover,button[disabled].info:focus,.button.disabled.info:hover,.button.disabled.info:focus,.button[disabled].info:hover,.button[disabled].info:focus{background-color:#a0d3e8}button::-moz-focus-inner{border:0;padding:0}@media only screen and (min-width: 40.0625em){button,.button{display:inline-block}}.clearing-thumbs,[data-clearing]{margin-bottom:0;margin-left:0;list-style:none}.clearing-thumbs:before,.clearing-thumbs:after,[data-clearing]:before,[data-clearing]:after{content:" ";display:table}.clearing-thumbs:after,[data-clearing]:after{clear:both}.clearing-thumbs li,[data-clearing] li{float:left;margin-right:10px}.clearing-thumbs[class*="block-grid-"] li,[data-clearing][class*="block-grid-"] li{margin-right:0}.clearing-blackout{background:#333;position:fixed;width:100%;height:100%;top:0;left:0;z-index:998}.clearing-blackout .clearing-close{display:block}.clearing-container{position:relative;z-index:998;height:100%;overflow:hidden;margin:0}.clearing-touch-label{position:absolute;top:50%;left:50%;color:#aaa;font-size:0.6em}.visible-img{height:95%;position:relative}.visible-img img{position:absolute;left:50%;top:50%;transform:translateY(-50%) translateX(-50%);-webkit-transform:translateY(-50%) translateX(-50%);-ms-transform:translateY(-50%) translateX(-50%);max-height:100%;max-width:100%}.clearing-caption{color:#ccc;font-size:.875em;line-height:1.3;margin-bottom:0;text-align:center;bottom:0;background:#333;width:100%;padding:10px 30px 20px;position:absolute;left:0}.clearing-close{z-index:999;padding-left:20px;padding-top:10px;font-size:30px;line-height:1;color:#ccc;display:none}.clearing-close:hover,.clearing-close:focus{color:#ccc}.clearing-assembled .clearing-container{height:100%}.clearing-assembled .clearing-container .carousel>ul{display:none}.clearing-feature li{display:none}.clearing-feature li.clearing-featured-img{display:block}@media only screen and (min-width: 40.0625em){.clearing-main-prev,.clearing-main-next{position:absolute;height:100%;width:40px;top:0}.clearing-main-prev>span,.clearing-main-next>span{position:absolute;top:50%;display:block;width:0;height:0;border:solid 12px}.clearing-main-prev>span:hover,.clearing-main-next>span:hover{opacity:0.8}.clearing-main-prev{left:0}.clearing-main-prev>span{left:5px;border-color:transparent;border-right-color:#ccc}.clearing-main-next{right:0}.clearing-main-next>span{border-color:transparent;border-left-color:#ccc}.clearing-main-prev.disabled,.clearing-main-next.disabled{opacity:0.3}.clearing-assembled .clearing-container .carousel{background:rgba(51,51,51,0.8);height:120px;margin-top:10px;text-align:center}.clearing-assembled .clearing-container .carousel>ul{display:inline-block;z-index:999;height:100%;position:relative;float:none}.clearing-assembled .clearing-container .carousel>ul li{display:block;width:120px;min-height:inherit;float:left;overflow:hidden;margin-right:0;padding:0;position:relative;cursor:pointer;opacity:0.4;clear:none}.clearing-assembled .clearing-container .carousel>ul li.fix-height img{height:100%;max-width:none}.clearing-assembled .clearing-container .carousel>ul li a.th{border:none;box-shadow:none;display:block}.clearing-assembled .clearing-container .carousel>ul li img{cursor:pointer !important;width:100% !important}.clearing-assembled .clearing-container .carousel>ul li.visible{opacity:1}.clearing-assembled .clearing-container .carousel>ul li:hover{opacity:0.8}.clearing-assembled .clearing-container .visible-img{background:#333;overflow:hidden;height:85%}.clearing-close{position:absolute;top:10px;right:20px;padding-left:0;padding-top:0}}form{margin:0 0 1rem}form .row .row{margin:0 -.5rem}form .row .row .column,form .row .row .columns{padding:0 .5rem}form .row .row.collapse{margin:0}form .row .row.collapse .column,form .row .row.collapse .columns{padding:0}form .row .row.collapse input{-webkit-border-bottom-right-radius:0;-webkit-border-top-right-radius:0;border-bottom-right-radius:0;border-top-right-radius:0}form .row input.column,form .row input.columns,form .row textarea.column,form .row textarea.columns{padding-left:.5rem}label{font-size:.875rem;color:#4d4c4c;cursor:pointer;display:block;font-weight:400;line-height:1.5;margin-bottom:0}label.right{float:none !important;text-align:right}label.inline{margin:0 0 1rem 0;padding:.5625rem 0}label small{text-transform:capitalize;color:#676767}.prefix,.postfix{display:block;position:relative;z-index:2;text-align:center;width:100%;padding-top:0;padding-bottom:0;border-style:solid;border-width:1px;overflow:visible;font-size:.875rem;height:2.3125rem;line-height:2.3125rem}.postfix.button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;text-align:center;border:none}.prefix.button{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;text-align:center;border:none}.prefix.button.radius{border-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-bottom-left-radius:3px;border-top-left-radius:3px}.postfix.button.radius{border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}.prefix.button.round{border-radius:0;-webkit-border-bottom-left-radius:1000px;-webkit-border-top-left-radius:1000px;border-bottom-left-radius:1000px;border-top-left-radius:1000px}.postfix.button.round{border-radius:0;-webkit-border-bottom-right-radius:1000px;-webkit-border-top-right-radius:1000px;border-bottom-right-radius:1000px;border-top-right-radius:1000px}span.prefix,label.prefix{background:#f2f2f2;border-right:none;color:#333;border-color:#ccc}span.postfix,label.postfix{background:#f2f2f2;border-left:none;color:#333;border-color:#ccc}input[type="text"],input[type="password"],input[type="date"],input[type="datetime"],input[type="datetime-local"],input[type="month"],input[type="week"],input[type="email"],input[type="number"],input[type="search"],input[type="tel"],input[type="time"],input[type="url"],input[type="color"],textarea{-webkit-appearance:none;border-radius:0;background-color:#fff;font-family:inherit;border-style:solid;border-width:1px;border-color:#ccc;box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);color:rgba(0,0,0,0.75);display:block;font-size:.875rem;margin:0 0 1rem 0;padding:.5rem;height:2.3125rem;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;transition:all .15s linear}input[type="text"]:focus,input[type="password"]:focus,input[type="date"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="month"]:focus,input[type="week"]:focus,input[type="email"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="time"]:focus,input[type="url"]:focus,input[type="color"]:focus,textarea:focus{background:#fafafa;border-color:#999;outline:none}input[type="text"]:disabled,input[type="password"]:disabled,input[type="date"]:disabled,input[type="datetime"]:disabled,input[type="datetime-local"]:disabled,input[type="month"]:disabled,input[type="week"]:disabled,input[type="email"]:disabled,input[type="number"]:disabled,input[type="search"]:disabled,input[type="tel"]:disabled,input[type="time"]:disabled,input[type="url"]:disabled,input[type="color"]:disabled,textarea:disabled{background-color:#ddd;cursor:default}input[type="text"][disabled],input[type="text"][readonly],fieldset[disabled] input[type="text"],input[type="password"][disabled],input[type="password"][readonly],fieldset[disabled] input[type="password"],input[type="date"][disabled],input[type="date"][readonly],fieldset[disabled] input[type="date"],input[type="datetime"][disabled],input[type="datetime"][readonly],fieldset[disabled] input[type="datetime"],input[type="datetime-local"][disabled],input[type="datetime-local"][readonly],fieldset[disabled] input[type="datetime-local"],input[type="month"][disabled],input[type="month"][readonly],fieldset[disabled] input[type="month"],input[type="week"][disabled],input[type="week"][readonly],fieldset[disabled] input[type="week"],input[type="email"][disabled],input[type="email"][readonly],fieldset[disabled] input[type="email"],input[type="number"][disabled],input[type="number"][readonly],fieldset[disabled] input[type="number"],input[type="search"][disabled],input[type="search"][readonly],fieldset[disabled] input[type="search"],input[type="tel"][disabled],input[type="tel"][readonly],fieldset[disabled] input[type="tel"],input[type="time"][disabled],input[type="time"][readonly],fieldset[disabled] input[type="time"],input[type="url"][disabled],input[type="url"][readonly],fieldset[disabled] input[type="url"],input[type="color"][disabled],input[type="color"][readonly],fieldset[disabled] input[type="color"],textarea[disabled],textarea[readonly],fieldset[disabled] textarea{background-color:#ddd;cursor:default}input[type="text"].radius,input[type="password"].radius,input[type="date"].radius,input[type="datetime"].radius,input[type="datetime-local"].radius,input[type="month"].radius,input[type="week"].radius,input[type="email"].radius,input[type="number"].radius,input[type="search"].radius,input[type="tel"].radius,input[type="time"].radius,input[type="url"].radius,input[type="color"].radius,textarea.radius{border-radius:3px}form .row .prefix-radius.row.collapse input,form .row .prefix-radius.row.collapse textarea,form .row .prefix-radius.row.collapse select,form .row .prefix-radius.row.collapse button{border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}form .row .prefix-radius.row.collapse .prefix{border-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-bottom-left-radius:3px;border-top-left-radius:3px}form .row .postfix-radius.row.collapse input,form .row .postfix-radius.row.collapse textarea,form .row .postfix-radius.row.collapse select,form .row .postfix-radius.row.collapse button{border-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-bottom-left-radius:3px;border-top-left-radius:3px}form .row .postfix-radius.row.collapse .postfix{border-radius:0;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}form .row .prefix-round.row.collapse input,form .row .prefix-round.row.collapse textarea,form .row .prefix-round.row.collapse select,form .row .prefix-round.row.collapse button{border-radius:0;-webkit-border-bottom-right-radius:1000px;-webkit-border-top-right-radius:1000px;border-bottom-right-radius:1000px;border-top-right-radius:1000px}form .row .prefix-round.row.collapse .prefix{border-radius:0;-webkit-border-bottom-left-radius:1000px;-webkit-border-top-left-radius:1000px;border-bottom-left-radius:1000px;border-top-left-radius:1000px}form .row .postfix-round.row.collapse input,form .row .postfix-round.row.collapse textarea,form .row .postfix-round.row.collapse select,form .row .postfix-round.row.collapse button{border-radius:0;-webkit-border-bottom-left-radius:1000px;-webkit-border-top-left-radius:1000px;border-bottom-left-radius:1000px;border-top-left-radius:1000px}form .row .postfix-round.row.collapse .postfix{border-radius:0;-webkit-border-bottom-right-radius:1000px;-webkit-border-top-right-radius:1000px;border-bottom-right-radius:1000px;border-top-right-radius:1000px}input[type="submit"]{-webkit-appearance:none;border-radius:0}textarea[rows]{height:auto}textarea{max-width:100%}select{-webkit-appearance:none !important;border-radius:0;background-color:#FAFAFA;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+);background-position:100% center;background-repeat:no-repeat;border-style:solid;border-width:1px;border-color:#ccc;padding:.5rem;font-size:.875rem;font-family:"Open Sans","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;color:rgba(0,0,0,0.75);line-height:normal;border-radius:0;height:2.3125rem}select::-ms-expand{display:none}select.radius{border-radius:3px}select:hover{background-color:#f3f2f2;border-color:#999}select:disabled{background-color:#ddd;cursor:default}select[multiple]{height:auto}input[type="file"],input[type="checkbox"],input[type="radio"],select{margin:0 0 1rem 0}input[type="checkbox"]+label,input[type="radio"]+label{display:inline-block;margin-left:.5rem;margin-right:1rem;margin-bottom:0;vertical-align:baseline}input[type="file"]{width:100%}fieldset{border:1px solid #ddd;padding:1.25rem;margin:1.125rem 0}fieldset legend{font-weight:700;background:#fff;padding:0 .1875rem;margin:0;margin-left:-.1875rem}[data-abide] .error small.error,[data-abide] .error span.error,[data-abide] span.error,[data-abide] small.error{display:block;padding:.375rem .5625rem .5625rem;margin-top:-1px;margin-bottom:1rem;font-size:.75rem;font-weight:400;font-style:italic;background:#f04124;color:#fff}[data-abide] span.error,[data-abide] small.error{display:none}span.error,small.error{display:block;padding:.375rem .5625rem .5625rem;margin-top:-1px;margin-bottom:1rem;font-size:.75rem;font-weight:400;font-style:italic;background:#f04124;color:#fff}.error input,.error textarea,.error select{margin-bottom:0}.error input[type="checkbox"],.error input[type="radio"]{margin-bottom:1rem}.error label,.error label.error{color:#f04124}.error small.error{display:block;padding:.375rem .5625rem .5625rem;margin-top:-1px;margin-bottom:1rem;font-size:.75rem;font-weight:400;font-style:italic;background:#f04124;color:#fff}.error>label>small{color:#676767;background:transparent;padding:0;text-transform:capitalize;font-style:normal;font-size:60%;margin:0;display:inline}.error span.error-message{display:block}input.error,textarea.error,select.error{margin-bottom:0}label.error{color:#f04124}.row{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5rem}.row:before,.row:after{content:" ";display:table}.row:after{clear:both}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0}.row.collapse .row{margin-left:0;margin-right:0}.row .row{width:auto;margin-left:-.9375rem;margin-right:-.9375rem;margin-top:0;margin-bottom:0;max-width:none}.row .row:before,.row .row:after{content:" ";display:table}.row .row:after{clear:both}.row .row.collapse{width:auto;margin:0;max-width:none}.row .row.collapse:before,.row .row.collapse:after{content:" ";display:table}.row .row.collapse:after{clear:both}.column,.columns{padding-left:.9375rem;padding-right:.9375rem;width:100%;float:left}[class*="column"]+[class*="column"]:last-child{float:right}[class*="column"]+[class*="column"].end{float:left}@media only screen{.small-push-0{position:relative;left:0%;right:auto}.small-pull-0{position:relative;right:0%;left:auto}.small-push-1{position:relative;left:8.3333333333%;right:auto}.small-pull-1{position:relative;right:8.3333333333%;left:auto}.small-push-2{position:relative;left:16.6666666667%;right:auto}.small-pull-2{position:relative;right:16.6666666667%;left:auto}.small-push-3{position:relative;left:25%;right:auto}.small-pull-3{position:relative;right:25%;left:auto}.small-push-4{position:relative;left:33.3333333333%;right:auto}.small-pull-4{position:relative;right:33.3333333333%;left:auto}.small-push-5{position:relative;left:41.6666666667%;right:auto}.small-pull-5{position:relative;right:41.6666666667%;left:auto}.small-push-6{position:relative;left:50%;right:auto}.small-pull-6{position:relative;right:50%;left:auto}.small-push-7{position:relative;left:58.3333333333%;right:auto}.small-pull-7{position:relative;right:58.3333333333%;left:auto}.small-push-8{position:relative;left:66.6666666667%;right:auto}.small-pull-8{position:relative;right:66.6666666667%;left:auto}.small-push-9{position:relative;left:75%;right:auto}.small-pull-9{position:relative;right:75%;left:auto}.small-push-10{position:relative;left:83.3333333333%;right:auto}.small-pull-10{position:relative;right:83.3333333333%;left:auto}.small-push-11{position:relative;left:91.6666666667%;right:auto}.small-pull-11{position:relative;right:91.6666666667%;left:auto}.column,.columns{position:relative;padding-left:.9375rem;padding-right:.9375rem;float:left}.small-1{width:8.3333333333%}.small-2{width:16.6666666667%}.small-3{width:25%}.small-4{width:33.3333333333%}.small-5{width:41.6666666667%}.small-6{width:50%}.small-7{width:58.3333333333%}.small-8{width:66.6666666667%}.small-9{width:75%}.small-10{width:83.3333333333%}.small-11{width:91.6666666667%}.small-12{width:100%}.small-offset-0{margin-left:0% !important}.small-offset-1{margin-left:8.3333333333% !important}.small-offset-2{margin-left:16.6666666667% !important}.small-offset-3{margin-left:25% !important}.small-offset-4{margin-left:33.3333333333% !important}.small-offset-5{margin-left:41.6666666667% !important}.small-offset-6{margin-left:50% !important}.small-offset-7{margin-left:58.3333333333% !important}.small-offset-8{margin-left:66.6666666667% !important}.small-offset-9{margin-left:75% !important}.small-offset-10{margin-left:83.3333333333% !important}.small-offset-11{margin-left:91.6666666667% !important}.small-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}.column.small-centered,.columns.small-centered{margin-left:auto;margin-right:auto;float:none}.column.small-uncentered,.columns.small-uncentered{margin-left:0;margin-right:0;float:left}.column.small-centered:last-child,.columns.small-centered:last-child{float:none}.column.small-uncentered:last-child,.columns.small-uncentered:last-child{float:left}.column.small-uncentered.opposite,.columns.small-uncentered.opposite{float:right}.row.small-collapse>.column,.row.small-collapse>.columns{padding-left:0;padding-right:0}.row.small-collapse .row{margin-left:0;margin-right:0}.row.small-uncollapse>.column,.row.small-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem;float:left}}@media only screen and (min-width: 40.0625em){.medium-push-0{position:relative;left:0%;right:auto}.medium-pull-0{position:relative;right:0%;left:auto}.medium-push-1{position:relative;left:8.3333333333%;right:auto}.medium-pull-1{position:relative;right:8.3333333333%;left:auto}.medium-push-2{position:relative;left:16.6666666667%;right:auto}.medium-pull-2{position:relative;right:16.6666666667%;left:auto}.medium-push-3{position:relative;left:25%;right:auto}.medium-pull-3{position:relative;right:25%;left:auto}.medium-push-4{position:relative;left:33.3333333333%;right:auto}.medium-pull-4{position:relative;right:33.3333333333%;left:auto}.medium-push-5{position:relative;left:41.6666666667%;right:auto}.medium-pull-5{position:relative;right:41.6666666667%;left:auto}.medium-push-6{position:relative;left:50%;right:auto}.medium-pull-6{position:relative;right:50%;left:auto}.medium-push-7{position:relative;left:58.3333333333%;right:auto}.medium-pull-7{position:relative;right:58.3333333333%;left:auto}.medium-push-8{position:relative;left:66.6666666667%;right:auto}.medium-pull-8{position:relative;right:66.6666666667%;left:auto}.medium-push-9{position:relative;left:75%;right:auto}.medium-pull-9{position:relative;right:75%;left:auto}.medium-push-10{position:relative;left:83.3333333333%;right:auto}.medium-pull-10{position:relative;right:83.3333333333%;left:auto}.medium-push-11{position:relative;left:91.6666666667%;right:auto}.medium-pull-11{position:relative;right:91.6666666667%;left:auto}.column,.columns{position:relative;padding-left:.9375rem;padding-right:.9375rem;float:left}.medium-1{width:8.3333333333%}.medium-2{width:16.6666666667%}.medium-3{width:25%}.medium-4{width:33.3333333333%}.medium-5{width:41.6666666667%}.medium-6{width:50%}.medium-7{width:58.3333333333%}.medium-8{width:66.6666666667%}.medium-9{width:75%}.medium-10{width:83.3333333333%}.medium-11{width:91.6666666667%}.medium-12{width:100%}.medium-offset-0{margin-left:0% !important}.medium-offset-1{margin-left:8.3333333333% !important}.medium-offset-2{margin-left:16.6666666667% !important}.medium-offset-3{margin-left:25% !important}.medium-offset-4{margin-left:33.3333333333% !important}.medium-offset-5{margin-left:41.6666666667% !important}.medium-offset-6{margin-left:50% !important}.medium-offset-7{margin-left:58.3333333333% !important}.medium-offset-8{margin-left:66.6666666667% !important}.medium-offset-9{margin-left:75% !important}.medium-offset-10{margin-left:83.3333333333% !important}.medium-offset-11{margin-left:91.6666666667% !important}.medium-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}.column.medium-centered,.columns.medium-centered{margin-left:auto;margin-right:auto;float:none}.column.medium-uncentered,.columns.medium-uncentered{margin-left:0;margin-right:0;float:left}.column.medium-centered:last-child,.columns.medium-centered:last-child{float:none}.column.medium-uncentered:last-child,.columns.medium-uncentered:last-child{float:left}.column.medium-uncentered.opposite,.columns.medium-uncentered.opposite{float:right}.row.medium-collapse>.column,.row.medium-collapse>.columns{padding-left:0;padding-right:0}.row.medium-collapse .row{margin-left:0;margin-right:0}.row.medium-uncollapse>.column,.row.medium-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem;float:left}.push-0{position:relative;left:0%;right:auto}.pull-0{position:relative;right:0%;left:auto}.push-1{position:relative;left:8.3333333333%;right:auto}.pull-1{position:relative;right:8.3333333333%;left:auto}.push-2{position:relative;left:16.6666666667%;right:auto}.pull-2{position:relative;right:16.6666666667%;left:auto}.push-3{position:relative;left:25%;right:auto}.pull-3{position:relative;right:25%;left:auto}.push-4{position:relative;left:33.3333333333%;right:auto}.pull-4{position:relative;right:33.3333333333%;left:auto}.push-5{position:relative;left:41.6666666667%;right:auto}.pull-5{position:relative;right:41.6666666667%;left:auto}.push-6{position:relative;left:50%;right:auto}.pull-6{position:relative;right:50%;left:auto}.push-7{position:relative;left:58.3333333333%;right:auto}.pull-7{position:relative;right:58.3333333333%;left:auto}.push-8{position:relative;left:66.6666666667%;right:auto}.pull-8{position:relative;right:66.6666666667%;left:auto}.push-9{position:relative;left:75%;right:auto}.pull-9{position:relative;right:75%;left:auto}.push-10{position:relative;left:83.3333333333%;right:auto}.pull-10{position:relative;right:83.3333333333%;left:auto}.push-11{position:relative;left:91.6666666667%;right:auto}.pull-11{position:relative;right:91.6666666667%;left:auto}}@media only screen and (min-width: 64.0625em){.large-push-0{position:relative;left:0%;right:auto}.large-pull-0{position:relative;right:0%;left:auto}.large-push-1{position:relative;left:8.3333333333%;right:auto}.large-pull-1{position:relative;right:8.3333333333%;left:auto}.large-push-2{position:relative;left:16.6666666667%;right:auto}.large-pull-2{position:relative;right:16.6666666667%;left:auto}.large-push-3{position:relative;left:25%;right:auto}.large-pull-3{position:relative;right:25%;left:auto}.large-push-4{position:relative;left:33.3333333333%;right:auto}.large-pull-4{position:relative;right:33.3333333333%;left:auto}.large-push-5{position:relative;left:41.6666666667%;right:auto}.large-pull-5{position:relative;right:41.6666666667%;left:auto}.large-push-6{position:relative;left:50%;right:auto}.large-pull-6{position:relative;right:50%;left:auto}.large-push-7{position:relative;left:58.3333333333%;right:auto}.large-pull-7{position:relative;right:58.3333333333%;left:auto}.large-push-8{position:relative;left:66.6666666667%;right:auto}.large-pull-8{position:relative;right:66.6666666667%;left:auto}.large-push-9{position:relative;left:75%;right:auto}.large-pull-9{position:relative;right:75%;left:auto}.large-push-10{position:relative;left:83.3333333333%;right:auto}.large-pull-10{position:relative;right:83.3333333333%;left:auto}.large-push-11{position:relative;left:91.6666666667%;right:auto}.large-pull-11{position:relative;right:91.6666666667%;left:auto}.column,.columns{position:relative;padding-left:.9375rem;padding-right:.9375rem;float:left}.large-1{width:8.3333333333%}.large-2{width:16.6666666667%}.large-3{width:25%}.large-4{width:33.3333333333%}.large-5{width:41.6666666667%}.large-6{width:50%}.large-7{width:58.3333333333%}.large-8{width:66.6666666667%}.large-9{width:75%}.large-10{width:83.3333333333%}.large-11{width:91.6666666667%}.large-12{width:100%}.large-offset-0{margin-left:0% !important}.large-offset-1{margin-left:8.3333333333% !important}.large-offset-2{margin-left:16.6666666667% !important}.large-offset-3{margin-left:25% !important}.large-offset-4{margin-left:33.3333333333% !important}.large-offset-5{margin-left:41.6666666667% !important}.large-offset-6{margin-left:50% !important}.large-offset-7{margin-left:58.3333333333% !important}.large-offset-8{margin-left:66.6666666667% !important}.large-offset-9{margin-left:75% !important}.large-offset-10{margin-left:83.3333333333% !important}.large-offset-11{margin-left:91.6666666667% !important}.large-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}.column.large-centered,.columns.large-centered{margin-left:auto;margin-right:auto;float:none}.column.large-uncentered,.columns.large-uncentered{margin-left:0;margin-right:0;float:left}.column.large-centered:last-child,.columns.large-centered:last-child{float:none}.column.large-uncentered:last-child,.columns.large-uncentered:last-child{float:left}.column.large-uncentered.opposite,.columns.large-uncentered.opposite{float:right}.row.large-collapse>.column,.row.large-collapse>.columns{padding-left:0;padding-right:0}.row.large-collapse .row{margin-left:0;margin-right:0}.row.large-uncollapse>.column,.row.large-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem;float:left}.push-0{position:relative;left:0%;right:auto}.pull-0{position:relative;right:0%;left:auto}.push-1{position:relative;left:8.3333333333%;right:auto}.pull-1{position:relative;right:8.3333333333%;left:auto}.push-2{position:relative;left:16.6666666667%;right:auto}.pull-2{position:relative;right:16.6666666667%;left:auto}.push-3{position:relative;left:25%;right:auto}.pull-3{position:relative;right:25%;left:auto}.push-4{position:relative;left:33.3333333333%;right:auto}.pull-4{position:relative;right:33.3333333333%;left:auto}.push-5{position:relative;left:41.6666666667%;right:auto}.pull-5{position:relative;right:41.6666666667%;left:auto}.push-6{position:relative;left:50%;right:auto}.pull-6{position:relative;right:50%;left:auto}.push-7{position:relative;left:58.3333333333%;right:auto}.pull-7{position:relative;right:58.3333333333%;left:auto}.push-8{position:relative;left:66.6666666667%;right:auto}.pull-8{position:relative;right:66.6666666667%;left:auto}.push-9{position:relative;left:75%;right:auto}.pull-9{position:relative;right:75%;left:auto}.push-10{position:relative;left:83.3333333333%;right:auto}.pull-10{position:relative;right:83.3333333333%;left:auto}.push-11{position:relative;left:91.6666666667%;right:auto}.pull-11{position:relative;right:91.6666666667%;left:auto}}.inline-list{margin:0 auto 1.0625rem auto;margin-left:-1.375rem;margin-right:0;padding:0;list-style:none;overflow:hidden}.inline-list>li{list-style:none;float:left;margin-left:1.375rem;display:block}.inline-list>li>*{display:block}.panel{border-style:solid;border-width:1px;border-color:#d8d8d8;margin-bottom:1.25rem;padding:1.25rem;background:#f2f2f2;color:#333}.panel>:first-child{margin-top:0}.panel>:last-child{margin-bottom:0}.panel h1,.panel h2,.panel h3,.panel h4,.panel h5,.panel h6,.panel p,.panel li,.panel dl{color:#333}.panel h1,.panel h2,.panel h3,.panel h4,.panel h5,.panel h6{line-height:1;margin-bottom:.625rem}.panel h1.subheader,.panel h2.subheader,.panel h3.subheader,.panel h4.subheader,.panel h5.subheader,.panel h6.subheader{line-height:1.4}.panel.callout{border-style:solid;border-width:1px;border-color:#f6c4bf;margin-bottom:1.25rem;padding:1.25rem;background:#fdf0ef;color:#333}.panel.callout>:first-child{margin-top:0}.panel.callout>:last-child{margin-bottom:0}.panel.callout h1,.panel.callout h2,.panel.callout h3,.panel.callout h4,.panel.callout h5,.panel.callout h6,.panel.callout p,.panel.callout li,.panel.callout dl{color:#333}.panel.callout h1,.panel.callout h2,.panel.callout h3,.panel.callout h4,.panel.callout h5,.panel.callout h6{line-height:1;margin-bottom:.625rem}.panel.callout h1.subheader,.panel.callout h2.subheader,.panel.callout h3.subheader,.panel.callout h4.subheader,.panel.callout h5.subheader,.panel.callout h6.subheader{line-height:1.4}.panel.callout a:not(.button){color:#ba2619}.panel.callout a:not(.button):hover,.panel.callout a:not(.button):focus{color:#a02116}.panel.radius{border-radius:3px}.side-nav{display:block;margin:0;padding:.875rem 0;list-style-type:none;list-style-position:outside;font-family:"Open Sans","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif}.side-nav li{margin:0 0 .4375rem 0;font-size:.875rem;font-weight:400}.side-nav li a:not(.button){display:block;color:#ba2619;margin:0;padding:.4375rem .875rem}.side-nav li a:not(.button):hover,.side-nav li a:not(.button):focus{background:rgba(0,0,0,0.025);color:#e65346}.side-nav li.active>a:first-child:not(.button){color:#e65346;font-weight:400;font-family:"Open Sans","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif}.side-nav li.divider{border-top:1px solid;height:0;padding:0;list-style:none;border-top-color:#fff}.side-nav li.heading{color:#ba2619;font-size:.875rem;font-weight:bold;text-transform:uppercase}table{background:#fff;margin-bottom:1.25rem;border:solid 1px #ddd;table-layout:auto}table caption{background:transparent;color:#222;font-size:1rem;font-weight:bold}table thead{background:#f5f5f5}table thead tr th,table thead tr td{padding:.5rem .625rem .625rem;font-size:.875rem;font-weight:700;color:#222}table tfoot{background:#f5f5f5}table tfoot tr th,table tfoot tr td{padding:.5rem .625rem .625rem;font-size:.875rem;font-weight:700;color:#222}table tr th,table tr td{padding:.5625rem .625rem;font-size:.875rem;color:#222;text-align:left}table tr.even,table tr.alt,table tr:nth-of-type(even){background:#F9F9F9}table thead tr th,table tfoot tr th,table tfoot tr td,table tbody tr th,table tbody tr td,table tr td{display:table-cell;line-height:1.125rem}.th{line-height:0;display:inline-block;border:solid 4px #fff;max-width:100%;box-shadow:0 0 0 1px rgba(0,0,0,0.2);transition:all 200ms ease-out}.th:hover,.th:focus{box-shadow:0 0 6px 1px rgba(186,38,25,0.5)}.th.radius{border-radius:3px}meta.foundation-mq-topbar{font-family:"/only screen and (min-width:40.0625em)/";width:40.0625em}.contain-to-grid{width:100%;background:#333}.contain-to-grid .top-bar{margin-bottom:0}.fixed{width:100%;left:0;position:fixed;top:0;z-index:99}.fixed.expanded:not(.top-bar){overflow-y:auto;height:auto;width:100%;max-height:100%}.fixed.expanded:not(.top-bar) .title-area{position:fixed;width:100%;z-index:99}.fixed.expanded:not(.top-bar) .top-bar-section{z-index:98;margin-top:2.8125rem}.top-bar{overflow:hidden;height:2.8125rem;line-height:2.8125rem;position:relative;background:#333;margin-bottom:0}.top-bar ul{margin-bottom:0;list-style:none}.top-bar .row{max-width:none}.top-bar form,.top-bar input{margin-bottom:0}.top-bar input{height:1.75rem;padding-top:.35rem;padding-bottom:.35rem;font-size:.75rem}.top-bar .button,.top-bar button{padding-top:0.4125rem;padding-bottom:0.4125rem;margin-bottom:0;font-size:.75rem}@media only screen and (max-width: 40em){.top-bar .button,.top-bar button{position:relative;top:-1px}}.top-bar .title-area{position:relative;margin:0}.top-bar .name{height:2.8125rem;margin:0;font-size:16px}.top-bar .name h1,.top-bar .name h2,.top-bar .name h3,.top-bar .name h4,.top-bar .name p,.top-bar .name span{line-height:2.8125rem;font-size:1.0625rem;margin:0}.top-bar .name h1 a,.top-bar .name h2 a,.top-bar .name h3 a,.top-bar .name h4 a,.top-bar .name p a,.top-bar .name span a{font-weight:400;color:#fff;width:75%;display:block;padding:0 .9375rem}.top-bar .toggle-topbar{position:absolute;right:0;top:0}.top-bar .toggle-topbar a{color:#fff;text-transform:uppercase;font-size:.8125rem;font-weight:700;position:relative;display:block;padding:0 .9375rem;height:2.8125rem;line-height:2.8125rem}.top-bar .toggle-topbar.menu-icon{top:50%;margin-top:-16px}.top-bar .toggle-topbar.menu-icon a{height:34px;line-height:33px;padding:0 2.5rem 0 .9375rem;color:#fff;position:relative}.top-bar .toggle-topbar.menu-icon a span::after{content:"";position:absolute;display:block;height:0;top:50%;margin-top:-8px;right:.9375rem;box-shadow:0 0 0 1px #fff,0 7px 0 1px #fff,0 14px 0 1px #fff;width:16px}.top-bar .toggle-topbar.menu-icon a span:hover:after{box-shadow:0 0 0 1px "",0 7px 0 1px "",0 14px 0 1px ""}.top-bar.expanded{height:auto;background:transparent}.top-bar.expanded .title-area{background:#333}.top-bar.expanded .toggle-topbar a{color:#888}.top-bar.expanded .toggle-topbar a span::after{box-shadow:0 0 0 1px #888,0 7px 0 1px #888,0 14px 0 1px #888}.top-bar-section{left:0;position:relative;width:auto;transition:left 300ms ease-out}.top-bar-section ul{padding:0;width:100%;height:auto;display:block;font-size:16px;margin:0}.top-bar-section .divider,.top-bar-section [role="separator"]{border-top:solid 1px #1a1919;clear:both;height:1px;width:100%}.top-bar-section ul li{background:#333}.top-bar-section ul li>a{display:block;width:100%;color:#fff;padding:12px 0 12px 0;padding-left:.9375rem;font-family:"Open Sans","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;font-size:.8125rem;font-weight:400;text-transform:none}.top-bar-section ul li>a.button{font-size:.8125rem;padding-right:.9375rem;padding-left:.9375rem;background-color:#ba2619;border-color:#951e14;color:#fff}.top-bar-section ul li>a.button:hover,.top-bar-section ul li>a.button:focus{background-color:#951e14}.top-bar-section ul li>a.button:hover,.top-bar-section ul li>a.button:focus{color:#fff}.top-bar-section ul li>a.button.secondary{background-color:#e7e7e7;border-color:#b9b9b9;color:#333}.top-bar-section ul li>a.button.secondary:hover,.top-bar-section ul li>a.button.secondary:focus{background-color:#b9b9b9}.top-bar-section ul li>a.button.secondary:hover,.top-bar-section ul li>a.button.secondary:focus{color:#333}.top-bar-section ul li>a.button.success{background-color:#43AC6A;border-color:#368a55;color:#fff}.top-bar-section ul li>a.button.success:hover,.top-bar-section ul li>a.button.success:focus{background-color:#368a55}.top-bar-section ul li>a.button.success:hover,.top-bar-section ul li>a.button.success:focus{color:#fff}.top-bar-section ul li>a.button.alert{background-color:#f04124;border-color:#cf2a0e;color:#fff}.top-bar-section ul li>a.button.alert:hover,.top-bar-section ul li>a.button.alert:focus{background-color:#cf2a0e}.top-bar-section ul li>a.button.alert:hover,.top-bar-section ul li>a.button.alert:focus{color:#fff}.top-bar-section ul li>a.button.warning{background-color:#f08a24;border-color:#cf6e0e;color:#fff}.top-bar-section ul li>a.button.warning:hover,.top-bar-section ul li>a.button.warning:focus{background-color:#cf6e0e}.top-bar-section ul li>a.button.warning:hover,.top-bar-section ul li>a.button.warning:focus{color:#fff}.top-bar-section ul li>button{font-size:.8125rem;padding-right:.9375rem;padding-left:.9375rem;background-color:#ba2619;border-color:#951e14;color:#fff}.top-bar-section ul li>button:hover,.top-bar-section ul li>button:focus{background-color:#951e14}.top-bar-section ul li>button:hover,.top-bar-section ul li>button:focus{color:#fff}.top-bar-section ul li>button.secondary{background-color:#e7e7e7;border-color:#b9b9b9;color:#333}.top-bar-section ul li>button.secondary:hover,.top-bar-section ul li>button.secondary:focus{background-color:#b9b9b9}.top-bar-section ul li>button.secondary:hover,.top-bar-section ul li>button.secondary:focus{color:#333}.top-bar-section ul li>button.success{background-color:#43AC6A;border-color:#368a55;color:#fff}.top-bar-section ul li>button.success:hover,.top-bar-section ul li>button.success:focus{background-color:#368a55}.top-bar-section ul li>button.success:hover,.top-bar-section ul li>button.success:focus{color:#fff}.top-bar-section ul li>button.alert{background-color:#f04124;border-color:#cf2a0e;color:#fff}.top-bar-section ul li>button.alert:hover,.top-bar-section ul li>button.alert:focus{background-color:#cf2a0e}.top-bar-section ul li>button.alert:hover,.top-bar-section ul li>button.alert:focus{color:#fff}.top-bar-section ul li>button.warning{background-color:#f08a24;border-color:#cf6e0e;color:#fff}.top-bar-section ul li>button.warning:hover,.top-bar-section ul li>button.warning:focus{background-color:#cf6e0e}.top-bar-section ul li>button.warning:hover,.top-bar-section ul li>button.warning:focus{color:#fff}.top-bar-section ul li:hover:not(.has-form)>a{background-color:#555;background:#333;color:#fff}.top-bar-section ul li.active>a{background:#ba2619;color:#fff}.top-bar-section ul li.active>a:hover{background:#a02116;color:#fff}.top-bar-section .has-form{padding:.9375rem}.top-bar-section .has-dropdown{position:relative}.top-bar-section .has-dropdown>a:after{content:"";display:block;width:0;height:0;border:inset 5px;border-color:transparent transparent transparent rgba(255,255,255,0.4);border-left-style:solid;margin-right:.9375rem;margin-top:-4.5px;position:absolute;top:50%;right:0}.top-bar-section .has-dropdown.moved{position:static}.top-bar-section .has-dropdown.moved>.dropdown{display:block;position:static !important;height:auto;width:auto;overflow:visible;clip:auto;position:absolute !important;width:100%}.top-bar-section .has-dropdown.moved>a:after{display:none}.top-bar-section .dropdown{padding:0;position:absolute;left:100%;top:0;z-index:99;display:block;position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}.top-bar-section .dropdown li{width:100%;height:auto}.top-bar-section .dropdown li a{font-weight:400;padding:8px .9375rem}.top-bar-section .dropdown li a.parent-link{font-weight:400}.top-bar-section .dropdown li.title h5,.top-bar-section .dropdown li.parent-link{margin-bottom:0;margin-top:0;font-size:1.125rem}.top-bar-section .dropdown li.title h5 a,.top-bar-section .dropdown li.parent-link a{color:#fff;display:block}.top-bar-section .dropdown li.title h5 a:hover,.top-bar-section .dropdown li.parent-link a:hover{background:none}.top-bar-section .dropdown li.has-form{padding:8px .9375rem}.top-bar-section .dropdown li .button,.top-bar-section .dropdown li button{top:auto}.top-bar-section .dropdown label{padding:8px .9375rem 2px;margin-bottom:0;text-transform:uppercase;color:#777;font-weight:700;font-size:.625rem}.js-generated{display:block}@media only screen and (min-width: 40.0625em){.top-bar{background:#333;overflow:visible}.top-bar:before,.top-bar:after{content:" ";display:table}.top-bar:after{clear:both}.top-bar .toggle-topbar{display:none}.top-bar .title-area{float:left}.top-bar .name h1 a,.top-bar .name h2 a,.top-bar .name h3 a,.top-bar .name h4 a,.top-bar .name h5 a,.top-bar .name h6 a{width:auto}.top-bar input,.top-bar .button,.top-bar button{font-size:.875rem;position:relative;height:1.75rem;top:.53125rem}.top-bar.expanded{background:#333}.contain-to-grid .top-bar{max-width:62.5rem;margin:0 auto;margin-bottom:0}.top-bar-section{transition:none 0 0;left:0 !important}.top-bar-section ul{width:auto;height:auto !important;display:inline}.top-bar-section ul li{float:left}.top-bar-section ul li .js-generated{display:none}.top-bar-section li.hover>a:not(.button){background-color:#555;background:#333;color:#fff}.top-bar-section li:not(.has-form) a:not(.button){padding:0 .9375rem;line-height:2.8125rem;background:#333}.top-bar-section li:not(.has-form) a:not(.button):hover{background-color:#555;background:#333}.top-bar-section li.active:not(.has-form) a:not(.button){padding:0 .9375rem;line-height:2.8125rem;color:#fff;background:#ba2619}.top-bar-section li.active:not(.has-form) a:not(.button):hover{background:#a02116;color:#fff}.top-bar-section .has-dropdown>a{padding-right:2.1875rem !important}.top-bar-section .has-dropdown>a:after{content:"";display:block;width:0;height:0;border:inset 5px;border-color:rgba(255,255,255,0.4) transparent transparent transparent;border-top-style:solid;margin-top:-2.5px;top:1.40625rem}.top-bar-section .has-dropdown.moved{position:relative}.top-bar-section .has-dropdown.moved>.dropdown{display:block;position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}.top-bar-section .has-dropdown.hover>.dropdown,.top-bar-section .has-dropdown.not-click:hover>.dropdown{display:block;position:static !important;height:auto;width:auto;overflow:visible;clip:auto;position:absolute !important}.top-bar-section .has-dropdown>a:focus+.dropdown{display:block;position:static !important;height:auto;width:auto;overflow:visible;clip:auto;position:absolute !important}.top-bar-section .has-dropdown .dropdown li.has-dropdown>a:after{border:none;content:"\00bb";top:1rem;margin-top:-1px;right:5px;line-height:1.2}.top-bar-section .dropdown{left:0;top:auto;background:transparent;min-width:100%}.top-bar-section .dropdown li a{color:#fff;line-height:2.8125rem;white-space:nowrap;padding:12px .9375rem;background:#333}.top-bar-section .dropdown li:not(.has-form):not(.active)>a:not(.button){color:#fff;background:#333}.top-bar-section .dropdown li:not(.has-form):not(.active):hover>a:not(.button){color:#fff;background-color:#555;background:#333}.top-bar-section .dropdown li label{white-space:nowrap;background:#333}.top-bar-section .dropdown li .dropdown{left:100%;top:0}.top-bar-section>ul>.divider,.top-bar-section>ul>[role="separator"]{border-bottom:none;border-top:none;border-right:solid 1px #4e4e4e;clear:none;height:2.8125rem;width:0}.top-bar-section .has-form{background:#333;padding:0 .9375rem;height:2.8125rem}.top-bar-section .right li .dropdown{left:auto;right:0}.top-bar-section .right li .dropdown li .dropdown{right:100%}.top-bar-section .left li .dropdown{right:auto;left:0}.top-bar-section .left li .dropdown li .dropdown{left:100%}.no-js .top-bar-section ul li:hover>a{background-color:#555;background:#333;color:#fff}.no-js .top-bar-section ul li:active>a{background:#ba2619;color:#fff}.no-js .top-bar-section .has-dropdown:hover>.dropdown{display:block;position:static !important;height:auto;width:auto;overflow:visible;clip:auto;position:absolute !important}.no-js .top-bar-section .has-dropdown>a:focus+.dropdown{display:block;position:static !important;height:auto;width:auto;overflow:visible;clip:auto;position:absolute !important}}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}.text-justify{text-align:justify !important}@media only screen and (max-width: 40em){.small-only-text-left{text-align:left !important}.small-only-text-right{text-align:right !important}.small-only-text-center{text-align:center !important}.small-only-text-justify{text-align:justify !important}}@media only screen{.small-text-left{text-align:left !important}.small-text-right{text-align:right !important}.small-text-center{text-align:center !important}.small-text-justify{text-align:justify !important}}@media only screen and (min-width: 40.0625em) and (max-width: 64em){.medium-only-text-left{text-align:left !important}.medium-only-text-right{text-align:right !important}.medium-only-text-center{text-align:center !important}.medium-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 40.0625em){.medium-text-left{text-align:left !important}.medium-text-right{text-align:right !important}.medium-text-center{text-align:center !important}.medium-text-justify{text-align:justify !important}}@media only screen and (min-width: 64.0625em) and (max-width: 90em){.large-only-text-left{text-align:left !important}.large-only-text-right{text-align:right !important}.large-only-text-center{text-align:center !important}.large-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 64.0625em){.large-text-left{text-align:left !important}.large-text-right{text-align:right !important}.large-text-center{text-align:center !important}.large-text-justify{text-align:justify !important}}@media only screen and (min-width: 90.0625em) and (max-width: 120em){.xlarge-only-text-left{text-align:left !important}.xlarge-only-text-right{text-align:right !important}.xlarge-only-text-center{text-align:center !important}.xlarge-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 90.0625em){.xlarge-text-left{text-align:left !important}.xlarge-text-right{text-align:right !important}.xlarge-text-center{text-align:center !important}.xlarge-text-justify{text-align:justify !important}}@media only screen and (min-width: 120.0625em) and (max-width: 99999999em){.xxlarge-only-text-left{text-align:left !important}.xxlarge-only-text-right{text-align:right !important}.xxlarge-only-text-center{text-align:center !important}.xxlarge-only-text-justify{text-align:justify !important}}@media only screen and (min-width: 120.0625em){.xxlarge-text-left{text-align:left !important}.xxlarge-text-right{text-align:right !important}.xxlarge-text-center{text-align:center !important}.xxlarge-text-justify{text-align:justify !important}}div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}a{color:#ba2619;text-decoration:none;line-height:inherit}a:hover,a:focus{color:#a02116}a img{border:none}p{font-family:inherit;font-weight:400;font-size:1rem;line-height:1.6;margin-bottom:1.25rem;text-rendering:optimizeLegibility}p.lead{font-size:1.21875rem;line-height:1.6}p aside{font-size:.875rem;line-height:1.35;font-style:italic}h1,h2,h3,h4,h5,h6{font-family:"Open Sans","Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;font-weight:700;font-style:normal;color:#222;text-rendering:optimizeLegibility;margin-top:.2rem;margin-bottom:.5rem;line-height:1.4}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-size:80%;color:#6f6f6f;line-height:0}h1{font-size:1.5625rem}h2{font-size:1.25rem}h3{font-size:1.0625rem}h4{font-size:.9375rem}h5{font-size:1rem}h6{font-size:1rem}.subheader{line-height:1.4;color:#6f6f6f;font-weight:400;margin-top:.2rem;margin-bottom:.5rem}hr{border:solid #ddd;border-width:1px 0 0;clear:both;margin:1.25rem 0 1.1875rem;height:0}em,i{font-style:italic;line-height:inherit}strong,b{font-weight:700;line-height:inherit}small{font-size:80%;line-height:inherit}code{font-family:Consolas,"Liberation Mono",Courier,monospace;font-weight:400;color:#333;background-color:rgba(0,0,0,0.04);border-width:1px;border-style:none;border-color:rgba(0,0,0,0.04);padding:.125rem .3125rem .0625rem}ul,ol,dl{font-size:1rem;line-height:1.6;margin-bottom:1.25rem;list-style-position:outside;font-family:inherit}ul{margin-left:1.1rem}ul.no-bullet{margin-left:0}ul.no-bullet li ul,ul.no-bullet li ol{margin-left:1.25rem;margin-bottom:0;list-style:none}ul li ul,ul li ol{margin-left:1.25rem;margin-bottom:0}ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}ul.square{list-style-type:square;margin-left:1.1rem}ul.circle{list-style-type:circle;margin-left:1.1rem}ul.disc{list-style-type:disc;margin-left:1.1rem}ul.no-bullet{list-style:none}ol{margin-left:1.4rem}ol li ul,ol li ol{margin-left:1.25rem;margin-bottom:0}dl dt{margin-bottom:.3rem;font-weight:700}dl dd{margin-bottom:.75rem}abbr,acronym{text-transform:uppercase;font-size:90%;color:#222;cursor:help}abbr{text-transform:none}abbr[title]{border-bottom:1px dotted #ddd}blockquote{margin:0 0 1.25rem;padding:.5625rem 1.25rem 0 1.1875rem;border-left:1px solid #ddd}blockquote cite{display:block;font-size:.8125rem;color:#555}blockquote cite:before{content:"\2014 \0020"}blockquote cite a,blockquote cite a:visited{color:#555}blockquote,blockquote p{line-height:1.6;color:#6f6f6f}.vcard{display:inline-block;margin:0 0 1.25rem 0;border:1px solid #ddd;padding:.625rem .75rem}.vcard li{margin:0;display:block}.vcard .fn{font-weight:700;font-size:.9375rem}.vevent .summary{font-weight:700}.vevent abbr{cursor:default;text-decoration:none;font-weight:700;border:none;padding:0 .0625rem}@media only screen and (min-width: 40.0625em){h1,h2,h3,h4,h5,h6{line-height:1.4}h1{font-size:1.875rem}h2{font-size:1.5625rem}h3{font-size:1.375rem}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:1rem}}@media only screen{.show-for-small-only,.show-for-small-up,.show-for-small,.show-for-small-down,.hide-for-medium-only,.hide-for-medium-up,.hide-for-medium,.show-for-medium-down,.hide-for-large-only,.hide-for-large-up,.hide-for-large,.show-for-large-down,.hide-for-xlarge-only,.hide-for-xlarge-up,.hide-for-xlarge,.show-for-xlarge-down,.hide-for-xxlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge,.show-for-xxlarge-down{display:inherit !important}.hide-for-small-only,.hide-for-small-up,.hide-for-small,.hide-for-small-down,.show-for-medium-only,.show-for-medium-up,.show-for-medium,.hide-for-medium-down,.show-for-large-only,.show-for-large-up,.show-for-large,.hide-for-large-down,.show-for-xlarge-only,.show-for-xlarge-up,.show-for-xlarge,.hide-for-xlarge-down,.show-for-xxlarge-only,.show-for-xxlarge-up,.show-for-xxlarge,.hide-for-xxlarge-down{display:none !important}.visible-for-small-only,.visible-for-small-up,.visible-for-small,.visible-for-small-down,.hidden-for-medium-only,.hidden-for-medium-up,.hidden-for-medium,.visible-for-medium-down,.hidden-for-large-only,.hidden-for-large-up,.hidden-for-large,.visible-for-large-down,.hidden-for-xlarge-only,.hidden-for-xlarge-up,.hidden-for-xlarge,.visible-for-xlarge-down,.hidden-for-xxlarge-only,.hidden-for-xxlarge-up,.hidden-for-xxlarge,.visible-for-xxlarge-down{position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.hidden-for-small-only,.hidden-for-small-up,.hidden-for-small,.hidden-for-small-down,.visible-for-medium-only,.visible-for-medium-up,.visible-for-medium,.hidden-for-medium-down,.visible-for-large-only,.visible-for-large-up,.visible-for-large,.hidden-for-large-down,.visible-for-xlarge-only,.visible-for-xlarge-up,.visible-for-xlarge,.hidden-for-xlarge-down,.visible-for-xxlarge-only,.visible-for-xxlarge-up,.visible-for-xxlarge,.hidden-for-xxlarge-down{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}table.show-for-small-only,table.show-for-small-up,table.show-for-small,table.show-for-small-down,table.hide-for-medium-only,table.hide-for-medium-up,table.hide-for-medium,table.show-for-medium-down,table.hide-for-large-only,table.hide-for-large-up,table.hide-for-large,table.show-for-large-down,table.hide-for-xlarge-only,table.hide-for-xlarge-up,table.hide-for-xlarge,table.show-for-xlarge-down,table.hide-for-xxlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge,table.show-for-xxlarge-down{display:table !important}thead.show-for-small-only,thead.show-for-small-up,thead.show-for-small,thead.show-for-small-down,thead.hide-for-medium-only,thead.hide-for-medium-up,thead.hide-for-medium,thead.show-for-medium-down,thead.hide-for-large-only,thead.hide-for-large-up,thead.hide-for-large,thead.show-for-large-down,thead.hide-for-xlarge-only,thead.hide-for-xlarge-up,thead.hide-for-xlarge,thead.show-for-xlarge-down,thead.hide-for-xxlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge,thead.show-for-xxlarge-down{display:table-header-group !important}tbody.show-for-small-only,tbody.show-for-small-up,tbody.show-for-small,tbody.show-for-small-down,tbody.hide-for-medium-only,tbody.hide-for-medium-up,tbody.hide-for-medium,tbody.show-for-medium-down,tbody.hide-for-large-only,tbody.hide-for-large-up,tbody.hide-for-large,tbody.show-for-large-down,tbody.hide-for-xlarge-only,tbody.hide-for-xlarge-up,tbody.hide-for-xlarge,tbody.show-for-xlarge-down,tbody.hide-for-xxlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge,tbody.show-for-xxlarge-down{display:table-row-group !important}tr.show-for-small-only,tr.show-for-small-up,tr.show-for-small,tr.show-for-small-down,tr.hide-for-medium-only,tr.hide-for-medium-up,tr.hide-for-medium,tr.show-for-medium-down,tr.hide-for-large-only,tr.hide-for-large-up,tr.hide-for-large,tr.show-for-large-down,tr.hide-for-xlarge-only,tr.hide-for-xlarge-up,tr.hide-for-xlarge,tr.show-for-xlarge-down,tr.hide-for-xxlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge,tr.show-for-xxlarge-down{display:table-row}th.show-for-small-only,td.show-for-small-only,th.show-for-small-up,td.show-for-small-up,th.show-for-small,td.show-for-small,th.show-for-small-down,td.show-for-small-down,th.hide-for-medium-only,td.hide-for-medium-only,th.hide-for-medium-up,td.hide-for-medium-up,th.hide-for-medium,td.hide-for-medium,th.show-for-medium-down,td.show-for-medium-down,th.hide-for-large-only,td.hide-for-large-only,th.hide-for-large-up,td.hide-for-large-up,th.hide-for-large,td.hide-for-large,th.show-for-large-down,td.show-for-large-down,th.hide-for-xlarge-only,td.hide-for-xlarge-only,th.hide-for-xlarge-up,td.hide-for-xlarge-up,th.hide-for-xlarge,td.hide-for-xlarge,th.show-for-xlarge-down,td.show-for-xlarge-down,th.hide-for-xxlarge-only,td.hide-for-xxlarge-only,th.hide-for-xxlarge-up,td.hide-for-xxlarge-up,th.hide-for-xxlarge,td.hide-for-xxlarge,th.show-for-xxlarge-down,td.show-for-xxlarge-down{display:table-cell !important}}@media only screen and (min-width: 40.0625em){.hide-for-small-only,.show-for-small-up,.hide-for-small,.hide-for-small-down,.show-for-medium-only,.show-for-medium-up,.show-for-medium,.show-for-medium-down,.hide-for-large-only,.hide-for-large-up,.hide-for-large,.show-for-large-down,.hide-for-xlarge-only,.hide-for-xlarge-up,.hide-for-xlarge,.show-for-xlarge-down,.hide-for-xxlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge,.show-for-xxlarge-down{display:inherit !important}.show-for-small-only,.hide-for-small-up,.show-for-small,.show-for-small-down,.hide-for-medium-only,.hide-for-medium-up,.hide-for-medium,.hide-for-medium-down,.show-for-large-only,.show-for-large-up,.show-for-large,.hide-for-large-down,.show-for-xlarge-only,.show-for-xlarge-up,.show-for-xlarge,.hide-for-xlarge-down,.show-for-xxlarge-only,.show-for-xxlarge-up,.show-for-xxlarge,.hide-for-xxlarge-down{display:none !important}.hidden-for-small-only,.visible-for-small-up,.hidden-for-small,.hidden-for-small-down,.visible-for-medium-only,.visible-for-medium-up,.visible-for-medium,.visible-for-medium-down,.hidden-for-large-only,.hidden-for-large-up,.hidden-for-large,.visible-for-large-down,.hidden-for-xlarge-only,.hidden-for-xlarge-up,.hidden-for-xlarge,.visible-for-xlarge-down,.hidden-for-xxlarge-only,.hidden-for-xxlarge-up,.hidden-for-xxlarge,.visible-for-xxlarge-down{position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.visible-for-small-only,.hidden-for-small-up,.visible-for-small,.visible-for-small-down,.hidden-for-medium-only,.hidden-for-medium-up,.hidden-for-medium,.hidden-for-medium-down,.visible-for-large-only,.visible-for-large-up,.visible-for-large,.hidden-for-large-down,.visible-for-xlarge-only,.visible-for-xlarge-up,.visible-for-xlarge,.hidden-for-xlarge-down,.visible-for-xxlarge-only,.visible-for-xxlarge-up,.visible-for-xxlarge,.hidden-for-xxlarge-down{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}table.hide-for-small-only,table.show-for-small-up,table.hide-for-small,table.hide-for-small-down,table.show-for-medium-only,table.show-for-medium-up,table.show-for-medium,table.show-for-medium-down,table.hide-for-large-only,table.hide-for-large-up,table.hide-for-large,table.show-for-large-down,table.hide-for-xlarge-only,table.hide-for-xlarge-up,table.hide-for-xlarge,table.show-for-xlarge-down,table.hide-for-xxlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge,table.show-for-xxlarge-down{display:table !important}thead.hide-for-small-only,thead.show-for-small-up,thead.hide-for-small,thead.hide-for-small-down,thead.show-for-medium-only,thead.show-for-medium-up,thead.show-for-medium,thead.show-for-medium-down,thead.hide-for-large-only,thead.hide-for-large-up,thead.hide-for-large,thead.show-for-large-down,thead.hide-for-xlarge-only,thead.hide-for-xlarge-up,thead.hide-for-xlarge,thead.show-for-xlarge-down,thead.hide-for-xxlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge,thead.show-for-xxlarge-down{display:table-header-group !important}tbody.hide-for-small-only,tbody.show-for-small-up,tbody.hide-for-small,tbody.hide-for-small-down,tbody.show-for-medium-only,tbody.show-for-medium-up,tbody.show-for-medium,tbody.show-for-medium-down,tbody.hide-for-large-only,tbody.hide-for-large-up,tbody.hide-for-large,tbody.show-for-large-down,tbody.hide-for-xlarge-only,tbody.hide-for-xlarge-up,tbody.hide-for-xlarge,tbody.show-for-xlarge-down,tbody.hide-for-xxlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge,tbody.show-for-xxlarge-down{display:table-row-group !important}tr.hide-for-small-only,tr.show-for-small-up,tr.hide-for-small,tr.hide-for-small-down,tr.show-for-medium-only,tr.show-for-medium-up,tr.show-for-medium,tr.show-for-medium-down,tr.hide-for-large-only,tr.hide-for-large-up,tr.hide-for-large,tr.show-for-large-down,tr.hide-for-xlarge-only,tr.hide-for-xlarge-up,tr.hide-for-xlarge,tr.show-for-xlarge-down,tr.hide-for-xxlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge,tr.show-for-xxlarge-down{display:table-row}th.hide-for-small-only,td.hide-for-small-only,th.show-for-small-up,td.show-for-small-up,th.hide-for-small,td.hide-for-small,th.hide-for-small-down,td.hide-for-small-down,th.show-for-medium-only,td.show-for-medium-only,th.show-for-medium-up,td.show-for-medium-up,th.show-for-medium,td.show-for-medium,th.show-for-medium-down,td.show-for-medium-down,th.hide-for-large-only,td.hide-for-large-only,th.hide-for-large-up,td.hide-for-large-up,th.hide-for-large,td.hide-for-large,th.show-for-large-down,td.show-for-large-down,th.hide-for-xlarge-only,td.hide-for-xlarge-only,th.hide-for-xlarge-up,td.hide-for-xlarge-up,th.hide-for-xlarge,td.hide-for-xlarge,th.show-for-xlarge-down,td.show-for-xlarge-down,th.hide-for-xxlarge-only,td.hide-for-xxlarge-only,th.hide-for-xxlarge-up,td.hide-for-xxlarge-up,th.hide-for-xxlarge,td.hide-for-xxlarge,th.show-for-xxlarge-down,td.show-for-xxlarge-down{display:table-cell !important}}@media only screen and (min-width: 64.0625em){.hide-for-small-only,.show-for-small-up,.hide-for-small,.hide-for-small-down,.hide-for-medium-only,.show-for-medium-up,.hide-for-medium,.hide-for-medium-down,.show-for-large-only,.show-for-large-up,.show-for-large,.show-for-large-down,.hide-for-xlarge-only,.hide-for-xlarge-up,.hide-for-xlarge,.show-for-xlarge-down,.hide-for-xxlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge,.show-for-xxlarge-down{display:inherit !important}.show-for-small-only,.hide-for-small-up,.show-for-small,.show-for-small-down,.show-for-medium-only,.hide-for-medium-up,.show-for-medium,.show-for-medium-down,.hide-for-large-only,.hide-for-large-up,.hide-for-large,.hide-for-large-down,.show-for-xlarge-only,.show-for-xlarge-up,.show-for-xlarge,.hide-for-xlarge-down,.show-for-xxlarge-only,.show-for-xxlarge-up,.show-for-xxlarge,.hide-for-xxlarge-down{display:none !important}.hidden-for-small-only,.visible-for-small-up,.hidden-for-small,.hidden-for-small-down,.hidden-for-medium-only,.visible-for-medium-up,.hidden-for-medium,.hidden-for-medium-down,.visible-for-large-only,.visible-for-large-up,.visible-for-large,.visible-for-large-down,.hidden-for-xlarge-only,.hidden-for-xlarge-up,.hidden-for-xlarge,.visible-for-xlarge-down,.hidden-for-xxlarge-only,.hidden-for-xxlarge-up,.hidden-for-xxlarge,.visible-for-xxlarge-down{position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.visible-for-small-only,.hidden-for-small-up,.visible-for-small,.visible-for-small-down,.visible-for-medium-only,.hidden-for-medium-up,.visible-for-medium,.visible-for-medium-down,.hidden-for-large-only,.hidden-for-large-up,.hidden-for-large,.hidden-for-large-down,.visible-for-xlarge-only,.visible-for-xlarge-up,.visible-for-xlarge,.hidden-for-xlarge-down,.visible-for-xxlarge-only,.visible-for-xxlarge-up,.visible-for-xxlarge,.hidden-for-xxlarge-down{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}table.hide-for-small-only,table.show-for-small-up,table.hide-for-small,table.hide-for-small-down,table.hide-for-medium-only,table.show-for-medium-up,table.hide-for-medium,table.hide-for-medium-down,table.show-for-large-only,table.show-for-large-up,table.show-for-large,table.show-for-large-down,table.hide-for-xlarge-only,table.hide-for-xlarge-up,table.hide-for-xlarge,table.show-for-xlarge-down,table.hide-for-xxlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge,table.show-for-xxlarge-down{display:table !important}thead.hide-for-small-only,thead.show-for-small-up,thead.hide-for-small,thead.hide-for-small-down,thead.hide-for-medium-only,thead.show-for-medium-up,thead.hide-for-medium,thead.hide-for-medium-down,thead.show-for-large-only,thead.show-for-large-up,thead.show-for-large,thead.show-for-large-down,thead.hide-for-xlarge-only,thead.hide-for-xlarge-up,thead.hide-for-xlarge,thead.show-for-xlarge-down,thead.hide-for-xxlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge,thead.show-for-xxlarge-down{display:table-header-group !important}tbody.hide-for-small-only,tbody.show-for-small-up,tbody.hide-for-small,tbody.hide-for-small-down,tbody.hide-for-medium-only,tbody.show-for-medium-up,tbody.hide-for-medium,tbody.hide-for-medium-down,tbody.show-for-large-only,tbody.show-for-large-up,tbody.show-for-large,tbody.show-for-large-down,tbody.hide-for-xlarge-only,tbody.hide-for-xlarge-up,tbody.hide-for-xlarge,tbody.show-for-xlarge-down,tbody.hide-for-xxlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge,tbody.show-for-xxlarge-down{display:table-row-group !important}tr.hide-for-small-only,tr.show-for-small-up,tr.hide-for-small,tr.hide-for-small-down,tr.hide-for-medium-only,tr.show-for-medium-up,tr.hide-for-medium,tr.hide-for-medium-down,tr.show-for-large-only,tr.show-for-large-up,tr.show-for-large,tr.show-for-large-down,tr.hide-for-xlarge-only,tr.hide-for-xlarge-up,tr.hide-for-xlarge,tr.show-for-xlarge-down,tr.hide-for-xxlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge,tr.show-for-xxlarge-down{display:table-row}th.hide-for-small-only,td.hide-for-small-only,th.show-for-small-up,td.show-for-small-up,th.hide-for-small,td.hide-for-small,th.hide-for-small-down,td.hide-for-small-down,th.hide-for-medium-only,td.hide-for-medium-only,th.show-for-medium-up,td.show-for-medium-up,th.hide-for-medium,td.hide-for-medium,th.hide-for-medium-down,td.hide-for-medium-down,th.show-for-large-only,td.show-for-large-only,th.show-for-large-up,td.show-for-large-up,th.show-for-large,td.show-for-large,th.show-for-large-down,td.show-for-large-down,th.hide-for-xlarge-only,td.hide-for-xlarge-only,th.hide-for-xlarge-up,td.hide-for-xlarge-up,th.hide-for-xlarge,td.hide-for-xlarge,th.show-for-xlarge-down,td.show-for-xlarge-down,th.hide-for-xxlarge-only,td.hide-for-xxlarge-only,th.hide-for-xxlarge-up,td.hide-for-xxlarge-up,th.hide-for-xxlarge,td.hide-for-xxlarge,th.show-for-xxlarge-down,td.show-for-xxlarge-down{display:table-cell !important}}@media only screen and (min-width: 90.0625em){.hide-for-small-only,.show-for-small-up,.hide-for-small,.hide-for-small-down,.hide-for-medium-only,.show-for-medium-up,.hide-for-medium,.hide-for-medium-down,.hide-for-large-only,.show-for-large-up,.hide-for-large,.hide-for-large-down,.show-for-xlarge-only,.show-for-xlarge-up,.show-for-xlarge,.show-for-xlarge-down,.hide-for-xxlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge,.show-for-xxlarge-down{display:inherit !important}.show-for-small-only,.hide-for-small-up,.show-for-small,.show-for-small-down,.show-for-medium-only,.hide-for-medium-up,.show-for-medium,.show-for-medium-down,.show-for-large-only,.hide-for-large-up,.show-for-large,.show-for-large-down,.hide-for-xlarge-only,.hide-for-xlarge-up,.hide-for-xlarge,.hide-for-xlarge-down,.show-for-xxlarge-only,.show-for-xxlarge-up,.show-for-xxlarge,.hide-for-xxlarge-down{display:none !important}.hidden-for-small-only,.visible-for-small-up,.hidden-for-small,.hidden-for-small-down,.hidden-for-medium-only,.visible-for-medium-up,.hidden-for-medium,.hidden-for-medium-down,.hidden-for-large-only,.visible-for-large-up,.hidden-for-large,.hidden-for-large-down,.visible-for-xlarge-only,.visible-for-xlarge-up,.visible-for-xlarge,.visible-for-xlarge-down,.hidden-for-xxlarge-only,.hidden-for-xxlarge-up,.hidden-for-xxlarge,.visible-for-xxlarge-down{position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.visible-for-small-only,.hidden-for-small-up,.visible-for-small,.visible-for-small-down,.visible-for-medium-only,.hidden-for-medium-up,.visible-for-medium,.visible-for-medium-down,.visible-for-large-only,.hidden-for-large-up,.visible-for-large,.visible-for-large-down,.hidden-for-xlarge-only,.hidden-for-xlarge-up,.hidden-for-xlarge,.hidden-for-xlarge-down,.visible-for-xxlarge-only,.visible-for-xxlarge-up,.visible-for-xxlarge,.hidden-for-xxlarge-down{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}table.hide-for-small-only,table.show-for-small-up,table.hide-for-small,table.hide-for-small-down,table.hide-for-medium-only,table.show-for-medium-up,table.hide-for-medium,table.hide-for-medium-down,table.hide-for-large-only,table.show-for-large-up,table.hide-for-large,table.hide-for-large-down,table.show-for-xlarge-only,table.show-for-xlarge-up,table.show-for-xlarge,table.show-for-xlarge-down,table.hide-for-xxlarge-only,table.hide-for-xxlarge-up,table.hide-for-xxlarge,table.show-for-xxlarge-down{display:table !important}thead.hide-for-small-only,thead.show-for-small-up,thead.hide-for-small,thead.hide-for-small-down,thead.hide-for-medium-only,thead.show-for-medium-up,thead.hide-for-medium,thead.hide-for-medium-down,thead.hide-for-large-only,thead.show-for-large-up,thead.hide-for-large,thead.hide-for-large-down,thead.show-for-xlarge-only,thead.show-for-xlarge-up,thead.show-for-xlarge,thead.show-for-xlarge-down,thead.hide-for-xxlarge-only,thead.hide-for-xxlarge-up,thead.hide-for-xxlarge,thead.show-for-xxlarge-down{display:table-header-group !important}tbody.hide-for-small-only,tbody.show-for-small-up,tbody.hide-for-small,tbody.hide-for-small-down,tbody.hide-for-medium-only,tbody.show-for-medium-up,tbody.hide-for-medium,tbody.hide-for-medium-down,tbody.hide-for-large-only,tbody.show-for-large-up,tbody.hide-for-large,tbody.hide-for-large-down,tbody.show-for-xlarge-only,tbody.show-for-xlarge-up,tbody.show-for-xlarge,tbody.show-for-xlarge-down,tbody.hide-for-xxlarge-only,tbody.hide-for-xxlarge-up,tbody.hide-for-xxlarge,tbody.show-for-xxlarge-down{display:table-row-group !important}tr.hide-for-small-only,tr.show-for-small-up,tr.hide-for-small,tr.hide-for-small-down,tr.hide-for-medium-only,tr.show-for-medium-up,tr.hide-for-medium,tr.hide-for-medium-down,tr.hide-for-large-only,tr.show-for-large-up,tr.hide-for-large,tr.hide-for-large-down,tr.show-for-xlarge-only,tr.show-for-xlarge-up,tr.show-for-xlarge,tr.show-for-xlarge-down,tr.hide-for-xxlarge-only,tr.hide-for-xxlarge-up,tr.hide-for-xxlarge,tr.show-for-xxlarge-down{display:table-row}th.hide-for-small-only,td.hide-for-small-only,th.show-for-small-up,td.show-for-small-up,th.hide-for-small,td.hide-for-small,th.hide-for-small-down,td.hide-for-small-down,th.hide-for-medium-only,td.hide-for-medium-only,th.show-for-medium-up,td.show-for-medium-up,th.hide-for-medium,td.hide-for-medium,th.hide-for-medium-down,td.hide-for-medium-down,th.hide-for-large-only,td.hide-for-large-only,th.show-for-large-up,td.show-for-large-up,th.hide-for-large,td.hide-for-large,th.hide-for-large-down,td.hide-for-large-down,th.show-for-xlarge-only,td.show-for-xlarge-only,th.show-for-xlarge-up,td.show-for-xlarge-up,th.show-for-xlarge,td.show-for-xlarge,th.show-for-xlarge-down,td.show-for-xlarge-down,th.hide-for-xxlarge-only,td.hide-for-xxlarge-only,th.hide-for-xxlarge-up,td.hide-for-xxlarge-up,th.hide-for-xxlarge,td.hide-for-xxlarge,th.show-for-xxlarge-down,td.show-for-xxlarge-down{display:table-cell !important}}@media only screen and (min-width: 120.0625em){.hide-for-small-only,.show-for-small-up,.hide-for-small,.hide-for-small-down,.hide-for-medium-only,.show-for-medium-up,.hide-for-medium,.hide-for-medium-down,.hide-for-large-only,.show-for-large-up,.hide-for-large,.hide-for-large-down,.hide-for-xlarge-only,.show-for-xlarge-up,.hide-for-xlarge,.hide-for-xlarge-down,.show-for-xxlarge-only,.show-for-xxlarge-up,.show-for-xxlarge,.show-for-xxlarge-down{display:inherit !important}.show-for-small-only,.hide-for-small-up,.show-for-small,.show-for-small-down,.show-for-medium-only,.hide-for-medium-up,.show-for-medium,.show-for-medium-down,.show-for-large-only,.hide-for-large-up,.show-for-large,.show-for-large-down,.show-for-xlarge-only,.hide-for-xlarge-up,.show-for-xlarge,.show-for-xlarge-down,.hide-for-xxlarge-only,.hide-for-xxlarge-up,.hide-for-xxlarge,.hide-for-xxlarge-down{display:none !important}.hidden-for-small-only,.visible-for-small-up,.hidden-for-small,.hidden-for-small-down,.hidden-for-medium-only,.visible-for-medium-up,.hidden-for-medium,.hidden-for-medium-down,.hidden-for-large-only,.visible-for-large-up,.hidden-for-large,.hidden-for-large-down,.hidden-for-xlarge-only,.visible-for-xlarge-up,.hidden-for-xlarge,.hidden-for-xlarge-down,.visible-for-xxlarge-only,.visible-for-xxlarge-up,.visible-for-xxlarge,.visible-for-xxlarge-down{position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.visible-for-small-only,.hidden-for-small-up,.visible-for-small,.visible-for-small-down,.visible-for-medium-only,.hidden-for-medium-up,.visible-for-medium,.visible-for-medium-down,.visible-for-large-only,.hidden-for-large-up,.visible-for-large,.visible-for-large-down,.visible-for-xlarge-only,.hidden-for-xlarge-up,.visible-for-xlarge,.visible-for-xlarge-down,.hidden-for-xxlarge-only,.hidden-for-xxlarge-up,.hidden-for-xxlarge,.hidden-for-xxlarge-down{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}table.hide-for-small-only,table.show-for-small-up,table.hide-for-small,table.hide-for-small-down,table.hide-for-medium-only,table.show-for-medium-up,table.hide-for-medium,table.hide-for-medium-down,table.hide-for-large-only,table.show-for-large-up,table.hide-for-large,table.hide-for-large-down,table.hide-for-xlarge-only,table.show-for-xlarge-up,table.hide-for-xlarge,table.hide-for-xlarge-down,table.show-for-xxlarge-only,table.show-for-xxlarge-up,table.show-for-xxlarge,table.show-for-xxlarge-down{display:table !important}thead.hide-for-small-only,thead.show-for-small-up,thead.hide-for-small,thead.hide-for-small-down,thead.hide-for-medium-only,thead.show-for-medium-up,thead.hide-for-medium,thead.hide-for-medium-down,thead.hide-for-large-only,thead.show-for-large-up,thead.hide-for-large,thead.hide-for-large-down,thead.hide-for-xlarge-only,thead.show-for-xlarge-up,thead.hide-for-xlarge,thead.hide-for-xlarge-down,thead.show-for-xxlarge-only,thead.show-for-xxlarge-up,thead.show-for-xxlarge,thead.show-for-xxlarge-down{display:table-header-group !important}tbody.hide-for-small-only,tbody.show-for-small-up,tbody.hide-for-small,tbody.hide-for-small-down,tbody.hide-for-medium-only,tbody.show-for-medium-up,tbody.hide-for-medium,tbody.hide-for-medium-down,tbody.hide-for-large-only,tbody.show-for-large-up,tbody.hide-for-large,tbody.hide-for-large-down,tbody.hide-for-xlarge-only,tbody.show-for-xlarge-up,tbody.hide-for-xlarge,tbody.hide-for-xlarge-down,tbody.show-for-xxlarge-only,tbody.show-for-xxlarge-up,tbody.show-for-xxlarge,tbody.show-for-xxlarge-down{display:table-row-group !important}tr.hide-for-small-only,tr.show-for-small-up,tr.hide-for-small,tr.hide-for-small-down,tr.hide-for-medium-only,tr.show-for-medium-up,tr.hide-for-medium,tr.hide-for-medium-down,tr.hide-for-large-only,tr.show-for-large-up,tr.hide-for-large,tr.hide-for-large-down,tr.hide-for-xlarge-only,tr.show-for-xlarge-up,tr.hide-for-xlarge,tr.hide-for-xlarge-down,tr.show-for-xxlarge-only,tr.show-for-xxlarge-up,tr.show-for-xxlarge,tr.show-for-xxlarge-down{display:table-row}th.hide-for-small-only,td.hide-for-small-only,th.show-for-small-up,td.show-for-small-up,th.hide-for-small,td.hide-for-small,th.hide-for-small-down,td.hide-for-small-down,th.hide-for-medium-only,td.hide-for-medium-only,th.show-for-medium-up,td.show-for-medium-up,th.hide-for-medium,td.hide-for-medium,th.hide-for-medium-down,td.hide-for-medium-down,th.hide-for-large-only,td.hide-for-large-only,th.show-for-large-up,td.show-for-large-up,th.hide-for-large,td.hide-for-large,th.hide-for-large-down,td.hide-for-large-down,th.hide-for-xlarge-only,td.hide-for-xlarge-only,th.show-for-xlarge-up,td.show-for-xlarge-up,th.hide-for-xlarge,td.hide-for-xlarge,th.hide-for-xlarge-down,td.hide-for-xlarge-down,th.show-for-xxlarge-only,td.show-for-xxlarge-only,th.show-for-xxlarge-up,td.show-for-xxlarge-up,th.show-for-xxlarge,td.show-for-xxlarge,th.show-for-xxlarge-down,td.show-for-xxlarge-down{display:table-cell !important}}.show-for-landscape,.hide-for-portrait{display:inherit !important}.hide-for-landscape,.show-for-portrait{display:none !important}table.hide-for-landscape,table.show-for-portrait{display:table !important}thead.hide-for-landscape,thead.show-for-portrait{display:table-header-group !important}tbody.hide-for-landscape,tbody.show-for-portrait{display:table-row-group !important}tr.hide-for-landscape,tr.show-for-portrait{display:table-row !important}td.hide-for-landscape,td.show-for-portrait,th.hide-for-landscape,th.show-for-portrait{display:table-cell !important}@media only screen and (orientation: landscape){.show-for-landscape,.hide-for-portrait{display:inherit !important}.hide-for-landscape,.show-for-portrait{display:none !important}table.show-for-landscape,table.hide-for-portrait{display:table !important}thead.show-for-landscape,thead.hide-for-portrait{display:table-header-group !important}tbody.show-for-landscape,tbody.hide-for-portrait{display:table-row-group !important}tr.show-for-landscape,tr.hide-for-portrait{display:table-row !important}td.show-for-landscape,td.hide-for-portrait,th.show-for-landscape,th.hide-for-portrait{display:table-cell !important}}@media only screen and (orientation: portrait){.show-for-portrait,.hide-for-landscape{display:inherit !important}.hide-for-portrait,.show-for-landscape{display:none !important}table.show-for-portrait,table.hide-for-landscape{display:table !important}thead.show-for-portrait,thead.hide-for-landscape{display:table-header-group !important}tbody.show-for-portrait,tbody.hide-for-landscape{display:table-row-group !important}tr.show-for-portrait,tr.hide-for-landscape{display:table-row !important}td.show-for-portrait,td.hide-for-landscape,th.show-for-portrait,th.hide-for-landscape{display:table-cell !important}}.show-for-touch{display:none !important}.hide-for-touch{display:inherit !important}.touch .show-for-touch{display:inherit !important}.touch .hide-for-touch{display:none !important}table.hide-for-touch{display:table !important}.touch table.show-for-touch{display:table !important}thead.hide-for-touch{display:table-header-group !important}.touch thead.show-for-touch{display:table-header-group !important}tbody.hide-for-touch{display:table-row-group !important}.touch tbody.show-for-touch{display:table-row-group !important}tr.hide-for-touch{display:table-row !important}.touch tr.show-for-touch{display:table-row !important}td.hide-for-touch{display:table-cell !important}.touch td.show-for-touch{display:table-cell !important}th.hide-for-touch{display:table-cell !important}.touch th.show-for-touch{display:table-cell !important}.print-only{display:none !important}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}.show-for-print{display:block}.hide-for-print{display:none}table.show-for-print{display:table !important}thead.show-for-print{display:table-header-group !important}tbody.show-for-print{display:table-row-group !important}tr.show-for-print{display:table-row !important}td.show-for-print{display:table-cell !important}th.show-for-print{display:table-cell !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.hide-on-print{display:none !important}.print-only{display:block !important}.hide-for-print{display:none !important}.show-for-print{display:inherit !important}}@media print{.show-for-print{display:block}.hide-for-print{display:none}table.show-for-print{display:table !important}thead.show-for-print{display:table-header-group !important}tbody.show-for-print{display:table-row-group !important}tr.show-for-print{display:table-row !important}td.show-for-print{display:table-cell !important}th.show-for-print{display:table-cell !important}}.slick-slider{position:relative;display:block;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.slick-list{position:relative;overflow:hidden;display:block;margin:0;padding:0}.slick-list:focus{outline:none}.slick-list.dragging{cursor:pointer;cursor:hand}.slick-slider .slick-track,.slick-slider .slick-list{-webkit-transform:translate3d(0, 0, 0);-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-o-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}.slick-track{position:relative;left:0;top:0;display:block}.slick-track:before,.slick-track:after{content:"";display:table}.slick-track:after{clear:both}.slick-loading .slick-track{visibility:hidden}.slick-slide{float:left;height:100%;min-height:1px;display:none}[dir="rtl"] .slick-slide{float:right}.slick-slide img{display:block}.slick-slide.slick-loading img{display:none}.slick-slide.dragging img{pointer-events:none}.slick-initialized .slick-slide{display:block}.slick-loading .slick-slide{visibility:hidden}.slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.slick-loading .slick-list{background:#fff url("../img/ajax-loader.gif") center center no-repeat}.slick-prev,.slick-next{position:absolute;display:block;height:20px;width:20px;line-height:0;font-size:0;cursor:pointer;background:transparent;color:transparent;top:50%;margin-top:-10px;padding:0;border:none;outline:none}.slick-prev:hover,.slick-prev:focus,.slick-next:hover,.slick-next:focus{outline:none;background:transparent;color:transparent}.slick-prev:hover:before,.slick-prev:focus:before,.slick-next:hover:before,.slick-next:focus:before{opacity:1}.slick-prev.slick-disabled:before,.slick-next.slick-disabled:before{opacity:.25}.slick-prev:before,.slick-next:before{font-family:"FontAwesome";font-size:20px;line-height:1;color:#ba2619;opacity:.75;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-prev{left:15px}[dir="rtl"] .slick-prev{left:auto;right:15px}.slick-prev:before{content:""}[dir="rtl"] .slick-prev:before{content:""}.slick-next{right:15px}[dir="rtl"] .slick-next{left:15px;right:auto}.slick-next:before{content:""}[dir="rtl"] .slick-next:before{content:""}.slick-slider{margin-bottom:30px}.slick-dots{margin:0;position:absolute;bottom:30px;list-style:none;display:block;text-align:center;padding:0;width:100%}.slick-dots li{position:relative;display:inline-block;height:20px;width:20px;margin:0 5px;padding:0;cursor:pointer}.slick-dots li button{border:0;background:transparent;display:block;height:20px;width:20px;outline:none;line-height:0;font-size:0;color:transparent;padding:5px;cursor:pointer}.slick-dots li button:hover,.slick-dots li button:focus{outline:none}.slick-dots li button:hover:before,.slick-dots li button:focus:before{opacity:1}.slick-dots li button:before{position:absolute;top:0;left:0;content:"";width:20px;height:20px;font-family:"FontAwesome";font-size:12px;line-height:20px;text-align:center;color:#000;opacity:.25;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-dots li.slick-active button:before{color:#ba2619;opacity:.75}/*! * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url("./fonts/fontawesome-webfont.eot?v=4.4.0");src:url("./fonts/fontawesome-webfont.eot?#iefix&v=4.4.0") format("embedded-opentype"),url("./fonts/fontawesome-webfont.woff2?v=4.4.0") format("woff2"),url("./fonts/fontawesome-webfont.woff?v=4.4.0") format("woff"),url("./fonts/fontawesome-webfont.ttf?v=4.4.0") format("truetype"),url("./fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857em;text-align:center}.fa-ul{padding-left:0;margin-left:2.1428571429em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.1428571429em;width:2.1428571429em;top:.1428571429em;text-align:center}.fa-li.fa-lg{left:-1.8571428571em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before{content:""}.fa-check-circle:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before{content:""}.fa-arrow-circle-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-hotel:before,.fa-bed:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-yc:before,.fa-y-combinator:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-tv:before,.fa-television:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.maxWidth{width:100%}.hidden{display:none}*{transition:all 0.15s ease}body{background-color:#333}body>main{padding:2.5rem 0;background-color:#fff}@media only screen and (max-width: 40em){body>main{padding:1.25rem 0}}body>main img{margin-bottom:1.25rem}@media only screen and (max-width: 40em){aside{margin-bottom:1.5rem}}@media only screen and (max-width: 40em){.row{overflow:hidden}}body>footer{background-color:#333;padding:2.5rem 0;color:#999}body>footer p,body>footer h1,body>footer h2,body>footer h3,body>footer h4,body>footer h5,body>footer h6{color:inherit}body>footer a{color:#e23424}code{font-size:85%;color:inherit !important;overflow-x:scroll;-webkit-overflow-scrolling:touch}.highlight{border:solid 1px #ddd;background:#fff;padding:1em;line-height:23px;margin-bottom:30px;white-space:pre;overflow-x:auto;word-break:inherit;word-wrap:inherit;background:#ffffff}@media only screen and (max-width: 40em){.highlight{overflow-x:scroll;-webkit-overflow-scrolling:touch}}.highlight code{background-color:transparent;border:none;padding:0}.highlight td{padding:8px 15px}.highlight .gl{background:#fafafa;border-right:1px solid #ddd;color:#999;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlight .c{color:#999988;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .k{font-weight:bold}.highlight .o{font-weight:bold}.highlight .cm{color:#999988;font-style:italic}.highlight .cp{color:#999999;font-weight:bold}.highlight .c1{color:#999988;font-style:italic}.highlight .cs{color:#999999;font-weight:bold;font-style:italic}.highlight .gd{color:#000000;background-color:#ffdddd}.highlight .gd .x{color:#000000;background-color:#ffaaaa}.highlight .ge{font-style:italic}.highlight .gr{color:#aa0000}.highlight .gh{color:#999999}.highlight .gi{color:#000000;background-color:#ddffdd}.highlight .gi .x{color:#000000;background-color:#aaffaa}.highlight .go{color:#888888}.highlight .gp{color:#555555}.highlight .gs{font-weight:bold}.highlight .gu{color:#aaaaaa}.highlight .gt{color:#aa0000}.highlight .kc{font-weight:bold}.highlight .kd{font-weight:bold}.highlight .kp{font-weight:bold}.highlight .kr{font-weight:bold}.highlight .kt{color:#445588;font-weight:bold}.highlight .m{color:#009999}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .nb{color:#0086B3}.highlight .nc{color:#445588;font-weight:bold}.highlight .no{color:#008080}.highlight .ni{color:#800080}.highlight .ne{color:#990000;font-weight:bold}.highlight .nf{color:#990000;font-weight:bold}.highlight .nn{color:#555555}.highlight .nt{color:#000080}.highlight .nv{color:#008080}.highlight .ow{font-weight:bold}.highlight .w{color:#bbbbbb}.highlight .mf{color:#009999}.highlight .mh{color:#009999}.highlight .mi{color:#009999}.highlight .mo{color:#009999}.highlight .sb{color:#d14}.highlight .sc{color:#d14}.highlight .sd{color:#d14}.highlight .s2{color:#d14}.highlight .se{color:#d14}.highlight .sh{color:#d14}.highlight .si{color:#d14}.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999999}.highlight .vc{color:#008080}.highlight .vg{color:#008080}.highlight .vi{color:#008080}.highlight .il{color:#009999}kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#555;vertical-align:middle;background-color:#fcfcfc;border:solid 1px #ccc;border-bottom-color:#bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}.social__icons{margin-bottom:10px}.social__icon{display:inline-block;margin-right:10px}.slider picture img{width:100%}.videoWrapper{position:relative;padding-top:56.25%;margin-bottom:1.25rem}.videoWrapper iframe{position:absolute;top:0;left:0;width:100%;height:100%}.icon{position:relative;top:1px;display:inline-block;width:16px;height:16px}.icon-color{border:1px solid #aaa}.icon-color-white{background-color:#fff}.icon-color-black{background-color:#000}.icon-color-red{background-color:#ba2619}.toc-header{margin-bottom:0}#toc{display:block;margin:1rem 0 0 0}#toc>ol{margin-left:0}#toc>ol>li{margin-bottom:0.5rem}#toc ol{list-style-type:none}.clickable-header{cursor:pointer}.clickable-header:hover{text-decoration:underline}.top-level-header{display:inline-block}.back-to-top{position:relative;margin-left:8px;cursor:pointer;top:-3px}.contentSearch{margin-bottom:30px}@media only screen and (max-width: 40em){.contentSearch{margin-bottom:5px}}.contentSearch-wrapper{position:relative}.contentSearch-wrapper.small-collapse{margin:0 !important}.liveSearch-field{margin-bottom:0 !important}.liveSearch-button{margin-bottom:0}.liveSearch-result-list{position:absolute;width:100%;height:auto;background:white;border:1px #ccc;border-style:none solid solid solid;z-index:99;margin:0;list-style-type:none}@media only screen and (max-width: 40em){.liveSearch-result-list{position:relative}}.liveSearch-result-list li a{-webkit-transition:all 0.15s ease;transition:all 0.15s ease;padding:4px 10px;display:block;width:100%;height:100%;line-height:1.2}.liveSearch-result-list li a:hover{background-color:#eee}.liveSearch-result-list li a:first-child{padding-top:8px}.liveSearch-result-list li a:last-child{padding-bottom:8px}.searchPage-result-list{line-height:1.2;list-style-type:none}.searchPage-result-list li{margin-bottom:20px}@media only screen and (max-width: 40em){.searchPage-result-list li{margin-bottom:15px}}.searchPage-result-list li a{font-weight:bold;color:#1a0dab}.searchPage-result-list li a:hover{color:#1a0dab;text-decoration:underline}.searchPage-result-list li .url{color:#006621}@media only screen and (max-width: 40em){.searchPage-result-list li .additionalInfo{display:none}}.article-list{margin:0;padding:0;list-style-type:none}.article-list header h1{font-size:1.5rem}article header{margin-bottom:0.5rem}article header h1{margin-bottom:0}article .meta{font-size:0.9em}.table-wrapper{width:100%;overflow-y:auto;_overflow:auto;margin:0 0 1em} + */@font-face{font-family:'FontAwesome';src:url("./fonts/fontawesome-webfont.eot?v=4.4.0");src:url("./fonts/fontawesome-webfont.eot?#iefix&v=4.4.0") format("embedded-opentype"),url("./fonts/fontawesome-webfont.woff2?v=4.4.0") format("woff2"),url("./fonts/fontawesome-webfont.woff?v=4.4.0") format("woff"),url("./fonts/fontawesome-webfont.ttf?v=4.4.0") format("truetype"),url("./fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857em;text-align:center}.fa-ul{padding-left:0;margin-left:2.1428571429em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.1428571429em;width:2.1428571429em;top:.1428571429em;text-align:center}.fa-li.fa-lg{left:-1.8571428571em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before{content:""}.fa-check-circle:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before{content:""}.fa-arrow-circle-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-hotel:before,.fa-bed:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-yc:before,.fa-y-combinator:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-tv:before,.fa-television:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.maxWidth{width:100%}.hidden{display:none}*{transition:all 0.15s ease}body{background-color:#333}body>main{padding:2.5rem 0;background-color:#fff}@media only screen and (max-width: 40em){body>main{padding:1.25rem 0}}body>main img{margin-bottom:1.25rem}@media only screen and (max-width: 40em){aside{margin-bottom:1.5rem}}@media only screen and (max-width: 40em){.row{overflow:hidden}}body>footer{background-color:#333;padding:2.5rem 0;color:#999}body>footer p,body>footer h1,body>footer h2,body>footer h3,body>footer h4,body>footer h5,body>footer h6{color:inherit}body>footer a{color:#e23424}code{font-size:85%;color:inherit !important;overflow-x:scroll;-webkit-overflow-scrolling:touch}pre.highlight{border:solid 1px #ddd;background:#fff;padding:1em;line-height:23px;margin-bottom:30px;white-space:pre;overflow-x:auto;word-break:inherit;word-wrap:inherit;background:#ffffff}@media only screen and (max-width: 40em){pre.highlight{overflow-x:scroll;-webkit-overflow-scrolling:touch}}pre.highlight code{background-color:transparent;border:none;padding:0}pre.highlight td{padding:8px 15px}pre.highlight .gl{background:#fafafa;border-right:1px solid #ddd;color:#999;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}pre.highlight .c{color:#999988;font-style:italic}pre.highlight .err{color:#a61717;background-color:#e3d2d2}pre.highlight .k{font-weight:bold}pre.highlight .o{font-weight:bold}pre.highlight .cm{color:#999988;font-style:italic}pre.highlight .cp{color:#999999;font-weight:bold}pre.highlight .c1{color:#999988;font-style:italic}pre.highlight .cs{color:#999999;font-weight:bold;font-style:italic}pre.highlight .gd{color:#000000;background-color:#ffdddd}pre.highlight .gd .x{color:#000000;background-color:#ffaaaa}pre.highlight .ge{font-style:italic}pre.highlight .gr{color:#aa0000}pre.highlight .gh{color:#999999}pre.highlight .gi{color:#000000;background-color:#ddffdd}pre.highlight .gi .x{color:#000000;background-color:#aaffaa}pre.highlight .go{color:#888888}pre.highlight .gp{color:#555555}pre.highlight .gs{font-weight:bold}pre.highlight .gu{color:#aaaaaa}pre.highlight .gt{color:#aa0000}pre.highlight .kc{font-weight:bold}pre.highlight .kd{font-weight:bold}pre.highlight .kp{font-weight:bold}pre.highlight .kr{font-weight:bold}pre.highlight .kt{color:#445588;font-weight:bold}pre.highlight .m{color:#009999}pre.highlight .s{color:#d14}pre.highlight .na{color:#008080}pre.highlight .nb{color:#0086B3}pre.highlight .nc{color:#445588;font-weight:bold}pre.highlight .no{color:#008080}pre.highlight .ni{color:#800080}pre.highlight .ne{color:#990000;font-weight:bold}pre.highlight .nf{color:#990000;font-weight:bold}pre.highlight .nn{color:#555555}pre.highlight .nt{color:#000080}pre.highlight .nv{color:#008080}pre.highlight .ow{font-weight:bold}pre.highlight .w{color:#bbbbbb}pre.highlight .mf{color:#009999}pre.highlight .mh{color:#009999}pre.highlight .mi{color:#009999}pre.highlight .mo{color:#009999}pre.highlight .sb{color:#d14}pre.highlight .sc{color:#d14}pre.highlight .sd{color:#d14}pre.highlight .s2{color:#d14}pre.highlight .se{color:#d14}pre.highlight .sh{color:#d14}pre.highlight .si{color:#d14}pre.highlight .sx{color:#d14}pre.highlight .sr{color:#009926}pre.highlight .s1{color:#d14}pre.highlight .ss{color:#990073}pre.highlight .bp{color:#999999}pre.highlight .vc{color:#008080}pre.highlight .vg{color:#008080}pre.highlight .vi{color:#008080}pre.highlight .il{color:#009999}kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#555;vertical-align:middle;background-color:#fcfcfc;border:solid 1px #ccc;border-bottom-color:#bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}.social__icons{margin-bottom:10px}.social__icon{display:inline-block;margin-right:10px}.slider picture img{width:100%}.videoWrapper{position:relative;padding-top:56.25%;margin-bottom:1.25rem}.videoWrapper iframe{position:absolute;top:0;left:0;width:100%;height:100%}.icon{position:relative;top:1px;display:inline-block;width:16px;height:16px}.icon-color{border:1px solid #aaa}.icon-color-white{background-color:#fff}.icon-color-black{background-color:#000}.icon-color-red{background-color:#ba2619}.toc-header{margin-bottom:0}#toc{display:block;margin:1rem 0 0 0}#toc>ol{margin-left:0}#toc>ol>li{margin-bottom:0.5rem}#toc ol{list-style-type:none}.clickable-header{cursor:pointer}.clickable-header:hover{text-decoration:underline}.top-level-header{display:inline-block}.back-to-top{position:relative;margin-left:8px;cursor:pointer;top:-3px}.contentSearch{margin-bottom:30px}@media only screen and (max-width: 40em){.contentSearch{margin-bottom:5px}}.contentSearch-wrapper{position:relative}.contentSearch-wrapper.small-collapse{margin:0 !important}.liveSearch-field{margin-bottom:0 !important}.liveSearch-button{margin-bottom:0}.liveSearch-result-list{position:absolute;width:100%;height:auto;background:white;border:1px #ccc;border-style:none solid solid solid;z-index:99;margin:0;list-style-type:none}@media only screen and (max-width: 40em){.liveSearch-result-list{position:relative}}.liveSearch-result-list li a{-webkit-transition:all 0.15s ease;transition:all 0.15s ease;padding:4px 10px;display:block;width:100%;height:100%;line-height:1.2}.liveSearch-result-list li a:hover{background-color:#eee}.liveSearch-result-list li a:first-child{padding-top:8px}.liveSearch-result-list li a:last-child{padding-bottom:8px}.searchPage-result-list{line-height:1.2;list-style-type:none}.searchPage-result-list li{margin-bottom:20px}@media only screen and (max-width: 40em){.searchPage-result-list li{margin-bottom:15px}}.searchPage-result-list li a{font-weight:bold;color:#1a0dab}.searchPage-result-list li a:hover{color:#1a0dab;text-decoration:underline}.searchPage-result-list li .url{color:#006621}@media only screen and (max-width: 40em){.searchPage-result-list li .additionalInfo{display:none}}.article-list{margin:0;padding:0;list-style-type:none}.article-list header h1{font-size:1.5rem}article header{margin-bottom:0.5rem}article header h1{margin-bottom:0}article .meta{font-size:0.9em}.table-wrapper{width:100%;overflow-y:auto;_overflow:auto;margin:0 0 1em} diff --git a/docs/js/footer.min.js b/docs/js/footer.min.js index c12f82fe62..7e9a86bd64 100644 --- a/docs/js/footer.min.js +++ b/docs/js/footer.min.js @@ -1,7 +1,7 @@ -window.Modernizr=function(a,b,c){function d(a){o.cssText=a}function e(a,b){return typeof a===b}var f,g,h,i="2.8.3",j={},k=!0,l=b.documentElement,m="modernizr",n=b.createElement(m),o=n.style,p=({}.toString,{}),q=[],r=q.slice,s={}.hasOwnProperty;h=e(s,"undefined")||e(s.call,"undefined")?function(a,b){return b in a&&e(a.constructor.prototype[b],"undefined")}:function(a,b){return s.call(a,b)},Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if("function"!=typeof b)throw new TypeError;var c=r.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,g=b.apply(f,c.concat(r.call(arguments)));return Object(g)===g?g:f}return b.apply(a,c.concat(r.call(arguments)))};return d});for(var t in p)h(p,t)&&(g=t.toLowerCase(),j[g]=p[t](),q.push((j[g]?"":"no-")+g));return j.addTest=function(a,b){if("object"==typeof a)for(var d in a)h(a,d)&&j.addTest(d,a[d]);else{if(a=a.toLowerCase(),j[a]!==c)return j;b="function"==typeof b?b():b,"undefined"!=typeof k&&k&&(l.className+=" "+(b?"":"no-")+a),j[a]=b}return j},d(""),n=f=null,function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=s.elements;return"string"==typeof a?a.split(" "):a}function e(a){var b=r[a[p]];return b||(b={},q++,a[p]=q,r[q]=b),b}function f(a,c,d){if(c||(c=b),k)return c.createElement(a);d||(d=e(c));var f;return f=d.cache[a]?d.cache[a].cloneNode():o.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!f.canHaveChildren||n.test(a)||f.tagUrn?f:d.frag.appendChild(f)}function g(a,c){if(a||(a=b),k)return a.createDocumentFragment();c=c||e(a);for(var f=c.frag.cloneNode(),g=0,h=d(),i=h.length;g",j="hidden"in a,k=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(a){j=!0,k=!0}}();var s={elements:m.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:l,shivCSS:m.shivCSS!==!1,supportsUnknownElements:k,shivMethods:m.shivMethods!==!1,type:"default",shivDocument:i,createElement:f,createDocumentFragment:g};a.html5=s,i(b)}(this,b),j._version=i,l.className=l.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(k?" js "+q.join(" "):""),j}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==q.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=r.shift();s=1,a?a.t?o(function(){("c"==a.t?m.injectCss:m.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):s=0}function i(a,c,d,e,f,i,j){function k(b){if(!n&&g(l.readyState)&&(t.r=n=1,!s&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&o(function(){v.removeChild(l)},50);for(var d in A[c])A[c].hasOwnProperty(d)&&A[c][d].onload()}}var j=j||m.errorTimeout,l=b.createElement(a),n=0,q=0,t={t:d,s:c,e:f,a:i,x:j};1===A[c]&&(q=1,A[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,q)},r.splice(e,0,t),"img"!=a&&(q||2===A[c]?(v.insertBefore(l,u?null:p),o(k,j)):A[c].push(l))}function j(a,b,c,d,f){return s=0,b=b||"j",e(a)?i("c"==b?x:w,a,b,this.i++,c,d,f):(r.splice(this.i++,0,a),1==r.length&&h()),this}function k(){var a=m;return a.loader={load:j,i:0},a}var l,m,n=b.documentElement,o=a.setTimeout,p=b.getElementsByTagName("script")[0],q={}.toString,r=[],s=0,t="MozAppearance"in n.style,u=t&&!!b.createRange().compareNode,v=u?n:p.parentNode,n=a.opera&&"[object Opera]"==q.call(a.opera),n=!!b.attachEvent&&!n,w=t?"object":n?"script":"img",x=n?"script":w,y=Array.isArray||function(a){return"[object Array]"==q.call(a)},z=[],A={},B={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}};m=function(a){function b(a){var b,c,d,a=a.split("!"),e=z.length,f=a.pop(),g=a.length,f={url:f,origUrl:f,prefixes:a};for(c=0;ca._pfLastSize)&&(a._pfLastSize=a.offsetWidth,d=a.sizes,a.sizes+=",100vw",setTimeout(function(){a.sizes=d}))},e=function(){var a,b=document.querySelectorAll("picture > img, img[srcset][sizes]");for(a=0;a2.7?h=c+1:(f=b-c,e=Math.pow(a-.6,1.5),g=f*e,d&&(g+=.1*e),h=a+g):h=c>1?Math.sqrt(a*b):a,h>c}function h(a){var b,c=s.getSet(a),d=!1;"pending"!==c&&(d=r,c&&(b=s.setRes(c),s.applySetCandidate(b,a))),a[s.ns].evaled=d}function i(a,b){return a.res-b.res}function j(a,b,c){var d;return!c&&b&&(c=a[s.ns].sets,c=c&&c[c.length-1]),d=k(b,c),d&&(b=s.makeUrl(b),a[s.ns].curSrc=b,a[s.ns].curCan=d,d.res||aa(d,d.set.sizes)),d}function k(a,b){var c,d,e;if(a&&b)for(e=s.parseSet(b),a=s.makeUrl(a),c=0;c=l)return n;g=c(V),h=[],","===g.slice(-1)?(g=g.replace(W,""),e()):f()}}function n(a){function b(a){function b(){f&&(g.push(f),f="")}function c(){g[0]&&(h.push(g),g=[])}for(var e,f="",g=[],h=[],i=0,j=0,k=!1;;){if(e=a.charAt(j),""===e)return b(),c(),h;if(k){if("*"===e&&"/"===a[j+1]){k=!1,j+=2,b();continue}j+=1}else{if(d(e)){if(a.charAt(j-1)&&d(a.charAt(j-1))||!f){j+=1;continue}if(0===i){b(),j+=1;continue}e=" "}else if("("===e)i+=1;else if(")"===e)i-=1;else{if(","===e){b(),c(),j+=1;continue}if("/"===e&&"*"===a.charAt(j+1)){k=!0,j+=2;continue}}f+=e,j+=1}}}function c(a){return!!(k.test(a)&&parseFloat(a)>=0)||(!!l.test(a)||("0"===a||"-0"===a||"+0"===a))}var e,f,g,h,i,j,k=/^(?:[+-]?[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?(?:ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmin|vmax|vw)$/i,l=/^calc\((?:[0-9a-z \.\+\-\*\/\(\)]+)\)$/i;for(f=b(a),g=f.length,e=0;e35,G="currentSrc",H=/\s+\+?\d+(e\d+)?w/,I=/(\([^)]+\))?\s*(.+)/,J=a.picturefillCFG,K="position:absolute;left:0;visibility:hidden;display:block;padding:0;border:none;font-size:1em;width:1em;overflow:hidden;clip:rect(0px, 0px, 0px, 0px)",L="font-size:100%!important;",M=!0,N={},O={},P=a.devicePixelRatio,Q={px:1,in:96},R=b.createElement("a"),S=!1,T=/^[ \t\n\r\u000c]+/,U=/^[, \t\n\r\u000c]+/,V=/^[^ \t\n\r\u000c]+/,W=/[,]+$/,X=/^\d+$/,Y=/^-?(?:[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?$/,Z=function(a,b,c,d){a.addEventListener?a.addEventListener(b,c,d||!1):a.attachEvent&&a.attachEvent("on"+b,c)},$=function(a){var b={};return function(c){return c in b||(b[c]=a(c)),b[c]}},_=function(){var a=/^([\d\.]+)(em|vw|px)$/,b=function(){for(var a=arguments,b=0,c=a[0];++b in a;)c=c.replace(a[b],a[++b]);return c},c=$(function(a){return"return "+b((a||"").toLowerCase(),/\band\b/g,"&&",/,/g,"||",/min-([a-z-\s]+):/g,"e.$1>=",/max-([a-z-\s]+):/g,"e.$1<=",/calc([^)]+)/g,"($1)",/(\d+[\.]*[\d]*)([a-z]+)/g,"($1 * e.$2)",/^(?!(e.[a-z]|[0-9\.&=|><\+\-\*\(\)\/])).*/gi,"")+";"});return function(b,d){var e;if(!(b in N))if(N[b]=!1,d&&(e=b.match(a)))N[b]=e[1]*Q[e[2]];else try{N[b]=new Function("e",c(b))(Q)}catch(a){}return N[b]}}(),aa=function(a,b){return a.w?(a.cWidth=s.calcListLength(b||"100vw"),a.res=a.w/a.cWidth):a.res=a.d,a},ba=function(a){if(t){var c,d,e,f=a||{};if(f.elements&&1===f.elements.nodeType&&("IMG"===f.elements.nodeName.toUpperCase()?f.elements=[f.elements]:(f.context=f.elements,f.elements=null)),c=f.elements||s.qsa(f.context||b,f.reevaluate||f.reselect?s.sel:s.selShort),e=c.length){for(s.setupRun(f),S=!0,d=0;dimg,img[srcset]",s.sel=s.selShort,s.cfg=B,s.DPR=P||1,s.u=Q,s.types=A,s.setSize=u,s.makeUrl=$(function(a){return R.href=a,R.href}),s.qsa=function(a,b){return"querySelector"in a?a.querySelectorAll(b):[]},s.matchesMedia=function(){return a.matchMedia&&(matchMedia("(min-width: 0.1em)")||{}).matches?s.matchesMedia=function(a){return!a||matchMedia(a).matches}:s.matchesMedia=s.mMQ,s.matchesMedia.apply(this,arguments)},s.mMQ=function(a){return!a||_(a)},s.calcLength=function(a){var b=_(a,!0)||!1;return b<0&&(b=!1),b},s.supportsType=function(a){return!a||A[a]},s.parseSize=$(function(a){var b=(a||"").match(I);return{media:b&&b[1],length:b&&b[2]}}),s.parseSet=function(a){return a.cands||(a.cands=m(a.srcset,a)),a.cands},s.getEmValue=function(){var a;if(!p&&(a=b.body)){var c=b.createElement("div"),d=z.style.cssText,e=a.style.cssText;c.style.cssText=K,z.style.cssText=L,a.style.cssText=L,a.appendChild(c),p=c.offsetWidth,a.removeChild(c),p=parseFloat(p,10),z.style.cssText=d,a.style.cssText=e}return p||16},s.calcListLength=function(a){if(!(a in O)||B.uT){var b=s.calcLength(n(a));O[a]=b?b:Q.width}return O[a]},s.setRes=function(a){var b;if(a){b=s.parseSet(a);for(var c=0,d=b.length;cp,n||(l.cached=!0,l.res>=p&&(h=l))),!h)for(a.sort(i),f=a.length,h=a[f-1],d=0;d=p){e=d-1,h=a[e]&&(n||k!==s.makeUrl(c.url))&&g(a[e].res,c.res,p,a[e].cached)?a[e]:c;break}h&&(m=s.makeUrl(h.url),o.curSrc=m,o.curCan=h,m!==k&&s.setSrc(b,h),s.setSize(b))}},s.setSrc=function(a,b){var c;a.src=b.url,"image/svg+xml"===b.set.type&&(c=a.style.width,a.style.width=a.offsetWidth+1+"px",a.offsetWidth+1&&(a.style.width=c))},s.getSet=function(a){var b,c,d,e=!1,f=a[s.ns].sets;for(b=0;b0&&b-1 in a)}function d(a,b,c){if(fa.isFunction(b))return fa.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return fa.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(pa.test(b))return fa.filter(b,a,c);b=fa.filter(b,a)}return fa.grep(a,function(a){return _.call(b,a)>-1!==c})}function e(a,b){for(;(a=a[b])&&1!==a.nodeType;);return a}function f(a){var b={};return fa.each(a.match(va)||[],function(a,c){b[c]=!0}),b}function g(){X.removeEventListener("DOMContentLoaded",g),a.removeEventListener("load",g),fa.ready()}function h(){this.expando=fa.expando+h.uid++}function i(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Ca,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c||"false"!==c&&("null"===c?null:+c+""===c?+c:Ba.test(c)?fa.parseJSON(c):c)}catch(a){}Aa.set(a,b,c)}else c=void 0;return c}function j(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return fa.css(a,b,"")},i=h(),j=c&&c[3]||(fa.cssNumber[b]?"":"px"),k=(fa.cssNumber[b]||"px"!==j&&+i)&&Ea.exec(fa.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,fa.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}function k(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&fa.nodeName(a,b)?fa.merge([a],c):c}function l(a,b){for(var c=0,d=a.length;d>c;c++)za.set(a[c],"globalEval",!b||za.get(b[c],"globalEval"))}function m(a,b,c,d,e){for(var f,g,h,i,j,m,n=b.createDocumentFragment(),o=[],p=0,q=a.length;q>p;p++)if(f=a[p],f||0===f)if("object"===fa.type(f))fa.merge(o,f.nodeType?[f]:f);else if(La.test(f)){for(g=g||n.appendChild(b.createElement("div")),h=(Ia.exec(f)||["",""])[1].toLowerCase(),i=Ka[h]||Ka._default,g.innerHTML=i[1]+fa.htmlPrefilter(f)+i[2],m=i[0];m--;)g=g.lastChild;fa.merge(o,g.childNodes),g=n.firstChild,g.textContent=""}else o.push(b.createTextNode(f));for(n.textContent="",p=0;f=o[p++];)if(d&&fa.inArray(f,d)>-1)e&&e.push(f);else if(j=fa.contains(f.ownerDocument,f),g=k(n.appendChild(f),"script"),j&&l(g),c)for(m=0;f=g[m++];)Ja.test(f.type||"")&&c.push(f);return n}function n(){return!0}function o(){return!1}function p(){try{return X.activeElement}catch(a){}}function q(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)q(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=o;else if(!e)return this;return 1===f&&(g=e,e=function(a){return fa().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=fa.guid++)),a.each(function(){fa.event.add(this,b,e,d,c)})}function r(a,b){return fa.nodeName(a,"table")&&fa.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function s(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function t(a){var b=Sa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function u(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(za.hasData(a)&&(f=za.access(a),g=za.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)fa.event.add(b,e,j[e][c])}Aa.hasData(a)&&(h=Aa.access(a),i=fa.extend({},h),Aa.set(b,i))}}function v(a,b){var c=b.nodeName.toLowerCase();"input"===c&&Ha.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}function w(a,b,c,d){b=Z.apply([],b);var e,f,g,h,i,j,l=0,n=a.length,o=n-1,p=b[0],q=fa.isFunction(p);if(q||n>1&&"string"==typeof p&&!da.checkClone&&Ra.test(p))return a.each(function(e){var f=a.eq(e);q&&(b[0]=p.call(this,e,f.html())),w(f,b,c,d)});if(n&&(e=m(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(g=fa.map(k(e,"script"),s),h=g.length;n>l;l++)i=e,l!==o&&(i=fa.clone(i,!0,!0),h&&fa.merge(g,k(i,"script"))),c.call(a[l],i,l);if(h)for(j=g[g.length-1].ownerDocument,fa.map(g,t),l=0;h>l;l++)i=g[l],Ja.test(i.type||"")&&!za.access(i,"globalEval")&&fa.contains(j,i)&&(i.src?fa._evalUrl&&fa._evalUrl(i.src):fa.globalEval(i.textContent.replace(Ta,"")))}return a}function x(a,b,c){for(var d,e=b?fa.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||fa.cleanData(k(d)),d.parentNode&&(c&&fa.contains(d.ownerDocument,d)&&l(k(d,"script")),d.parentNode.removeChild(d));return a}function y(a,b){var c=fa(b.createElement(a)).appendTo(b.body),d=fa.css(c[0],"display");return c.detach(),d}function z(a){var b=X,c=Va[a];return c||(c=y(a,b),"none"!==c&&c||(Ua=(Ua||fa("

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