android / android/ndk

C++ Wrapper for jstring

Open
#1,109 1 comment 0 reactions 0 assignees View on GitHub
c++ wrapper request enhancement
Dominant language
No language data
Stars
2.3k
Forks
310
PR merge metrics
No merged PRs in 30d

Description

Forked from #476

Proposal for jstring C++ wrapper
char16_t wrapper is commented out in example as it requires some utf32-utf16 convertion

jstring.hpp
```
#pragma once
#include "common.h"
#include
#include
#include

using jenv = JNIEnv *;

namespace jni
{
///\brief resource managment type
enum struct jownership_e : uint8_t
{
external, ///\brief external owned not managment
owned ///\brief internaly managed
};
enum struct attach_mode_e : uint8_t
{
attached, ///\brief after intance is created internal java buffers are auto attached for jstring, jarray
detached //\brief after intance is created internal java buffers are not attached
};

template
struct char_traits : public std::char_traits
{};

template<>
struct char_traits : public std::char_traits
{
inline static char const * jatatch_string(jenv env, ::jstring instance) noexcept
{ return env->GetStringUTFChars(instance, nullptr); }

inline static void detach_string(jenv env, ::jstring instance, char const * ptr ) noexcept
{ env->ReleaseStringUTFChars(instance, ptr); }

inline static ::jstring construct( jenv env, char const * src , size_t sz = 0u) noexcept
{ return env->NewStringUTF(src); }


inline static size_t length(jenv env, ::jstring s, char_type const * p) noexcept { return std::char_traits::length(p); }
};
#if 0
template<>
struct char_traits : public std::char_traits
{
inline static char16_t const * jatatch_string(jenv env, ::jstring instance) noexcept
{ return reinterpret_cast(env->GetStringChars(instance, nullptr)); }

inline static void detach_string(jenv env, ::jstring instance, char16_t const * ptr ) noexcept
{ env->ReleaseStringChars(instance, reinterpret_cast(ptr)); }

inline static ::jstring construct( jenv env, char16_t const * src ) noexcept
{ return env->NewString(reinterpret_cast(src), std::char_traits::length(src) ); }

inline static ::jstring construct( jenv env, char16_t const * src, size_t sz ) noexcept
{ return env->NewString(reinterpret_cast(src),sz); }

//charset unused
inline static ::jstring construct( jenv env, wchar_t const * src, size_t sz, uint8_t charset = 0 ) noexcept
{
Aqurat::u16_char_buffer_type buff;
size_t const code_points_count { Aqurat::WasU16(src, src + sz, buff) };
if( !buff.empty())
return env->NewString(reinterpret_cast(buff.data()), code_points_count );
return nullptr;
}
///\warning u16 java string is not nullterminated
inline static size_t length(jenv env, ::jstring s, char_type const * p) noexcept { return env->GetStringLength(s); }
};
#endif

template>
class basic_string
{
public:
using char_type = CharType;
using char_traits = CharTraits;
using const_pointer = char_type const *;
using const_iterator = const_pointer;
using native_string_type = std::basic_string;

private:
jenv env_;
::jstring instance_;
const_pointer begin_, end_;
jownership_e owns_object_;

public:
inline explicit operator bool() const noexcept { return nullptr != instance_ ; }
inline char_type operator[]( size_t ix ) const noexcept { return begin_[ix]; }
inline operator native_string_type() const { return native_string_type{ c_str(), size() }; }
inline ::jstring get() const noexcept { return instance_; }
inline explicit operator ::jstring() const noexcept { return instance_; }
inline explicit operator ::jobject() const noexcept { return instance_; }
inline bool empty() const noexcept { return begin_ == end_; }
inline size_t size() const noexcept { return static_cast(std::distance(begin(), end())); }
inline const_pointer data() const noexcept { return begin_; }
///\warning u16 string is not null terminated
inline const_pointer c_str() const noexcept { return begin_; }
inline const_iterator begin() const noexcept { return begin_; }
inline const_iterator end() const noexcept { return end_; }

inline basic_string() noexcept :
env_(), instance_(), begin_(), end_(), owns_object_()
{}
///\param mode use attach_mode_e::detached if string will be used only as argument to jni methods
template
basic_string(jenv env, size_t size, friend_char_type const * src, attach_mode_e mode = attach_mode_e::attached ) noexcept;

///\warning this constructor should be used only with char ansi, with char16 is ineffective, will calculate length
///\param src null terminated string
///\param mode use attach_mode_e::detached if string will be used only as argument to jni methods
basic_string(jenv env, char_type const * src, attach_mode_e mode = attach_mode_e::attached ) noexcept;

inline basic_string(jenv env, native_string_type const & src, attach_mode_e mode = attach_mode_e::attached ) noexcept :
basic_string( env, src.size(), src.c_str(), mode )
{}

///\warning if \param instance was obtained from call to java method in native code, set \param own to jownership_e::owned
///\param mode use attach_mode_e::detached if string will be used only as argument to jni methods
basic_string(jenv env, ::jstring instance, jownership_e own = jownership_e::external,
attach_mode_e mode = attach_mode_e::attached ) noexcept;

basic_string( basic_string && rh ) noexcept;
basic_string & operator=( basic_string && rh ) noexcept;
~basic_string() { reset(); }

void reset() noexcept;

///\brief releases repsponsibility for object, ex when returning obejct to java that was constructed in native code
::jstring release() noexcept;
};

using string = basic_string;
// using u16string = basic_string;

inline std::ostream & operator << ( std::ostream & outstr, jni::string const & src )
{
outstr.write( src.c_str(), static_cast( src.size()) );
return outstr;
}


template
template
basic_string::basic_string(jenv env, size_t size, friend_char_type const * src, attach_mode_e mode ) noexcept :
env_(env), instance_( char_traits::construct(env,src,size) ),
begin_(), end_(), owns_object_(jownership_e::owned)
{
if(nullptr != instance_ && attach_mode_e::attached == mode)
{
begin_ = char_traits::jatatch_string(env, instance_);
if(nullptr != begin_)
end_= std::next(begin_, static_cast(char_traits::length(env,instance_,begin_)) );
}
}

extern template class basic_string;
}

```

jstring.cc
```
#include

namespace jni
{

template
basic_string::basic_string(jenv env, char_type const * src, attach_mode_e mode ) noexcept :
env_(env), instance_( char_traits::construct(env,src) ),
begin_(), end_(), owns_object_(jownership_e::owned)
{
if( nullptr != instance_ && attach_mode_e::attached == mode )
{
begin_ = char_traits::jatatch_string(env, instance_);
if(nullptr != begin_)
end_= std::next(begin_, static_cast( char_traits::length(env,instance_,begin_)) );
}
}

template
basic_string::basic_string( basic_string && rh ) noexcept :
env_(rh.env_), instance_(rh.instance_), begin_(rh.begin_), end_(rh.end_), owns_object_(rh.owns_object_)
{
rh.env_ = nullptr;
rh.instance_ = nullptr;
rh.begin_ = nullptr;
rh.end_ = nullptr;
rh.owns_object_ = jownership_e::external;
}

template
basic_string::basic_string(jenv env, ::jstring instance, jownership_e own, attach_mode_e mode ) noexcept :
env_(env), instance_(instance), begin_(), end_(), owns_object_(own)
{
if(nullptr != instance_ && attach_mode_e::attached == mode)
{
begin_ = char_traits::jatatch_string(env, instance_);
if(nullptr != begin_)
end_= std::next(begin_, static_cast(char_traits::length(env,instance_,begin_)) );
}
}

template
basic_string &
basic_string::operator=( basic_string && rh ) noexcept
{
std::swap(env_,rh.env_);
std::swap(instance_,rh.instance_);
std::swap(begin_,rh.begin_);
std::swap(end_,rh.end_);
std::swap(owns_object_,rh.owns_object_);
return *this;
}

template
::jstring basic_string::release() noexcept
{
::jstring ret { instance_ };
if( nullptr != instance_ )
{
if(nullptr != begin_)
{
char_traits::detach_string(env_, instance_, begin_ );
begin_ = nullptr;
end_ = nullptr;
}
env_ = nullptr;
owns_object_ = jownership_e::external;
instance_ = nullptr;
}
return ret;
}

template
void basic_string::reset() noexcept
{
if( nullptr != instance_ )
{
if(nullptr != begin_)
{
char_traits::detach_string(env_, instance_, begin_ );
begin_ = nullptr;
end_ = nullptr;
}
if(owns_object_ == jownership_e::owned)
env_->DeleteLocalRef(instance_);
instance_ = nullptr;
env_ = nullptr;
}
}

template class basic_string;
}

```

Contributor guide

Open the contributing guide

Research direction

The proposal names jstring.hpp and jstring.cc. Start by reviewing those files and the original #476 context; the issue does not specify tests or acceptance criteria, so confirm the intended API and definition of done before implementing.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, cpp
Domain
mobile-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.