Merge branch 'master' into enable-c++20

This commit is contained in:
Kitzunu
2022-02-02 22:39:39 +01:00
committed by GitHub
45 changed files with 4870 additions and 1526 deletions
+3 -3
View File
@@ -15,14 +15,14 @@ function import() {
updPath="$UPDATES_PATH/$folder"
archivedPath="$AC_PATH_ROOT/data/sql/archive/$folder/5.x"
latestUpd=`ls -1 $updPath/ | tail -n 1`
latestUpd=$(ls -1 $updPath/ | tail -n 1)
if [ -z $latestUpd ]; then
latestUpd=`ls -1 $archivedPath/ | tail -n 1`
latestUpd=$(ls -1 $archivedPath/ | tail -n 1)
echo "> Last update file for db $db is missing! Using archived file" $latestUpd
fi
dateToday=`date +%Y_%m_%d`
dateToday=$(date +%Y_%m_%d)
counter=0
dateLast=$latestUpd
+924
View File
@@ -0,0 +1,924 @@
-- DB update 2022_01_30_01 -> 2022_01_30_02
DROP PROCEDURE IF EXISTS `updateDb`;
DELIMITER //
CREATE PROCEDURE updateDb ()
proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE';
SELECT COUNT(*) INTO @COLEXISTS
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2022_01_30_01';
IF @COLEXISTS = 0 THEN LEAVE proc; END IF;
START TRANSACTION;
ALTER TABLE version_db_world CHANGE COLUMN 2022_01_30_01 2022_01_30_02 bit;
SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1643556744064585623'; IF OK <> 'FALSE' THEN LEAVE proc; END IF;
--
-- START UPDATING QUERIES
--
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1643556744064585623');
-- Zeth'Gor Spawning and movement Fixup
DELETE FROM `creature` WHERE `guid` IN (45782,45783,45784,45785,45786,45787,45788);
DELETE FROM `creature_addon` WHERE `guid` IN (45782,45783,45784,45785,45786,45787,45788);
INSERT INTO `creature` (`guid`,`id1`,`id2`,`id3`,`map`,`zoneId`,`areaId`,`spawnMask`,`phaseMask`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`wander_distance`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`,`ScriptName`,`VerifiedBuild`) VALUES
(45782, 16871, 0, 0, 530, 0, 0, 1, 1, 0, -807.8129, 2027.0621, 38.892704, 6.161012172698974609, 300, 0, 0, 1, 0, 0, 0, 0, 0, '', 0),
(45783, 16871, 0, 0, 530, 0, 0, 1, 1, 0, -822.5257, 2044.3488, 37.695446, 1.2042771577835083, 300, 0, 0, 1, 0, 0, 0, 0, 0, '', 0),
(45784, 16871, 0, 0, 530, 0, 0, 1, 1, 0, -865.7735, 1896.9525, 65.74987, 0.03490658476948738, 300, 0, 0, 1, 0, 0, 0, 0, 0, '', 0),
(45785, 16871, 0, 0, 530, 0, 0, 1, 1, 0, -898.994, 1910.3027, 67.31581, 5.235987663269042968, 300, 0, 0, 1, 0, 0, 0, 0, 0, '', 0),
(45786, 16871, 0, 0, 530, 0, 0, 1, 1, 0, -927.2268, 2035.844, 60.010384, 0.715584993362426757, 300, 0, 0, 1, 0, 0, 0, 0, 0, '', 0),
(45787, 16871, 0, 0, 530, 0, 0, 1, 1, 0, -834.9824, 1846.7698, 72.75926, 0.03490658476948738, 300, 0, 0, 1, 0, 2, 0, 0, 0, '', 0),
(45788, 19424, 0, 0, 530, 0, 0, 1, 1, 0, -897.68835, 2189.9019, 10.518843, 0.715584993362426757, 300, 0, 0, 1, 0, 2, 0, 0, 0, '', 0);
UPDATE `creature` SET `wander_distance`=8,`MovementType`=1,`position_x`=-1181.6936,`position_y`=1985.3013,`position_z`=74.38876 WHERE `guid`=69464;
UPDATE `creature` SET `wander_distance`=8,`MovementType`=1,`position_x`=-1189.3722,`position_y`=2006.4264,`position_z`=73.808334 WHERE `guid`=69465;
UPDATE `creature` SET `wander_distance`=6,`MovementType`=1,`position_x`=-1104.3905,`position_y`=1954.3973,`position_z`=76.613914 WHERE `guid`=69466;
UPDATE `creature` SET `wander_distance`=8,`MovementType`=1,`position_x`=-1079.3612,`position_y`=1986.3934,`position_z`=69.460915 WHERE `guid`=69467;
UPDATE `creature` SET `wander_distance`=7,`MovementType`=1,`position_x`=-1188.5541,`position_y`=2077.5652,`position_z`=75.27074 WHERE `guid`=69469;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=0,`position_x`=-890.7098,`position_y`=2034.1686,`position_z`=46.072994,`orientation`=1.2042771577835083 WHERE `guid`=58243;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=0,`position_x`=-908.11035,`position_y`=2013.416,`position_z`=61.22073,`orientation`=0.994837641716003417 WHERE `guid`=58244;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=0,`position_x`=-967.3483,`position_y`=1878.4844,`position_z`=94.32011,`orientation`=0.383972436189651489 WHERE `guid`=58246;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=0,`position_x`=-975.8573,`position_y`=1869.6091,`position_z`=95.02343,`orientation`=0.261799395084381103 WHERE `guid`=58639;
DELETE FROM `creature_addon` WHERE `guid` IN (58627,58639,58640,58645,58650,58246,58243,58244);
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES
(58627,0,0,0,1,234,0, ''),(58639,0,0,0,1,234,0, ''),(58640,0,0,0,1,234,0, ''),(58645,0,0,0,1,234,0, ''),(58650,0,0,0,1,234,0, '');
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69471;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1157.1704,`position_y`=1943.3959,`position_z`=81.403046 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1157.1704,1943.3959,81.403046,0,0,0,0,100,0),
(@PATH,2,-1151.6719,1940.954,81.40482,0,0,0,0,100,0),
(@PATH,3,-1142.8424,1932.4397,81.404175,0,0,0,0,100,0),
(@PATH,4,-1139.161,1923.0259,81.20053,0,0,0,0,100,0),
(@PATH,5,-1138.5701,1918.2799,81.375465,0,0,0,0,100,0),
(@PATH,6,-1135.4027,1912.3275,81.39697,0,0,0,0,100,0),
(@PATH,7,-1138.5154,1901.6501,81.35381,0,0,0,0,100,0),
(@PATH,8,-1145.6313,1891.6217,81.36971,0,0,0,0,100,0),
(@PATH,9,-1139.8673,1899.9113,81.357574,0,0,0,0,100,0),
(@PATH,10,-1155.2814,1909.1354,81.45224,0,0,0,0,100,0),
(@PATH,11,-1139.8673,1899.9113,81.357574,0,0,0,0,100,0),
(@PATH,12,-1145.6313,1891.6217,81.36971,0,0,0,0,100,0),
(@PATH,13,-1138.5154,1901.6501,81.35381,0,0,0,0,100,0),
(@PATH,14,-1135.4027,1912.3275,81.39697,0,0,0,0,100,0),
(@PATH,15,-1138.5701,1918.2799,81.375465,0,0,0,0,100,0),
(@PATH,16,-1139.161,1923.0259,81.20053,0,0,0,0,100,0),
(@PATH,17,-1142.8424,1932.4397,81.404175,0,0,0,0,100,0),
(@PATH,18,-1151.6719,1940.954,81.40482,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69474;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1144.8174,`position_y`=2032.2614,`position_z`=67.06461 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,9562,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1144.8174,2032.2614,67.06461,0,0,0,0,100,0),
(@PATH,2,-1116.361,2037.7001,67.31456,0,0,0,0,100,0),
(@PATH,3,-1091.6481,2053.8057,66.977875,0,0,0,0,100,0),
(@PATH,4,-1066.8229,2092.3264,61.734165,0,0,0,0,100,0),
(@PATH,5,-1057.882,2119.232,53.147633,0,0,0,0,100,0),
(@PATH,6,-1057.2283,2147.0603,39.76081,0,0,0,0,100,0),
(@PATH,7,-1050.9537,2177.783,24.66163,0,0,0,0,100,0),
(@PATH,8,-1067.8984,2200.7527,23.48374,0,0,0,0,100,0),
(@PATH,9,-1104.823,2223.4246,30.217102,0,0,0,0,100,0),
(@PATH,10,-1143.3398,2237.3584,37.079468,0,0,0,0,100,0),
(@PATH,11,-1173.3419,2256.9282,42.52737,0,0,0,0,100,0),
(@PATH,12,-1167.3082,2283.0247,39.495857,0,0,0,0,100,0),
(@PATH,13,-1153.5748,2314.1628,34.823036,0,0,0,0,100,0),
(@PATH,14,-1154.6868,2333.6782,34.29837,0,0,0,0,100,0),
(@PATH,15,-1155.3208,2370.2817,33.166924,0,0,0,0,100,0),
(@PATH,16,-1168.0349,2405.9602,34.725605,0,0,0,0,100,0),
(@PATH,17,-1175.9275,2432.895,38.330708,0,0,0,0,100,0),
(@PATH,18,-1155.4517,2453.8184,38.19942,0,0,0,0,100,0),
(@PATH,19,-1135.9495,2447.9055,34.89974,0,0,0,0,100,0),
(@PATH,20,-1104.8999,2460.6992,28.163822,0,0,0,0,100,0),
(@PATH,21,-1084.1737,2475.2322,21.265442,0,0,0,0,100,0),
(@PATH,22,-1064.8492,2494.363,17.211071,0,0,0,0,100,0),
(@PATH,23,-1046.6875,2502.54,14.809375,0,0,0,0,100,0),
(@PATH,24,-1040.1833,2484.5042,14.376109,0,0,0,0,100,0),
(@PATH,25,-1050.2819,2456.2148,16.02626,0,0,0,0,100,0),
(@PATH,26,-1075.9325,2434.0872,19.862206,0,0,0,0,100,0),
(@PATH,27,-1078.9696,2400.6445,20.558924,0,0,0,0,100,0),
(@PATH,28,-1073.9623,2367.1272,19.022785,0,0,0,0,100,0),
(@PATH,29,-1063.6683,2350.1462,17.185312,0,0,0,0,100,0),
(@PATH,30,-1066.3506,2317.7517,17.526283,0,0,0,0,100,0),
(@PATH,31,-1073.8533,2297.761,23.025248,0,0,0,0,100,0),
(@PATH,32,-1080.1339,2267.6746,24.925638,0,0,0,0,100,0),
(@PATH,33,-1066.642,2246.7378,24.66178,0,0,0,0,100,0),
(@PATH,34,-1045.459,2226.914,18.562717,0,0,0,0,100,0),
(@PATH,35,-1033.9397,2196.5354,17.735605,0,0,0,0,100,0),
(@PATH,36,-1039.7316,2166.545,26.34919,0,0,0,0,100,0),
(@PATH,37,-1053.653,2131.6536,47.057056,0,0,0,0,100,0),
(@PATH,38,-1059.5895,2114.807,54.945484,0,0,0,0,100,0),
(@PATH,39,-1046.4648,2099.709,60.07795,0,0,0,0,100,0),
(@PATH,40,-1023.1835,2081.2344,67.66391,0,0,0,0,100,0),
(@PATH,41,-998.32965,2056.466,67.189545,0,0,0,0,100,0),
(@PATH,42,-981.2092,2057.198,67.064545,0,0,0,0,100,0),
(@PATH,43,-998.32965,2056.466,67.189545,0,0,0,0,100,0),
(@PATH,44,-1023.1835,2081.2344,67.66391,0,0,0,0,100,0),
(@PATH,45,-1046.3953,2099.6096,60.166817,0,0,0,0,100,0),
(@PATH,46,-1059.5195,2114.707,54.87517,0,0,0,0,100,0),
(@PATH,47,-1053.653,2131.6536,47.057056,0,0,0,0,100,0),
(@PATH,48,-1039.7316,2166.545,26.34919,0,0,0,0,100,0),
(@PATH,49,-1033.9397,2196.5354,17.735605,0,0,0,0,100,0),
(@PATH,50,-1045.459,2226.914,18.562717,0,0,0,0,100,0),
(@PATH,51,-1066.642,2246.7378,24.66178,0,0,0,0,100,0),
(@PATH,52,-1080.1339,2267.6746,24.925638,0,0,0,0,100,0),
(@PATH,53,-1073.8533,2297.761,23.025248,0,0,0,0,100,0),
(@PATH,54,-1066.3506,2317.7517,17.526283,0,0,0,0,100,0),
(@PATH,55,-1063.6683,2350.1462,17.185312,0,0,0,0,100,0),
(@PATH,56,-1073.9623,2367.1272,19.022785,0,0,0,0,100,0),
(@PATH,57,-1078.9696,2400.6445,20.558924,0,0,0,0,100,0),
(@PATH,58,-1075.9325,2434.0872,19.862206,0,0,0,0,100,0),
(@PATH,59,-1050.2819,2456.2148,16.02626,0,0,0,0,100,0),
(@PATH,60,-1040.1833,2484.5042,14.376109,0,0,0,0,100,0),
(@PATH,61,-1046.6875,2502.54,14.809375,0,0,0,0,100,0),
(@PATH,62,-1064.8492,2494.363,17.211071,0,0,0,0,100,0),
(@PATH,63,-1084.1737,2475.2322,21.265442,0,0,0,0,100,0),
(@PATH,64,-1104.8999,2460.6992,28.163822,0,0,0,0,100,0),
(@PATH,65,-1135.9495,2447.9055,34.89974,0,0,0,0,100,0),
(@PATH,66,-1155.4517,2453.8184,38.19942,0,0,0,0,100,0),
(@PATH,67,-1175.9275,2432.895,38.330708,0,0,0,0,100,0),
(@PATH,68,-1168.0349,2405.9602,34.725605,0,0,0,0,100,0),
(@PATH,69,-1155.3208,2370.2817,33.166924,0,0,0,0,100,0),
(@PATH,70,-1154.6868,2333.6782,34.29837,0,0,0,0,100,0),
(@PATH,71,-1153.5748,2314.1628,34.823036,0,0,0,0,100,0),
(@PATH,72,-1167.3082,2283.0247,39.495857,0,0,0,0,100,0),
(@PATH,73,-1173.3419,2256.9282,42.52737,0,0,0,0,100,0),
(@PATH,74,-1143.3398,2237.3584,37.079468,0,0,0,0,100,0),
(@PATH,75,-1104.823,2223.4246,30.217102,0,0,0,0,100,0),
(@PATH,76,-1067.8984,2200.7527,23.48374,0,0,0,0,100,0),
(@PATH,77,-1050.9537,2177.783,24.66163,0,0,0,0,100,0),
(@PATH,78,-1057.2283,2147.0603,39.76081,0,0,0,0,100,0),
(@PATH,79,-1057.882,2119.232,53.147633,0,0,0,0,100,0),
(@PATH,80,-1066.8229,2092.3264,61.734165,0,0,0,0,100,0),
(@PATH,81,-1091.6481,2053.8057,66.977875,0,0,0,0,100,0),
(@PATH,82,-1116.361,2037.7001,67.31456,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69476;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-918.9573,`position_y`=1886.1849,`position_z`=78.159615 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-918.9573,1886.1849,78.159615,0,0,0,0,100,0),
(@PATH,2,-951.46313,1888.7223,82.49074,0,0,0,0,100,0),
(@PATH,3,-974.32935,1917.3013,76.94507,0,0,0,0,100,0),
(@PATH,4,-984.9029,1950.981,70.32558,0,0,0,0,100,0),
(@PATH,5,-983.9862,1982.5497,68.81455,0,0,0,0,100,0),
(@PATH,6,-1011.4597,2004.1027,67.06455,0,0,0,0,100,0),
(@PATH,7,-1053.092,2025.2274,67.56455,0,0,0,0,100,0),
(@PATH,8,-1098.1647,2044.0681,66.977875,0,0,0,0,100,0),
(@PATH,9,-1141.4509,2039.2743,67.064575,0,0,0,0,100,0),
(@PATH,10,-1098.1647,2044.0681,66.977875,0,0,0,0,100,0),
(@PATH,11,-1053.092,2025.2274,67.56455,0,0,0,0,100,0),
(@PATH,12,-1011.4597,2004.1027,67.06455,0,0,0,0,100,0),
(@PATH,13,-983.9862,1982.5497,68.81455,0,0,0,0,100,0),
(@PATH,14,-984.9029,1950.981,70.32558,0,0,0,0,100,0),
(@PATH,15,-974.32935,1917.3013,76.94507,0,0,0,0,100,0),
(@PATH,16,-951.46313,1888.7223,82.49074,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69477;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-975.8649,`position_y`=1879.6927,`position_z`=94.820885 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,9562,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-975.8649,1879.6927,94.820885,0,0,0,0,100,0),
(@PATH,2,-975.67773,1903.6924,84.414185,0,0,0,0,100,0),
(@PATH,3,-973.8419,1939.4952,70.39467,0,0,0,0,100,0),
(@PATH,4,-955.70294,1969.0148,68.00587,0,0,0,0,100,0),
(@PATH,5,-933.93445,1986.5293,66.71876,0,0,0,0,100,0),
(@PATH,6,-920.0254,2004.1454,64.96164,0,0,0,0,100,0),
(@PATH,7,-912.63696,2028.0221,56.542572,0,0,0,0,100,0),
(@PATH,8,-891.1589,2064.7395,34.642937,0,0,0,0,100,0),
(@PATH,9,-869.7386,2091.601,23.570396,0,0,0,0,100,0),
(@PATH,10,-858.73914,2124.8645,17.03608,0,0,0,0,100,0),
(@PATH,11,-823.71747,2119.5713,16.566298,0,0,0,0,100,0),
(@PATH,12,-792.22266,2090.2607,22.424997,0,0,0,0,100,0),
(@PATH,13,-783.20844,2054.525,29.639727,0,0,0,0,100,0),
(@PATH,14,-779.9326,2023.7704,34.753212,0,0,0,0,100,0),
(@PATH,15,-800.3509,1985.5853,39.80645,0,0,0,0,100,0),
(@PATH,16,-814.7488,1949.572,47.55807,0,0,0,0,100,0),
(@PATH,17,-822.0464,1919.7396,54.06172,0,0,0,0,100,0),
(@PATH,18,-847.4603,1891.778,64.08673,0,0,0,0,100,0),
(@PATH,19,-885.2077,1883.8082,72.72009,0,0,0,0,100,0),
(@PATH,20,-915.13196,1902.3485,70.37255,0,0,0,0,100,0),
(@PATH,21,-940.0393,1898.6892,74.6819,0,0,0,0,100,0),
(@PATH,22,-958.8931,1878.3401,92.07265,0,0,0,0,100,0),
(@PATH,23,-967.469,1873.9791,94.75582,0,0,0,0,100,0),
(@PATH,24,-976.3881,1877.9034,94.820885,0,0,0,0,100,0),
(@PATH,25,-967.469,1873.9791,94.75582,0,0,0,0,100,0),
(@PATH,26,-958.8931,1878.3401,92.07265,0,0,0,0,100,0),
(@PATH,27,-940.0393,1898.6892,74.6819,0,0,0,0,100,0),
(@PATH,28,-915.13196,1902.3485,70.37255,0,0,0,0,100,0),
(@PATH,29,-885.2077,1883.8082,72.72009,0,0,0,0,100,0),
(@PATH,30,-847.4603,1891.778,64.08673,0,0,0,0,100,0),
(@PATH,31,-822.0464,1919.7396,54.06172,0,0,0,0,100,0),
(@PATH,32,-814.7488,1949.572,47.55807,0,0,0,0,100,0),
(@PATH,33,-800.3509,1985.5853,39.80645,0,0,0,0,100,0),
(@PATH,34,-779.9326,2023.7704,34.753212,0,0,0,0,100,0),
(@PATH,35,-783.20844,2054.525,29.639727,0,0,0,0,100,0),
(@PATH,36,-792.23676,2090.261,22.406199,0,0,0,0,100,0),
(@PATH,37,-823.71747,2119.5713,16.566298,0,0,0,0,100,0),
(@PATH,38,-858.73914,2124.8645,17.03608,0,0,0,0,100,0),
(@PATH,39,-869.74414,2091.6416,23.679771,0,0,0,0,100,0),
(@PATH,40,-891.1589,2064.7395,34.642937,0,0,0,0,100,0),
(@PATH,41,-912.63696,2028.0221,56.542572,0,0,0,0,100,0),
(@PATH,42,-920.0254,2004.1454,64.96164,0,0,0,0,100,0),
(@PATH,43,-933.93445,1986.5293,66.71876,0,0,0,0,100,0),
(@PATH,44,-955.70294,1969.0148,68.00587,0,0,0,0,100,0),
(@PATH,45,-973.8419,1939.4952,70.39467,0,0,0,0,100,0),
(@PATH,46,-975.67535,1903.7174,84.44507,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69478;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-824.48157,`position_y`=1990.7778,`position_z`=38.913017 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,9562,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-824.48157,1990.7778,38.913017,0,0,0,0,100,0),
(@PATH,2,-800.97296,2019.102,38.81275,0,0,0,0,100,0),
(@PATH,3,-801.469,2043.1168,41.418495,0,0,0,0,100,0),
(@PATH,4,-820.14905,2057.4697,35.70707,0,0,0,0,100,0),
(@PATH,5,-830.23114,2072.1282,25.74135,0,0,0,0,100,0),
(@PATH,6,-842.6779,2101.8196,19.235298,0,0,0,0,100,0),
(@PATH,7,-854.4006,2133.8242,15.765491,0,0,0,0,100,0),
(@PATH,8,-854.38306,2150.4915,13.765491,0,0,0,0,100,0),
(@PATH,9,-871.99493,2163.9001,11.569413,0,0,0,0,100,0),
(@PATH,10,-900.2237,2167.0774,11.697643,0,0,0,0,100,0),
(@PATH,11,-871.99493,2163.9001,11.569413,0,0,0,0,100,0),
(@PATH,12,-854.38306,2150.4915,13.765491,0,0,0,0,100,0),
(@PATH,13,-854.4006,2133.8242,15.765491,0,0,0,0,100,0),
(@PATH,14,-842.7129,2101.8828,19.332344,0,0,0,0,100,0),
(@PATH,15,-830.23114,2072.1282,25.74135,0,0,0,0,100,0),
(@PATH,16,-820.14905,2057.4697,35.70707,0,0,0,0,100,0),
(@PATH,17,-801.469,2043.1168,41.418495,0,0,0,0,100,0),
(@PATH,18,-800.97296,2019.102,38.81275,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69479;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-839.2043,`position_y`=2035.8622,`position_z`=40.1465 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,9562,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-839.2043,2035.8622,40.1465,0,0,0,0,100,0),
(@PATH,2,-834.4606,2064.8481,28.52858,0,0,0,0,100,0),
(@PATH,3,-867.7588,2092.5183,23.16903,0,0,0,0,100,0),
(@PATH,4,-899.0653,2097.202,24.101158,0,0,0,0,100,0),
(@PATH,5,-917.93164,2134.7314,17.444939,0,0,0,0,100,0),
(@PATH,6,-929.82214,2168.7473,12.796154,0,0,0,0,100,0),
(@PATH,7,-960.3612,2199.0093,11.107691,0,0,0,0,100,0),
(@PATH,8,-1000.6773,2218.161,11.399557,0,0,0,0,100,0),
(@PATH,9,-1034.1177,2233.8848,16.91886,0,0,0,0,100,0),
(@PATH,10,-1000.6773,2218.161,11.399557,0,0,0,0,100,0),
(@PATH,11,-960.3612,2199.0093,11.107691,0,0,0,0,100,0),
(@PATH,12,-929.82214,2168.7473,12.796154,0,0,0,0,100,0),
(@PATH,13,-917.97095,2134.846,17.456902,0,0,0,0,100,0),
(@PATH,14,-899.0653,2097.202,24.101158,0,0,0,0,100,0),
(@PATH,15,-867.7588,2092.5183,23.16903,0,0,0,0,100,0),
(@PATH,16,-834.4606,2064.8481,28.52858,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69480;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-912.63074,`position_y`=2132.925,`position_z`=17.529076 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,9562,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-912.63074,2132.925,17.529076,0,0,0,0,100,0),
(@PATH,2,-915.43134,2157.9617,13.551995,0,0,0,0,100,0),
(@PATH,3,-950.73566,2192.6895,11.500147,0,0,0,0,100,0),
(@PATH,4,-975.54425,2209.2466,10.593191,0,0,0,0,100,0),
(@PATH,5,-1016.8659,2228.8008,13.342184,0,0,0,0,100,0),
(@PATH,6,-1050.3086,2248.4658,22.708654,0,0,0,0,100,0),
(@PATH,7,-1072.5449,2254.373,24.994837,0,0,0,0,100,0),
(@PATH,8,-1050.3086,2248.4658,22.708654,0,0,0,0,100,0),
(@PATH,9,-1016.8659,2228.8008,13.342184,0,0,0,0,100,0),
(@PATH,10,-975.54425,2209.2466,10.593191,0,0,0,0,100,0),
(@PATH,11,-950.73566,2192.6895,11.500147,0,0,0,0,100,0),
(@PATH,12,-915.43134,2157.9617,13.551995,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 69481;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1066.7217,`position_y`=2249.2952,`position_z`=24.791834 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,9562,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1066.7217,2249.2952,24.791834,0,0,0,0,100,0),
(@PATH,2,-1099.4371,2271.7798,25.420755,0,0,0,0,100,0),
(@PATH,3,-1132.4531,2268.6387,32.148235,0,0,0,0,100,0),
(@PATH,4,-1167.4694,2260.2366,40.901394,0,0,0,0,100,0),
(@PATH,5,-1177.4648,2233.2986,45.33928,0,0,0,0,100,0),
(@PATH,6,-1177.5826,2199.8652,51.312763,0,0,0,0,100,0),
(@PATH,7,-1172.9514,2155.1165,63.388287,0,0,0,0,100,0),
(@PATH,8,-1177.5826,2199.8652,51.312763,0,0,0,0,100,0),
(@PATH,9,-1177.4648,2233.2986,45.33928,0,0,0,0,100,0),
(@PATH,10,-1167.4694,2260.2366,40.901394,0,0,0,0,100,0),
(@PATH,11,-1132.4531,2268.6387,32.148235,0,0,0,0,100,0),
(@PATH,12,-1099.582,2271.7646,25.425638,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Tormentor Entry: 19424
SET @NPC := 45788;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-897.68835,`position_y`=2189.9019,`position_z`=10.518843 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,9562,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-897.68835,2189.9019,10.518843,0,0,0,0,100,0),
(@PATH,2,-862.864,2165.974,11.532458,0,0,0,0,100,0),
(@PATH,3,-840.77765,2152.8508,13.3574095,0,0,0,0,100,0),
(@PATH,4,-837.7058,2133.5583,15.672473,0,0,0,0,100,0),
(@PATH,5,-852.2029,2118.3584,17.441841,0,0,0,0,100,0),
(@PATH,6,-871.53156,2098.8684,21.649864,0,0,0,0,100,0),
(@PATH,7,-887.3162,2100.3923,22.981367,0,0,0,0,100,0),
(@PATH,8,-902.8832,2104.852,22.5635,0,0,0,0,100,0),
(@PATH,9,-915.3331,2120.114,20.053001,0,0,0,0,100,0),
(@PATH,10,-914.8217,2141.3044,15.656854,0,0,0,0,100,0),
(@PATH,11,-920.68976,2180.2544,11.733288,0,0,0,0,100,0),
(@PATH,12,-928.6917,2208.0442,9.395775,0,0,0,0,100,0),
(@PATH,13,-935.8201,2223.3782,8.009735,0,0,0,0,100,0),
(@PATH,14,-957.25446,2229.223,7.9334416,0,0,0,0,100,0),
(@PATH,15,-962.3887,2210.6462,10.176727,0,0,0,0,100,0),
(@PATH,16,-949.9908,2203.8,9.920502,0,0,0,0,100,0),
(@PATH,17,-929.2674,2205.433,9.8395,0,0,0,0,100,0);
-- Pathing for Eye of Grillok Entry: 19440
SET @NPC := 69630;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1192.7301,`position_y`=1901.408,`position_z`=81.40844 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1192.7301,1901.408,81.40844,0,0,0,0,100,0),
(@PATH,2,-1197.3092,1911.6306,81.36666,0,0,0,0,100,0),
(@PATH,3,-1198.9302,1925.219,81.35436,0,0,0,0,100,0),
(@PATH,4,-1194.5005,1933.2014,81.36169,0,0,0,0,100,0),
(@PATH,5,-1188.6738,1930.3163,81.37732,0,0,0,0,100,0),
(@PATH,6,-1177.2075,1923.7491,80.29272,0,0,0,0,100,0),
(@PATH,7,-1168.7435,1929.0977,81.547424,0,0,0,0,100,0),
(@PATH,8,-1156.435,1918.1936,81.54837,0,0,0,0,100,0),
(@PATH,9,-1158.967,1910.9397,81.54838,0,0,0,0,100,0),
(@PATH,10,-1139.8248,1900.3737,81.35509,0,0,0,0,100,0),
(@PATH,11,-1135.0538,1914.743,81.38086,0,0,0,0,100,0),
(@PATH,12,-1140.5521,1924.9927,81.384735,0,0,0,0,100,0),
(@PATH,13,-1143.8522,1934.3616,81.413734,0,0,0,0,100,0),
(@PATH,14,-1153.7489,1941.5273,81.40304,0,0,0,0,100,0),
(@PATH,15,-1139.4741,1963.0577,77.43079,0,0,0,0,100,0),
(@PATH,16,-1133.53,1974.1111,73.668015,0,0,0,0,100,0),
(@PATH,17,-1130.4148,1977.3342,73.542435,0,0,0,0,100,0),
(@PATH,18,-1113.2056,1975.7834,72.860794,0,0,0,0,100,0),
(@PATH,19,-1097.9889,1958.7505,74.65789,0,0,0,0,100,0),
(@PATH,20,-1101.236,1949.125,76.376854,0,0,0,0,100,0),
(@PATH,21,-1118.553,1952.2955,74.294334,0,0,0,0,100,0),
(@PATH,22,-1123.422,1973.4846,73.44966,0,0,0,0,100,0),
(@PATH,23,-1137.158,1989.2379,72.25078,0,0,0,0,100,0),
(@PATH,24,-1162.1504,2001.9258,72.56461,0,0,0,0,100,0),
(@PATH,25,-1189.884,2008.2639,73.808334,0,0,0,0,100,0),
(@PATH,26,-1193.3334,2001.9054,73.7545,0,0,0,0,100,0),
(@PATH,27,-1176.8627,1983.8529,74.179665,0,0,0,0,100,0),
(@PATH,28,-1153.4813,1986.2709,73.918015,0,0,0,0,100,0),
(@PATH,29,-1139.647,1984.8119,73.48808,0,0,0,0,100,0),
(@PATH,30,-1133.5446,1974.2188,73.668015,0,0,0,0,100,0),
(@PATH,31,-1139.647,1984.8119,73.48808,0,0,0,0,100,0),
(@PATH,32,-1153.4813,1986.2709,73.918015,0,0,0,0,100,0),
(@PATH,33,-1176.8627,1983.8529,74.179665,0,0,0,0,100,0),
(@PATH,34,-1193.3334,2001.9054,73.7545,0,0,0,0,100,0),
(@PATH,35,-1189.884,2008.2639,73.808334,0,0,0,0,100,0),
(@PATH,36,-1162.2444,2001.9727,72.578896,0,0,0,0,100,0),
(@PATH,37,-1137.158,1989.2379,72.25078,0,0,0,0,100,0),
(@PATH,38,-1123.422,1973.4846,73.44966,0,0,0,0,100,0),
(@PATH,39,-1118.553,1952.2955,74.294334,0,0,0,0,100,0),
(@PATH,40,-1101.236,1949.125,76.376854,0,0,0,0,100,0),
(@PATH,41,-1097.9889,1958.7505,74.65789,0,0,0,0,100,0),
(@PATH,42,-1113.2056,1975.7834,72.860794,0,0,0,0,100,0),
(@PATH,43,-1130.4148,1977.3342,73.542435,0,0,0,0,100,0),
(@PATH,44,-1133.53,1974.1111,73.668015,0,0,0,0,100,0),
(@PATH,45,-1139.4741,1963.0577,77.43079,0,0,0,0,100,0),
(@PATH,46,-1153.7489,1941.5273,81.40304,0,0,0,0,100,0),
(@PATH,47,-1143.8522,1934.3616,81.413734,0,0,0,0,100,0),
(@PATH,48,-1140.5521,1924.9927,81.384735,0,0,0,0,100,0),
(@PATH,49,-1135.0538,1914.743,81.38086,0,0,0,0,100,0),
(@PATH,50,-1139.8248,1900.3737,81.35509,0,0,0,0,100,0),
(@PATH,51,-1158.967,1910.9397,81.54838,0,0,0,0,100,0),
(@PATH,52,-1156.435,1918.1936,81.54837,0,0,0,0,100,0),
(@PATH,53,-1168.7435,1929.0977,81.547424,0,0,0,0,100,0),
(@PATH,54,-1177.1844,1923.736,80.298355,0,0,0,0,100,0),
(@PATH,55,-1188.6364,1930.2977,81.37329,0,0,0,0,100,0),
(@PATH,56,-1194.5005,1933.2014,81.36169,0,0,0,0,100,0),
(@PATH,57,-1198.9302,1925.219,81.35436,0,0,0,0,100,0),
(@PATH,58,-1197.3092,1911.6306,81.36666,0,0,0,0,100,0);
-- Pathing for Eye of Grillok Entry: 19440
SET @NPC := 69631;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-970.10016,`position_y`=2184.593,`position_z`=14.417984 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-970.10016,2184.593,14.417984,0,0,0,0,100,0),
(@PATH,2,-1000.6766,2189.1104,14.284336,0,0,0,0,100,0),
(@PATH,3,-1038.272,2175.676,22.846445,0,0,0,0,100,0),
(@PATH,4,-1055.2834,2148.6592,38.238106,0,0,0,0,100,0),
(@PATH,5,-1059.6584,2118.1074,53.765553,0,0,0,0,100,0),
(@PATH,6,-1045.6895,2098.584,60.57795,0,0,0,0,100,0),
(@PATH,7,-1014.3764,2076.2415,68.65146,0,0,0,0,100,0),
(@PATH,8,-991.5126,2053.3726,67.064545,0,0,0,0,100,0),
(@PATH,9,-966.98566,2030.3434,67.06455,0,0,0,0,100,0),
(@PATH,10,-959.8001,2017.5282,67.03322,0,0,0,0,100,0),
(@PATH,11,-921.6862,2020.9375,61.3862,0,0,0,0,100,0),
(@PATH,12,-904.4248,2040.5842,48.97299,0,0,0,0,100,0),
(@PATH,13,-891.80695,2071.3374,32.139977,0,0,0,0,100,0),
(@PATH,14,-902.8315,2093.767,24.965975,0,0,0,0,100,0),
(@PATH,15,-919.97656,2121.9658,20.227806,0,0,0,0,100,0),
(@PATH,16,-939.8874,2146.1133,17.118343,0,0,0,0,100,0),
(@PATH,17,-950.2776,2165.2285,15.736874,0,0,0,0,100,0);
-- Pathing for Eye of Grillok Entry: 19440
SET @NPC := 69632;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1102.2666,`position_y`=2066.6333,`position_z`=67.68956 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1102.2666,2066.6333,67.68956,0,0,0,0,100,0),
(@PATH,2,-1083.3512,2080.7144,65.12747,0,0,0,0,100,0),
(@PATH,3,-1052.895,2094.3591,61.021797,0,0,0,0,100,0),
(@PATH,4,-1017.9338,2079.23,68.333466,0,0,0,0,100,0),
(@PATH,5,-1003.4672,2046.2118,67.2819,0,0,0,0,100,0),
(@PATH,6,-995.76,2017.3312,67.06455,0,0,0,0,100,0),
(@PATH,7,-1002.2729,2000.3123,67.06455,0,0,0,0,100,0),
(@PATH,8,-994.0292,1982.86,67.843605,0,0,0,0,100,0),
(@PATH,9,-989.314,1952.2728,70.449844,0,0,0,0,100,0),
(@PATH,10,-960.0438,1951.9045,67.81455,0,0,0,0,100,0),
(@PATH,11,-989.314,1952.2728,70.449844,0,0,0,0,100,0),
(@PATH,12,-994.0292,1982.86,67.843605,0,0,0,0,100,0),
(@PATH,13,-1002.2729,2000.3123,67.06455,0,0,0,0,100,0),
(@PATH,14,-995.76,2017.3312,67.06455,0,0,0,0,100,0),
(@PATH,15,-1003.4672,2046.2118,67.2819,0,0,0,0,100,0),
(@PATH,16,-1017.9338,2079.23,68.333466,0,0,0,0,100,0),
(@PATH,17,-1052.895,2094.3591,61.021797,0,0,0,0,100,0),
(@PATH,18,-1083.3512,2080.7144,65.12747,0,0,0,0,100,0);
-- Pathing for Eye of Grillok Entry: 19440
SET @NPC := 69633;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-920.0879,`position_y`=1955.2574,`position_z`=67.56455 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-920.0879,1955.2574,67.56455,0,0,0,0,100,0),
(@PATH,2,-928.7871,1988.1289,66.67532,0,0,0,0,100,0),
(@PATH,3,-948.8636,1987.6844,68.46583,0,0,0,0,100,0),
(@PATH,4,-957.97156,1998.7296,68.808846,0,0,0,0,100,0),
(@PATH,5,-958.2822,2014.4004,67.03322,0,0,0,0,100,0),
(@PATH,6,-971.1483,2038.9076,67.03989,0,0,0,0,100,0),
(@PATH,7,-989.33093,2057.3228,67.064545,0,0,0,0,100,0),
(@PATH,8,-1024.2134,2078.929,67.38486,0,0,0,0,100,0),
(@PATH,9,-1046.7137,2102.792,59.162037,0,0,0,0,100,0),
(@PATH,10,-1083.0226,2112.7605,61.479824,0,0,0,0,100,0),
(@PATH,11,-1122.4673,2124.2188,67.07792,0,0,0,0,100,0),
(@PATH,12,-1083.0226,2112.7605,61.479824,0,0,0,0,100,0),
(@PATH,13,-1046.7137,2102.792,59.162037,0,0,0,0,100,0),
(@PATH,14,-1024.2134,2078.929,67.38486,0,0,0,0,100,0),
(@PATH,15,-989.33093,2057.3228,67.064545,0,0,0,0,100,0),
(@PATH,16,-971.1483,2038.9076,67.03989,0,0,0,0,100,0),
(@PATH,17,-958.2822,2014.4004,67.03322,0,0,0,0,100,0),
(@PATH,18,-957.97156,1998.7296,68.808846,0,0,0,0,100,0),
(@PATH,19,-948.8636,1987.6844,68.46583,0,0,0,0,100,0),
(@PATH,20,-928.804,1988.2194,66.7764,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Grunt Entry: 16871
SET @NPC := 58236;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-911.2977,`position_y`=2137.6472,`position_z`=16.452751 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-911.2977,2137.6472,16.452751,0,1000,0,0,100,0),
(@PATH,2,-933.04755,2164.178,14.056634,0,0,0,0,100,0),
(@PATH,3,-965.8881,2184.0625,13.970484,0,0,0,0,100,0),
(@PATH,4,-1001.5982,2191.2812,14.134434,0,0,0,0,100,0),
(@PATH,5,-1031.2466,2190.9478,18.232334,0,0,0,0,100,0),
(@PATH,6,-1066.5594,2192.525,24.265146,0,0,0,0,100,0),
(@PATH,7,-1100.3105,2206.673,31.346252,0,0,0,0,100,0),
(@PATH,8,-1133.5823,2203.8928,39.47308,0,0,0,0,100,0),
(@PATH,9,-1143.3346,2191.7742,44.641357,0,0,0,0,100,0),
(@PATH,10,-1154.0084,2165.3813,56.286015,0,0,0,0,100,0),
(@PATH,11,-1175.0612,2156.6692,63.02769,0,1000,0,0,100,0),
(@PATH,12,-1154.0084,2165.3813,56.286015,0,0,0,0,100,0),
(@PATH,13,-1143.3346,2191.7742,44.641357,0,0,0,0,100,0),
(@PATH,14,-1133.5823,2203.8928,39.47308,0,0,0,0,100,0),
(@PATH,15,-1100.3105,2206.673,31.346252,0,0,0,0,100,0),
(@PATH,16,-1066.5594,2192.525,24.265146,0,0,0,0,100,0),
(@PATH,17,-1031.2466,2190.9478,18.232334,0,0,0,0,100,0),
(@PATH,18,-1001.5982,2191.2812,14.134434,0,0,0,0,100,0),
(@PATH,19,-965.8881,2184.0625,13.970484,0,0,0,0,100,0),
(@PATH,20,-933.04755,2164.178,14.056634,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Grunt Entry: 16871
SET @NPC := 58237;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1195.9425,`position_y`=2143.4817,`position_z`=67.85826 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1195.9425,2143.4817,67.85826,0,0,0,0,100,0),
(@PATH,2,-1172.4357,2167.9402,59.144794,0,0,0,0,100,0),
(@PATH,3,-1143.1027,2196.7788,43.097656,0,0,0,0,100,0),
(@PATH,4,-1113.0748,2214.188,32.71222,0,0,0,0,100,0),
(@PATH,5,-1067.642,2205.2668,23.075537,0,0,0,0,100,0),
(@PATH,6,-1033.1847,2201.046,17.112448,0,0,0,0,100,0),
(@PATH,7,-1000.649,2192.764,13.967808,0,0,0,0,100,0),
(@PATH,8,-966.1215,2189.5737,13.125635,0,0,0,0,100,0),
(@PATH,9,-933.0646,2176.6072,11.977917,0,0,0,0,100,0),
(@PATH,10,-902.13654,2147.4033,14.568231,0,0,0,0,100,0),
(@PATH,11,-933.0646,2176.6072,11.977917,0,0,0,0,100,0),
(@PATH,12,-966.1215,2189.5737,13.125635,0,0,0,0,100,0),
(@PATH,13,-1000.649,2192.764,13.967808,0,0,0,0,100,0),
(@PATH,14,-1033.1847,2201.046,17.112448,0,0,0,0,100,0),
(@PATH,15,-1067.642,2205.2668,23.075537,0,0,0,0,100,0),
(@PATH,16,-1113.0748,2214.188,32.71222,0,0,0,0,100,0),
(@PATH,17,-1143.1027,2196.7788,43.097656,0,0,0,0,100,0),
(@PATH,18,-1172.4357,2167.9402,59.144794,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Grunt Entry: 16871
SET @NPC := 45787;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-834.9824,`position_y`=1846.7698,`position_z`=72.75926 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-834.9824,1846.7698,72.75926,0,0,0,0,100,0),
(@PATH,2,-841.6329,1883.8331,64.91925,0,0,0,0,100,0),
(@PATH,3,-836.8684,1914.0354,57.143185,0,0,0,0,100,0),
(@PATH,4,-826.2271,1932.676,51.817093,0,0,0,0,100,0),
(@PATH,5,-819.6504,1969.0977,41.618828,0,0,0,0,100,0),
(@PATH,6,-828.8496,1999.6823,39.118828,0,0,0,0,100,0),
(@PATH,7,-840.6439,2019.1708,40.532825,0,0,0,0,100,0),
(@PATH,8,-840.4643,2032.6373,40.56139,0,0,0,0,100,0),
(@PATH,9,-842.6254,2058.1357,34.30641,0,0,0,0,100,0),
(@PATH,10,-857.2351,2099.6333,20.792768,0,0,0,0,100,0),
(@PATH,11,-866.78107,2114.27,18.586348,0,0,0,0,100,0),
(@PATH,12,-857.2351,2099.6333,20.792768,0,0,0,0,100,0),
(@PATH,13,-842.6254,2058.1357,34.30641,0,0,0,0,100,0),
(@PATH,14,-840.4643,2032.6373,40.56139,0,0,0,0,100,0),
(@PATH,15,-840.6439,2019.1708,40.532825,0,0,0,0,100,0),
(@PATH,16,-828.8496,1999.6823,39.118828,0,0,0,0,100,0),
(@PATH,17,-819.6449,1969.2327,41.673027,0,0,0,0,100,0),
(@PATH,18,-826.2207,1932.8105,51.84102,0,0,0,0,100,0),
(@PATH,19,-836.8684,1914.0354,57.143185,0,0,0,0,100,0),
(@PATH,20,-841.6329,1883.8331,64.91925,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Grunt Entry: 16871
SET @NPC := 58254;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-885.7324,`position_y`=2104.3176,`position_z`=21.929853 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-885.7324,2104.3176,21.929853,0,0,0,0,100,0),
(@PATH,2,-850.65704,2081.7834,24.162397,0,0,0,0,100,0),
(@PATH,3,-815.51715,2055.5637,38.643227,0,0,0,0,100,0),
(@PATH,4,-795.41144,2031.4738,38.869423,0,0,0,0,100,0),
(@PATH,5,-788.1208,1993.4674,39.46691,0,0,0,0,100,0),
(@PATH,6,-796.1838,1965.6188,44.035126,0,0,0,0,100,0),
(@PATH,7,-815.2461,1930.4629,50.96602,0,0,0,0,100,0),
(@PATH,8,-826.89453,1893.6521,60.460438,0,0,0,0,100,0),
(@PATH,9,-841.63153,1857.9562,68.85875,0,0,0,0,100,0),
(@PATH,10,-826.89453,1893.6521,60.460438,0,0,0,0,100,0),
(@PATH,11,-815.26324,1930.4427,51.019485,0,0,0,0,100,0),
(@PATH,12,-796.1838,1965.6188,44.035126,0,0,0,0,100,0),
(@PATH,13,-788.1208,1993.4674,39.46691,0,0,0,0,100,0),
(@PATH,14,-795.41144,2031.4738,38.869423,0,0,0,0,100,0),
(@PATH,15,-815.51715,2055.5637,38.643227,0,0,0,0,100,0),
(@PATH,16,-850.65704,2081.7834,24.162397,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Dark Shaman Entry: 16873
SET @NPC := 58256;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1144.5983,`position_y`=1954.9115,`position_z`=80.52448 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1144.5983,1954.9115,80.52448,0,0,0,0,100,0),
(@PATH,2,-1133.44,1972.2246,73.668015,0,0,0,0,100,0),
(@PATH,3,-1122.8121,1998.954,68.95625,0,0,0,0,100,0),
(@PATH,4,-1099.5635,2031.8724,67.05327,0,0,0,0,100,0),
(@PATH,5,-1084.6843,2065.1223,66.827484,0,0,0,0,100,0),
(@PATH,6,-1070.7125,2090.6348,62.183628,0,0,0,0,100,0),
(@PATH,7,-1100.127,2084.8633,66.63342,0,0,0,0,100,0),
(@PATH,8,-1129.7533,2078.1355,67.00842,0,0,0,0,100,0),
(@PATH,9,-1100.243,2084.8494,66.599976,0,0,0,0,100,0),
(@PATH,10,-1070.7125,2090.6348,62.183628,0,0,0,0,100,0),
(@PATH,11,-1084.6465,2065.2031,66.727875,0,0,0,0,100,0),
(@PATH,12,-1099.5635,2031.8724,67.05327,0,0,0,0,100,0),
(@PATH,13,-1122.8121,1998.954,68.95625,0,0,0,0,100,0),
(@PATH,14,-1133.44,1972.2246,73.668015,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Dark Shaman Entry: 16873
SET @NPC := 58257;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1008.1821,`position_y`=1997.0387,`position_z`=67.06455 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1008.1821,1997.0387,67.06455,0,0,0,0,100,0),
(@PATH,2,-993.7006,2017.7288,67.06455,0,0,0,0,100,0),
(@PATH,3,-1011.8848,2038.5491,67.04899,0,0,0,0,100,0),
(@PATH,4,-1024.8915,2036.1044,67.17399,0,0,0,0,100,0),
(@PATH,5,-1035.883,2045.8641,67.884285,0,0,0,0,100,0),
(@PATH,6,-1027.7516,2060.0034,67.17399,0,0,0,0,100,0),
(@PATH,7,-1044.7845,2080.9624,64.488106,0,0,0,0,100,0),
(@PATH,8,-1057.2191,2099.7556,59.511543,0,0,0,0,100,0),
(@PATH,9,-1058.6903,2123.3728,51.636158,0,1000,0,0,100,0),
(@PATH,10,-1057.2191,2099.7556,59.511543,0,0,0,0,100,0),
(@PATH,11,-1044.7845,2080.9624,64.488106,0,0,0,0,100,0),
(@PATH,12,-1027.7516,2060.0034,67.17399,0,0,0,0,100,0),
(@PATH,13,-1035.883,2045.8641,67.884285,0,0,0,0,100,0),
(@PATH,14,-1024.8915,2036.1044,67.17399,0,0,0,0,100,0),
(@PATH,15,-1011.8848,2038.5491,67.04899,0,0,0,0,100,0),
(@PATH,16,-993.7006,2017.7288,67.06455,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Dark Shaman Entry: 16873
SET @NPC := 58258;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-877.10846,`position_y`=1921.7887,`position_z`=70.60205 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-877.10846,1921.7887,70.60205,0,0,0,0,100,0),
(@PATH,2,-879.1632,1955.2843,67.81312,0,0,0,0,100,0),
(@PATH,3,-889.66406,1985.5029,67.37617,0,0,0,0,100,0),
(@PATH,4,-909.5775,1992.9149,67.29996,0,0,0,0,100,0),
(@PATH,5,-921.1564,2015.1986,62.660126,0,0,0,0,100,0),
(@PATH,6,-938.3379,2024.596,65.73439,0,0,0,0,100,0),
(@PATH,7,-961.82477,2037.4991,67.04703,0,0,0,0,100,0),
(@PATH,8,-990.0961,2053.444,67.064545,0,0,0,0,100,0),
(@PATH,9,-1018.7484,2084.7126,68.99667,0,0,0,0,100,0),
(@PATH,10,-1037.1669,2107.136,59.970142,0,0,0,0,100,0),
(@PATH,11,-1060.8475,2105.1194,58.135914,0,0,0,0,100,0),
(@PATH,12,-1087.7483,2111.2378,62.76498,0,0,0,0,100,0),
(@PATH,13,-1119.0748,2129.2595,67.07792,0,0,0,0,100,0),
(@PATH,14,-1151.7645,2123.411,67.512314,0,0,0,0,100,0),
(@PATH,15,-1186.8909,2110.9136,70.73141,0,0,0,0,100,0),
(@PATH,16,-1151.7645,2123.411,67.512314,0,0,0,0,100,0),
(@PATH,17,-1119.0748,2129.2595,67.07792,0,0,0,0,100,0),
(@PATH,18,-1087.8555,2111.295,62.866543,0,0,0,0,100,0),
(@PATH,19,-1060.8475,2105.1194,58.135914,0,0,0,0,100,0),
(@PATH,20,-1037.1669,2107.136,59.970142,0,0,0,0,100,0),
(@PATH,21,-1018.7484,2084.7126,68.99667,0,0,0,0,100,0),
(@PATH,22,-990.0961,2053.444,67.064545,0,0,0,0,100,0),
(@PATH,23,-961.82477,2037.4991,67.04703,0,0,0,0,100,0),
(@PATH,24,-938.3379,2024.596,65.73439,0,0,0,0,100,0),
(@PATH,25,-921.1564,2015.1986,62.660126,0,0,0,0,100,0),
(@PATH,26,-909.6328,1993.0059,67.30032,0,0,0,0,100,0),
(@PATH,27,-889.6608,1985.5399,67.38715,0,0,0,0,100,0),
(@PATH,28,-879.1632,1955.2843,67.81312,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Dark Shaman Entry: 16873
SET @NPC := 29978;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-968.44434,`position_y`=2047.7053,`position_z`=67.064545 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-968.44434,2047.7053,67.064545,0,0,0,0,100,0),
(@PATH,2,-965.73956,2015.7266,67.03322,0,0,0,0,100,0),
(@PATH,3,-941.426,2015.6324,66.31691,0,0,0,0,100,0),
(@PATH,4,-929.8001,1991.0143,66.44107,0,0,0,0,100,0),
(@PATH,5,-914.9733,1976.5547,67.05032,0,0,0,0,100,0),
(@PATH,6,-932.1639,1983.5491,66.961945,0,0,0,0,100,0),
(@PATH,7,-946.79645,1966.628,67.06455,0,0,0,0,100,0),
(@PATH,8,-945.31305,1948.2524,67.06455,0,0,0,0,100,0),
(@PATH,9,-946.79645,1966.628,67.06455,0,0,0,0,100,0),
(@PATH,10,-932.1639,1983.5491,66.961945,0,0,0,0,100,0),
(@PATH,11,-914.9733,1976.5547,67.05032,0,0,0,0,100,0),
(@PATH,12,-929.8001,1991.0143,66.44107,0,0,0,0,100,0),
(@PATH,13,-941.426,2015.6324,66.31691,0,0,0,0,100,0),
(@PATH,14,-965.73956,2015.7266,67.03322,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Peon Entry: 16907
SET @NPC := 58628;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-1065.0123,`position_y`=2062.5,`position_z`=67.39088 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-1065.0123,2062.5,67.39088,0,16000,0,7,100,0),
(@PATH,2,-1074.1842,2099.383,61.61527,0,0,0,0,100,0),
(@PATH,3,-1100.0312,2096.4375,66.50842,0,0,0,0,100,0),
(@PATH,4,-1133.0763,2088.5916,67.601685,0,0,0,0,100,0),
(@PATH,5,-1143.4805,2084.83,67.064,0,16000,0,7,100,0),
(@PATH,6,-1147.8286,2089.2617,67.26493,0,0,0,0,100,0),
(@PATH,7,-1133.9977,2085.5886,67.27213,0,0,0,0,100,0),
(@PATH,8,-1101.0415,2090.6885,66.57092,0,0,0,0,100,0),
(@PATH,9,-1067.6989,2079.4993,64.35623,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Peon Entry: 16907
SET @NPC := 58632;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-968.0788,`position_y`=2012.5426,`position_z`=67.06455 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-968.0788,2012.5426,67.06455,0,16000,0,7,100,0),
(@PATH,2,-966.6169,2033.4601,67.04703,0,0,0,0,100,0),
(@PATH,3,-966.8878,2053.8928,67.064545,0,0,0,0,100,0),
(@PATH,4,-960.416,2063.937,67.04703,0,16000,0,7,100,0),
(@PATH,5,-981.17566,2071.8386,68.231735,0,0,0,0,100,0),
(@PATH,6,-987.19794,2063.2188,67.064545,0,0,0,0,100,0),
(@PATH,7,-980.19226,2043.2919,67.689545,0,0,0,0,100,0),
(@PATH,8,-966.6517,2033.1412,67.03322,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Peon Entry: 16907
SET @NPC := 58635;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-928.00714,`position_y`=1999.8239,`position_z`=65.75894 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-928.00714,1999.8239,65.75894,0,0,0,0,100,0),
(@PATH,2,-944.20184,2000.4841,67.02101,0,16000,0,7,100,0),
(@PATH,3,-907.9869,1999.1202,66.136505,0,0,0,0,100,0),
(@PATH,4,-905.9106,1982.6091,67.65091,0,16000,0,7,100,0),
(@PATH,5,-907.9869,1999.1202,66.136505,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Peon Entry: 16907
SET @NPC := 58636;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-969.9539,`position_y`=1906.9163,`position_z`=80.04651 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-969.9539,1906.9163,80.04651,0,0,0,0,100,0),
(@PATH,2,-968.75,1884.959,93.570885,0,16000,0,7,100,0),
(@PATH,3,-979.4396,1922.8817,76.151,0,0,0,0,100,0),
(@PATH,4,-1000.2953,1951.5786,70.21996,0,0,0,0,100,0),
(@PATH,5,-1021.2665,1969.5962,68.742065,0,0,0,0,100,0),
(@PATH,6,-1022.2342,1977.1777,69.25833,0,16000,0,7,100,0),
(@PATH,7,-1023.959,1967.709,69.18955,0,0,0,0,100,0),
(@PATH,8,-992.0776,1933.2765,73.80286,0,0,0,0,100,0);
-- Pathing for Bleeding Hollow Peon Entry: 16907
SET @NPC := 58637;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-902.6096,`position_y`=1967.311,`position_z`=68.788765 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-904.89417,1969.064,68.80128,0,0,0,0,100,0),
(@PATH,2,-905.89417,1967.064,69.05128,0,0,0,0,100,0),
(@PATH,3,-906.17880,1965.817,68.81379,0,60000,0,8,100,0),
(@PATH,4,-904.39417,1968.564,68.80128,0,0,0,0,100,0),
(@PATH,5,-902.60960,1967.311,68.78877,0,16000,0,7,100,0);
-- Pathing for Bleeding Hollow Peon Entry: 16907
SET @NPC := 58638;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-911.8403,`position_y`=1931.7609,`position_z`=67.027214 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-911.8403,1931.7609,67.027214,0,0,0,0,100,0),
(@PATH,2,-901.5605,1930.1989,67.027214,0,16000,0,7,100,0),
(@PATH,3,-914.4311,1926.0009,67.027214,0,0,0,0,100,0),
(@PATH,4,-932.3509,1900.8297,72.94836,0,0,0,0,100,0),
(@PATH,5,-967.2116,1894.1256,85.81161,0,0,0,0,100,0),
(@PATH,6,-982.6649,1896.1285,92.67928,0,0,0,0,100,0),
(@PATH,7,-981.78516,1890.1934,94.570885,0,16000,0,7,100,0),
(@PATH,8,-964.5519,1900.1129,81.00927,0,0,0,0,100,0),
(@PATH,9,-931.487,1906.1285,70.59911,0,0,0,0,100,0);
-- Path scripting for Bleeding Hollow Peon
DELETE FROM `waypoint_scripts` WHERE `id`=7;
INSERT INTO `waypoint_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`,`dataint`,`x`,`y`,`z`,`o`,`guid`) VALUES
(7,1,1,69,1,0,0,0,0,0,22), -- Emote 69
(7,15,1,0,1,0,0,0,0,0,23); -- Emote 0
DELETE FROM `waypoint_scripts` WHERE `id`=8;
INSERT INTO `waypoint_scripts` (`id`,`delay`,`command`,`datalong`,`datalong2`,`dataint`,`x`,`y`,`z`,`o`,`guid`) VALUES
(8,1,1,233,1,0,0,0,0,0,103), -- Emote 233
(8,59,1,0,1,0,0,0,0,0,104); -- Emote 0
-- Pathing for Mekthorg the Wild Entry: 18677 RARE one of 3 spawn points now pathed. only two points in db.
SET @NPC := 151922;
SET @PATH := @NPC * 10;
UPDATE `creature` SET `wander_distance`=0,`MovementType`=2,`position_x`=-987.7194,`position_y`=1881.4501,`position_z`=95.89022,`curhealth`=1,`curmana`=0 WHERE `guid`=@NPC;
DELETE FROM `creature_addon` WHERE `guid`=@NPC;
INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`visibilityDistanceType`,`auras`) VALUES (@NPC,@PATH,0,0,1,0,0, '');
DELETE FROM `waypoint_data` WHERE `id`=@PATH;
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
(@PATH,1,-987.7194,1881.4501,95.89022,0,0,0,0,100,0),
(@PATH,2,-984.1102,1899.1782,90.84872,0,0,0,0,100,0),
(@PATH,3,-976.1932,1921.5786,75.70105,0,0,0,0,100,0),
(@PATH,4,-975.6608,1952.5315,69.22548,0,0,0,0,100,0),
(@PATH,5,-978.0282,1984.714,68.93955,0,0,0,0,100,0),
(@PATH,6,-1002.7509,2003.1498,67.06455,0,0,0,0,100,0),
(@PATH,7,-1010.0032,2023.6588,67.80088,0,0,0,0,100,0),
(@PATH,8,-1028.8805,2038.1241,67.04899,0,0,0,0,100,0),
(@PATH,9,-1063.9316,2026.484,67.67393,0,0,0,0,100,0),
(@PATH,10,-1085.6248,2030.5725,67.05327,0,0,0,0,100,0),
(@PATH,11,-1105.8884,2042.7852,67.18956,0,0,0,0,100,0),
(@PATH,12,-1148.4607,2039.7408,67.189575,0,0,0,0,100,0),
(@PATH,13,-1172.25,2056.3086,73.368835,0,0,0,0,100,0),
(@PATH,14,-1178.7042,2078.21,71.083725,0,0,0,0,100,0),
(@PATH,15,-1174.2474,2108.973,69.47176,0,0,0,0,100,0),
(@PATH,16,-1152.0271,2122.7058,67.59691,0,0,0,0,100,0),
(@PATH,17,-1121.1113,2120.4404,67.20292,0,0,0,0,100,0),
(@PATH,18,-1085.4517,2106.8176,62.74423,0,0,0,0,100,0),
(@PATH,19,-1064.012,2104.008,58.782154,0,0,0,0,100,0),
(@PATH,20,-1054.82,2133.3486,46.279366,0,0,0,0,100,0),
(@PATH,21,-1042.7645,2165.6113,27.274483,0,0,0,0,100,0),
(@PATH,22,-1039.8318,2186.8723,20.115,0,0,0,0,100,0),
(@PATH,23,-1016.6897,2190.1084,16.460728,0,0,0,0,100,0),
(@PATH,24,-974.7051,2189.5803,14.407852,0,0,0,0,100,0),
(@PATH,25,-950.99567,2183.5935,13.458887,0,0,0,0,100,0),
(@PATH,26,-938.94183,2156.4084,16.141659,0,0,0,0,100,0),
(@PATH,27,-937.7561,2138.6687,18.047665,0,0,0,0,100,0),
(@PATH,28,-923.14343,2122.5134,20.539085,0,0,0,0,100,0),
(@PATH,29,-902.0319,2091.4502,25.522127,0,0,0,0,100,0),
(@PATH,30,-889.11847,2062.8213,34.843987,0,0,0,0,100,0),
(@PATH,31,-904.67645,2041.6077,48.600674,0,0,0,0,100,0),
(@PATH,32,-918.005,2020.2242,60.673798,0,0,0,0,100,0),
(@PATH,33,-923.1109,1986.4141,66.74307,0,0,0,0,100,0),
(@PATH,34,-920.11066,1953.3234,67.54038,0,0,0,0,100,0),
(@PATH,35,-885.3757,1939.7952,67.02503,0,0,0,0,100,0),
(@PATH,36,-920.11066,1953.3234,67.54038,0,0,0,0,100,0),
(@PATH,37,-923.1109,1986.4141,66.74307,0,0,0,0,100,0),
(@PATH,38,-918.005,2020.2242,60.673798,0,0,0,0,100,0),
(@PATH,39,-904.67645,2041.6077,48.600674,0,0,0,0,100,0),
(@PATH,40,-889.11847,2062.8213,34.843987,0,0,0,0,100,0),
(@PATH,41,-902.0319,2091.4502,25.522127,0,0,0,0,100,0),
(@PATH,42,-923.14343,2122.5134,20.539085,0,0,0,0,100,0),
(@PATH,43,-937.7561,2138.6687,18.047665,0,0,0,0,100,0),
(@PATH,44,-938.94183,2156.4084,16.141659,0,0,0,0,100,0),
(@PATH,45,-950.99567,2183.5935,13.458887,0,0,0,0,100,0),
(@PATH,46,-974.7051,2189.5803,14.407852,0,0,0,0,100,0),
(@PATH,47,-1016.6897,2190.1084,16.460728,0,0,0,0,100,0),
(@PATH,48,-1039.8318,2186.8723,20.115,0,0,0,0,100,0),
(@PATH,49,-1042.7645,2165.6113,27.274483,0,0,0,0,100,0),
(@PATH,50,-1054.82,2133.3486,46.279366,0,0,0,0,100,0),
(@PATH,51,-1064.012,2104.008,58.782154,0,0,0,0,100,0),
(@PATH,52,-1085.4517,2106.8176,62.74423,0,0,0,0,100,0),
(@PATH,53,-1121.1113,2120.4404,67.20292,0,0,0,0,100,0),
(@PATH,54,-1152.0271,2122.7058,67.59691,0,0,0,0,100,0),
(@PATH,55,-1174.168,2109.046,69.499596,0,0,0,0,100,0),
(@PATH,56,-1178.7042,2078.21,71.083725,0,0,0,0,100,0),
(@PATH,57,-1172.3702,2056.4028,73.31464,0,0,0,0,100,0),
(@PATH,58,-1148.4607,2039.7408,67.189575,0,0,0,0,100,0),
(@PATH,59,-1105.8884,2042.7852,67.18956,0,0,0,0,100,0),
(@PATH,60,-1085.6248,2030.5725,67.05327,0,0,0,0,100,0),
(@PATH,61,-1063.9316,2026.484,67.67393,0,0,0,0,100,0),
(@PATH,62,-1028.8805,2038.1241,67.04899,0,0,0,0,100,0),
(@PATH,63,-1010.0032,2023.6588,67.80088,0,0,0,0,100,0),
(@PATH,64,-1002.7509,2003.1498,67.06455,0,0,0,0,100,0),
(@PATH,65,-978.0282,1984.714,68.93955,0,0,0,0,100,0),
(@PATH,66,-975.6608,1952.5315,69.22548,0,0,0,0,100,0),
(@PATH,67,-976.1932,1921.5786,75.70105,0,0,0,0,100,0),
(@PATH,68,-984.1102,1899.1782,90.84872,0,0,0,0,100,0);
--
-- END UPDATING QUERIES
--
UPDATE version_db_world SET date = '2022_01_30_02' WHERE sql_rev = '1643556744064585623';
COMMIT;
END //
DELIMITER ;
CALL updateDb();
DROP PROCEDURE IF EXISTS `updateDb`;
@@ -0,0 +1,29 @@
-- DB update 2022_01_30_02 -> 2022_01_31_00
DROP PROCEDURE IF EXISTS `updateDb`;
DELIMITER //
CREATE PROCEDURE updateDb ()
proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE';
SELECT COUNT(*) INTO @COLEXISTS
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2022_01_30_02';
IF @COLEXISTS = 0 THEN LEAVE proc; END IF;
START TRANSACTION;
ALTER TABLE version_db_world CHANGE COLUMN 2022_01_30_02 2022_01_31_00 bit;
SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1642869202090443400'; IF OK <> 'FALSE' THEN LEAVE proc; END IF;
--
-- START UPDATING QUERIES
--
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1642869202090443400');
UPDATE `spell_group` SET `special_flag`=8192 WHERE `spell_id`=48090;
--
-- END UPDATING QUERIES
--
UPDATE version_db_world SET date = '2022_01_31_00' WHERE sql_rev = '1642869202090443400';
COMMIT;
END //
DELIMITER ;
CALL updateDb();
DROP PROCEDURE IF EXISTS `updateDb`;
@@ -0,0 +1,31 @@
-- DB update 2022_01_31_00 -> 2022_01_31_01
DROP PROCEDURE IF EXISTS `updateDb`;
DELIMITER //
CREATE PROCEDURE updateDb ()
proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE';
SELECT COUNT(*) INTO @COLEXISTS
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2022_01_31_00';
IF @COLEXISTS = 0 THEN LEAVE proc; END IF;
START TRANSACTION;
ALTER TABLE version_db_world CHANGE COLUMN 2022_01_31_00 2022_01_31_01 bit;
SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1642904052333135300'; IF OK <> 'FALSE' THEN LEAVE proc; END IF;
--
-- START UPDATING QUERIES
--
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1642904052333135300');
DELETE FROM `creature_loot_template` WHERE (`Entry` = 3281) AND (`Item` IN (4905));
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(3281, 4905, 0, 100, 1, 1, 0, 1, 1, 'Sarkoth - Sarkoth\'s Mangled Claw');
--
-- END UPDATING QUERIES
--
UPDATE version_db_world SET date = '2022_01_31_01' WHERE sql_rev = '1642904052333135300';
COMMIT;
END //
DELIMITER ;
CALL updateDb();
DROP PROCEDURE IF EXISTS `updateDb`;
@@ -0,0 +1,35 @@
-- DB update 2022_01_31_01 -> 2022_01_31_02
DROP PROCEDURE IF EXISTS `updateDb`;
DELIMITER //
CREATE PROCEDURE updateDb ()
proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE';
SELECT COUNT(*) INTO @COLEXISTS
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2022_01_31_01';
IF @COLEXISTS = 0 THEN LEAVE proc; END IF;
START TRANSACTION;
ALTER TABLE version_db_world CHANGE COLUMN 2022_01_31_01 2022_01_31_02 bit;
SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1643502379399332300'; IF OK <> 'FALSE' THEN LEAVE proc; END IF;
--
-- START UPDATING QUERIES
--
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1643502379399332300');
DELETE FROM `command` WHERE `name` = 'go quest';
INSERT INTO `command` (`name`, `security`, `help`) VALUES
('go quest', 1, 'Syntax: .go quest <starter/ender> <quest>.\nTeleports you to the quest starter/ender creature or object.');
DELETE FROM `acore_string` WHERE `entry` = 5082;
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_deDE`) VALUES
(5082, 'Incorrect syntax. Specify either \'starter\' or \'ender\'.', 'Falsche syntax. Entweder \'starter\' oder \'ender\' angeben.');
--
-- END UPDATING QUERIES
--
UPDATE version_db_world SET date = '2022_01_31_02' WHERE sql_rev = '1643502379399332300';
COMMIT;
END //
DELIMITER ;
CALL updateDb();
DROP PROCEDURE IF EXISTS `updateDb`;
@@ -0,0 +1,33 @@
-- DB update 2022_01_31_02 -> 2022_02_01_00
DROP PROCEDURE IF EXISTS `updateDb`;
DELIMITER //
CREATE PROCEDURE updateDb ()
proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE';
SELECT COUNT(*) INTO @COLEXISTS
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2022_01_31_02';
IF @COLEXISTS = 0 THEN LEAVE proc; END IF;
START TRANSACTION;
ALTER TABLE version_db_world CHANGE COLUMN 2022_01_31_02 2022_02_01_00 bit;
SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1642953762715459200'; IF OK <> 'FALSE' THEN LEAVE proc; END IF;
--
-- START UPDATING QUERIES
--
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1642953762715459200');
UPDATE `smart_scripts` SET `id`=19 WHERE `entryorguid`=12818 AND `source_type`=0 AND `id`=18 AND `event_type`=11;
UPDATE `smart_scripts` SET `link`=18 WHERE `entryorguid`=12818 AND `source_type`=0 AND `id`=17;
DELETE FROM `smart_scripts` WHERE `entryorguid`=12818 AND `source_type`=0 AND `id`=18;
INSERT INTO `smart_scripts` VALUES
(12818,0,18,0,61,0,100,0,0,0,0,0,0,26,6482,0,0,0,0,0,7,0,0,0,0,0,0,0,0,'Ruul Snowhoof - On Waypoint Finished - Quest Complete');
--
-- END UPDATING QUERIES
--
UPDATE version_db_world SET date = '2022_02_01_00' WHERE sql_rev = '1642953762715459200';
COMMIT;
END //
DELIMITER ;
CALL updateDb();
DROP PROCEDURE IF EXISTS `updateDb`;
@@ -0,0 +1,28 @@
-- DB update 2022_02_01_00 -> 2022_02_01_01
DROP PROCEDURE IF EXISTS `updateDb`;
DELIMITER //
CREATE PROCEDURE updateDb ()
proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE';
SELECT COUNT(*) INTO @COLEXISTS
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2022_02_01_00';
IF @COLEXISTS = 0 THEN LEAVE proc; END IF;
START TRANSACTION;
ALTER TABLE version_db_world CHANGE COLUMN 2022_02_01_00 2022_02_01_01 bit;
SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1642220996463864536'; IF OK <> 'FALSE' THEN LEAVE proc; END IF;
--
-- START UPDATING QUERIES
--
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1642220996463864536');
UPDATE `creature_template_movement` SET `Flight` = 1 WHERE `CreatureId` IN (10184,36538);
--
-- END UPDATING QUERIES
--
UPDATE version_db_world SET date = '2022_02_01_01' WHERE sql_rev = '1642220996463864536';
COMMIT;
END //
DELIMITER ;
CALL updateDb();
DROP PROCEDURE IF EXISTS `updateDb`;
+5
View File
@@ -59,6 +59,11 @@ if (HAVE_STRTOD_L)
FMT_LOCALE)
endif()
# Define FMT_CONSTEVAL for current using in c++20
target_compile_definitions(fmt
PUBLIC
FMT_CONSTEVAL=)
target_include_directories(fmt
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include)
+385 -8
View File
@@ -1,3 +1,374 @@
8.1.1 - 2022-01-06
------------------
* Restored ABI compatibility with version 8.0.x
(`#2695 <https://github.com/fmtlib/fmt/issues/2695>`_,
`#2696 <https://github.com/fmtlib/fmt/pull/2696>`_).
Thanks `@saraedum (Julian Rüth) <https://github.com/saraedum>`_.
* Fixed chrono formatting on big endian systems
(`#2698 <https://github.com/fmtlib/fmt/issues/2698>`_,
`#2699 <https://github.com/fmtlib/fmt/pull/2699>`_).
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_ and
`@xvitaly (Vitaly Zaitsev) <https://github.com/xvitaly>`_.
* Fixed a linkage error with mingw
(`#2691 <https://github.com/fmtlib/fmt/issues/2691>`_,
`#2692 <https://github.com/fmtlib/fmt/pull/2692>`_).
Thanks `@rbberger (Richard Berger) <https://github.com/rbberger>`_.
8.1.0 - 2022-01-02
------------------
* Optimized chrono formatting
(`#2500 <https://github.com/fmtlib/fmt/pull/2500>`_,
`#2537 <https://github.com/fmtlib/fmt/pull/2537>`_,
`#2541 <https://github.com/fmtlib/fmt/issues/2541>`_,
`#2544 <https://github.com/fmtlib/fmt/pull/2544>`_,
`#2550 <https://github.com/fmtlib/fmt/pull/2550>`_,
`#2551 <https://github.com/fmtlib/fmt/pull/2551>`_,
`#2576 <https://github.com/fmtlib/fmt/pull/2576>`_,
`#2577 <https://github.com/fmtlib/fmt/issues/2577>`_,
`#2586 <https://github.com/fmtlib/fmt/pull/2586>`_,
`#2591 <https://github.com/fmtlib/fmt/pull/2591>`_,
`#2594 <https://github.com/fmtlib/fmt/pull/2594>`_,
`#2602 <https://github.com/fmtlib/fmt/pull/2602>`_,
`#2617 <https://github.com/fmtlib/fmt/pull/2617>`_,
`#2628 <https://github.com/fmtlib/fmt/issues/2628>`_,
`#2633 <https://github.com/fmtlib/fmt/pull/2633>`_,
`#2670 <https://github.com/fmtlib/fmt/issues/2670>`_,
`#2671 <https://github.com/fmtlib/fmt/pull/2671>`_).
Processing of some specifiers such as ``%z`` and ``%Y`` is now up to 10-20
times faster, for example on GCC 11 with libstdc++::
----------------------------------------------------------------------------
Benchmark Before After
----------------------------------------------------------------------------
FMTFormatter_z 261 ns 26.3 ns
FMTFormatterCompile_z 246 ns 11.6 ns
FMTFormatter_Y 263 ns 26.1 ns
FMTFormatterCompile_Y 244 ns 10.5 ns
----------------------------------------------------------------------------
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_ and
`@toughengineer (Pavel Novikov) <https://github.com/toughengineer>`_.
* Implemented subsecond formatting for chrono durations
(`#2623 <https://github.com/fmtlib/fmt/pull/2623>`_).
For example (`godbolt <https://godbolt.org/z/es7vWTETe>`__):
.. code:: c++
#include <fmt/chrono.h>
int main() {
fmt::print("{:%S}", std::chrono::milliseconds(1234));
}
prints "01.234".
Thanks `@matrackif <https://github.com/matrackif>`_.
* Fixed handling of precision 0 when formatting chrono durations
(`#2587 <https://github.com/fmtlib/fmt/issues/2587>`_,
`#2588 <https://github.com/fmtlib/fmt/pull/2588>`_).
Thanks `@lukester1975 <https://github.com/lukester1975>`_.
* Fixed an overflow on invalid inputs in the ``tm`` formatter
(`#2564 <https://github.com/fmtlib/fmt/pull/2564>`_).
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
* Added ``fmt::group_digits`` that formats integers with a non-localized digit
separator (comma) for groups of three digits.
For example (`godbolt <https://godbolt.org/z/TxGxG9Poq>`__):
.. code:: c++
#include <fmt/format.h>
int main() {
fmt::print("{} dollars", fmt::group_digits(1000000));
}
prints "1,000,000 dollars".
* Added support for faint, conceal, reverse and blink text styles
(`#2394 <https://github.com/fmtlib/fmt/pull/2394>`_):
https://user-images.githubusercontent.com/576385/147710227-c68f5317-f8fa-42c3-9123-7c4ba3c398cb.mp4
Thanks `@benit8 (Benoît Lormeau) <https://github.com/benit8>`_ and
`@data-man (Dmitry Atamanov) <https://github.com/data-man>`_.
* Added experimental support for compile-time floating point formatting
(`#2426 <https://github.com/fmtlib/fmt/pull/2426>`_,
`#2470 <https://github.com/fmtlib/fmt/pull/2470>`_).
It is currently limited to the header-only mode.
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
* Added UDL-based named argument support to compile-time format string checks
(`#2640 <https://github.com/fmtlib/fmt/issues/2640>`_,
`#2649 <https://github.com/fmtlib/fmt/pull/2649>`_).
For example (`godbolt <https://godbolt.org/z/ohGbbvonv>`__):
.. code:: c++
#include <fmt/format.h>
int main() {
using namespace fmt::literals;
fmt::print("{answer:s}", "answer"_a=42);
}
gives a compile-time error on compilers with C++20 ``consteval`` and non-type
template parameter support (gcc 10+) because ``s`` is not a valid format
specifier for an integer.
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
* Implemented escaping of string range elements.
For example (`godbolt <https://godbolt.org/z/rKvM1vKf3>`__):
.. code:: c++
#include <fmt/ranges.h>
#include <vector>
int main() {
fmt::print("{}", std::vector<std::string>{"\naan"});
}
is now printed as::
["\naan"]
instead of::
["
aan"]
* Switched to JSON-like representation of maps and sets for consistency with
Python's ``str.format``.
For example (`godbolt <https://godbolt.org/z/seKjoY9W5>`__):
.. code:: c++
#include <fmt/ranges.h>
#include <map>
int main() {
fmt::print("{}", std::map<std::string, int>{{"answer", 42}});
}
is now printed as::
{"answer": 42}
* Extended ``fmt::join`` to support C++20-only ranges
(`#2549 <https://github.com/fmtlib/fmt/pull/2549>`_).
Thanks `@BRevzin (Barry Revzin) <https://github.com/BRevzin>`_.
* Optimized handling of non-const-iterable ranges and implemented initial
support for non-const-formattable types.
* Disabled implicit conversions of scoped enums to integers that was
accidentally introduced in earlier versions
(`#1841 <https://github.com/fmtlib/fmt/pull/1841>`_).
* Deprecated implicit conversion of ``[const] signed char*`` and
``[const] unsigned char*`` to C strings.
* Deprecated ``_format``, a legacy UDL-based format API
(`#2646 <https://github.com/fmtlib/fmt/pull/2646>`_).
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
* Marked ``format``, ``formatted_size`` and ``to_string`` as ``[[nodiscard]]``
(`#2612 <https://github.com/fmtlib/fmt/pull/2612>`_).
`@0x8000-0000 (Florin Iucha) <https://github.com/0x8000-0000>`_.
* Added missing diagnostic when trying to format function and member pointers
as well as objects convertible to pointers which is explicitly disallowed
(`#2598 <https://github.com/fmtlib/fmt/issues/2598>`_,
`#2609 <https://github.com/fmtlib/fmt/pull/2609>`_,
`#2610 <https://github.com/fmtlib/fmt/pull/2610>`_).
Thanks `@AlexGuteniev (Alex Guteniev) <https://github.com/AlexGuteniev>`_.
* Optimized writing to a contiguous buffer with ``format_to_n``
(`#2489 <https://github.com/fmtlib/fmt/pull/2489>`_).
Thanks `@Roman-Koshelev <https://github.com/Roman-Koshelev>`_.
* Optimized writing to non-``char`` buffers
(`#2477 <https://github.com/fmtlib/fmt/pull/2477>`_).
Thanks `@Roman-Koshelev <https://github.com/Roman-Koshelev>`_.
* Decimal point is now localized when using the ``L`` specifier.
* Improved floating point formatter implementation
(`#2498 <https://github.com/fmtlib/fmt/pull/2498>`_,
`#2499 <https://github.com/fmtlib/fmt/pull/2499>`_).
Thanks `@Roman-Koshelev <https://github.com/Roman-Koshelev>`_.
* Fixed handling of very large precision in fixed format
(`#2616 <https://github.com/fmtlib/fmt/pull/2616>`_).
* Made a table of cached powers used in FP formatting static
(`#2509 <https://github.com/fmtlib/fmt/pull/2509>`_).
Thanks `@jk-jeon (Junekey Jeon) <https://github.com/jk-jeon>`_.
* Resolved a lookup ambiguity with C++20 format-related functions due to ADL
(`#2639 <https://github.com/fmtlib/fmt/issues/2639>`_,
`#2641 <https://github.com/fmtlib/fmt/pull/2641>`_).
Thanks `@mkurdej (Marek Kurdej) <https://github.com/mkurdej>`_.
* Removed unnecessary inline namespace qualification
(`#2642 <https://github.com/fmtlib/fmt/issues/2642>`_,
`#2643 <https://github.com/fmtlib/fmt/pull/2643>`_).
Thanks `@mkurdej (Marek Kurdej) <https://github.com/mkurdej>`_.
* Implemented argument forwarding in ``format_to_n``
(`#2462 <https://github.com/fmtlib/fmt/issues/2462>`_,
`#2463 <https://github.com/fmtlib/fmt/pull/2463>`_).
Thanks `@owent (WenTao Ou) <https://github.com/owent>`_.
* Fixed handling of implicit conversions in ``fmt::to_string`` and format string
compilation (`#2565 <https://github.com/fmtlib/fmt/issues/2565>`_).
* Changed the default access mode of files created by ``fmt::output_file`` to
``-rw-r--r--`` for consistency with ``fopen``
(`#2530 <https://github.com/fmtlib/fmt/issues/2530>`_).
* Make ``fmt::ostream::flush`` public
(`#2435 <https://github.com/fmtlib/fmt/issues/2435>`_).
* Improved C++14/17 attribute detection
(`#2615 <https://github.com/fmtlib/fmt/pull/2615>`_).
Thanks `@AlexGuteniev (Alex Guteniev) <https://github.com/AlexGuteniev>`_.
* Improved ``consteval`` detection for MSVC
(`#2559 <https://github.com/fmtlib/fmt/pull/2559>`_).
Thanks `@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_.
* Improved documentation
(`#2406 <https://github.com/fmtlib/fmt/issues/2406>`_,
`#2446 <https://github.com/fmtlib/fmt/pull/2446>`_,
`#2493 <https://github.com/fmtlib/fmt/issues/2493>`_,
`#2513 <https://github.com/fmtlib/fmt/issues/2513>`_,
`#2515 <https://github.com/fmtlib/fmt/pull/2515>`_,
`#2522 <https://github.com/fmtlib/fmt/issues/2522>`_,
`#2562 <https://github.com/fmtlib/fmt/pull/2562>`_,
`#2575 <https://github.com/fmtlib/fmt/pull/2575>`_,
`#2606 <https://github.com/fmtlib/fmt/pull/2606>`_,
`#2620 <https://github.com/fmtlib/fmt/pull/2620>`_,
`#2676 <https://github.com/fmtlib/fmt/issues/2676>`_).
Thanks `@sobolevn (Nikita Sobolev) <https://github.com/sobolevn>`_,
`@UnePierre (Max FERGER) <https://github.com/UnePierre>`_,
`@zhsj <https://github.com/zhsj>`_,
`@phprus (Vladislav Shchapov) <https://github.com/phprus>`_,
`@ericcurtin (Eric Curtin) <https://github.com/ericcurtin>`_,
`@Lounarok <https://github.com/Lounarok>`_.
* Improved fuzzers and added a fuzzer for chrono timepoint formatting
(`#2461 <https://github.com/fmtlib/fmt/pull/2461>`_,
`#2469 <https://github.com/fmtlib/fmt/pull/2469>`_).
`@pauldreik (Paul Dreik) <https://github.com/pauldreik>`_,
* Added the ``FMT_SYSTEM_HEADERS`` CMake option setting which marks {fmt}'s
headers as system. It can be used to suppress warnings
(`#2644 <https://github.com/fmtlib/fmt/issues/2644>`_,
`#2651 <https://github.com/fmtlib/fmt/pull/2651>`_).
Thanks `@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_.
* Added the Bazel build system support
(`#2505 <https://github.com/fmtlib/fmt/pull/2505>`_,
`#2516 <https://github.com/fmtlib/fmt/pull/2516>`_).
Thanks `@Vertexwahn <https://github.com/Vertexwahn>`_.
* Improved build configuration and tests
(`#2437 <https://github.com/fmtlib/fmt/issues/2437>`_,
`#2558 <https://github.com/fmtlib/fmt/pull/2558>`_,
`#2648 <https://github.com/fmtlib/fmt/pull/2648>`_,
`#2650 <https://github.com/fmtlib/fmt/pull/2650>`_,
`#2663 <https://github.com/fmtlib/fmt/pull/2663>`_,
`#2677 <https://github.com/fmtlib/fmt/pull/2677>`_).
Thanks `@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_,
`@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_,
`@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
* Fixed various warnings and compilation issues
(`#2353 <https://github.com/fmtlib/fmt/pull/2353>`_,
`#2356 <https://github.com/fmtlib/fmt/pull/2356>`_,
`#2399 <https://github.com/fmtlib/fmt/pull/2399>`_,
`#2408 <https://github.com/fmtlib/fmt/issues/2408>`_,
`#2414 <https://github.com/fmtlib/fmt/pull/2414>`_,
`#2427 <https://github.com/fmtlib/fmt/pull/2427>`_,
`#2432 <https://github.com/fmtlib/fmt/pull/2432>`_,
`#2442 <https://github.com/fmtlib/fmt/pull/2442>`_,
`#2434 <https://github.com/fmtlib/fmt/pull/2434>`_,
`#2439 <https://github.com/fmtlib/fmt/issues/2439>`_,
`#2447 <https://github.com/fmtlib/fmt/pull/2447>`_,
`#2450 <https://github.com/fmtlib/fmt/pull/2450>`_,
`#2455 <https://github.com/fmtlib/fmt/issues/2455>`_,
`#2465 <https://github.com/fmtlib/fmt/issues/2465>`_,
`#2472 <https://github.com/fmtlib/fmt/issues/2472>`_,
`#2474 <https://github.com/fmtlib/fmt/issues/2474>`_,
`#2476 <https://github.com/fmtlib/fmt/pull/2476>`_,
`#2478 <https://github.com/fmtlib/fmt/issues/2478>`_,
`#2479 <https://github.com/fmtlib/fmt/issues/2479>`_,
`#2481 <https://github.com/fmtlib/fmt/issues/2481>`_,
`#2482 <https://github.com/fmtlib/fmt/pull/2482>`_,
`#2483 <https://github.com/fmtlib/fmt/pull/2483>`_,
`#2490 <https://github.com/fmtlib/fmt/issues/2490>`_,
`#2491 <https://github.com/fmtlib/fmt/pull/2491>`_,
`#2510 <https://github.com/fmtlib/fmt/pull/2510>`_,
`#2518 <https://github.com/fmtlib/fmt/pull/2518>`_,
`#2528 <https://github.com/fmtlib/fmt/issues/2528>`_,
`#2529 <https://github.com/fmtlib/fmt/pull/2529>`_,
`#2539 <https://github.com/fmtlib/fmt/pull/2539>`_,
`#2540 <https://github.com/fmtlib/fmt/issues/2540>`_,
`#2545 <https://github.com/fmtlib/fmt/pull/2545>`_,
`#2555 <https://github.com/fmtlib/fmt/pull/2555>`_,
`#2557 <https://github.com/fmtlib/fmt/issues/2557>`_,
`#2570 <https://github.com/fmtlib/fmt/issues/2570>`_,
`#2573 <https://github.com/fmtlib/fmt/pull/2573>`_,
`#2582 <https://github.com/fmtlib/fmt/pull/2582>`_,
`#2605 <https://github.com/fmtlib/fmt/issues/2605>`_,
`#2611 <https://github.com/fmtlib/fmt/pull/2611>`_,
`#2647 <https://github.com/fmtlib/fmt/pull/2647>`_,
`#2627 <https://github.com/fmtlib/fmt/issues/2627>`_,
`#2630 <https://github.com/fmtlib/fmt/pull/2630>`_,
`#2635 <https://github.com/fmtlib/fmt/issues/2635>`_,
`#2638 <https://github.com/fmtlib/fmt/issues/2638>`_,
`#2653 <https://github.com/fmtlib/fmt/issues/2653>`_,
`#2654 <https://github.com/fmtlib/fmt/issues/2654>`_,
`#2661 <https://github.com/fmtlib/fmt/issues/2661>`_,
`#2664 <https://github.com/fmtlib/fmt/pull/2664>`_,
`#2684 <https://github.com/fmtlib/fmt/pull/2684>`_).
Thanks `@DanielaE (Daniela Engert) <https://github.com/DanielaE>`_,
`@mwinterb <https://github.com/mwinterb>`_,
`@cdacamar (Cameron DaCamara) <https://github.com/cdacamar>`_,
`@TrebledJ (Johnathan) <https://github.com/TrebledJ>`_,
`@bodomartin (brm) <https://github.com/bodomartin>`_,
`@cquammen (Cory Quammen) <https://github.com/cquammen>`_,
`@white238 (Chris White) <https://github.com/white238>`_,
`@mmarkeloff (Max) <https://github.com/mmarkeloff>`_,
`@palacaze (Pierre-Antoine Lacaze) <https://github.com/palacaze>`_,
`@jcelerier (Jean-Michaël Celerier) <https://github.com/jcelerier>`_,
`@mborn-adi (Mathias Born) <https://github.com/mborn-adi>`_,
`@BrukerJWD (Jonathan W) <https://github.com/BrukerJWD>`_,
`@spyridon97 (Spiros Tsalikis) <https://github.com/spyridon97>`_,
`@phprus (Vladislav Shchapov) <https://github.com/phprus>`_,
`@oliverlee (Oliver Lee) <https://github.com/oliverlee>`_,
`@joshessman-llnl (Josh Essman) <https://github.com/joshessman-llnl>`_,
`@akohlmey (Axel Kohlmeyer) <https://github.com/akohlmey>`_,
`@timkalu <https://github.com/timkalu>`_,
`@olupton (Olli Lupton) <https://github.com/olupton>`_,
`@Acretock <https://github.com/Acretock>`_,
`@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_,
`@andrewcorrigan (Andrew Corrigan) <https://github.com/andrewcorrigan>`_,
`@lucpelletier <https://github.com/lucpelletier>`_,
`@HazardyKnusperkeks (Björn Schäpers) <https://github.com/HazardyKnusperkeks>`_.
8.0.1 - 2021-07-02
------------------
@@ -34,7 +405,7 @@
`#2389 <https://github.com/fmtlib/fmt/pull/2389>`_,
`#2395 <https://github.com/fmtlib/fmt/pull/2395>`_,
`#2397 <https://github.com/fmtlib/fmt/pull/2397>`_,
`#2400 <https://github.com/fmtlib/fmt/issues/2400>`_
`#2400 <https://github.com/fmtlib/fmt/issues/2400>`_,
`#2401 <https://github.com/fmtlib/fmt/issues/2401>`_,
`#2407 <https://github.com/fmtlib/fmt/pull/2407>`_).
Thanks `@zx2c4 (Jason A. Donenfeld) <https://github.com/zx2c4>`_,
@@ -50,7 +421,7 @@
8.0.0 - 2021-06-21
------------------
* Enabled compile-time format string check by default.
* Enabled compile-time format string checks by default.
For example (`godbolt <https://godbolt.org/z/sMxcohGjz>`__):
.. code:: c++
@@ -281,6 +652,9 @@
This doesn't introduce a dependency on ``<locale>`` so there is virtually no
compile time effect.
* Deprecated an undocumented ``format_to`` overload that takes
``basic_memory_buffer``.
* Made parameter order in ``vformat_to`` consistent with ``format_to``
(`#2327 <https://github.com/fmtlib/fmt/issues/2327>`_).
@@ -387,6 +761,9 @@
Thanks `@mikecrowe (Mike Crowe) <https://github.com/mikecrowe>`_.
* The undocumented support for specializing ``formatter`` for pointer types
has been removed.
* Fixed ``fmt::formatted_size`` with format string compilation
(`#2141 <https://github.com/fmtlib/fmt/pull/2141>`_,
`#2161 <https://github.com/fmtlib/fmt/pull/2161>`_).
@@ -559,13 +936,13 @@
`#2067 <https://github.com/fmtlib/fmt/pull/2067>`_,
`#2068 <https://github.com/fmtlib/fmt/pull/2068>`_,
`#2073 <https://github.com/fmtlib/fmt/pull/2073>`_,
`#2103 <https://github.com/fmtlib/fmt/issues/2103>`_
`#2105 <https://github.com/fmtlib/fmt/issues/2105>`_
`#2103 <https://github.com/fmtlib/fmt/issues/2103>`_,
`#2105 <https://github.com/fmtlib/fmt/issues/2105>`_,
`#2106 <https://github.com/fmtlib/fmt/pull/2106>`_,
`#2107 <https://github.com/fmtlib/fmt/pull/2107>`_,
`#2116 <https://github.com/fmtlib/fmt/issues/2116>`_
`#2116 <https://github.com/fmtlib/fmt/issues/2116>`_,
`#2117 <https://github.com/fmtlib/fmt/pull/2117>`_,
`#2118 <https://github.com/fmtlib/fmt/issues/2118>`_
`#2118 <https://github.com/fmtlib/fmt/issues/2118>`_,
`#2119 <https://github.com/fmtlib/fmt/pull/2119>`_,
`#2127 <https://github.com/fmtlib/fmt/issues/2127>`_,
`#2128 <https://github.com/fmtlib/fmt/pull/2128>`_,
@@ -638,7 +1015,7 @@
`@yeswalrus (Walter Gray) <https://github.com/yeswalrus>`_,
`@Finkman <https://github.com/Finkman>`_,
`@HazardyKnusperkeks (Björn Schäpers) <https://github.com/HazardyKnusperkeks>`_,
`@dkavolis (Daumantas Kavolis) <https://github.com/dkavolis>`_
`@dkavolis (Daumantas Kavolis) <https://github.com/dkavolis>`_,
`@concatime (Issam Maghni) <https://github.com/concatime>`_,
`@chronoxor (Ivan Shynkarenka) <https://github.com/chronoxor>`_,
`@summivox (Yin Zhong) <https://github.com/summivox>`_,
@@ -1095,7 +1472,7 @@
`#1912 <https://github.com/fmtlib/fmt/issues/1912>`_,
`#1928 <https://github.com/fmtlib/fmt/issues/1928>`_,
`#1929 <https://github.com/fmtlib/fmt/pull/1929>`_,
`#1935 <https://github.com/fmtlib/fmt/issues/1935>`_
`#1935 <https://github.com/fmtlib/fmt/issues/1935>`_,
`#1937 <https://github.com/fmtlib/fmt/pull/1937>`_,
`#1942 <https://github.com/fmtlib/fmt/pull/1942>`_,
`#1949 <https://github.com/fmtlib/fmt/issues/1949>`_).
+6 -6
View File
@@ -10,7 +10,7 @@
.. image:: https://github.com/fmtlib/fmt/workflows/windows/badge.svg
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows
.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v
.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v?svg=true
:target: https://ci.appveyor.com/project/vitaut/fmt
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg
@@ -143,10 +143,10 @@ Output::
.. code:: c++
std::string s = fmt::format(FMT_STRING("{:d}"), "I am not a number");
std::string s = fmt::format("{:d}", "I am not a number");
This gives a compile-time error because ``d`` is an invalid format specifier for
a string.
This gives a compile-time error in C++20 because ``d`` is an invalid format
specifier for a string.
**Write a file from a single thread**
@@ -205,7 +205,7 @@ The above results were generated by building ``tinyformat_test.cpp`` on macOS
best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
further details refer to the `source
<https://github.com/fmtlib/format-benchmark/blob/master/tinyformat_test.cpp>`_.
<https://github.com/fmtlib/format-benchmark/blob/master/src/tinyformat-test.cc>`_.
{fmt} is up to 20-30x faster than ``std::ostringstream`` and ``sprintf`` on
floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
@@ -469,7 +469,7 @@ Boost Format
This is a very powerful library which supports both ``printf``-like format
strings and positional arguments. Its main drawback is performance. According to
various, benchmarks it is much slower than other methods considered here. Boost
various benchmarks, it is much slower than other methods considered here. Boost
Format also has excessive build times and severe code bloat issues (see
`Benchmarks`_).
+2
View File
@@ -143,6 +143,8 @@ class dynamic_format_arg_store
}
public:
constexpr dynamic_format_arg_store() = default;
/**
\rst
Adds an argument into the dynamic store for later passing to a formatting
+982 -211
View File
File diff suppressed because it is too large Load Diff
+40 -24
View File
@@ -185,9 +185,13 @@ enum class terminal_color : uint8_t {
enum class emphasis : uint8_t {
bold = 1,
italic = 1 << 1,
underline = 1 << 2,
strikethrough = 1 << 3
faint = 1 << 1,
italic = 1 << 2,
underline = 1 << 3,
blink = 1 << 4,
reverse = 1 << 5,
conceal = 1 << 6,
strikethrough = 1 << 7,
};
// rgb is a struct for red, green and blue colors.
@@ -409,16 +413,18 @@ template <typename Char> struct ansi_color_escape {
buffer[19] = static_cast<Char>(0);
}
FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT {
uint8_t em_codes[4] = {};
uint8_t em_bits = static_cast<uint8_t>(em);
if (em_bits & static_cast<uint8_t>(emphasis::bold)) em_codes[0] = 1;
if (em_bits & static_cast<uint8_t>(emphasis::italic)) em_codes[1] = 3;
if (em_bits & static_cast<uint8_t>(emphasis::underline)) em_codes[2] = 4;
if (em_bits & static_cast<uint8_t>(emphasis::strikethrough))
em_codes[3] = 9;
uint8_t em_codes[num_emphases] = {};
if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;
if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;
if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3;
if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4;
if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5;
if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7;
if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8;
if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9;
size_t index = 0;
for (int i = 0; i < 4; ++i) {
for (size_t i = 0; i < num_emphases; ++i) {
if (!em_codes[i]) continue;
buffer[index++] = static_cast<Char>('\x1b');
buffer[index++] = static_cast<Char>('[');
@@ -435,7 +441,8 @@ template <typename Char> struct ansi_color_escape {
}
private:
Char buffer[7u + 3u * 4u + 1u];
static constexpr size_t num_emphases = 8;
Char buffer[7u + 3u * num_emphases + 1u];
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
char delimiter) FMT_NOEXCEPT {
@@ -444,6 +451,10 @@ template <typename Char> struct ansi_color_escape {
out[2] = static_cast<Char>('0' + c % 10);
out[3] = static_cast<Char>(delimiter);
}
static FMT_CONSTEXPR bool has_emphasis(emphasis em,
emphasis mask) FMT_NOEXCEPT {
return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask);
}
};
template <typename Char>
@@ -463,26 +474,27 @@ FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT {
return ansi_color_escape<Char>(em);
}
template <typename Char>
inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT {
std::fputs(chars, stream);
template <typename Char> inline void fputs(const Char* chars, FILE* stream) {
int result = std::fputs(chars, stream);
if (result < 0)
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
}
template <>
inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {
std::fputws(chars, stream);
template <> inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) {
int result = std::fputws(chars, stream);
if (result < 0)
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
}
template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
template <typename Char> inline void reset_color(FILE* stream) {
fputs("\x1b[0m", stream);
}
template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
template <> inline void reset_color<wchar_t>(FILE* stream) {
fputs(L"\x1b[0m", stream);
}
template <typename Char>
inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT {
template <typename Char> inline void reset_color(buffer<Char>& buffer) {
auto reset_color = string_view("\x1b[0m");
buffer.append(reset_color.begin(), reset_color.end());
}
@@ -518,8 +530,12 @@ void vprint(std::FILE* f, const text_style& ts, const S& format,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buf;
detail::vformat_to(buf, ts, to_string_view(format), args);
buf.push_back(Char(0));
detail::fputs(buf.data(), f);
if (detail::is_utf8()) {
detail::print(f, basic_string_view<Char>(buf.begin(), buf.size()));
} else {
buf.push_back(Char(0));
detail::fputs(buf.data(), f);
}
}
/**
+14 -11
View File
@@ -156,7 +156,7 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {};
std::string s = fmt::format(FMT_COMPILE("{}"), 42);
\endrst
*/
#ifdef __cpp_if_constexpr
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
# define FMT_COMPILE(s) \
FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit)
#else
@@ -179,7 +179,7 @@ const T& first(const T& value, const Tail&...) {
return value;
}
#ifdef __cpp_if_constexpr
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
template <typename... Args> struct type_list {};
// Returns a reference to the argument at index N from [first, rest...].
@@ -190,7 +190,7 @@ constexpr const auto& get([[maybe_unused]] const T& first,
if constexpr (N == 0)
return first;
else
return get<N - 1>(rest...);
return detail::get<N - 1>(rest...);
}
template <typename Char, typename... Args>
@@ -202,7 +202,8 @@ constexpr int get_arg_index_by_name(basic_string_view<Char> name,
template <int N, typename> struct get_type_impl;
template <int N, typename... Args> struct get_type_impl<N, type_list<Args...>> {
using type = remove_cvref_t<decltype(get<N>(std::declval<Args>()...))>;
using type =
remove_cvref_t<decltype(detail::get<N>(std::declval<Args>()...))>;
};
template <int N, typename T>
@@ -242,7 +243,7 @@ template <typename Char> struct code_unit {
// This ensures that the argument type is convertible to `const T&`.
template <typename T, int N, typename... Args>
constexpr const T& get_arg_checked(const Args&... args) {
const auto& arg = get<N>(args...);
const auto& arg = detail::get<N>(args...);
if constexpr (detail::is_named_arg<remove_cvref_t<decltype(arg)>>()) {
return arg.value;
} else {
@@ -289,7 +290,7 @@ template <typename Char> struct runtime_named_field {
constexpr OutputIt format(OutputIt out, const Args&... args) const {
bool found = (try_format_argument(out, name, args) || ...);
if (!found) {
throw format_error("argument with specified name is not found");
FMT_THROW(format_error("argument with specified name is not found"));
}
return out;
}
@@ -399,7 +400,9 @@ template <typename Char> struct arg_id_handler {
return 0;
}
constexpr void on_error(const char* message) { throw format_error(message); }
constexpr void on_error(const char* message) {
FMT_THROW(format_error(message));
}
};
template <typename Char> struct parse_arg_id_result {
@@ -451,7 +454,7 @@ constexpr auto compile_format_string(S format_str) {
constexpr auto str = basic_string_view<char_type>(format_str);
if constexpr (str[POS] == '{') {
if constexpr (POS + 1 == str.size())
throw format_error("unmatched '{' in format string");
FMT_THROW(format_error("unmatched '{' in format string"));
if constexpr (str[POS + 1] == '{') {
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
} else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') {
@@ -500,7 +503,7 @@ constexpr auto compile_format_string(S format_str) {
}
} else if constexpr (str[POS] == '}') {
if constexpr (POS + 1 == str.size())
throw format_error("unmatched '}' in format string");
FMT_THROW(format_error("unmatched '}' in format string"));
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
} else {
constexpr auto end = parse_text(str, POS + 1);
@@ -527,12 +530,12 @@ constexpr auto compile(S format_str) {
return result;
}
}
#endif // __cpp_if_constexpr
#endif // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
} // namespace detail
FMT_MODULE_EXPORT_BEGIN
#ifdef __cpp_if_constexpr
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
template <typename CompiledFormat, typename... Args,
typename Char = typename CompiledFormat::char_type,
+491 -275
View File
File diff suppressed because it is too large Load Diff
+309 -285
View File
@@ -40,6 +40,10 @@ FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
std::terminate();
}
FMT_FUNC void throw_format_error(const char* message) {
FMT_THROW(format_error(message));
}
#ifndef _MSC_VER
# define FMT_SNPRINTF snprintf
#else // _MSC_VER
@@ -145,141 +149,13 @@ template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {
return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1;
}
#if __cplusplus < 201703L
template <typename T> constexpr const char basic_data<T>::digits[][2];
template <typename T> constexpr const char basic_data<T>::hex_digits[];
template <typename T> constexpr const char basic_data<T>::signs[];
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
template <typename T> constexpr const char basic_data<T>::left_padding_shifts[];
template <typename T>
constexpr const char basic_data<T>::right_padding_shifts[];
#endif
// log10(2) = 0x0.4d104d427de7fbcc...
static constexpr uint64_t log10_2_significand = 0x4d104d427de7fbcc;
template <typename T> struct bits {
static FMT_CONSTEXPR_DECL const int value =
static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits);
};
class fp;
template <int SHIFT = 0> fp normalize(fp value);
// Lower (upper) boundary is a value half way between a floating-point value
// and its predecessor (successor). Boundaries have the same exponent as the
// value so only significands are stored.
struct boundaries {
uint64_t lower;
uint64_t upper;
};
// A handmade floating-point number f * pow(2, e).
class fp {
private:
using significand_type = uint64_t;
template <typename Float>
using is_supported_float = bool_constant<sizeof(Float) == sizeof(uint64_t) ||
sizeof(Float) == sizeof(uint32_t)>;
public:
significand_type f;
int e;
// All sizes are in bits.
// Subtract 1 to account for an implicit most significant bit in the
// normalized form.
static FMT_CONSTEXPR_DECL const int double_significand_size =
std::numeric_limits<double>::digits - 1;
static FMT_CONSTEXPR_DECL const uint64_t implicit_bit =
1ULL << double_significand_size;
static FMT_CONSTEXPR_DECL const int significand_size =
bits<significand_type>::value;
fp() : f(0), e(0) {}
fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
// Constructs fp from an IEEE754 double. It is a template to prevent compile
// errors on platforms where double is not IEEE754.
template <typename Double> explicit fp(Double d) { assign(d); }
// Assigns d to this and return true iff predecessor is closer than successor.
template <typename Float, FMT_ENABLE_IF(is_supported_float<Float>::value)>
bool assign(Float d) {
// Assume float is in the format [sign][exponent][significand].
using limits = std::numeric_limits<Float>;
const int float_significand_size = limits::digits - 1;
const int exponent_size =
bits<Float>::value - float_significand_size - 1; // -1 for sign
const uint64_t float_implicit_bit = 1ULL << float_significand_size;
const uint64_t significand_mask = float_implicit_bit - 1;
const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask;
const int exponent_bias = (1 << exponent_size) - limits::max_exponent - 1;
constexpr bool is_double = sizeof(Float) == sizeof(uint64_t);
auto u = bit_cast<conditional_t<is_double, uint64_t, uint32_t>>(d);
f = u & significand_mask;
int biased_e =
static_cast<int>((u & exponent_mask) >> float_significand_size);
// Predecessor is closer if d is a normalized power of 2 (f == 0) other than
// the smallest normalized number (biased_e > 1).
bool is_predecessor_closer = f == 0 && biased_e > 1;
if (biased_e != 0)
f += float_implicit_bit;
else
biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
e = biased_e - exponent_bias - float_significand_size;
return is_predecessor_closer;
}
template <typename Float, FMT_ENABLE_IF(!is_supported_float<Float>::value)>
bool assign(Float) {
*this = fp();
return false;
}
};
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
template <int SHIFT> fp normalize(fp value) {
// Handle subnormals.
const auto shifted_implicit_bit = fp::implicit_bit << SHIFT;
while ((value.f & shifted_implicit_bit) == 0) {
value.f <<= 1;
--value.e;
}
// Subtract 1 to account for hidden bit.
const auto offset =
fp::significand_size - fp::double_significand_size - SHIFT - 1;
value.f <<= offset;
value.e -= offset;
return value;
}
inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; }
// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
#if FMT_USE_INT128
auto product = static_cast<__uint128_t>(lhs) * rhs;
auto f = static_cast<uint64_t>(product >> 64);
return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
#else
// Multiply 32-bit parts of significands.
uint64_t mask = (1ULL << 32) - 1;
uint64_t a = lhs >> 32, b = lhs & mask;
uint64_t c = rhs >> 32, d = rhs & mask;
uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
// Compute mid 64-bit of result and round.
uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
#endif
}
inline fp operator*(fp x, fp y) { return {multiply(x.f, y.f), x.e + y.e + 64}; }
// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
inline fp get_cached_power(int min_exponent, int& pow10_exponent) {
template <typename T = void> struct basic_impl_data {
// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
// These are generated by support/compute-powers.py.
static constexpr const uint64_t pow10_significands[] = {
static constexpr uint64_t pow10_significands[87] = {
0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
@@ -311,9 +187,13 @@ inline fp get_cached_power(int min_exponent, int& pow10_exponent) {
0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
};
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnarrowing"
#endif
// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
// to significands above.
static constexpr const int16_t pow10_exponents[] = {
static constexpr int16_t pow10_exponents[87] = {
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
-927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
-635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
@@ -322,11 +202,137 @@ inline fp get_cached_power(int min_exponent, int& pow10_exponent) {
242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
# pragma GCC diagnostic pop
#endif
static constexpr uint64_t power_of_10_64[20] = {
1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL),
10000000000000000000ULL};
};
// This is a struct rather than an alias to avoid shadowing warnings in gcc.
struct impl_data : basic_impl_data<> {};
#if __cplusplus < 201703L
template <typename T>
constexpr uint64_t basic_impl_data<T>::pow10_significands[];
template <typename T> constexpr int16_t basic_impl_data<T>::pow10_exponents[];
template <typename T> constexpr uint64_t basic_impl_data<T>::power_of_10_64[];
#endif
template <typename T> struct bits {
static FMT_CONSTEXPR_DECL const int value =
static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits);
};
// Returns the number of significand bits in Float excluding the implicit bit.
template <typename Float> constexpr int num_significand_bits() {
// Subtract 1 to account for an implicit most significant bit in the
// normalized form.
return std::numeric_limits<Float>::digits - 1;
}
// A floating-point number f * pow(2, e).
struct fp {
uint64_t f;
int e;
static constexpr const int num_significand_bits = bits<decltype(f)>::value;
constexpr fp() : f(0), e(0) {}
constexpr fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
// Constructs fp from an IEEE754 floating-point number. It is a template to
// prevent compile errors on systems where n is not IEEE754.
template <typename Float> explicit FMT_CONSTEXPR fp(Float n) { assign(n); }
template <typename Float>
using is_supported = bool_constant<sizeof(Float) == sizeof(uint64_t) ||
sizeof(Float) == sizeof(uint32_t)>;
// Assigns d to this and return true iff predecessor is closer than successor.
template <typename Float, FMT_ENABLE_IF(is_supported<Float>::value)>
FMT_CONSTEXPR bool assign(Float n) {
// Assume float is in the format [sign][exponent][significand].
const int num_float_significand_bits =
detail::num_significand_bits<Float>();
const uint64_t implicit_bit = 1ULL << num_float_significand_bits;
const uint64_t significand_mask = implicit_bit - 1;
constexpr bool is_double = sizeof(Float) == sizeof(uint64_t);
auto u = bit_cast<conditional_t<is_double, uint64_t, uint32_t>>(n);
f = u & significand_mask;
const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask;
int biased_e =
static_cast<int>((u & exponent_mask) >> num_float_significand_bits);
// The predecessor is closer if n is a normalized power of 2 (f == 0) other
// than the smallest normalized number (biased_e > 1).
bool is_predecessor_closer = f == 0 && biased_e > 1;
if (biased_e != 0)
f += implicit_bit;
else
biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
const int exponent_bias = std::numeric_limits<Float>::max_exponent - 1;
e = biased_e - exponent_bias - num_float_significand_bits;
return is_predecessor_closer;
}
template <typename Float, FMT_ENABLE_IF(!is_supported<Float>::value)>
bool assign(Float) {
FMT_ASSERT(false, "");
return false;
}
};
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
template <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) {
// Handle subnormals.
const uint64_t implicit_bit = 1ULL << num_significand_bits<double>();
const auto shifted_implicit_bit = implicit_bit << SHIFT;
while ((value.f & shifted_implicit_bit) == 0) {
value.f <<= 1;
--value.e;
}
// Subtract 1 to account for hidden bit.
const auto offset =
fp::num_significand_bits - num_significand_bits<double>() - SHIFT - 1;
value.f <<= offset;
value.e -= offset;
return value;
}
inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; }
// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
#if FMT_USE_INT128
auto product = static_cast<__uint128_t>(lhs) * rhs;
auto f = static_cast<uint64_t>(product >> 64);
return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
#else
// Multiply 32-bit parts of significands.
uint64_t mask = (1ULL << 32) - 1;
uint64_t a = lhs >> 32, b = lhs & mask;
uint64_t c = rhs >> 32, d = rhs & mask;
uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
// Compute mid 64-bit of result and round.
uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
#endif
}
FMT_CONSTEXPR inline fp operator*(fp x, fp y) {
return {multiply(x.f, y.f), x.e + y.e + 64};
}
// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
FMT_CONSTEXPR inline fp get_cached_power(int min_exponent,
int& pow10_exponent) {
const int shift = 32;
const auto significand = static_cast<int64_t>(data::log10_2_significand);
const auto significand = static_cast<int64_t>(log10_2_significand);
int index = static_cast<int>(
((min_exponent + fp::significand_size - 1) * (significand >> shift) +
((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) +
((int64_t(1) << shift) - 1)) // ceil
>> 32 // arithmetic shift
);
@@ -336,7 +342,8 @@ inline fp get_cached_power(int min_exponent, int& pow10_exponent) {
const int dec_exp_step = 8;
index = (index - first_dec_exp - 1) / dec_exp_step + 1;
pow10_exponent = first_dec_exp + index * dec_exp_step;
return {pow10_significands[index], pow10_exponents[index]};
return {impl_data::pow10_significands[index],
impl_data::pow10_exponents[index]};
}
// A simple accumulator to hold the sums of terms in bigint::square if uint128_t
@@ -345,14 +352,16 @@ struct accumulator {
uint64_t lower;
uint64_t upper;
accumulator() : lower(0), upper(0) {}
explicit operator uint32_t() const { return static_cast<uint32_t>(lower); }
constexpr accumulator() : lower(0), upper(0) {}
constexpr explicit operator uint32_t() const {
return static_cast<uint32_t>(lower);
}
void operator+=(uint64_t n) {
FMT_CONSTEXPR void operator+=(uint64_t n) {
lower += n;
if (lower < n) ++upper;
}
void operator>>=(int shift) {
FMT_CONSTEXPR void operator>>=(int shift) {
FMT_ASSERT(shift == 32, "");
(void)shift;
lower = (upper << 32) | (lower >> 32);
@@ -370,27 +379,31 @@ class bigint {
basic_memory_buffer<bigit, bigits_capacity> bigits_;
int exp_;
bigit operator[](int index) const { return bigits_[to_unsigned(index)]; }
bigit& operator[](int index) { return bigits_[to_unsigned(index)]; }
FMT_CONSTEXPR20 bigit operator[](int index) const {
return bigits_[to_unsigned(index)];
}
FMT_CONSTEXPR20 bigit& operator[](int index) {
return bigits_[to_unsigned(index)];
}
static FMT_CONSTEXPR_DECL const int bigit_bits = bits<bigit>::value;
friend struct formatter<bigint>;
void subtract_bigits(int index, bigit other, bigit& borrow) {
FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {
auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;
(*this)[index] = static_cast<bigit>(result);
borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
}
void remove_leading_zeros() {
FMT_CONSTEXPR20 void remove_leading_zeros() {
int num_bigits = static_cast<int>(bigits_.size()) - 1;
while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;
bigits_.resize(to_unsigned(num_bigits + 1));
}
// Computes *this -= other assuming aligned bigints and *this >= other.
void subtract_aligned(const bigint& other) {
FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {
FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
FMT_ASSERT(compare(*this, other) >= 0, "");
bigit borrow = 0;
@@ -401,7 +414,7 @@ class bigint {
remove_leading_zeros();
}
void multiply(uint32_t value) {
FMT_CONSTEXPR20 void multiply(uint32_t value) {
const double_bigit wide_value = value;
bigit carry = 0;
for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
@@ -412,7 +425,7 @@ class bigint {
if (carry != 0) bigits_.push_back(carry);
}
void multiply(uint64_t value) {
FMT_CONSTEXPR20 void multiply(uint64_t value) {
const bigit mask = ~bigit(0);
const double_bigit lower = value & mask;
const double_bigit upper = value >> bigit_bits;
@@ -430,14 +443,16 @@ class bigint {
}
public:
bigint() : exp_(0) {}
FMT_CONSTEXPR20 bigint() : exp_(0) {}
explicit bigint(uint64_t n) { assign(n); }
~bigint() { FMT_ASSERT(bigits_.capacity() <= bigits_capacity, ""); }
FMT_CONSTEXPR20 ~bigint() {
FMT_ASSERT(bigits_.capacity() <= bigits_capacity, "");
}
bigint(const bigint&) = delete;
void operator=(const bigint&) = delete;
void assign(const bigint& other) {
FMT_CONSTEXPR20 void assign(const bigint& other) {
auto size = other.bigits_.size();
bigits_.resize(size);
auto data = other.bigits_.data();
@@ -445,7 +460,7 @@ class bigint {
exp_ = other.exp_;
}
void assign(uint64_t n) {
FMT_CONSTEXPR20 void assign(uint64_t n) {
size_t num_bigits = 0;
do {
bigits_[num_bigits++] = n & ~bigit(0);
@@ -455,9 +470,11 @@ class bigint {
exp_ = 0;
}
int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; }
FMT_CONSTEXPR20 int num_bigits() const {
return static_cast<int>(bigits_.size()) + exp_;
}
FMT_NOINLINE bigint& operator<<=(int shift) {
FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) {
FMT_ASSERT(shift >= 0, "");
exp_ += shift / bigit_bits;
shift %= bigit_bits;
@@ -472,13 +489,13 @@ class bigint {
return *this;
}
template <typename Int> bigint& operator*=(Int value) {
template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) {
FMT_ASSERT(value > 0, "");
multiply(uint32_or_64_or_128_t<Int>(value));
return *this;
}
friend int compare(const bigint& lhs, const bigint& rhs) {
friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) {
int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
if (num_lhs_bigits != num_rhs_bigits)
return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
@@ -495,8 +512,8 @@ class bigint {
}
// Returns compare(lhs1 + lhs2, rhs).
friend int add_compare(const bigint& lhs1, const bigint& lhs2,
const bigint& rhs) {
friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2,
const bigint& rhs) {
int max_lhs_bigits = (std::max)(lhs1.num_bigits(), lhs2.num_bigits());
int num_rhs_bigits = rhs.num_bigits();
if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
@@ -519,7 +536,7 @@ class bigint {
}
// Assigns pow(10, exp) to this bigint.
void assign_pow10(int exp) {
FMT_CONSTEXPR20 void assign_pow10(int exp) {
FMT_ASSERT(exp >= 0, "");
if (exp == 0) return assign(1);
// Find the top bit.
@@ -538,7 +555,7 @@ class bigint {
*this <<= exp; // Multiply by pow(2, exp) by shifting.
}
void square() {
FMT_CONSTEXPR20 void square() {
int num_bigits = static_cast<int>(bigits_.size());
int num_result_bigits = 2 * num_bigits;
basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
@@ -569,7 +586,7 @@ class bigint {
// If this bigint has a bigger exponent than other, adds trailing zero to make
// exponents equal. This simplifies some operations such as subtraction.
void align(const bigint& other) {
FMT_CONSTEXPR20 void align(const bigint& other) {
int exp_difference = exp_ - other.exp_;
if (exp_difference <= 0) return;
int num_bigits = static_cast<int>(bigits_.size());
@@ -582,7 +599,7 @@ class bigint {
// Divides this bignum by divisor, assigning the remainder to this and
// returning the quotient.
int divmod_assign(const bigint& divisor) {
FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) {
FMT_ASSERT(this != &divisor, "");
if (compare(*this, divisor) < 0) return 0;
FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
@@ -602,8 +619,9 @@ enum class round_direction { unknown, up, down };
// some number v and the error, returns whether v should be rounded up, down, or
// whether the rounding direction can't be determined due to error.
// error should be less than divisor / 2.
inline round_direction get_round_direction(uint64_t divisor, uint64_t remainder,
uint64_t error) {
FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor,
uint64_t remainder,
uint64_t error) {
FMT_ASSERT(remainder < divisor, ""); // divisor - remainder won't overflow.
FMT_ASSERT(error < divisor, ""); // divisor - error won't overflow.
FMT_ASSERT(error < divisor - error, ""); // error * 2 won't overflow.
@@ -626,19 +644,52 @@ enum result {
};
}
inline uint64_t power_of_10_64(int exp) {
static constexpr const uint64_t data[] = {1, FMT_POWERS_OF_10(1),
FMT_POWERS_OF_10(1000000000ULL),
10000000000000000000ULL};
return data[exp];
}
struct gen_digits_handler {
char* buf;
int size;
int precision;
int exp10;
bool fixed;
FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor,
uint64_t remainder, uint64_t error,
bool integral) {
FMT_ASSERT(remainder < divisor, "");
buf[size++] = digit;
if (!integral && error >= remainder) return digits::error;
if (size < precision) return digits::more;
if (!integral) {
// Check if error * 2 < divisor with overflow prevention.
// The check is not needed for the integral part because error = 1
// and divisor > (1 << 32) there.
if (error >= divisor || error >= divisor - error) return digits::error;
} else {
FMT_ASSERT(error == 1 && divisor > 2, "");
}
auto dir = get_round_direction(divisor, remainder, error);
if (dir != round_direction::up)
return dir == round_direction::down ? digits::done : digits::error;
++buf[size - 1];
for (int i = size - 1; i > 0 && buf[i] > '9'; --i) {
buf[i] = '0';
++buf[i - 1];
}
if (buf[0] > '9') {
buf[0] = '1';
if (fixed)
buf[size++] = '0';
else
++exp10;
}
return digits::done;
}
};
// Generates output using the Grisu digit-gen algorithm.
// error: the size of the region (lower, upper) outside of which numbers
// definitely do not round to value (Delta in Grisu3).
template <typename Handler>
FMT_INLINE digits::result grisu_gen_digits(fp value, uint64_t error, int& exp,
Handler& handler) {
FMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits(
fp value, uint64_t error, int& exp, gen_digits_handler& handler) {
const fp one(1ULL << -value.e, value.e);
// The integral part of scaled value (p1 in Grisu) = value / one. It cannot be
// zero because it contains a product of two 64-bit numbers with MSB set (due
@@ -649,10 +700,28 @@ FMT_INLINE digits::result grisu_gen_digits(fp value, uint64_t error, int& exp,
// The fractional part of scaled value (p2 in Grisu) c = value % one.
uint64_t fractional = value.f & (one.f - 1);
exp = count_digits(integral); // kappa in Grisu.
// Divide by 10 to prevent overflow.
auto result = handler.on_start(power_of_10_64(exp - 1) << -one.e,
value.f / 10, error * 10, exp);
if (result != digits::more) return result;
// Non-fixed formats require at least one digit and no precision adjustment.
if (handler.fixed) {
// Adjust fixed precision by exponent because it is relative to decimal
// point.
int precision_offset = exp + handler.exp10;
if (precision_offset > 0 &&
handler.precision > max_value<int>() - precision_offset) {
FMT_THROW(format_error("number is too big"));
}
handler.precision += precision_offset;
// Check if precision is satisfied just by leading zeros, e.g.
// format("{:.2f}", 0.001) gives "0.00" without generating any digits.
if (handler.precision <= 0) {
if (handler.precision < 0) return digits::done;
// Divide by 10 to prevent overflow.
uint64_t divisor = impl_data::power_of_10_64[exp - 1] << -one.e;
auto dir = get_round_direction(divisor, value.f / 10, error * 10);
if (dir == round_direction::unknown) return digits::error;
handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0';
return digits::done;
}
}
// Generate digits for the integral part. This can produce up to 10 digits.
do {
uint32_t digit = 0;
@@ -699,9 +768,9 @@ FMT_INLINE digits::result grisu_gen_digits(fp value, uint64_t error, int& exp,
}
--exp;
auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional;
result = handler.on_digit(static_cast<char>('0' + digit),
power_of_10_64(exp) << -one.e, remainder, error,
exp, true);
auto result = handler.on_digit(static_cast<char>('0' + digit),
impl_data::power_of_10_64[exp] << -one.e,
remainder, error, true);
if (result != digits::more) return result;
} while (exp > 0);
// Generate digits for the fractional part.
@@ -711,69 +780,11 @@ FMT_INLINE digits::result grisu_gen_digits(fp value, uint64_t error, int& exp,
char digit = static_cast<char>('0' + (fractional >> -one.e));
fractional &= one.f - 1;
--exp;
result = handler.on_digit(digit, one.f, fractional, error, exp, false);
auto result = handler.on_digit(digit, one.f, fractional, error, false);
if (result != digits::more) return result;
}
}
// The fixed precision digit handler.
struct fixed_handler {
char* buf;
int size;
int precision;
int exp10;
bool fixed;
digits::result on_start(uint64_t divisor, uint64_t remainder, uint64_t error,
int& exp) {
// Non-fixed formats require at least one digit and no precision adjustment.
if (!fixed) return digits::more;
// Adjust fixed precision by exponent because it is relative to decimal
// point.
precision += exp + exp10;
// Check if precision is satisfied just by leading zeros, e.g.
// format("{:.2f}", 0.001) gives "0.00" without generating any digits.
if (precision > 0) return digits::more;
if (precision < 0) return digits::done;
auto dir = get_round_direction(divisor, remainder, error);
if (dir == round_direction::unknown) return digits::error;
buf[size++] = dir == round_direction::up ? '1' : '0';
return digits::done;
}
digits::result on_digit(char digit, uint64_t divisor, uint64_t remainder,
uint64_t error, int, bool integral) {
FMT_ASSERT(remainder < divisor, "");
buf[size++] = digit;
if (!integral && error >= remainder) return digits::error;
if (size < precision) return digits::more;
if (!integral) {
// Check if error * 2 < divisor with overflow prevention.
// The check is not needed for the integral part because error = 1
// and divisor > (1 << 32) there.
if (error >= divisor || error >= divisor - error) return digits::error;
} else {
FMT_ASSERT(error == 1 && divisor > 2, "");
}
auto dir = get_round_direction(divisor, remainder, error);
if (dir != round_direction::up)
return dir == round_direction::down ? digits::done : digits::error;
++buf[size - 1];
for (int i = size - 1; i > 0 && buf[i] > '9'; --i) {
buf[i] = '0';
++buf[i - 1];
}
if (buf[0] > '9') {
buf[0] = '1';
if (fixed)
buf[size++] = '0';
else
++exp10;
}
return digits::done;
}
};
// A 128-bit integer type used internally,
struct uint128_wrapper {
uint128_wrapper() = default;
@@ -896,9 +907,9 @@ inline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT {
// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4.
inline int floor_log10_pow2(int e) FMT_NOEXCEPT {
FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
const int shift = 22;
return (e * static_cast<int>(data::log10_2_significand >> (64 - shift))) >>
shift;
return (e * static_cast<int>(log10_2_significand >> (64 - shift))) >> shift;
}
// Various fast log computations.
@@ -916,8 +927,7 @@ inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT {
FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375;
const int shift_amount = 22;
return (e * static_cast<int>(data::log10_2_significand >>
(64 - shift_amount)) -
return (e * static_cast<int>(log10_2_significand >> (64 - shift_amount)) -
static_cast<int>(log10_4_over_3_fractional_digits >>
(64 - shift_amount))) >>
shift_amount;
@@ -1042,7 +1052,7 @@ template <> struct cache_accessor<float> {
static uint64_t get_cached_power(int k) FMT_NOEXCEPT {
FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k,
"k is out of range");
constexpr const uint64_t pow10_significands[] = {
static constexpr const uint64_t pow10_significands[] = {
0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f,
0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb,
0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28,
@@ -2210,24 +2220,21 @@ small_divisor_case_label:
}
} // namespace dragonbox
// Formats value using a variation of the Fixed-Precision Positive
// Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
// Formats a floating-point number using a variation of the Fixed-Precision
// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
// https://fmt.dev/papers/p372-steele.pdf.
template <typename Double>
void fallback_format(Double d, int num_digits, bool binary32, buffer<char>& buf,
int& exp10) {
FMT_CONSTEXPR20 inline void format_dragon(fp value, bool is_predecessor_closer,
int num_digits, buffer<char>& buf,
int& exp10) {
bigint numerator; // 2 * R in (FPP)^2.
bigint denominator; // 2 * S in (FPP)^2.
// lower and upper are differences between value and corresponding boundaries.
bigint lower; // (M^- in (FPP)^2).
bigint upper_store; // upper's value if different from lower.
bigint* upper = nullptr; // (M^+ in (FPP)^2).
fp value;
// Shift numerator and denominator by an extra bit or two (if lower boundary
// is closer) to make lower and upper integers. This eliminates multiplication
// by 2 during later computations.
const bool is_predecessor_closer =
binary32 ? value.assign(static_cast<float>(d)) : value.assign(d);
int shift = is_predecessor_closer ? 2 : 1;
uint64_t significand = value.f << shift;
if (value.e >= 0) {
@@ -2297,9 +2304,9 @@ void fallback_format(Double d, int num_digits, bool binary32, buffer<char>& buf,
// Generate the given number of digits.
exp10 -= num_digits - 1;
if (num_digits == 0) {
buf.try_resize(1);
denominator *= 10;
buf[0] = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
buf.push_back(digit);
return;
}
buf.try_resize(to_unsigned(num_digits));
@@ -2330,9 +2337,12 @@ void fallback_format(Double d, int num_digits, bool binary32, buffer<char>& buf,
buf[num_digits - 1] = static_cast<char>('0' + digit);
}
template <typename T>
int format_float(T value, int precision, float_specs specs, buffer<char>& buf) {
static_assert(!std::is_same<T, float>::value, "");
template <typename Float>
FMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision,
float_specs specs,
buffer<char>& buf) {
// float is passed as double to reduce the number of instantiations.
static_assert(!std::is_same<Float, float>::value, "");
FMT_ASSERT(value >= 0, "value is negative");
const bool fixed = specs.format == float_format::fixed;
@@ -2342,13 +2352,13 @@ int format_float(T value, int precision, float_specs specs, buffer<char>& buf) {
return 0;
}
buf.try_resize(to_unsigned(precision));
std::uninitialized_fill_n(buf.data(), precision, '0');
fill_n(buf.data(), precision, '0');
return -precision;
}
if (!specs.use_grisu) return snprintf_float(value, precision, specs, buf);
if (specs.fallback) return snprintf_float(value, precision, specs, buf);
if (precision < 0) {
if (!is_constant_evaluated() && precision < 0) {
// Use Dragonbox for the shortest format.
if (specs.binary32) {
auto dec = dragonbox::to_decimal(static_cast<float>(value));
@@ -2360,26 +2370,37 @@ int format_float(T value, int precision, float_specs specs, buffer<char>& buf) {
return dec.exponent;
}
// Use Grisu + Dragon4 for the given precision:
// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf.
int exp = 0;
const int min_exp = -60; // alpha in Grisu.
int cached_exp10 = 0; // K in Grisu.
fp normalized = normalize(fp(value));
const auto cached_pow = get_cached_power(
min_exp - (normalized.e + fp::significand_size), cached_exp10);
normalized = normalized * cached_pow;
// Limit precision to the maximum possible number of significant digits in an
// IEEE754 double because we don't need to generate zeros.
const int max_double_digits = 767;
if (precision > max_double_digits) precision = max_double_digits;
fixed_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};
if (grisu_gen_digits(normalized, 1, exp, handler) == digits::error) {
exp += handler.size - cached_exp10 - 1;
fallback_format(value, handler.precision, specs.binary32, buf, exp);
} else {
exp += handler.exp10;
buf.try_resize(to_unsigned(handler.size));
bool use_dragon = true;
if (is_fast_float<Float>()) {
// Use Grisu + Dragon4 for the given precision:
// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf.
const int min_exp = -60; // alpha in Grisu.
int cached_exp10 = 0; // K in Grisu.
fp normalized = normalize(fp(value));
const auto cached_pow = get_cached_power(
min_exp - (normalized.e + fp::num_significand_bits), cached_exp10);
normalized = normalized * cached_pow;
gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};
if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error &&
!is_constant_evaluated()) {
exp += handler.exp10;
buf.try_resize(to_unsigned(handler.size));
use_dragon = false;
} else {
exp += handler.size - cached_exp10 - 1;
precision = handler.precision;
}
}
if (use_dragon) {
auto f = fp();
bool is_predecessor_closer =
specs.binary32 ? f.assign(static_cast<float>(value)) : f.assign(value);
// Limit precision to the maximum possible number of significant digits in
// an IEEE754 double because we don't need to generate zeros.
const int max_double_digits = 767;
if (precision > max_double_digits) precision = max_double_digits;
format_dragon(f, is_predecessor_closer, precision, buf, exp);
}
if (!fixed && !specs.showpoint) {
// Remove trailing zeros.
@@ -2391,7 +2412,7 @@ int format_float(T value, int precision, float_specs specs, buffer<char>& buf) {
buf.try_resize(num_digits);
}
return exp;
} // namespace detail
}
template <typename T>
int snprintf_float(T value, int precision, float_specs specs,
@@ -2525,8 +2546,8 @@ template <> struct formatter<detail::bigint> {
};
FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
for_each_codepoint(s, [this](uint32_t cp, int error) {
if (error != 0) FMT_THROW(std::runtime_error("invalid utf8"));
for_each_codepoint(s, [this](uint32_t cp, string_view) {
if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8"));
if (cp <= 0xFFFF) {
buffer_.push_back(static_cast<wchar_t>(cp));
} else {
@@ -2534,6 +2555,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10)));
buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF)));
}
return true;
});
buffer_.push_back(0);
}
@@ -2549,15 +2571,17 @@ FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
format_error_code(out, error_code, message);
}
FMT_FUNC void detail::error_handler::on_error(const char* message) {
FMT_THROW(format_error(message));
}
FMT_FUNC void report_system_error(int error_code,
const char* message) FMT_NOEXCEPT {
report_error(format_system_error, error_code, message);
}
// DEPRECATED!
// This function is defined here and not inline for ABI compatiblity.
FMT_FUNC void detail::error_handler::on_error(const char* message) {
throw_format_error(message);
}
FMT_FUNC std::string vformat(string_view fmt, format_args args) {
// Don't optimize the "{}" case to keep the binary size small and because it
// can be better optimized in fmt::format anyway.
+592 -318
View File
File diff suppressed because it is too large Load Diff
+31 -18
View File
@@ -21,17 +21,20 @@
#include "format.h"
#ifndef FMT_USE_FCNTL
// UWP doesn't provide _pipe.
#if FMT_HAS_INCLUDE("winapifamily.h")
# include <winapifamily.h>
#endif
#if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
defined(__linux__)) && \
(!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
# include <fcntl.h> // for O_RDONLY
# define FMT_USE_FCNTL 1
#else
# define FMT_USE_FCNTL 0
# if FMT_HAS_INCLUDE("winapifamily.h")
# include <winapifamily.h>
# endif
# if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
defined(__linux__)) && \
(!defined(WINAPI_FAMILY) || \
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
# include <fcntl.h> // for O_RDONLY
# define FMT_USE_FCNTL 1
# else
# define FMT_USE_FCNTL 0
# endif
#endif
#ifndef FMT_POSIX
@@ -262,6 +265,7 @@ class buffered_file {
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
// DEPRECATED! Rename to descriptor to avoid issues with macros.
FMT_API int(fileno)() const;
void vprint(string_view format_str, format_args args) {
@@ -390,23 +394,26 @@ struct ostream_params {
: ostream_params(params...) {
this->buffer_size = bs.value;
}
// Intel has a bug that results in failure to deduce a constructor
// for empty parameter packs.
# if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000
ostream_params(int new_oflag) : oflag(new_oflag) {}
ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}
# endif
};
FMT_END_DETAIL_NAMESPACE
constexpr detail::buffer_size buffer_size;
// Added {} below to work around default constructor error known to
// occur in Xcode versions 7.2.1 and 8.2.1.
constexpr detail::buffer_size buffer_size{};
/** A fast output stream which is not thread-safe. */
class FMT_API ostream final : private detail::buffer<char> {
private:
file file_;
void flush() {
if (size() == 0) return;
file_.write(data(), size());
clear();
}
void grow(size_t) override;
ostream(cstring_view path, const detail::ostream_params& params)
@@ -426,6 +433,12 @@ class FMT_API ostream final : private detail::buffer<char> {
delete[] data();
}
void flush() {
if (size() == 0) return;
file_.write(data(), size());
clear();
}
template <typename... T>
friend ostream output_file(cstring_view path, T... params);
@@ -500,7 +513,7 @@ class locale {
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double strtod(const char*& str) const {
FMT_DEPRECATED double strtod(const char*& str) const {
char* end = nullptr;
double result = strtod_l(str, &end, locale_);
str = end;
+33 -79
View File
@@ -14,73 +14,20 @@
FMT_BEGIN_NAMESPACE
template <typename Char> class basic_printf_parse_context;
template <typename OutputIt, typename Char> class basic_printf_context;
namespace detail {
template <class Char> class formatbuf : public std::basic_streambuf<Char> {
private:
using int_type = typename std::basic_streambuf<Char>::int_type;
using traits_type = typename std::basic_streambuf<Char>::traits_type;
buffer<Char>& buffer_;
public:
formatbuf(buffer<Char>& buf) : buffer_(buf) {}
protected:
// The put-area is actually always empty. This makes the implementation
// simpler and has the advantage that the streambuf and the buffer are always
// in sync and sputc never writes into uninitialized memory. The obvious
// disadvantage is that each call to sputc always results in a (virtual) call
// to overflow. There is no disadvantage here for sputn since this always
// results in a call to xsputn.
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
if (!traits_type::eq_int_type(ch, traits_type::eof()))
buffer_.push_back(static_cast<Char>(ch));
return ch;
}
std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE {
buffer_.append(s, s + count);
return count;
}
};
struct converter {
template <typename T, FMT_ENABLE_IF(is_integral<T>::value)> converter(T);
};
template <typename Char> struct test_stream : std::basic_ostream<Char> {
private:
void_t<> operator<<(converter);
};
// Hide insertion operators for built-in types.
template <typename Char, typename Traits>
void_t<> operator<<(std::basic_ostream<Char, Traits>&, Char);
template <typename Char, typename Traits>
void_t<> operator<<(std::basic_ostream<Char, Traits>&, char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, signed char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, unsigned char);
// Checks if T has a user-defined operator<< (e.g. not a member of
// std::ostream).
template <typename T, typename Char> class is_streamable {
// Checks if T has a user-defined operator<<.
template <typename T, typename Char, typename Enable = void>
class is_streamable {
private:
template <typename U>
static bool_constant<!std::is_same<decltype(std::declval<test_stream<Char>&>()
<< std::declval<U>()),
void_t<>>::value>
test(int);
static auto test(int)
-> bool_constant<sizeof(std::declval<std::basic_ostream<Char>&>()
<< std::declval<U>()) != 0>;
template <typename> static std::false_type test(...);
template <typename> static auto test(...) -> std::false_type;
using result = decltype(test<T>(0));
@@ -90,7 +37,21 @@ template <typename T, typename Char> class is_streamable {
static const bool value = result::value;
};
// Formatting of built-in types and arrays is intentionally disabled because
// it's handled by standard (non-ostream) formatters.
template <typename T, typename Char>
struct is_streamable<
T, Char,
enable_if_t<
std::is_arithmetic<T>::value || std::is_array<T>::value ||
std::is_pointer<T>::value || std::is_same<T, char8_type>::value ||
std::is_same<T, std::basic_string<Char>>::value ||
std::is_same<T, std_string_view<Char>>::value ||
(std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>
: std::false_type {};
// Write the content of buf to os.
// It is a separate function rather than a part of vprint to simplify testing.
template <typename Char>
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
const Char* buf_data = buf.data();
@@ -108,8 +69,8 @@ void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
template <typename Char, typename T>
void format_value(buffer<Char>& buf, const T& value,
locale_ref loc = locale_ref()) {
formatbuf<Char> format_buf(buf);
std::basic_ostream<Char> output(&format_buf);
auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
auto&& output = std::basic_ostream<Char>(&format_buf);
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
if (loc) output.imbue(loc.get<std::locale>());
#endif
@@ -122,29 +83,22 @@ void format_value(buffer<Char>& buf, const T& value,
template <typename T, typename Char>
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
: private formatter<basic_string_view<Char>, Char> {
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
return formatter<basic_string_view<Char>, Char>::parse(ctx);
}
template <typename ParseCtx,
FMT_ENABLE_IF(std::is_same<
ParseCtx, basic_printf_parse_context<Char>>::value)>
auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
using formatter<basic_string_view<Char>, Char>::parse;
template <typename OutputIt>
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
-> OutputIt {
basic_memory_buffer<Char> buffer;
auto buffer = basic_memory_buffer<Char>();
format_value(buffer, value, ctx.locale());
basic_string_view<Char> str(buffer.data(), buffer.size());
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
return formatter<basic_string_view<Char>, Char>::format(
{buffer.data(), buffer.size()}, ctx);
}
// DEPRECATED!
template <typename OutputIt>
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx) const
-> OutputIt {
basic_memory_buffer<Char> buffer;
auto buffer = basic_memory_buffer<Char>();
format_value(buffer, value, ctx.locale());
return std::copy(buffer.begin(), buffer.end(), ctx.out());
}
@@ -155,7 +109,7 @@ FMT_MODULE_EXPORT
template <typename Char>
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buffer;
auto buffer = basic_memory_buffer<Char>();
detail::vformat_to(buffer, format_str, args);
detail::write_buffer(os, buffer);
}
+12 -7
View File
@@ -233,7 +233,7 @@ class printf_arg_formatter : public arg_formatter<Char> {
OutputIt write_null_pointer(bool is_string = false) {
auto s = this->specs;
s.type = 0;
s.type = presentation_type::none;
return write_bytes(this->out, is_string ? "(null)" : "(nil)", s);
}
@@ -249,8 +249,10 @@ class printf_arg_formatter : public arg_formatter<Char> {
// std::is_same instead.
if (std::is_same<T, Char>::value) {
format_specs fmt_specs = this->specs;
if (fmt_specs.type && fmt_specs.type != 'c')
if (fmt_specs.type != presentation_type::none &&
fmt_specs.type != presentation_type::chr) {
return (*this)(static_cast<int>(value));
}
fmt_specs.sign = sign::none;
fmt_specs.alt = false;
fmt_specs.fill[0] = ' '; // Ignore '0' flag for char types.
@@ -271,13 +273,13 @@ class printf_arg_formatter : public arg_formatter<Char> {
/** Formats a null-terminated C string. */
OutputIt operator()(const char* value) {
if (value) return base::operator()(value);
return write_null_pointer(this->specs.type != 'p');
return write_null_pointer(this->specs.type != presentation_type::pointer);
}
/** Formats a null-terminated wide C string. */
OutputIt operator()(const wchar_t* value) {
if (value) return base::operator()(value);
return write_null_pointer(this->specs.type != 'p');
return write_null_pointer(this->specs.type != presentation_type::pointer);
}
OutputIt operator()(basic_string_view<Char> value) {
@@ -490,13 +492,13 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
// Parse type.
if (it == end) FMT_THROW(format_error("invalid format string"));
specs.type = static_cast<char>(*it++);
char type = static_cast<char>(*it++);
if (arg.is_integral()) {
// Normalize type.
switch (specs.type) {
switch (type) {
case 'i':
case 'u':
specs.type = 'd';
type = 'd';
break;
case 'c':
visit_format_arg(
@@ -505,6 +507,9 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
break;
}
}
specs.type = parse_presentation_type(type);
if (specs.type == presentation_type::none)
parse_ctx.on_error("invalid type specifier");
start = it;
+512 -119
View File
@@ -13,37 +13,13 @@
#define FMT_RANGES_H_
#include <initializer_list>
#include <tuple>
#include <type_traits>
#include "format.h"
FMT_BEGIN_NAMESPACE
template <typename Char, typename Enable = void> struct formatting_range {
#ifdef FMT_DEPRECATED_BRACED_RANGES
Char prefix = '{';
Char postfix = '}';
#else
Char prefix = '[';
Char postfix = ']';
#endif
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
};
template <typename Char, typename Enable = void> struct formatting_tuple {
Char prefix = '(';
Char postfix = ')';
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
};
namespace detail {
template <typename RangeT, typename OutputIterator>
@@ -71,7 +47,7 @@ OutputIterator copy(wchar_t ch, OutputIterator out) {
return out;
}
/// Return true value if T has std::string interface, like std::string_view.
// Returns true if T has a std::string-like interface, like std::string_view.
template <typename T> class is_std_string_like {
template <typename U>
static auto check(U* p)
@@ -80,12 +56,40 @@ template <typename T> class is_std_string_like {
public:
static FMT_CONSTEXPR_DECL const bool value =
is_string<T>::value || !std::is_void<decltype(check<T>(nullptr))>::value;
is_string<T>::value ||
std::is_convertible<T, std_string_view<char>>::value ||
!std::is_void<decltype(check<T>(nullptr))>::value;
};
template <typename Char>
struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
template <typename T> class is_map {
template <typename U> static auto check(U*) -> typename U::mapped_type;
template <typename> static void check(...);
public:
#ifdef FMT_FORMAT_MAP_AS_LIST
static FMT_CONSTEXPR_DECL const bool value = false;
#else
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value;
#endif
};
template <typename T> class is_set {
template <typename U> static auto check(U*) -> typename U::key_type;
template <typename> static void check(...);
public:
#ifdef FMT_FORMAT_SET_AS_LIST
static FMT_CONSTEXPR_DECL const bool value = false;
#else
static FMT_CONSTEXPR_DECL const bool value =
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
#endif
};
template <typename... Ts> struct conditional_helper {};
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
@@ -143,16 +147,16 @@ struct has_mutable_begin_end : std::false_type {};
template <typename T>
struct has_const_begin_end<
T, void_t<decltype(detail::range_begin(
std::declval<const remove_cvref_t<T>&>())),
decltype(detail::range_begin(
std::declval<const remove_cvref_t<T>&>()))>>
T,
void_t<
decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
: std::true_type {};
template <typename T>
struct has_mutable_begin_end<
T, void_t<decltype(detail::range_begin(std::declval<T>())),
decltype(detail::range_begin(std::declval<T>())),
decltype(detail::range_end(std::declval<T>())),
enable_if_t<std::is_copy_constructible<T>::value>>>
: std::true_type {};
@@ -160,34 +164,10 @@ template <typename T>
struct is_range_<T, void>
: std::integral_constant<bool, (has_const_begin_end<T>::value ||
has_mutable_begin_end<T>::value)> {};
template <typename T, typename Enable = void> struct range_to_view;
template <typename T>
struct range_to_view<T, enable_if_t<has_const_begin_end<T>::value>> {
struct view_t {
const T* m_range_ptr;
auto begin() const FMT_DECLTYPE_RETURN(detail::range_begin(*m_range_ptr));
auto end() const FMT_DECLTYPE_RETURN(detail::range_end(*m_range_ptr));
};
static auto view(const T& range) -> view_t { return {&range}; }
};
template <typename T>
struct range_to_view<T, enable_if_t<!has_const_begin_end<T>::value &&
has_mutable_begin_end<T>::value>> {
struct view_t {
T m_range_copy;
auto begin() FMT_DECLTYPE_RETURN(detail::range_begin(m_range_copy));
auto end() FMT_DECLTYPE_RETURN(detail::range_end(m_range_copy));
};
static auto view(const T& range) -> view_t { return {range}; }
};
# undef FMT_DECLTYPE_RETURN
#endif
/// tuple_size and tuple_element check.
// tuple_size and tuple_element check.
template <typename T> class is_tuple_like_ {
template <typename U>
static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
@@ -241,9 +221,28 @@ template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
}
#if FMT_MSC_VER
// Older MSVC doesn't get the reference type correctly for arrays.
template <typename R> struct range_reference_type_impl {
using type = decltype(*detail::range_begin(std::declval<R&>()));
};
template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
using type = T&;
};
template <typename T>
using range_reference_type = typename range_reference_type_impl<T>::type;
#else
template <typename Range>
using value_type =
remove_cvref_t<decltype(*detail::range_begin(std::declval<Range>()))>;
using range_reference_type =
decltype(*detail::range_begin(std::declval<Range&>()));
#endif
// We don't use the Range's value_type for anything, but we do need the Range's
// reference type, with cv-ref stripped.
template <typename Range>
using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
*out++ = ',';
@@ -251,16 +250,295 @@ template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
return out;
}
template <
typename Char, typename OutputIt, typename Arg,
FMT_ENABLE_IF(is_std_string_like<typename std::decay<Arg>::type>::value)>
OutputIt write_range_entry(OutputIt out, const Arg& v) {
struct singleton {
unsigned char upper;
unsigned char lower_count;
};
inline auto is_printable(uint16_t x, const singleton* singletons,
size_t singletons_size,
const unsigned char* singleton_lowers,
const unsigned char* normal, size_t normal_size)
-> bool {
auto upper = x >> 8;
auto lower_start = 0;
for (size_t i = 0; i < singletons_size; ++i) {
auto s = singletons[i];
auto lower_end = lower_start + s.lower_count;
if (upper < s.upper) break;
if (upper == s.upper) {
for (auto j = lower_start; j < lower_end; ++j) {
if (singleton_lowers[j] == (x & 0xff)) return false;
}
}
lower_start = lower_end;
}
auto xsigned = static_cast<int>(x);
auto current = true;
for (size_t i = 0; i < normal_size; ++i) {
auto v = static_cast<int>(normal[i]);
auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v;
xsigned -= len;
if (xsigned < 0) break;
current = !current;
}
return current;
}
// Returns true iff the code point cp is printable.
// This code is generated by support/printable.py.
inline auto is_printable(uint32_t cp) -> bool {
static constexpr singleton singletons0[] = {
{0x00, 1}, {0x03, 5}, {0x05, 6}, {0x06, 3}, {0x07, 6}, {0x08, 8},
{0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13},
{0x0f, 4}, {0x10, 3}, {0x12, 18}, {0x13, 9}, {0x16, 1}, {0x17, 5},
{0x18, 2}, {0x19, 3}, {0x1a, 7}, {0x1c, 2}, {0x1d, 1}, {0x1f, 22},
{0x20, 3}, {0x2b, 3}, {0x2c, 2}, {0x2d, 11}, {0x2e, 1}, {0x30, 3},
{0x31, 2}, {0x32, 1}, {0xa7, 2}, {0xa9, 2}, {0xaa, 4}, {0xab, 8},
{0xfa, 2}, {0xfb, 5}, {0xfd, 4}, {0xfe, 3}, {0xff, 9},
};
static constexpr unsigned char singletons0_lower[] = {
0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90,
0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f,
0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1,
0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04,
0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d,
0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf,
0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,
0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d,
0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,
0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5,
0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,
0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49,
0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,
0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7,
0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,
0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16,
0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,
0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f,
0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0,
0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91,
0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,
0xfe, 0xff,
};
static constexpr singleton singletons1[] = {
{0x00, 6}, {0x01, 1}, {0x03, 1}, {0x04, 2}, {0x08, 8}, {0x09, 2},
{0x0a, 5}, {0x0b, 2}, {0x0e, 4}, {0x10, 1}, {0x11, 2}, {0x12, 5},
{0x13, 17}, {0x14, 1}, {0x15, 2}, {0x17, 2}, {0x19, 13}, {0x1c, 5},
{0x1d, 8}, {0x24, 1}, {0x6a, 3}, {0x6b, 2}, {0xbc, 2}, {0xd1, 2},
{0xd4, 12}, {0xd5, 9}, {0xd6, 2}, {0xd7, 2}, {0xda, 1}, {0xe0, 5},
{0xe1, 2}, {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2}, {0xf9, 2},
{0xfa, 2}, {0xfb, 1},
};
static constexpr unsigned char singletons1_lower[] = {
0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07,
0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,
0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87,
0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b,
0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,
0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66,
0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,
0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc,
0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,
0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6,
0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,
0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,
0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,
0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,
};
static constexpr unsigned char normal0[] = {
0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04,
0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0,
0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01,
0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03,
0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03,
0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a,
0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15,
0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f,
0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80,
0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07,
0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06,
0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04,
0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac,
0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c,
0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11,
0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c,
0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b,
0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6,
0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03,
0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80,
0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06,
0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c,
0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17,
0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80,
0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80,
0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d,
};
static constexpr unsigned char normal1[] = {
0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f,
0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e,
0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04,
0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09,
0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16,
0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f,
0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36,
0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33,
0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08,
0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e,
0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41,
0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03,
0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22,
0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04,
0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45,
0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03,
0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81,
0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75,
0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1,
0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a,
0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11,
0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09,
0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89,
0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6,
0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09,
0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50,
0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05,
0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83,
0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05,
0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80,
0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80,
0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07,
0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e,
0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07,
0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06,
};
auto lower = static_cast<uint16_t>(cp);
if (cp < 0x10000) {
return is_printable(lower, singletons0,
sizeof(singletons0) / sizeof(*singletons0),
singletons0_lower, normal0, sizeof(normal0));
}
if (cp < 0x20000) {
return is_printable(lower, singletons1,
sizeof(singletons1) / sizeof(*singletons1),
singletons1_lower, normal1, sizeof(normal1));
}
if (0x2a6de <= cp && cp < 0x2a700) return false;
if (0x2b735 <= cp && cp < 0x2b740) return false;
if (0x2b81e <= cp && cp < 0x2b820) return false;
if (0x2cea2 <= cp && cp < 0x2ceb0) return false;
if (0x2ebe1 <= cp && cp < 0x2f800) return false;
if (0x2fa1e <= cp && cp < 0x30000) return false;
if (0x3134b <= cp && cp < 0xe0100) return false;
if (0xe01f0 <= cp && cp < 0x110000) return false;
return cp < 0x110000;
}
inline auto needs_escape(uint32_t cp) -> bool {
return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' ||
!is_printable(cp);
}
template <typename Char> struct find_escape_result {
const Char* begin;
const Char* end;
uint32_t cp;
};
template <typename Char>
auto find_escape(const Char* begin, const Char* end)
-> find_escape_result<Char> {
for (; begin != end; ++begin) {
auto cp = static_cast<typename std::make_unsigned<Char>::type>(*begin);
if (sizeof(Char) == 1 && cp >= 0x80) continue;
if (needs_escape(cp)) return {begin, begin + 1, cp};
}
return {begin, nullptr, 0};
}
inline auto find_escape(const char* begin, const char* end)
-> find_escape_result<char> {
if (!is_utf8()) return find_escape<char>(begin, end);
auto result = find_escape_result<char>{end, nullptr, 0};
for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
[&](uint32_t cp, string_view sv) {
if (needs_escape(cp)) {
result = {sv.begin(), sv.end(), cp};
return false;
}
return true;
});
return result;
}
template <typename Char, typename OutputIt>
auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {
*out++ = '"';
out = write<Char>(out, v);
auto begin = str.begin(), end = str.end();
do {
auto escape = find_escape(begin, end);
out = copy_str<Char>(begin, escape.begin, out);
begin = escape.end;
if (!begin) break;
auto c = static_cast<Char>(escape.cp);
switch (escape.cp) {
case '\n':
*out++ = '\\';
c = 'n';
break;
case '\r':
*out++ = '\\';
c = 'r';
break;
case '\t':
*out++ = '\\';
c = 't';
break;
case '"':
FMT_FALLTHROUGH;
case '\\':
*out++ = '\\';
break;
default:
if (is_utf8()) {
if (escape.cp < 0x100) {
out = format_to(out, "\\x{:02x}", escape.cp);
continue;
}
if (escape.cp < 0x10000) {
out = format_to(out, "\\u{:04x}", escape.cp);
continue;
}
if (escape.cp < 0x110000) {
out = format_to(out, "\\U{:08x}", escape.cp);
continue;
}
}
for (Char escape_char : basic_string_view<Char>(
escape.begin, to_unsigned(escape.end - escape.begin))) {
out = format_to(
out, "\\x{:02x}",
static_cast<typename std::make_unsigned<Char>::type>(escape_char));
}
continue;
}
*out++ = c;
} while (begin != end);
*out++ = '"';
return out;
}
template <typename Char, typename OutputIt, typename T,
FMT_ENABLE_IF(std::is_convertible<T, std_string_view<char>>::value)>
inline auto write_range_entry(OutputIt out, const T& str) -> OutputIt {
auto sv = std_string_view<Char>(str);
return write_range_entry<Char>(out, basic_string_view<Char>(sv));
}
template <typename Char, typename OutputIt, typename Arg,
FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>
OutputIt write_range_entry(OutputIt out, const Arg v) {
@@ -288,78 +566,169 @@ template <typename T> struct is_tuple_like {
template <typename TupleT, typename Char>
struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
private:
// C++11 generic lambda for format()
// C++11 generic lambda for format().
template <typename FormatContext> struct format_each {
template <typename T> void operator()(const T& v) {
if (i > 0) out = detail::write_delimiter(out);
out = detail::write_range_entry<Char>(out, v);
++i;
}
formatting_tuple<Char>& formatting;
size_t& i;
typename std::add_lvalue_reference<
decltype(std::declval<FormatContext>().out())>::type out;
int i;
typename FormatContext::iterator& out;
};
public:
formatting_tuple<Char> formatting;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return formatting.parse(ctx);
return ctx.begin();
}
template <typename FormatContext = format_context>
auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
auto out = ctx.out();
size_t i = 0;
detail::copy(formatting.prefix, out);
detail::for_each(values, format_each<FormatContext>{formatting, i, out});
detail::copy(formatting.postfix, out);
return ctx.out();
*out++ = '(';
detail::for_each(values, format_each<FormatContext>{0, out});
*out++ = ')';
return out;
}
};
template <typename T, typename Char> struct is_range {
static FMT_CONSTEXPR_DECL const bool value =
detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
!detail::is_map<T>::value &&
!std::is_convertible<T, std::basic_string<Char>>::value &&
!std::is_constructible<detail::std_string_view<Char>, T>::value;
};
namespace detail {
template <typename Context, typename Element> struct range_mapper {
using mapper = arg_mapper<Context>;
template <typename T,
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
static auto map(T&& value) -> T&& {
return static_cast<T&&>(value);
}
template <typename T,
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
static auto map(T&& value)
-> decltype(mapper().map(static_cast<T&&>(value))) {
return mapper().map(static_cast<T&&>(value));
}
};
template <typename Char, typename Element>
using range_formatter_type =
conditional_t<is_formattable<Element, Char>::value,
formatter<remove_cvref_t<decltype(
range_mapper<buffer_context<Char>, Element>{}
.map(std::declval<Element>()))>,
Char>,
fallback_formatter<Element, Char>>;
} // namespace detail
template <typename R, typename Char>
struct formatter<
R, Char,
enable_if_t<fmt::is_range<R, Char>::value
// Workaround a bug in MSVC 2019 and earlier.
#if !FMT_MSC_VER
&& (is_formattable<detail::uncvref_type<R>, Char>::value ||
detail::has_fallback_formatter<detail::uncvref_type<R>,
Char>::value)
#endif
>> {
using formatter_type =
detail::range_formatter_type<Char, detail::uncvref_type<R>>;
formatter_type underlying_;
bool custom_specs_ = false;
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto it = ctx.begin();
auto end = ctx.end();
if (it == end || *it == '}') return it;
if (*it != ':')
FMT_THROW(format_error("no top-level range formatters supported"));
custom_specs_ = true;
++it;
ctx.advance_to(it);
return underlying_.parse(ctx);
}
template <
typename FormatContext, typename U,
FMT_ENABLE_IF(
std::is_same<U, conditional_t<detail::has_const_begin_end<R>::value,
const R, R>>::value)>
auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) {
#ifdef FMT_DEPRECATED_BRACED_RANGES
Char prefix = '{';
Char postfix = '}';
#else
Char prefix = detail::is_set<R>::value ? '{' : '[';
Char postfix = detail::is_set<R>::value ? '}' : ']';
#endif
detail::range_mapper<buffer_context<Char>, detail::uncvref_type<R>> mapper;
auto out = ctx.out();
*out++ = prefix;
int i = 0;
auto it = std::begin(range);
auto end = std::end(range);
for (; it != end; ++it) {
if (i > 0) out = detail::write_delimiter(out);
if (custom_specs_) {
ctx.advance_to(out);
out = underlying_.format(mapper.map(*it), ctx);
} else {
out = detail::write_range_entry<Char>(out, *it);
}
++i;
}
*out++ = postfix;
return out;
}
};
template <typename T, typename Char>
struct formatter<
T, Char,
enable_if_t<
fmt::is_range<T, Char>::value
// Workaround a bug in MSVC 2017 and earlier.
#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
&& (has_formatter<detail::value_type<T>, format_context>::value ||
detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
enable_if_t<detail::is_map<T>::value
// Workaround a bug in MSVC 2019 and earlier.
#if !FMT_MSC_VER
&& (is_formattable<detail::uncvref_type<T>, Char>::value ||
detail::has_fallback_formatter<detail::uncvref_type<T>,
Char>::value)
#endif
>> {
formatting_range<Char> formatting;
>> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return formatting.parse(ctx);
return ctx.begin();
}
template <typename FormatContext>
typename FormatContext::iterator format(const T& values, FormatContext& ctx) {
auto out = detail::copy(formatting.prefix, ctx.out());
size_t i = 0;
auto view = detail::range_to_view<T>::view(values);
auto it = view.begin();
auto end = view.end();
for (; it != end; ++it) {
template <
typename FormatContext, typename U,
FMT_ENABLE_IF(
std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
const T, T>>::value)>
auto format(U& map, FormatContext& ctx) -> decltype(ctx.out()) {
auto out = ctx.out();
*out++ = '{';
int i = 0;
for (const auto& item : map) {
if (i > 0) out = detail::write_delimiter(out);
out = detail::write_range_entry<Char>(out, *it);
out = detail::write_range_entry<Char>(out, item.first);
*out++ = ':';
*out++ = ' ';
out = detail::write_range_entry<Char>(out, item.second);
++i;
}
return detail::copy(formatting.postfix, out);
*out++ = '}';
return out;
}
};
@@ -374,46 +743,70 @@ template <typename Char, typename... T> struct tuple_join_view : detail::view {
template <typename Char, typename... T>
using tuple_arg_join = tuple_join_view<Char, T...>;
// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
// support in tuple_join. It is disabled by default because of issues with
// the dynamic width and precision.
#ifndef FMT_TUPLE_JOIN_SPECIFIERS
# define FMT_TUPLE_JOIN_SPECIFIERS 0
#endif
template <typename Char, typename... T>
struct formatter<tuple_join_view<Char, T...>, Char> {
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
}
template <typename FormatContext>
auto format(const tuple_join_view<Char, T...>& value, FormatContext& ctx) ->
typename FormatContext::iterator {
return format(value, ctx, detail::make_index_sequence<sizeof...(T)>{});
auto format(const tuple_join_view<Char, T...>& value,
FormatContext& ctx) const -> typename FormatContext::iterator {
return do_format(value, ctx,
std::integral_constant<size_t, sizeof...(T)>());
}
private:
template <typename FormatContext, size_t... N>
auto format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
detail::index_sequence<N...>) ->
typename FormatContext::iterator {
using std::get;
return format_args(value, ctx, get<N>(value.tuple)...);
std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
template <typename ParseContext>
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
std::integral_constant<size_t, 0>)
-> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename ParseContext, size_t N>
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
std::integral_constant<size_t, N>)
-> decltype(ctx.begin()) {
auto end = ctx.begin();
#if FMT_TUPLE_JOIN_SPECIFIERS
end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
if (N > 1) {
auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
if (end != end1)
FMT_THROW(format_error("incompatible format specs for tuple elements"));
}
#endif
return end;
}
template <typename FormatContext>
auto format_args(const tuple_join_view<Char, T...>&, FormatContext& ctx) ->
auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
std::integral_constant<size_t, 0>) const ->
typename FormatContext::iterator {
// NOTE: for compilers that support C++17, this empty function instantiation
// can be replaced with a constexpr branch in the variadic overload.
return ctx.out();
}
template <typename FormatContext, typename Arg, typename... Args>
auto format_args(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
const Arg& arg, const Args&... args) ->
template <typename FormatContext, size_t N>
auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
std::integral_constant<size_t, N>) const ->
typename FormatContext::iterator {
using base = formatter<typename std::decay<Arg>::type, Char>;
auto out = base().format(arg, ctx);
if (sizeof...(Args) > 0) {
auto out = std::get<sizeof...(T) - N>(formatters_)
.format(std::get<sizeof...(T) - N>(value.tuple), ctx);
if (N > 1) {
out = std::copy(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
return format_args(value, ctx, args...);
return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
}
return out;
}
+5 -5
View File
@@ -5,8 +5,8 @@
//
// For the license information refer to format.h.
#ifndef FMT_WCHAR_H_
#define FMT_WCHAR_H_
#ifndef FMT_XCHAR_H_
#define FMT_XCHAR_H_
#include <cwchar>
#include <tuple>
@@ -217,11 +217,11 @@ inline void vprint(wstring_view fmt, wformat_args args) {
template <typename... T>
void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
return vprint(f, wstring_view(fmt), make_wformat_args(args...));
return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));
}
template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
return vprint(wstring_view(fmt), make_wformat_args(args...));
return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));
}
/**
@@ -233,4 +233,4 @@ template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
FMT_MODULE_EXPORT_END
FMT_END_NAMESPACE
#endif // FMT_WCHAR_H_
#endif // FMT_XCHAR_H_
-1
View File
@@ -79,7 +79,6 @@ export module fmt;
#define FMT_END_DETAIL_NAMESPACE \
} \
export {
// all library-provided declarations and definitions
// must be in the module purview to be exported
#include "fmt/args.h"
+46
View File
@@ -10,6 +10,52 @@
FMT_BEGIN_NAMESPACE
namespace detail {
// DEPRECATED!
template <typename T = void> struct basic_data {
FMT_API static constexpr const char digits[100][2] = {
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
{'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
{'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
{'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
{'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
{'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
{'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
{'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
{'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
{'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
{'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
{'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
{'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
{'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
{'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
{'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
FMT_API static constexpr const char hex_digits[] = "0123456789abcdef";
FMT_API static constexpr const char signs[4] = {0, '-', '+', ' '};
FMT_API static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1,
0};
FMT_API static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1,
0};
FMT_API static constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
0x1000000u | ' '};
};
#ifdef FMT_SHARED
// Required for -flto, -fivisibility=hidden and -shared to work
extern template struct basic_data<void>;
#endif
#if __cplusplus < 201703L
// DEPRECATED! These are here only for ABI compatiblity.
template <typename T> constexpr const char basic_data<T>::digits[][2];
template <typename T> constexpr const char basic_data<T>::hex_digits[];
template <typename T> constexpr const char basic_data<T>::signs[];
template <typename T> constexpr const char basic_data<T>::left_padding_shifts[];
template <typename T>
constexpr const char basic_data<T>::right_padding_shifts[];
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
#endif
template <typename T>
int format_float(char* buf, std::size_t size, const char* format, int precision,
T value) {
+9 -8
View File
@@ -26,19 +26,17 @@
# endif
# include <io.h>
# define O_CREAT _O_CREAT
# define O_TRUNC _O_TRUNC
# ifndef S_IRUSR
# define S_IRUSR _S_IREAD
# endif
# ifndef S_IWUSR
# define S_IWUSR _S_IWRITE
# endif
# ifdef __MINGW32__
# define _SH_DENYNO 0x40
# ifndef S_IRGRP
# define S_IRGRP 0
# endif
# ifndef S_IROTH
# define S_IROTH 0
# endif
# endif // _WIN32
#endif // FMT_USE_FCNTL
@@ -213,7 +211,10 @@ int buffered_file::fileno() const {
#if FMT_USE_FCNTL
file::file(cstring_view path, int oflag) {
int mode = S_IRUSR | S_IWUSR;
# ifdef _WIN32
using mode_t = int;
# endif
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
# if defined(_WIN32) && !defined(__MINGW32__)
fd_ = -1;
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
+30 -38
View File
@@ -101,61 +101,53 @@ target_compile_definitions(acore-compile-option-interface
-D__STDC_LIMIT_MACROS)
message(STATUS "MSVC: Disabled INTMAX_MAX warnings")
# disable warnings in Visual Studio 8 and above if not wanted
if(NOT WITH_WARNINGS)
if(MSVC AND NOT CMAKE_GENERATOR MATCHES "Visual Studio 7")
target_compile_options(acore-warning-interface
INTERFACE
/wd4996
/wd4355
/wd4244
/wd4985
/wd4267
/wd4619
# /wd4512
)
message(STATUS "MSVC: Disabled generic compiletime warnings")
endif()
endif()
# Ignore specific warnings
# C4351: new behavior: elements of array 'x' will be default initialized
# C4091: 'typedef ': ignored on left of '' when no variable is declared
target_compile_options(acore-compile-option-interface
INTERFACE
/wd4351
/wd4091)
/wd4351 # C4351: new behavior: elements of array 'x' will be default initialized
/wd4091) # C4091: 'typedef ': ignored on left of '' when no variable is declared
# Specify the maximum PreCompiled Header memory allocation limit
# Fixes a compiler-problem when using PCH - the /Ym flag is adjusted by the compiler in MSVC2012, hence we need to set an upper limit with /Zm to avoid discrepancies)
# (And yes, this is a verified , unresolved bug with MSVC... *sigh*)
string(REGEX REPLACE "/Zm[0-9]+ *" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm500")
if(NOT WITH_WARNINGS)
target_compile_options(acore-warning-interface
INTERFACE
/wd4996 # C4996 deprecation
/wd4985 # C4985 'symbol-name': attributes not present on previous declaration.
/wd4244 # C4244 'argument' : conversion from 'type1' to 'type2', possible loss of data
/wd4267 # C4267 'var' : conversion from 'size_t' to 'type', possible loss of data
/wd4619 # C4619 #pragma warning : there is no warning number 'number'
/wd4512) # C4512 'class' : assignment operator could not be generated
# Enable and treat as errors the following warnings to easily detect virtual function signature failures:
# 'function' : member function does not override any base class virtual member function
# 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden
target_compile_options(acore-warning-interface
message(STATUS "MSVC: Disabled generic compiletime warnings")
endif()
# Move some warnings that are enabled for other compilers from level 4 to level 3
target_compile_options(acore-compile-option-interface
INTERFACE
/we4263
/we4264)
/w34100 # C4100 'identifier' : unreferenced formal parameter
/w34101 # C4101: 'identifier' : unreferenced local variable
/w34189 # C4189: 'identifier' : local variable is initialized but not referenced
/w34389) # C4189: 'equality-operator' : signed/unsigned mismatch
if(BUILD_SHARED_LIBS)
# C4251: needs to have dll-interface to be used by clients of class '...'
# C4275: non dll-interface class ...' used as base for dll-interface class '...'
target_compile_options(acore-compile-option-interface
INTERFACE
/wd4251
/wd4275)
/wd4251 # C4251: needs to have dll-interface to be used by clients of class '...'
/wd4275) # C4275: non dll-interface class ...' used as base for dll-interface class '...'
message(STATUS "MSVC: Enabled shared linking")
endif()
# Enable and treat as errors the following warnings to easily detect virtual function signature failures:
target_compile_options(acore-warning-interface
INTERFACE
/we4263 # 'function' : member function does not override any base class virtual member function
/we4264) # 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden
# Disable incremental linking in debug builds.
# To prevent linking getting stuck (which might be fixed in a later VS version).
macro(DisableIncrementalLinking variable)
string(REGEX REPLACE "/INCREMENTAL *" "" ${variable} "${${variable}}")
set(${variable} "${${variable}} /INCREMENTAL:NO")
string(REGEX REPLACE "/INCREMENTAL *" "" ${variable} "${${variable}}")
set(${variable} "${${variable}} /INCREMENTAL:NO")
endmacro()
DisableIncrementalLinking(CMAKE_EXE_LINKER_FLAGS_DEBUG)
+2 -2
View File
@@ -51,9 +51,9 @@ void CreatureAI::OnCharmed(bool /*apply*/)
AISpellInfoType* UnitAI::AISpellInfo;
AISpellInfoType* GetAISpellInfo(uint32 i) { return &CreatureAI::AISpellInfo[i]; }
void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= nullptr*/)
void CreatureAI::Talk(uint8 id, WorldObject const* target /*= nullptr*/)
{
sCreatureTextMgr->SendChat(me, id, whisperTarget);
sCreatureTextMgr->SendChat(me, id, target);
}
inline bool IsValidCombatTarget(Creature* source, Player* target)
@@ -22,7 +22,7 @@
namespace lfg
{
LfgGroupData::LfgGroupData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE),
m_Dungeon(0), m_KicksLeft(sWorld->getIntConfig(CONFIG_LFG_MAX_KICK_COUNT))
m_Dungeon(0), _isLFGGroup(false), m_KicksLeft(sWorld->getIntConfig(CONFIG_LFG_MAX_KICK_COUNT))
{ }
LfgGroupData::~LfgGroupData()
@@ -30,11 +30,23 @@ namespace lfg
bool LfgGroupData::IsLfgGroup()
{
return m_OldState != LFG_STATE_NONE;
return _isLFGGroup;
}
void LfgGroupData::SetState(LfgState state)
{
switch (state)
{
case LFG_STATE_DUNGEON:
_isLFGGroup = true;
break;
case LFG_STATE_FINISHED_DUNGEON:
_isLFGGroup = false;
break;
default:
break;
}
switch (state)
{
case LFG_STATE_NONE:
@@ -68,6 +68,7 @@ namespace lfg
LfgGuidSet m_Players; ///< Players in group
// Dungeon
uint32 m_Dungeon; ///< Dungeon entry
bool _isLFGGroup;
// Vote Kick
uint8 m_KicksLeft; ///< Number of kicks left
};
+1 -1
View File
@@ -407,7 +407,7 @@ namespace lfg
}
proposal.queues = strGuids;
proposal.isNew = numLfgGroups != 1 || sLFGMgr->GetOldState(proposal.group) != LFG_STATE_DUNGEON;
proposal.isNew = numLfgGroups != 1;
if (!sLFGMgr->AllQueued(check)) // can't create proposal
return LFG_COMPATIBILITY_PENDING;
+6 -2
View File
@@ -9171,7 +9171,11 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
if (AuraEffect* aurEff = owner->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 3220, 0))
{
basepoints0 = int32((aurEff->GetAmount() * owner->SpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_MAGIC)) + 100.0f) / 100.0f); // TODO: Is it right?
int32 spellPower = owner->SpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_MAGIC));
if (AuraEffect const* demonicAuraEffect = GetAuraEffect(trigger_spell_id, EFFECT_0))
spellPower -= demonicAuraEffect->GetAmount();
basepoints0 = int32((aurEff->GetAmount() * spellPower + 100.0f) / 100.0f);
CastCustomSpell(this, trigger_spell_id, &basepoints0, &basepoints0, nullptr, true, castItem, triggeredByAura);
return true;
}
@@ -11975,8 +11979,8 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
{
float TakenTotalMod = 1.0f;
float minval = 0.0f;
// Healing taken percent
// Healing taken percent
if (!sScriptMgr->OnSpellHealingBonusTakenNegativeModifiers(this, caster, spellProto, minval))
{
minval = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
@@ -627,11 +627,6 @@ void WorldSession::HandleSpellClick(WorldPacket& recvData)
if (!unit)
return;
if (_player->IsHostileTo(unit))
{
return;
}
// TODO: Unit::SetCharmedBy: 28782 is not in world but 0 is trying to charm it! -> crash
if (!unit->IsInWorld())
return;
+3 -1
View File
@@ -1248,7 +1248,9 @@ enum AcoreStrings
LANG_CMD_SETTINGS_ANNOUNCER_ON = 5080,
LANG_CMD_SETTINGS_ANNOUNCER_OFF = 5081,
// Room for more strings 5082-9999
LANG_CMD_GOQUEST_INVALID_SYNTAX = 5082,
// Room for more strings 5083-9999
// Level requirement notifications
LANG_SAY_REQ = 6604,
+23 -20
View File
@@ -380,33 +380,36 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in
ReputationRank old_rank = ReputationToRank(itr->second.Standing + BaseRep);
ReputationRank new_rank = ReputationToRank(standing);
itr->second.Standing = standing - BaseRep;
itr->second.needSend = true;
itr->second.needSave = true;
if (sScriptMgr->OnPlayerReputationChange(_player, factionEntry->ID, standing, incremental))
{
itr->second.Standing = standing - BaseRep;
itr->second.needSend = true;
itr->second.needSave = true;
SetVisible(&itr->second);
SetVisible(&itr->second);
if (new_rank <= REP_HOSTILE)
SetAtWar(&itr->second, true);
if (new_rank <= REP_HOSTILE)
SetAtWar(&itr->second, true);
if (new_rank > old_rank)
_sendFactionIncreased = true;
if (new_rank > old_rank)
_sendFactionIncreased = true;
sScriptMgr->OnPlayerReputationChange(_player, factionEntry->ID, standing, incremental);
if (new_rank != old_rank)
{
sScriptMgr->OnPlayerReputationRankChange(_player, factionEntry->ID, new_rank, old_rank, _sendFactionIncreased);
}
if (new_rank != old_rank)
sScriptMgr->OnPlayerReputationRankChange(_player, factionEntry->ID, new_rank, old_rank, _sendFactionIncreased);
UpdateRankCounters(old_rank, new_rank);
UpdateRankCounters(old_rank, new_rank);
_player->ReputationChanged(factionEntry);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID);
_player->ReputationChanged(factionEntry);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID);
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID);
return true;
return true;
}
}
return false;
}
@@ -143,13 +143,21 @@ bool ScriptMgr::OnSpellHealingBonusTakenNegativeModifiers(Unit const* target, Un
{
auto ret = IsValidBoolScript<GlobalScript>([&](GlobalScript* script)
{
return !script->OnSpellHealingBonusTakenNegativeModifiers(target, caster, spellInfo, val);
return script->OnSpellHealingBonusTakenNegativeModifiers(target, caster, spellInfo, val);
});
if (ret && *ret)
{
return false;
return true;
}
return true;
return false;
}
void ScriptMgr::OnLoadSpellCustomAttr(SpellInfo* spell)
{
ExecuteScript<GlobalScript>([&](GlobalScript* script)
{
script->OnLoadSpellCustomAttr(spell);
});
}
@@ -154,12 +154,19 @@ void ScriptMgr::OnGivePlayerXP(Player* player, uint32& amount, Unit* victim)
});
}
void ScriptMgr::OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental)
bool ScriptMgr::OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
auto ret = IsValidBoolScript<PlayerScript>([&](PlayerScript* script)
{
return !script->OnReputationChange(player, factionID, standing, incremental);
});
if (ret && *ret)
{
script->OnReputationChange(player, factionID, standing, incremental);
});
return false;
}
return true;
}
void ScriptMgr::OnPlayerReputationRankChange(Player* player, uint32 factionID, ReputationRank newRank, ReputationRank oldRank, bool increased)
+7 -3
View File
@@ -1005,7 +1005,7 @@ public:
virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/) { }
// Called when a player's reputation changes (before it is actually changed)
virtual void OnReputationChange(Player* /*player*/, uint32 /*factionId*/, int32& /*standing*/, bool /*incremental*/) { }
virtual bool OnReputationChange(Player* /*player*/, uint32 /*factionID*/, int32& /*standing*/, bool /*incremental*/) { return true; }
// Called when a player's reputation rank changes (before it is actually changed)
virtual void OnReputationRankChange(Player* /*player*/, uint32 /*factionID*/, ReputationRank /*newRank*/, ReputationRank /*olRank*/, bool /*increased*/) { }
@@ -1530,7 +1530,10 @@ public:
virtual bool OnIsAffectedBySpellModCheck(SpellInfo const* /*affectSpell*/, SpellInfo const* /*checkSpell*/, SpellModifier const* /*mod*/) { return true; };
// Called when checking for spell negative healing modifiers
virtual bool OnSpellHealingBonusTakenNegativeModifiers(Unit const* /*target*/, Unit const* /*caster*/, SpellInfo const* /*spellInfo*/, float& /*val*/) { return true; };
virtual bool OnSpellHealingBonusTakenNegativeModifiers(Unit const* /*target*/, Unit const* /*caster*/, SpellInfo const* /*spellInfo*/, float& /*val*/) { return false; };
// Called after loading spell dbc corrections
virtual void OnLoadSpellCustomAttr(SpellInfo* /*spell*/) { }
};
class BGScript : public ScriptObject
@@ -2165,7 +2168,7 @@ public: /* PlayerScript */
void OnPlayerTalentsReset(Player* player, bool noCost);
void OnPlayerMoneyChanged(Player* player, int32& amount);
void OnGivePlayerXP(Player* player, uint32& amount, Unit* victim);
void OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental);
bool OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental);
void OnPlayerReputationRankChange(Player* player, uint32 factionID, ReputationRank newRank, ReputationRank oldRank, bool increased);
void OnPlayerLearnSpell(Player* player, uint32 spellID);
void OnPlayerForgotSpell(Player* player, uint32 spellID);
@@ -2350,6 +2353,7 @@ public: /* GlobalScript */
void OnBeforeWorldObjectSetPhaseMask(WorldObject const* worldObject, uint32& oldPhaseMask, uint32& newPhaseMask, bool& useCombinedPhases, bool& update);
bool OnIsAffectedBySpellModCheck(SpellInfo const* affectSpell, SpellInfo const* checkSpell, SpellModifier const* mod);
bool OnSpellHealingBonusTakenNegativeModifiers(Unit const* target, Unit const* caster, SpellInfo const* spellInfo, float& val);
void OnLoadSpellCustomAttr(SpellInfo* spell);
public: /* Scheduled scripts */
uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; }
+6 -1
View File
@@ -2031,9 +2031,14 @@ bool Aura::CanStackWith(Aura const* existingAura, bool remove) const
// xinef: check priority before effect mask
SpellGroupSpecialFlags thisAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(GetId());
SpellGroupSpecialFlags existingAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(existingSpellInfo->Id);
if (thisAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && existingAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1)
if (thisAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && thisAuraFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 &&
existingAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && existingAuraFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4)
{
if (thisAuraFlag < existingAuraFlag)
{
return false;
}
}
// xinef: forced strongest aura in group by flag
if (stackFlags & SPELL_GROUP_STACK_FLAG_FORCED_STRONGEST)
+9 -2
View File
@@ -1618,12 +1618,19 @@ bool SpellInfo::IsStrongerAuraActive(Unit const* caster, Unit const* target) con
if (!auraGroup || auraGroup != groupId)
continue;
if (IsRankOf((*iter)->GetSpellInfo()) && (sFlag & SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_SAME_SPELL))
{
continue;
}
// xinef: check priority before effect mask
if (sFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1)
if (sFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && sFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4)
{
SpellGroupSpecialFlags sFlagCurr = sSpellMgr->GetSpellGroupSpecialFlags((*iter)->GetId());
if (sFlagCurr >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && sFlagCurr < sFlag)
if (sFlagCurr >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && sFlagCurr <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 && sFlagCurr < sFlag)
{
return true;
}
}
// xinef: check aura effect equal auras only, some auras have different effects on different ranks - check rank also
+9
View File
@@ -31,6 +31,7 @@
#include "SpellAuraDefines.h"
#include "SpellAuras.h"
#include "SpellInfo.h"
#include "ScriptMgr.h"
#include "World.h"
bool IsPrimaryProfessionSkill(uint32 skill)
@@ -3403,6 +3404,8 @@ void SpellMgr::LoadSpellCustomAttr()
}
}
spellInfo->_InitializeExplicitTargetMask();
sScriptMgr->OnLoadSpellCustomAttr(spellInfo);
}
// Xinef: addition for binary spells, ommit spells triggering other spells
@@ -7580,6 +7583,12 @@ void SpellMgr::LoadDbcDataCorrections()
spellInfo->AttributesEx4 |= SPELL_ATTR4_AURA_EXPIRES_OFFLINE;
});
// PX-238 Winter Wondervolt
ApplySpellFix({ 26157, 26272, 26273, 26274 }, [](SpellEntry* spellInfo)
{
spellInfo->Mechanic = 0;
});
for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i)
{
SpellEntry* spellInfo = (SpellEntry*)sSpellStore.LookupEntry(i);
+16 -15
View File
@@ -325,21 +325,22 @@ typedef std::unordered_map<uint32, SpellBonusEntry> SpellBonusMap;
enum SpellGroupSpecialFlags
{
SPELL_GROUP_SPECIAL_FLAG_NONE = 0x000,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE = 0x001,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN = 0x002,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_UNSTABLE = 0x004,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_SHATTRATH = 0x008,
SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX = 0x00F,
SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST = 0x010, // xinef: specially helpful flag if some spells have different auras, but only one should be present
SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_CHECK = 0x020,
SPELL_GROUP_SPECIAL_FLAG_BASE_AMOUNT_CHECK = 0x040,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 = 0x100,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY2 = 0x200,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY3 = 0x400,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 = 0x800,
SPELL_GROUP_SPECIAL_FLAG_SAME_SPELL_CHECK = 0x1000,
SPELL_GROUP_SPECIAL_FLAG_MAX = 0x2000
SPELL_GROUP_SPECIAL_FLAG_NONE = 0x000,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE = 0x001,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN = 0x002,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_UNSTABLE = 0x004,
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_SHATTRATH = 0x008,
SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX = 0x00F,
SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST = 0x010, // xinef: specially helpful flag if some spells have different auras, but only one should be present
SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_CHECK = 0x020,
SPELL_GROUP_SPECIAL_FLAG_BASE_AMOUNT_CHECK = 0x040,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 = 0x100,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY2 = 0x200,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY3 = 0x400,
SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 = 0x800,
SPELL_GROUP_SPECIAL_FLAG_SAME_SPELL_CHECK = 0x1000,
SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_SAME_SPELL = 0x2000,
SPELL_GROUP_SPECIAL_FLAG_MAX = 0x4000
};
enum SpellGroupStackFlags
+11 -11
View File
@@ -196,7 +196,7 @@ void CreatureTextMgr::LoadCreatureTextLocales()
LOG_INFO("server.loading", " ");
}
uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject const* whisperTarget /*= nullptr*/, ChatMsg msgType /*= CHAT_MSG_ADDON*/, Language language /*= LANG_ADDON*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, uint32 sound /*= 0*/, TeamId teamId /*= TEAM_NEUTRAL*/, bool gmOnly /*= false*/, Player* srcPlr /*= nullptr*/)
uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject const* target /*= nullptr*/, ChatMsg msgType /*= CHAT_MSG_ADDON*/, Language language /*= LANG_ADDON*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, uint32 sound /*= 0*/, TeamId teamId /*= TEAM_NEUTRAL*/, bool gmOnly /*= false*/, Player* srcPlr /*= nullptr*/)
{
if (!source)
return 0;
@@ -282,7 +282,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
range = iter->TextRange;
if (finalSound)
SendSound(source, finalSound, finalType, whisperTarget, range, teamId, gmOnly);
SendSound(source, finalSound, finalType, target, range, teamId, gmOnly);
Unit* finalSource = source;
if (srcPlr)
@@ -293,13 +293,13 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
if (srcPlr)
{
PlayerTextBuilder builder(source, finalSource, finalSource->getGender(), finalType, iter->group, iter->id, finalLang, whisperTarget);
SendChatPacket(finalSource, builder, finalType, whisperTarget, range, teamId, gmOnly);
PlayerTextBuilder builder(source, finalSource, finalSource->getGender(), finalType, iter->group, iter->id, finalLang, target);
SendChatPacket(finalSource, builder, finalType, target, range, teamId, gmOnly);
}
else
{
CreatureTextBuilder builder(finalSource, finalSource->getGender(), finalType, iter->group, iter->id, finalLang, whisperTarget);
SendChatPacket(finalSource, builder, finalType, whisperTarget, range, teamId, gmOnly);
CreatureTextBuilder builder(finalSource, finalSource->getGender(), finalType, iter->group, iter->id, finalLang, target);
SendChatPacket(finalSource, builder, finalType, target, range, teamId, gmOnly);
}
if (isEqualChanced || (!isEqualChanced && totalChance == 100.0f))
SetRepeatId(source, textGroup, iter->id);
@@ -326,17 +326,17 @@ float CreatureTextMgr::GetRangeForChatType(ChatMsg msgType) const
return dist;
}
void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType, WorldObject const* whisperTarget, CreatureTextRange range, TeamId teamId, bool gmOnly)
void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType, WorldObject const* target, CreatureTextRange range, TeamId teamId, bool gmOnly)
{
if (!sound || !source)
return;
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(sound);
SendNonChatPacket(source, &data, msgType, whisperTarget, range, teamId, gmOnly);
SendNonChatPacket(source, &data, msgType, target, range, teamId, gmOnly);
}
void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data, ChatMsg msgType, WorldObject const* whisperTarget, CreatureTextRange range, TeamId teamId, bool gmOnly) const
void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data, ChatMsg msgType, WorldObject const* target, CreatureTextRange range, TeamId teamId, bool gmOnly) const
{
float dist = GetRangeForChatType(msgType);
@@ -347,10 +347,10 @@ void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data,
{
if (range == TEXT_RANGE_NORMAL)//ignores team and gmOnly
{
if (!whisperTarget || whisperTarget->GetTypeId() != TYPEID_PLAYER)
if (!target || target->GetTypeId() != TYPEID_PLAYER)
return;
whisperTarget->ToPlayer()->GetSession()->SendPacket(data);
target->ToPlayer()->GetSession()->SendPacket(data);
return;
}
break;
+7 -7
View File
@@ -94,21 +94,21 @@ public:
void LoadCreatureTextLocales();
CreatureTextMap const& GetTextMap() const { return mTextMap; }
void SendSound(Creature* source, uint32 sound, ChatMsg msgType, WorldObject const* whisperTarget, CreatureTextRange range, TeamId teamId, bool gmOnly);
void SendSound(Creature* source, uint32 sound, ChatMsg msgType, WorldObject const* target, CreatureTextRange range, TeamId teamId, bool gmOnly);
void SendEmote(Unit* source, uint32 emote);
//if sent, returns the 'duration' of the text else 0 if error
uint32 SendChat(Creature* source, uint8 textGroup, WorldObject const* whisperTarget = nullptr, ChatMsg msgType = CHAT_MSG_ADDON, Language language = LANG_ADDON, CreatureTextRange range = TEXT_RANGE_NORMAL, uint32 sound = 0, TeamId teamId = TEAM_NEUTRAL, bool gmOnly = false, Player* srcPlr = nullptr);
uint32 SendChat(Creature* source, uint8 textGroup, WorldObject const* target = nullptr, ChatMsg msgType = CHAT_MSG_ADDON, Language language = LANG_ADDON, CreatureTextRange range = TEXT_RANGE_NORMAL, uint32 sound = 0, TeamId teamId = TEAM_NEUTRAL, bool gmOnly = false, Player* srcPlr = nullptr);
bool TextExist(uint32 sourceEntry, uint8 textGroup);
std::string GetLocalizedChatString(uint32 entry, uint8 gender, uint8 textGroup, uint32 id, LocaleConstant locale) const;
template<class Builder> void SendChatPacket(WorldObject* source, Builder const& builder, ChatMsg msgType, WorldObject const* whisperTarget = nullptr, CreatureTextRange range = TEXT_RANGE_NORMAL, TeamId teamId = TEAM_NEUTRAL, bool gmOnly = false) const;
template<class Builder> void SendChatPacket(WorldObject* source, Builder const& builder, ChatMsg msgType, WorldObject const* target = nullptr, CreatureTextRange range = TEXT_RANGE_NORMAL, TeamId teamId = TEAM_NEUTRAL, bool gmOnly = false) const;
private:
CreatureTextRepeatIds GetRepeatGroup(Creature* source, uint8 textGroup);
void SetRepeatId(Creature* source, uint8 textGroup, uint8 id);
void SendNonChatPacket(WorldObject* source, WorldPacket* data, ChatMsg msgType, WorldObject const* whisperTarget, CreatureTextRange range, TeamId teamId, bool gmOnly) const;
void SendNonChatPacket(WorldObject* source, WorldPacket* data, ChatMsg msgType, WorldObject const* target, CreatureTextRange range, TeamId teamId, bool gmOnly) const;
float GetRangeForChatType(ChatMsg msgType) const;
CreatureTextMap mTextMap;
@@ -177,7 +177,7 @@ private:
};
template<class Builder>
void CreatureTextMgr::SendChatPacket(WorldObject* source, Builder const& builder, ChatMsg msgType, WorldObject const* whisperTarget /*= nullptr*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, TeamId teamId /*= TEAM_NEUTRAL*/, bool gmOnly /*= false*/) const
void CreatureTextMgr::SendChatPacket(WorldObject* source, Builder const& builder, ChatMsg msgType, WorldObject const* target /*= nullptr*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, TeamId teamId /*= TEAM_NEUTRAL*/, bool gmOnly /*= false*/) const
{
if (!source)
return;
@@ -191,10 +191,10 @@ void CreatureTextMgr::SendChatPacket(WorldObject* source, Builder const& builder
{
if (range == TEXT_RANGE_NORMAL) //ignores team and gmOnly
{
if (!whisperTarget || whisperTarget->GetTypeId() != TYPEID_PLAYER)
if (!target || target->GetTypeId() != TYPEID_PLAYER)
return;
localizer(const_cast<Player*>(whisperTarget->ToPlayer()));
localizer(const_cast<Player*>(target->ToPlayer()));
return;
}
break;
+144 -29
View File
@@ -52,7 +52,8 @@ public:
{ "trigger", HandleGoTriggerCommand, SEC_MODERATOR, Console::No },
{ "zonexy", HandleGoZoneXYCommand, SEC_MODERATOR, Console::No },
{ "xyz", HandleGoXYZCommand, SEC_MODERATOR, Console::No },
{ "ticket", HandleGoTicketCommand, SEC_GAMEMASTER, Console::No }
{ "ticket", HandleGoTicketCommand, SEC_GAMEMASTER, Console::No },
{ "quest", HandleGoQuestCommand, SEC_MODERATOR, Console::No },
};
static ChatCommandTable commandTable =
@@ -91,20 +92,7 @@ public:
static bool HandleGoCreatureCIdCommand(ChatHandler* handler, Variant<Hyperlink<creature_entry>, uint32> cId)
{
CreatureData const* spawnpoint = nullptr;
for (auto const& pair : sObjectMgr->GetAllCreatureData())
{
if (pair.second.id1 != *cId)
continue;
if (!spawnpoint)
spawnpoint = &pair.second;
else
{
handler->SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
break;
}
}
CreatureData const* spawnpoint = GetCreatureData(handler, *cId);
if (!spawnpoint)
{
@@ -144,20 +132,7 @@ public:
static bool HandleGoGameObjectGOIdCommand(ChatHandler* handler, uint32 goId)
{
GameObjectData const* spawnpoint = nullptr;
for (auto const& pair : sObjectMgr->GetAllGOData())
{
if (pair.second.id != goId)
continue;
if (!spawnpoint)
spawnpoint = &pair.second;
else
{
handler->SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
break;
}
}
GameObjectData const* spawnpoint = GetGameObjectData(handler, goId);
if (!spawnpoint)
{
@@ -367,6 +342,146 @@ public:
ticket->TeleportTo(player);
return true;
}
static bool HandleGoQuestCommand(ChatHandler* handler, std::string_view type, Quest const* quest)
{
uint32 entry = quest->GetQuestId();
if (type == "starter")
{
QuestRelations* qr = sObjectMgr->GetCreatureQuestRelationMap();
for (auto itr = qr->begin(); itr != qr->end(); ++itr)
{
if (itr->second == entry)
{
CreatureData const* spawnpoint = GetCreatureData(handler, itr->first);
if (!spawnpoint)
{
handler->SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
handler->SetSentErrorMessage(true);
return false;
}
// We've found a creature, teleport to it.
return DoTeleport(handler, { spawnpoint->posX, spawnpoint->posY, spawnpoint->posZ }, spawnpoint->mapid);
}
}
qr = sObjectMgr->GetGOQuestRelationMap();
for (auto itr = qr->begin(); itr != qr->end(); ++itr)
{
if (itr->second == entry)
{
GameObjectData const* spawnpoint = GetGameObjectData(handler, itr->first);
if (!spawnpoint)
{
handler->SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
handler->SetSentErrorMessage(true);
return false;
}
return DoTeleport(handler, { spawnpoint->posX, spawnpoint->posY, spawnpoint->posZ }, spawnpoint->mapid);
}
}
}
else if (type == "ender")
{
QuestRelations* qr = sObjectMgr->GetCreatureQuestInvolvedRelationMap();
for (auto itr = qr->begin(); itr != qr->end(); ++itr)
{
if (itr->second == entry)
{
CreatureData const* spawnpoint = GetCreatureData(handler, itr->first);
if (!spawnpoint)
{
handler->SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
handler->SetSentErrorMessage(true);
return false;
}
// We've found a creature, teleport to it.
return DoTeleport(handler, { spawnpoint->posX, spawnpoint->posY, spawnpoint->posZ }, spawnpoint->mapid);
}
}
qr = sObjectMgr->GetGOQuestInvolvedRelationMap();
for (auto itr = qr->begin(); itr != qr->end(); ++itr)
{
if (itr->second == entry)
{
GameObjectData const* spawnpoint = GetGameObjectData(handler, itr->first);
if (!spawnpoint)
{
handler->SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
handler->SetSentErrorMessage(true);
return false;
}
return DoTeleport(handler, { spawnpoint->posX, spawnpoint->posY, spawnpoint->posZ }, spawnpoint->mapid);
}
}
}
else
{
handler->SendSysMessage(LANG_CMD_GOQUEST_INVALID_SYNTAX);
handler->SetSentErrorMessage(true);
return false;
}
return false;
}
static CreatureData const* GetCreatureData(ChatHandler* handler, uint32 entry)
{
CreatureData const* spawnpoint = nullptr;
for (auto const& pair : sObjectMgr->GetAllCreatureData())
{
if (pair.second.id1 != entry)
{
continue;
}
if (!spawnpoint)
{
spawnpoint = &pair.second;
}
else
{
handler->SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
break;
}
}
return spawnpoint;
}
static GameObjectData const* GetGameObjectData(ChatHandler* handler, uint32 entry)
{
GameObjectData const* spawnpoint = nullptr;
for (auto const& pair : sObjectMgr->GetAllGOData())
{
if (pair.second.id != entry)
{
continue;
}
if (!spawnpoint)
{
spawnpoint = &pair.second;
}
else
{
handler->SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
break;
}
}
return spawnpoint;
}
};
void AddSC_go_commandscript()
+2 -2
View File
@@ -78,11 +78,11 @@ class spell_pri_shadowfiend_scaling : public AuraScript
void CalculateStatAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
{
// xinef: shadowfiend inherits 30% of intellect / stamina (guessed)
// xinef: shadowfiend inherits 30% of intellect and 65% of stamina (guessed)
if (Unit* owner = GetUnitOwner()->GetOwner())
{
Stats stat = Stats(aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].MiscValue);
amount = CalculatePct(std::max<int32>(0, owner->GetStat(stat)), 30);
amount = CalculatePct(std::max<int32>(0, owner->GetStat(stat)), stat == STAT_STAMINA ? 65 : 30);
}
}