Commit d74d3ae5 authored by Andrew Twyman's avatar Andrew Twyman

Standardize whitespace in code, with a repeatable script

parent 7dfc5b18
File mode changed from 100755 to 100644
...@@ -9,26 +9,26 @@ import java.util.logging.Logger; ...@@ -9,26 +9,26 @@ import java.util.logging.Logger;
import com.dropbox.djinni.NativeLibLoader; import com.dropbox.djinni.NativeLibLoader;
public class SortTest { public class SortTest {
private static SecureRandom random = new SecureRandom(); private static SecureRandom random = new SecureRandom();
private static final Logger log = private static final Logger log =
Logger.getLogger(SortTest.class.getName()); Logger.getLogger(SortTest.class.getName());
public static String randomString() { public static String randomString() {
return new BigInteger(130, random).toString(10).substring(0, 5); return new BigInteger(130, random).toString(10).substring(0, 5);
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
NativeLibLoader.loadLibs(); NativeLibLoader.loadLibs();
// Create some random strings to sort below // Create some random strings to sort below
ArrayList<String> strs = new ArrayList<String>(); ArrayList<String> strs = new ArrayList<String>();
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
strs.add(randomString()); strs.add(randomString());
} }
log.log(Level.INFO, "Input strings:\n" + String.join("\n", strs)); log.log(Level.INFO, "Input strings:\n" + String.join("\n", strs));
// Sort them! // Sort them!
ItemList sorted = SortItems.runSort(new ItemList(strs)); ItemList sorted = SortItems.runSort(new ItemList(strs));
log.log( log.log(
......
...@@ -26,7 +26,7 @@ import com.intellij.psi.TokenType; ...@@ -26,7 +26,7 @@ import com.intellij.psi.TokenType;
/** /**
* This class is a scanner generated by * This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3 * <a href="http://www.jflex.de/">JFlex</a> 1.4.3
* on 8/11/15 2:15 PM from the specification file * on 8/11/15 2:15 PM from the specification file
* <tt>/Users/jaetzold/src/idea/plugins/djinni/src/com/dropbox/djinni/ideaplugin/YamlLexer.flex</tt> * <tt>/Users/jaetzold/src/idea/plugins/djinni/src/com/dropbox/djinni/ideaplugin/YamlLexer.flex</tt>
...@@ -45,23 +45,23 @@ class YamlLexer implements FlexLexer { ...@@ -45,23 +45,23 @@ class YamlLexer implements FlexLexer {
* at the beginning of a line * at the beginning of a line
* l is of the form l = 2*k, k a non negative integer * l is of the form l = 2*k, k a non negative integer
*/ */
private static final int ZZ_LEXSTATE[] = { private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1 0, 0, 1, 1
}; };
/** /**
* Translates characters to character classes * Translates characters to character classes
*/ */
private static final String ZZ_CMAP_PACKED = private static final String ZZ_CMAP_PACKED =
"\11\0\1\3\1\1\1\0\1\6\1\2\22\0\1\5\1\7\1\0"+ "\11\0\1\3\1\1\1\0\1\6\1\2\22\0\1\5\1\7\1\0"+
"\1\7\26\0\1\10\2\0\1\10\36\0\1\4\uffa3\0"; "\1\7\26\0\1\10\2\0\1\10\36\0\1\4\uffa3\0";
/** /**
* Translates characters to character classes * Translates characters to character classes
*/ */
private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
/** /**
* Translates DFA states to action switch labels. * Translates DFA states to action switch labels.
*/ */
private static final int [] ZZ_ACTION = zzUnpackAction(); private static final int [] ZZ_ACTION = zzUnpackAction();
...@@ -90,7 +90,7 @@ class YamlLexer implements FlexLexer { ...@@ -90,7 +90,7 @@ class YamlLexer implements FlexLexer {
} }
/** /**
* Translates a state to a row index in the transition table * Translates a state to a row index in the transition table
*/ */
private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
...@@ -118,7 +118,7 @@ class YamlLexer implements FlexLexer { ...@@ -118,7 +118,7 @@ class YamlLexer implements FlexLexer {
return j; return j;
} }
/** /**
* The transition table of the DFA * The transition table of the DFA
*/ */
private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final int [] ZZ_TRANS = zzUnpackTrans();
...@@ -250,7 +250,7 @@ class YamlLexer implements FlexLexer { ...@@ -250,7 +250,7 @@ class YamlLexer implements FlexLexer {
} }
/** /**
* Unpacks the compressed character translation table. * Unpacks the compressed character translation table.
* *
* @param packed the packed character translation table * @param packed the packed character translation table
...@@ -399,7 +399,7 @@ class YamlLexer implements FlexLexer { ...@@ -399,7 +399,7 @@ class YamlLexer implements FlexLexer {
private void zzDoEOF() { private void zzDoEOF() {
if (!zzEOFDone) { if (!zzEOFDone) {
zzEOFDone = true; zzEOFDone = true;
} }
} }
...@@ -482,35 +482,35 @@ class YamlLexer implements FlexLexer { ...@@ -482,35 +482,35 @@ class YamlLexer implements FlexLexer {
zzMarkedPos = zzMarkedPosL; zzMarkedPos = zzMarkedPosL;
switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
case 6: case 6:
{ yybegin(WAITING_VALUE);return YamlTypes.SEPARATOR; { yybegin(WAITING_VALUE);return YamlTypes.SEPARATOR;
} }
case 9: break; case 9: break;
case 2: case 2:
{ yybegin(YYINITIAL); return YamlTypes.CRLF; { yybegin(YYINITIAL); return YamlTypes.CRLF;
} }
case 10: break; case 10: break;
case 5: case 5:
{ yybegin(YYINITIAL); return YamlTypes.COMMENT; { yybegin(YYINITIAL); return YamlTypes.COMMENT;
} }
case 11: break; case 11: break;
case 4: case 4:
{ return TokenType.BAD_CHARACTER; { return TokenType.BAD_CHARACTER;
} }
case 12: break; case 12: break;
case 7: case 7:
{ yybegin(YYINITIAL); return YamlTypes.VALUE; { yybegin(YYINITIAL); return YamlTypes.VALUE;
} }
case 13: break; case 13: break;
case 3: case 3:
{ yybegin(YYINITIAL); return TokenType.WHITE_SPACE; { yybegin(YYINITIAL); return TokenType.WHITE_SPACE;
} }
case 14: break; case 14: break;
case 8: case 8:
{ yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE; { yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE;
} }
case 15: break; case 15: break;
case 1: case 1:
{ yybegin(YYINITIAL); return YamlTypes.KEY; { yybegin(YYINITIAL); return YamlTypes.KEY;
} }
case 16: break; case 16: break;
......
...@@ -86,4 +86,4 @@ public class YamlParserDefinition implements ParserDefinition{ ...@@ -86,4 +86,4 @@ public class YamlParserDefinition implements ParserDefinition{
public PsiElement createElement(ASTNode node) { public PsiElement createElement(ASTNode node) {
return YamlTypes.Factory.createElement(node); return YamlTypes.Factory.createElement(node);
} }
} }
\ No newline at end of file
...@@ -23,7 +23,7 @@ import static com.dropbox.djinni.ideaplugin.psi.DjinniTypes.*; ...@@ -23,7 +23,7 @@ import static com.dropbox.djinni.ideaplugin.psi.DjinniTypes.*;
/** /**
* This class is a scanner generated by * This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3 * <a href="http://www.jflex.de/">JFlex</a> 1.4.3
* on 8/12/15 1:36 PM from the specification file * on 8/12/15 1:36 PM from the specification file
* <tt>/Users/jaetzold/src/idea/plugins/djinni/src/com/dropbox/djinni/ideaplugin/_DjinniLexer.flex</tt> * <tt>/Users/jaetzold/src/idea/plugins/djinni/src/com/dropbox/djinni/ideaplugin/_DjinniLexer.flex</tt>
...@@ -41,14 +41,14 @@ public class _DjinniLexer implements FlexLexer { ...@@ -41,14 +41,14 @@ public class _DjinniLexer implements FlexLexer {
* at the beginning of a line * at the beginning of a line
* l is of the form l = 2*k, k a non negative integer * l is of the form l = 2*k, k a non negative integer
*/ */
private static final int ZZ_LEXSTATE[] = { private static final int ZZ_LEXSTATE[] = {
0, 0 0, 0
}; };
/** /**
* Translates characters to character classes * Translates characters to character classes
*/ */
private static final String ZZ_CMAP_PACKED = private static final String ZZ_CMAP_PACKED =
"\11\0\1\1\1\2\1\3\1\1\1\1\22\0\1\1\1\0\1\7"+ "\11\0\1\1\1\2\1\3\1\1\1\1\22\0\1\1\1\0\1\7"+
"\1\4\3\0\1\5\1\27\1\30\1\0\1\22\1\21\1\10\1\12"+ "\1\4\3\0\1\5\1\27\1\30\1\0\1\22\1\21\1\10\1\12"+
"\1\0\12\11\1\17\1\20\1\25\1\16\1\26\1\0\1\31\32\15"+ "\1\0\12\11\1\17\1\20\1\25\1\16\1\26\1\0\1\31\32\15"+
...@@ -111,12 +111,12 @@ public class _DjinniLexer implements FlexLexer { ...@@ -111,12 +111,12 @@ public class _DjinniLexer implements FlexLexer {
"\32\13\13\0\131\13\3\0\6\13\2\0\6\13\2\0\6\13\2\0"+ "\32\13\13\0\131\13\3\0\6\13\2\0\6\13\2\0\6\13\2\0"+
"\3\13\43\0"; "\3\13\43\0";
/** /**
* Translates characters to character classes * Translates characters to character classes
*/ */
private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
/** /**
* Translates DFA states to action switch labels. * Translates DFA states to action switch labels.
*/ */
private static final int [] ZZ_ACTION = zzUnpackAction(); private static final int [] ZZ_ACTION = zzUnpackAction();
...@@ -148,7 +148,7 @@ public class _DjinniLexer implements FlexLexer { ...@@ -148,7 +148,7 @@ public class _DjinniLexer implements FlexLexer {
} }
/** /**
* Translates a state to a row index in the transition table * Translates a state to a row index in the transition table
*/ */
private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
...@@ -180,7 +180,7 @@ public class _DjinniLexer implements FlexLexer { ...@@ -180,7 +180,7 @@ public class _DjinniLexer implements FlexLexer {
return j; return j;
} }
/** /**
* The transition table of the DFA * The transition table of the DFA
*/ */
private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final int [] ZZ_TRANS = zzUnpackTrans();
...@@ -329,7 +329,7 @@ public class _DjinniLexer implements FlexLexer { ...@@ -329,7 +329,7 @@ public class _DjinniLexer implements FlexLexer {
} }
/** /**
* Unpacks the compressed character translation table. * Unpacks the compressed character translation table.
* *
* @param packed the packed character translation table * @param packed the packed character translation table
...@@ -549,99 +549,99 @@ public class _DjinniLexer implements FlexLexer { ...@@ -549,99 +549,99 @@ public class _DjinniLexer implements FlexLexer {
zzMarkedPos = zzMarkedPosL; zzMarkedPos = zzMarkedPosL;
switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
case 17: case 17:
{ return LEFT_PARAM_BRACE; { return LEFT_PARAM_BRACE;
} }
case 25: break; case 25: break;
case 14: case 14:
{ return RIGHT_BLOCK_BRACE; { return RIGHT_BLOCK_BRACE;
} }
case 26: break; case 26: break;
case 4: case 4:
{ return COMMENT; { return COMMENT;
} }
case 27: break; case 27: break;
case 22: case 22:
{ return MAP; { return MAP;
} }
case 28: break; case 28: break;
case 6: case 6:
{ return IDENTIFIER; { return IDENTIFIER;
} }
case 29: break; case 29: break;
case 24: case 24:
{ return OPTIONAL; { return OPTIONAL;
} }
case 30: break; case 30: break;
case 1: case 1:
{ return com.intellij.psi.TokenType.BAD_CHARACTER; { return com.intellij.psi.TokenType.BAD_CHARACTER;
} }
case 31: break; case 31: break;
case 12: case 12:
{ return PLUS; { return PLUS;
} }
case 32: break; case 32: break;
case 11: case 11:
{ return LIST_SEPARATOR; { return LIST_SEPARATOR;
} }
case 33: break; case 33: break;
case 9: case 9:
{ return COLON; { return COLON;
} }
case 34: break; case 34: break;
case 20: case 20:
{ return STRING_LITERAL; { return STRING_LITERAL;
} }
case 35: break; case 35: break;
case 13: case 13:
{ return LEFT_BLOCK_BRACE; { return LEFT_BLOCK_BRACE;
} }
case 36: break; case 36: break;
case 19: case 19:
{ return AT; { return AT;
} }
case 37: break; case 37: break;
case 21: case 21:
{ return SET; { return SET;
} }
case 38: break; case 38: break;
case 23: case 23:
{ return LIST; { return LIST;
} }
case 39: break; case 39: break;
case 10: case 10:
{ return SEMICOLON; { return SEMICOLON;
} }
case 40: break; case 40: break;
case 18: case 18:
{ return RIGHT_PARAM_BRACE; { return RIGHT_PARAM_BRACE;
} }
case 41: break; case 41: break;
case 15: case 15:
{ return LEFT_GENERICS_BRACE; { return LEFT_GENERICS_BRACE;
} }
case 42: break; case 42: break;
case 16: case 16:
{ return RIGHT_GENERICS_BRACE; { return RIGHT_GENERICS_BRACE;
} }
case 43: break; case 43: break;
case 8: case 8:
{ return EQ; { return EQ;
} }
case 44: break; case 44: break;
case 3: case 3:
{ return SPACE; { return SPACE;
} }
case 45: break; case 45: break;
case 7: case 7:
{ return TEXT; { return TEXT;
} }
case 46: break; case 46: break;
case 5: case 5:
{ return NUMBER_LITERAL; { return NUMBER_LITERAL;
} }
case 47: break; case 47: break;
case 2: case 2:
{ return com.intellij.psi.TokenType.WHITE_SPACE; { return com.intellij.psi.TokenType.WHITE_SPACE;
} }
case 48: break; case 48: break;
......
...@@ -38,7 +38,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -38,7 +38,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
def find(ty: TypeRef) { find(ty.resolved) } def find(ty: TypeRef) { find(ty.resolved) }
def find(tm: MExpr) { def find(tm: MExpr) {
tm.args.foreach(find) tm.args.foreach(find)
find(tm.base) find(tm.base)
} }
def find(m: Meta) = for(r <- objcppMarshal.references(m)) r match { def find(m: Meta) = for(r <- objcppMarshal.references(m)) r match {
case ImportRef(arg) => body.add("#import " + arg) case ImportRef(arg) => body.add("#import " + arg)
...@@ -78,7 +78,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -78,7 +78,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
case Some(nnHdr) => refs.privHeader.add("#include " + nnHdr) case Some(nnHdr) => refs.privHeader.add("#include " + nnHdr)
case _ => case _ =>
} }
def writeObjcFuncDecl(method: Interface.Method, w: IndentWriter) { def writeObjcFuncDecl(method: Interface.Method, w: IndentWriter) {
val label = if (method.static) "+" else "-" val label = if (method.static) "+" else "-"
val ret = objcMarshal.fqReturnType(method.ret) val ret = objcMarshal.fqReturnType(method.ret)
...@@ -264,7 +264,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -264,7 +264,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
} }
w.wl w.wl
val fromCppFunc = if (spec.cppNnType.isEmpty) "fromCpp(const CppType& cpp)" val fromCppFunc = if (spec.cppNnType.isEmpty) "fromCpp(const CppType& cpp)"
else "fromCppOpt(const CppOptType& cpp)" else "fromCppOpt(const CppOptType& cpp)"
w.wl(s"auto $helperClass::$fromCppFunc -> ObjcType").braced { w.wl(s"auto $helperClass::$fromCppFunc -> ObjcType").braced {
// Handle null // Handle null
w.w("if (!cpp)").braced { w.w("if (!cpp)").braced {
...@@ -309,7 +309,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) { ...@@ -309,7 +309,7 @@ class ObjcppGenerator(spec: Spec) extends Generator(spec) {
refs.privHeader.add("!#import " + q(spec.objcppIncludeObjcPrefix + (if(r.ext.objc) "../" else "") + headerName(ident))) refs.privHeader.add("!#import " + q(spec.objcppIncludeObjcPrefix + (if(r.ext.objc) "../" else "") + headerName(ident)))
refs.privHeader.add("!#include " + q(spec.objcppIncludeCppPrefix + (if(r.ext.cpp) "../" else "") + spec.cppFileIdentStyle(ident) + "." + spec.cppHeaderExt)) refs.privHeader.add("!#include " + q(spec.objcppIncludeCppPrefix + (if(r.ext.cpp) "../" else "") + spec.cppFileIdentStyle(ident) + "." + spec.cppHeaderExt))
refs.body.add("#include <cassert>") refs.body.add("#include <cassert>")
refs.body.add("!#import " + q(spec.objcppIncludePrefix + objcppMarshal.privateHeaderName(objcName))) refs.body.add("!#import " + q(spec.objcppIncludePrefix + objcppMarshal.privateHeaderName(objcName)))
......
...@@ -18,7 +18,7 @@ class YamlGenerator(spec: Spec) extends Generator(spec) { ...@@ -18,7 +18,7 @@ class YamlGenerator(spec: Spec) extends Generator(spec) {
val jniMarshal = new JNIMarshal(spec) val jniMarshal = new JNIMarshal(spec)
case class QuotedString(str: String) // For anything that migt require escaping case class QuotedString(str: String) // For anything that migt require escaping
private def writeYamlFile(name: String, origin: String, f: IndentWriter => Unit): Unit = { private def writeYamlFile(name: String, origin: String, f: IndentWriter => Unit): Unit = {
createFile(spec.yamlOutFolder.get, name, out => new IndentWriter(out, " "), w => { createFile(spec.yamlOutFolder.get, name, out => new IndentWriter(out, " "), w => {
w.wl("# AUTOGENERATED FILE - DO NOT MODIFY!") w.wl("# AUTOGENERATED FILE - DO NOT MODIFY!")
...@@ -40,59 +40,59 @@ class YamlGenerator(spec: Spec) extends Generator(spec) { ...@@ -40,59 +40,59 @@ class YamlGenerator(spec: Spec) extends Generator(spec) {
} }
private def writeYamlFile(ident: String, origin: String, td: InternTypeDecl): Unit = private def writeYamlFile(ident: String, origin: String, td: InternTypeDecl): Unit =
writeYamlFile(spec.yamlPrefix + ident + ".yaml", origin, w => { writeYamlFile(spec.yamlPrefix + ident + ".yaml", origin, w => {
write(w, td) write(w, td)
}) })
private def write(w: IndentWriter, td: TypeDecl) { private def write(w: IndentWriter, td: TypeDecl) {
write(w, preamble(td)) write(w, preamble(td))
w.wl("cpp:").nested { write(w, cpp(td)) } w.wl("cpp:").nested { write(w, cpp(td)) }
w.wl("objc:").nested { write(w, objc(td)) } w.wl("objc:").nested { write(w, objc(td)) }
w.wl("objcpp:").nested { write(w, objcpp(td)) } w.wl("objcpp:").nested { write(w, objcpp(td)) }
w.wl("java:").nested { write(w, java(td)) } w.wl("java:").nested { write(w, java(td)) }
w.wl("jni:").nested { write(w, jni(td)) } w.wl("jni:").nested { write(w, jni(td)) }
} }
private def write(w: IndentWriter, m: Map[String, Any]) { private def write(w: IndentWriter, m: Map[String, Any]) {
for((k, v) <- m) { for((k, v) <- m) {
w.w(k + ": ") w.w(k + ": ")
v match { v match {
case s: String => write(w, s) case s: String => write(w, s)
case s: QuotedString => write(w, s) case s: QuotedString => write(w, s)
case m: Map[_, _] => w.wl.nested { write(w, m.asInstanceOf[Map[String, Any]]) } case m: Map[_, _] => w.wl.nested { write(w, m.asInstanceOf[Map[String, Any]]) }
case s: Seq[_] => write(w, s) case s: Seq[_] => write(w, s)
case b: Boolean => write(w, b) case b: Boolean => write(w, b)
case _ => throw new AssertionError("unexpected map value") case _ => throw new AssertionError("unexpected map value")
} }
} }
} }
private def write(w: IndentWriter, s: Seq[Any]) { private def write(w: IndentWriter, s: Seq[Any]) {
// The only arrays we have are small enough to use flow notation // The only arrays we have are small enough to use flow notation
w.wl(s.mkString("[", ",", "]")) w.wl(s.mkString("[", ",", "]"))
} }
private def write(w: IndentWriter, b: Boolean) { private def write(w: IndentWriter, b: Boolean) {
w.wl(if(b) "true" else "false") w.wl(if(b) "true" else "false")
} }
private def write(w: IndentWriter, s: String) { private def write(w: IndentWriter, s: String) {
if(s.isEmpty) w.wl(q("")) else w.wl(s) if(s.isEmpty) w.wl(q("")) else w.wl(s)
} }
private def write(w: IndentWriter, s: QuotedString) { private def write(w: IndentWriter, s: QuotedString) {
if(s.str.isEmpty) w.wl(q("")) else w.wl("'" + s.str.replaceAllLiterally("'", "''") + "'") if(s.str.isEmpty) w.wl(q("")) else w.wl("'" + s.str.replaceAllLiterally("'", "''") + "'")
} }
private def preamble(td: TypeDecl) = Map[String, Any]( private def preamble(td: TypeDecl) = Map[String, Any](
"name" -> (spec.yamlPrefix + td.ident.name), "name" -> (spec.yamlPrefix + td.ident.name),
"typedef" -> QuotedString(typeDef(td)), "typedef" -> QuotedString(typeDef(td)),
"params" -> td.params.collect { case p: TypeParam => p.ident.name }, "params" -> td.params.collect { case p: TypeParam => p.ident.name },
"prefix" -> spec.yamlPrefix "prefix" -> spec.yamlPrefix
) )
private def typeDef(td: TypeDecl) = { private def typeDef(td: TypeDecl) = {
def ext(e: Ext): String = (if(e.cpp) " +c" else "") + (if(e.objc) " +o" else "") + (if(e.java) " +j" else "") def ext(e: Ext): String = (if(e.cpp) " +c" else "") + (if(e.objc) " +o" else "") + (if(e.java) " +j" else "")
def deriving(r: Record) = { def deriving(r: Record) = {
if(r.derivingTypes.isEmpty) { if(r.derivingTypes.isEmpty) {
"" ""
...@@ -103,11 +103,11 @@ class YamlGenerator(spec: Spec) extends Generator(spec) { ...@@ -103,11 +103,11 @@ class YamlGenerator(spec: Spec) extends Generator(spec) {
}.mkString(" deriving(", ", ", ")") }.mkString(" deriving(", ", ", ")")
} }
} }
td.body match { td.body match {
case i: Interface => "interface" + ext(i.ext) case i: Interface => "interface" + ext(i.ext)
case r: Record => "record" + ext(r.ext) + deriving(r) case r: Record => "record" + ext(r.ext) + deriving(r)
case e: Enum => "enum" case e: Enum => "enum"
} }
} }
private def cpp(td: TypeDecl) = Map[String, Any]( private def cpp(td: TypeDecl) = Map[String, Any](
...@@ -138,8 +138,8 @@ class YamlGenerator(spec: Spec) extends Generator(spec) { ...@@ -138,8 +138,8 @@ class YamlGenerator(spec: Spec) extends Generator(spec) {
) )
private def jni(td: TypeDecl) = Map[String, Any]( private def jni(td: TypeDecl) = Map[String, Any](
"translator" -> QuotedString(jniMarshal.helperName(mexpr(td))), "translator" -> QuotedString(jniMarshal.helperName(mexpr(td))),
"header" -> QuotedString(jniMarshal.include(td.ident)), "header" -> QuotedString(jniMarshal.include(td.ident)),
"typename" -> jniMarshal.fqParamType(mexpr(td)), "typename" -> jniMarshal.fqParamType(mexpr(td)),
"typeSignature" -> QuotedString(jniMarshal.fqTypename(td.ident, td.body)) "typeSignature" -> QuotedString(jniMarshal.fqTypename(td.ident, td.body))
) )
...@@ -148,44 +148,44 @@ class YamlGenerator(spec: Spec) extends Generator(spec) { ...@@ -148,44 +148,44 @@ class YamlGenerator(spec: Spec) extends Generator(spec) {
private def mexpr(td: TypeDecl) = MExpr(meta(td), List()) private def mexpr(td: TypeDecl) = MExpr(meta(td), List())
private def meta(td: TypeDecl) = { private def meta(td: TypeDecl) = {
val defType = td.body match { val defType = td.body match {
case i: Interface => DInterface case i: Interface => DInterface
case r: Record => DRecord case r: Record => DRecord
case e: Enum => DEnum case e: Enum => DEnum
} }
MDef(td.ident, 0, defType, td.body) MDef(td.ident, 0, defType, td.body)
} }
override def generate(idl: Seq[TypeDecl]) { override def generate(idl: Seq[TypeDecl]) {
val internOnly = idl.collect { case itd: InternTypeDecl => itd }.sortWith(_.ident.name < _.ident.name) val internOnly = idl.collect { case itd: InternTypeDecl => itd }.sortWith(_.ident.name < _.ident.name)
if(spec.yamlOutFile.isDefined) { if(spec.yamlOutFile.isDefined) {
writeYamlFile(internOnly) writeYamlFile(internOnly)
} else { } else {
for(td <- internOnly) { for(td <- internOnly) {
writeYamlFile(td.ident, td.origin, td) writeYamlFile(td.ident, td.origin, td)
} }
} }
} }
override def generateEnum(origin: String, ident: Ident, doc: Doc, e: Enum) { override def generateEnum(origin: String, ident: Ident, doc: Doc, e: Enum) {
// unused // unused
} }
override def generateInterface(origin: String, ident: Ident, doc: Doc, typeParams: Seq[TypeParam], i: Interface) { override def generateInterface(origin: String, ident: Ident, doc: Doc, typeParams: Seq[TypeParam], i: Interface) {
// unused // unused
} }
override def generateRecord(origin: String, ident: Ident, doc: Doc, params: Seq[TypeParam], r: Record) { override def generateRecord(origin: String, ident: Ident, doc: Doc, params: Seq[TypeParam], r: Record) {
// unused // unused
} }
} }
object YamlGenerator { object YamlGenerator {
def metaFromYaml(td: ExternTypeDecl) = MExtern( def metaFromYaml(td: ExternTypeDecl) = MExtern(
td.ident.name.stripPrefix(td.properties("prefix").toString), // Make sure the generator uses this type with its original name for all intents and purposes td.ident.name.stripPrefix(td.properties("prefix").toString), // Make sure the generator uses this type with its original name for all intents and purposes
td.params.size, td.params.size,
defType(td), defType(td),
td.body, td.body,
MExtern.Cpp( MExtern.Cpp(
nested(td, "cpp")("typename").toString, nested(td, "cpp")("typename").toString,
nested(td, "cpp")("header").toString, nested(td, "cpp")("header").toString,
...@@ -213,12 +213,12 @@ object YamlGenerator { ...@@ -213,12 +213,12 @@ object YamlGenerator {
) )
private def nested(td: ExternTypeDecl, key: String) = { private def nested(td: ExternTypeDecl, key: String) = {
td.properties.get(key).collect { case m: JMap[_, _] => m.collect { case (k: String, v: Any) => (k, v) } } getOrElse(Map[String, Any]()) td.properties.get(key).collect { case m: JMap[_, _] => m.collect { case (k: String, v: Any) => (k, v) } } getOrElse(Map[String, Any]())
} }
private def defType(td: ExternTypeDecl) = td.body match { private def defType(td: ExternTypeDecl) = td.body match {
case i: Interface => DInterface case i: Interface => DInterface
case r: Record => DRecord case r: Record => DRecord
case e: Enum => DEnum case e: Enum => DEnum
} }
} }
...@@ -248,7 +248,7 @@ abstract class Generator(spec: Spec) ...@@ -248,7 +248,7 @@ abstract class Generator(spec: Spec)
} }
protected def createFile(folder: File, fileName: String, f: IndentWriter => Unit): Unit = createFile(folder, fileName, out => new IndentWriter(out), f) protected def createFile(folder: File, fileName: String, f: IndentWriter => Unit): Unit = createFile(folder, fileName, out => new IndentWriter(out), f)
implicit def identToString(ident: Ident): String = ident.name implicit def identToString(ident: Ident): String = ident.name
val idCpp = spec.cppIdentStyle val idCpp = spec.cppIdentStyle
val idJava = spec.javaIdentStyle val idJava = spec.javaIdentStyle
......
// //
// Copyright 2015 Dropbox, Inc. // Copyright 2015 Dropbox, Inc.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
...@@ -45,33 +45,33 @@ import java.util.stream.Stream; ...@@ -45,33 +45,33 @@ import java.util.stream.Stream;
* <code> * <code>
* NativeLibLoader.loadLibs() * NativeLibLoader.loadLibs()
* </code> * </code>
* to load the libraries (e.g. in your main() or a class static initializer). * to load the libraries (e.g. in your main() or a class static initializer).
*/ */
public class NativeLibLoader { public class NativeLibLoader {
/** /**
* Canonical directory in a jar containing (djinni-adapted) native libraries * Canonical directory in a jar containing (djinni-adapted) native libraries
*/ */
public static final String djinniNativeLibsJarPath = public static final String djinniNativeLibsJarPath =
"resources/djinni_native_libs"; "resources/djinni_native_libs";
/** /**
* Load native libraries with djinni support from the (comma-separated) * Load native libraries with djinni support from the (comma-separated)
* path(s) provided in this system property * path(s) provided in this system property
*/ */
public static final String djinniNativeLibsSysProp = public static final String djinniNativeLibsSysProp =
"djinni.native_libs_dirs"; "djinni.native_libs_dirs";
private static final Logger log = private static final Logger log =
Logger.getLogger(NativeLibLoader.class.getName()); Logger.getLogger(NativeLibLoader.class.getName());
private NativeLibLoader() { } private NativeLibLoader() { }
// Load native libs from canonical locations // Load native libs from canonical locations
public static void loadLibs() throws URISyntaxException, IOException { public static void loadLibs() throws URISyntaxException, IOException {
// Try to load from Jar // Try to load from Jar
loadLibsFromJarPath(djinniNativeLibsJarPath); loadLibsFromJarPath(djinniNativeLibsJarPath);
// Try to load from system // Try to load from system
String localPaths = System.getProperty(djinniNativeLibsSysProp); String localPaths = System.getProperty(djinniNativeLibsSysProp);
if (localPaths != null) { if (localPaths != null) {
...@@ -81,7 +81,7 @@ public class NativeLibLoader { ...@@ -81,7 +81,7 @@ public class NativeLibLoader {
} }
} }
} }
// Load native lib(s) from the given `localPath` - a file or directory // Load native lib(s) from the given `localPath` - a file or directory
public static void loadLibsFromLocalPath(Path localPath) throws IOException { public static void loadLibsFromLocalPath(Path localPath) throws IOException {
File localFile = localPath.toFile(); File localFile = localPath.toFile();
...@@ -100,7 +100,7 @@ public class NativeLibLoader { ...@@ -100,7 +100,7 @@ public class NativeLibLoader {
loadLibrary(localFile.getAbsolutePath()); loadLibrary(localFile.getAbsolutePath());
} }
} }
// Load a directory of libs from a jar resource path // Load a directory of libs from a jar resource path
public static void loadLibsFromJarPath(String jarPath) public static void loadLibsFromJarPath(String jarPath)
throws URISyntaxException, IOException { throws URISyntaxException, IOException {
...@@ -111,12 +111,12 @@ public class NativeLibLoader { ...@@ -111,12 +111,12 @@ public class NativeLibLoader {
.getClassLoader() .getClassLoader()
.getResource(djinniNativeLibsJarPath); .getResource(djinniNativeLibsJarPath);
if (libsURL == null) { return; } if (libsURL == null) { return; }
// Are we actually referencing a jar path? // Are we actually referencing a jar path?
if (!libsURL.toURI().getScheme().equals("jar")) { return; } if (!libsURL.toURI().getScheme().equals("jar")) { return; }
log.log(Level.FINE, "Loading libs from jar path " + jarPath); log.log(Level.FINE, "Loading libs from jar path " + jarPath);
// Walk the directory and load libs // Walk the directory and load libs
FileSystem fs = FileSystem fs =
FileSystems.newFileSystem(libsURL.toURI(), Collections.emptyMap()); FileSystems.newFileSystem(libsURL.toURI(), Collections.emptyMap());
...@@ -124,10 +124,10 @@ public class NativeLibLoader { ...@@ -124,10 +124,10 @@ public class NativeLibLoader {
for (Path p : (Iterable<Path>)Files.walk(myPath, 1)::iterator) { for (Path p : (Iterable<Path>)Files.walk(myPath, 1)::iterator) {
loadLibFromJarPath(p); loadLibFromJarPath(p);
} }
fs.close(); fs.close();
} }
// Load a single native lib from a jar resource with path `libPath` // Load a single native lib from a jar resource with path `libPath`
public static void loadLibFromJarPath(Path libPath) throws IOException { public static void loadLibFromJarPath(Path libPath) throws IOException {
...@@ -137,7 +137,7 @@ public class NativeLibLoader { ...@@ -137,7 +137,7 @@ public class NativeLibLoader {
InputStream libIn = InputStream libIn =
NativeLibLoader.class.getResourceAsStream(libPath.toString()); NativeLibLoader.class.getResourceAsStream(libPath.toString());
if (libIn == null) { return; } // Invalid `libPath` if (libIn == null) { return; } // Invalid `libPath`
// Name the tempfile // Name the tempfile
String libName = libPath.getName(libPath.getNameCount() - 1).toString(); String libName = libPath.getName(libPath.getNameCount() - 1).toString();
// Name the tempfile after the lib to ease debugging // Name the tempfile after the lib to ease debugging
...@@ -146,27 +146,27 @@ public class NativeLibLoader { ...@@ -146,27 +146,27 @@ public class NativeLibLoader {
if (extPos > 0) { suffix = libName.substring(extPos + 1); } if (extPos > 0) { suffix = libName.substring(extPos + 1); }
// Try to suffix the tempfile with the lib's suffix so that other // Try to suffix the tempfile with the lib's suffix so that other
// tools (e.g. profilers) identify the file correctly // tools (e.g. profilers) identify the file correctly
File tempLib = File.createTempFile(libName, suffix); File tempLib = File.createTempFile(libName, suffix);
tempLib.deleteOnExit(); tempLib.deleteOnExit();
log.log( log.log(
Level.FINE, Level.FINE,
"Copying jar lib " + libPath + " to " + tempLib.getAbsolutePath()); "Copying jar lib " + libPath + " to " + tempLib.getAbsolutePath());
try { try {
Files.copy(libIn, tempLib.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.copy(libIn, tempLib.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (SecurityException e) { } catch (SecurityException e) {
throw new RuntimeException( throw new RuntimeException(
"SecurityException while trying to create tempfile: " + "SecurityException while trying to create tempfile: " +
e.getMessage() + "\n\n If you cannot grant this process " + e.getMessage() + "\n\n If you cannot grant this process " +
"permissions to create temporary files, you need to install " + "permissions to create temporary files, you need to install " +
"the native libraries manually and provide the installation " + "the native libraries manually and provide the installation " +
"path(s) using the system property " + djinniNativeLibsSysProp); "path(s) using the system property " + djinniNativeLibsSysProp);
} }
loadLibrary(tempLib.getAbsolutePath()); loadLibrary(tempLib.getAbsolutePath());
} }
private static void loadLibrary(String abspath) { private static void loadLibrary(String abspath) {
System.load(abspath); System.load(abspath);
log.log(Level.INFO, "Loaded " + abspath); log.log(Level.INFO, "Loaded " + abspath);
......
...@@ -27,166 +27,166 @@ ...@@ -27,166 +27,166 @@
namespace djinni namespace djinni
{ {
template<class Self, class CppT, class JniT> template<class Self, class CppT, class JniT>
class Primitive class Primitive
{ {
public: public:
using CppType = CppT; using CppType = CppT;
using JniType = JniT; using JniType = JniT;
static CppType toCpp(JNIEnv* /*jniEnv*/, JniType j) noexcept { return static_cast<CppType>(j); } static CppType toCpp(JNIEnv* /*jniEnv*/, JniType j) noexcept { return static_cast<CppType>(j); }
static JniType fromCpp(JNIEnv* /*jniEnv*/, CppType c) noexcept { return static_cast<JniType>(c); } static JniType fromCpp(JNIEnv* /*jniEnv*/, CppType c) noexcept { return static_cast<JniType>(c); }
struct Boxed struct Boxed
{ {
using JniType = jobject; using JniType = jobject;
static CppType toCpp(JNIEnv* jniEnv, JniType j) static CppType toCpp(JNIEnv* jniEnv, JniType j)
{ {
assert(j != nullptr); assert(j != nullptr);
const auto& data = JniClass<Self>::get(); const auto& data = JniClass<Self>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get())); assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto ret = Primitive::toCpp(jniEnv, Self::unbox(jniEnv, data.method_unbox, j)); auto ret = Primitive::toCpp(jniEnv, Self::unbox(jniEnv, data.method_unbox, j));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return ret; return ret;
} }
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, CppType c) static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, CppType c)
{ {
const auto& data = JniClass<Self>::get(); const auto& data = JniClass<Self>::get();
auto ret = jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_box, Primitive::fromCpp(jniEnv, c)); auto ret = jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_box, Primitive::fromCpp(jniEnv, c));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return {jniEnv, ret}; return {jniEnv, ret};
} }
}; };
protected: protected:
Primitive(const char* javaClassSpec, Primitive(const char* javaClassSpec,
const char* staticBoxMethod, const char* staticBoxMethod,
const char* staticBoxMethodSignature, const char* staticBoxMethodSignature,
const char* unboxMethod, const char* unboxMethod,
const char* unboxMethodSignature) const char* unboxMethodSignature)
: clazz(jniFindClass(javaClassSpec)) : clazz(jniFindClass(javaClassSpec))
, method_box(jniGetStaticMethodID(clazz.get(), staticBoxMethod, staticBoxMethodSignature)) , method_box(jniGetStaticMethodID(clazz.get(), staticBoxMethod, staticBoxMethodSignature))
, method_unbox(jniGetMethodID(clazz.get(), unboxMethod, unboxMethodSignature)) , method_unbox(jniGetMethodID(clazz.get(), unboxMethod, unboxMethodSignature))
{} {}
private: private:
const GlobalRef<jclass> clazz; const GlobalRef<jclass> clazz;
const jmethodID method_box; const jmethodID method_box;
const jmethodID method_unbox; const jmethodID method_unbox;
}; };
class Bool : public Primitive<Bool, bool, jboolean> class Bool : public Primitive<Bool, bool, jboolean>
{ {
Bool() : Primitive("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", "booleanValue", "()Z") {} Bool() : Primitive("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", "booleanValue", "()Z") {}
friend JniClass<Bool>; friend JniClass<Bool>;
friend Primitive<Bool, bool, jboolean>; friend Primitive<Bool, bool, jboolean>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
auto result = jniEnv->CallBooleanMethod(j, method); auto result = jniEnv->CallBooleanMethod(j, method);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return result; return result;
} }
}; };
class I8 : public Primitive<I8, int8_t, jbyte> class I8 : public Primitive<I8, int8_t, jbyte>
{ {
I8() : Primitive("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", "byteValue", "()B") {} I8() : Primitive("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", "byteValue", "()B") {}
friend JniClass<I8>; friend JniClass<I8>;
friend Primitive<I8, int8_t, jbyte>; friend Primitive<I8, int8_t, jbyte>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
auto result = jniEnv->CallByteMethod(j, method); auto result = jniEnv->CallByteMethod(j, method);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return result; return result;
} }
}; };
class I16 : public Primitive<I16, int16_t, jshort> class I16 : public Primitive<I16, int16_t, jshort>
{ {
I16() : Primitive("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", "shortValue", "()S") {} I16() : Primitive("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", "shortValue", "()S") {}
friend JniClass<I16>; friend JniClass<I16>;
friend Primitive<I16, int16_t, jshort>; friend Primitive<I16, int16_t, jshort>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
auto result = jniEnv->CallShortMethod(j, method); auto result = jniEnv->CallShortMethod(j, method);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return result; return result;
} }
}; };
class I32 : public Primitive<I32, int32_t, jint> class I32 : public Primitive<I32, int32_t, jint>
{ {
I32() : Primitive("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", "intValue", "()I") {} I32() : Primitive("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", "intValue", "()I") {}
friend JniClass<I32>; friend JniClass<I32>;
friend Primitive<I32, int32_t, jint>; friend Primitive<I32, int32_t, jint>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
auto result = jniEnv->CallIntMethod(j, method); auto result = jniEnv->CallIntMethod(j, method);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return result; return result;
} }
}; };
class I64 : public Primitive<I64, int64_t, jlong> class I64 : public Primitive<I64, int64_t, jlong>
{ {
I64() : Primitive("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", "longValue", "()J") {} I64() : Primitive("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", "longValue", "()J") {}
friend JniClass<I64>; friend JniClass<I64>;
friend Primitive<I64, int64_t, jlong>; friend Primitive<I64, int64_t, jlong>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
auto result = jniEnv->CallLongMethod(j, method); auto result = jniEnv->CallLongMethod(j, method);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return result; return result;
} }
}; };
class F32 : public Primitive<F32, float, jfloat> class F32 : public Primitive<F32, float, jfloat>
{ {
F32() : Primitive("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", "floatValue", "()F") {} F32() : Primitive("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", "floatValue", "()F") {}
friend JniClass<F32>; friend JniClass<F32>;
friend Primitive<F32, float, jfloat>; friend Primitive<F32, float, jfloat>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
auto result = jniEnv->CallFloatMethod(j, method); auto result = jniEnv->CallFloatMethod(j, method);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return result; return result;
} }
}; };
class F64 : public Primitive<F64, double, jdouble> class F64 : public Primitive<F64, double, jdouble>
{ {
F64() : Primitive("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", "doubleValue", "()D") {} F64() : Primitive("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", "doubleValue", "()D") {}
friend JniClass<F64>; friend JniClass<F64>;
friend Primitive<F64, double, jdouble>; friend Primitive<F64, double, jdouble>;
static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
auto result = jniEnv->CallDoubleMethod(j, method); auto result = jniEnv->CallDoubleMethod(j, method);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return result; return result;
} }
}; };
struct String struct String
{ {
using CppType = std::string; using CppType = std::string;
using JniType = jstring; using JniType = jstring;
using Boxed = String; using Boxed = String;
static CppType toCpp(JNIEnv* jniEnv, JniType j) static CppType toCpp(JNIEnv* jniEnv, JniType j)
{ {
assert(j != nullptr); assert(j != nullptr);
return jniUTF8FromString(jniEnv, j); return jniUTF8FromString(jniEnv, j);
} }
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{ {
return {jniEnv, jniStringFromUTF8(jniEnv, c.c_str())}; return {jniEnv, jniStringFromUTF8(jniEnv, c.c_str())};
} }
}; };
struct Binary struct Binary
{ {
using CppType = std::vector<uint8_t>; using CppType = std::vector<uint8_t>;
using JniType = jbyteArray; using JniType = jbyteArray;
using Boxed = Binary; using Boxed = Binary;
static CppType toCpp(JNIEnv* jniEnv, JniType j) static CppType toCpp(JNIEnv* jniEnv, JniType j)
{ {
assert(j != nullptr); assert(j != nullptr);
std::vector<uint8_t> ret; std::vector<uint8_t> ret;
...@@ -220,63 +220,63 @@ namespace djinni ...@@ -220,63 +220,63 @@ namespace djinni
} }
return ret; return ret;
} }
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{ {
assert(c.size() <= std::numeric_limits<jsize>::max()); assert(c.size() <= std::numeric_limits<jsize>::max());
auto j = LocalRef<jbyteArray>(jniEnv, jniEnv->NewByteArray(static_cast<jsize>(c.size()))); auto j = LocalRef<jbyteArray>(jniEnv, jniEnv->NewByteArray(static_cast<jsize>(c.size())));
jniExceptionCheck(jniEnv);
// Using .data() on an empty vector is UB
if(!c.empty())
{
jniEnv->SetByteArrayRegion(j.get(), 0, c.size(), reinterpret_cast<const jbyte*>(c.data()));
}
return j;
}
};
struct Date
{
using CppType = std::chrono::system_clock::time_point;
using JniType = jobject;
using Boxed = Date;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
assert(j != nullptr);
const auto & data = JniClass<Date>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto time_millis = jniEnv->CallLongMethod(j, data.method_get_time);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return POSIX_EPOCH + std::chrono::milliseconds{time_millis}; // Using .data() on an empty vector is UB
} if(!c.empty())
{
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) jniEnv->SetByteArrayRegion(j.get(), 0, c.size(), reinterpret_cast<const jbyte*>(c.data()));
{ }
static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0); return j;
const auto & data = JniClass<Date>::get(); }
const auto cpp_millis = std::chrono::duration_cast<std::chrono::milliseconds>(c - POSIX_EPOCH); };
const jlong millis = static_cast<jlong>(cpp_millis.count());
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, millis)); struct Date
jniExceptionCheck(jniEnv); {
return j; using CppType = std::chrono::system_clock::time_point;
} using JniType = jobject;
private: using Boxed = Date;
Date() = default;
friend ::djinni::JniClass<Date>; static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/Date") }; static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(J)V") }; assert(j != nullptr);
const jmethodID method_get_time { jniGetMethodID(clazz.get(), "getTime", "()J") }; const auto & data = JniClass<Date>::get();
}; assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto time_millis = jniEnv->CallLongMethod(j, data.method_get_time);
template <template <class> class OptionalType, class T> jniExceptionCheck(jniEnv);
struct Optional return POSIX_EPOCH + std::chrono::milliseconds{time_millis};
{ }
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
const auto & data = JniClass<Date>::get();
const auto cpp_millis = std::chrono::duration_cast<std::chrono::milliseconds>(c - POSIX_EPOCH);
const jlong millis = static_cast<jlong>(cpp_millis.count());
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, millis));
jniExceptionCheck(jniEnv);
return j;
}
private:
Date() = default;
friend ::djinni::JniClass<Date>;
const GlobalRef<jclass> clazz { jniFindClass("java/util/Date") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(J)V") };
const jmethodID method_get_time { jniGetMethodID(clazz.get(), "getTime", "()J") };
};
template <template <class> class OptionalType, class T>
struct Optional
{
// SFINAE helper: if C::CppOptType exists, opt_type<T>(nullptr) will return // SFINAE helper: if C::CppOptType exists, opt_type<T>(nullptr) will return
// that type. If not, it returns OptionalType<C::CppType>. This is necessary // that type. If not, it returns OptionalType<C::CppType>. This is necessary
// because we special-case optional interfaces to be represented as a nullable // because we special-case optional interfaces to be represented as a nullable
...@@ -285,228 +285,228 @@ namespace djinni ...@@ -285,228 +285,228 @@ namespace djinni
template <typename C> static typename C::CppOptType opt_type(typename C::CppOptType *); template <typename C> static typename C::CppOptType opt_type(typename C::CppOptType *);
using CppType = decltype(opt_type<T>(nullptr)); using CppType = decltype(opt_type<T>(nullptr));
using JniType = typename T::Boxed::JniType; using JniType = typename T::Boxed::JniType;
using Boxed = Optional; using Boxed = Optional;
static CppType toCpp(JNIEnv* jniEnv, JniType j) static CppType toCpp(JNIEnv* jniEnv, JniType j)
{ {
return j ? CppType(T::Boxed::toCpp(jniEnv, j)) : CppType(); return j ? CppType(T::Boxed::toCpp(jniEnv, j)) : CppType();
} }
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const OptionalType<typename T::CppType> &c) static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const OptionalType<typename T::CppType> &c)
{ {
return c ? T::Boxed::fromCpp(jniEnv, *c) : LocalRef<JniType>{}; return c ? T::Boxed::fromCpp(jniEnv, *c) : LocalRef<JniType>{};
} }
// fromCpp used for nullable shared_ptr // fromCpp used for nullable shared_ptr
template <typename C = T> template <typename C = T>
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const typename C::CppOptType & cppOpt) { static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const typename C::CppOptType & cppOpt) {
return T::Boxed::fromCppOpt(jniEnv, cppOpt); return T::Boxed::fromCppOpt(jniEnv, cppOpt);
} }
}; };
struct ListJniInfo struct ListJniInfo
{ {
const GlobalRef<jclass> clazz { jniFindClass("java/util/ArrayList") }; const GlobalRef<jclass> clazz { jniFindClass("java/util/ArrayList") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(I)V") }; const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "(I)V") };
const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") }; const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") };
const jmethodID method_get { jniGetMethodID(clazz.get(), "get", "(I)Ljava/lang/Object;") }; const jmethodID method_get { jniGetMethodID(clazz.get(), "get", "(I)Ljava/lang/Object;") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") }; const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
}; };
template <class T> template <class T>
class List class List
{ {
using ECppType = typename T::CppType; using ECppType = typename T::CppType;
using EJniType = typename T::Boxed::JniType; using EJniType = typename T::Boxed::JniType;
public: public:
using CppType = std::vector<ECppType>; using CppType = std::vector<ECppType>;
using JniType = jobject; using JniType = jobject;
using Boxed = List; using Boxed = List;
static CppType toCpp(JNIEnv* jniEnv, JniType j) static CppType toCpp(JNIEnv* jniEnv, JniType j)
{ {
assert(j != nullptr); assert(j != nullptr);
const auto& data = JniClass<ListJniInfo>::get(); const auto& data = JniClass<ListJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get())); assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size); auto size = jniEnv->CallIntMethod(j, data.method_size);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
auto c = CppType(); auto c = CppType();
c.reserve(size); c.reserve(size);
for(jint i = 0; i < size; ++i) for(jint i = 0; i < size; ++i)
{ {
auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_get, i)); auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_get, i));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
c.push_back(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get()))); c.push_back(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get())));
} }
return c; return c;
} }
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{ {
const auto& data = JniClass<ListJniInfo>::get(); const auto& data = JniClass<ListJniInfo>::get();
assert(c.size() <= std::numeric_limits<jint>::max()); assert(c.size() <= std::numeric_limits<jint>::max());
auto size = static_cast<jint>(c.size()); auto size = static_cast<jint>(c.size());
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size)); auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
jniExceptionCheck(jniEnv);
for(const auto& ce : c)
{
auto je = T::Boxed::fromCpp(jniEnv, ce);
jniEnv->CallBooleanMethod(j, data.method_add, get(je));
jniExceptionCheck(jniEnv);
}
return j;
}
};
struct IteratorJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/Iterator") };
const jmethodID method_next { jniGetMethodID(clazz.get(), "next", "()Ljava/lang/Object;") };
};
struct SetJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/HashSet") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") };
const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") };
};
template <class T>
class Set
{
using ECppType = typename T::CppType;
using EJniType = typename T::Boxed::JniType;
public:
using CppType = std::unordered_set<ECppType>;
using JniType = jobject;
using Boxed = Set;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
const auto& data = JniClass<SetJniInfo>::get();
const auto& iteData = JniClass<IteratorJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
auto c = CppType(); for(const auto& ce : c)
auto it = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_iterator)); {
auto je = T::Boxed::fromCpp(jniEnv, ce);
jniEnv->CallBooleanMethod(j, data.method_add, get(je));
jniExceptionCheck(jniEnv);
}
return j;
}
};
struct IteratorJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/Iterator") };
const jmethodID method_next { jniGetMethodID(clazz.get(), "next", "()Ljava/lang/Object;") };
};
struct SetJniInfo
{
const GlobalRef<jclass> clazz { jniFindClass("java/util/HashSet") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") };
const jmethodID method_add { jniGetMethodID(clazz.get(), "add", "(Ljava/lang/Object;)Z") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") };
};
template <class T>
class Set
{
using ECppType = typename T::CppType;
using EJniType = typename T::Boxed::JniType;
public:
using CppType = std::unordered_set<ECppType>;
using JniType = jobject;
using Boxed = Set;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
const auto& data = JniClass<SetJniInfo>::get();
const auto& iteData = JniClass<IteratorJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size);
jniExceptionCheck(jniEnv);
auto c = CppType();
auto it = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_iterator));
jniExceptionCheck(jniEnv);
for(jint i = 0; i < size; ++i)
{
auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next));
jniExceptionCheck(jniEnv);
c.insert(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get())));
}
return c;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
assert(c.size() <= std::numeric_limits<jint>::max());
const auto& data = JniClass<SetJniInfo>::get();
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
for(jint i = 0; i < size; ++i) for(const auto& ce : c)
{ {
auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next)); auto je = T::fromCpp(jniEnv, ce);
jniExceptionCheck(jniEnv); jniEnv->CallBooleanMethod(j, data.method_add, get(je));
c.insert(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get()))); jniExceptionCheck(jniEnv);
} }
return c; return j;
} }
};
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{ struct MapJniInfo
assert(c.size() <= std::numeric_limits<jint>::max()); {
const auto& data = JniClass<SetJniInfo>::get(); const GlobalRef<jclass> clazz { jniFindClass("java/util/HashMap") };
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor)); const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") };
jniExceptionCheck(jniEnv); const jmethodID method_put { jniGetMethodID(clazz.get(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") };
for(const auto& ce : c) const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") };
{ const jmethodID method_entrySet { jniGetMethodID(clazz.get(), "entrySet", "()Ljava/util/Set;") };
auto je = T::fromCpp(jniEnv, ce); };
jniEnv->CallBooleanMethod(j, data.method_add, get(je));
jniExceptionCheck(jniEnv); struct EntrySetJniInfo
} {
return j; const GlobalRef<jclass> clazz { jniFindClass("java/util/Set") };
} const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") };
}; };
struct MapJniInfo struct EntryJniInfo
{ {
const GlobalRef<jclass> clazz { jniFindClass("java/util/HashMap") }; const GlobalRef<jclass> clazz { jniFindClass("java/util/Map$Entry") };
const jmethodID constructor { jniGetMethodID(clazz.get(), "<init>", "()V") }; const jmethodID method_getKey { jniGetMethodID(clazz.get(), "getKey", "()Ljava/lang/Object;") };
const jmethodID method_put { jniGetMethodID(clazz.get(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") }; const jmethodID method_getValue { jniGetMethodID(clazz.get(), "getValue", "()Ljava/lang/Object;") };
const jmethodID method_size { jniGetMethodID(clazz.get(), "size", "()I") }; };
const jmethodID method_entrySet { jniGetMethodID(clazz.get(), "entrySet", "()Ljava/util/Set;") };
}; template <class Key, class Value>
class Map
struct EntrySetJniInfo {
{ using CppKeyType = typename Key::CppType;
const GlobalRef<jclass> clazz { jniFindClass("java/util/Set") }; using CppValueType = typename Value::CppType;
const jmethodID method_iterator { jniGetMethodID(clazz.get(), "iterator", "()Ljava/util/Iterator;") }; using JniKeyType = typename Key::Boxed::JniType;
}; using JniValueType = typename Value::Boxed::JniType;
struct EntryJniInfo public:
{ using CppType = std::unordered_map<CppKeyType, CppValueType>;
const GlobalRef<jclass> clazz { jniFindClass("java/util/Map$Entry") }; using JniType = jobject;
const jmethodID method_getKey { jniGetMethodID(clazz.get(), "getKey", "()Ljava/lang/Object;") };
const jmethodID method_getValue { jniGetMethodID(clazz.get(), "getValue", "()Ljava/lang/Object;") }; using Boxed = Map;
};
static CppType toCpp(JNIEnv* jniEnv, JniType j)
template <class Key, class Value> {
class Map assert(j != nullptr);
{ const auto& data = JniClass<MapJniInfo>::get();
using CppKeyType = typename Key::CppType; const auto& entrySetData = JniClass<EntrySetJniInfo>::get();
using CppValueType = typename Value::CppType; const auto& entryData = JniClass<EntryJniInfo>::get();
using JniKeyType = typename Key::Boxed::JniType; const auto& iteData = JniClass<IteratorJniInfo>::get();
using JniValueType = typename Value::Boxed::JniType; assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size);
public:
using CppType = std::unordered_map<CppKeyType, CppValueType>;
using JniType = jobject;
using Boxed = Map;
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
const auto& data = JniClass<MapJniInfo>::get();
const auto& entrySetData = JniClass<EntrySetJniInfo>::get();
const auto& entryData = JniClass<EntryJniInfo>::get();
const auto& iteData = JniClass<IteratorJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
auto size = jniEnv->CallIntMethod(j, data.method_size);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
auto entrySet = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_entrySet)); auto entrySet = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_entrySet));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
auto c = CppType(); auto c = CppType();
c.reserve(size); c.reserve(size);
auto it = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(entrySet, entrySetData.method_iterator)); auto it = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(entrySet, entrySetData.method_iterator));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
for(jint i = 0; i < size; ++i) for(jint i = 0; i < size; ++i)
{ {
auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next)); auto je = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next));
jniExceptionCheck(jniEnv);
auto jKey = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getKey));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
auto jKey = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getKey)); auto jValue = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getValue));
jniExceptionCheck(jniEnv);
c.emplace(Key::Boxed::toCpp(jniEnv, static_cast<JniKeyType>(jKey.get())),
Value::Boxed::toCpp(jniEnv, static_cast<JniValueType>(jValue.get())));
}
return c;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
const auto& data = JniClass<MapJniInfo>::get();
assert(c.size() <= std::numeric_limits<jint>::max());
auto size = c.size();
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
jniExceptionCheck(jniEnv);
for(const auto& ce : c)
{
auto jKey = Key::Boxed::fromCpp(jniEnv, ce.first);
auto jValue = Value::Boxed::fromCpp(jniEnv, ce.second);
jniEnv->CallObjectMethod(j, data.method_put, get(jKey), get(jValue));
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
auto jValue = LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getValue)); }
jniExceptionCheck(jniEnv); return j;
c.emplace(Key::Boxed::toCpp(jniEnv, static_cast<JniKeyType>(jKey.get())), }
Value::Boxed::toCpp(jniEnv, static_cast<JniValueType>(jValue.get()))); };
}
return c;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
{
const auto& data = JniClass<MapJniInfo>::get();
assert(c.size() <= std::numeric_limits<jint>::max());
auto size = c.size();
auto j = LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
jniExceptionCheck(jniEnv);
for(const auto& ce : c)
{
auto jKey = Key::Boxed::fromCpp(jniEnv, ce.first);
auto jValue = Value::Boxed::fromCpp(jniEnv, ce.second);
jniEnv->CallObjectMethod(j, data.method_put, get(jKey), get(jValue));
jniExceptionCheck(jniEnv);
}
return j;
}
};
} // namespace djinni } // namespace djinni
...@@ -12,4 +12,3 @@ java: ...@@ -12,4 +12,3 @@ java:
linux: linux:
cd ..; ./test-suite/java/docker/run_dockerized_test.sh cd ..; ./test-suite/java/docker/run_dockerized_test.sh
...@@ -5,52 +5,52 @@ ...@@ -5,52 +5,52 @@
namespace djinni namespace djinni
{ {
struct DurationJniInfo struct DurationJniInfo
{ {
const GlobalRef<jclass> clazz { jniFindClass("java/time/Duration") }; const GlobalRef<jclass> clazz { jniFindClass("java/time/Duration") };
const jmethodID method_ofNanos { jniGetStaticMethodID(clazz.get(), "ofNanos", "(J)Ljava/time/Duration;") }; const jmethodID method_ofNanos { jniGetStaticMethodID(clazz.get(), "ofNanos", "(J)Ljava/time/Duration;") };
const jmethodID method_toNanos { jniGetMethodID(clazz.get(), "toNanos", "()J") }; const jmethodID method_toNanos { jniGetMethodID(clazz.get(), "toNanos", "()J") };
}; };
// This is only a helper, trying to use it as member/param will fail // This is only a helper, trying to use it as member/param will fail
template<class Ratio> template<class Ratio>
struct DurationPeriod; struct DurationPeriod;
using Duration_h = DurationPeriod<std::ratio<3600>>; using Duration_h = DurationPeriod<std::ratio<3600>>;
using Duration_min = DurationPeriod<std::ratio<60>>; using Duration_min = DurationPeriod<std::ratio<60>>;
using Duration_s = DurationPeriod<std::ratio<1>>; using Duration_s = DurationPeriod<std::ratio<1>>;
using Duration_ms = DurationPeriod<std::milli>; using Duration_ms = DurationPeriod<std::milli>;
using Duration_us = DurationPeriod<std::micro>; using Duration_us = DurationPeriod<std::micro>;
using Duration_ns = DurationPeriod<std::nano>; using Duration_ns = DurationPeriod<std::nano>;
template<class Rep, class Period> template<class Rep, class Period>
struct Duration; struct Duration;
template<class Rep, class Ratio> template<class Rep, class Ratio>
struct Duration<Rep, DurationPeriod<Ratio>> struct Duration<Rep, DurationPeriod<Ratio>>
{ {
using CppType = std::chrono::duration<typename Rep::CppType, Ratio>; using CppType = std::chrono::duration<typename Rep::CppType, Ratio>;
using JniType = jobject; using JniType = jobject;
using Boxed = Duration; using Boxed = Duration;
static CppType toCpp(JNIEnv* jniEnv, JniType j) static CppType toCpp(JNIEnv* jniEnv, JniType j)
{ {
assert(j != nullptr); assert(j != nullptr);
const auto& data = JniClass<DurationJniInfo>::get(); const auto& data = JniClass<DurationJniInfo>::get();
assert(jniEnv->IsInstanceOf(j, data.clazz.get())); assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
jlong nanos = jniEnv->CallLongMethod(j, data.method_toNanos); jlong nanos = jniEnv->CallLongMethod(j, data.method_toNanos);
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return std::chrono::duration_cast<CppType>(std::chrono::duration<jlong, std::nano>{nanos}); return std::chrono::duration_cast<CppType>(std::chrono::duration<jlong, std::nano>{nanos});
} }
static LocalRef<jobject> fromCpp(JNIEnv* jniEnv, CppType c) static LocalRef<jobject> fromCpp(JNIEnv* jniEnv, CppType c)
{ {
const auto& data = JniClass<DurationJniInfo>::get(); const auto& data = JniClass<DurationJniInfo>::get();
jlong nanos = std::chrono::duration_cast<std::chrono::duration<jlong, std::nano>>(c).count(); jlong nanos = std::chrono::duration_cast<std::chrono::duration<jlong, std::nano>>(c).count();
auto j = LocalRef<JniType>{jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_ofNanos, nanos)}; auto j = LocalRef<JniType>{jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_ofNanos, nanos)};
jniExceptionCheck(jniEnv); jniExceptionCheck(jniEnv);
return j; return j;
} }
}; };
} }
...@@ -5,47 +5,47 @@ ...@@ -5,47 +5,47 @@
namespace djinni namespace djinni
{ {
// This is only a helper, trying to use it as member/param will fail // This is only a helper, trying to use it as member/param will fail
template<class Ratio> template<class Ratio>
struct DurationPeriod; struct DurationPeriod;
using Duration_h = DurationPeriod<std::ratio<3600>>;
using Duration_min = DurationPeriod<std::ratio<60>>;
using Duration_s = DurationPeriod<std::ratio<1>>;
using Duration_ms = DurationPeriod<std::milli>;
using Duration_us = DurationPeriod<std::micro>;
using Duration_ns = DurationPeriod<std::nano>;
template<class Rep, class Period>
struct Duration;
template<class Rep, class Ratio> using Duration_h = DurationPeriod<std::ratio<3600>>;
struct Duration<Rep, DurationPeriod<Ratio>> using Duration_min = DurationPeriod<std::ratio<60>>;
{ using Duration_s = DurationPeriod<std::ratio<1>>;
using CppType = std::chrono::duration<typename Rep::CppType, Ratio>; using Duration_ms = DurationPeriod<std::milli>;
using ObjcType = NSTimeInterval; using Duration_us = DurationPeriod<std::micro>;
using Duration_ns = DurationPeriod<std::nano>;
static CppType toCpp(ObjcType dt)
{ template<class Rep, class Period>
return std::chrono::duration_cast<CppType>(std::chrono::duration<double>{dt}); struct Duration;
}
static ObjcType fromCpp(CppType dt) template<class Rep, class Ratio>
{ struct Duration<Rep, DurationPeriod<Ratio>>
return std::chrono::duration_cast<std::chrono::duration<double>>(dt).count(); {
} using CppType = std::chrono::duration<typename Rep::CppType, Ratio>;
using ObjcType = NSTimeInterval;
struct Boxed
{ static CppType toCpp(ObjcType dt)
using ObjcType = NSNumber*; {
static CppType toCpp(ObjcType dt) return std::chrono::duration_cast<CppType>(std::chrono::duration<double>{dt});
{ }
assert(dt); static ObjcType fromCpp(CppType dt)
return std::chrono::duration_cast<CppType>(Duration::toCpp([dt doubleValue])); {
} return std::chrono::duration_cast<std::chrono::duration<double>>(dt).count();
static ObjcType fromCpp(CppType dt) }
{
return [NSNumber numberWithDouble:Duration::fromCpp(dt)]; struct Boxed
} {
}; using ObjcType = NSNumber*;
}; static CppType toCpp(ObjcType dt)
{
assert(dt);
return std::chrono::duration_cast<CppType>(Duration::toCpp([dt doubleValue]));
}
static ObjcType fromCpp(CppType dt)
{
return [NSNumber numberWithDouble:Duration::fromCpp(dt)];
}
};
};
} }
...@@ -4,104 +4,104 @@ namespace testsuite { ...@@ -4,104 +4,104 @@ namespace testsuite {
std::string TestDuration::hoursString(std::chrono::duration<int32_t, std::ratio<3600>> dt) std::string TestDuration::hoursString(std::chrono::duration<int32_t, std::ratio<3600>> dt)
{ {
return std::to_string(dt.count()); return std::to_string(dt.count());
} }
std::string TestDuration::minutesString(std::chrono::duration<int32_t, std::ratio<60>> dt) std::string TestDuration::minutesString(std::chrono::duration<int32_t, std::ratio<60>> dt)
{ {
return std::to_string(dt.count()); return std::to_string(dt.count());
} }
std::string TestDuration::secondsString(std::chrono::duration<int32_t, std::ratio<1>> dt) std::string TestDuration::secondsString(std::chrono::duration<int32_t, std::ratio<1>> dt)
{ {
return std::to_string(dt.count()); return std::to_string(dt.count());
} }
std::string TestDuration::millisString(std::chrono::duration<int32_t, std::milli> dt) std::string TestDuration::millisString(std::chrono::duration<int32_t, std::milli> dt)
{ {
return std::to_string(dt.count()); return std::to_string(dt.count());
} }
std::string TestDuration::microsString(std::chrono::duration<int32_t, std::micro> dt) std::string TestDuration::microsString(std::chrono::duration<int32_t, std::micro> dt)
{ {
return std::to_string(dt.count()); return std::to_string(dt.count());
} }
std::string TestDuration::nanosString(std::chrono::duration<int32_t, std::nano> dt) std::string TestDuration::nanosString(std::chrono::duration<int32_t, std::nano> dt)
{ {
return std::to_string(dt.count()); return std::to_string(dt.count());
} }
std::chrono::duration<int32_t, std::ratio<3600>> TestDuration::hours(int32_t count) std::chrono::duration<int32_t, std::ratio<3600>> TestDuration::hours(int32_t count)
{ {
return std::chrono::duration<int32_t, std::ratio<3600>>{count}; return std::chrono::duration<int32_t, std::ratio<3600>>{count};
} }
std::chrono::duration<int32_t, std::ratio<60>> TestDuration::minutes(int32_t count) std::chrono::duration<int32_t, std::ratio<60>> TestDuration::minutes(int32_t count)
{ {
return std::chrono::duration<int32_t, std::ratio<60>>{count}; return std::chrono::duration<int32_t, std::ratio<60>>{count};
} }
std::chrono::duration<int32_t, std::ratio<1>> TestDuration::seconds(int32_t count) std::chrono::duration<int32_t, std::ratio<1>> TestDuration::seconds(int32_t count)
{ {
return std::chrono::duration<int32_t, std::ratio<1>>{count}; return std::chrono::duration<int32_t, std::ratio<1>>{count};
} }
std::chrono::duration<int32_t, std::milli> TestDuration::millis(int32_t count) std::chrono::duration<int32_t, std::milli> TestDuration::millis(int32_t count)
{ {
return std::chrono::duration<int32_t, std::milli>{count}; return std::chrono::duration<int32_t, std::milli>{count};
} }
std::chrono::duration<int32_t, std::micro> TestDuration::micros(int32_t count) std::chrono::duration<int32_t, std::micro> TestDuration::micros(int32_t count)
{ {
return std::chrono::duration<int32_t, std::micro>{count}; return std::chrono::duration<int32_t, std::micro>{count};
} }
std::chrono::duration<int32_t, std::nano> TestDuration::nanos(int32_t count) std::chrono::duration<int32_t, std::nano> TestDuration::nanos(int32_t count)
{ {
return std::chrono::duration<int32_t, std::nano>{count}; return std::chrono::duration<int32_t, std::nano>{count};
} }
std::chrono::duration<double, std::ratio<3600>> TestDuration::hoursf(double count) std::chrono::duration<double, std::ratio<3600>> TestDuration::hoursf(double count)
{ {
return std::chrono::duration<double, std::ratio<3600>>{count}; return std::chrono::duration<double, std::ratio<3600>>{count};
} }
std::chrono::duration<double, std::ratio<60>> TestDuration::minutesf(double count) std::chrono::duration<double, std::ratio<60>> TestDuration::minutesf(double count)
{ {
return std::chrono::duration<double, std::ratio<60>>{count}; return std::chrono::duration<double, std::ratio<60>>{count};
} }
std::chrono::duration<double, std::ratio<1>> TestDuration::secondsf(double count) std::chrono::duration<double, std::ratio<1>> TestDuration::secondsf(double count)
{ {
return std::chrono::duration<double, std::ratio<1>>{count}; return std::chrono::duration<double, std::ratio<1>>{count};
} }
std::chrono::duration<double, std::milli> TestDuration::millisf(double count) std::chrono::duration<double, std::milli> TestDuration::millisf(double count)
{ {
return std::chrono::duration<double, std::milli>{count}; return std::chrono::duration<double, std::milli>{count};
} }
std::chrono::duration<double, std::micro> TestDuration::microsf(double count) std::chrono::duration<double, std::micro> TestDuration::microsf(double count)
{ {
return std::chrono::duration<double, std::micro>{count}; return std::chrono::duration<double, std::micro>{count};
} }
std::chrono::duration<double, std::nano> TestDuration::nanosf(double count) std::chrono::duration<double, std::nano> TestDuration::nanosf(double count)
{ {
return std::chrono::duration<double, std::nano>{count}; return std::chrono::duration<double, std::nano>{count};
} }
std::experimental::optional<std::chrono::duration<int64_t, std::ratio<1>>> TestDuration::box(int64_t count) std::experimental::optional<std::chrono::duration<int64_t, std::ratio<1>>> TestDuration::box(int64_t count)
{ {
using D = std::chrono::duration<int64_t, std::ratio<1>>; using D = std::chrono::duration<int64_t, std::ratio<1>>;
using O = std::experimental::optional<D>; using O = std::experimental::optional<D>;
return count < 0 ? O{} : O{D{count}}; return count < 0 ? O{} : O{D{count}};
} }
int64_t TestDuration::unbox(std::experimental::optional<std::chrono::duration<int64_t, std::ratio<1>>> dt) int64_t TestDuration::unbox(std::experimental::optional<std::chrono::duration<int64_t, std::ratio<1>>> dt)
{ {
return dt ? dt->count() : -1; return dt ? dt->count() : -1;
} }
} // namespace testsuite } // namespace testsuite
...@@ -11,7 +11,7 @@ SetRecord TestHelpers::get_set_record() { ...@@ -11,7 +11,7 @@ SetRecord TestHelpers::get_set_record() {
"StringA", "StringA",
"StringB", "StringB",
"StringC" "StringC"
}, std::unordered_set<int32_t>{} }; }, std::unordered_set<int32_t>{} };
} }
bool TestHelpers::check_set_record(const SetRecord & rec) { bool TestHelpers::check_set_record(const SetRecord & rec) {
......
...@@ -24,8 +24,8 @@ public class AllTests extends TestSuite { ...@@ -24,8 +24,8 @@ public class AllTests extends TestSuite {
return mySuite; return mySuite;
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
NativeLibLoader.loadLibs(); NativeLibLoader.loadLibs();
JUnitCore.main("com.dropbox.djinni.test.AllTests"); JUnitCore.main("com.dropbox.djinni.test.AllTests");
} }
} }
...@@ -8,11 +8,11 @@ public class ClientInterfaceImpl extends ClientInterface { ...@@ -8,11 +8,11 @@ public class ClientInterfaceImpl extends ClientInterface {
} }
return new ClientReturnedRecord(id, utf8string, misc); return new ClientReturnedRecord(id, utf8string, misc);
} }
@Override @Override
public double identifierCheck(byte[] data, int r, long jret) public double identifierCheck(byte[] data, int r, long jret)
{ {
return 0.0; return 0.0;
} }
@Override @Override
public String returnStr() { public String returnStr() {
return "test"; return "test";
......
...@@ -7,31 +7,31 @@ import java.time.Duration; ...@@ -7,31 +7,31 @@ import java.time.Duration;
public class DurationTest extends TestCase { public class DurationTest extends TestCase {
public void test() { public void test() {
assertEquals(TestDuration.hoursString(Duration.ofHours(1)), "1"); assertEquals(TestDuration.hoursString(Duration.ofHours(1)), "1");
assertEquals(TestDuration.minutesString(Duration.ofMinutes(1)), "1"); assertEquals(TestDuration.minutesString(Duration.ofMinutes(1)), "1");
assertEquals(TestDuration.secondsString(Duration.ofSeconds(1)), "1"); assertEquals(TestDuration.secondsString(Duration.ofSeconds(1)), "1");
assertEquals(TestDuration.millisString(Duration.ofMillis(1)), "1"); assertEquals(TestDuration.millisString(Duration.ofMillis(1)), "1");
assertEquals(TestDuration.microsString(Duration.ofNanos(1000)), "1"); assertEquals(TestDuration.microsString(Duration.ofNanos(1000)), "1");
assertEquals(TestDuration.nanosString(Duration.ofNanos(1)), "1"); assertEquals(TestDuration.nanosString(Duration.ofNanos(1)), "1");
assertEquals(TestDuration.hours(1).toHours(), 1); assertEquals(TestDuration.hours(1).toHours(), 1);
assertEquals(TestDuration.minutes(1).toMinutes(), 1); assertEquals(TestDuration.minutes(1).toMinutes(), 1);
assertEquals(TestDuration.seconds(1).getSeconds(), 1); assertEquals(TestDuration.seconds(1).getSeconds(), 1);
assertEquals(TestDuration.millis(1).toMillis(), 1); assertEquals(TestDuration.millis(1).toMillis(), 1);
assertEquals(TestDuration.micros(1).toNanos(), 1000); assertEquals(TestDuration.micros(1).toNanos(), 1000);
assertEquals(TestDuration.nanos(1).toNanos(), 1); assertEquals(TestDuration.nanos(1).toNanos(), 1);
assertEquals(TestDuration.hoursf(1.5).toMinutes(), 90); assertEquals(TestDuration.hoursf(1.5).toMinutes(), 90);
assertEquals(TestDuration.minutesf(1.5).getSeconds(), 90); assertEquals(TestDuration.minutesf(1.5).getSeconds(), 90);
assertEquals(TestDuration.secondsf(1.5).toMillis(), 1500); assertEquals(TestDuration.secondsf(1.5).toMillis(), 1500);
assertEquals(TestDuration.millisf(1.5).toNanos(), 1500 * 1000); assertEquals(TestDuration.millisf(1.5).toNanos(), 1500 * 1000);
assertEquals(TestDuration.microsf(1.5).toNanos(), 1500); assertEquals(TestDuration.microsf(1.5).toNanos(), 1500);
assertEquals(TestDuration.nanosf(1.0).toNanos(), 1); assertEquals(TestDuration.nanosf(1.0).toNanos(), 1);
assertEquals(TestDuration.box(1).getSeconds(), 1); assertEquals(TestDuration.box(1).getSeconds(), 1);
assertEquals(TestDuration.box(-1), null); assertEquals(TestDuration.box(-1), null);
assertEquals(TestDuration.unbox(Duration.ofSeconds(1)), 1); assertEquals(TestDuration.unbox(Duration.ofSeconds(1)), 1);
assertEquals(TestDuration.unbox(null), -1); assertEquals(TestDuration.unbox(null), -1);
} }
} }
...@@ -17,7 +17,7 @@ public class SetRecordTest extends TestCase { ...@@ -17,7 +17,7 @@ public class SetRecordTest extends TestCase {
public void testJavaSetToCppSet() { public void testJavaSetToCppSet() {
HashSet<String> jSet = new HashSet<String>(); HashSet<String> jSet = new HashSet<String>();
HashSet<Integer> iSet = new HashSet<Integer>(); HashSet<Integer> iSet = new HashSet<Integer>();
jSet.add("StringA"); jSet.add("StringA");
jSet.add("StringB"); jSet.add("StringB");
jSet.add("StringC"); jSet.add("StringC");
......
...@@ -14,10 +14,10 @@ static NSString *DBNonAscii = @"Non-ASCII / 非 ASCII 字符"; ...@@ -14,10 +14,10 @@ static NSString *DBNonAscii = @"Non-ASCII / 非 ASCII 字符";
- (double)identifierCheck:(nonnull NSData *)data r:(int32_t)r jret:(int64_t)jret - (double)identifierCheck:(nonnull NSData *)data r:(int32_t)r jret:(int64_t)jret
{ {
(void)data; (void)data;
(void)r; (void)r;
(void)jret; (void)jret;
return 0.0; return 0.0;
} }
- (NSString *)returnStr - (NSString *)returnStr
......
...@@ -37,14 +37,14 @@ using namespace testsuite; ...@@ -37,14 +37,14 @@ using namespace testsuite;
- (void)testObjcRoundTrip - (void)testObjcRoundTrip
{ {
NSDate *now = [NSDate date]; NSDate *now = [NSDate date];
DBDateRecord *date1 = [[DBDateRecord alloc] initWithCreatedAt:now]; DBDateRecord *date1 = [[DBDateRecord alloc] initWithCreatedAt:now];
const auto cpp_date1 = djinni_generated::DateRecord::toCpp(date1); const auto cpp_date1 = djinni_generated::DateRecord::toCpp(date1);
DBDateRecord *date2 = djinni_generated::DateRecord::fromCpp(cpp_date1); DBDateRecord *date2 = djinni_generated::DateRecord::fromCpp(cpp_date1);
const auto cpp_date2 = djinni_generated::DateRecord::toCpp(date2); const auto cpp_date2 = djinni_generated::DateRecord::toCpp(date2);
DBDateRecord *date3 = djinni_generated::DateRecord::fromCpp(cpp_date2); DBDateRecord *date3 = djinni_generated::DateRecord::fromCpp(cpp_date2);
const auto cpp_date3 = djinni_generated::DateRecord::toCpp(date3); const auto cpp_date3 = djinni_generated::DateRecord::toCpp(date3);
const bool cpp_is_equal = cpp_date1.created_at == cpp_date2.created_at && cpp_date2.created_at == cpp_date3.created_at; const bool cpp_is_equal = cpp_date1.created_at == cpp_date2.created_at && cpp_date2.created_at == cpp_date3.created_at;
// cpp is a integer representation (with less precision than NSDate), so direct comparison will work // cpp is a integer representation (with less precision than NSDate), so direct comparison will work
XCTAssertTrue(cpp_is_equal); XCTAssertTrue(cpp_is_equal);
......
...@@ -11,42 +11,42 @@ ...@@ -11,42 +11,42 @@
- (void)setUp - (void)setUp
{ {
[super setUp]; [super setUp];
} }
- (void)tearDown - (void)tearDown
{ {
[super tearDown]; [super tearDown];
} }
- (void)test - (void)test
{ {
XCTAssertEqual([[DBTestDuration hoursString:3600] compare:@"1"], NSOrderedSame); XCTAssertEqual([[DBTestDuration hoursString:3600] compare:@"1"], NSOrderedSame);
XCTAssertEqual([[DBTestDuration minutesString:60] compare:@"1"], NSOrderedSame); XCTAssertEqual([[DBTestDuration minutesString:60] compare:@"1"], NSOrderedSame);
XCTAssertEqual([[DBTestDuration secondsString:1] compare:@"1"], NSOrderedSame); XCTAssertEqual([[DBTestDuration secondsString:1] compare:@"1"], NSOrderedSame);
XCTAssertEqual([[DBTestDuration millisString:0.001] compare:@"1"], NSOrderedSame); XCTAssertEqual([[DBTestDuration millisString:0.001] compare:@"1"], NSOrderedSame);
XCTAssertEqual([[DBTestDuration microsString:0.000001] compare:@"1"], NSOrderedSame); XCTAssertEqual([[DBTestDuration microsString:0.000001] compare:@"1"], NSOrderedSame);
XCTAssertEqual([[DBTestDuration nanosString:0.000000001] compare:@"1"], NSOrderedSame); XCTAssertEqual([[DBTestDuration nanosString:0.000000001] compare:@"1"], NSOrderedSame);
XCTAssertEqualWithAccuracy([DBTestDuration hours:1], 3600, 0.001); XCTAssertEqualWithAccuracy([DBTestDuration hours:1], 3600, 0.001);
XCTAssertEqualWithAccuracy([DBTestDuration minutes:1], 60, 0.001); XCTAssertEqualWithAccuracy([DBTestDuration minutes:1], 60, 0.001);
XCTAssertEqualWithAccuracy([DBTestDuration seconds:1], 1, 0.001); XCTAssertEqualWithAccuracy([DBTestDuration seconds:1], 1, 0.001);
XCTAssertEqualWithAccuracy([DBTestDuration millis:1], 0.001, 0.000001); XCTAssertEqualWithAccuracy([DBTestDuration millis:1], 0.001, 0.000001);
XCTAssertEqualWithAccuracy([DBTestDuration micros:1], 0.000001, 0.000000001); XCTAssertEqualWithAccuracy([DBTestDuration micros:1], 0.000001, 0.000000001);
XCTAssertEqualWithAccuracy([DBTestDuration nanos:1], 0.000000001, 0.000000000001); XCTAssertEqualWithAccuracy([DBTestDuration nanos:1], 0.000000001, 0.000000000001);
XCTAssertEqualWithAccuracy([DBTestDuration hoursf:1.5], 5400, 0.001); XCTAssertEqualWithAccuracy([DBTestDuration hoursf:1.5], 5400, 0.001);
XCTAssertEqualWithAccuracy([DBTestDuration minutesf:1.5], 90, 0.001); XCTAssertEqualWithAccuracy([DBTestDuration minutesf:1.5], 90, 0.001);
XCTAssertEqualWithAccuracy([DBTestDuration secondsf:1.5], 1.5, 0.001); XCTAssertEqualWithAccuracy([DBTestDuration secondsf:1.5], 1.5, 0.001);
XCTAssertEqualWithAccuracy([DBTestDuration millisf:1.5], 0.0015, 0.000001); XCTAssertEqualWithAccuracy([DBTestDuration millisf:1.5], 0.0015, 0.000001);
XCTAssertEqualWithAccuracy([DBTestDuration microsf:1.5], 0.0000015, 0.000000001); XCTAssertEqualWithAccuracy([DBTestDuration microsf:1.5], 0.0000015, 0.000000001);
XCTAssertEqualWithAccuracy([DBTestDuration nanosf:1.0], 0.000000001, 0.000000000001); XCTAssertEqualWithAccuracy([DBTestDuration nanosf:1.0], 0.000000001, 0.000000000001);
XCTAssertEqual([[DBTestDuration box:1.0] intValue],1); XCTAssertEqual([[DBTestDuration box:1.0] intValue],1);
XCTAssertEqual([DBTestDuration box:-1.0], nil); XCTAssertEqual([DBTestDuration box:-1.0], nil);
XCTAssertEqual([DBTestDuration unbox:[NSNumber numberWithDouble:1.0]], 1); XCTAssertEqual([DBTestDuration unbox:[NSNumber numberWithDouble:1.0]], 1);
XCTAssertEqual([DBTestDuration unbox:nil], -1); XCTAssertEqual([DBTestDuration unbox:nil], -1);
} }
@end @end
...@@ -26,21 +26,21 @@ using namespace testsuite; ...@@ -26,21 +26,21 @@ using namespace testsuite;
- (void)testCppToObjc - (void)testCppToObjc
{ {
MapRecord cppMapRecord([self getCppMap], {}); MapRecord cppMapRecord([self getCppMap], {});
DBMapRecord *objcMapRecord = djinni_generated::MapRecord::fromCpp(cppMapRecord); DBMapRecord *objcMapRecord = djinni_generated::MapRecord::fromCpp(cppMapRecord);
[self checkObjcMap:objcMapRecord.map]; [self checkObjcMap:objcMapRecord.map];
} }
- (void)testObjcToCpp - (void)testObjcToCpp
{ {
DBMapRecord *objcMapRecord = [DBMapRecord mapRecordWithMap:[self getObjcMap] imap:[NSDictionary dictionary]]; DBMapRecord *objcMapRecord = [DBMapRecord mapRecordWithMap:[self getObjcMap] imap:[NSDictionary dictionary]];
MapRecord cppMapRecord = djinni_generated::MapRecord::toCpp(objcMapRecord); MapRecord cppMapRecord = djinni_generated::MapRecord::toCpp(objcMapRecord);
[self checkCppMap:cppMapRecord.map]; [self checkCppMap:cppMapRecord.map];
} }
- (void)testCppToObjcEmpty - (void)testCppToObjcEmpty
{ {
MapRecord cppMapRecord{ {}, {} }; MapRecord cppMapRecord{ {}, {} };
DBMapRecord *objcMapRecord = djinni_generated::MapRecord::fromCpp(cppMapRecord); DBMapRecord *objcMapRecord = djinni_generated::MapRecord::fromCpp(cppMapRecord);
XCTAssertEqual([objcMapRecord.map count], (NSUInteger)0, @"Count 0 expected, actual: %lu", (unsigned long)[objcMapRecord.map count]); XCTAssertEqual([objcMapRecord.map count], (NSUInteger)0, @"Count 0 expected, actual: %lu", (unsigned long)[objcMapRecord.map count]);
...@@ -56,7 +56,7 @@ using namespace testsuite; ...@@ -56,7 +56,7 @@ using namespace testsuite;
- (void)testCppMapListToObjc - (void)testCppMapListToObjc
{ {
MapListRecord cppMapListRecord{ { [self getCppMap] } }; MapListRecord cppMapListRecord{ { [self getCppMap] } };
DBMapListRecord *objcMapListRecord = djinni_generated::MapListRecord::fromCpp(cppMapListRecord); DBMapListRecord *objcMapListRecord = djinni_generated::MapListRecord::fromCpp(cppMapListRecord);
NSArray *objcMapList = objcMapListRecord.mapList; NSArray *objcMapList = objcMapListRecord.mapList;
XCTAssertEqual([objcMapList count], (NSUInteger)1, @"List with 1 map expected, actual no: %lu", (unsigned long)[objcMapList count]); XCTAssertEqual([objcMapList count], (NSUInteger)1, @"List with 1 map expected, actual no: %lu", (unsigned long)[objcMapList count]);
......
...@@ -25,25 +25,25 @@ ...@@ -25,25 +25,25 @@
- (void)testPrimitives - (void)testPrimitives
{ {
DBAssortedPrimitives * p = [DBAssortedPrimitives assortedPrimitivesWithB:YES DBAssortedPrimitives * p = [DBAssortedPrimitives assortedPrimitivesWithB:YES
eight:(int8_t)123 eight:(int8_t)123
sixteen:(int16_t)20000 sixteen:(int16_t)20000
thirtytwo:(int32_t)1000000000 thirtytwo:(int32_t)1000000000
sixtyfour:(int64_t)1234567890123456789L sixtyfour:(int64_t)1234567890123456789L
fthirtytwo:(float)1.23 fthirtytwo:(float)1.23
fsixtyfour:1.23 fsixtyfour:1.23
oB:[NSNumber numberWithBool:YES] oB:[NSNumber numberWithBool:YES]
oEight:[NSNumber numberWithChar:123] oEight:[NSNumber numberWithChar:123]
oSixteen:[NSNumber numberWithShort:20000] oSixteen:[NSNumber numberWithShort:20000]
oThirtytwo:[NSNumber numberWithInt:1000000000] oThirtytwo:[NSNumber numberWithInt:1000000000]
oSixtyfour:[NSNumber numberWithLongLong:1234567890123456789L] oSixtyfour:[NSNumber numberWithLongLong:1234567890123456789L]
oFthirtytwo:[NSNumber numberWithFloat:(float)123] oFthirtytwo:[NSNumber numberWithFloat:(float)123]
oFsixtyfour:[NSNumber numberWithDouble:123]]; oFsixtyfour:[NSNumber numberWithDouble:123]];
XCTAssertEqualObjects(p, [DBTestHelpers assortedPrimitivesId:p]); XCTAssertEqualObjects(p, [DBTestHelpers assortedPrimitivesId:p]);
} }
- (void)testEmptyRecord - (void)testEmptyRecord
{ {
(void)[DBEmptyRecord emptyRecord]; (void)[DBEmptyRecord emptyRecord];
} }
- (void)testObjcToCppConverter - (void)testObjcToCppConverter
......
...@@ -13,13 +13,13 @@ using namespace testsuite; ...@@ -13,13 +13,13 @@ using namespace testsuite;
- (SetRecord)getCppSetRecord - (SetRecord)getCppSetRecord
{ {
return SetRecord({"StringA", "StringB", "StringC"}, {}); return SetRecord({"StringA", "StringB", "StringC"}, {});
} }
- (DBSetRecord *)getObjcSetRecord - (DBSetRecord *)getObjcSetRecord
{ {
NSSet *set = [NSSet setWithObjects:@"StringA", @"StringB", @"StringC", nil]; NSSet *set = [NSSet setWithObjects:@"StringA", @"StringB", @"StringC", nil];
DBSetRecord *objcSetRecord = [DBSetRecord setRecordWithSet:set iset:[NSSet set]]; DBSetRecord *objcSetRecord = [DBSetRecord setRecordWithSet:set iset:[NSSet set]];
return objcSetRecord; return objcSetRecord;
} }
......
#! /usr/bin/env bash
# This script formats sources in Djinni with standard whitespace conventions.
# Specifically, tabs are converted to spaces (2 for Scala, 4 for other languages),
# and trailing whitespace is removed.
# This script is idempotent, so can be safely run on existing code without making changes.
set -eu
# Locate the script file. Cross symlinks if necessary.
loc="$0"
while [ -h "$loc" ]; do
ls=`ls -ld "$loc"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
loc="$link" # Absolute link
else
loc="`dirname "$loc"`/$link" # Relative link
fi
done
djinni_dir=$(cd "`dirname "$loc"`" && cd .. && pwd)
# Format source types with 4-space indentation
cd "$djinni_dir" && find . '(' -name '*.[chm]' -or -name '*.[ch]pp' -or -name '*.mm' -or -name '*.java' -or -name '*.py' ')' -and -not -path './deps/*' -exec sh -c 'expand -t 4 "{}" | sed "s/ *$//" | tr -d "\r" > _tmp_ && mv _tmp_ "{}"' \;
# Format source types with 2-space indentatino
cd "$djinni_dir" && find . '(' -name '*.scala' ')' -and -not -path './deps/*' -exec sh -c 'expand -t 2 "{}" | sed "s/ *$//" | tr -d "\r" > _tmp_ && mv _tmp_ "{}"' \;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment