Skip to content

Commit

Permalink
Generator: add BasicStringAdapter
Browse files Browse the repository at this point in the history
Add BasicStringAdapter, which is new version of StringAdapter
that can work with any basic_string<T>.

Also add `@StdU16String` and `@StdU32String` annotations
to use with `std::u16string` and `std::u32string`.
  • Loading branch information
equeim committed Jan 29, 2021
1 parent c493d8a commit bb06845
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 7 deletions.
19 changes: 19 additions & 0 deletions src/main/java/org/bytedeco/javacpp/annotation/StdBasicString.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.bytedeco.javacpp.annotation;

import org.bytedeco.javacpp.Pointer;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Adapter("BasicStringAdapter")
public @interface StdBasicString {
/** The template type of {@code BasicStringAdapter}. If not specified, it is
* inferred from the value type of the {@link Pointer} or Java array. */
String value() default "";
}
15 changes: 15 additions & 0 deletions src/main/java/org/bytedeco/javacpp/annotation/StdU16String.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.bytedeco.javacpp.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Adapter("BasicStringAdapter")
public @interface StdU16String {
String value() default "unsigned short, char16_t";
}
15 changes: 15 additions & 0 deletions src/main/java/org/bytedeco/javacpp/annotation/StdU32String.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.bytedeco.javacpp.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Adapter("BasicStringAdapter")
public @interface StdU32String {
String value() default "int, char32_t";
}
51 changes: 51 additions & 0 deletions src/main/java/org/bytedeco/javacpp/tools/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,57 @@ boolean classes(boolean handleExceptions, boolean defineAdapters, boolean conver
out.println(" std::basic_string<T>& str;");
out.println("};");
out.println();
out.println("template<typename P, typename T = P> class JavaCPP_hidden BasicStringAdapter {");
out.println("public:");
out.println(" BasicStringAdapter(const P* ptr, typename std::basic_string<T>::size_type size, void* owner) : str(str2) { assign(const_cast<P*>(ptr), size, owner); }");
out.println();
out.println(" BasicStringAdapter(const std::basic_string<T>& str) : size(0), owner(NULL), ptr(NULL), str2(str), str(str2) { }");
out.println(" BasicStringAdapter( std::basic_string<T>& str) : size(0), owner(NULL), ptr(NULL), str(str) { }");
out.println(" BasicStringAdapter(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 P*() {");
out.println(" const T* data = str.data();");
out.println(" if (str.size() > size) {");
out.println(" ptr = new (std::nothrow) T[str.size() + 1]();");
out.println(" }");
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 reinterpret_cast<P*>(ptr);");
out.println(" }");
out.println(" operator const P*() {");
out.println(" size = str.size();");
out.println(" return reinterpret_cast<const P*>(str.c_str());");
out.println(" }");
out.println();
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(P* ptr, typename std::basic_string<T>::size_type size, void* owner) {");
out.println(" this->ptr = reinterpret_cast<T*>(ptr);");
out.println(" this->size = size;");
out.println(" this->owner = owner;");
out.println(" if (this->ptr) {");
out.println(" str.assign(this->ptr, size > 0 ? size : std::char_traits<T>::length(this->ptr));");
out.println(" } else {");
out.println(" str.clear();");
out.println(" }");
out.println(" }");
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();
out.println("#ifdef SHARED_PTR_NAMESPACE");
out.println("template<class T> class SharedPtrAdapter {");
out.println("public:");
Expand Down
38 changes: 34 additions & 4 deletions src/test/java/org/bytedeco/javacpp/AdapterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@
import org.bytedeco.javacpp.annotation.Function;
import org.bytedeco.javacpp.annotation.Platform;
import org.bytedeco.javacpp.annotation.SharedPtr;
import org.bytedeco.javacpp.annotation.StdBasicString;
import org.bytedeco.javacpp.annotation.StdMove;
import org.bytedeco.javacpp.annotation.StdString;
import org.bytedeco.javacpp.annotation.StdU16String;
import org.bytedeco.javacpp.annotation.StdU32String;
import org.bytedeco.javacpp.annotation.StdVector;
import org.bytedeco.javacpp.annotation.StdWString;
import org.bytedeco.javacpp.annotation.UniquePtr;
Expand All @@ -53,6 +56,14 @@ public class AdapterTest {
static native @StdWString CharPointer testStdWString(@StdWString CharPointer str);
static native @StdWString IntPointer testStdWString(@StdWString IntPointer str);

static native @StdBasicString("char") String testStdString2(@StdBasicString("char") String str);
static native @Cast("char*") @StdBasicString("char") BytePointer testStdString2(@Cast("char*") @StdBasicString("char") @StdString BytePointer str);
static native @Cast("wchar_t*") @StdBasicString("wchar_t") CharPointer testStdWString2(@Cast("wchar_t*") @StdBasicString("wchar_t") CharPointer str);
static native @Cast("wchar_t*") @StdBasicString("wchar_t") IntPointer testStdWString2(@Cast("wchar_t*") @StdBasicString("wchar_t") IntPointer str);

static native @StdU16String CharPointer testStdU16String(@StdU16String CharPointer str);
static native @StdU32String IntPointer testStdU32String(@StdU32String IntPointer str);

static native String testCharString(String str);
static native @Cast("char*") BytePointer testCharString(@Cast("char*") BytePointer str);

Expand All @@ -61,6 +72,7 @@ public class AdapterTest {
static native IntPointer testIntString(IntPointer str);

static native @Const @ByRef @StdString byte[] getConstStdString();
static native @Const @ByRef @Cast("char*") @StdBasicString("char") byte[] getConstStdString2();

static class SharedData extends Pointer {
SharedData(Pointer p) { super(p); }
Expand Down Expand Up @@ -133,28 +145,46 @@ static class MovedData extends Pointer {
String textStr1 = "This is a normal ASCII string.";
String textStr2 = testStdString(textStr1);
assertEquals(textStr1, textStr2);
String textStr3 = testStdString2(textStr1);
assertEquals(textStr1, textStr3);

BytePointer textPtr1 = new BytePointer(textStr1);
BytePointer textPtr2 = testStdString(textPtr1);
assertEquals(textStr1, textPtr1.getString());
assertEquals(textStr1, textPtr2.getString());
BytePointer textPtr3 = testStdString2(textPtr1);
assertEquals(textStr1, textPtr3.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());
CharPointer textCharPtr3 = testStdWString2(textCharPtr1);
assertEquals(textStr1, textCharPtr3.getString());
} else {
// UTF-32
IntPointer textIntPtr1 = new IntPointer(textStr1);
IntPointer textIntPtr2 = testStdWString(textIntPtr1);
assertEquals(textStr1, textIntPtr1.getString());
assertEquals(textStr1, textIntPtr2.getString());
IntPointer textIntPtr3 = testStdWString2(textIntPtr1);
assertEquals(textStr1, textIntPtr3.getString());
}

CharPointer textCharPtr4 = testStdU16String(textCharPtr1);
assertEquals(textStr1, textCharPtr4.getString());

IntPointer textIntPtr4 = testStdU32String(textIntPtr1);
assertEquals(textStr1, textIntPtr4.getString());

byte[] test = getConstStdString();
assertEquals("test", new String(test));
byte[] test2 = getConstStdString2();
assertEquals("test", new String(test2));
System.gc();
}

Expand Down
33 changes: 30 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,32 @@ std::wstring testStdWString(std::wstring str) {
return str;
}

char *testCharString(const char *str) {
return strdup(str);
// memory leak...
std::string testStdString2(std::string str) {
return str;
}

std::wstring testStdWString2(std::wstring str) {
return str;
}

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 All @@ -28,6 +51,10 @@ const std::string& getConstStdString() {
return test;
}

const std::string& getConstStdString2() {
return getConstStdString();
}

int constructorCount = 0;
int destructorCount = 0;

Expand Down

0 comments on commit bb06845

Please sign in to comment.