From b543e3182d6e7e3b6cf18ae4087d8542987da791 Mon Sep 17 00:00:00 2001
From: merttozer <mertt.ozer@hotmail.com>
Date: Sun, 14 Apr 2024 16:23:25 +0300
Subject: [PATCH] Port tutorial codes to C++11, fixing issue #977 partially

---
 .../Tutorials/Tutorial-DpdkL2Fwd/main.cpp     |  66 +++-------
 .../Tutorials/Tutorial-HelloWorld/main.cpp    |  11 +-
 .../Tutorials/Tutorial-LiveTraffic/main.cpp   | 120 +++++++++---------
 .../Tutorial-PacketCraftAndEdit/main.cpp      |  31 +++--
 .../Tutorials/Tutorial-PacketParsing/main.cpp | 107 +++++++---------
 .../Tutorials/Tutorial-PcapFiles/main.cpp     |  29 +++--
 6 files changed, 162 insertions(+), 202 deletions(-)

diff --git a/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp b/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp
index 4f9ceecc2c..20b0d3b1c1 100644
--- a/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp
+++ b/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp
@@ -4,47 +4,31 @@
 #include "SystemUtils.h"
 #include "DpdkDeviceList.h"
 #include "TablePrinter.h"
-
 #include "WorkerThread.h"
 
-
 #define MBUF_POOL_SIZE 16*1024-1
 #define DEVICE_ID_1 0
 #define DEVICE_ID_2 1
-
 #define COLLECT_STATS_EVERY_SEC 2
 
-
 // Keep running flag
 bool keepRunning = true;
 
 void onApplicationInterrupted(void* cookie)
 {
 	keepRunning = false;
-	std::cout << std::endl << "Shutting down..." << std::endl;
+    std::cout << "\nShutting down...\n";
 }
 
 
 void printStats(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice)
 {
-	pcpp::DpdkDevice::DpdkDeviceStats rxStats;
-	pcpp::DpdkDevice::DpdkDeviceStats txStats;
+	pcpp::DpdkDevice::DpdkDeviceStats rxStats, txStats;
 	rxDevice->getStatistics(rxStats);
 	txDevice->getStatistics(txStats);
 
-	std::vector<std::string> columnNames;
-	columnNames.push_back(" ");
-	columnNames.push_back("Total Packets");
-	columnNames.push_back("Packets/sec");
-	columnNames.push_back("Bytes");
-	columnNames.push_back("Bits/sec");
-
-	std::vector<int> columnLengths;
-	columnLengths.push_back(10);
-	columnLengths.push_back(15);
-	columnLengths.push_back(15);
-	columnLengths.push_back(15);
-	columnLengths.push_back(15);
+	std::vector<std::string> columnNames = {" ", "Total Packets", "Packets/sec", "Bytes", "Bits/sec"};
+    std::vector<int> columnLengths = {10, 15, 15, 15, 15};
 
 	pcpp::TablePrinter printer(columnNames, columnLengths);
 
@@ -68,49 +52,46 @@ int main(int argc, char* argv[])
 	pcpp::DpdkDeviceList::initDpdk(coreMaskToUse, MBUF_POOL_SIZE);
 
 	// Find DPDK devices
-	pcpp::DpdkDevice* device1 = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(DEVICE_ID_1);
-	if (device1 == NULL)
+	auto* device1 = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(DEVICE_ID_1);
+	if (device1 == nullptr)
 	{
-		std::cerr << "Cannot find device1 with port '" << DEVICE_ID_1 << "'" << std::endl;
+		std::cerr << "Cannot find device1 with port '" << DEVICE_ID_1 << "'\n";
 		return 1;
 	}
 
-	pcpp::DpdkDevice* device2 = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(DEVICE_ID_2);
-	if (device2 == NULL)
+	auto* device2 = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(DEVICE_ID_2);
+	if (device2 == nullptr)
 	{
-		std::cerr << "Cannot find device2 with port '" << DEVICE_ID_2 << "'" << std::endl;
+		std::cerr << "Cannot find device2 with port '" << DEVICE_ID_2 << "'\n";
 		return 1;
 	}
 
 	// Open DPDK devices
 	if (!device1->openMultiQueues(1, 1))
 	{
-		std::cerr << "Couldn't open device1 #" << device1->getDeviceId() << ", PMD '" << device1->getPMDName() << "'" << std::endl;
+		std::cerr << "Couldn't open device1 #" << device1->getDeviceId() << ", PMD '" << device1->getPMDName() << "'\n";
 		return 1;
 	}
 
 	if (!device2->openMultiQueues(1, 1))
 	{
-		std::cerr << "Couldn't open device2 #" << device2->getDeviceId() << ", PMD '" << device2->getPMDName() << "'" << std::endl;
+		std::cerr << "Couldn't open device2 #" << device2->getDeviceId() << ", PMD '" << device2->getPMDName() << "'\n";
 		return 1;
 	}
 
 	// Create worker threads
 	std::vector<pcpp::DpdkWorkerThread*> workers;
-	workers.push_back(new L2FwdWorkerThread(device1, device2));
-	workers.push_back(new L2FwdWorkerThread(device2, device1));
+	// Constructs a DpdkWorkerThread* directly within the vector's storage
+	workers.emplace_back(new L2FwdWorkerThread(device1, device2));
+	workers.emplace_back(new L2FwdWorkerThread(device2, device1));
 
 	// Create core mask - use core 1 and 2 for the two threads
-	int workersCoreMask = 0;
-	for (int i = 1; i <= 2; i++)
-	{
-		workersCoreMask = workersCoreMask | (1 << i);
-	}
+	int workersCoreMask = 0x06; // Binary 110, using cores 1 and 2
 
 	// Start capture in async mode
 	if (!pcpp::DpdkDeviceList::getInstance().startDpdkWorkerThreads(workersCoreMask, workers))
 	{
-		std::cerr << "Couldn't start worker threads" << std::endl;
+		std::cerr << "Couldn't start worker threads\n";
 		return 1;
 	}
 
@@ -129,21 +110,14 @@ int main(int argc, char* argv[])
 			// Clear screen and move to top left
 			std::cout << "\033[2J\033[1;1H";
 
-			std::cout
-				<< "Stats #" << statsCounter++ << std::endl
-				<< "==========" << std::endl
-				<< std::endl;
+			std::cout << "Stats #" << statsCounter++ << "\n==========\n\n";
 
 			// Print stats of traffic going from Device1 to Device2
-			std::cout << std::endl
-				<< "Device1->Device2 stats:" << std::endl
-				<< std::endl;
+			std::cout << "\nDevice1->Device2 stats:\n\n";
 			printStats(device1, device2);
 
 			// Print stats of traffic going from Device2 to Device1
-			std::cout << std::endl
-				<< "Device2->Device1 stats:" << std::endl
-				<< std::endl;
+			std::cout << "\nDevice2->Device1 stats:\n\n";
 			printStats(device2, device1);
 		}
 		counter++;
