Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the option for customs constexpr string constants #157

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ verify the build and binary from the command line.
- DataView for copy free data passing
- DateRef for copy free data passing with ownership
- Generating string names for C++ enums
- Support for custom constexpr strings such as "string_view" and "const char*"
- Bug fixes

## Using new features
Expand Down
37 changes: 24 additions & 13 deletions src/source/CppGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
var hppFwds = mutable.TreeSet[String]()
var cpp = mutable.TreeSet[String]()

def find(ty: TypeRef, forwardDeclareOnly: Boolean) { find(ty.resolved, forwardDeclareOnly) }
def find(tm: MExpr, forwardDeclareOnly: Boolean) {
tm.args.foreach((x) => find(x, forwardDeclareOnly))
find(tm.base, forwardDeclareOnly)
def find(ty: TypeRef, forwardDeclareOnly: Boolean, constants: Boolean) { find(ty.resolved, forwardDeclareOnly, constants) }
def find(tm: MExpr, forwardDeclareOnly: Boolean, constants: Boolean) {
tm.args.foreach((x) => find(x, forwardDeclareOnly, constants))
find(tm.base, forwardDeclareOnly, constants)
}
def find(m: Meta, forwardDeclareOnly : Boolean) = {
for(r <- marshal.hppReferences(m, name, forwardDeclareOnly)) r match {
def find(m: Meta, forwardDeclareOnly : Boolean, constants: Boolean) = {
for(r <- marshal.hppReferences(m, name, forwardDeclareOnly, constants)) r match {
case ImportRef(arg) => hpp.add("#include " + arg)
case DeclRef(decl, Some(spec.cppNamespace)) => hppFwds.add(decl)
case DeclRef(_, _) =>
Expand Down Expand Up @@ -129,26 +129,37 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
// Make sure we don't constexpr optionals as some might not support it
val canConstexpr = c.ty.resolved.base match {
case p: MPrimitive if c.ty.resolved.base != MOptional => true
// if we have defined a constexpr string
case MString => spec.cppStringConstexpr.isDefined
case _ => false
}
canConstexpr
}

// Gets the type of the constant to be used in the header file
// If the type is a string and we have defined constexpr string we use that one.
def generateHppConstantType(constexpr: Boolean, field_type: String) : String = {
val ft = if(constexpr && field_type == "std::string") spec.cppStringConstexpr.get else field_type
if (constexpr) s"constexpr ${ft}" else s"${ft} const"
}

def generateHppConstants(w: IndentWriter, consts: Seq[Const]) = {
for (c <- consts) {
// set value in header if can constexpr (only primitives)
var constexpr = shouldConstexpr(c)
var constValue = ";"
var field_type = marshal.fieldType(c.ty)
if (constexpr) {
constValue = c.value match {
case l: Long => " = " + l.toString + ";"
case d: Double if marshal.fieldType(c.ty) == "float" => " = " + d.toString + "f;"
case d: Double if field_type == "float" => " = " + d.toString + "f;"
case d: Double => " = " + d.toString + ";"
case b: Boolean => if (b) " = true;" else " = false;"
case s: String => " = " + s + ";"
case _ => ";"
}
}
val constFieldType = if (constexpr) s"constexpr ${marshal.fieldType(c.ty)}" else s"${marshal.fieldType(c.ty)} const"
val constFieldType = generateHppConstantType(constexpr, field_type)

// Write code to the header file
w.wl
Expand Down Expand Up @@ -197,8 +208,8 @@ class CppGenerator(spec: Spec) extends Generator(spec) {

override def generateRecord(origin: String, ident: Ident, doc: Doc, params: Seq[TypeParam], r: Record) {
val refs = new CppRefs(ident.name)
r.fields.foreach(f => refs.find(f.ty, false))
r.consts.foreach(c => refs.find(c.ty, false))
r.fields.foreach(f => refs.find(f.ty, false, false))
r.consts.foreach(c => refs.find(c.ty, false, true))
refs.hpp.add("#include <utility>") // Add for std::move

val self = marshal.typename(ident, r)
Expand Down Expand Up @@ -329,11 +340,11 @@ class CppGenerator(spec: Spec) extends Generator(spec) {
override def generateInterface(origin: String, ident: Ident, doc: Doc, typeParams: Seq[TypeParam], i: Interface) {
val refs = new CppRefs(ident.name)
i.methods.map(m => {
m.params.map(p => refs.find(p.ty, true))
m.ret.foreach((x)=>refs.find(x, true))
m.params.map(p => refs.find(p.ty, true, false))
m.ret.foreach((x)=>refs.find(x, true, false))
})
i.consts.map(c => {
refs.find(c.ty, true)
refs.find(c.ty, true, true)
})

val self = marshal.typename(ident, i)
Expand Down
7 changes: 5 additions & 2 deletions src/source/CppMarshal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,15 @@ class CppMarshal(spec: Spec) extends Marshal(spec) {
override def toCpp(tm: MExpr, expr: String): String = throw new AssertionError("cpp to cpp conversion")
override def fromCpp(tm: MExpr, expr: String): String = throw new AssertionError("cpp to cpp conversion")

def hppReferences(m: Meta, exclude: String, forwardDeclareOnly: Boolean): Seq[SymbolReference] = m match {
def hppReferences(m: Meta, exclude: String, forwardDeclareOnly: Boolean, constant: Boolean): Seq[SymbolReference] = m match {
case p: MPrimitive => p.idlName match {
case "i8" | "i16" | "i32" | "i64" => List(ImportRef("<cstdint>"))
case _ => List()
}
case MString => List(ImportRef("<string>"))
case MString =>
if( constant && spec.cppStringConstexpr.isDefined ) {
if( spec.cppStringConstexprHeader.isDefined ) List(ImportRef(spec.cppStringConstexprHeader.get)) else List()
} else List(ImportRef("<string>"))
case MDate => List(ImportRef("<chrono>"))
case MBinary => List(ImportRef("<vector>"), ImportRef("<cstdint>"))
case MOptional => List(ImportRef(spec.cppOptionalHeader))
Expand Down
8 changes: 8 additions & 0 deletions src/source/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ object Main {
var idlIncludePaths: List[String] = List("")
var cppOutFolder: Option[File] = None
var cppNamespace: String = ""
var cppStringConstexpr: Option[String] = None
var cppStringConstexprHeader: Option[String] = None
var cppIncludePrefix: String = ""
var cppExtendedRecordIncludePrefix: String = ""
var cppFileIdentStyle: IdentConverter = IdentStyle.underLower
Expand Down Expand Up @@ -154,6 +156,10 @@ object Main {
.text("The C++ base library's include path, relative to the C++ classes.")
opt[String]("cpp-namespace").valueName("...").foreach(x => cppNamespace = x)
.text("The namespace name to use for generated C++ classes.")
opt[String]("cpp-string-constexpr").valueName("<class>").foreach(x => cppStringConstexpr = Some(x))
.text("The type for string constants for generated C++ classes.")
opt[String]("cpp-string-constexpr-header").valueName("<header>>").foreach(x => cppStringConstexprHeader = Some(x))
.text("The header file to be included for string constants for generated C++ classes.")
opt[String]("cpp-ext").valueName("<ext>").foreach(cppExt = _)
.text("The filename extension for C++ files (default: \"cpp\").")
opt[String]("hpp-ext").valueName("<ext>").foreach(cppHeaderExt = _)
Expand Down Expand Up @@ -382,6 +388,8 @@ object Main {
cppIncludePrefix,
cppExtendedRecordIncludePrefix,
cppNamespace,
cppStringConstexpr,
cppStringConstexprHeader,
cppIdentStyle,
cppFileIdentStyle,
cppBaseLibIncludePrefix,
Expand Down
2 changes: 2 additions & 0 deletions src/source/generator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ package object generatorTools {
cppIncludePrefix: String,
cppExtendedRecordIncludePrefix: String,
cppNamespace: String,
cppStringConstexpr: Option[String],
cppStringConstexprHeader: Option[String],
cppIdentStyle: CppIdentStyle,
cppFileIdentStyle: IdentConverter,
cppBaseLibIncludePrefix: String,
Expand Down
Loading