Skip to content

Commit aa08c90

Browse files
committed
Improve TypeSignature implementation
1 parent ecf9550 commit aa08c90

File tree

2 files changed

+84
-55
lines changed

2 files changed

+84
-55
lines changed

include/jni/type_signature.hpp

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,63 +4,86 @@
44
#include <jni/object.hpp>
55
#include <jni/array.hpp>
66

7-
#include <initializer_list>
8-
#include <string>
9-
107
namespace jni
118
{
9+
template < char... chars >
10+
struct StringLiteral
11+
{
12+
operator const char *() const
13+
{
14+
static const char result[] = { chars..., 0 };
15+
return result;
16+
}
17+
};
18+
19+
constexpr std::size_t StringLiteralLength(const char * str, std::size_t len = 0)
20+
{
21+
return str[0] ? StringLiteralLength(str + 1, len + 1) : len;
22+
}
23+
24+
template < class, class >
25+
struct TagLiteralImpl;
26+
27+
template < class Tag, std::size_t... Is >
28+
struct TagLiteralImpl< Tag, std::index_sequence<Is...> >
29+
{
30+
using Value = StringLiteral< Tag::Name()[Is]... >;
31+
};
32+
33+
template < class Tag >
34+
using TagLiteral = typename TagLiteralImpl< Tag, std::make_index_sequence<StringLiteralLength(Tag::Name())> >::Value;
35+
36+
template < char... As, char... Bs >
37+
constexpr auto Concat(const StringLiteral<As...>&,
38+
const StringLiteral<Bs...>&)
39+
{
40+
return StringLiteral<As..., Bs...>();
41+
}
42+
43+
template < class A, class B, class... Rest >
44+
constexpr auto Concat(const A& a,
45+
const B& b,
46+
const Rest&... rest)
47+
{
48+
return Concat(Concat(a, b), rest...);
49+
}
50+
1251
template < class > struct TypeSignature;
1352

14-
template <> struct TypeSignature< jboolean > { const char * operator()() const { return "Z"; } };
15-
template <> struct TypeSignature< jbyte > { const char * operator()() const { return "B"; } };
16-
template <> struct TypeSignature< jchar > { const char * operator()() const { return "C"; } };
17-
template <> struct TypeSignature< jshort > { const char * operator()() const { return "S"; } };
18-
template <> struct TypeSignature< jint > { const char * operator()() const { return "I"; } };
19-
template <> struct TypeSignature< jlong > { const char * operator()() const { return "J"; } };
20-
template <> struct TypeSignature< jfloat > { const char * operator()() const { return "F"; } };
21-
template <> struct TypeSignature< jdouble > { const char * operator()() const { return "D"; } };
22-
template <> struct TypeSignature< void > { const char * operator()() const { return "V"; } };
53+
template <> struct TypeSignature< jboolean > { constexpr auto operator()() const { return StringLiteral<'Z'>(); } };
54+
template <> struct TypeSignature< jbyte > { constexpr auto operator()() const { return StringLiteral<'B'>(); } };
55+
template <> struct TypeSignature< jchar > { constexpr auto operator()() const { return StringLiteral<'C'>(); } };
56+
template <> struct TypeSignature< jshort > { constexpr auto operator()() const { return StringLiteral<'S'>(); } };
57+
template <> struct TypeSignature< jint > { constexpr auto operator()() const { return StringLiteral<'I'>(); } };
58+
template <> struct TypeSignature< jlong > { constexpr auto operator()() const { return StringLiteral<'J'>(); } };
59+
template <> struct TypeSignature< jfloat > { constexpr auto operator()() const { return StringLiteral<'F'>(); } };
60+
template <> struct TypeSignature< jdouble > { constexpr auto operator()() const { return StringLiteral<'D'>(); } };
61+
template <> struct TypeSignature< void > { constexpr auto operator()() const { return StringLiteral<'V'>(); } };
2362

2463
template < class TheTag >
2564
struct TypeSignature< Object<TheTag> >
2665
{
27-
const char * operator()() const
66+
constexpr auto operator()() const
2867
{
29-
static std::string value { std::string("L") + TheTag::Name() + ";" };
30-
return value.c_str();
68+
return Concat(StringLiteral<'L'>(), TagLiteral<TheTag>(), StringLiteral<';'>());
3169
}
3270
};
3371

3472
template < class E >
3573
struct TypeSignature< Array<E> >
3674
{
37-
const char * operator()() const
75+
constexpr auto operator()() const
3876
{
39-
static std::string value { std::string("[") + TypeSignature<E>()() };
40-
return value.c_str();
77+
return Concat(StringLiteral<'['>(), TypeSignature<E>()());
4178
}
4279
};
4380

4481
template < class R, class... Args >
4582
struct TypeSignature< R (Args...) >
4683
{
47-
private:
48-
template < class T > void DoNothingWith(const std::initializer_list<T>&) const {}
49-
50-
std::string Compute() const
51-
{
52-
static std::string result("(");
53-
DoNothingWith<int>( { ( result += TypeSignature<Args>()(), 0 )... } );
54-
result += ")";
55-
result += TypeSignature<R>()();
56-
return result;
57-
}
58-
59-
public:
60-
const char * operator()() const
61-
{
62-
static std::string result = Compute();
63-
return result.c_str();
64-
}
84+
constexpr auto operator()() const
85+
{
86+
return Concat(StringLiteral<'('>(), TypeSignature<Args>()()..., StringLiteral<')'>(), TypeSignature<R>()());
87+
}
6588
};
6689
}

test/high_level.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,40 @@ namespace
2626
struct Derived : public Base {};
2727
}
2828

29+
template < char... Cs >
30+
bool operator==(const jni::StringLiteral<Cs...>& a, const char * b)
31+
{
32+
return std::string(a) == std::string(b);
33+
}
34+
2935
int main()
3036
{
3137
/// TypeSignature
3238

33-
assert(jni::TypeSignature< jni::jboolean >()() == std::string("Z"));
34-
assert(jni::TypeSignature< jni::jbyte >()() == std::string("B"));
35-
assert(jni::TypeSignature< jni::jchar >()() == std::string("C"));
36-
assert(jni::TypeSignature< jni::jshort >()() == std::string("S"));
37-
assert(jni::TypeSignature< jni::jint >()() == std::string("I"));
38-
assert(jni::TypeSignature< jni::jlong >()() == std::string("J"));
39-
assert(jni::TypeSignature< jni::jfloat >()() == std::string("F"));
40-
assert(jni::TypeSignature< jni::jdouble >()() == std::string("D"));
41-
assert(jni::TypeSignature< void >()() == std::string("V"));
39+
assert(jni::TypeSignature< jni::jboolean >()() == "Z");
40+
assert(jni::TypeSignature< jni::jbyte >()() == "B");
41+
assert(jni::TypeSignature< jni::jchar >()() == "C");
42+
assert(jni::TypeSignature< jni::jshort >()() == "S");
43+
assert(jni::TypeSignature< jni::jint >()() == "I");
44+
assert(jni::TypeSignature< jni::jlong >()() == "J");
45+
assert(jni::TypeSignature< jni::jfloat >()() == "F");
46+
assert(jni::TypeSignature< jni::jdouble >()() == "D");
47+
assert(jni::TypeSignature< void >()() == "V");
4248

43-
assert(jni::TypeSignature< jni::Object<> >()() == std::string("Ljava/lang/Object;"));
44-
assert(jni::TypeSignature< jni::String >()() == std::string("Ljava/lang/String;"));
49+
assert(jni::TypeSignature< jni::Object<> >()() == "Ljava/lang/Object;");
50+
assert(jni::TypeSignature< jni::String >()() == "Ljava/lang/String;");
4551

46-
assert(jni::TypeSignature< jni::Array<jni::jboolean> >()() == std::string("[Z"));
47-
assert(jni::TypeSignature< jni::Array<jni::String> >()() == std::string("[Ljava/lang/String;"));
52+
assert(jni::TypeSignature< jni::Array<jni::jboolean> >()() == "[Z");
53+
assert(jni::TypeSignature< jni::Array<jni::String> >()() == "[Ljava/lang/String;");
4854

49-
assert(jni::TypeSignature< void () >()() == std::string("()V"));
50-
assert(jni::TypeSignature< jni::jboolean () >()() == std::string("()Z"));
51-
assert(jni::TypeSignature< void (jni::jboolean, jni::jbyte, jni::jchar) >()() == std::string("(ZBC)V"));
55+
assert(jni::TypeSignature< void () >()() == "()V");
56+
assert(jni::TypeSignature< jni::jboolean () >()() == "()Z");
57+
assert(jni::TypeSignature< void (jni::jboolean, jni::jbyte, jni::jchar) >()() == "(ZBC)V");
5258

5359
struct String { static constexpr const char * Name() { return "java/lang/String"; } };
54-
assert(jni::TypeSignature< jni::Object<String> >()() == std::string("Ljava/lang/String;"));
55-
assert(jni::TypeSignature< void (jni::Object<String>) >()() == std::string("(Ljava/lang/String;)V"));
56-
assert(jni::TypeSignature< jni::Object<String> (void) >()() == std::string("()Ljava/lang/String;"));
60+
assert(jni::TypeSignature< jni::Object<String> >()() == "Ljava/lang/String;");
61+
assert(jni::TypeSignature< void (jni::Object<String>) >()() == "(Ljava/lang/String;)V");
62+
assert(jni::TypeSignature< jni::Object<String> (void) >()() == "()Ljava/lang/String;");
5763

5864

5965
/// Class

0 commit comments

Comments
 (0)