diff --git a/Examples/Tutorials/Tutorial-HelloWorld/main.cpp b/Examples/Tutorials/Tutorial-HelloWorld/main.cpp
index fcad0e09fb..168f2d74a0 100644
--- a/Examples/Tutorials/Tutorial-HelloWorld/main.cpp
+++ b/Examples/Tutorials/Tutorial-HelloWorld/main.cpp
@@ -9,7 +9,7 @@ int main(int argc, char* argv[])
 	pcpp::PcapFileReaderDevice reader("1_packet.pcap");
 	if (!reader.open())
 	{
-		std::cerr << "Error opening the pcap file" << std::endl;
+		std::cerr << "Error opening the pcap file\n";
 		return 1;
 	}
 
@@ -17,7 +17,7 @@ int main(int argc, char* argv[])
 	pcpp::RawPacket rawPacket;
 	if (!reader.getNextPacket(rawPacket))
 	{
-		std::cerr << "Couldn't read the first packet in the file" << std::endl;
+		std::cerr << "Couldn't read the first packet in the file\n";
 		return 1;
 	}
 
@@ -28,14 +28,13 @@ int main(int argc, char* argv[])
 	if (parsedPacket.isPacketOfType(pcpp::IPv4))
 	{
 		// extract source and dest IPs
-		pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType<pcpp::IPv4Layer>()->getSrcIPv4Address();
-		pcpp::IPv4Address destIP = parsedPacket.getLayerOfType<pcpp::IPv4Layer>()->getDstIPv4Address();
+		auto srcIP = parsedPacket.getLayerOfType<pcpp::IPv4Layer>()->getSrcIPv4Address();
+		auto destIP = parsedPacket.getLayerOfType<pcpp::IPv4Layer>()->getDstIPv4Address();
 
 		// print source and dest IPs
 		std::cout
 			<< "Source IP is '" << srcIP << "'; "
-			<< "Dest IP is '" << destIP << "'"
-			<< std::endl;
+			<< "Dest IP is '" << destIP << "'\n";
 	}
 
 	// close the file
diff --git a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp
index 834a397872..28a8599770 100644
--- a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp
+++ b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <algorithm>
 #include "stdlib.h"
 #include "PcapLiveDeviceList.h"
 #include "SystemUtils.h"
