jstring String_createJavaStringFromNTS(const char* cp) { jstring result = 0; if(cp != 0) { jobject bytebuf; jobject charbuf; Size sz = strlen(cp); char const * utf8 = cp; if ( s_two_step_conversion ) { utf8 = (char*)pg_do_encoding_conversion((unsigned char*)cp, (int)sz, s_server_encoding, PG_UTF8); sz = strlen(utf8); } bytebuf = JNI_newDirectByteBuffer((void *)utf8, sz); charbuf = JNI_callObjectMethodLocked(s_CharsetDecoder_instance, s_CharsetDecoder_decode, bytebuf); result = JNI_callObjectMethodLocked(charbuf, s_Object_toString); JNI_deleteLocalRef(bytebuf); JNI_deleteLocalRef(charbuf); /* pg_do_encoding_conversion will return the source argument * when no conversion is required. We don't want to accidentally * free that pointer. */ if(utf8 != cp) pfree((void *)utf8); } return result; }
jstring String_createJavaString(text* t) { jstring result = 0; if(t != 0) { jobject bytebuf; jobject charbuf; char* src = VARDATA(t); char* utf8 = src; Size srcLen = VARSIZE(t) - VARHDRSZ; if(srcLen == 0) return s_the_empty_string; if ( s_two_step_conversion ) { utf8 = (char*)pg_do_encoding_conversion((unsigned char*)src, (int)srcLen, s_server_encoding, PG_UTF8); srcLen = strlen(utf8); } bytebuf = JNI_newDirectByteBuffer(utf8, srcLen); charbuf = JNI_callObjectMethodLocked(s_CharsetDecoder_instance, s_CharsetDecoder_decode, bytebuf); result = JNI_callObjectMethodLocked(charbuf, s_Object_toString); JNI_deleteLocalRef(bytebuf); JNI_deleteLocalRef(charbuf); /* pg_do_encoding_conversion will return the source argument * when no conversion is required. We don't want to accidentally * free that pointer. */ if(utf8 != src) pfree(utf8); } return result; }
static void appendCharBuffer(StringInfoData* buf, jobject charbuf) { Size nchars; char *bp; Size cap; jobject bytebuf; jobject coderresult; for ( ;; ) { /* * Invariant: charbuf has some chars to encode, buf _might_ have room. * Broken StringInfo invariant: within this loop, might lack end NUL. */ nchars = JNI_callIntMethodLocked(charbuf, s_Buffer_remaining); /* * enlargeStringInfo does nothing if it's already large enough, and * enlarges generously if it isn't, not by nickels and dimes. */ cap = (Size)(s_CharsetEncoder_averageBytesPerChar * (double)nchars); enlargeStringInfo(buf, (int)cap); /* * Give the JVM a window into the unused portion of buf. */ bp = buf->data + buf->len; cap = buf->maxlen - buf->len; bytebuf = JNI_newDirectByteBuffer(bp, cap); /* * Encode as much as will fit, then update StringInfo len to reflect it. */ coderresult = JNI_callObjectMethodLocked(s_CharsetEncoder_instance, s_CharsetEncoder_encode, charbuf, bytebuf, (jboolean)JNI_TRUE); buf->len += JNI_callIntMethodLocked(bytebuf, s_Buffer_position); JNI_deleteLocalRef(bytebuf); if ( ! JNI_isSameObject(coderresult, s_CoderResult_OVERFLOW) ) break; JNI_deleteLocalRef(coderresult); } /* * Remember the StringInfo-is-NUL-terminated invariant might not hold here. */ if ( JNI_isSameObject(coderresult, s_CoderResult_UNDERFLOW) ) if ( 0 == JNI_callIntMethodLocked(charbuf, s_Buffer_remaining) ) { JNI_deleteLocalRef(coderresult); enlargeStringInfo(buf, 1); /* MOST PROBABLY a no-op */ buf->data[buf->len] = '\0'; /* I want my invariant back! */ return; } JNI_callVoidMethodLocked(coderresult, s_CoderResult_throwException); }
static Datum _byte_array_coerceObject(Type self, jobject byteArray) { bytea* bytes = 0; if(byteArray == 0) return 0; if(JNI_isInstanceOf(byteArray, s_byteArray_class)) { jsize length = JNI_getArrayLength((jarray)byteArray); int32 byteaSize = length + VARHDRSZ; bytes = (bytea*)palloc(byteaSize); #if (PGSQL_MAJOR_VER == 8 && PGSQL_MINOR_VER < 3) VARATT_SIZEP(bytes) = byteaSize; #else SET_VARSIZE(bytes, byteaSize); #endif JNI_getByteArrayRegion((jbyteArray)byteArray, 0, length, (jbyte*)VARDATA(bytes)); } else if(JNI_isInstanceOf(byteArray, s_BlobValue_class)) { jobject byteBuffer; int32 byteaSize; jlong length = JNI_callLongMethod(byteArray, s_BlobValue_length); byteaSize = (int32)(length + VARHDRSZ); bytes = (bytea*)palloc(byteaSize); #if (PGSQL_MAJOR_VER == 8 && PGSQL_MINOR_VER < 3) VARATT_SIZEP(bytes) = byteaSize; #else SET_VARSIZE(bytes, byteaSize); #endif byteBuffer = JNI_newDirectByteBuffer((void*)VARDATA(bytes), length); if(byteBuffer != 0) JNI_callVoidMethod(byteArray, s_BlobValue_getContents, byteBuffer); JNI_deleteLocalRef(byteBuffer); } else { Exception_throwIllegalArgument("Not coercable to bytea"); } PG_RETURN_BYTEA_P(bytes); }