templates

package
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2020 License: GPL-3.0 Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var CBindingTemplate = template.Must(template.New("binding").Funcs(funcMap).Parse(
	`// Code generated by ObjectBox; DO NOT EDIT.

#pragma once

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "flatcc/flatcc.h"
#include "flatcc/flatcc_builder.h"
#include "objectbox.h"
{{range $entity := .Model.EntitiesWithMeta}}
{{PrintComments 0 $entity.Comments}}typedef struct {{$entity.Meta.CName}} {
	{{range $property := $entity.Properties}}{{$propType := PropTypeName $property.Type -}}
	{{PrintComments 1 $property.Comments}}{{if $property.Meta.FbIsVector}}{{$property.Meta.CElementType}}* {{$property.Meta.CppName}};
	{{- if or (eq $propType "StringVector") (eq $propType "ByteVector")}}
	size_t {{$property.Meta.CppName}}_len;{{end}}
	{{else}}{{$property.Meta.CppType}} {{$property.Meta.CppName}};
	{{end}}{{end}}
} {{$entity.Meta.CName}};

enum {{$entity.Meta.CName}}_ {
	{{$entity.Meta.CName}}_ENTITY_ID = {{$entity.Id.GetId}},
{{- range $property := $entity.Properties}}
	{{$entity.Meta.CName}}_PROP_ID_{{$property.Meta.CppName}} = {{$property.Id.GetId}},
{{- end}}
};
{{end}}
{{- range $entity := .Model.EntitiesWithMeta}}
/// Write given object to the FlatBufferBuilder
/// TODO test on a big-endian platform... especially vector creation
static bool {{$entity.Meta.CName}}_to_flatbuffer(flatcc_builder_t* B, const {{$entity.Meta.CName}}* object, void** out_buffer, size_t* out_size) {
    assert(B);
    assert(object);
    assert(out_buffer);
    assert(out_size);

    flatcc_builder_reset(B);
	flatcc_builder_start_buffer(B, 0, 0, 0);
	{{range $property := $entity.Properties}}{{$propType := PropTypeName $property.Type}}
	{{- if eq $propType "String"}}
	flatcc_builder_ref_t offset_{{$property.Meta.CppName}} = !object->{{$property.Meta.CppName}} ? 0 : flatcc_builder_create_string_str(B, object->{{$property.Meta.CppName}});
	{{- else if eq $propType "ByteVector"}}
	flatcc_builder_ref_t offset_{{$property.Meta.CppName}} = !object->{{$property.Meta.CppName}} ? 0 : flatcc_builder_create_vector(B, object->{{$property.Meta.CppName}}, object->{{$property.Meta.CppName}}_len, sizeof({{$property.Meta.CElementType}}), sizeof({{$property.Meta.CElementType}}), FLATBUFFERS_COUNT_MAX(sizeof({{$property.Meta.CElementType}})));
	{{- else if eq $propType "StringVector"}}
	flatcc_builder_ref_t offset_{{$property.Meta.CppName}} = 0;
	if (object->{{$property.Meta.CppName}}) {
		flatcc_builder_start_offset_vector(B);
		for (size_t i = 0; i < object->{{$property.Meta.CppName}}_len; i++) {
			flatcc_builder_ref_t ref = !object->{{$property.Meta.CppName}}[i] ? 0 : flatcc_builder_create_string_str(B, object->{{$property.Meta.CppName}}[i]);
			if (ref) flatcc_builder_offset_vector_push(B, ref);
		}
		offset_{{$property.Meta.CppName}} = flatcc_builder_end_offset_vector(B);
	}
	{{- end}}{{end}}

    if (flatcc_builder_start_table(B, {{len $entity.Properties}}) != 0) return false;

    void* p;
	flatcc_builder_ref_t* _p;
	{{range $property := $entity.Properties}}
	{{- if $property.Meta.FbIsVector}}
	if (offset_{{$property.Meta.CppName}}) {
        if (!(_p = flatcc_builder_table_add_offset(B, {{$property.FbSlot}}))) return false;
        *_p = offset_{{$property.Meta.CppName}};
    }
	{{- else}}
	if (!(p = flatcc_builder_table_add(B, {{$property.FbSlot}}, {{$property.Meta.FbTypeSize}}, {{$property.Meta.FbTypeSize}}))) return false;
    {{$property.Meta.FlatccFnPrefix}}_write_to_pe(p, object->{{$property.Meta.CppName}});
	{{- end}}
	{{end}}
    flatcc_builder_ref_t ref;
	if (!(ref = flatcc_builder_end_table(B))) return false;
	if (!flatcc_builder_end_buffer(B, ref)) return false;
    return (*out_buffer = flatcc_builder_finalize_aligned_buffer(B, out_size)) != NULL;
}

/// Read an object from a valid FlatBuffer.
/// If the read object contains vectors or strings, those are allocated on heap and must be freed after use by calling {{$entity.Meta.CName}}_free_pointers().
/// If the given object already contains un-freed pointers, the memory will be lost - free manually before calling this function twice on the same object. 
static void {{$entity.Meta.CName}}_from_flatbuffer(const void* data, size_t size, {{$entity.Meta.CName}}* out_object) {
	assert(data);
	assert(out_object);

	const uint8_t* table = (const uint8_t*) data + __flatbuffers_uoffset_read_from_pe(data);
	assert(table);
	flatbuffers_voffset_t *vt = (flatbuffers_voffset_t*) (table - __flatbuffers_soffset_read_from_pe(table));
	flatbuffers_voffset_t vs = __flatbuffers_voffset_read_from_pe(vt);

	// variables reused when reading strings and vectors
	flatbuffers_voffset_t offset;
	const flatbuffers_uoffset_t* val;
	size_t len;

	{{range $property := $entity.Properties}}{{$propType := PropTypeName $property.Type -}}
	{{if $property.Meta.FbIsVector}}
	if ((offset = (vs < sizeof(vt[0]) * ({{$property.FbSlot}} + 3)) ? {{$property.Meta.FbDefaultValue}} : __flatbuffers_voffset_read_from_pe(vt + {{$property.FbSlot}} + 2))) {
		val = (const flatbuffers_uoffset_t*)(table + offset + sizeof(flatbuffers_uoffset_t) + __flatbuffers_uoffset_read_from_pe(table + offset));
		len = (size_t) __flatbuffers_uoffset_read_from_pe(val - 1);
		out_object->{{$property.Meta.CppName}} = ({{$property.Meta.CElementType}}*) malloc(len * sizeof({{$property.Meta.CElementType}}));
		{{- if not (eq $propType "String")}}
		out_object->{{$property.Meta.CppName}}_len = len;
		{{- end -}}
		{{/*Note: direct copy for string and byte vectors*/}}
		{{if eq $propType "String"}}memcpy((void*)out_object->{{$property.Meta.CppName}}, (const void*)val, len+1);
		{{else if eq $propType "ByteVector"}}memcpy((void*)out_object->{{$property.Meta.CppName}}, (const void*)val, len);
		{{else}}{{/* StringVector - FB vector contains offsets to strings, each must be read separately*/ -}}
		for (size_t i = 0; i < len; i++, val++) {
			const uint8_t* str = (const uint8_t*) val + (size_t)__flatbuffers_uoffset_read_from_pe(val) + sizeof(val[0]);
			out_object->{{$property.Meta.CppName}}[i] = (char*) malloc((strlen((const char*)str) + 1) * sizeof(char));
			strcpy((char*)out_object->{{$property.Meta.CppName}}[i], (const char*)str);
		}{{end}}
	} else {
		out_object->{{$property.Meta.CppName}} = NULL;
		{{- if not (eq $propType "String")}}
		out_object->{{$property.Meta.CppName}}_len = 0;
		{{- end}}
	}
	{{else}}out_object->{{$property.Meta.CppName}} = (vs < sizeof(vt[0]) * ({{$property.FbSlot}} + 3)) ? {{$property.Meta.FbDefaultValue}} : {{$property.Meta.FlatccFnPrefix}}_read_from_pe(table + __flatbuffers_voffset_read_from_pe(vt + {{$property.FbSlot}} + 2));
	{{- end}}
	{{end}}
}

/// Read an object from a valid FlatBuffer, allocating the object on heap. 
/// The object must be freed after use by calling {{$entity.Meta.CName}}_free();
static {{$entity.Meta.CName}}* {{$entity.Meta.CName}}_new_from_flatbuffer(const void* data, size_t size) {
	{{$entity.Meta.CName}}* object = ({{$entity.Meta.CName}}*) malloc(sizeof({{$entity.Meta.CName}}));
	{{$entity.Meta.CName}}_from_flatbuffer(data, size, object);
	return object;
}

static void {{$entity.Meta.CName}}_free_pointers({{$entity.Meta.CName}}* object) {
	{{- range $property := $entity.Properties}}{{$propType := PropTypeName $property.Type}}{{if $property.Meta.FbIsVector}}
	if (object->{{$property.Meta.CppName}}) {
		{{- if eq $propType "StringVector"}}
		assert(object->{{$property.Meta.CppName}}_len > 0);
		for (size_t i = 0; i < object->{{$property.Meta.CppName}}_len; i++) {
			if (object->{{$property.Meta.CppName}}[i]) free(object->{{$property.Meta.CppName}}[i]);
		}{{end}}
		free(object->{{$property.Meta.CppName}});
		object->{{$property.Meta.CppName}} = NULL;
	{{- if not (eq $propType "String")}}
		object->{{$property.Meta.CppName}}_len = 0;
	} else {
		assert(object->{{$property.Meta.CppName}}_len == 0);
	{{- end}}
	}
	{{end}}
	{{- end}}
}

static void {{$entity.Meta.CName}}_free({{$entity.Meta.CName}}** object) {
	if (!object || !*object) return;
	{{$entity.Meta.CName}}_free_pointers(*object);
	free(*object);
	*object = NULL;
}
{{end}}
`))