@@ -7,25 +8,23 @@
  */
 struct PacketStats
 {
-	int ethPacketCount;
-	int ipv4PacketCount;
-	int ipv6PacketCount;
-	int tcpPacketCount;
-	int udpPacketCount;
-	int dnsPacketCount;
-	int httpPacketCount;
-	int sslPacketCount;
+	int ethPacketCount = 0;
+    int ipv4PacketCount = 0;
+    int ipv6PacketCount = 0;
+    int tcpPacketCount = 0;
+    int udpPacketCount = 0;
+    int dnsPacketCount = 0;
+    int httpPacketCount = 0;
+    int sslPacketCount = 0;
 
 
 	/**
 	 * Clear all stats
 	 */
-	void clear() { ethPacketCount = 0; ipv4PacketCount = 0; ipv6PacketCount = 0; tcpPacketCount = 0; udpPacketCount = 0; tcpPacketCount = 0; dnsPacketCount = 0; httpPacketCount = 0; sslPacketCount = 0; }
+	void clear() { ethPacketCount = ipv4PacketCount = ipv6PacketCount = tcpPacketCount = udpPacketCount = dnsPacketCount = httpPacketCount = sslPacketCount = 0; }
 
-	/**
-	 * C'tor
-	 */
-	PacketStats() { clear(); }
+	// Constructor is optional here since the members are already initialized
+	PacketStats() = default;
 
 	/**
 	 * Collect stats from a packet
@@ -55,15 +54,14 @@ struct PacketStats
 	 */
 	void printToConsole()
 	{
-		std::cout
-			<< "Ethernet packet count: " << ethPacketCount << std::endl
-			<< "IPv4 packet count:     " << ipv4PacketCount << std::endl
-			<< "IPv6 packet count:     " << ipv6PacketCount << std::endl
-			<< "TCP packet count:      " << tcpPacketCount << std::endl
-			<< "UDP packet count:      " << udpPacketCount << std::endl
-			<< "DNS packet count:      " << dnsPacketCount << std::endl
-			<< "HTTP packet count:     " << httpPacketCount << std::endl
-			<< "SSL packet count:      " << sslPacketCount << std::endl;
+		std::cout << "Ethernet packet count: " << ethPacketCount << "\n"
+                  << "IPv4 packet count:     " << ipv4PacketCount << "\n"
+                  << "IPv6 packet count:     " << ipv6PacketCount << "\n"
+                  << "TCP packet count:      " << tcpPacketCount << "\n"
+                  << "UDP packet count:      " << udpPacketCount << "\n"
+                  << "DNS packet count:      " << dnsPacketCount << "\n"
+                  << "HTTP packet count:     " << httpPacketCount << "\n"
+                  << "SSL packet count:      " << sslPacketCount << "\n";
 	}
 };
 
