godot_voxel/generators/graph/code_gen_helper.cpp
2022-04-16 01:16:58 +01:00

103 lines
2.5 KiB
C++

#include "code_gen_helper.h"
#include "../../util/errors.h"
#include "../../util/fixed_array.h"
#include "../../util/string_funcs.h"
#include <cstring>
#include <sstream>
namespace zylann {
CodeGenHelper::CodeGenHelper(std::stringstream &main_ss, std::stringstream &lib_ss) :
_main_ss(main_ss), _lib_ss(lib_ss) {}
void CodeGenHelper::indent() {
++_indent_level;
}
void CodeGenHelper::dedent() {
ZN_ASSERT(_indent_level > 0);
--_indent_level;
}
void CodeGenHelper::add(const char *s, unsigned int len) {
for (unsigned int i = 0; i < len; ++i) {
const char c = s[i];
if (_newline) {
for (unsigned int j = 0; j < _indent_level; ++j) {
_main_ss << " ";
}
_newline = false;
}
_main_ss << c;
if (c == '\n') {
_newline = true;
}
}
}
void CodeGenHelper::add(const char *s) {
add(s, strlen(s));
}
void CodeGenHelper::add(FwdConstStdString s) {
add(s.s.c_str(), s.s.size());
}
void CodeGenHelper::add(float x) {
FixedArray<char, 32> buffer;
// Godot shaders want float constants to be explicit
const unsigned int decimals = float(int(x)) == x ? 1 : 10;
const unsigned int len = snprintf(buffer.data(), buffer.size(), "%.*f", decimals, x);
add(buffer.data(), len);
}
void CodeGenHelper::add(double x) {
FixedArray<char, 32> buffer;
// Godot shaders want float constants to be explicit
const unsigned int decimals = double(int(x)) == x ? 1 : 16;
const unsigned int len = snprintf(buffer.data(), buffer.size(), "%.*lf", decimals, x);
add(buffer.data(), len);
}
void CodeGenHelper::add(int x) {
FixedArray<char, 32> buffer;
const unsigned int len = snprintf(buffer.data(), buffer.size(), "%i", x);
add(buffer.data(), len);
}
void CodeGenHelper::require_lib_code(const char *lib_name, const char *code) {
auto p = _included_libs.insert(lib_name);
if (p.second) {
_lib_ss << "\n\n";
_lib_ss << code;
_lib_ss << "\n\n";
}
}
// Some code can be too big to fit in a single literal depending on the compiler,
// so an option is to provide it as a zero-terminated array of string literals
void CodeGenHelper::require_lib_code(const char *lib_name, const char **code) {
auto p = _included_libs.insert(lib_name);
if (p.second) {
_lib_ss << "\n\n";
while (*code != 0) {
_lib_ss << *code;
++code;
}
_lib_ss << "\n\n";
}
}
void CodeGenHelper::generate_var_name(FwdMutableStdString out_var_name) {
const std::string s = format("v{}", _next_var_name_id);
++_next_var_name_id;
out_var_name.s = s;
}
void CodeGenHelper::print(FwdMutableStdString output) {
output.s = _lib_ss.str() + _main_ss.str();
}
} // namespace zylann