Skip to content

Commit

Permalink
Generator: refactor StringAdapter to support std::u16string
Browse files Browse the repository at this point in the history
Also add tests for std::u16string and std::u32string.
  • Loading branch information
equeim committed Jan 9, 2021
1 parent 2ee94b8 commit 784fe2e
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 74 deletions.
123 changes: 56 additions & 67 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1082,87 +1082,76 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
out.println("#include <string>");
out.println("template<typename T = char> class JavaCPP_hidden StringAdapter {");
out.println("public:");
out.println(" StringAdapter(const char* ptr, typename std::basic_string<T>::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<T>::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<T>::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<T>::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<T>::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<T>::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<T>& str) : ptr(0), size(0), owner(0), str2(str), str(str2) { }");
out.println(" StringAdapter( std::basic_string<T>& str) : ptr(0), size(0), owner(0), str(str) { }");
out.println(" StringAdapter(const std::basic_string<T>* str) : ptr(0), size(0), owner(0), str(*(std::basic_string<T>*)str) { }");
out.println(" void assign(char* ptr, typename std::basic_string<T>::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<T>::size_type size, void* owner) { assign((char*)ptr, size, owner); }");
out.println(" void assign(const signed char* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((char*)ptr, size, owner); }");
out.println(" void assign(const unsigned char* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((char*)ptr, size, owner); }");
out.println(" void assign(wchar_t* ptr, typename std::basic_string<T>::size_type size, void* owner) {");
out.println(" this->ptr = ptr;");
out.println(" StringAdapter(const char* ptr, typename std::basic_string<T>::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }");
out.println(" StringAdapter(const signed char* ptr, typename std::basic_string<T>::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }");
out.println(" StringAdapter(const unsigned short* ptr, typename std::basic_string<T>::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }");
out.println(" StringAdapter(const int* ptr, typename std::basic_string<T>::size_type size, void* owner) : str(str2) { assign(ptr, size, owner); }");
out.println();
out.println(" StringAdapter(const std::basic_string<T>& str) : size(0), owner(NULL), ptr(NULL), str2(str), str(str2) { }");
out.println(" StringAdapter( std::basic_string<T>& str) : size(0), owner(NULL), ptr(NULL), str(str) { }");
out.println(" StringAdapter(const std::basic_string<T>* str) : size(0), owner(NULL), ptr(NULL), str(*const_cast<std::basic_string<T>*>(str)) { }");
out.println();
out.println(" static void deallocate(void* owner) { delete[] static_cast<T*>(owner); }");
out.println();
out.println(" operator char*() { return getPtrImpl<char>(); }");
out.println(" operator signed char*() { return getPtrImpl<signed char>(); }");
out.println(" operator const char*() { return getConstPtrImpl<char>(); }");
out.println(" operator const signed char*() { return getConstPtrImpl<signed char>(); }");
out.println(" operator unsigned short*() { return getPtrImpl<unsigned short>(); }");
out.println(" operator int*() { return getPtrImpl<int>(); }");
out.println(" operator const unsigned short*() { return getConstPtrImpl<unsigned short>(); }");
out.println(" operator const int*() { return getConstPtrImpl<int>(); }");
out.println(" operator std::basic_string<T>&() { return str; }");
out.println(" operator std::basic_string<T>*() { return ptr ? &str : NULL; }");
out.println();
out.println(" void assign(const char* ptr, typename std::basic_string<T>::size_type size, void* owner) { assignImpl(ptr, size, owner); }");
out.println(" void assign(const signed char* ptr, typename std::basic_string<T>::size_type size, void* owner) { assignImpl(ptr, size, owner); }");
out.println(" void assign(const unsigned short* ptr, typename std::basic_string<T>::size_type size, void* owner) { assignImpl(ptr, size, owner); }");
out.println(" void assign(const int* ptr, typename std::basic_string<T>::size_type size, void* owner) { assignImpl(ptr, size, owner); }");
out.println();
out.println(" typename std::basic_string<T>::size_type size;");
out.println(" void* owner;");
out.println();
out.println("private:");
out.println(" T* ptr;");
out.println(" std::basic_string<T> str2;");
out.println(" std::basic_string<T>& str;");
out.println();
out.println(" static const T emptyStringLiteral[1];");
out.println();
out.println(" template<typename P>");
out.println(" void assignImpl(const P* ptr, typename std::basic_string<T>::size_type size, void* owner) {");
out.println(" T* p = reinterpret_cast<T*>(const_cast<P*>(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<T>::length(p)) : 0);");
out.println(" }");
out.println(" void assign(const wchar_t* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }");
out.println(" void assign(const unsigned short* ptr, typename std::basic_string<T>::size_type size, void* owner) { assign((wchar_t*)ptr, size, owner); }");
out.println(" void assign(const signed int* ptr, typename std::basic_string<T>::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<typename P>");
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<P*>(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<typename P>");
out.println(" const P* getConstPtrImpl() {");
out.println(" size = str.size();");
out.println(" owner = ptr;");
out.println(" return ptr;");
out.println(" return reinterpret_cast<const P*>(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<T>&() { return str; }");
out.println(" operator std::basic_string<T>*() { return ptr ? &str : 0; }");
out.println(" T* ptr;");
out.println(" typename std::basic_string<T>::size_type size;");
out.println(" void* owner;");
out.println(" std::basic_string<T> str2;");
out.println(" std::basic_string<T>& str;");
out.println("};");
out.println();
out.println("template<typename T> const T StringAdapter<T>::emptyStringLiteral[1] = { 0 };");
out.println();
out.println("#ifdef SHARED_PTR_NAMESPACE");
out.println("template<class T> class SharedPtrAdapter {");
out.println("public:");
Expand Down
19 changes: 15 additions & 4 deletions src/test/java/org/bytedeco/javacpp/AdapterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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();
Expand Down
21 changes: 18 additions & 3 deletions src/test/resources/org/bytedeco/javacpp/AdapterTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 784fe2e

Please sign in to comment.