@@ -74,7 +72,7 @@ struct PacketStats
 static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie)
 {
 	// extract the stats object form the cookie
-	PacketStats* stats = (PacketStats*)cookie;
+	auto* stats = static_cast<PacketStats*>(cookie);
 
 	// parsed the raw packet
 	pcpp::Packet parsedPacket(packet);
@@ -90,7 +88,7 @@ static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev,
 static bool onPacketArrivesBlockingMode(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie)
 {
 	// extract the stats object form the cookie
-	PacketStats* stats = (PacketStats*)cookie;
+	auto* stats = static_cast<PacketStats*>(cookie);
 
 	// parsed the raw packet
 	pcpp::Packet parsedPacket(packet);
@@ -112,10 +110,10 @@ int main(int argc, char* argv[])
 	std::string interfaceIPAddr = "10.0.0.1";
 
 	// find the interface by IP address
-	pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(interfaceIPAddr);
+	auto* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(interfaceIPAddr);
 	if (dev == nullptr)
 	{
-		std::cerr << "Cannot find interface with IPv4 address of '" << interfaceIPAddr << "'" << std::endl;
+		std::cerr << "Cannot find interface with IPv4 address of '" << interfaceIPAddr << "'\n";
 		return 1;
 	}
 
@@ -124,20 +122,20 @@ int main(int argc, char* argv[])
 
 	// before capturing packets let's print some info about this interface
 	std::cout
-		<< "Interface info:" << std::endl
-		<< "   Interface name:        " << dev->getName() << std::endl // get interface name
-		<< "   Interface description: " << dev->getDesc() << std::endl // get interface description
-		<< "   MAC address:           " << dev->getMacAddress() << std::endl // get interface MAC address
-		<< "   Default gateway:       " << dev->getDefaultGateway() << std::endl // get default gateway
-		<< "   Interface MTU:         " << dev->getMtu() << std::endl; // get interface MTU
+		<< "Interface info:\n"
+		<< "   Interface name:        " << dev->getName() << "\n" // get interface name
+		<< "   Interface description: " << dev->getDesc() << "\n" // get interface description
+		<< "   MAC address:           " << dev->getMacAddress() << "\n" // get interface MAC address
+		<< "   Default gateway:       " << dev->getDefaultGateway() << "\n" // get default gateway
+		<< "   Interface MTU:         " << dev->getMtu() << "\n"; // get interface MTU
 
-	if (dev->getDnsServers().size() > 0)
-		std::cout << "   DNS server:            " << dev->getDnsServers().at(0) << std::endl;
+	if (!dev->getDnsServers().empty())
+        std::cout << "   DNS server:            " << dev->getDnsServers().front() << "\n";
 
 	// open the device before start capturing/sending packets
 	if (!dev->open())
 	{
-		std::cerr << "Cannot open device" << std::endl;
+		std::cerr << "Cannot open device\n";
 		return 1;
 	}
 
@@ -148,7 +146,7 @@ int main(int argc, char* argv[])
 	// Async packet capture with a callback function
 	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-	std::cout << std::endl << "Starting async capture..." << std::endl;
+	std::cout << "\nStarting async capture...\n";
 
 	// start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats object as the cookie
 	dev->startCapture(onPacketArrives, &stats);
@@ -160,7 +158,7 @@ int main(int argc, char* argv[])
 	dev->stopCapture();
 
 	// print results
-	std::cout << "Results:" << std::endl;
+	std::cout << "Results:\n";
 	stats.printToConsole();
 
 	// clear stats
@@ -170,7 +168,7 @@ int main(int argc, char* argv[])
 	// Capturing packets in a packet vector
 	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-	std::cout << std::endl << "Starting capture with packet vector..." << std::endl;
+	std::cout << "\nStarting capture with packet vector...\n";
 
 	// create an empty packet vector object
 	pcpp::RawPacketVector packetVec;
@@ -185,17 +183,13 @@ int main(int argc, char* argv[])
 	dev->stopCapture();
 
 	// go over the packet vector and feed all packets to the stats object
-	for (pcpp::RawPacketVector::ConstVectorIterator iter = packetVec.begin(); iter != packetVec.end(); iter++)
-	{
-		// parse raw packet
-		pcpp::Packet parsedPacket(*iter);
-
-		// feed packet to the stats object
-		stats.consumePacket(parsedPacket);
-	}
+	for (const auto& packet : packetVec) {
+        pcpp::Packet parsedPacket(packet);
+        stats.consumePacket(parsedPacket);
+    }
 
 	// print results
-	std::cout << "Results:" << std::endl;
+	std::cout << "Results:\n";
 	stats.printToConsole();
 
 	// clear stats
@@ -205,7 +199,7 @@ int main(int argc, char* argv[])
 	// Capturing packets in blocking mode
 	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-	std::cout << std::endl << "Starting capture in blocking mode..." << std::endl;
+	std::cout << "\nStarting capture in blocking mode...\n";
 
 	// start capturing in blocking mode. Give a callback function to call to whenever a packet is captured, the stats object as the cookie and a 10 seconds timeout
 	dev->startCaptureBlockingMode(onPacketArrivesBlockingMode, &stats, 10);
@@ -213,7 +207,7 @@ int main(int argc, char* argv[])
 	// thread is blocked until capture is finished
 
 	// capture is finished, print results
-	std::cout << "Results:" << std::endl;
+	std::cout << "Results:\n";
 	stats.printToConsole();
 
 	stats.clear();
@@ -222,30 +216,30 @@ int main(int argc, char* argv[])
 	// Sending single packets
 	// ~~~~~~~~~~~~~~~~~~~~~~
 
-	std::cout << std::endl << "Sending " << packetVec.size() << " packets one by one..." << std::endl;
+	std::cout << "\nSending " << packetVec.size() << " packets one by one...\n";
 
 	// go over the vector of packets and send them one by one
-	for (pcpp::RawPacketVector::ConstVectorIterator iter = packetVec.begin(); iter != packetVec.end(); iter++)
-	{
-		// send the packet. If fails exit the application
-		if (!dev->sendPacket(**iter))
-		{
-			std::cerr << "Couldn't send packet" << std::endl;
-			return 1;
-		}
+	bool allSent = std::all_of(packetVec.begin(), packetVec.end(), [dev](const auto& packet) {
+		return dev->sendPacket(*packet);
+	});
+
+	if (!allSent) {
+		std::cerr << "Couldn't send packet\n";
+		return 1;
 	}
-	std::cout << packetVec.size() << " packets sent" << std::endl;
+
+	std::cout << packetVec.size() << " packets sent\n";
 
 
 	// Sending batch of packets
 	// ~~~~~~~~~~~~~~~~~~~~~~~~
 
-	std::cout << std::endl << "Sending " << packetVec.size() << " packets..." << std::endl;
+	std::cout << "\nSending " << packetVec.size() << " packets...\n";
 
 	// send all packets in the vector. The returned number shows how many packets were actually sent (expected to be equal to vector size)
 	int packetsSent = dev->sendPackets(packetVec);
 
-	std::cout << packetsSent << " packets sent" << std::endl;
+	std::cout << packetsSent << " packets sent\n";
 
 
 	// Using filters
@@ -265,7 +259,7 @@ int main(int argc, char* argv[])
 	// set the filter on the device
 	dev->setFilter(andFilter);
 
-	std::cout << std::endl << "Starting packet capture with a filter in place..." << std::endl;
+	std::cout << "\nStarting packet capture with a filter in place...\n";
 
 	// start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats object as the cookie
 	dev->startCapture(onPacketArrives, &stats);
@@ -277,7 +271,7 @@ int main(int argc, char* argv[])
 	dev->stopCapture();
 
 	// print results - should capture only packets which match the filter (which is TCP port 80)
-	std::cout << "Results:" << std::endl;
+	std::cout << "Results:\n";
 	stats.printToConsole();
 
 
diff --git a/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp b/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp
index 54d71ffb34..6a8591bad5 100644
--- a/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp
+++ b/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <memory>
 #include "stdlib.h"
 #include "SystemUtils.h"
 #include "Packet.h"
@@ -18,19 +19,19 @@ int main(int argc, char* argv[])
 
 	// use the IFileReaderDevice interface to automatically identify file type (pcap/pcap-ng)
 	// and create an interface instance that both readers implement
-	pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader("1_http_packet.pcap");
+    std::unique_ptr<pcpp::IFileReaderDevice> reader(pcpp::IFileReaderDevice::getReader("1_http_packet.pcap"));
 
 	// verify that a reader interface was indeed created
 	if (reader == nullptr)
 	{
-		std::cerr << "Cannot determine reader for file type" << std::endl;
+		std::cerr << "Cannot determine reader for file type\n";
 		return 1;
 	}
 
 	// open the reader for reading
 	if (!reader->open())
 	{
-		std::cerr << "Cannot open input.pcap for reading" << std::endl;
+		std::cerr << "Cannot open input.pcap for reading\n";
 		return 1;
 	}
 
@@ -38,7 +39,7 @@ int main(int argc, char* argv[])
 	pcpp::RawPacket rawPacket;
 	if (!reader->getNextPacket(rawPacket))
 	{
-		std::cerr << "Couldn't read the first packet in the file" << std::endl;
+		std::cerr << "Couldn't read the first packet in the file\n";
 		return 1;
 	}
 
@@ -49,12 +50,12 @@ int main(int argc, char* argv[])
 	pcpp::Packet parsedPacket(&rawPacket);
 
 	// now let's get the Ethernet layer
-	pcpp::EthLayer* ethernetLayer = parsedPacket.getLayerOfType<pcpp::EthLayer>();
+	auto* ethernetLayer = parsedPacket.getLayerOfType<pcpp::EthLayer>();
 	// change the source dest MAC address
 	ethernetLayer->setDestMac(pcpp::MacAddress("aa:bb:cc:dd:ee:ff"));
 
 	// let's get the IPv4 layer
-	pcpp::IPv4Layer* ipLayer = parsedPacket.getLayerOfType<pcpp::IPv4Layer>();
+	auto* ipLayer = parsedPacket.getLayerOfType<pcpp::IPv4Layer>();
 	// change source IP address
 	ipLayer->setSrcIPv4Address(pcpp::IPv4Address("1.1.1.1"));
 	// change IP ID
@@ -63,7 +64,7 @@ int main(int argc, char* argv[])
 	ipLayer->getIPv4Header()->timeToLive = 12;
 
 	// let's get the TCP layer
-	pcpp::TcpLayer* tcpLayer = parsedPacket.getLayerOfType<pcpp::TcpLayer>();
+	auto* tcpLayer = parsedPacket.getLayerOfType<pcpp::TcpLayer>();
 	// change source port
 	tcpLayer->getTcpHeader()->portSrc = pcpp::hostToNet16(12345);
 	// add URG flag
@@ -72,7 +73,7 @@ int main(int argc, char* argv[])
 	tcpLayer->addTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TCPOPT_MSS, (uint16_t)1460));
 
 	// let's get the HTTP layer
-	pcpp::HttpRequestLayer* httpRequestLayer = parsedPacket.getLayerOfType<pcpp::HttpRequestLayer>();
+	auto* httpRequestLayer = parsedPacket.getLayerOfType<pcpp::HttpRequestLayer>();
 	// change the request method from GET to TRACE
 	httpRequestLayer->getFirstLine()->setMethod(pcpp::HttpRequestLayer::HttpTRACE);
 	// change host to www.google.com
@@ -97,9 +98,10 @@ int main(int argc, char* argv[])
 
 	// write the modified packet to a pcap file
 	pcpp::PcapFileWriterDevice writer("1_modified_packet.pcap");
-	writer.open();
-	writer.writePacket(*(parsedPacket.getRawPacket()));
-	writer.close();
+	if (writer.open()) {
+        writer.writePacket(*(parsedPacket.getRawPacket()));
+        writer.close();
+    }
 
 
 	// Packet Creation
@@ -134,7 +136,8 @@ int main(int argc, char* argv[])
 
 	// write the new packet to a pcap file
 	pcpp::PcapFileWriterDevice writer2("1_new_packet.pcap");
-	writer2.open();
-	writer2.writePacket(*(newPacket.getRawPacket()));
-	writer2.close();
+	if (writer2.open()) {
+        writer2.writePacket(*(newPacket.getRawPacket()));
+        writer2.close();
+    }
 }
diff --git a/Examples/Tutorials/Tutorial-PacketParsing/main.cpp b/Examples/Tutorials/Tutorial-PacketParsing/main.cpp
index 15280ffef0..07487bd094 100644
--- a/Examples/Tutorials/Tutorial-PacketParsing/main.cpp
+++ b/Examples/Tutorials/Tutorial-PacketParsing/main.cpp
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <memory>
 #include "stdlib.h"
 #include "SystemUtils.h"
 #include "Packet.h"
@@ -28,25 +29,17 @@ std::string getProtocolTypeAsString(pcpp::ProtocolType protocolType)
 
 std::string printTcpFlags(pcpp::TcpLayer* tcpLayer)
 {
-	std::string result = "";
-	if (tcpLayer->getTcpHeader()->synFlag == 1)
-		result += "SYN ";
-	if (tcpLayer->getTcpHeader()->ackFlag == 1)
-		result += "ACK ";
-	if (tcpLayer->getTcpHeader()->pshFlag == 1)
-		result += "PSH ";
-	if (tcpLayer->getTcpHeader()->cwrFlag == 1)
-		result += "CWR ";
-	if (tcpLayer->getTcpHeader()->urgFlag == 1)
-		result += "URG ";
-	if (tcpLayer->getTcpHeader()->eceFlag == 1)
-		result += "ECE ";
-	if (tcpLayer->getTcpHeader()->rstFlag == 1)
-		result += "RST ";
-	if (tcpLayer->getTcpHeader()->finFlag == 1)
-		result += "FIN ";
-
-	return result;
+	std::string result;
+    auto* tcpHeader = tcpLayer->getTcpHeader();
+    if (tcpHeader->synFlag) result += "SYN ";
+    if (tcpHeader->ackFlag) result += "ACK ";
+    if (tcpHeader->pshFlag) result += "PSH ";
+    if (tcpHeader->cwrFlag) result += "CWR ";
+    if (tcpHeader->urgFlag) result += "URG ";
+    if (tcpHeader->eceFlag) result += "ECE ";
+    if (tcpHeader->rstFlag) result += "RST ";
+    if (tcpHeader->finFlag) result += "FIN ";
+    return result;
 }
 
 std::string printTcpOptionType(pcpp::TcpOptionType optionType)