CBindingTemplate is used to generated the binding code

View Source
var CppBindingTemplate = template.Must(template.New("binding").Funcs(funcMap).Parse(
	`// Code generated by ObjectBox; DO NOT EDIT.

#pragma once

#include <stdbool.h>
#include <stdint.h>

#include "flatbuffers/flatbuffers.h"
#include "objectbox.h"
{{range $entity := .Model.EntitiesWithMeta}}{{with $entity.Meta.CppNamespaceStart}}
{{.}}{{end}}
struct {{$entity.Meta.CppName}}_;

{{PrintComments 0 $entity.Comments}}struct {{$entity.Meta.CppName}} {
    using _OBX_MetaInfo = {{$entity.Meta.CppName}}_;
	{{range $property := $entity.Properties}}
	{{PrintComments 1 $property.Comments}}{{$property.Meta.CppType}} {{$property.Meta.CppName}};
	{{- end}}
};

struct {{$entity.Meta.CppName}}_ {
{{- range $property := $entity.Properties}}
	static const obx_schema_id {{$property.Meta.CppName}} = {{$property.Id.GetId}};
{{- end}}

    static constexpr obx_schema_id entityId() { return {{$entity.Id.GetId}}; }

    static void setObjectId({{$entity.Meta.CppName}}& object, obx_id newId) { object.{{$entity.IdProperty.Meta.CppName}} = newId; }

	/// Write given object to the FlatBufferBuilder
	static void toFlatBuffer(flatbuffers::FlatBufferBuilder& fbb, const {{$entity.Meta.CppName}}& object);

	/// Read an object from a valid FlatBuffer
	static {{$entity.Meta.CppName}} fromFlatBuffer(const void* data, size_t size);

	/// Read an object from a valid FlatBuffer
	static std::unique_ptr<{{$entity.Meta.CppName}}> newFromFlatBuffer(const void* data, size_t size);

	/// Read an object from a valid FlatBuffer
	static void fromFlatBuffer(const void* data, size_t size, {{$entity.Meta.CppName}}& outObject);
};
{{with $entity.Meta.CppNamespaceEnd}}{{.}}{{end -}}
{{end}}
{{- range $entity := .Model.EntitiesWithMeta}}
inline void {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}_::toFlatBuffer(flatbuffers::FlatBufferBuilder& fbb, const {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}& object) {
	fbb.Clear();
	{{- range $property := $entity.Properties}}{{$factory := $property.Meta.FbOffsetFactory}}{{if $factory}}
	auto offset{{$property.Meta.CppName}} = fbb.{{$factory}}(object.{{$property.Meta.CppName}});
	{{- end}}{{end}}
	flatbuffers::uoffset_t fbStart = fbb.StartTable();
	{{range $property := $entity.Properties}}
	{{- if $property.Meta.FbOffsetFactory}}fbb.AddOffset({{$property.FbvTableOffset}}, offset{{$property.Meta.CppName}});
	{{- else if eq "bool" $property.Meta.CppType}}fbb.TrackField({{$property.FbvTableOffset}}, fbb.PushElement<uint8_t>(object.{{$property.Meta.CppName}} ? 1 : 0));
	{{- else}}fbb.TrackField({{$property.FbvTableOffset}}, fbb.PushElement<{{$property.Meta.CppType}}>(object.{{$property.Meta.CppName}}));
	{{- end}}
	{{end -}}
	flatbuffers::Offset<flatbuffers::Table> offset;
	offset.o = fbb.EndTable(fbStart);
	fbb.Finish(offset);
}

inline {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}} {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}_::fromFlatBuffer(const void* data, size_t size) {
	{{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}} object;
	fromFlatBuffer(data, size, object);
	return object;
}

inline std::unique_ptr<{{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}> {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}_::newFromFlatBuffer(const void* data, size_t size) {
	auto object = std::unique_ptr<{{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}>(new {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}());
	fromFlatBuffer(data, size, *object);
	return object;
}

inline void {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}_::fromFlatBuffer(const void* data, size_t size, {{$entity.Meta.CppNamespacePrefix}}{{$entity.Meta.CppName}}& outObject) {
	const auto* table = flatbuffers::GetRoot<flatbuffers::Table>(data);
	assert(table);
	{{range $property := $entity.Properties}}
	{{- if eq "std::vector<std::string>" $property.Meta.CppType}}{
		auto* ptr = table->GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>*>({{$property.FbvTableOffset}});
		if (ptr) {
			outObject.{{$property.Meta.CppName}}.reserve(ptr->size());
			for (size_t i = 0; i < ptr->size(); i++) {
				auto* itemPtr = ptr->Get(i);
				if (itemPtr) outObject.{{$property.Meta.CppName}}.emplace_back(itemPtr->c_str());
			}
		}
	}{{else if eq "std::string" $property.Meta.CppType}}{
		auto* ptr = table->GetPointer<const flatbuffers::String*>({{$property.FbvTableOffset}});
		if (ptr) outObject.{{$property.Meta.CppName}}.assign(ptr->c_str());
	}{{else if $property.Meta.FbIsVector}}{
		auto* ptr = table->GetPointer<const {{$property.Meta.FbOffsetType}}*>({{$property.FbvTableOffset}});
		if (ptr) outObject.{{$property.Meta.CppName}}.assign(ptr->begin(), ptr->end());
	}{{- else if eq "bool" $property.Meta.CppType}}outObject.{{$property.Meta.CppName}} = table->GetField<uint8_t>({{$property.FbvTableOffset}}, 0) != 0;
	{{- else}}outObject.{{$property.Meta.CppName}} = table->GetField<{{$property.Meta.CppType}}>({{$property.FbvTableOffset}}, {{$property.Meta.FbDefaultValue}});
	{{- end}}
	{{end}}
}
{{end}}
`))

