mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-10 05:27:01 +03:00
big merge
This commit is contained in:
6
components/spotify/cspot/cpp-reflection/.gitignore
vendored
Normal file
6
components/spotify/cspot/cpp-reflection/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.vscode
|
||||
protoc-gen-cpprefl
|
||||
generator/
|
||||
`
|
||||
out/
|
||||
protos/
|
||||
7
components/spotify/cspot/cpp-reflection/README.md
Normal file
7
components/spotify/cspot/cpp-reflection/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Running
|
||||
|
||||
```sh
|
||||
$ go build -o protoc-gen-cpprefl . && protoc --plugin=protoc-gen-cpprefl=protoc-gen-cpprefl --cpprefl_out okon protos/*.proto --proto_path protos/
|
||||
```
|
||||
|
||||
Will get protos from `protos/` and output to `out/protobuf.h`
|
||||
21
components/spotify/cspot/cpp-reflection/alias_type.go
Normal file
21
components/spotify/cspot/cpp-reflection/alias_type.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
type AliasType struct {
|
||||
Of GeneratableType
|
||||
cppType string
|
||||
}
|
||||
|
||||
func (at *AliasType) IdentifierName() string {
|
||||
return at.Of.IdentifierName()
|
||||
}
|
||||
|
||||
func (at *AliasType) CppType() string {
|
||||
return at.cppType
|
||||
}
|
||||
|
||||
func (at *AliasType) WriteDeclarations(gen *CppGenerator) {
|
||||
|
||||
}
|
||||
func (at *AliasType) WriteReflection(gen *CppGenerator) {
|
||||
|
||||
}
|
||||
192
components/spotify/cspot/cpp-reflection/any_types.go
Normal file
192
components/spotify/cspot/cpp-reflection/any_types.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func GenerateAnyTypes(gen *CppGenerator, primitiveTypes []GeneratableType, allTypes []GeneratableType) {
|
||||
|
||||
exceptionalTypes := []GeneratableType{}
|
||||
allTypesWithoutAliases := []GeneratableType{}
|
||||
for _, t := range allTypes {
|
||||
_, isPrimitve := t.(*PrimitiveType)
|
||||
_, isEnum := t.(*EnumType)
|
||||
_, isGeneric := t.(GenericType)
|
||||
if isPrimitve || isEnum || isGeneric {
|
||||
exceptionalTypes = append(exceptionalTypes, t)
|
||||
}
|
||||
if _, ok := t.(*AliasType); !ok {
|
||||
log.Printf("%#v", t)
|
||||
allTypesWithoutAliases = append(allTypesWithoutAliases, t)
|
||||
}
|
||||
}
|
||||
|
||||
template.Must(template.New("any.cpp").Parse(`
|
||||
|
||||
|
||||
class AnyRef {
|
||||
public:
|
||||
ReflectTypeID typeID;
|
||||
AnyRef() {};
|
||||
AnyRef(ReflectTypeID typeID, void *obj) {
|
||||
this->typeID = typeID;
|
||||
this->value.voidptr = obj;
|
||||
}
|
||||
template<typename T>
|
||||
T *as() {
|
||||
// if(T::_TYPE_ID != this->typeID) {
|
||||
// throw "invalid as call";
|
||||
// }
|
||||
return (T*) this->value.voidptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool is() {
|
||||
{{range .PrimitiveTypes}}if constexpr(std::is_same<T, {{.CppType}}>::value) {
|
||||
return ReflectTypeID::{{.IdentifierName}} == this->typeID;
|
||||
} else
|
||||
{{end}} {
|
||||
return T::_TYPE_ID == this->typeID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ReflectType *reflectType();
|
||||
AnyRef getField(int i);
|
||||
template <typename T>
|
||||
static AnyRef of(T *obj)
|
||||
{
|
||||
ReflectTypeID typeID;
|
||||
{{range .PrimitiveTypes}}if constexpr(std::is_same<T, {{.CppType}}>::value) {
|
||||
typeID = ReflectTypeID::{{.IdentifierName}};
|
||||
} else
|
||||
{{end}} {
|
||||
typeID = T::_TYPE_ID;
|
||||
}
|
||||
AnyRef a;
|
||||
a.typeID = typeID;
|
||||
a.value.voidptr = (void*) obj;
|
||||
return a;
|
||||
}
|
||||
|
||||
union ReflectedTypes {
|
||||
void *voidptr;
|
||||
{{range .allTypes}}{{.CppType}} *u_{{.IdentifierName}};
|
||||
{{end}}
|
||||
} value;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
`)).Execute(gen.Body, map[string]interface{}{
|
||||
"PrimitiveTypes": exceptionalTypes,
|
||||
"allTypes": allTypesWithoutAliases,
|
||||
})
|
||||
}
|
||||
|
||||
func GenerateAnyTypesImplementation(gen *CppGenerator) {
|
||||
fmt.Fprintf(gen.SubFile("AnyRefImpl.cpp", false).AddLocalInclude(gen.Filename).Body, `
|
||||
ReflectType *AnyRef::reflectType() {
|
||||
return &reflectTypeInfo[static_cast<int>(this->typeID)];
|
||||
}
|
||||
AnyRef AnyRef::getField(int i) {
|
||||
auto info = this->reflectType();
|
||||
if(info->kind != ReflectTypeKind::Class) {
|
||||
throw "not a class";
|
||||
}
|
||||
return AnyRef(info->fields[i].typeID, static_cast<char *>(this->value.voidptr) + info->fields[i].offset);
|
||||
}
|
||||
`)
|
||||
|
||||
fmt.Fprintf(gen.Body, `
|
||||
|
||||
|
||||
class UniqueAny: public AnyRef {
|
||||
public:
|
||||
UniqueAny() {
|
||||
this->value.voidptr = nullptr;
|
||||
};
|
||||
UniqueAny(ReflectTypeID typeID) {
|
||||
this->typeID = typeID;
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(typeID)];
|
||||
AnyRef a;
|
||||
this->value.voidptr = new unsigned char[typeInfo->size];
|
||||
typeInfo->_Construct(this->value.voidptr);
|
||||
};
|
||||
~UniqueAny() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(typeID)];
|
||||
typeInfo->_Destruct(this->value.voidptr);
|
||||
delete reinterpret_cast<char *>(this->value.voidptr);
|
||||
};
|
||||
};
|
||||
|
||||
class AnyVectorRef {
|
||||
public:
|
||||
AnyRef ref;
|
||||
AnyVectorRef(AnyRef r): ref(r) {}
|
||||
void push_back(AnyRef &v) {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
typeInfo->vectorOps.push_back(ref, v);
|
||||
}
|
||||
size_t size() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
return typeInfo->vectorOps.size(ref);
|
||||
}
|
||||
|
||||
void emplace_back() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
typeInfo->vectorOps.emplace_back(ref);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
typeInfo->vectorOps.clear(ref);
|
||||
}
|
||||
|
||||
void reserve(size_t n) {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
typeInfo->vectorOps.reserve(ref, n);
|
||||
}
|
||||
|
||||
|
||||
AnyRef at(size_t index) {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
return typeInfo->vectorOps.at(ref, index);
|
||||
}
|
||||
};
|
||||
|
||||
class AnyOptionalRef {
|
||||
public:
|
||||
AnyRef ref;
|
||||
AnyOptionalRef(AnyRef r): ref(r) {}
|
||||
|
||||
AnyRef get() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
return typeInfo->optionalOps.get(ref);
|
||||
}
|
||||
|
||||
bool has_value() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
return typeInfo->optionalOps.has_value(ref);
|
||||
}
|
||||
void set(AnyRef &o) {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
typeInfo->optionalOps.set(ref, o);
|
||||
}
|
||||
void reset() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
typeInfo->optionalOps.reset(ref);
|
||||
}
|
||||
|
||||
void emplaceEmpty() {
|
||||
auto typeInfo = &reflectTypeInfo[static_cast<int>(this->ref.typeID)];
|
||||
typeInfo->optionalOps.emplaceEmpty(ref);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
`)
|
||||
}
|
||||
69
components/spotify/cspot/cpp-reflection/class_type.go
Normal file
69
components/spotify/cspot/cpp-reflection/class_type.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ClassField struct {
|
||||
Name string
|
||||
ProtobufTag uint32
|
||||
Type GeneratableType
|
||||
}
|
||||
|
||||
type ClassType struct {
|
||||
Name string
|
||||
Fields []ClassField
|
||||
AdditionalCode string
|
||||
AdditionalLibraryIncludes []string
|
||||
ProtoName string
|
||||
}
|
||||
|
||||
func (ct *ClassType) IdentifierName() string {
|
||||
return "Class" + ct.Name
|
||||
}
|
||||
|
||||
func (ct *ClassType) CppType() string {
|
||||
return ct.Name
|
||||
}
|
||||
|
||||
func (et *ClassType) DeclarationOrder() int {
|
||||
return -10
|
||||
}
|
||||
|
||||
func (ct *ClassType) ForwardDeclaration() string {
|
||||
return fmt.Sprintf("class %v;", ct.Name)
|
||||
}
|
||||
|
||||
func (ct *ClassType) WriteDeclarations(gen *CppGenerator) {
|
||||
classSubfile := gen.SubFile(ct.ProtoName+".h", true)
|
||||
gen.AddLocalInclude(classSubfile.Filename)
|
||||
for _, f := range ct.Fields {
|
||||
AddIncludeForType(f.Type, classSubfile)
|
||||
}
|
||||
for _, i := range ct.AdditionalLibraryIncludes {
|
||||
classSubfile.AddLibraryInclude(i)
|
||||
}
|
||||
classSubfile.OutputClass(ct.Name, func() {
|
||||
for _, t := range ct.Fields {
|
||||
classSubfile.OutputClassField(t.Type.CppType(), t.Name)
|
||||
}
|
||||
classSubfile.OutputClassTypeID(ct.IdentifierName())
|
||||
fmt.Fprint(classSubfile.Body, ct.AdditionalCode)
|
||||
})
|
||||
}
|
||||
func (ct *ClassType) WriteReflection(gen *CppGenerator) {
|
||||
gen.AddLibraryInclude("vector")
|
||||
fieldsContents := ""
|
||||
for _, f := range ct.Fields {
|
||||
fieldsContents += fmt.Sprintf("ReflectField( /* typeID */ ReflectTypeID::%v, /* name */ %v, /* offset */ offsetof(%v, %v), /* protobuf tag */ %v),\n",
|
||||
f.Type.IdentifierName(), gen.EscapeCppString(f.Name), ct.CppType(), f.Name, f.ProtobufTag)
|
||||
}
|
||||
fmt.Fprintf(gen.Body, `ReflectType::ofClass(
|
||||
/* mine type id */ ReflectTypeID::%v,
|
||||
/* name */ %v,
|
||||
/* fields */ std::move(std::vector<ReflectField>{%v}),
|
||||
/* size */ sizeof(%v),
|
||||
__reflectConstruct<%v>,
|
||||
__reflectDestruct<%v>)`,
|
||||
ct.IdentifierName(), gen.EscapeCppString(ct.CppType()), fieldsContents, ct.CppType(), ct.CppType(), ct.CppType())
|
||||
}
|
||||
417
components/spotify/cspot/cpp-reflection/corntext.go
Normal file
417
components/spotify/cspot/cpp-reflection/corntext.go
Normal file
@@ -0,0 +1,417 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"sort"
|
||||
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||
)
|
||||
|
||||
type GeneratableType interface {
|
||||
IdentifierName() string
|
||||
CppType() string
|
||||
WriteDeclarations(gen *CppGenerator)
|
||||
WriteReflection(gen *CppGenerator)
|
||||
}
|
||||
|
||||
type GenericType interface {
|
||||
GeneratableType
|
||||
GetInnerType() GeneratableType
|
||||
}
|
||||
|
||||
type ForwardDeclarable interface {
|
||||
ForwardDeclaration() string
|
||||
}
|
||||
|
||||
type DelcarationOrderable interface {
|
||||
DeclarationOrder() int
|
||||
}
|
||||
|
||||
type Corntext struct {
|
||||
CG *CppGenerator
|
||||
Request *plugin.CodeGeneratorRequest // The input.
|
||||
Response *plugin.CodeGeneratorResponse // The output.
|
||||
AllTypes []GeneratableType
|
||||
PrimitiveTypes map[string]GeneratableType
|
||||
|
||||
// types required for reflection
|
||||
TypeIDEnum GeneratableType
|
||||
ReflectType GeneratableType
|
||||
ReflectField GeneratableType
|
||||
ReflectEnumValue GeneratableType
|
||||
TypeKindEnum GeneratableType
|
||||
vectorOfReflectFields GeneratableType
|
||||
vectorOfReflectEnumValues GeneratableType
|
||||
}
|
||||
|
||||
func NewCorntext() *Corntext {
|
||||
i64 := &PrimitiveType{identifierName: "Int64", cppType: "int64_t"}
|
||||
return &Corntext{
|
||||
Request: new(plugin.CodeGeneratorRequest),
|
||||
Response: new(plugin.CodeGeneratorResponse),
|
||||
CG: NewCppGenerator("protobuf.h"),
|
||||
AllTypes: []GeneratableType{},
|
||||
PrimitiveTypes: map[string]GeneratableType{
|
||||
"int": &PrimitiveType{identifierName: "Int", cppType: "int"},
|
||||
// "unsigned int": &PrimitiveType{identifierName: "UnsignedInt", cppType: "unsigned int"},
|
||||
"char": &PrimitiveType{identifierName: "Char", cppType: "char"},
|
||||
"unsigned char": &PrimitiveType{identifierName: "UnsignedChar", cppType: "unsigned char"},
|
||||
"double": &PrimitiveType{identifierName: "Double", cppType: "double"},
|
||||
"float": &PrimitiveType{identifierName: "Float", cppType: "float"},
|
||||
"bool": &PrimitiveType{identifierName: "Bool", cppType: "bool"},
|
||||
"std::string": &PrimitiveType{identifierName: "String", cppType: "std::string"},
|
||||
"size_t": &AliasType{Of: i64, cppType: "size_t"},
|
||||
"int32_t": &PrimitiveType{identifierName: "Int32", cppType: "int32_t"},
|
||||
"int64_t": i64,
|
||||
"uint32_t": &PrimitiveType{identifierName: "Uint32", cppType: "uint32_t"},
|
||||
"uint64_t": &PrimitiveType{identifierName: "Uint64", cppType: "uint64_t"},
|
||||
"uint8_t": &PrimitiveType{identifierName: "Uint8", cppType: "uint8_t"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Corntext) outputTypes() {
|
||||
c.CG.AddLibraryInclude("utility")
|
||||
c.CG.AddLibraryInclude("vector")
|
||||
vht := &VectorHelperTypes{}
|
||||
oht := &OptionalHelperTypes{}
|
||||
fmt.Fprintln(c.CG.Body, `
|
||||
template<class T>
|
||||
void __reflectConstruct(void *mem) {
|
||||
new(mem) T;
|
||||
}
|
||||
template<class T>
|
||||
void __reflectDestruct(void *obj) {
|
||||
((T*) obj)->~T();
|
||||
}
|
||||
|
||||
`)
|
||||
vht.GenerateVectorOperationsStruct(c.CG)
|
||||
oht.GenerateOptionalOperationsStruct(c.CG)
|
||||
for _, t := range c.AllTypes {
|
||||
if fwd, ok := t.(ForwardDeclarable); ok {
|
||||
fmt.Fprintf(c.CG.Body, "%v\n", fwd.ForwardDeclaration())
|
||||
}
|
||||
|
||||
}
|
||||
c.CG.AddLibraryInclude("type_traits")
|
||||
|
||||
typesToDeclare := make([]GeneratableType, len(c.AllTypes))
|
||||
for i := range c.AllTypes {
|
||||
typesToDeclare[i] = c.AllTypes[i]
|
||||
}
|
||||
sort.SliceStable(typesToDeclare, func(i, j int) bool {
|
||||
var ival, jval int
|
||||
if orderable, ok := typesToDeclare[i].(DelcarationOrderable); ok {
|
||||
ival = orderable.DeclarationOrder()
|
||||
}
|
||||
if orderable, ok := typesToDeclare[j].(DelcarationOrderable); ok {
|
||||
jval = orderable.DeclarationOrder()
|
||||
}
|
||||
return ival < jval
|
||||
})
|
||||
for _, t := range typesToDeclare {
|
||||
t.WriteDeclarations(c.CG)
|
||||
}
|
||||
|
||||
primitiveList := make([]GeneratableType, 0, len(c.PrimitiveTypes))
|
||||
for _, pt := range c.PrimitiveTypes {
|
||||
primitiveList = append(primitiveList, pt)
|
||||
}
|
||||
GenerateAnyTypes(c.CG, primitiveList, c.AllTypes)
|
||||
vht.GenerateVectorManipulator(c.CG)
|
||||
oht.GenerateOptionalManipulator(c.CG)
|
||||
|
||||
c.CG.OutputArrayVariableExtern(c.ReflectType.CppType(), "reflectTypeInfo", len(c.AllTypes))
|
||||
dataFile := c.CG.SubFile("ReflectTypeInfo.cpp", false).AddLocalInclude(c.CG.Filename)
|
||||
dataFile.OutputArrayVariable(c.ReflectType.CppType(), "reflectTypeInfo", len(c.AllTypes), func() {
|
||||
|
||||
for _, t := range c.AllTypes {
|
||||
if _, ok := t.(*AliasType); ok {
|
||||
continue
|
||||
}
|
||||
t.WriteReflection(dataFile)
|
||||
fmt.Fprintf(dataFile.Body, ",\n")
|
||||
}
|
||||
})
|
||||
|
||||
GenerateAnyTypesImplementation(c.CG)
|
||||
|
||||
c.CG.OutputToDirectory("protos/")
|
||||
}
|
||||
|
||||
func (c *Corntext) buildAllTypes() {
|
||||
c.generateReflectionTypes()
|
||||
c.AllTypes = append(c.AllTypes,
|
||||
c.TypeIDEnum,
|
||||
c.ReflectField,
|
||||
c.ReflectEnumValue,
|
||||
c.ReflectType,
|
||||
c.TypeKindEnum,
|
||||
c.vectorOfReflectFields,
|
||||
c.vectorOfReflectEnumValues,
|
||||
)
|
||||
for _, t := range c.PrimitiveTypes {
|
||||
c.AllTypes = append(c.AllTypes, t)
|
||||
}
|
||||
c.generateProtobufTypes()
|
||||
i := 0
|
||||
for _, t := range c.AllTypes {
|
||||
if _, ok := t.(*AliasType); ok {
|
||||
continue
|
||||
}
|
||||
c.TypeIDEnum.(*EnumType).Values = append(c.TypeIDEnum.(*EnumType).Values, EnumValue{Name: t.IdentifierName(), Value: fmt.Sprintf("%v", i)})
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Corntext) generateProtobufTypes() {
|
||||
var pbType2reflection = map[descriptor.FieldDescriptorProto_Type]GeneratableType{
|
||||
descriptor.FieldDescriptorProto_TYPE_INT32: c.PrimitiveTypes["int32_t"],
|
||||
descriptor.FieldDescriptorProto_TYPE_SINT32: c.PrimitiveTypes["int32_t"],
|
||||
descriptor.FieldDescriptorProto_TYPE_SINT64: c.PrimitiveTypes["int64_t"],
|
||||
descriptor.FieldDescriptorProto_TYPE_INT64: c.PrimitiveTypes["int64_t"],
|
||||
descriptor.FieldDescriptorProto_TYPE_UINT32: c.PrimitiveTypes["uint32_t"],
|
||||
descriptor.FieldDescriptorProto_TYPE_UINT64: c.PrimitiveTypes["uint64_t"],
|
||||
descriptor.FieldDescriptorProto_TYPE_BOOL: c.PrimitiveTypes["bool"],
|
||||
descriptor.FieldDescriptorProto_TYPE_BYTES: c.genericOf(NewVectorType, c.PrimitiveTypes["uint8_t"]),
|
||||
descriptor.FieldDescriptorProto_TYPE_STRING: c.PrimitiveTypes["std::string"],
|
||||
}
|
||||
for _, f := range c.Request.ProtoFile {
|
||||
log.Printf("Doing file %v", *f.Name)
|
||||
typeMappings := map[string]GeneratableType{}
|
||||
for _, e := range f.EnumType {
|
||||
values := make([]EnumValue, 0, len(e.Value))
|
||||
for _, v := range e.Value {
|
||||
values = append(values, EnumValue{
|
||||
Name: *v.Name,
|
||||
Value: fmt.Sprint(*v.Number),
|
||||
})
|
||||
}
|
||||
log.Printf("name: %v", *f.Name)
|
||||
et := &EnumType{
|
||||
Name: *e.Name,
|
||||
Values: values,
|
||||
ProtoName: StripExtenstion(*f.Name),
|
||||
}
|
||||
typeMappings[*e.Name] = et
|
||||
c.AllTypes = append(c.AllTypes, et)
|
||||
}
|
||||
|
||||
for _, m := range f.MessageType {
|
||||
|
||||
ct := &ClassType{
|
||||
Name: *m.Name,
|
||||
ProtoName: StripExtenstion(*f.Name),
|
||||
}
|
||||
typeMappings[*m.Name] = ct
|
||||
c.AllTypes = append(c.AllTypes, ct)
|
||||
}
|
||||
|
||||
for _, m := range f.MessageType {
|
||||
|
||||
fields := []ClassField{}
|
||||
for _, f := range m.Field {
|
||||
isMessage := *f.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE
|
||||
isEnum := *f.Type == descriptor.FieldDescriptorProto_TYPE_ENUM
|
||||
|
||||
var fieldType GeneratableType
|
||||
if isMessage || isEnum {
|
||||
fqn := strings.Split(*f.TypeName, ".")
|
||||
className := fqn[1]
|
||||
|
||||
fieldType = typeMappings[className]
|
||||
} else {
|
||||
primitiveType, ok := pbType2reflection[*f.Type]
|
||||
if !ok {
|
||||
log.Fatal("unsupported proto type", (*f.Type).String())
|
||||
}
|
||||
fieldType = primitiveType
|
||||
|
||||
// log.Printf("%#v == %v", primitiveType, *f.Type)
|
||||
|
||||
}
|
||||
if f.Label != nil && *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
|
||||
fieldType = c.genericOf(NewVectorType, fieldType)
|
||||
} else if f.Label != nil && *f.Label != descriptor.FieldDescriptorProto_LABEL_REQUIRED {
|
||||
fieldType = c.genericOf(NewOptionalType, fieldType)
|
||||
}
|
||||
|
||||
fields = append(fields, ClassField{
|
||||
Name: *f.Name,
|
||||
Type: fieldType,
|
||||
ProtobufTag: uint32(*f.Number),
|
||||
})
|
||||
}
|
||||
ct := typeMappings[*m.Name].(*ClassType)
|
||||
ct.Fields = fields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Corntext) genericOf(constructor func(inner GeneratableType) GenericType, inner GeneratableType) (ret GeneratableType) {
|
||||
sample := constructor(nil)
|
||||
for _, t := range c.AllTypes {
|
||||
if v, ok := t.(GenericType); ok {
|
||||
|
||||
if reflect.TypeOf(sample).String() == reflect.TypeOf(v).String() && v.GetInnerType() == inner {
|
||||
ret = v
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if ret == nil {
|
||||
ret = constructor(inner)
|
||||
|
||||
c.AllTypes = append(c.AllTypes, ret)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Corntext) generateReflectionTypes() {
|
||||
c.TypeIDEnum = &EnumType{
|
||||
Name: "ReflectTypeID",
|
||||
ProtoName: "ReflectionInternal",
|
||||
Values: []EnumValue{},
|
||||
}
|
||||
c.TypeKindEnum = &EnumType{
|
||||
Name: "ReflectTypeKind",
|
||||
ProtoName: "ReflectionInternal",
|
||||
Values: []EnumValue{
|
||||
{Name: "Primitive", Value: "0"},
|
||||
{Name: "Enum", Value: "1"},
|
||||
{Name: "Class", Value: "2"},
|
||||
{Name: "Vector", Value: "3"},
|
||||
{Name: "Optional", Value: "4"},
|
||||
},
|
||||
}
|
||||
c.ReflectField = &ClassType{
|
||||
Name: "ReflectField",
|
||||
ProtoName: "ReflectionInternal",
|
||||
Fields: []ClassField{
|
||||
{"typeID", 0, c.TypeIDEnum},
|
||||
{"name", 0, c.PrimitiveTypes["std::string"]},
|
||||
{"offset", 0, c.PrimitiveTypes["size_t"]},
|
||||
{"protobufTag", 0, c.PrimitiveTypes["uint32_t"]},
|
||||
},
|
||||
AdditionalLibraryIncludes: []string{
|
||||
"string",
|
||||
},
|
||||
AdditionalCode: `
|
||||
ReflectField() {};
|
||||
ReflectField(ReflectTypeID typeID, std::string name, size_t offset, uint32_t protobufTag) {
|
||||
this->typeID = typeID;
|
||||
this->name = name;
|
||||
this->offset = offset;
|
||||
this->protobufTag = protobufTag;
|
||||
}
|
||||
`,
|
||||
}
|
||||
c.ReflectEnumValue = &ClassType{
|
||||
Name: "ReflectEnumValue",
|
||||
ProtoName: "ReflectionInternal",
|
||||
Fields: []ClassField{
|
||||
{"name", 0, c.PrimitiveTypes["std::string"]},
|
||||
{"value", 0, c.PrimitiveTypes["int"]},
|
||||
},
|
||||
AdditionalLibraryIncludes: []string{
|
||||
"string",
|
||||
},
|
||||
AdditionalCode: `
|
||||
ReflectEnumValue(){};
|
||||
ReflectEnumValue( std::string name, int value) {
|
||||
this->name = name;
|
||||
this->value = value;
|
||||
}
|
||||
`,
|
||||
}
|
||||
c.vectorOfReflectFields = &VectorType{
|
||||
InnerType: c.ReflectField,
|
||||
}
|
||||
c.vectorOfReflectEnumValues = &VectorType{
|
||||
InnerType: c.ReflectEnumValue,
|
||||
}
|
||||
c.ReflectType = &ClassType{
|
||||
Name: "ReflectType",
|
||||
ProtoName: "ReflectionInternal",
|
||||
Fields: []ClassField{
|
||||
{"typeID", 0, c.TypeIDEnum},
|
||||
{"name", 0, c.PrimitiveTypes["std::string"]},
|
||||
{"kind", 0, c.TypeKindEnum},
|
||||
{"size", 0, c.PrimitiveTypes["size_t"]},
|
||||
{"innerType", 0, c.TypeIDEnum},
|
||||
{"fields", 0, c.vectorOfReflectFields},
|
||||
{"enumValues", 0, c.vectorOfReflectEnumValues},
|
||||
},
|
||||
AdditionalLibraryIncludes: []string{
|
||||
"string",
|
||||
"vector",
|
||||
},
|
||||
AdditionalCode: `
|
||||
void (*_Construct)(void *mem);
|
||||
void (*_Destruct)(void *obj);
|
||||
VectorOperations vectorOps;
|
||||
OptionalOperations optionalOps;
|
||||
static ReflectType ofPrimitive(ReflectTypeID id, std::string name, size_t size) {
|
||||
ReflectType t;
|
||||
t.kind = ReflectTypeKind::Primitive;
|
||||
t.typeID = id;
|
||||
t.name = name;
|
||||
t.size = size;
|
||||
return t;
|
||||
}
|
||||
static ReflectType ofEnum(ReflectTypeID id, std::string name, std::vector<ReflectEnumValue> enumValues, size_t size) {
|
||||
ReflectType t;
|
||||
t.kind = ReflectTypeKind::Enum;
|
||||
t.typeID = id;
|
||||
t.name = name;
|
||||
t.size = size;
|
||||
t.enumValues = enumValues;
|
||||
return t;
|
||||
}
|
||||
static ReflectType ofVector(ReflectTypeID id, ReflectTypeID innerType, size_t size,
|
||||
VectorOperations vectorOps,
|
||||
void (*_Construct)(void *mem), void (*_Destruct)(void *obj)) {
|
||||
ReflectType t;
|
||||
t.kind = ReflectTypeKind::Vector;
|
||||
t.typeID = id;
|
||||
t.innerType = innerType;
|
||||
t.size = size;
|
||||
t._Construct = _Construct;
|
||||
t._Destruct = _Destruct;
|
||||
t.vectorOps = vectorOps;
|
||||
return t;
|
||||
}
|
||||
static ReflectType ofOptional(ReflectTypeID id, ReflectTypeID innerType, size_t size,
|
||||
OptionalOperations optionalOps,
|
||||
void (*_Construct)(void *mem), void (*_Destruct)(void *obj)) {
|
||||
ReflectType t;
|
||||
t.kind = ReflectTypeKind::Optional;
|
||||
t.typeID = id;
|
||||
t.innerType = innerType;
|
||||
t.size = size;
|
||||
t._Construct = _Construct;
|
||||
t._Destruct = _Destruct;
|
||||
t.optionalOps = optionalOps;
|
||||
return t;
|
||||
}
|
||||
static ReflectType ofClass(ReflectTypeID id, std::string name, std::vector<ReflectField> fields, size_t size, void (*_Construct)(void *mem), void (*_Destruct)(void *obj)) {
|
||||
ReflectType t;
|
||||
t.kind = ReflectTypeKind::Class;
|
||||
t.name = name;
|
||||
t.typeID = id;
|
||||
t.size = size;
|
||||
t.fields = std::move(fields);
|
||||
t._Construct = _Construct;
|
||||
t._Destruct = _Destruct;
|
||||
return t;
|
||||
}
|
||||
|
||||
`,
|
||||
}
|
||||
}
|
||||
165
components/spotify/cspot/cpp-reflection/cpp_generator.go
Normal file
165
components/spotify/cspot/cpp-reflection/cpp_generator.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type CppGenerator struct {
|
||||
includes []string
|
||||
files map[string]*CppGenerator
|
||||
Body *bytes.Buffer
|
||||
BodyBeforeLocalIncludes *bytes.Buffer
|
||||
Filename string
|
||||
IsHeader bool
|
||||
}
|
||||
|
||||
// NewCppGenerator docsy bo ci wywali sie blad xd
|
||||
func NewCppGenerator(filename string) *CppGenerator {
|
||||
isHeader := true
|
||||
if strings.HasSuffix(filename, ".cpp") {
|
||||
isHeader = false
|
||||
}
|
||||
return &CppGenerator{
|
||||
includes: []string{},
|
||||
Body: &bytes.Buffer{},
|
||||
BodyBeforeLocalIncludes: &bytes.Buffer{},
|
||||
files: make(map[string]*CppGenerator),
|
||||
Filename: filename,
|
||||
IsHeader: isHeader,
|
||||
}
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) SubFile(filename string, isHeader bool) *CppGenerator {
|
||||
if gen, ok := cg.files[filename]; ok {
|
||||
return gen
|
||||
}
|
||||
gen := NewCppGenerator(filename)
|
||||
gen.IsHeader = isHeader
|
||||
gen.files = cg.files
|
||||
cg.files[filename] = gen
|
||||
return gen
|
||||
}
|
||||
|
||||
// AddLibraryInclude yes
|
||||
func (cg *CppGenerator) AddLibraryInclude(name string) *CppGenerator {
|
||||
resultingLine := fmt.Sprintf("#include <%s>", name)
|
||||
for _, a := range cg.includes {
|
||||
if a == resultingLine {
|
||||
return cg
|
||||
}
|
||||
}
|
||||
cg.includes = append(cg.includes, resultingLine)
|
||||
return cg
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) AddLocalInclude(name string) *CppGenerator {
|
||||
resultingLine := fmt.Sprintf("#include \"%s\"", name)
|
||||
for _, a := range cg.includes {
|
||||
if a == resultingLine {
|
||||
return cg
|
||||
}
|
||||
}
|
||||
cg.includes = append(cg.includes, resultingLine)
|
||||
return cg
|
||||
}
|
||||
|
||||
// OutputClassField yes
|
||||
func (cg *CppGenerator) OutputClassField(theType string, name string) {
|
||||
fmt.Fprintf(cg.Body, "%v %v;\n", theType, name)
|
||||
}
|
||||
|
||||
// OutputClassTypeID yes
|
||||
func (cg *CppGenerator) OutputClassTypeID(theID string) {
|
||||
fmt.Fprintf(cg.Body, "static constexpr ReflectTypeID _TYPE_ID = ReflectTypeID::%v;\n", theID)
|
||||
}
|
||||
|
||||
// OutputClass yes
|
||||
func (cg *CppGenerator) OutputClass(name string, cb func()) {
|
||||
fmt.Fprintf(cg.Body, "class %v {\npublic:\n", name)
|
||||
cb()
|
||||
fmt.Fprintf(cg.Body, "};\n\n")
|
||||
}
|
||||
|
||||
// OutputEnumClass
|
||||
func (cg *CppGenerator) OutputEnumClass(name string, cb func()) {
|
||||
fmt.Fprintf(cg.Body, "enum class %v {\n", name)
|
||||
cb()
|
||||
fmt.Fprintf(cg.Body, "};\n\n")
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) OutputArrayVariable(t string, name string, length int, cb func()) {
|
||||
fmt.Fprintf(cg.Body, "%v %v[%d] = {\n", t, name, length)
|
||||
cb()
|
||||
fmt.Fprintf(cg.Body, "};\n\n")
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) OutputArrayVariableExtern(t string, name string, length int) {
|
||||
fmt.Fprintf(cg.Body, "extern %v %v[%d];", t, name, length)
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) OutputEnumClassField(name string, value string) {
|
||||
fmt.Fprintf(cg.Body, "%v", name)
|
||||
if value != "" {
|
||||
fmt.Fprintf(cg.Body, " = %v", value)
|
||||
}
|
||||
fmt.Fprintf(cg.Body, ",\n")
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) EscapeCppString(str string) string {
|
||||
d, _ := json.Marshal(str)
|
||||
|
||||
return string(d)
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) WriteToWriter(w io.Writer) {
|
||||
fmt.Fprintf(w, "// THIS CORNFILE IS GENERATED. DO NOT EDIT! 🌽\n")
|
||||
guardString := "_"
|
||||
for _, c := range []rune(cg.Filename) {
|
||||
if unicode.IsUpper(c) {
|
||||
guardString += "_"
|
||||
}
|
||||
if unicode.IsLetter(c) {
|
||||
guardString += strings.ToUpper(string([]rune{c}))
|
||||
}
|
||||
}
|
||||
if cg.IsHeader {
|
||||
|
||||
fmt.Fprintf(w, "#ifndef %v\n", guardString)
|
||||
fmt.Fprintf(w, "#define %v\n", guardString)
|
||||
}
|
||||
for _, a := range cg.includes {
|
||||
if strings.Contains(a, "<") {
|
||||
fmt.Fprintf(w, "%v\n", a)
|
||||
}
|
||||
}
|
||||
io.Copy(w, cg.BodyBeforeLocalIncludes)
|
||||
for _, a := range cg.includes {
|
||||
if !strings.Contains(a, "<") && a != fmt.Sprintf("#include \"%v\"", cg.Filename) {
|
||||
fmt.Fprintf(w, "%v\n", a)
|
||||
}
|
||||
}
|
||||
io.Copy(w, cg.Body)
|
||||
if cg.IsHeader {
|
||||
fmt.Fprintf(w, "#endif\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (cg *CppGenerator) OutputToDirectory(dirPath string) {
|
||||
f, _ := os.Create(path.Join(dirPath, cg.Filename))
|
||||
defer f.Close()
|
||||
cg.WriteToWriter(f)
|
||||
|
||||
for _, fileToOutput := range cg.files {
|
||||
f, _ := os.Create(path.Join(dirPath, fileToOutput.Filename))
|
||||
defer f.Close()
|
||||
fileToOutput.WriteToWriter(f)
|
||||
}
|
||||
|
||||
}
|
||||
44
components/spotify/cspot/cpp-reflection/enum_type.go
Normal file
44
components/spotify/cspot/cpp-reflection/enum_type.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type EnumValue struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type EnumType struct {
|
||||
Name string
|
||||
Values []EnumValue
|
||||
ProtoName string
|
||||
}
|
||||
|
||||
func (et *EnumType) IdentifierName() string {
|
||||
return "Enum" + et.Name
|
||||
}
|
||||
|
||||
func (et *EnumType) DeclarationOrder() int {
|
||||
return -20
|
||||
}
|
||||
|
||||
func (et *EnumType) CppType() string {
|
||||
return et.Name
|
||||
}
|
||||
|
||||
func (et *EnumType) WriteDeclarations(gen *CppGenerator) {
|
||||
enumSubfile := gen.SubFile(et.ProtoName+".h", true)
|
||||
gen.AddLocalInclude(enumSubfile.Filename)
|
||||
enumSubfile.OutputEnumClass(et.Name, func() {
|
||||
for _, v := range et.Values {
|
||||
enumSubfile.OutputEnumClassField(v.Name, v.Value)
|
||||
}
|
||||
})
|
||||
}
|
||||
func (et *EnumType) WriteReflection(gen *CppGenerator) {
|
||||
enumValues := ""
|
||||
for _, v := range et.Values {
|
||||
enumValues += fmt.Sprintf(" ReflectEnumValue(%v, %v),\n", gen.EscapeCppString(v.Name), v.Value)
|
||||
}
|
||||
fmt.Fprintf(gen.Body, "ReflectType::ofEnum(/* mine id */ ReflectTypeID::%v, /* name */ %v, /* enum values */ std::move(std::vector<ReflectEnumValue>{%v}), /* size */ sizeof(%v))",
|
||||
et.IdentifierName(), gen.EscapeCppString(et.CppType()), enumValues, et.CppType())
|
||||
}
|
||||
21
components/spotify/cspot/cpp-reflection/go.sum
Normal file
21
components/spotify/cspot/cpp-reflection/go.sum
Normal file
@@ -0,0 +1,21 @@
|
||||
github.com/celer-network/pb3-gen-sol v1.1.1 h1:MaWWsz17plSDCh538l6QaJQ1cOORqzx82lt/slz9pkM=
|
||||
github.com/celer-network/pb3-gen-sol v1.1.1/go.mod h1:mJkD650gSksCeWrGLzKfj1nMc7y0cFlP3ZC2qaqOk3g=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
34
components/spotify/cspot/cpp-reflection/main.go
Normal file
34
components/spotify/cspot/cpp-reflection/main.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/celer-network/pb3-gen-sol/generator"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := NewCorntext()
|
||||
|
||||
data, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
generator.Error(err, "reading input")
|
||||
}
|
||||
|
||||
if err := proto.Unmarshal(data, c.Request); err != nil {
|
||||
generator.Error(err, "parsing input proto")
|
||||
}
|
||||
c.buildAllTypes()
|
||||
c.outputTypes()
|
||||
// Send back the results.
|
||||
data, err = proto.Marshal(c.Response)
|
||||
if err != nil {
|
||||
log.Fatal(err, "failed to marshal output proto")
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
if err != nil {
|
||||
log.Fatal(err, "failed to write output proto")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type OptionalHelperTypes struct {
|
||||
}
|
||||
|
||||
func (oht *OptionalHelperTypes) GenerateOptionalOperationsStruct(cg *CppGenerator) {
|
||||
fmt.Fprintln(cg.BodyBeforeLocalIncludes, `
|
||||
class AnyRef;
|
||||
struct OptionalOperations {
|
||||
AnyRef (*get)(AnyRef &opt);
|
||||
bool (*has_value)(AnyRef &opt);
|
||||
void (*set)(AnyRef &opt, AnyRef &val);
|
||||
void (*reset)(AnyRef &opt);
|
||||
void (*emplaceEmpty)(AnyRef &opt);
|
||||
};
|
||||
|
||||
`)
|
||||
}
|
||||
|
||||
func (oht *OptionalHelperTypes) GenerateOptionalManipulator(cg *CppGenerator) {
|
||||
fmt.Fprintln(cg.Body, `
|
||||
template<class T>
|
||||
class __OptionalManipulator {
|
||||
public:
|
||||
static AnyRef get(AnyRef &opt) {
|
||||
auto theOptional = reinterpret_cast<std::optional<T>*>(opt.value.voidptr);
|
||||
return AnyRef::of<T>(&**theOptional);
|
||||
}
|
||||
static bool has_value(AnyRef &opt) {
|
||||
auto theOptional = reinterpret_cast<std::optional<T>*>(opt.value.voidptr);
|
||||
return theOptional->has_value();
|
||||
}
|
||||
static void set(AnyRef &opt, AnyRef &val) {
|
||||
auto theOptional = reinterpret_cast<std::optional<T>*>(opt.value.voidptr);
|
||||
auto theValue = reinterpret_cast<T*>(val.value.voidptr);
|
||||
*theOptional = *theValue;
|
||||
}
|
||||
|
||||
static void reset(AnyRef &opt) {
|
||||
auto theOptional = reinterpret_cast<std::optional<T>*>(opt.value.voidptr);
|
||||
theOptional->reset();
|
||||
}
|
||||
|
||||
static void emplaceEmpty(AnyRef &opt) {
|
||||
auto theOptional = reinterpret_cast<std::optional<T>*>(opt.value.voidptr);
|
||||
theOptional->emplace();
|
||||
}
|
||||
};
|
||||
|
||||
`)
|
||||
}
|
||||
54
components/spotify/cspot/cpp-reflection/optional_type.go
Normal file
54
components/spotify/cspot/cpp-reflection/optional_type.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type OptionalType struct {
|
||||
InnerType GeneratableType
|
||||
}
|
||||
|
||||
func NewOptionalType(inner GeneratableType) GenericType {
|
||||
return &OptionalType{
|
||||
InnerType: inner,
|
||||
}
|
||||
}
|
||||
|
||||
func (vt *OptionalType) GetInnerType() GeneratableType {
|
||||
return vt.InnerType
|
||||
}
|
||||
|
||||
func (vt *OptionalType) IdentifierName() string {
|
||||
return "OptionalOf" + vt.InnerType.IdentifierName()
|
||||
}
|
||||
func (vt *OptionalType) CppType() string {
|
||||
return fmt.Sprintf("std::optional<%v>", vt.InnerType.CppType())
|
||||
}
|
||||
|
||||
func (vt *OptionalType) WriteDeclarations(gen *CppGenerator) {
|
||||
gen.AddLibraryInclude("optional")
|
||||
}
|
||||
func (vt *OptionalType) WriteReflection(gen *CppGenerator) {
|
||||
|
||||
template.Must(template.New("any.cpp").Parse(`
|
||||
ReflectType::ofOptional(
|
||||
/* mine typeId */ ReflectTypeID::{{ .IdentifierName }},
|
||||
/* inner type id */ ReflectTypeID::{{ .InnerType.IdentifierName }},
|
||||
/* size */ sizeof({{ .CppType }}),
|
||||
/* option */ OptionalOperations{
|
||||
.get = __OptionalManipulator<{{ .InnerType.CppType }}>::get,
|
||||
.has_value = __OptionalManipulator<{{ .InnerType.CppType }}>::has_value,
|
||||
.set = __OptionalManipulator<{{ .InnerType.CppType }}>::set,
|
||||
.reset = __OptionalManipulator<{{ .InnerType.CppType }}>::reset,
|
||||
.emplaceEmpty = __OptionalManipulator<{{ .InnerType.CppType }}>::emplaceEmpty,
|
||||
},
|
||||
__reflectConstruct<{{ .CppType }}>,
|
||||
__reflectDestruct<{{ .CppType }}>
|
||||
)
|
||||
|
||||
|
||||
|
||||
`)).Execute(gen.Body, vt)
|
||||
|
||||
}
|
||||
26
components/spotify/cspot/cpp-reflection/primitive_type.go
Normal file
26
components/spotify/cspot/cpp-reflection/primitive_type.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type PrimitiveType struct {
|
||||
identifierName string
|
||||
cppType string
|
||||
}
|
||||
|
||||
func (pt *PrimitiveType) IdentifierName() string {
|
||||
return pt.identifierName
|
||||
}
|
||||
|
||||
func (pt *PrimitiveType) CppType() string {
|
||||
return pt.cppType
|
||||
}
|
||||
|
||||
func (pt *PrimitiveType) WriteDeclarations(gen *CppGenerator) {
|
||||
if pt.cppType == "std::string" {
|
||||
gen.AddLibraryInclude("string")
|
||||
}
|
||||
}
|
||||
func (pt *PrimitiveType) WriteReflection(gen *CppGenerator) {
|
||||
fmt.Fprintf(gen.Body, "ReflectType::ofPrimitive(/* type id */ ReflectTypeID::%v, /* name */ %v, /* size */ sizeof(%v))",
|
||||
pt.IdentifierName(), gen.EscapeCppString(pt.CppType()), pt.CppType())
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package main
|
||||
25
components/spotify/cspot/cpp-reflection/util.go
Normal file
25
components/spotify/cspot/cpp-reflection/util.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func AddIncludeForType(t GeneratableType, gen *CppGenerator) {
|
||||
switch v := t.(type) {
|
||||
case *ClassType:
|
||||
gen.AddLocalInclude(v.ProtoName + ".h")
|
||||
case *EnumType:
|
||||
gen.AddLocalInclude(v.ProtoName + ".h")
|
||||
case *VectorType:
|
||||
gen.AddLibraryInclude("vector")
|
||||
AddIncludeForType(v.InnerType, gen)
|
||||
case *OptionalType:
|
||||
gen.AddLibraryInclude("optional")
|
||||
AddIncludeForType(v.InnerType, gen)
|
||||
}
|
||||
}
|
||||
|
||||
func StripExtenstion(filename string) string {
|
||||
return strings.TrimSuffix(filename, filepath.Ext(filename))
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type VectorHelperTypes struct {
|
||||
}
|
||||
|
||||
func (vht *VectorHelperTypes) GenerateVectorOperationsStruct(cg *CppGenerator) {
|
||||
fmt.Fprintln(cg.BodyBeforeLocalIncludes, `
|
||||
class AnyRef;
|
||||
struct VectorOperations {
|
||||
void (*push_back)(AnyRef &vec, AnyRef &val);
|
||||
AnyRef (*at)(AnyRef &vec, size_t index);
|
||||
size_t (*size)(AnyRef &vec);
|
||||
void (*emplace_back)(AnyRef &vec);
|
||||
void (*clear)(AnyRef &vec);
|
||||
void (*reserve)(AnyRef &vec, size_t n);
|
||||
};
|
||||
|
||||
`)
|
||||
}
|
||||
|
||||
func (vht *VectorHelperTypes) GenerateVectorManipulator(cg *CppGenerator) {
|
||||
fmt.Fprintln(cg.Body, `
|
||||
template<class T>
|
||||
class __VectorManipulator {
|
||||
public:
|
||||
static void push_back(AnyRef &vec, AnyRef &val) {
|
||||
auto theVector = reinterpret_cast<std::vector<T>*>(vec.value.voidptr);
|
||||
auto theValue = *reinterpret_cast<T*>(val.value.voidptr);
|
||||
theVector->push_back(theValue);
|
||||
};
|
||||
static AnyRef at(AnyRef &vec, size_t index) {
|
||||
auto theVector = reinterpret_cast<std::vector<T>*>(vec.value.voidptr);
|
||||
return AnyRef::of<T>(&(*theVector)[index]);
|
||||
};
|
||||
static size_t size(AnyRef &vec) {
|
||||
auto theVector = reinterpret_cast<std::vector<T>*>(vec.value.voidptr);
|
||||
return theVector->size();
|
||||
};
|
||||
static void emplace_back(AnyRef &vec) {
|
||||
auto theVector = reinterpret_cast<std::vector<T>*>(vec.value.voidptr);
|
||||
theVector->emplace_back();
|
||||
};
|
||||
static void clear(AnyRef &vec) {
|
||||
auto theVector = reinterpret_cast<std::vector<T>*>(vec.value.voidptr);
|
||||
theVector->clear();
|
||||
};
|
||||
static void reserve(AnyRef &vec, size_t n) {
|
||||
auto theVector = reinterpret_cast<std::vector<T>*>(vec.value.voidptr);
|
||||
theVector->reserve(n);
|
||||
};
|
||||
};
|
||||
`)
|
||||
}
|
||||
65
components/spotify/cspot/cpp-reflection/vector_type.go
Normal file
65
components/spotify/cspot/cpp-reflection/vector_type.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type VectorType struct {
|
||||
InnerType GeneratableType
|
||||
}
|
||||
|
||||
func NewVectorType(inner GeneratableType) GenericType {
|
||||
return &VectorType{
|
||||
InnerType: inner,
|
||||
}
|
||||
}
|
||||
|
||||
func (vt *VectorType) GetInnerType() GeneratableType {
|
||||
return vt.InnerType
|
||||
}
|
||||
|
||||
func (vt *VectorType) IdentifierName() string {
|
||||
return "VectorOf" + vt.InnerType.IdentifierName()
|
||||
}
|
||||
func (vt *VectorType) CppType() string {
|
||||
return fmt.Sprintf("std::vector<%v>", vt.InnerType.CppType())
|
||||
}
|
||||
|
||||
func (vt *VectorType) WriteDeclarations(gen *CppGenerator) {
|
||||
gen.AddLibraryInclude("vector")
|
||||
}
|
||||
func (vt *VectorType) WriteReflection(gen *CppGenerator) {
|
||||
|
||||
template.Must(template.New("any.cpp").Parse(`
|
||||
ReflectType::ofVector(
|
||||
/* mine typeId */ ReflectTypeID::{{ .IdentifierName }},
|
||||
/* inner type id */ ReflectTypeID::{{ .InnerType.IdentifierName }},
|
||||
/* size */ sizeof({{ .CppType }}),
|
||||
VectorOperations{
|
||||
.push_back = __VectorManipulator<{{ .InnerType.CppType }}>::push_back,
|
||||
.at = __VectorManipulator<{{ .InnerType.CppType }}>::at,
|
||||
.size = __VectorManipulator<{{ .InnerType.CppType }}>::size,
|
||||
.emplace_back = __VectorManipulator<{{ .InnerType.CppType }}>::emplace_back,
|
||||
.clear = __VectorManipulator<{{ .InnerType.CppType }}>::clear,
|
||||
.reserve = __VectorManipulator<{{ .InnerType.CppType }}>::reserve,
|
||||
},
|
||||
__reflectConstruct<{{ .CppType }}>,
|
||||
__reflectDestruct<{{ .CppType }}>
|
||||
)
|
||||
|
||||
|
||||
|
||||
`)).Execute(gen.Body, vt)
|
||||
// fmt.Fprintf(gen.Body, `ReflectType::ofVector(
|
||||
// /* mine typeId */ ReflectTypeID::%v,
|
||||
// /* inner type id */ ReflectTypeID::%v,
|
||||
// /* size */ sizeof(%v),
|
||||
// VectorOperations{
|
||||
// .push_back = __VectorManipulator<%v>
|
||||
// },
|
||||
// __reflectConstruct<%v>,
|
||||
// __reflectDestruct<%v>
|
||||
// )`,
|
||||
// vt.IdentifierName(), vt.InnerType.IdentifierName(), vt.CppType(), vt.CppType(), vt.CppType(), vt.CppType())
|
||||
}
|
||||
Reference in New Issue
Block a user