@@ -79,19 +72,19 @@ int main(int argc, char* argv[])
 {
 	// use the IFileReaderDevice interface to automatically identify file type (pcap/pcap-ng)
 	// and create an interface instance that both readers implement
-	pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader("1_http_packet.pcap");
+	std::unique_ptr<pcpp::IFileReaderDevice> reader(pcpp::IFileReaderDevice::getReader("1_http_packet.pcap"));
 
 	// verify that a reader interface was indeed created
 	if (reader == nullptr)
 	{
-		std::cerr << "Cannot determine reader for file type" << std::endl;
+		std::cerr << "Cannot determine reader for file type\n";
 		return 1;
 	}
 
 	// open the reader for reading
 	if (!reader->open())
 	{
-		std::cerr << "Cannot open input.pcap for reading" << std::endl;
+		std::cerr << "Cannot open input.pcap for reading\n";
 		return 1;
 	}
 
@@ -99,7 +92,7 @@ int main(int argc, char* argv[])
 	pcpp::RawPacket rawPacket;
 	if (!reader->getNextPacket(rawPacket))
 	{
-		std::cerr << "Couldn't read the first packet in the file" << std::endl;
+		std::cerr << "Couldn't read the first packet in the file\n";
 		return 1;
 	}
 
@@ -110,86 +103,76 @@ int main(int argc, char* argv[])
 	pcpp::Packet parsedPacket(&rawPacket);
 
 	// first let's go over the layers one by one and find out its type, its total length, its header length and its payload length
-	for (pcpp::Layer* curLayer = parsedPacket.getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
+	for (auto* curLayer = parsedPacket.getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer())
 	{
 		std::cout
 			<< "Layer type: " << getProtocolTypeAsString(curLayer->getProtocol()) << "; " // get layer type
 			<< "Total data: " << curLayer->getDataLen() << " [bytes]; " // get total length of the layer
 			<< "Layer data: " << curLayer->getHeaderLen() << " [bytes]; " // get the header length of the layer
-			<< "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]" // get the payload length of the layer (equals total length minus header length)
-			<< std::endl;
+			<< "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]\n"; // get the payload length of the layer (equals total length minus header length)
 	}
 
 	// now let's get the Ethernet layer
-	pcpp::EthLayer* ethernetLayer = parsedPacket.getLayerOfType<pcpp::EthLayer>();
+	auto* ethernetLayer = parsedPacket.getLayerOfType<pcpp::EthLayer>();
 	if (ethernetLayer == nullptr)
 	{
-		std::cerr << "Something went wrong, couldn't find Ethernet layer" << std::endl;
+		std::cerr << "Something went wrong, couldn't find Ethernet layer\n";
 		return 1;
 	}
 
 	// print the source and dest MAC addresses and the Ether type
-	std::cout << std::endl
-		<< "Source MAC address: " << ethernetLayer->getSourceMac() << std::endl
-		<< "Destination MAC address: " << ethernetLayer->getDestMac() << std::endl
-		<< "Ether type = 0x" << std::hex << pcpp::netToHost16(ethernetLayer->getEthHeader()->etherType) << std::endl;
+	std::cout << "\nSource MAC address: " << ethernetLayer->getSourceMac() << "\n"
+              << "Destination MAC address: " << ethernetLayer->getDestMac() << "\n"
+              << "Ether type = 0x" << std::hex << pcpp::netToHost16(ethernetLayer->getEthHeader()->etherType) << std::dec << "\n";
 
 	// let's get the IPv4 layer
-	pcpp::IPv4Layer* ipLayer = parsedPacket.getLayerOfType<pcpp::IPv4Layer>();
+	auto* ipLayer = parsedPacket.getLayerOfType<pcpp::IPv4Layer>();
 	if (ipLayer == nullptr)
 	{
-		std::cerr << "Something went wrong, couldn't find IPv4 layer" << std::endl;
+		std::cerr << "Something went wrong, couldn't find IPv4 layer\n";
 		return 1;
 	}
 
 	// print source and dest IP addresses, IP ID and TTL
-	std::cout << std::endl
-		<< "Source IP address: " << ipLayer->getSrcIPAddress() << std::endl
-		<< "Destination IP address: " << ipLayer->getDstIPAddress() << std::endl
-		<< "IP ID: 0x" << std::hex << pcpp::netToHost16(ipLayer->getIPv4Header()->ipId) << std::endl
-		<< "TTL: " << std::dec << (int)ipLayer->getIPv4Header()->timeToLive << std::endl;
+	 std::cout << "\nSource IP address: " << ipLayer->getSrcIPAddress() << "\n"
+              << "Destination IP address: " << ipLayer->getDstIPAddress() << "\n"
+              << "IP ID: 0x" << std::hex << pcpp::netToHost16(ipLayer->getIPv4Header()->ipId) << std::dec << "\n"
+              << "TTL: " << static_cast<int>(ipLayer->getIPv4Header()->timeToLive) << "\n";
 
 	// let's get the TCP layer
-	pcpp::TcpLayer* tcpLayer = parsedPacket.getLayerOfType<pcpp::TcpLayer>();
+	auto* tcpLayer = parsedPacket.getLayerOfType<pcpp::TcpLayer>();
 	if (tcpLayer == nullptr)
 	{
-		std::cerr << "Something went wrong, couldn't find TCP layer" << std::endl;
+		std::cerr << "Something went wrong, couldn't find TCP layer\n";
 		return 1;
 	}
 
 	// print TCP source and dest ports, window size, and the TCP flags that are set in this layer
-	std::cout << std::endl
-		<< "Source TCP port: " << tcpLayer->getSrcPort() << std::endl
-		<< "Destination TCP port: " << tcpLayer->getDstPort() << std::endl
-		<< "Window size: " << pcpp::netToHost16(tcpLayer->getTcpHeader()->windowSize) << std::endl
-		<< "TCP flags: " << printTcpFlags(tcpLayer) << std::endl;
+	std::cout << "\nSource TCP port: " << tcpLayer->getSrcPort() << "\n"
+              << "Destination TCP port: " << tcpLayer->getDstPort() << "\n"
+              << "Window size: " << pcpp::netToHost16(tcpLayer->getTcpHeader()->windowSize) << "\n"
+              << "TCP flags: " << printTcpFlags(tcpLayer) << "\n";
 
 	std::cout << "TCP options: ";
 	for (pcpp::TcpOption tcpOption = tcpLayer->getFirstTcpOption(); tcpOption.isNotNull(); tcpOption = tcpLayer->getNextTcpOption(tcpOption))
 	{
 		std::cout << printTcpOptionType(tcpOption.getTcpOptionType()) << " ";
 	}
-	std::cout << std::endl;
+	std::cout << "\n";
 
 	// let's get the HTTP request layer
-	pcpp::HttpRequestLayer* httpRequestLayer = parsedPacket.getLayerOfType<pcpp::HttpRequestLayer>();
+	auto* httpRequestLayer = parsedPacket.getLayerOfType<pcpp::HttpRequestLayer>();
 	if (httpRequestLayer == nullptr)
 	{
-		std::cerr << "Something went wrong, couldn't find HTTP request layer" << std::endl;
+		std::cerr << "Something went wrong, couldn't find HTTP request layer\n";
 		return 1;
 	}
 
-	// print HTTP method and URI. Both appear in the first line of the HTTP request
-	std::cout << std::endl
-		<< "HTTP method: " << printHttpMethod(httpRequestLayer->getFirstLine()->getMethod()) << std::endl
-		<< "HTTP URI: " << httpRequestLayer->getFirstLine()->getUri() << std::endl;
-
-	// print values of the following HTTP field: Host, User-Agent and Cookie
-	std::cout
-		<< "HTTP host: " << httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD)->getFieldValue() << std::endl
-		<< "HTTP user-agent: " << httpRequestLayer->getFieldByName(PCPP_HTTP_USER_AGENT_FIELD)->getFieldValue() << std::endl
-		<< "HTTP cookie: " << httpRequestLayer->getFieldByName(PCPP_HTTP_COOKIE_FIELD)->getFieldValue() << std::endl;
-
-	// print the full URL of this request
-	std::cout << "HTTP full URL: " << httpRequestLayer->getUrl() << std::endl;
+	// print HTTP method, URI, Host, User-Agent, Cookie and full URL of this request
+	std::cout << "\nHTTP method: " << printHttpMethod(httpRequestLayer->getFirstLine()->getMethod()) << "\n"
+              << "HTTP URI: " << httpRequestLayer->getFirstLine()->getUri() << "\n"
+              << "HTTP host: " << httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD)->getFieldValue() << "\n"
+              << "HTTP user-agent: " << httpRequestLayer->getFieldByName(PCPP_HTTP_USER_AGENT_FIELD)->getFieldValue() << "\n"
+              << "HTTP cookie: " << httpRequestLayer->getFieldByName(PCPP_HTTP_COOKIE_FIELD)->getFieldValue() << "\n"
+              << "HTTP full URL: " << httpRequestLayer->getUrl() << std::endl;
 }
