diff --git a/.gitignore b/.gitignore
index 259148f..f3e8296 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+# Ignore Visual Studio temporary files, build results, and
+# files generated by popular Visual Studio add-ons.
+.vs/
+
# Prerequisites
*.d
diff --git a/.vs/Master_Slaves_Management/v16/.suo b/.vs/Master_Slaves_Management/v16/.suo
new file mode 100644
index 0000000..efd7a41
Binary files /dev/null and b/.vs/Master_Slaves_Management/v16/.suo differ
diff --git a/.vs/Master_Slaves_Management/v16/Browse.VC.db b/.vs/Master_Slaves_Management/v16/Browse.VC.db
new file mode 100644
index 0000000..190a1ac
Binary files /dev/null and b/.vs/Master_Slaves_Management/v16/Browse.VC.db differ
diff --git a/.vs/Master_Slaves_Management/v16/ipch/AutoPCH/837ee7b03459ac96/MASTER_SLAVES_MANAGEMENT.ipch b/.vs/Master_Slaves_Management/v16/ipch/AutoPCH/837ee7b03459ac96/MASTER_SLAVES_MANAGEMENT.ipch
new file mode 100644
index 0000000..0beae1f
Binary files /dev/null and b/.vs/Master_Slaves_Management/v16/ipch/AutoPCH/837ee7b03459ac96/MASTER_SLAVES_MANAGEMENT.ipch differ
diff --git a/Design Templates/Desien Schedular.pptx b/Design Templates/Desien Schedular.pptx
new file mode 100644
index 0000000..34987b7
Binary files /dev/null and b/Design Templates/Desien Schedular.pptx differ
diff --git a/Master_Slave_Management/Master_Slave_Management.sln b/Master_Slave_Management/Master_Slave_Management.sln
new file mode 100644
index 0000000..13eb169
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management.sln
@@ -0,0 +1,33 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33530.505
+MinimumVisualStudioVersion = 10.0.40219.1
+
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Master_Slave_Management", "Master_Slave_Management\Master_Slave_Management.vcxproj", "{F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Debug|x64.ActiveCfg = Debug|x64
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Debug|x64.Build.0 = Debug|x64
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Debug|x86.ActiveCfg = Debug|Win32
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Debug|x86.Build.0 = Debug|Win32
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Release|x64.ActiveCfg = Release|x64
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Release|x64.Build.0 = Release|x64
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Release|x86.ActiveCfg = Release|Win32
+ {F9EDCB29-48B8-43A3-A1E9-803A0A1C9B61}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+
+ SolutionGuid = {79CD0622-68CD-43C0-AEB3-EAD9469AEB40}
+ EndGlobalSection
+EndGlobal
diff --git a/Master_Slave_Management/Master_Slave_Management/ImagefromSlave.h b/Master_Slave_Management/Master_Slave_Management/ImagefromSlave.h
new file mode 100644
index 0000000..20489fb
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/ImagefromSlave.h
@@ -0,0 +1,49 @@
+#pragma once
+#include "PointForSlave.h"
+class ImageFromSlave
+{
+private:
+ int id;
+ static int counterForImage;
+ PointForSlave TL;
+ PointForSlave BR;
+ int slaveId;
+ int ReqId;
+public:
+ ImageFromSlave() {};
+ ImageFromSlave(float top, float left, float bottom, float right, int slavenum, int
+ reqId) :
+ BR(bottom, right),
+ TL(top, left),
+ slaveId(slavenum),
+ ReqId(reqId),
+ id(counterForImage++) {};
+ PointForSlave GetBR()
+ {
+ return this->BR;
+ }
+ PointForSlave GetTL()
+ {
+ return this->TL;
+ }
+ int GetSlaveId()
+ {
+ return this->slaveId;
+ };
+ int GetReqId()
+ {
+ return this->ReqId;
+ }
+ int GetId()
+ {
+ return this->id;
+ }
+ int getCounter()
+ {
+ return this->counterForImage;
+ }
+ void setSlaveId(int id)
+ {
+ this->slaveId = id;
+ }
+};
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj
new file mode 100644
index 0000000..548c222
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj
@@ -0,0 +1,158 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {1f2ffa9e-bc10-4430-866d-053f6befc127}
+ MasterSlaveManagement
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ C:\Program Files (x86)\Intel\oneAPI\compiler\2024.2\include\sycl
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.filters b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.filters
new file mode 100644
index 0000000..a5be13d
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.filters
@@ -0,0 +1,135 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {0f069b12-04ed-4fda-9180-12e9c5d92963}
+
+
+ {e64bbce5-d410-4ae4-83f3-1e09d0e12667}
+
+
+ {4e84754e-1d3f-4ac6-abda-eea7869ca299}
+
+
+ {c109b872-7eff-4593-a59f-9798dd93d3f8}
+
+
+ {c3b09243-06fc-440c-b466-29368c97dd74}
+
+
+ {3dee35dd-7fae-49ff-9334-e6c744a244ef}
+
+
+ {d17b479f-98b5-4202-82b1-c5777111305c}
+
+
+ {df662f50-dab6-46c6-971a-2d82042b7f8c}
+
+
+ {7a384252-d52c-4d37-bd07-c67bdb0ba65c}
+
+
+ {e9cc0b0a-9442-46a4-b673-7a0d2e9b75b5}
+
+
+ {70108ba4-9051-4453-a4eb-b8320f602998}
+
+
+ {80ce57cc-afd4-4776-9737-7473a000bbb3}
+
+
+ {dae342f1-4fc8-47dd-96f6-25d514359bc0}
+
+
+ {ca5b45a1-4694-4487-95f8-5aea5767da1b}
+
+
+ {6dbbf2c8-0236-481f-9dcc-1a5b21127e57}
+
+
+ {b7275b32-0b39-4740-8f66-5b62c0a90b23}
+
+
+ {c1c1e146-3a03-44a5-830a-516cedae788a}
+
+
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\MessageTemplate
+
+
+ Header Files\Scheduler
+
+
+ Header Files\Scheduler
+
+
+ Header Files\Scheduler\Tests
+
+
+
+
+ Source Files\MessageTemplate
+
+
+ Source Files\MessageTemplate
+
+
+ Source Files\MessageTemplate
+
+
+ Source Files\Scheduler
+
+
+ Source Files\Scheduler
+
+
+ Header Files\Scheduler\Tests
+
+
+
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.user b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Master_Slave_Management.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Message.cpp b/Master_Slave_Management/Master_Slave_Management/Message.cpp
new file mode 100644
index 0000000..f71a84e
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Message.cpp
@@ -0,0 +1,3 @@
+#pragma once
+#include "Message.h"
+int Message::counter = 0;
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Message.h b/Master_Slave_Management/Master_Slave_Management/Message.h
new file mode 100644
index 0000000..1739df9
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Message.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "MessageParams.h"
+#include "Priority.h"
+struct Message
+{
+ int messageId;
+ int reqId;
+ MessageType messageType;
+ int droneId;
+ MessageParams* messageParams;
+ Priority priority;
+
+ Message() :messageId(counter++), messageParams(nullptr) {}
+
+ // Copy constructor
+ /*Message(const Message& message)
+ : messageId(counter++),reqId(message.reqId),messageType(message.messageType),droneId(message.droneId),
+ messageParams(message.messageParams),priority(message.priority)
+ {}*/
+
+ Message& operator=(const Message& other)
+ {
+ if (this != &other)
+ {
+ // Note: messageId should remain unique, so we do not copy it.
+ reqId = other.reqId;
+ messageType = other.messageType;
+ droneId = other.droneId;
+ messageParams = other.messageParams;
+ priority = other.priority;
+ }
+ return *this;
+ }
+
+private:
+ int static counter;
+
+};
+
diff --git a/Master_Slave_Management/Master_Slave_Management/MessageParams.cpp b/Master_Slave_Management/Master_Slave_Management/MessageParams.cpp
new file mode 100644
index 0000000..cd99bb7
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/MessageParams.cpp
@@ -0,0 +1 @@
+#include "MessageParams.h"
diff --git a/Master_Slave_Management/Master_Slave_Management/MessageParams.h b/Master_Slave_Management/Master_Slave_Management/MessageParams.h
new file mode 100644
index 0000000..faaa052
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/MessageParams.h
@@ -0,0 +1,234 @@
+#pragma once
+#include
+#include "Priority.h"
+#include "event.h"
+#include "MessageType.h"
+//#include "RealImage.h"
+#include "PointForSlave.h"
+#include "ImagefromSlave.h"
+#include "mapRequest.h"
+using namespace std;
+struct M_GOT_REQ_PARAMS {
+ mapRequest mp;
+ M_GOT_REQ_PARAMS() {
+ mp = mapRequest();
+ }
+ //MESSAGE_TYPE:M_GOT_REQ
+ //handling function: SlavesManager::getARequestForAMap
+};
+struct MTS_ASK_FOR_IMAGES_PROP_PARAMS {
+ PointForSlave pfs;
+ int slaveId;
+ int reqId;
+ MTS_ASK_FOR_IMAGES_PROP_PARAMS() {
+ pfs = PointForSlave();
+ }
+ //MESSAGE_TYPE:MTS_ASK_FOR_IMAGES
+ //handling function: SlavesManager::sendRequestForImageInSpecificPoint
+};
+struct STM_SEND_IMAGES_PROP_PARAMS
+{
+ bool HaveOrNot_Image;
+ vector imgRes = {};
+ STM_SEND_IMAGES_PROP_PARAMS() {
+ imgRes = vector();
+ }
+ //MESSAGE_TYPE:STM_SEND_IMAGE_PROP
+ //handling function: Slave::GetAStructForImageInPoint
+};
+struct MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS {
+ ImageFromSlave img;
+ MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS() {
+ img = ImageFromSlave();
+ }
+ //MESSAGE_TYPE:MTS_GIVE_THE_CHOSEN_IMAGE
+ //handling function:sendRequestToSlaveToGetRealImage
+};
+struct STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS {
+ //RealImage realImg;
+ STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS() {
+ //realImg=RealImage();
+ }
+ //MESSAGE_TYPE:STM_RESPONSE_TO_THE_CHOSEN_IMAGE
+ //handling function:return_of_an_image_by_its_properties
+};
+struct MTS_REQ_FOR_PHOTO_PARAMS {
+ PointForSlave pfs;
+ MTS_REQ_FOR_PHOTO_PARAMS() {
+ pfs = PointForSlave();
+ }
+};
+struct MTIP_REQ_FOR_REAL_MAP_PARAMS {
+ //vector realImages;
+ MTIP_REQ_FOR_REAL_MAP_PARAMS() {
+ //realImages=vector();
+ }
+};
+struct MTM_NO_COMMUNICATION_AT_ALL_PARAMS
+{
+ MTM_NO_COMMUNICATION_AT_ALL_PARAMS(){}
+ //MESSAGE_TYPE:MTM_NO_COMMUNICATION_AT_ALL,-MessageOfNoCommuincationBetwwenAllSlaves
+ //handling function:__________________
+};
+struct MTM_SLAVES_NOT_COMMUNICATE_PARAMS
+{
+ vector SlavesWithNoCommunication;
+ MTM_SLAVES_NOT_COMMUNICATE_PARAMS() {
+ SlavesWithNoCommunication = vector();
+ }
+ //MESSAGE_TYPE:MTM_SLAVES_NOT_COMMUNICATE,-GetTheSlavesThatDidntCommunicate
+ //handling function:SlavesManager::getTheSlavesThatDidntCommunicate
+};
+struct MTS_SEND_LOCATION_PARAMS {
+ int second;
+ MTS_SEND_LOCATION_PARAMS() {}
+};
+struct MTS_MOVE_OUT_OF_THIS_EREA_PARAMS {
+ MTS_MOVE_OUT_OF_THIS_EREA_PARAMS() {}
+};
+struct MTS_STOP_SEND_LOCATION_PARAMS {
+ MTS_STOP_SEND_LOCATION_PARAMS() {}
+};
+struct MTS_STOP_AT_PLACE_PARAMS {
+ MTS_STOP_AT_PLACE_PARAMS() {}
+};
+struct MTS_BACK_TO_STARTING_POINT_PARAMS {
+ MTS_BACK_TO_STARTING_POINT_PARAMS() {}
+};
+struct STM_LOCATION_PARAMS {
+ float x; float y;
+ STM_LOCATION_PARAMS() {}
+};
+struct MTS_SEND_EVENTS_PARAMS {
+ tm startTime;
+ tm endTime;
+ size_t maxSize;
+ MTS_SEND_EVENTS_PARAMS() {
+ startTime = tm();
+ endTime = tm();
+ maxSize = size_t();
+ }
+};
+struct STM_GET_EVENTS_PARAMS {
+ vector events;
+ STM_GET_EVENTS_PARAMS() {
+ events = vector();
+ }
+};
+
+
+union MessageParams
+{
+ M_GOT_REQ_PARAMS M_GOT_REQ_PARAMS;
+ MTS_ASK_FOR_IMAGES_PROP_PARAMS MTS_ASK_FOR_IMAGES_PROP_PARAMS;
+ STM_SEND_IMAGES_PROP_PARAMS STM_SEND_IMAGES_PROP_PARAMS;
+ MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS;
+ STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS;
+ MTIP_REQ_FOR_REAL_MAP_PARAMS MTIP_REQ_FOR_REAL_MAP_PARAMS;
+ MTS_REQ_FOR_PHOTO_PARAMS MTS_REQ_FOR_PHOTO_PARAMS;
+ MTM_NO_COMMUNICATION_AT_ALL_PARAMS MTM_NO_COMMUNICATION_AT_ALL_PARAMS;
+ MTM_SLAVES_NOT_COMMUNICATE_PARAMS MTM_SLAVES_NOT_COMMUNICATE_PARAMS;
+ MTS_SEND_LOCATION_PARAMS MTS_SEND_LOCATION_PARAMS;
+ MTS_MOVE_OUT_OF_THIS_EREA_PARAMS MTS_MOVE_OUT_OF_THIS_EREA_PARAMS;
+ MTS_STOP_SEND_LOCATION_PARAMS MTS_STOP_SEND_LOCATION_PARAMS;
+ STM_LOCATION_PARAMS STM_LOCATION_PARAMS;
+ MTS_STOP_AT_PLACE_PARAMS MTS_STOP_AT_PLACE_PARAMS;
+ MTS_BACK_TO_STARTING_POINT_PARAMS MTS_BACK_TO_STARTING_POINT_PARAMS;
+ MTS_SEND_EVENTS_PARAMS MTS_SEND_EVENTS_PARAMS;
+ STM_GET_EVENTS_PARAMS STM_GET_EVENTS_PARAMS;
+
+ // áðàé áøéøú îçãì
+ MessageParams() {}
+ ~MessageParams() {}
+
+ // ñéîåï äùãä äôòì
+ //MessageType activeField;
+
+
+// // îééùí àåôøèåø äùîä
+// MessageParams& operator=(const MessageParams& other)
+// {
+// if (this != &other) {
+// // ìð÷åú àú äùãä äðåëçé ìôðé äùîä çãùä
+// destroyCurrentActiveField();
+//
+// activeField = other.activeField;
+// switch (activeField) {
+// case MessageType::M_GOT_REQ:
+// new (&M_GOT_REQ_PARAMS)struct M_GOT_REQ_PARAMS(other.M_GOT_REQ_PARAMS);
+// break;
+// case MessageType::MTS_ASK_FOR_IMAGES:
+// new (&MTS_ASK_FOR_IMAGES_PARAMS)struct MTS_ASK_FOR_IMAGES_PARAMS(other.MTS_ASK_FOR_IMAGES_PARAMS);
+// break;
+// case MessageType::STM_SEND_IMAGES_PROP:
+// new (&STM_SEND_IMAGES_PROP_PARAMS)struct STM_SEND_IMAGES_PROP_PARAMS(other.STM_SEND_IMAGES_PROP_PARAMS);
+// break;
+// case MessageType::MTS_GIVE_THE_CHOSEN_IMAGE:
+// new (&MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS)struct MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS(other.MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS);
+// break;
+// case MessageType::STM_RESPONSE_TO_THE_CHOSEN_IMAGE:
+// new (&STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS) struct STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS(other.STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS);
+// break;
+// case MessageType::MTS_SEND_LOCATION:
+// new(&MTS_SEND_LOCATION_PARAMS)struct MTS_SEND_LOCATION_PARAMS(other.MTS_SEND_LOCATION_PARAMS);
+// break;
+// case MessageType::MTS_MOVE_OUT_OF_THIS_EREA:
+// new (&MTS_MOVE_OUT_OF_THIS_EREA_PARAMS) struct MTS_MOVE_OUT_OF_THIS_EREA_PARAMS(other.MTS_MOVE_OUT_OF_THIS_EREA_PARAMS);
+// break;
+// case MessageType::MTS_STOP_SEND_LOCATION:
+// new (&MTS_STOP_SEND_LOCATION_PARAMS)struct MTS_STOP_SEND_LOCATION_PARAMS(other.MTS_STOP_SEND_LOCATION_PARAMS);
+// break;
+// case MessageType::MTS_STOP_AT_PLACE:
+// new (&MTS_STOP_AT_PLACE_PARAMS) struct MTS_STOP_AT_PLACE_PARAMS(other.MTS_STOP_AT_PLACE_PARAMS);
+// break;
+// case MessageType::MTS_BACK_TO_STARTING_POINT:
+// new (&MTS_BACK_TO_STARTING_POINT_PARAMS)struct MTS_BACK_TO_STARTING_POINT_PARAMS(other.MTS_BACK_TO_STARTING_POINT_PARAMS);
+// break;
+// case MessageType::MTS_SEND_EVENTS:
+// new (&MTS_SEND_EVENTS_PARAMS) struct MTS_SEND_EVENTS_PARAMS(other.MTS_SEND_EVENTS_PARAMS);
+// break;
+// case MessageType::STM_GET_EVENTS:
+// new (&STM_GET_EVENTS_PARAMS)struct STM_GET_EVENTS_PARAMS(other.STM_GET_EVENTS_PARAMS);
+// break;
+// default:
+// // ìà ùãä ôòéì
+// activeField = MessageType::size;
+// break;
+// }
+// }
+// return *this;
+// }
+//
+// // äøñ àåôøèåø
+// ~MessageParams()
+// {
+// destroyCurrentActiveField();
+// }
+//
+//private:
+// void destroyCurrentActiveField()
+// {
+// switch (activeField) {
+// case 0:
+// M_GOT_REQ_PARAMS.~M_GOT_REQ_PARAMS();
+// break;
+// case 1:
+// MTS_ASK_FOR_IMAGES_PARAMS.~MTS_ASK_FOR_IMAGES_PARAMS();
+// break;
+// case 2:
+// STM_SEND_IMAGES_PROP_PARAMS.~STM_SEND_IMAGES_PROP_PARAMS();
+// break;
+// // äåñó òåã î÷øéí ìëì ùãä á-union
+// // ...
+// default:
+// break;
+// }
+// }
+
+
+};
+
+
+
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/MessageType.cpp b/Master_Slave_Management/Master_Slave_Management/MessageType.cpp
new file mode 100644
index 0000000..008f38b
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/MessageType.cpp
@@ -0,0 +1 @@
+#include "MessageType.h"
diff --git a/Master_Slave_Management/Master_Slave_Management/MessageType.h b/Master_Slave_Management/Master_Slave_Management/MessageType.h
new file mode 100644
index 0000000..8e9a22c
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/MessageType.h
@@ -0,0 +1,25 @@
+#pragma once
+enum class MessageType
+{
+ M_GOT_REQ,
+ MTS_ASK_FOR_IMAGES,
+ STM_SEND_IMAGES_PROP,
+ MTS_GIVE_THE_CHOSEN_IMAGE,
+ STM_RESPONSE_TO_THE_CHOSEN_IMAGE,
+ MTS_REQ_FOR_PHOTO,
+ MTIP_REQ_FOR_REAL_MAP,
+ MTM_NO_COMMUNICATION_AT_ALL,
+ MTM_SLAVES_NOT_COMMUNICATE,
+ //IPTM_SEND_THE_IMAGES,
+ MTS_SEND_LOCATION,
+ MTS_MOVE_OUT_OF_THIS_EREA,
+ MTS_STOP_SEND_LOCATION,
+ STM_LOCATION,
+ MTS_STOP_AT_PLACE,
+ MTS_BACK_TO_STARTING_POINT,
+ MTS_SEND_EVENTS,
+ STM_GET_EVENTS,
+ size
+};
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/PointForSlave.h b/Master_Slave_Management/Master_Slave_Management/PointForSlave.h
new file mode 100644
index 0000000..b7eecd0
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/PointForSlave.h
@@ -0,0 +1,23 @@
+#pragma once
+
+class PointForSlave
+{
+private:
+ float x;
+ float y;
+public:
+ PointForSlave() :x(0), y(0) {};
+ PointForSlave(float x, float y)
+ {
+ this->x = x;
+ this->y = y;
+ }
+ float GetX()
+ {
+ return this->x;
+ }
+ float GetY()
+ {
+ return this->y;
+ }
+};
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Priority.h b/Master_Slave_Management/Master_Slave_Management/Priority.h
new file mode 100644
index 0000000..1df7c62
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Priority.h
@@ -0,0 +1,9 @@
+#pragma once
+enum class Priority
+{
+ Low, // Low priority - tasks that are not urgent and can be addressed later.
+ MediumLow, // Medium-Low priority - tasks that are less urgent than medium priority tasks.
+ Medium, // Medium priority - tasks that are somewhat urgent but not the highest priority.
+ MediumHigh, // Medium-High priority - tasks that are more urgent and require timely attention.
+ High // High priority - tasks that are the most urgent and require immediate attention.
+};
diff --git a/Master_Slave_Management/Master_Slave_Management/Queue.cpp b/Master_Slave_Management/Master_Slave_Management/Queue.cpp
new file mode 100644
index 0000000..4530105
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Queue.cpp
@@ -0,0 +1,104 @@
+#pragma once
+#include "Queue.h"
+#include
+#include
+#include
+#include "Message.h"
+#include "dataOfMessage.h"
+
+
+// Push an item to the end of the queue
+void Queue::push(Message data) {
+ std::lock_guard lock(mtx);
+ Node* newNode = new Node(&data);
+ if (tail == nullptr) {
+ head = tail = newNode;
+ }
+ else {
+ tail->next = newNode;
+ newNode->prev = tail;
+ tail = newNode;
+ }
+}
+
+// Pop an item from the front of the queue
+Message* Queue::pop() {
+ std::lock_guard lock(mtx);
+ if (head == nullptr) {
+ throw std::out_of_range("Queue is empty");
+ }
+ Node* temp = head;
+ head = head->next;
+ if (head != nullptr) {
+ head->prev = nullptr;
+ }
+ else {
+ tail = nullptr;
+ }
+ return temp->data;
+}
+
+// Pick (remove) an item from the middle of the queue
+Node* Queue::pick(int index) {
+ std::lock_guard lock(mtx);
+ if (head == nullptr) {
+ throw std::out_of_range("Queue is empty");
+ }
+ Node* temp = head;
+ for (int i = 0; i < index && temp != nullptr; ++i) {
+ temp = temp->next;
+ }
+ if (temp == nullptr) {
+ throw std::out_of_range("Index out of range");
+ }
+ if (temp->prev != nullptr) {
+ temp->prev->next = temp->next;
+ }
+ else {
+ head = temp->next;
+ }
+ if (temp->next != nullptr) {
+ temp->next->prev = temp->prev;
+ }
+ else {
+ tail = temp->prev;
+ }
+ return temp;
+}
+
+// Pass (iterate) over the queue
+int Queue::pass() const {
+ int counter = 0;
+ Node* current = head;
+ while (current != nullptr) {
+ counter++;
+ //std::cout << current->data.getMessage();
+ current = current->next;
+ }
+ //std::cout << std::endl;
+ return counter;
+}
+
+// Check if the queue is empty
+bool Queue::isEmpty() const {
+ return head == nullptr;
+}
+
+// Get the current priority of the queue
+int Queue::getPriority() const {
+ return priority;
+}
+
+// Set a new priority for the queue
+void Queue::setPriority(int newPriority) {
+ priority = newPriority;
+}
+
+//
+void Queue::Handler() {
+ Message* message = pop();
+ //Handles the message in the appropriate function
+ dataOfMessageVector[static_cast(message->messageType)].func(message);
+}
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/Queue.h b/Master_Slave_Management/Master_Slave_Management/Queue.h
new file mode 100644
index 0000000..1856d8b
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Queue.h
@@ -0,0 +1,87 @@
+#pragma once
+#include
+#include
+#include
+#include
+#include "Message.h"
+
+// Node structure for the doubly linked list
+struct Node {
+ Message* data;
+ Node* next;
+ Node* prev;
+
+ Node(Message* data) : data(data), next(nullptr), prev(nullptr) {}
+};
+typedef void (*FuncPtr)();
+
+class Queue {
+private:
+ //
+ std::vector pointersToFunctions;
+
+ //
+ Node* head;
+ Node* tail;
+ int priority;
+ int weight;
+ int currentWeight;
+ std::mutex mtx;
+public:
+ // Constructor to initialize an empty queue with a default priority
+ Queue(int weight, int priority = 0) : head(nullptr), tail(nullptr), priority(priority), weight(weight), currentWeight(weight) {}
+
+ // Destructor to clean up the allocated memory
+ ~Queue() {
+ while (head != nullptr) {
+ Node* temp = head;
+ head = head->next;
+ delete temp;
+ }
+ }
+
+ // Push an item to the end of the queue
+ void push(Message data);
+
+ // Pop an item from the front of the queue
+ Message* pop();
+
+ // Pick (remove) an item from the middle of the queue
+ Node* pick(int index);
+
+ Message* top() {
+ return head->data;
+ }
+ // Pass (iterate) over the queue
+ int pass() const;
+
+ // Check if the queue is empty
+ bool isEmpty() const;
+
+ // Get the current priority of the queue
+ int getPriority() const;
+
+ // Set a new priority for the queue
+ void setPriority(int newPriority);
+
+ int GetSize() {
+ return pass();
+ }
+
+ //Decrease the weight by one
+ void DecreaseWeight() {
+ this->currentWeight -= 1;
+ }
+ int GetCurrentWeight() const {
+ return currentWeight;
+ }
+ void SetCurrentWeight(int w) { currentWeight = w; }
+ int GetWeight() const {
+ return weight;
+ }
+ //Handler the message
+ void Handler();
+
+
+};
+
diff --git a/Master_Slave_Management/Master_Slave_Management/RealImage.h b/Master_Slave_Management/Master_Slave_Management/RealImage.h
new file mode 100644
index 0000000..3f34fb1
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/RealImage.h
@@ -0,0 +1,48 @@
+#pragma once
+#pragma once
+#include "opencv2/opencv.hpp"
+using namespace std;
+using namespace cv;
+#ifdef _DEBUG
+// the debug version that corresponds to the opencv_world420d.dll:
+#pragma comment(lib, "opencv_world454d.lib")
+#else
+// the release version that corresponds to the opencv_world420.dll:
+#pragma comment(lib, "opencv_world454.lib")
+#endif
+class RealImage
+{
+private:
+ Mat img;
+ int id;
+ int slaveId;
+public:
+ RealImage() {}
+ RealImage(int id, int slaveId, Mat img)
+ {
+ this->id = id;
+ this->slaveId = slaveId;
+ this->img = img;
+ //for (int y = 0; y < img.rows; ++y) {
+ // for (int x = 0; x < img.cols; ++x) {
+ // Vec3b pixel = img.at(y, x);
+ // Vec3b pixel1 = this->img.at(y, x);
+ // pixel1[0] = pixel[0];
+ // pixel1[1] = pixel[1];
+ // pixel1[2] = pixel[2];
+ // }
+ //}
+ }
+ int getId()
+ {
+ return this->id;
+ }
+ int getSlaveId()
+ {
+ return this->slaveId;
+ }
+ Mat getImg()
+ {
+ return this->img;
+ }
+};
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/Scheduling.cpp b/Master_Slave_Management/Master_Slave_Management/Scheduling.cpp
new file mode 100644
index 0000000..cec90ef
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Scheduling.cpp
@@ -0,0 +1,87 @@
+#pragma once
+#include "Queue.h"
+#include "Message.h"
+#include
+#include
+
+/**
+ * @brief Function to check if all queues are empty and all weights are zero.
+ *
+ * @param listOfTaskQueues Reference to the list of QueueManagement objects.
+ * @return true If all queues are empty and all weights are zero.
+ * @return false If any queue is not empty or any weight is not zero.
+ */
+bool CheckQueueIsEmptyAndWeightNotZeroForAll(std::list& listOfTaskQueues) {
+ for (auto& qm : listOfTaskQueues) {
+ if (!qm.isEmpty() || qm.GetCurrentWeight() > 0)
+ return false;
+ }
+ return true;
+}
+
+
+/**
+ * @brief Function to reset the current weights of the queues to their initial values.
+ *
+ * @param listOfTaskQueues Pointer to the list of QueueManagement objects.
+ */
+void InitialWeights(std::list* listOfTaskQueues) {
+ for (auto& queue : *listOfTaskQueues) {
+ queue.SetCurrentWeight(queue.GetWeight());
+ }
+}
+
+/**
+ * @brief Function to add additional tasks to non-empty queues.
+ *
+ * @param listOfTaskQueues Reference to the list of QueueManagement objects.
+ */
+void addAdditionalTasks(std::list& listOfTaskQueues) {
+ for (auto& queue : listOfTaskQueues) {
+ Message additionalTask = Message(); // éöéøú îùéîä çãùä òí îöáéò
+ queue.push(additionalTask); // äåñôú äîùéîä ìúåø
+ }
+}
+
+/**
+ * @brief Function to perform weighted round robin scheduling.
+ *
+ * @param listOfTaskQueues Pointer to the list of QueueManagement objects.
+ * @param addTasks Boolean flag to indicate whether to add additional tasks during execution.
+ */
+void WeightedRoundRobin(std::list* listOfTaskQueues, bool addTasks) {
+ while (true) {
+ // Loop until all queues are empty
+ while (CheckQueueIsEmptyAndWeightNotZeroForAll(*listOfTaskQueues) == false) {
+ bool allWeightsZero = true;
+ bool allQueuesEmpty = true;
+ // Iterate through each QueueManagement object in the list
+ for (auto& queueManagement : *listOfTaskQueues) {
+ // Check if the current queue has remaining weight and if the current queue is not empty
+ if (!queueManagement.isEmpty() && queueManagement.GetCurrentWeight() > 0) {
+ // Print a message indicating a task is running
+ std::cout << "Running task: " << std::endl;
+ // Handle the task at the front of the queue
+ queueManagement.Handler();
+ // Decrease the weight of the current queue
+ queueManagement.DecreaseWeight();
+ }
+ if (queueManagement.GetCurrentWeight() > 0)
+ allWeightsZero = false;
+ if (!queueManagement.isEmpty())
+ allQueuesEmpty = false;
+ }
+ if (allQueuesEmpty)
+ break;
+ if (allWeightsZero) {
+ InitialWeights(listOfTaskQueues);
+ }
+ if (addTasks) {
+ addAdditionalTasks(*listOfTaskQueues); // äåñôú îùéîåú ðåñôåú
+ }
+ }
+ }
+}
+
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/Scheduling.h b/Master_Slave_Management/Master_Slave_Management/Scheduling.h
new file mode 100644
index 0000000..a81a645
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Scheduling.h
@@ -0,0 +1,11 @@
+#pragma once
+#include "Queue.h"
+#include "Message.h"
+#include
+#include
+
+// Function to check if all queues are empty
+bool CheckQueueIsEmptyAndWeightZeroForAll(std::list& listOfTaskQueues);
+void InitialWeights(std::list* listOfTaskQueues);
+void WeightedRoundRobin(std::list* listOfTaskQueues, bool addTasks);
+void addAdditionalTasks(std::list& listOfTaskQueues);
diff --git a/Master_Slave_Management/Master_Slave_Management/Slave.h b/Master_Slave_Management/Master_Slave_Management/Slave.h
new file mode 100644
index 0000000..4f6bedb
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/Slave.h
@@ -0,0 +1,43 @@
+#pragma once
+#pragma once
+#include "ImageFromSlave.h"
+#include "MessageParams.h"
+
+using namespace std;
+class Slave
+{
+private:
+ int id;
+ static int Counter;
+public:
+ Slave()
+ {
+ Counter++;
+ this->id = Counter;
+ };
+ int GetId()
+ {
+ return this->id;
+ };
+ int GetSlaveId()
+ {
+ return Counter;
+ }
+ void setId(int id)
+ {
+ this->id = id;
+ }
+ vector CheckIfIHaveImage(PointForSlave p, ImageFromSlave MyArrOfImages[]);
+ bool isPointInImage(PointForSlave p, ImageFromSlave img);
+ STM_SEND_IMAGES_PROP_PARAMS GetAStructForImageInPoint(MTS_ASK_FOR_IMAGES_PROP_PARAMS msg) {};
+ STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS return_of_an_image_by_its_properties(MTS_GIVE_THE_CHOSEN_IMAGE_PARAMS msgR) {};
+};
+
+
+
+
+
+
+
+
+
diff --git a/Master_Slave_Management/Master_Slave_Management/SlavesManager.h b/Master_Slave_Management/Master_Slave_Management/SlavesManager.h
new file mode 100644
index 0000000..8adb3f3
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/SlavesManager.h
@@ -0,0 +1,43 @@
+#pragma once
+#include
+#include "ImageFromSlave.h"
+#include "mapRequest.h"
+#include "MessageParams.h"
+#include "RealImage.h"
+using namespace std;
+struct GlobalData {
+ static int static_current_ID;
+ static vector TheImagesFromSlaves;
+ static int NumOfSlaves_HasToAnswer;
+ static vector theBoolAnswers;
+ static float MinimumLine;
+ static vector TheOptimals;
+ static PointForSlave pfs;
+ static mapRequest mapReqGlobal;
+ static vector RealImagesV;
+};
+class SlavesManager {
+public:
+ void addEvent(string event);
+ bool handle_photo_request();
+ bool verify_photo(bool photo_taken);
+ bool no_comments();
+ int belongs_to_the_current_process(int ID, int current_ID, int number_of_slaves);
+ bool the_irrelevant_images_did_not_enter_the_array(const vector& IDresponses, int current_ID);
+ bool request_for_a_map_arrived(bool map_request);
+ bool Enter_the_queue(vector queue, int map_request_ID);
+ bool The_request_is_processed(int map_request_ID);
+ ImageFromSlave ChooseTheOptimalImage();
+ PointForSlave next_point_to_send(ImageFromSlave selected_image, float next_minimum_line);
+ vectorrandom_slaves_for_getting_images(ImageFromSlave temporary[]);
+ PointForSlave getARequestForAMap(M_GOT_REQ_PARAMS getReqMap);
+ vector sendRequestForImageInSpecificPoint();
+ void getResponse_ImageFromSlave(STM_SEND_IMAGES_PROP_PARAMS ResFromSlave);
+ void sendRequestToSlaveToGetRealImage();
+ void getTheRealImageFromSlave(STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS resFromSlave);
+ bool checking_if_there_is_a_real_picture(STM_RESPONSE_TO_THE_CHOSEN_IMAGE_PARAMS RealI);
+ void sendMessageToTakeAPicture();
+ bool forCaseSeveralDidntAnswer(int numOfSlaves);
+ void getTheSlavesThatDidntCommunicate(MTM_SLAVES_NOT_COMMUNICATE_PARAMS msgToMaster);
+ void TheWhileFunc();
+};
\ No newline at end of file
diff --git a/Master_Slave_Management/Master_Slave_Management/dataOfMessage.h b/Master_Slave_Management/Master_Slave_Management/dataOfMessage.h
new file mode 100644
index 0000000..4513089
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/dataOfMessage.h
@@ -0,0 +1,59 @@
+#pragma once
+#include "Priority.h"
+#include "Message.h"
+
+struct dataOfMessage {
+ Priority priority;
+ void (*func)(Message* message);
+};
+//functions
+void getARequestForAMap(Message* message) {};//M_GOT_REQ
+void sendRequestForImageInSpecificPoint(Message* message) {};//MTS_ASK_FOR_IMAGES
+void GetAStructForImageInPoint(Message* message) {};//STM_SEND_IMAGE_PROP
+void sendRequestToSlaveToGetRealImage(Message* message) {};//MTS_GIVE_THE_CHOSEN_IMAGE
+void return_of_an_image_by_its_properties(Message* message) {};//STM_RESPONSE_TO_THE_CHOSEN_IMAGE
+void sendMessageToTakeAPicture(Message* message) {};//MTS_REQ_FOR_PHOTO
+void getTheSlavesThatDidntCommunicate(Message* message) {};//MTM_SLAVES_NOT_COMMUNICATE
+void receiveEventsFromSlave(Message* message) {};//STM_GET_EVENTS_PARAMS
+void getEvents(Message* message) {};//MTS_SEND_EVENTS_PARAMS
+void handleLocation(Message* message) {};//MTS_SEND_LOCATIONint sec
+void moveFromYourPlaceSafely(Message* message) {};//MTS_MOVE_OUT_OF_THIS_AREA
+void setSendLocation(Message* message) {};//MTS_STOP_SEND_LOCATION
+void updateDroneLocation(Message* message) {};//STM_LOCATION
+
+dataOfMessage dataOfMessageVector[int(MessageType::size)];
+
+//initial vector pointer to function
+void InitialPointerToFunction() {
+ dataOfMessageVector[static_cast(MessageType::M_GOT_REQ)].func = &getARequestForAMap;
+ dataOfMessageVector[static_cast(MessageType::M_GOT_REQ)].priority = Priority::Medium;
+ dataOfMessageVector[static_cast(MessageType::MTS_ASK_FOR_IMAGES)].func = &sendRequestForImageInSpecificPoint;
+ dataOfMessageVector[static_cast(MessageType::MTS_ASK_FOR_IMAGES)].priority = Priority::MediumHigh;
+ dataOfMessageVector[static_cast(MessageType::STM_SEND_IMAGES_PROP)].func = &GetAStructForImageInPoint;
+ dataOfMessageVector[static_cast(MessageType::STM_SEND_IMAGES_PROP)].priority = Priority::Medium;
+ dataOfMessageVector[static_cast(MessageType::MTS_GIVE_THE_CHOSEN_IMAGE)].func = &sendRequestToSlaveToGetRealImage;
+ dataOfMessageVector[static_cast(MessageType::MTS_GIVE_THE_CHOSEN_IMAGE)].priority = Priority::MediumHigh;
+ dataOfMessageVector[static_cast(MessageType::STM_RESPONSE_TO_THE_CHOSEN_IMAGE)].func = &return_of_an_image_by_its_properties;
+ dataOfMessageVector[static_cast(MessageType::STM_RESPONSE_TO_THE_CHOSEN_IMAGE)].priority = Priority::High;
+ dataOfMessageVector[static_cast(MessageType::MTS_REQ_FOR_PHOTO)].func = &sendMessageToTakeAPicture;
+ dataOfMessageVector[static_cast(MessageType::MTS_REQ_FOR_PHOTO)].priority = Priority::MediumLow;
+ dataOfMessageVector[static_cast(MessageType::MTIP_REQ_FOR_REAL_MAP)].func = &getEvents;
+ dataOfMessageVector[static_cast(MessageType::MTIP_REQ_FOR_REAL_MAP)].priority = Priority::Medium;
+ dataOfMessageVector[static_cast(MessageType::MTS_SEND_LOCATION)].func = &handleLocation;
+ dataOfMessageVector[static_cast(MessageType::MTS_SEND_LOCATION)].priority = Priority::MediumLow;
+ dataOfMessageVector[static_cast(MessageType::MTS_MOVE_OUT_OF_THIS_EREA)].func = &moveFromYourPlaceSafely;
+ dataOfMessageVector[static_cast(MessageType::MTS_MOVE_OUT_OF_THIS_EREA)].priority = Priority::Medium;
+ dataOfMessageVector[static_cast(MessageType::MTS_STOP_SEND_LOCATION)].func = &setSendLocation;
+ dataOfMessageVector[static_cast(MessageType::MTS_STOP_SEND_LOCATION)].priority = Priority::Low;
+ dataOfMessageVector[static_cast(MessageType::STM_LOCATION)].func = &updateDroneLocation;
+ dataOfMessageVector[static_cast(MessageType::STM_LOCATION)].priority = Priority::Low;
+ dataOfMessageVector[static_cast(MessageType::MTS_STOP_AT_PLACE)].func = nullptr;//no function
+ dataOfMessageVector[static_cast(MessageType::MTS_STOP_AT_PLACE)].priority = Priority::Medium;
+ dataOfMessageVector[static_cast(MessageType::MTS_BACK_TO_STARTING_POINT)].func = nullptr;//no function
+ dataOfMessageVector[static_cast(MessageType::MTS_BACK_TO_STARTING_POINT)].priority = Priority::High;
+ dataOfMessageVector[static_cast(MessageType::MTS_SEND_EVENTS)].func = &getEvents;
+ dataOfMessageVector[static_cast(MessageType::MTS_SEND_EVENTS)].priority = Priority::MediumLow;
+ dataOfMessageVector[static_cast(MessageType::STM_GET_EVENTS)].func = &receiveEventsFromSlave;
+ dataOfMessageVector[static_cast(MessageType::STM_GET_EVENTS)].priority = Priority::MediumHigh;
+}
+void getTheSlavesThatDidntCommunicate(Message* message);//MTM_SLAVES_NOT_COMMUNICATE#pragma once
diff --git a/Master_Slave_Management/Master_Slave_Management/doctest.h b/Master_Slave_Management/Master_Slave_Management/doctest.h
new file mode 100644
index 0000000..b2b031a
--- /dev/null
+++ b/Master_Slave_Management/Master_Slave_Management/doctest.h
@@ -0,0 +1,7165 @@
+#pragma once
+// ====================================================================== lgtm [cpp/missing-header-guard]
+// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
+// ======================================================================
+//
+// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
+//
+// Copyright (c) 2016-2023 Viktor Kirilov
+//
+// Distributed under the MIT Software License
+// See accompanying file LICENSE.txt or copy at
+// https://opensource.org/licenses/MIT
+//
+// The documentation can be found at the library's page:
+// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+//
+// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt
+//
+// The concept of subcases (sections in Catch) and expression decomposition are from there.
+// Some parts of the code are taken directly:
+// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
+// - the Approx() helper class for floating point comparison
+// - colors in the console
+// - breaking into a debugger
+// - signal / SEH handling
+// - timer
+// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste)
+//
+// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+
+#ifndef DOCTEST_LIBRARY_INCLUDED
+#define DOCTEST_LIBRARY_INCLUDED
+
+// =================================================================================================
+// == VERSION ======================================================================================
+// =================================================================================================
+
+#define DOCTEST_VERSION_MAJOR 2
+#define DOCTEST_VERSION_MINOR 4
+#define DOCTEST_VERSION_PATCH 11
+
+// util we need here
+#define DOCTEST_TOSTR_IMPL(x) #x
+#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
+
+#define DOCTEST_VERSION_STR \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_PATCH)
+
+#define DOCTEST_VERSION \
+ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
+
+// =================================================================================================
+// == COMPILER VERSION =============================================================================
+// =================================================================================================
+
+// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect
+
+#ifdef _MSC_VER
+#define DOCTEST_CPLUSPLUS _MSVC_LANG
+#else
+#define DOCTEST_CPLUSPLUS __cplusplus
+#endif
+
+#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH))
+
+// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
+#if defined(_MSC_VER) && defined(_MSC_FULL_VER)
+#if _MSC_VER == _MSC_FULL_VER / 10000
+#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
+#else // MSVC
+#define DOCTEST_MSVC \
+ DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
+#endif // MSVC
+#endif // MSVC
+#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \
+ !defined(__INTEL_COMPILER)
+#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#endif // GCC
+#if defined(__INTEL_COMPILER)
+#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif // ICC
+
+#ifndef DOCTEST_MSVC
+#define DOCTEST_MSVC 0
+#endif // DOCTEST_MSVC
+#ifndef DOCTEST_CLANG
+#define DOCTEST_CLANG 0
+#endif // DOCTEST_CLANG
+#ifndef DOCTEST_GCC
+#define DOCTEST_GCC 0
+#endif // DOCTEST_GCC
+#ifndef DOCTEST_ICC
+#define DOCTEST_ICC 0
+#endif // DOCTEST_ICC
+
+// =================================================================================================
+// == COMPILER WARNINGS HELPERS ====================================================================
+// =================================================================================================
+
+#if DOCTEST_CLANG && !DOCTEST_ICC
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop")
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#else // DOCTEST_CLANG
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_CLANG
+
+#if DOCTEST_GCC
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push")
+#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop")
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w)
+#else // DOCTEST_GCC
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_GCC_SUPPRESS_WARNING(w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_GCC
+
+#if DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push))
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#else // DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_MSVC
+
+// =================================================================================================
+// == COMPILER WARNINGS ============================================================================
+// =================================================================================================
+
+// both the header and the implementation suppress all of these,
+// so it only makes sense to aggregate them like so
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \
+ \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \
+ \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ /* these 4 also disabled globally via cmake: */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
+ /* common ones */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \
+ /* static analysis */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
+
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
+
+DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
+
+DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
+
+DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+// =================================================================================================
+// == FEATURE DETECTION ============================================================================
+// =================================================================================================
+
+// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support
+// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx
+// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
+// MSVC version table:
+// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
+// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022)
+// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
+// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
+// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
+// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
+// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
+// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
+// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
+// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
+
+// Universal Windows Platform support
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#define DOCTEST_CONFIG_NO_WINDOWS_SEH
+#endif // WINAPI_FAMILY
+#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#define DOCTEST_CONFIG_WINDOWS_SEH
+#endif // MSVC
+#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#undef DOCTEST_CONFIG_WINDOWS_SEH
+#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH
+
+#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \
+ !defined(__EMSCRIPTEN__) && !defined(__wasi__)
+#define DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // _WIN32
+#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS)
+#undef DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \
+ || defined(__wasi__)
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // no exceptions
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
+#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+#ifdef __wasi__
+#define DOCTEST_CONFIG_NO_MULTITHREADING
+#endif
+
+#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT)
+#define DOCTEST_CONFIG_IMPLEMENT
+#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#if DOCTEST_MSVC
+#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport)
+#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport)
+#else // MSVC
+#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport))
+#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport))
+#endif // MSVC
+#else // _WIN32
+#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default")))
+#define DOCTEST_SYMBOL_IMPORT
+#endif // _WIN32
+
+#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#ifdef DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT
+#else // DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT
+#endif // DOCTEST_CONFIG_IMPLEMENT
+#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#define DOCTEST_INTERFACE
+#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+
+// needed for extern template instantiations
+// see https://github.com/fmtlib/fmt/issues/2228
+#if DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL
+#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE
+#else // DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE
+#define DOCTEST_INTERFACE_DEF
+#endif // DOCTEST_MSVC
+
+#define DOCTEST_EMPTY
+
+#if DOCTEST_MSVC
+#define DOCTEST_NOINLINE __declspec(noinline)
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0)
+#define DOCTEST_NOINLINE
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#else
+#define DOCTEST_NOINLINE __attribute__((noinline))
+#define DOCTEST_UNUSED __attribute__((unused))
+#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
+#endif
+
+#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE
+#define DOCTEST_INLINE_NOINLINE inline
+#else
+#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE
+#endif
+
+#ifndef DOCTEST_NORETURN
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NORETURN
+#else // DOCTEST_MSVC
+#define DOCTEST_NORETURN [[noreturn]]
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_NORETURN
+
+#ifndef DOCTEST_NOEXCEPT
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NOEXCEPT
+#else // DOCTEST_MSVC
+#define DOCTEST_NOEXCEPT noexcept
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_NOEXCEPT
+
+#ifndef DOCTEST_CONSTEXPR
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_CONSTEXPR const
+#define DOCTEST_CONSTEXPR_FUNC inline
+#else // DOCTEST_MSVC
+#define DOCTEST_CONSTEXPR constexpr
+#define DOCTEST_CONSTEXPR_FUNC constexpr
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_CONSTEXPR
+
+#ifndef DOCTEST_NO_SANITIZE_INTEGER
+#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0)
+#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define DOCTEST_NO_SANITIZE_INTEGER
+#endif
+#endif // DOCTEST_NO_SANITIZE_INTEGER
+
+// =================================================================================================
+// == FEATURE DETECTION END ========================================================================
+// =================================================================================================
+
+#define DOCTEST_DECLARE_INTERFACE(name) \
+ virtual ~name(); \
+ name() = default; \
+ name(const name&) = delete; \
+ name(name&&) = delete; \
+ name& operator=(const name&) = delete; \
+ name& operator=(name&&) = delete;
+
+#define DOCTEST_DEFINE_INTERFACE(name) \
+ name::~name() = default;
+
+// internal macros for string concatenation and anonymous variable name generation
+#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
+#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
+#ifdef __COUNTER__ // not standard and may be missing for some compilers
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
+#else // __COUNTER__
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
+#endif // __COUNTER__
+
+#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x&
+#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x
+#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+
+// not using __APPLE__ because... this is how Catch does it
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+#define DOCTEST_PLATFORM_MAC
+#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+#define DOCTEST_PLATFORM_IPHONE
+#elif defined(_WIN32)
+#define DOCTEST_PLATFORM_WINDOWS
+#elif defined(__wasi__)
+#define DOCTEST_PLATFORM_WASI
+#else // DOCTEST_PLATFORM
+#define DOCTEST_PLATFORM_LINUX
+#endif // DOCTEST_PLATFORM
+
+namespace doctest {
+ namespace detail {
+ static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; }
+ }
+}
+
+#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
+ static const int var = doctest::detail::consume(&var, __VA_ARGS__); \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#ifndef DOCTEST_BREAK_INTO_DEBUGGER
+// should probably take a look at https://github.com/scottt/debugbreak
+#ifdef DOCTEST_PLATFORM_LINUX
+#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
+// Break at the location of the failing check if possible
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
+#else
+#include
+#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
+#endif
+#elif defined(DOCTEST_PLATFORM_MAC)
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
+#elif defined(__ppc__) || defined(__ppc64__)
+// https://www.cocoawithlove.com/2008/03/break-into-debugger.html
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler)
+#else
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler)
+#endif
+#elif DOCTEST_MSVC
+#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
+#elif defined(__MINGW32__)
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
+extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
+#else // linux
+#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0))
+#endif // linux
+#endif // DOCTEST_BREAK_INTO_DEBUGGER
+
+// this is kept here for backwards compatibility since the config option was changed
+#ifdef DOCTEST_CONFIG_USE_IOSFWD
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
+#endif // DOCTEST_CONFIG_USE_IOSFWD
+
+// for clang - always include ciso646 (which drags some std stuff) because
+// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in
+// which case we don't want to forward declare stuff from std - for reference:
+// https://github.com/doctest/doctest/issues/126
+// https://github.com/doctest/doctest/issues/356
+#if DOCTEST_CLANG
+#include
+#endif // clang
+
+#ifdef _LIBCPP_VERSION
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
+#endif // _LIBCPP_VERSION
+
+#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
+#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
+#include
+#include
+#include
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
+#else // DOCTEST_CONFIG_USE_STD_HEADERS
+
+// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
+
+namespace std { // NOLINT(cert-dcl58-cpp)
+ typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using)
+ typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using)
+ template
+ struct char_traits;
+ template <>
+ struct char_traits;
+ template
+ class basic_ostream; // NOLINT(fuchsia-virtual-inheritance)
+ typedef basic_ostream> ostream; // NOLINT(modernize-use-using)
+ template
+ // NOLINTNEXTLINE
+ basic_ostream& operator<<(basic_ostream&, const char*);
+ template
+ class basic_istream;
+ typedef basic_istream> istream; // NOLINT(modernize-use-using)
+ template
+ class tuple;
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+ // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+ template
+ class allocator;
+ template
+ class basic_string;
+ using string = basic_string, allocator>;
+#endif // VS 2019
+} // namespace std
+
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_USE_STD_HEADERS
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#include
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+namespace doctest {
+
+ using std::size_t;
+
+ DOCTEST_INTERFACE extern bool is_running_in_test;
+
+#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE
+#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned
+#endif
+
+ // A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length
+ // of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for:
+ // - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128)
+ // - if small - capacity left before going on the heap - using the lowest 5 bits
+ // - if small - 2 bits are left unused - the second and third highest ones
+ // - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator)
+ // and the "is small" bit remains "0" ("as well as the capacity left") so its OK
+ // Idea taken from this lecture about the string implementation of facebook/folly - fbstring
+ // https://www.youtube.com/watch?v=kPR8h4-qZdk
+ // TODO:
+ // - optimizations - like not deleting memory unnecessarily in operator= and etc.
+ // - resize/reserve/clear
+ // - replace
+ // - back/front
+ // - iterator stuff
+ // - find & friends
+ // - push_back/pop_back
+ // - assign/insert/erase
+ // - relational operators as free functions - taking const char* as one of the params
+ class DOCTEST_INTERFACE String
+ {
+ public:
+ using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE;
+
+ private:
+ static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members
+ static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members
+
+ struct view // len should be more than sizeof(view) - because of the final byte for flags
+ {
+ char* ptr;
+ size_type size;
+ size_type capacity;
+ };
+
+ union
+ {
+ char buf[len]; // NOLINT(*-avoid-c-arrays)
+ view data;
+ };
+
+ char* allocate(size_type sz);
+
+ bool isOnStack() const noexcept { return (buf[last] & 128) == 0; }
+ void setOnHeap() noexcept;
+ void setLast(size_type in = last) noexcept;
+ void setSize(size_type sz) noexcept;
+
+ void copy(const String& other);
+
+ public:
+ static DOCTEST_CONSTEXPR size_type npos = static_cast(-1);
+
+ String() noexcept;
+ ~String();
+
+ // cppcheck-suppress noExplicitConstructor
+ String(const char* in);
+ String(const char* in, size_type in_size);
+
+ String(std::istream& in, size_type in_size);
+
+ String(const String& other);
+ String& operator=(const String& other);
+
+ String& operator+=(const String& other);
+
+ String(String&& other) noexcept;
+ String& operator=(String&& other) noexcept;
+
+ char operator[](size_type i) const;
+ char& operator[](size_type i);
+
+ // the only functions I'm willing to leave in the interface - available for inlining
+ const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT
+ char* c_str() {
+ if (isOnStack()) {
+ return reinterpret_cast(buf);
+ }
+ return data.ptr;
+ }
+
+ size_type size() const;
+ size_type capacity() const;
+
+ String substr(size_type pos, size_type cnt = npos)&&;
+ String substr(size_type pos, size_type cnt = npos) const&;
+
+ size_type find(char ch, size_type pos = 0) const;
+ size_type rfind(char ch, size_type pos = npos) const;
+
+ int compare(const char* other, bool no_case = false) const;
+ int compare(const String& other, bool no_case = false) const;
+
+ friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
+ };
+
+ DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs);
+
+ DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs);
+
+ class DOCTEST_INTERFACE Contains {
+ public:
+ explicit Contains(const String& string);
+
+ bool checkWith(const String& other) const;
+
+ String string;
+ };
+
+ DOCTEST_INTERFACE String toString(const Contains& in);
+
+ DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs);
+ DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs);
+ DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs);
+ DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs);
+
+ namespace Color {
+ enum Enum
+ {
+ None = 0,
+ White,
+ Red,
+ Green,
+ Blue,
+ Cyan,
+ Yellow,
+ Grey,
+
+ Bright = 0x10,
+
+ BrightRed = Bright | Red,
+ BrightGreen = Bright | Green,
+ LightGrey = Bright | Grey,
+ BrightWhite = Bright | White
+ };
+
+ DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code);
+ } // namespace Color
+
+ namespace assertType {
+ enum Enum
+ {
+ // macro traits
+
+ is_warn = 1,
+ is_check = 2 * is_warn,
+ is_require = 2 * is_check,
+
+ is_normal = 2 * is_require,
+ is_throws = 2 * is_normal,
+ is_throws_as = 2 * is_throws,
+ is_throws_with = 2 * is_throws_as,
+ is_nothrow = 2 * is_throws_with,
+
+ is_false = 2 * is_nothrow,
+ is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types
+
+ is_eq = 2 * is_unary,
+ is_ne = 2 * is_eq,
+
+ is_lt = 2 * is_ne,
+ is_gt = 2 * is_lt,
+
+ is_ge = 2 * is_gt,
+ is_le = 2 * is_ge,
+
+ // macro types
+
+ DT_WARN = is_normal | is_warn,
+ DT_CHECK = is_normal | is_check,
+ DT_REQUIRE = is_normal | is_require,
+
+ DT_WARN_FALSE = is_normal | is_false | is_warn,
+ DT_CHECK_FALSE = is_normal | is_false | is_check,
+ DT_REQUIRE_FALSE = is_normal | is_false | is_require,
+
+ DT_WARN_THROWS = is_throws | is_warn,
+ DT_CHECK_THROWS = is_throws | is_check,
+ DT_REQUIRE_THROWS = is_throws | is_require,
+
+ DT_WARN_THROWS_AS = is_throws_as | is_warn,
+ DT_CHECK_THROWS_AS = is_throws_as | is_check,
+ DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
+
+ DT_WARN_THROWS_WITH = is_throws_with | is_warn,
+ DT_CHECK_THROWS_WITH = is_throws_with | is_check,
+ DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
+
+ DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
+ DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
+ DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
+
+ DT_WARN_NOTHROW = is_nothrow | is_warn,
+ DT_CHECK_NOTHROW = is_nothrow | is_check,
+ DT_REQUIRE_NOTHROW = is_nothrow | is_require,
+
+ DT_WARN_EQ = is_normal | is_eq | is_warn,
+ DT_CHECK_EQ = is_normal | is_eq | is_check,
+ DT_REQUIRE_EQ = is_normal | is_eq | is_require,
+
+ DT_WARN_NE = is_normal | is_ne | is_warn,
+ DT_CHECK_NE = is_normal | is_ne | is_check,
+ DT_REQUIRE_NE = is_normal | is_ne | is_require,
+
+ DT_WARN_GT = is_normal | is_gt | is_warn,
+ DT_CHECK_GT = is_normal | is_gt | is_check,
+ DT_REQUIRE_GT = is_normal | is_gt | is_require,
+
+ DT_WARN_LT = is_normal | is_lt | is_warn,
+ DT_CHECK_LT = is_normal | is_lt | is_check,
+ DT_REQUIRE_LT = is_normal | is_lt | is_require,
+
+ DT_WARN_GE = is_normal | is_ge | is_warn,
+ DT_CHECK_GE = is_normal | is_ge | is_check,
+ DT_REQUIRE_GE = is_normal | is_ge | is_require,
+
+ DT_WARN_LE = is_normal | is_le | is_warn,
+ DT_CHECK_LE = is_normal | is_le | is_check,
+ DT_REQUIRE_LE = is_normal | is_le | is_require,
+
+ DT_WARN_UNARY = is_normal | is_unary | is_warn,
+ DT_CHECK_UNARY = is_normal | is_unary | is_check,
+ DT_REQUIRE_UNARY = is_normal | is_unary | is_require,
+
+ DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn,
+ DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check,
+ DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require,
+ };
+ } // namespace assertType
+
+ DOCTEST_INTERFACE const char* assertString(assertType::Enum at);
+ DOCTEST_INTERFACE const char* failureString(assertType::Enum at);
+ DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file);
+
+ struct DOCTEST_INTERFACE TestCaseData
+ {
+ String m_file; // the file in which the test was registered (using String - see #350)
+ unsigned m_line; // the line where the test was registered
+ const char* m_name; // name of the test case
+ const char* m_test_suite; // the test suite in which the test was added
+ const char* m_description;
+ bool m_skip;
+ bool m_no_breaks;
+ bool m_no_output;
+ bool m_may_fail;
+ bool m_should_fail;
+ int m_expected_failures;
+ double m_timeout;
+ };
+
+ struct DOCTEST_INTERFACE AssertData
+ {
+ // common - for all asserts
+ const TestCaseData* m_test_case;
+ assertType::Enum m_at;
+ const char* m_file;
+ int m_line;
+ const char* m_expr;
+ bool m_failed;
+
+ // exception-related - for all asserts
+ bool m_threw;
+ String m_exception;
+
+ // for normal asserts
+ String m_decomp;
+
+ // for specific exception-related asserts
+ bool m_threw_as;
+ const char* m_exception_type;
+
+ class DOCTEST_INTERFACE StringContains {
+ private:
+ Contains content;
+ bool isContains;
+
+ public:
+ StringContains(const String& str) : content(str), isContains(false) { }
+ StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { }
+
+ bool check(const String& str) { return isContains ? (content == str) : (content.string == str); }
+
+ operator const String& () const { return content.string; }
+
+ const char* c_str() const { return content.string.c_str(); }
+ } m_exception_string;
+
+ AssertData(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const StringContains& exception_string);
+ };
+
+ struct DOCTEST_INTERFACE MessageData
+ {
+ String m_string;
+ const char* m_file;
+ int m_line;
+ assertType::Enum m_severity;
+ };
+
+ struct DOCTEST_INTERFACE SubcaseSignature
+ {
+ String m_name;
+ const char* m_file;
+ int m_line;
+
+ bool operator==(const SubcaseSignature& other) const;
+ bool operator<(const SubcaseSignature& other) const;
+ };
+
+ struct DOCTEST_INTERFACE IContextScope
+ {
+ DOCTEST_DECLARE_INTERFACE(IContextScope)
+ virtual void stringify(std::ostream*) const = 0;
+ };
+
+ namespace detail {
+ struct DOCTEST_INTERFACE TestCase;
+ } // namespace detail
+
+ struct ContextOptions //!OCLINT too many fields
+ {
+ std::ostream* cout = nullptr; // stdout stream
+ String binary_name; // the test binary name
+
+ const detail::TestCase* currentTest = nullptr;
+
+ // == parameters from the command line
+ String out; // output filename
+ String order_by; // how tests should be ordered
+ unsigned rand_seed; // the seed for rand ordering
+
+ unsigned first; // the first (matching) test to be executed
+ unsigned last; // the last (matching) test to be executed
+
+ int abort_after; // stop tests after this many failed assertions
+ int subcase_filter_levels; // apply the subcase filters for the first N levels
+
+ bool success; // include successful assertions in output
+ bool case_sensitive; // if filtering should be case sensitive
+ bool exit; // if the program should be exited after the tests are ran/whatever
+ bool duration; // print the time duration of each test case
+ bool minimal; // minimal console output (only test failures)
+ bool quiet; // no console output
+ bool no_throw; // to skip exceptions-related assertion macros
+ bool no_exitcode; // if the framework should return 0 as the exitcode
+ bool no_run; // to not run the tests at all (can be done with an "*" exclude)
+ bool no_intro; // to not print the intro of the framework
+ bool no_version; // to not print the version of the framework
+ bool no_colors; // if output to the console should be colorized
+ bool force_colors; // forces the use of colors even when a tty cannot be detected
+ bool no_breaks; // to not break into the debugger
+ bool no_skip; // don't skip test cases which are marked to be skipped
+ bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x):
+ bool no_path_in_filenames; // if the path to files should be removed from the output
+ bool no_line_numbers; // if source code line numbers should be omitted from the output
+ bool no_debug_output; // no output in the debug console when a debugger is attached
+ bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!!
+ bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!!
+
+ bool help; // to print the help
+ bool version; // to print the version
+ bool count; // if only the count of matching tests is to be retrieved
+ bool list_test_cases; // to list all tests matching the filters
+ bool list_test_suites; // to list all suites matching the filters
+ bool list_reporters; // lists all registered reporters
+ };
+
+ namespace detail {
+ namespace types {
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ using namespace std;
+#else
+ template
+ struct enable_if { };
+
+ template
+ struct enable_if { using type = T; };
+
+ struct true_type { static DOCTEST_CONSTEXPR bool value = true; };
+ struct false_type { static DOCTEST_CONSTEXPR bool value = false; };
+
+ template struct remove_reference { using type = T; };
+ template struct remove_reference { using type = T; };
+ template struct remove_reference { using type = T; };
+
+ template struct is_rvalue_reference : false_type { };
+ template struct is_rvalue_reference : true_type { };
+
+ template struct remove_const { using type = T; };
+ template struct remove_const { using type = T; };
+
+ // Compiler intrinsics
+ template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); };
+ template struct underlying_type { using type = __underlying_type(T); };
+
+ template struct is_pointer : false_type { };
+ template struct is_pointer : true_type { };
+
+ template struct is_array : false_type { };
+ // NOLINTNEXTLINE(*-avoid-c-arrays)
+ template struct is_array : true_type { };
+#endif
+ }
+
+ //
+ template
+ T&& declval();
+
+ template
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT {
+ return static_cast(t);
+ }
+
+ template
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT {
+ return static_cast(t);
+ }
+
+ template
+ struct deferred_false : types::false_type { };
+
+ // MSVS 2015 :(
+#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900
+ template
+ struct has_global_insertion_operator : types::false_type { };
+
+ template
+ struct has_global_insertion_operator(), declval()), void())> : types::true_type { };
+
+ template
+ struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; };
+
+ template
+ struct insert_hack;
+
+ template
+ struct insert_hack {
+ static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); }
+ };
+
+ template
+ struct insert_hack {
+ static void insert(std::ostream& os, const T& t) { operator<<(os, t); }
+ };
+
+ template
+ using insert_hack_t = insert_hack::value>;
+#else
+ template
+ struct has_insertion_operator : types::false_type { };
+#endif
+
+ template
+ struct has_insertion_operator(), declval()), void())> : types::true_type { };
+
+ template
+ struct should_stringify_as_underlying_type {
+ static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value;
+ };
+
+ DOCTEST_INTERFACE std::ostream* tlssPush();
+ DOCTEST_INTERFACE String tlssPop();
+
+ template
+ struct StringMakerBase {
+ template
+ static String convert(const DOCTEST_REF_WRAP(T)) {
+#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES
+ static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual");
+#endif
+ return "{?}";
+ }
+ };
+
+ template
+ struct filldata;
+
+ template
+ void filloss(std::ostream* stream, const T& in) {
+ filldata::fill(stream, in);
+ }
+
+ template
+ void filloss(std::ostream* stream, const T(&in)[N]) { // NOLINT(*-avoid-c-arrays)
+ // T[N], T(&)[N], T(&&)[N] have same behaviour.
+ // Hence remove reference.
+ filloss::type>(stream, in);
+ }
+
+ template
+ String toStream(const T& in) {
+ std::ostream* stream = tlssPush();
+ filloss(stream, in);
+ return tlssPop();
+ }
+
+ template <>
+ struct StringMakerBase {
+ template
+ static String convert(const DOCTEST_REF_WRAP(T) in) {
+ return toStream(in);
+ }
+ };
+ } // namespace detail
+
+ template
+ struct StringMaker : public detail::StringMakerBase<
+ detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value>
+ {};
+
+#ifndef DOCTEST_STRINGIFY
+#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY
+#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__))
+#else
+#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__)
+#endif
+#endif
+
+ template
+ String toString() {
+#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0
+ String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void)
+ String::size_type beginPos = ret.find('<');
+ return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)")));
+#else
+ String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE]
+ String::size_type begin = ret.find('=') + 2;
+ return ret.substr(begin, ret.size() - begin - 1);
+#endif
+ }
+
+ template ::value, bool>::type = true>
+ String toString(const DOCTEST_REF_WRAP(T) value) {
+ return StringMaker::convert(value);
+ }
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE String toString(const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+ // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+ DOCTEST_INTERFACE String toString(const std::string& in);
+#endif // VS 2019
+
+ DOCTEST_INTERFACE String toString(String in);
+
+ DOCTEST_INTERFACE String toString(std::nullptr_t);
+
+ DOCTEST_INTERFACE String toString(bool in);
+
+ DOCTEST_INTERFACE String toString(float in);
+ DOCTEST_INTERFACE String toString(double in);
+ DOCTEST_INTERFACE String toString(double long in);
+
+ DOCTEST_INTERFACE String toString(char in);
+ DOCTEST_INTERFACE String toString(char signed in);
+ DOCTEST_INTERFACE String toString(char unsigned in);
+ DOCTEST_INTERFACE String toString(short in);
+ DOCTEST_INTERFACE String toString(short unsigned in);
+ DOCTEST_INTERFACE String toString(signed in);
+ DOCTEST_INTERFACE String toString(unsigned in);
+ DOCTEST_INTERFACE String toString(long in);
+ DOCTEST_INTERFACE String toString(long unsigned in);
+ DOCTEST_INTERFACE String toString(long long in);
+ DOCTEST_INTERFACE String toString(long long unsigned in);
+
+ template ::value, bool>::type = true>
+ String toString(const DOCTEST_REF_WRAP(T) value) {
+ using UT = typename detail::types::underlying_type::type;
+ return (DOCTEST_STRINGIFY(static_cast(value)));
+ }
+
+ namespace detail {
+ template
+ struct filldata
+ {
+ static void fill(std::ostream* stream, const T& in) {
+#if defined(_MSC_VER) && _MSC_VER <= 1900
+ insert_hack_t::insert(*stream, in);
+#else
+ operator<<(*stream, in);
+#endif
+ }
+ };
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
+ // NOLINTBEGIN(*-avoid-c-arrays)
+ template
+ struct filldata {
+ static void fill(std::ostream* stream, const T(&in)[N]) {
+ *stream << "[";
+ for (size_t i = 0; i < N; i++) {
+ if (i != 0) { *stream << ", "; }
+ *stream << (DOCTEST_STRINGIFY(in[i]));
+ }
+ *stream << "]";
+ }
+ };
+ // NOLINTEND(*-avoid-c-arrays)
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ // Specialized since we don't want the terminating null byte!
+ // NOLINTBEGIN(*-avoid-c-arrays)
+ template
+ struct filldata {
+ static void fill(std::ostream* stream, const char(&in)[N]) {
+ *stream << String(in, in[N - 1] ? N : N - 1);
+ } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
+ };
+ // NOLINTEND(*-avoid-c-arrays)
+
+ template <>
+ struct filldata {
+ static void fill(std::ostream* stream, const void* in);
+ };
+
+ template
+ struct filldata {
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180)
+ static void fill(std::ostream* stream, const T* in) {
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast")
+ filldata::fill(stream,
+#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
+ reinterpret_cast(in)
+#else
+ * reinterpret_cast(&in)
+#endif
+ );
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ }
+ };
+ }
+
+ struct DOCTEST_INTERFACE Approx
+ {
+ Approx(double value);
+
+ Approx operator()(double value) const;
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template
+ explicit Approx(const T& value,
+ typename detail::types::enable_if::value>::type* =
+ static_cast(nullptr)) {
+ *this = static_cast(value);
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& epsilon(double newEpsilon);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template
+ typename std::enable_if::value, Approx&>::type epsilon(
+ const T& newEpsilon) {
+ m_epsilon = static_cast(newEpsilon);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& scale(double newScale);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template
+ typename std::enable_if::value, Approx&>::type scale(
+ const T& newScale) {
+ m_scale = static_cast(newScale);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format off
+ DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator==(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator!=(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator<=(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator>=(const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator< (const Approx& lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx& rhs);
+ DOCTEST_INTERFACE friend bool operator> (const Approx& lhs, double rhs);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_APPROX_PREFIX \
+ template friend typename std::enable_if::value, bool>::type
+
+ DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); }
+ DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; }
+#undef DOCTEST_APPROX_PREFIX
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format on
+
+ double m_epsilon;
+ double m_scale;
+ double m_value;
+ };
+
+ DOCTEST_INTERFACE String toString(const Approx& in);
+
+ DOCTEST_INTERFACE const ContextOptions* getContextOptions();
+
+ template
+ struct DOCTEST_INTERFACE_DECL IsNaN
+ {
+ F value; bool flipped;
+ IsNaN(F f, bool flip = false) : value(f), flipped(flip) { }
+ IsNaN operator!() const { return { value, !flipped }; }
+ operator bool() const;
+ };
+#ifndef __MINGW32__
+ extern template struct DOCTEST_INTERFACE_DECL IsNaN;
+ extern template struct DOCTEST_INTERFACE_DECL IsNaN;
+ extern template struct DOCTEST_INTERFACE_DECL IsNaN;
+#endif
+ DOCTEST_INTERFACE String toString(IsNaN in);
+ DOCTEST_INTERFACE String toString(IsNaN in);
+ DOCTEST_INTERFACE String toString(IsNaN in);
+
+#ifndef DOCTEST_CONFIG_DISABLE
+
+ namespace detail {
+ // clang-format off
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ template struct decay_array { using type = T; };
+ template struct decay_array { using type = T*; };
+ template struct decay_array { using type = T*; };
+
+ template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; };
+ template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; };
+ template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; };
+
+ template struct can_use_op : public not_char_pointer::type> {};
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+ struct DOCTEST_INTERFACE TestFailureException
+ {
+ };
+
+ DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_NORETURN
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_INTERFACE void throwException();
+
+ struct DOCTEST_INTERFACE Subcase
+ {
+ SubcaseSignature m_signature;
+ bool m_entered = false;
+
+ Subcase(const String& name, const char* file, int line);
+ Subcase(const Subcase&) = delete;
+ Subcase(Subcase&&) = delete;
+ Subcase& operator=(const Subcase&) = delete;
+ Subcase& operator=(Subcase&&) = delete;
+ ~Subcase();
+
+ operator bool() const;
+
+ private:
+ bool checkFilters();
+ };
+
+ template
+ String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs));
+ }
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
+#endif
+
+ // This will check if there is any way it could find a operator like member or friend and uses it.
+ // If not it doesn't find the operator or if the operator at global scope is defined after
+ // this template, the template won't be instantiated due to SFINAE. Once the template is not
+ // instantiated it can look for global operator using normal conversions.
+#ifdef __NVCC__
+#define SFINAE_OP(ret,op) ret
+#else
+#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{})
+#endif
+
+#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
+ template \
+ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
+ bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \
+ if(m_at & assertType::is_false) \
+ res = !res; \
+ if(!res || doctest::getContextOptions()->success) \
+ return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \
+ return Result(res); \
+ }
+
+ // more checks could be added - like in Catch:
+ // https://github.com/catchorg/Catch2/pull/1480/files
+ // https://github.com/catchorg/Catch2/pull/1481/files
+#define DOCTEST_FORBIT_EXPRESSION(rt, op) \
+ template \
+ rt& operator op(const R&) { \
+ static_assert(deferred_false::value, \
+ "Expression Too Complex Please Rewrite As Binary Comparison!"); \
+ return *this; \
+ }
+
+ struct DOCTEST_INTERFACE Result // NOLINT(*-member-init)
+ {
+ bool m_passed;
+ String m_decomp;
+
+ Result() = default; // TODO: Why do we need this? (To remove NOLINT)
+ Result(bool passed, const String& decomposition = String());
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Result, &)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^)
+ DOCTEST_FORBIT_EXPRESSION(Result, | )
+ DOCTEST_FORBIT_EXPRESSION(Result, &&)
+ DOCTEST_FORBIT_EXPRESSION(Result, || )
+ DOCTEST_FORBIT_EXPRESSION(Result, == )
+ DOCTEST_FORBIT_EXPRESSION(Result, != )
+ DOCTEST_FORBIT_EXPRESSION(Result, < )
+ DOCTEST_FORBIT_EXPRESSION(Result, > )
+ DOCTEST_FORBIT_EXPRESSION(Result, <= )
+ DOCTEST_FORBIT_EXPRESSION(Result, >= )
+ DOCTEST_FORBIT_EXPRESSION(Result, =)
+ DOCTEST_FORBIT_EXPRESSION(Result, +=)
+ DOCTEST_FORBIT_EXPRESSION(Result, -=)
+ DOCTEST_FORBIT_EXPRESSION(Result, *=)
+ DOCTEST_FORBIT_EXPRESSION(Result, /=)
+ DOCTEST_FORBIT_EXPRESSION(Result, %=)
+ DOCTEST_FORBIT_EXPRESSION(Result, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Result, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Result, &=)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Result, |=)
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+ // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
+ DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch
+ //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ // clang-format off
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE bool
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type
+ inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
+ inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
+ inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
+ inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); }
+ inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
+ inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+#define DOCTEST_RELATIONAL_OP(name, op) \
+ template \
+ DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \
+ const DOCTEST_REF_WRAP(R) rhs) { \
+ return lhs op rhs; \
+ }
+
+ DOCTEST_RELATIONAL_OP(eq, == )
+ DOCTEST_RELATIONAL_OP(ne, != )
+ DOCTEST_RELATIONAL_OP(lt, < )
+ DOCTEST_RELATIONAL_OP(gt, > )
+ DOCTEST_RELATIONAL_OP(le, <= )
+ DOCTEST_RELATIONAL_OP(ge, >= )
+
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) l == r
+#define DOCTEST_CMP_NE(l, r) l != r
+#define DOCTEST_CMP_GT(l, r) l > r
+#define DOCTEST_CMP_LT(l, r) l < r
+#define DOCTEST_CMP_GE(l, r) l >= r
+#define DOCTEST_CMP_LE(l, r) l <= r
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) eq(l, r)
+#define DOCTEST_CMP_NE(l, r) ne(l, r)
+#define DOCTEST_CMP_GT(l, r) gt(l, r)
+#define DOCTEST_CMP_LT(l, r) lt(l, r)
+#define DOCTEST_CMP_GE(l, r) ge(l, r)
+#define DOCTEST_CMP_LE(l, r) le(l, r)
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+ template
+ // cppcheck-suppress copyCtorAndEqOperator
+ struct Expression_lhs
+ {
+ L lhs;
+ assertType::Enum m_at;
+
+ explicit Expression_lhs(L&& in, assertType::Enum at)
+ : lhs(static_cast(in))
+ , m_at(at) {}
+
+ DOCTEST_NOINLINE operator Result() {
+ // this is needed only for MSVC 2015
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
+ bool res = static_cast(lhs);
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
+ res = !res;
+ }
+
+ if (!res || getContextOptions()->success) {
+ return { res, (DOCTEST_STRINGIFY(lhs)) };
+ }
+ return { res };
+ }
+
+ /* This is required for user-defined conversions from Expression_lhs to L */
+ operator L() const { return lhs; }
+
+ // clang-format off
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(== , " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!= , " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(> , " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(< , " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>= , " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<= , " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
+ // clang-format on
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, | )
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, || )
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=)
+ // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
+ // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, << )
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >> )
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#endif
+
+ struct DOCTEST_INTERFACE ExpressionDecomposer
+ {
+ assertType::Enum m_at;
+
+ ExpressionDecomposer(assertType::Enum at);
+
+ // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
+ // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
+ // https://github.com/catchorg/Catch2/issues/870
+ // https://github.com/catchorg/Catch2/issues/565
+ template
+ Expression_lhs operator<<(L&& operand) {
+ return Expression_lhs(static_cast(operand), m_at);
+ }
+
+ template ::value, void >::type* = nullptr>
+ Expression_lhs operator<<(const L& operand) {
+ return Expression_lhs(operand, m_at);
+ }
+ };
+
+ struct DOCTEST_INTERFACE TestSuite
+ {
+ const char* m_test_suite = nullptr;
+ const char* m_description = nullptr;
+ bool m_skip = false;
+ bool m_no_breaks = false;
+ bool m_no_output = false;
+ bool m_may_fail = false;
+ bool m_should_fail = false;
+ int m_expected_failures = 0;
+ double m_timeout = 0;
+
+ TestSuite& operator*(const char* in);
+
+ template
+ TestSuite& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+ };
+
+ using funcType = void (*)();
+
+ struct DOCTEST_INTERFACE TestCase : public TestCaseData
+ {
+ funcType m_test; // a function pointer to the test case
+
+ String m_type; // for templated test cases - gets appended to the real name
+ int m_template_id; // an ID used to distinguish between the different versions of a templated test case
+ String m_full_name; // contains the name (only for templated test cases!) + the template type
+
+ TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
+ const String& type = String(), int template_id = -1);
+
+ TestCase(const TestCase& other);
+ TestCase(TestCase&&) = delete;
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
+ TestCase& operator=(const TestCase& other);
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ TestCase& operator=(TestCase&&) = delete;
+
+ TestCase& operator*(const char* in);
+
+ template
+ TestCase& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+
+ bool operator<(const TestCase& other) const;
+
+ ~TestCase() = default;
+ };
+
+ // forward declarations of functions used by the macros
+ DOCTEST_INTERFACE int regTest(const TestCase& tc);
+ DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
+ DOCTEST_INTERFACE bool isDebuggerActive();
+
+ template
+ int instantiationHelper(const T&) { return 0; }
+
+ namespace binaryAssertComparison {
+ enum Enum
+ {
+ eq = 0,
+ ne,
+ gt,
+ lt,
+ ge,
+ le
+ };
+ } // namespace binaryAssertComparison
+
+ // clang-format off
+ template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R)) const { return false; } };
+
+#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
+ template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
+ // clang-format on
+
+ DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq)
+ DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne)
+ DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt)
+ DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt)
+ DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge)
+ DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le)
+
+ struct DOCTEST_INTERFACE ResultBuilder : public AssertData
+ {
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type = "", const String& exception_string = "");
+
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const Contains& exception_string);
+
+ void setResult(const Result& res);
+
+ template
+ DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ m_failed = !RelationalComparator()(lhs, rhs);
+ if (m_failed || getContextOptions()->success) {
+ m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
+ }
+ return !m_failed;
+ }
+
+ template