Files
filament/tools/codegen-options/serializer.template
Philip Rideout a572a10ef7 Add codegen golang program. (#5534)
This adds a code generator, implemented in Go.

This PR also prepares `Options.h` (the ground truth) by simplifying its
syntax just a bit. The ground truth file must have very simple C++
syntax, which is described in the README:

https://github.com/google/filament/blob/pr/codegen2/tools/codegen-options/README.md

This process revealed a small bug: `Filter.MEDIAN` was bound to the
incorrect value in Java.

The generated code is not yet used, stay tuned.
2022-05-10 14:40:51 -07:00

251 lines
8.0 KiB
Plaintext

{{define "CppHeader"}}// This file has been generated by codegen-options
#include "Settings_generated.h"
#include <filament/Options.h>
#include <utils/Log.h>
#include <ostream>
#include "jsonParseUtils.h"
using namespace utils;
namespace filament::viewer {
std::ostream& writeJson(std::ostream& oss, const float* v, int count) {
oss << "[";
for (int i = 0; i < count; i++) {
oss << v[i];
if (i < count - 1) {
oss << ", ";
}
}
oss << "]";
return oss;
}
std::ostream& operator<<(std::ostream& out, math::float2 v) {
return writeJson(out, v.v, 2);
}
std::ostream& operator<<(std::ostream& out, math::float3 v) {
return writeJson(out, v.v, 3);
}
std::ostream& operator<<(std::ostream& out, math::float4 v) {
return writeJson(out, v.v, 4);
}
const char* to_string(bool b) { return b ? "true" : "false"; }
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint8_t* val) {
CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
*val = strtol(jsonChunk + tokens[i].start, nullptr, 10);
return i + 1;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint16_t* val) {
CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
*val = strtol(jsonChunk + tokens[i].start, nullptr, 10);
return i + 1;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint32_t* val) {
CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
*val = strtol(jsonChunk + tokens[i].start, nullptr, 10);
return i + 1;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, int* val) {
CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
*val = strtol(jsonChunk + tokens[i].start, nullptr, 10);
return i + 1;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, float* val) {
CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
*val = strtod(jsonChunk + tokens[i].start, nullptr);
return i + 1;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, float* vals, int size) {
CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
if (tokens[i].size != size) {
slog.w << "Expected " << size << " floats, got " << tokens[i].size << io::endl;
return i + 1 + tokens[i].size;
}
++i;
for (int j = 0; j < size; ++j) {
i = parse(tokens, i, jsonChunk, &vals[j]);
}
return i;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, bool* val) {
CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
if (0 == compare(tokens[i], jsonChunk, "true")) {
*val = true;
return i + 1;
}
if (0 == compare(tokens[i], jsonChunk, "false")) {
*val = false;
return i + 1;
}
return -1;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, math::float2* val) {
float values[2];
i = parse(tokens, i, jsonChunk, values, 2);
*val = {values[0], values[1]};
return i;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, math::float3* val) {
float values[3];
i = parse(tokens, i, jsonChunk, values, 3);
*val = {values[0], values[1], values[2]};
return i;
}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, math::float4* val) {
float values[4];
i = parse(tokens, i, jsonChunk, values, 4);
*val = {values[0], values[1], values[2], values[3]};
return i;
}
{{end}}
////////////////////////////////////////////////////////////////////////////////////////////////////
{{define "CppEnumReader"}}
{{- $enum_name := .QualifiedName }}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, {{$enum_name}}* out) {
{{- range $index, $value := .Values}}
{{elseif $index}} (0 == compare(tokens[i], jsonChunk, "
{{- $value}}")) { *out = {{$enum_name}}::{{.}}; }
{{- end}}
else {
slog.w << "Invalid {{$enum_name}}: '" << STR(tokens[i], jsonChunk) << "'" << io::endl;
}
return i + 1;
}
{{end}}
////////////////////////////////////////////////////////////////////////////////////////////////////
{{define "CppEnumWriter"}}
{{- $enum_name := .QualifiedName }}
std::ostream& operator<<(std::ostream& out, {{$enum_name}} in) {
switch (in) {
{{- range $index, $value := .Values}}
case {{$enum_name}}::{{$value}}: return out << "\"{{$value}}\"";
{{- end}}
}
return out << "\"INVALID\"";
}
{{end}}
////////////////////////////////////////////////////////////////////////////////////////////////////
{{define "CppStructReader"}}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, {{.QualifiedName}}* out) {
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
int size = tokens[i++].size;
for (int j = 0; j < size; ++j) {
const jsmntok_t tok = tokens[i];
CHECK_KEY(tok);
{{- range $index, $field := .Fields}}
{{- if $field.SkipJson}}
{{braceif $index}} (compare(tok, jsonChunk, "{{$field.Name}}") == 0) {
// JSON serialization for {{$field.Name}} is not supported.
int unused;
i = parse(tokens, i + 1, jsonChunk, &unused);
{{- else }}
{{braceif $index}} (compare(tok, jsonChunk, "{{$field.Name}}") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->{{$field.Name}});
{{- end}}
{{- end}}
} else {
slog.w << "Invalid {{.BaseName}} key: '" << STR(tok, jsonChunk) << "'" << io::endl;
i = parse(tokens, i + 1);
}
if (i < 0) {
slog.e << "Invalid {{.BaseName}} value: '" << STR(tok, jsonChunk) << "'" << io::endl;
return i;
}
}
return i;
}
{{end}}
////////////////////////////////////////////////////////////////////////////////////////////////////
{{define "CppStructWriter"}}
{{- $length := len .Fields }}
std::ostream& operator<<(std::ostream& out, const {{.QualifiedName}}& in) {
return out << "{\n"
{{- range $index, $field := .Fields}}
{{- if $field.SkipJson }}
// JSON serialization for {{$field.Name}} is not supported.
{{- else }}
<< "\"{{$field.Name}}\": " << {{ cast $field.Type }}(in.{{$field.Name}}) << "
{{- trailingcomma $index $length}}\n"
{{- end}}
{{- end}}
<< "}";
}
{{end}}
////////////////////////////////////////////////////////////////////////////////////////////////////
{{define "CppFooter"}}
} // namespace filament::viewer
{{end}}
////////////////////////////////////////////////////////////////////////////////////////////////////
{{define "HppHeader"}}// This file has been generated by codegen-options
#include <filament/Options.h>
#include <ostream>
#include <jsmn.h>
namespace filament::viewer {
std::ostream& writeJson(std::ostream& oss, const float* v, int count);
std::ostream& operator<<(std::ostream& out, math::float2 v);
std::ostream& operator<<(std::ostream& out, math::float3 v);
std::ostream& operator<<(std::ostream& out, math::float4 v);
const char* to_string(bool b);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint8_t* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint16_t* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, uint32_t* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, int* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, float* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, float* vals, int size);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, bool* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, math::float2* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, math::float3* val);
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, math::float4* val);
{{end}}
{{define "HppEnum"}}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, {{.QualifiedName}}* out);
std::ostream& operator<<(std::ostream& out, {{$.QualifiedName}} in);
{{end}}
{{define "HppStruct"}}
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, {{.QualifiedName}}* out);
std::ostream& operator<<(std::ostream& out, const {{.QualifiedName}}& in);
{{end}}
{{define "HppFooter"}}
} // namespace filament::viewer
{{end}}