diff --git a/Examples/Tutorials/Tutorial-PcapFiles/main.cpp b/Examples/Tutorials/Tutorial-PcapFiles/main.cpp
index 89bff2f3d7..2d9aef64c5 100644
--- a/Examples/Tutorials/Tutorial-PcapFiles/main.cpp
+++ b/Examples/Tutorials/Tutorial-PcapFiles/main.cpp
@@ -1,3 +1,4 @@
+#include <memory>
 #include <iostream>
 #include "stdlib.h"
 #include "PcapFileDevice.h"
@@ -9,19 +10,19 @@ int main(int argc, char* argv[])
 {
 	// use the IFileReaderDevice interface to automatically identify file type (pcap/pcap-ng)
 	// and create an interface instance that both readers implement
-	pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader("input.pcap");
+	std::unique_ptr<pcpp::IFileReaderDevice> reader(pcpp::IFileReaderDevice::getReader("input.pcap"));
 
 	// verify that a reader interface was indeed created
 	if (reader == nullptr)
 	{
-		std::cerr << "Cannot determine reader for file type" << std::endl;
+		std::cerr << "Cannot determine reader for file type\n";
 		return 1;
 	}
 
 	// open the reader for reading
 	if (!reader->open())
 	{
-		std::cerr << "Cannot open input.pcap for reading" << std::endl;
+		std::cerr << "Cannot open input.pcap for reading\n";
 		return 1;
 	}
 
@@ -32,7 +33,7 @@ int main(int argc, char* argv[])
 	// try to open the file for writing
 	if (!pcapWriter.open())
 	{
-		std::cerr << "Cannot open output.pcap for writing" << std::endl;
+		std::cerr << "Cannot open output.pcap for writing\n";
 		return 1;
 	}
 
@@ -43,14 +44,14 @@ int main(int argc, char* argv[])
 	// try to open the file for writing
 	if (!pcapNgWriter.open())
 	{
-		std::cerr << "Cannot open output.pcapng for writing" << std::endl;
+		std::cerr << "Cannot open output.pcapng for writing\n";
 		return 1;
 	}
 
 	// set a BPF filter for the reader - only packets that match the filter will be read
 	if (!reader->setFilter("net 98.138.19.88"))
 	{
-		std::cerr << "Cannot set filter for file reader" << std::endl;
+		std::cerr << "Cannot set filter for file reader\n";
 		return 1;
 	}
 
@@ -66,20 +67,26 @@ int main(int argc, char* argv[])
 		pcapNgWriter.writePacket(rawPacket);
 	}
 
