aboutsummaryrefslogtreecommitdiff
path: root/buildtools/codegen/CodegenUtils.inl
blob: 6feb65474782276d2ad8747025b9f5abba3c01ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#pragma once

#include "CodegenConfig.hpp"
#include "CodegenMacros.hpp"

#include "CodegenOutput.inl"

#include <Macros.hpp>
#include <ScopeGuard.hpp>

#include <cstdio>
#include <cstdlib>
#include <filesystem>

namespace Utils {

std::string ReadFileAsString(const std::filesystem::path& path) {
	auto file = Utils::OpenCstdioFile(path, Utils::Read);
	if (!file) throw std::runtime_error("Failed to open source file.");
	DEFER { fclose(file); };

	fseek(file, 0, SEEK_END);
	auto fileSize = ftell(file);
	rewind(file);

	std::string result(fileSize, '\0');
	fread(result.data(), fileSize, 1, file);

	return result;
}

bool WriteOutputFile(const CodegenOutput& output, std::string_view dir, std::string_view filename, std::string_view additionalSuffix = {}) {
	char path[2048];
	snprintf(path, sizeof(path), "%.*s/%.*s%.*s", PRINTF_STRING_VIEW(dir), PRINTF_STRING_VIEW(filename), PRINTF_STRING_VIEW(additionalSuffix));

	auto outputFile = Utils::OpenCstdioFile(path, Utils::WriteTruncate);
	if (!outputFile) {
		printf("[ERROR] unable to open output file %s\n", path);
		return false;
	}
	DEFER { fclose(outputFile); };

	DEBUG_PRINTF("Writing output %s\n", path);
	output.Write(outputFile);

	return true;
}

std::string MakeFullName(std::string_view name, DeclNamespace* ns = nullptr) {
	size_t length = 0;
	std::vector<std::string_view> components;
	if (!name.empty()) {
		components.push_back(name);
		length += name.length();
	}

	DeclNamespace* currentNamespace = ns;
	while (currentNamespace) {
		components.push_back(currentNamespace->name);
		length += currentNamespace->name.size() + /*::*/ 2;
		currentNamespace = currentNamespace->container;
	}

	std::string fullname;
	fullname.reserve(length);
	for (auto it = components.rbegin(); it != components.rend(); ++it) {
		fullname += *it;
		fullname += "::";
	}
	// Get rid of the last "::"
	fullname.pop_back();
	fullname.pop_back();

	return fullname;
}

void ProduceGeneratedHeaderFileHeader(CodegenOutput& output) {
	output.AddOutputThing(CodegenOutputThing{
		.text = &R"""(
// This file is generated. Any changes will be overidden when building.
#pragma once

#include <MetadataBase.hpp>

#include <cstddef>
#include <cstdint>
)"""[1],
	});
}

void ProduceGeneratedSourceFileHeader(CodegenOutput& output) {
	output.AddOutputThing(CodegenOutputThing{
		// TODO we need to get the header name
		.text = &R"""(
// This file is generated. Any changes will be overidden when building.

#include <cstddef>
#include <cstdint>
#include <frozen/string.h>
#include <frozen/unordered_map.h>
using namespace std::literals;
		)"""[1],
	});
}

} // namespace Utils