Skip to content

Commit 73495bb

Browse files
committed
JRI: convert to/from native encoding in Read/WriteConsole (#24)
1 parent 4ad98c2 commit 73495bb

2 files changed

Lines changed: 67 additions & 35 deletions

File tree

jri/src/Makefile.all

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ JRI.jar: $(JRI_JSRC) $(JNIPREFIX)jri$(JNISO)
1515
org_rosuda_JRI_Rengine.h: org/rosuda/JRI/Rengine.class
1616
if [ -n "$(JAVAH)" ]; then $(JAVAH) -d . -classpath . org.rosuda.JRI.Rengine; fi
1717

18-
Rcallbacks.o: Rcallbacks.c Rcallbacks.h globals.h org_rosuda_JRI_Rengine.h
18+
Rcallbacks.o: Rcallbacks.c Rcallbacks.h globals.h rjstring.h org_rosuda_JRI_Rengine.h
19+
$(CC) -c -o $@ $< $(CFLAGS) $(CPICF) $(JAVAINC) $(RINC) $(JRI_CPPFLAGS)
20+
21+
rjstring.o: rjstring.c rjstring.h
1922
$(CC) -c -o $@ $< $(CFLAGS) $(CPICF) $(JAVAINC) $(RINC) $(JRI_CPPFLAGS)
2023

2124
Rinit.o: Rinit.c Rinit.h Rcallbacks.h
@@ -33,7 +36,7 @@ Rengine.o: Rengine.c org_rosuda_JRI_Rengine.h globals.h Rcallbacks.h Rinit.h
3336
jri.o: jri.c
3437
$(CC) -c -o $@ jri.c $(CFLAGS) $(CPICF) $(JAVAINC) $(RINC) $(JRI_CPPFLAGS)
3538

36-
$(JNIPREFIX)jri$(JNISO): Rengine.o jri.o Rcallbacks.o Rinit.o globals.o rjava.o $(JRIDEPS)
39+
$(JNIPREFIX)jri$(JNISO): Rengine.o jri.o Rcallbacks.o Rinit.o globals.o rjava.o rjstring.o $(JRIDEPS)
3740
$(CC) -o $@ $^ $(LDFLAGS) $(JNILD) $(RLD) $(JRI_LIBS)
3841

3942
win32/libjvm.dll.a:

jri/src/Rcallbacks.c

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "globals.h"
66
#include "Rdecl.h"
77
#include "Rcallbacks.h"
8+
#include "rjstring.h"
89

910
#include "org_rosuda_JRI_Rengine.h"
1011
#include <R_ext/Parse.h>
@@ -64,41 +65,62 @@ JNIEnv *checkEnvironment()
6465

6566
int Re_ReadConsole(RCCONST char *prompt, RCSIGN char *buf, int len, int addtohistory)
6667
{
67-
jstring r,s;
68+
jstring r, s;
6869
jmethodID mid;
69-
JNIEnv *lenv=checkEnvironment();
70-
71-
if (!lenv || !engineObj) return -1;
72-
70+
JNIEnv *lenv=checkEnvironment();
71+
const void *vmax = 0;
72+
int ret = -1;
73+
const char *c = 0;
74+
75+
if (!lenv || !engineObj) return -1;
76+
7377
jri_checkExceptions(lenv, 1);
7478
mid=(*lenv)->GetMethodID(eenv, engineClass, "jriReadConsole", "(Ljava/lang/String;I)Ljava/lang/String;");
7579
#ifdef JRI_DEBUG
7680
printf("jriReadconsole mid=%x\n", mid);
7781
#endif
7882
jri_checkExceptions(lenv, 0);
7983
if (!mid) return -1;
80-
81-
s=(*lenv)->NewStringUTF(eenv, prompt);
82-
r=(jstring) (*lenv)->CallObjectMethod(lenv, engineObj, mid, s, addtohistory);
84+
vmax = vmaxget();
85+
s = rj_newNativeJavaString(lenv, prompt, -1);
86+
vmaxset(vmax);
87+
if (!s) return -1;
88+
r = (jstring) (*lenv)->CallObjectMethod(lenv, engineObj, mid, s, addtohistory);
8389
jri_checkExceptions(lenv, 1);
8490
(*lenv)->DeleteLocalRef(lenv, s);
8591
jri_checkExceptions(lenv, 0);
86-
if (r) {
87-
const char *c=(*lenv)->GetStringUTFChars(lenv, r, 0);
88-
if (!c) return -1;
89-
{
90-
int l=strlen(c);
91-
strncpy((char*)buf, c, (l>len-1)?len-1:l);
92-
buf[(l>len-1)?len-1:l]=0;
92+
while (r) {
93+
/* get string in Java UTF-8 */
94+
c = (*lenv)->GetStringUTFChars(lenv, r, 0);
95+
if (!c) break;
96+
vmax = vmaxget();
97+
98+
/* convert from Java UTF-8 to real UTF-8 in a CHARSXP */
99+
SEXP sRes = rj_mkCharUTF8_noerr(c);
100+
if (!sRes) {
101+
vmaxset(vmax);
102+
break;
103+
}
104+
105+
/* UTF8 -> native */
106+
const char *rc = Rf_translateChar(sRes);
107+
int l = strlen(rc);
108+
strncpy((char*)buf, rc, (l > len - 1) ? len - 1 : l);
109+
vmaxset(vmax);
110+
111+
/* truncate if needed */
112+
buf[(l > len - 1) ? len - 1 : l] = 0;
93113
#ifdef JRI_DEBUG
94-
printf("Re_ReadConsole succeeded: \"%s\"\n",buf);
114+
printf("Re_ReadConsole succeeded: \"%s\"\n", buf);
95115
#endif
96-
}
97-
(*lenv)->ReleaseStringUTFChars(lenv, r, c);
116+
ret = 1;
117+
break;
118+
}
119+
if (r) {
120+
if (c) (*lenv)->ReleaseStringUTFChars(lenv, r, c);
98121
(*lenv)->DeleteLocalRef(lenv, r);
99-
return 1;
100-
}
101-
return -1;
122+
}
123+
return ret;
102124
}
103125

104126
void Re_Busy(int which)
@@ -118,20 +140,27 @@ void Re_Busy(int which)
118140

119141
void Re_WriteConsoleEx(RCCONST char *buf, int len, int oType)
120142
{
121-
JNIEnv *lenv=checkEnvironment();
122-
jri_checkExceptions(lenv, 1);
123-
{
124-
jstring s=(*lenv)->NewStringUTF(lenv, buf);
125-
jmethodID mid=(*lenv)->GetMethodID(lenv, engineClass, "jriWriteConsole", "(Ljava/lang/String;I)V");
126-
jri_checkExceptions(lenv, 0);
143+
JNIEnv *lenv = checkEnvironment();
144+
jri_checkExceptions(lenv, 1);
145+
146+
const void *vmax = vmaxget();
147+
jstring s = rj_newNativeJavaString(lenv, buf, len);
148+
vmaxset(vmax);
149+
if (!s) {
127150
#ifdef JRI_DEBUG
128-
printf("jriWriteConsole mid=%x\n", mid);
151+
printf("jriWriteConsole rj_newNativeJavaString() FAILED!\n");
129152
#endif
130-
if (!mid) return;
131-
(*lenv)->CallVoidMethod(lenv, engineObj, mid, s, oType);
132-
jri_checkExceptions(lenv, 1);
133-
(*lenv)->DeleteLocalRef(lenv, s);
134-
}
153+
return;
154+
}
155+
jmethodID mid = (*lenv)->GetMethodID(lenv, engineClass, "jriWriteConsole", "(Ljava/lang/String;I)V");
156+
jri_checkExceptions(lenv, 0);
157+
#ifdef JRI_DEBUG
158+
printf("jriWriteConsole mid=%x\n", mid);
159+
#endif
160+
if (!mid) return;
161+
(*lenv)->CallVoidMethod(lenv, engineObj, mid, s, oType);
162+
jri_checkExceptions(lenv, 1);
163+
(*lenv)->DeleteLocalRef(lenv, s);
135164
}
136165

137166
/* old-style WriteConsole (for old R versions only) */

0 commit comments

Comments
 (0)