Skip to content

Commit ef19c43

Browse files
committed
06
1 parent 36b299b commit ef19c43

File tree

16 files changed

+528
-29
lines changed

16 files changed

+528
-29
lines changed

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"makefile.configureOnOpen": false
3+
}

.zed/tasks.json

Lines changed: 0 additions & 28 deletions
This file was deleted.

06/ex00/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
NAME = scalar
2+
SRC = ScalarConverter.cpp main.cpp
3+
HEADERS = ScalarConverter.hpp
4+
BUILD_DIR = build
5+
BUILD = $(addprefix $(BUILD_DIR)/, $(SRC:.cpp=.o))
6+
7+
all: $(NAME)
8+
9+
$(NAME): $(BUILD_DIR) $(BUILD)
10+
@c++ $(BUILD) -o $(NAME)
11+
12+
$(BUILD_DIR)/%.o: %.cpp | $(BUILD_DIR)
13+
@c++ -Werror -Wall -Wextra -Wno-implicit-fallthrough -std=c++23 -c $< -o $@
14+
15+
$(BUILD_DIR):
16+
@mkdir -p $(BUILD_DIR)
17+
18+
clean:
19+
@rm -rf $(NAME)
20+
21+
fclean: clean
22+
@rm -rf $(BUILD_DIR)
23+
24+
re: fclean all
25+
26+
format:
27+
@clang-format -i $(SRC) $(HEADERS)
28+
29+
run: all
30+
@printf "\n🤖 06/ex00 $(NAME) output:\n\n"
31+
@./$(NAME)
32+
33+
.PHONY: all clean fclean re