+	// Use lambda to simplify statistics output
+    auto printStats = [](const std::string& writerName, const pcpp::IPcapDevice::PcapStats& stats) {
+        std::cout << "Written " << stats.packetsRecv << " packets successfully to " << writerName
+                  << " and " << stats.packetsDrop << " packets could not be written\n";
+    };
+
 	// create the stats object
 	pcpp::IPcapDevice::PcapStats stats;
 
 	// read stats from reader and print them
 	reader->getStatistics(stats);
-	std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop << " packets could not be read" << std::endl;
+	std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop << " packets could not be read\n";
 
 	// read stats from pcap writer and print them
 	pcapWriter.getStatistics(stats);
-	std::cout << "Written " << stats.packetsRecv << " packets successfully to pcap writer and " << stats.packetsDrop << " packets could not be written" << std::endl;
+	printStats("pcap writer", stats);
 
 	// read stats from pcap-ng writer and print them
 	pcapNgWriter.getStatistics(stats);
-	std::cout << "Written " << stats.packetsRecv << " packets successfully to pcap-ng writer and " << stats.packetsDrop << " packets could not be written" << std::endl;
+	printStats("pcap-ng writer", stats);
 
 	// close reader
 	reader->close();
@@ -88,6 +95,6 @@ int main(int argc, char* argv[])
 	pcapWriter.close();
 	pcapNgWriter.close();
 
-	// free reader memory because it was created by pcpp::IFileReaderDevice::getReader()
-	delete reader;
+	// No need to delete reader, unique_ptr will handle that
+    return 0;
 }