CppBindingTemplate is used to generated the binding code

View Source
var ModelTemplate = template.Must(template.New("model").Funcs(funcMap).Parse(
	`// Code generated by ObjectBox; DO NOT EDIT.

#pragma once

#ifdef __cplusplus
#include <cstdbool>
#include <cstdint>
extern "C" {
#else
#include <stdbool.h>
#include <stdint.h>
#endif
#include "objectbox.h"

/// Initializes an ObjectBox model for all entities. 
/// The returned pointer may be NULL if the allocation failed. If the returned model is not NULL, you should check if   
/// any error occurred by calling obx_model_error_code() and/or obx_model_error_message(). If an error occurred, you're
/// responsible for freeing the resources by calling obx_model_free().
/// In case there was no error when setting the model up (i.e. obx_model_error_code() returned 0), you may configure 
/// OBX_store_options with the model by calling obx_opt_model() and subsequently opening a store with obx_store_open().
/// As soon as you call obx_store_open(), the model pointer is consumed and MUST NOT be freed manually.
static inline OBX_model* create_obx_model() {
    OBX_model* model = obx_model();
    if (!model) return NULL;
	{{range $entity := .Model.Entities}}
	obx_model_entity(model, "{{$entity.Name}}", {{$entity.Id.GetId}}, {{$entity.Id.GetUid}});
	{{range $property := $entity.Properties -}}
	obx_model_property(model, "{{$property.Name}}", OBXPropertyType_{{PropTypeName $property.Type}}, {{$property.Id.GetId}}, {{$property.Id.GetUid}});
	{{with $property.Flags}}obx_model_property_flags(model, {{CorePropFlags .}});
	{{end -}}
	{{if $property.RelationTarget}}obx_model_property_relation(model, "{{$property.RelationTarget}}", {{$property.IndexId.GetId}}, {{$property.IndexId.GetUid}});
	{{else if $property.IndexId}}obx_model_property_index_id(model, {{$property.IndexId.GetId}}, {{$property.IndexId.GetUid}})
	{{end -}}
	{{end -}}
	obx_model_entity_last_property_id(model, {{$entity.LastPropertyId.GetId}}, {{$entity.LastPropertyId.GetUid}});
	{{end}}
	obx_model_last_entity_id(model, {{.Model.LastEntityId.GetId}}, {{.Model.LastEntityId.GetUid}});
	{{- if .Model.LastIndexId}}
	obx_model_last_index_id(model, {{.Model.LastIndexId.GetId}}, {{.Model.LastIndexId.GetUid}});
	{{- end}}
	{{- if .Model.LastRelationId}}
	obx_model_last_relation_id(model, {{.Model.LastRelationId.GetId}}, {{.Model.LastRelationId.GetUid}});
	{{- end}}
	return model; // NOTE: the returned model will contain error information if an error occurred.
}

#ifdef __cplusplus
}
#endif
`))

ModelTemplate is used to generate the model initialization code TODO property relations, indexes

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL