diff --git a/src/main/java/org/bytedeco/javacpp/tools/Generator.java b/src/main/java/org/bytedeco/javacpp/tools/Generator.java index 572dcf3be..47594bfc2 100644 --- a/src/main/java/org/bytedeco/javacpp/tools/Generator.java +++ b/src/main/java/org/bytedeco/javacpp/tools/Generator.java @@ -1082,87 +1082,76 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver out.println("#include "); out.println("template class JavaCPP_hidden StringAdapter {"); out.println("public:"); - out.println(" StringAdapter(const char* ptr, typename std::basic_string::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),"); - out.println(" str2(ptr ? (T*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }"); - out.println(" StringAdapter(const signed char* ptr, typename std::basic_string::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),"); - out.println(" str2(ptr ? (T*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }"); - out.println(" StringAdapter(const unsigned char* ptr, typename std::basic_string::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),"); - out.println(" str2(ptr ? (T*)ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0), str(str2) { }"); - out.println(" StringAdapter(const wchar_t* ptr, typename std::basic_string::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),"); - out.println(" str2(ptr ? (T*)ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0), str(str2) { }"); - out.println(" StringAdapter(const unsigned short* ptr, typename std::basic_string::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),"); - out.println(" str2(ptr ? (T*)ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0), str(str2) { }"); - out.println(" StringAdapter(const signed int* ptr, typename std::basic_string::size_type size, void* owner) : ptr((T*)ptr), size(size), owner(owner),"); - out.println(" str2(ptr ? (T*)ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0), str(str2) { }"); - out.println(" StringAdapter(const std::basic_string& str) : ptr(0), size(0), owner(0), str2(str), str(str2) { }"); - out.println(" StringAdapter( std::basic_string& str) : ptr(0), size(0), owner(0), str(str) { }"); - out.println(" StringAdapter(const std::basic_string* str) : ptr(0), size(0), owner(0), str(*(std::basic_string*)str) { }"); - out.println(" void assign(char* ptr, typename std::basic_string::size_type size, void* owner) {"); - out.println(" this->ptr = ptr;"); - out.println(" this->size = size;"); - out.println(" this->owner = owner;"); - out.println(" str.assign(ptr ? ptr : \"\", ptr ? (size > 0 ? size : strlen((char*)ptr)) : 0);"); - out.println(" }"); - out.println(" void assign(const char* ptr, typename std::basic_string::size_type size, void* owner) { assign((char*)ptr, size, owner); }"); - out.println(" void assign(const signed char* ptr, typename std::basic_string::size_type size, void* owner) { assign((char*)ptr, size, owner); }"); - out.println(" void assign(const unsigned char* ptr, typename std::basic_string::size_type size, void* owner) { assign((char*)ptr, size, owner); }"); - out.println(" void assign(wchar_t* ptr, typename std::basic_string::size_type size, void* owner) {"); - out.println(" this->ptr = ptr;"); + out.println(" StringAdapter(const char* ptr, typename std::basic_string::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }"); + out.println(" StringAdapter(const signed char* ptr, typename std::basic_string::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }"); + out.println(" StringAdapter(const unsigned short* ptr, typename std::basic_string::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }"); + out.println(" StringAdapter(const int* ptr, typename std::basic_string::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }"); + out.println(); + out.println(" StringAdapter(const std::basic_string& str) : size(0), owner(NULL), ptr(NULL), str2(str), str(str2) { }"); + out.println(" StringAdapter( std::basic_string& str) : size(0), owner(NULL), ptr(NULL), str(str) { }"); + out.println(" StringAdapter(const std::basic_string* str) : size(0), owner(NULL), ptr(NULL), str(*const_cast*>(str)) { }"); + out.println(); + out.println(" static void deallocate(void* owner) { delete[] static_cast(owner); }"); + out.println(); + out.println(" operator char*() { return getPtrImpl(); }"); + out.println(" operator signed char*() { return getPtrImpl(); }"); + out.println(" operator const char*() { return getConstPtrImpl(); }"); + out.println(" operator const signed char*() { return getConstPtrImpl(); }"); + out.println(" operator unsigned short*() { return getPtrImpl(); }"); + out.println(" operator int*() { return getPtrImpl(); }"); + out.println(" operator const unsigned short*() { return getConstPtrImpl(); }"); + out.println(" operator const int*() { return getConstPtrImpl(); }"); + out.println(" operator std::basic_string&() { return str; }"); + out.println(" operator std::basic_string*() { return ptr ? &str : NULL; }"); + out.println(); + out.println(" void assign(const char* ptr, typename std::basic_string::size_type size, void* owner) { assignImpl(ptr, size, owner); }"); + out.println(" void assign(const signed char* ptr, typename std::basic_string::size_type size, void* owner) { assignImpl(ptr, size, owner); }"); + out.println(" void assign(const unsigned short* ptr, typename std::basic_string::size_type size, void* owner) { assignImpl(ptr, size, owner); }"); + out.println(" void assign(const int* ptr, typename std::basic_string::size_type size, void* owner) { assignImpl(ptr, size, owner); }"); + out.println(); + out.println(" typename std::basic_string::size_type size;"); + out.println(" void* owner;"); + out.println(); + out.println("private:"); + out.println(" T* ptr;"); + out.println(" std::basic_string str2;"); + out.println(" std::basic_string& str;"); + out.println(); + out.println(" static const T emptyStringLiteral[1];"); + out.println(); + out.println(" template"); + out.println(" void assignImpl(const P* ptr, typename std::basic_string::size_type size, void* owner) {"); + out.println(" T* p = reinterpret_cast(const_cast(ptr));"); + out.println(" this->ptr = p;"); out.println(" this->size = size;"); out.println(" this->owner = owner;"); - out.println(" str.assign(ptr ? ptr : L\"\", ptr ? (size > 0 ? size : wcslen((wchar_t*)ptr)) : 0);"); + out.println(" str.assign(p ? p: emptyStringLiteral, p ? (size > 0 ? size : std::char_traits::length(p)) : 0);"); out.println(" }"); - out.println(" void assign(const wchar_t* ptr, typename std::basic_string::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }"); - out.println(" void assign(const unsigned short* ptr, typename std::basic_string::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }"); - out.println(" void assign(const signed int* ptr, typename std::basic_string::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }"); - out.println(" static void deallocate(void* owner) { delete[] (T*)owner; }"); - out.println(" operator char*() {"); - out.println(" const char* data = str.data();"); + out.println(); + out.println(" template"); + out.println(" P* getPtrImpl() {"); + out.println(" const T* data = str.data();"); out.println(" if (str.size() > size) {"); - out.println(" ptr = new (std::nothrow) char[str.size()+1];"); - out.println(" if (ptr) memset(ptr, 0, str.size()+1);"); + out.println(" ptr = new (std::nothrow) T[str.size() + 1]();"); out.println(" }"); - out.println(" if (ptr && memcmp(ptr, data, str.size()) != 0) {"); - out.println(" memcpy(ptr, data, str.size());"); + out.println(" if (ptr && memcmp(ptr, data, sizeof(T) * str.size()) != 0) {"); + out.println(" memcpy(ptr, data, sizeof(T) * str.size());"); out.println(" if (size > str.size()) ptr[str.size()] = 0;"); out.println(" }"); out.println(" size = str.size();"); out.println(" owner = ptr;"); - out.println(" return ptr;"); + out.println(" return reinterpret_cast(ptr);"); out.println(" }"); - out.println(" operator signed char*() { return (signed char*)(operator char*)(); }"); - out.println(" operator unsigned char*() { return (unsigned char*)(operator char*)(); }"); - out.println(" operator const char*() { size = str.size(); return str.c_str(); }"); - out.println(" operator const signed char*() { size = str.size(); return (signed char*)str.c_str(); }"); - out.println(" operator const unsigned char*() { size = str.size(); return (unsigned char*)str.c_str(); }"); - out.println(" operator wchar_t*() {"); - out.println(" const wchar_t* data = str.data();"); - out.println(" if (str.size() > size) {"); - out.println(" ptr = new (std::nothrow) wchar_t[str.size()+1];"); - out.println(" if (ptr) memset(ptr, 0, sizeof(wchar_t) * (str.size()+1));"); - out.println(" }"); - out.println(" if (ptr && memcmp(ptr, data, sizeof(wchar_t) * str.size()) != 0) {"); - out.println(" memcpy(ptr, data, sizeof(wchar_t) * str.size());"); - out.println(" if (size > str.size()) ptr[str.size()] = 0;"); - out.println(" }"); + out.println(); + out.println(" template"); + out.println(" const P* getConstPtrImpl() {"); out.println(" size = str.size();"); - out.println(" owner = ptr;"); - out.println(" return ptr;"); + out.println(" return reinterpret_cast(str.c_str());"); out.println(" }"); - out.println(" operator unsigned short*() { return (unsigned short*)(operator wchar_t*)(); }"); - out.println(" operator signed int*() { return ( signed int*)(operator wchar_t*)(); }"); - out.println(" operator const wchar_t*() { size = str.size(); return str.c_str(); }"); - out.println(" operator const unsigned short*() { size = str.size(); return (unsigned short*)str.c_str(); }"); - out.println(" operator const signed int*() { size = str.size(); return ( signed int*)str.c_str(); }"); - out.println(" operator std::basic_string&() { return str; }"); - out.println(" operator std::basic_string*() { return ptr ? &str : 0; }"); - out.println(" T* ptr;"); - out.println(" typename std::basic_string::size_type size;"); - out.println(" void* owner;"); - out.println(" std::basic_string str2;"); - out.println(" std::basic_string& str;"); out.println("};"); out.println(); + out.println("template const T StringAdapter::emptyStringLiteral[1] = { 0 };"); + out.println(); out.println("#ifdef SHARED_PTR_NAMESPACE"); out.println("template class SharedPtrAdapter {"); out.println("public:"); diff --git a/src/test/java/org/bytedeco/javacpp/AdapterTest.java b/src/test/java/org/bytedeco/javacpp/AdapterTest.java index be8a88186..e1fdcd321 100644 --- a/src/test/java/org/bytedeco/javacpp/AdapterTest.java +++ b/src/test/java/org/bytedeco/javacpp/AdapterTest.java @@ -53,6 +53,9 @@ public class AdapterTest { static native @StdWString CharPointer testStdWString(@StdWString CharPointer str); static native @StdWString IntPointer testStdWString(@StdWString IntPointer str); + static native @StdString("char16_t") CharPointer testStdU16String(@StdString("char16_t") CharPointer str); + static native @StdString("char32_t") IntPointer testStdU32String(@StdString("char32_t") IntPointer str); + static native String testCharString(String str); static native @Cast("char*") BytePointer testCharString(@Cast("char*") BytePointer str); @@ -139,20 +142,28 @@ static class MovedData extends Pointer { assertEquals(textStr1, textPtr1.getString()); assertEquals(textStr1, textPtr2.getString()); + CharPointer textCharPtr1 = new CharPointer(textStr1); + assertEquals(textStr1, textCharPtr1.getString()); + + IntPointer textIntPtr1 = new IntPointer(textStr1); + assertEquals(textStr1, textIntPtr1.getString()); + if (Loader.getPlatform().startsWith("windows")) { // UTF-16 - CharPointer textCharPtr1 = new CharPointer(textStr1); CharPointer textCharPtr2 = testStdWString(textCharPtr1); - assertEquals(textStr1, textCharPtr1.getString()); assertEquals(textStr1, textCharPtr2.getString()); } else { // UTF-32 - IntPointer textIntPtr1 = new IntPointer(textStr1); IntPointer textIntPtr2 = testStdWString(textIntPtr1); - assertEquals(textStr1, textIntPtr1.getString()); assertEquals(textStr1, textIntPtr2.getString()); } + CharPointer textCharPtr3 = testStdU16String(textCharPtr1); + assertEquals(textStr1, textCharPtr3.getString()); + + IntPointer textIntPtr3 = testStdU32String(textIntPtr1); + assertEquals(textStr1, textIntPtr3.getString()); + byte[] test = getConstStdString(); assertEquals("test", new String(test)); System.gc(); diff --git a/src/test/resources/org/bytedeco/javacpp/AdapterTest.h b/src/test/resources/org/bytedeco/javacpp/AdapterTest.h index ea677fc35..ab6418a88 100644 --- a/src/test/resources/org/bytedeco/javacpp/AdapterTest.h +++ b/src/test/resources/org/bytedeco/javacpp/AdapterTest.h @@ -10,9 +10,24 @@ std::wstring testStdWString(std::wstring str) { return str; } -char *testCharString(const char *str) { - return strdup(str); - // memory leak... +std::u16string testStdU16String(std::u16string str) { + return str; +} + +std::u32string testStdU32String(std::u32string str) { + return str; +} + +const char *testCharString(const char *str) { + return str; +} + +char *testCharString(char *str) { + return str; +} + +const unsigned short *testShortString(const unsigned short *str) { + return str; } unsigned short *testShortString(unsigned short *str) {