06/ex00/ScalarConverter.cpp

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#include "ScalarConverter.hpp"
2+
3+
#include <cctype>
4+
#include <cerrno>
5+
#include <cfloat>
6+
#include <cmath>
7+
#include <cstdlib>
8+
#include <iostream>
9+
#include <limits>
10+
#include <stdexcept>
11+
#include <string>
12+
13+
// Constructor
14+
ScalarConverter::ScalarConverter() {}
15+
// Copy constructor
16+
ScalarConverter::ScalarConverter(const ScalarConverter&) {}
17+
// Assignment operator
18+
ScalarConverter& ScalarConverter::operator=(const ScalarConverter&) { return *this; }
19+
// Destructor
20+
ScalarConverter::~ScalarConverter() {}
21+
// Convert function
22+
void ScalarConverter::convert(const std::string& literal) {
23+
Result result = parseLiteral(literal);
24+
printResult(result);
25+
}
26+
// Parse the literal
27+
ScalarConverter::Result ScalarConverter::parseLiteral(const std::string& literal) {
28+
Result result;
29+
// Check for special cases: NaN, +inf, -inf
30+
if (literal == "nan" || literal == "nanf") {
31+
result.isNaN = true;
32+
return result;
33+
}
34+
if (literal == "+inf" || literal == "-inf" || literal == "inf" || literal == "+inff" || literal == "-inff" ||
35+
literal == "inff") {
36+
result.isInf = true;
37+
return result;
38+
}
39+
// Check for char
40+
if (literal.length() == 1 && std::isprint(literal[0])) {
41+
result.c = literal[0];
42+
result.hasChar = true;
43+
return result;
44+
}
45+
// Check for int
46+
try {
47+
long intValue = std::stol(literal);
48+
if (intValue < std::numeric_limits<int>::min() || intValue > std::numeric_limits<int>::max()) {
49+
throw std::out_of_range("Integer out of range");
50+
}
51+
result.i = static_cast<int>(intValue);
52+
result.hasInt = true;
53+
} catch (const std::invalid_argument&) {
54+
} catch (const std::out_of_range&) {
55+
}
56+
// Check for float
57+
try {
58+
float floatValue = std::stof(literal);
59+
if (floatValue < -std::numeric_limits<float>::max() || floatValue > std::numeric_limits<float>::max()) {
60+
throw std::out_of_range("Float out of range");
61+
}
62+
result.f = floatValue;
63+
result.hasFloat = true;
64+
} catch (const std::invalid_argument&) {
65+
} catch (const std::out_of_range&) {
66+
}
67+
// Check for double
68+
try {
69+
double doubleValue = std::stod(literal);
70+
if (doubleValue < -std::numeric_limits<double>::max() || doubleValue > std::numeric_limits<double>::max()) {
71+
throw std::out_of_range("Double out of range");
72+
}
73+
result.d = doubleValue;
74+
result.hasDouble = true;
75+
} catch (const std::invalid_argument&) {
76+
} catch (const std::out_of_range&) {
77+
}
78+
// If all conversions fail, throw an exception
79+
if (!result.hasChar && !result.hasInt && !result.hasFloat && !result.hasDouble) {
80+
throw std::invalid_argument("Invalid literal");
81+
}
82+
return result;
83+
}
84+
85+
// Print the result
86+
void ScalarConverter::printResult(const Result& r) {
87+
if (r.isNaN) {
88+
std::cout << "char: impossible" << std::endl;
89+
std::cout << "int: impossible" << std::endl;
90+
std::cout << "float: nanf" << std::endl;
91+
std::cout << "double: nan" << std::endl;
92+
} else if (r.isInf) {
93+
std::cout << "char: impossible" << std::endl;
94+
std::cout << "int: impossible" << std::endl;
95+
std::cout << "float: inf" << std::endl;
96+
std::cout << "double: inf" << std::endl;
97+
} else {
98+
// Print char
99+
if (r.hasChar && std::isprint(r.c)) {
100+
std::cout << "char: '" << r.c << "'" << std::endl;
101+
} else {
102+
std::cout << "char: non displayable" << std::endl;
103+
}
104+
105+
// Print int
106+
if (r.hasInt) {
107+
std::cout << "int: " << r.i << std::endl;
108+
} else {
109+
std::cout << "int: impossible" << std::endl;
110+
}
111+
112+
// Print float
113+
if (r.hasFloat) {
114+
float val = r.f;
115+
if (val == -0.0f) {
116+
val = 0.0f; // Handle -0.0 case
117+
}
118+
if (std::isinf(val) || std::isnan(val)) {
119+
std::cout << "float: " << (std::isnan(val) ? "nanf" : (val < 0 ? "-inff" : "+inff")) << std::endl;
120+
} else {
121+
std::cout.precision(1);
122+
std::cout.setf(std::ios_base::fixed);
123+
std::cout << "float: " << val << "f" << std::endl;
124+
}
125+
} else {
126+
std::cout << "float: impossible" << std::endl;
127+
}
128+
129+
// Print double
130+
if (r.hasDouble) {
131+
double val = r.d;
132+
if (val == -0.0) {
133+
val = 0.0; // Handle -0.0 case
134+
}
135+
if (std::isinf(val) || std::isnan(val)) {
136+
std::cout << "double: " << (std::isnan(val) ? "nan" : (val < 0 ? "-inf" : "+inf")) << std::endl;
137+
} else {
138+
std::cout.precision(1);
139+
std::cout.setf(std::ios_base::fixed);
140+
std::cout << "double: " << val << std::endl;
141+
}
142+
} else {
143+
std::cout << "double: impossible" << std::endl;
144+
}
145+
}
146+
}

06/ex00/ScalarConverter.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <string>
2+
3+
#pragma once
4+
5+
class ScalarConverter {
6+
public:
7+
// Holds every possible converted value
8+
struct Result {
9+
char c;
10+
int i;
11+
float f;
12+
double d;
13+
bool hasChar = false;
14+
bool hasInt = false;
15+
bool hasFloat = false;
16+
bool hasDouble = false;
17+
bool isNaN = false;
18+
bool isInf = false;
19+
};
20+
21+
// constructors and destructors
22+
ScalarConverter();
23+
ScalarConverter(const ScalarConverter&);
24+
ScalarConverter& operator=(const ScalarConverter&);
25+
~ScalarConverter();
26+
27+
// Entry point: parses, converts & prints
28+
static void convert(const std::string& literal);
29+
30+
private:
31+
// Steps: parse → convert → print
32+
static Result parseLiteral(const std::string& literal);
33+
static Result convertAll(const std::string& literal);
34+
static void printResult(const Result& r);
35+
};

06/ex00/main.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <cctype>
2+
#include <cerrno>
3+
#include <cfloat>
4+
#include <cstdlib>
5+
#include <iostream>
6+
#include <string>
7+
8+
#include "ScalarConverter.hpp"
9+
10+
int main() {
11+
std::string input;
12+
std::cout << "Enter a literal: ";
13+
std::getline(std::cin, input);
14+
15+
try {
16+
ScalarConverter::convert(input);
17+
} catch (const std::exception& e) {
18+
std::cerr << "Error: " << e.what() << std::endl;
19+
}
20+
21+
return 0;
22+
}

06/ex01/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
NAME = serialize
2+
SRC = Serialize.cpp main.cpp
3+
HEADERS = Serialize.hpp
4+
BUILD_DIR = build
5+
BUILD = $(addprefix $(BUILD_DIR)/, $(SRC:.cpp=.o))
6+
7+
all: $(NAME)
8+
9+
$(NAME): $(BUILD_DIR) $(BUILD)
10+
@c++ $(BUILD) -o $(NAME)
11+
12+
$(BUILD_DIR)/%.o: %.cpp | $(BUILD_DIR)
13+
@c++ -Werror -Wall -Wextra -Wno-implicit-fallthrough -std=c++23 -c $< -o $@
14+
15+
$(BUILD_DIR):
16+
@mkdir -p $(BUILD_DIR)
17+
18+
clean:
19+
@rm -rf $(NAME)
20+
21+
fclean: clean
22+
@rm -rf $(BUILD_DIR)
23+
24+
re: fclean all
25+
26+
format:
27+
@clang-format -i $(SRC) $(HEADERS)
28+
29+
run: all
30+
@printf "\n🤖 06/ex01 $(NAME) output:\n\n"
31+
@./$(NAME)
32+
33+
.PHONY: all clean fclean re

06/ex01/Serialize.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include "Serialize.hpp"
2+
3+
Serialize::Serialize() {}
4+
5+
Serialize::Serialize(const Serialize&) {}
6+
7+
Serialize& Serialize::operator=(const Serialize&) {
8+
return *this;
9+
}
10+
11+
Serialize::~Serialize() {}
12+
13+
uintptr_t Serialize::serialize(Data* ptr) {
14+
return reinterpret_cast<uintptr_t>(ptr);
15+
}
16+
17+
Data* Serialize::deserialize(uintptr_t raw) {
18+
return reinterpret_cast<Data*>(raw);
19+
}

06/ex01/Serialize.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
5+
#include <string>
6+
7+
struct Data {
8+
std::string str;
9+
size_t num;
10+
};
11+
12+
class Serialize {
13+
public:
14+
Serialize();
15+
Serialize(const Serialize&);
16+
Serialize& operator=(const Serialize&);
17+
~Serialize();
18+
uintptr_t serialize(Data* ptr);
19+
Data* deserialize(uintptr_t raw);
20+
};

06/ex01/main.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <cassert>
2+
#include <iostream>
3+
4+
#include "Serialize.hpp"
5+
6+
/**
7+
* @brief The main function demonstrates serialization and deserialization of a Data structure.
8+
* This example creates a Data object, serializes it to a raw pointer, then deserializes it back to a Data
9+
* object.
10+
*/
11+
int main(void) {
12+
Data data;
13+
data.str = "Hello, World!";
14+
data.num = 42;
15+
16+
Serialize serializer;
17+
18+
// Serialize the data
19+
uintptr_t raw = serializer.serialize(&data);
20+
std::cout << "Serialized data to raw pointer: " << raw << std::endl;
21+
22+
// Deserialize the raw pointer back to Data
23+
Data* deserializedData = serializer.deserialize(raw);
24+
std::cout << "Deserialized data: " << deserializedData->str << ", " << deserializedData->num << std::endl;
25+
26+
// Assert to ensure the deserialized data matches the original (fails when the code is incorrect)
27+
assert(deserializedData->str == data.str);
28+
29+
return 0;
30+
}

0 commit comments

Comments
 (0)