The R Project SVN R

Rev

Rev 63219 | Rev 64516 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 63219 Rev 63223
Line 778... Line 778...
778
   R_alloc stack */
778
   R_alloc stack */
779
const char *translateChar(SEXP x)
779
const char *translateChar(SEXP x)
780
{
780
{
781
    void * obj;
781
    void * obj;
782
    const char *inbuf, *ans = CHAR(x);
782
    const char *inbuf, *ans = CHAR(x);
783
    char *outbuf, *p;
783
    char *outbuf;
784
    size_t inb, outb, res;
784
    size_t inb, outb, res;
785
    cetype_t ienc = getCharCE(x);
785
    cetype_t ienc = getCharCE(x);
786
    R_StringBuffer cbuff = {NULL, 0, MAXELTSIZE};
786
    R_StringBuffer cbuff = {NULL, 0, MAXELTSIZE};
787
 
787
 
788
    if(TYPEOF(x) != CHARSXP)
788
    if(TYPEOF(x) != CHARSXP)
Line 874... Line 874...
874
	}
874
	}
875
	goto next_char;
875
	goto next_char;
876
    }
876
    }
877
    *outbuf = '\0';
877
    *outbuf = '\0';
878
    res = strlen(cbuff.data) + 1;
878
    res = strlen(cbuff.data) + 1;
879
    p = R_alloc(res, 1);
879
    char *p = R_alloc(res, 1);
880
    memcpy(p, cbuff.data, res);
880
    memcpy(p, cbuff.data, res);
881
    R_FreeStringBuffer(&cbuff);
881
    R_FreeStringBuffer(&cbuff);
882
    return p;
882
    return p;
883
}
883
}
884
 
884
 
-
 
885
SEXP installTrChar(SEXP x)
-
 
886
{
-
 
887
    void * obj;
-
 
888
    const char *inbuf, *ans = CHAR(x);
-
 
889
    char *outbuf;
-
 
890
    size_t inb, outb, res;
-
 
891
    cetype_t ienc = getCharCE(x);
-
 
892
    R_StringBuffer cbuff = {NULL, 0, MAXELTSIZE};
-
 
893
 
-
 
894
    if(TYPEOF(x) != CHARSXP)
-
 
895
	error(_("'%s' must be called on a CHARSXP"), "translateChar");
-
 
896
    if(x == NA_STRING || !(ENC_KNOWN(x))) return install(ans);
-
 
897
    if(IS_BYTES(x))
-
 
898
	error(_("translating strings with \"bytes\" encoding is not allowed"));
-
 
899
    if(utf8locale && IS_UTF8(x)) return install(ans);
-
 
900
    if(latin1locale && IS_LATIN1(x)) return install(ans);
-
 
901
    if(IS_ASCII(x)) return install(ans);
-
 
902
 
-
 
903
    if(IS_LATIN1(x)) {
-
 
904
	if(!latin1_obj) {
-
 
905
	    obj = Riconv_open("", "latin1");
-
 
906
	    /* should never happen */
-
 
907
	    if(obj == (void *)(-1))
-
 
908
#ifdef Win32
-
 
909
		error(_("unsupported conversion from '%s' in codepage %d"),
-
 
910
		      "latin1", localeCP);
-
 
911
#else
-
 
912
	        error(_("unsupported conversion from '%s' to '%s'"),
-
 
913
		      "latin1", "");
-
 
914
#endif
-
 
915
	    latin1_obj = obj;
-
 
916
	}
-
 
917
	obj = latin1_obj;
-
 
918
    } else {
-
 
919
	if(!utf8_obj) {
-
 
920
	    obj = Riconv_open("", "UTF-8");
-
 
921
	    /* should never happen */
-
 
922
	    if(obj == (void *)(-1)) 
-
 
923
#ifdef Win32
-
 
924
		error(_("unsupported conversion from '%s' in codepage %d"),
-
 
925
		      "latin1", localeCP);
-
 
926
#else
-
 
927
	        error(_("unsupported conversion from '%s' to '%s'"),
-
 
928
		      "latin1", "");
-
 
929
#endif
-
 
930
	    utf8_obj = obj;
-
 
931
	}
-
 
932
	obj = utf8_obj;
-
 
933
    }
-
 
934
 
-
 
935
    R_AllocStringBuffer(0, &cbuff);
-
 
936
top_of_loop:
-
 
937
    inbuf = ans; inb = strlen(inbuf);
-
 
938
    outbuf = cbuff.data; outb = cbuff.bufsize - 1;
-
 
939
    /* First initialize output */
-
 
940
    Riconv (obj, NULL, NULL, &outbuf, &outb);
-
 
941
next_char:
-
 
942
    /* Then convert input  */
-
 
943
    res = Riconv(obj, &inbuf , &inb, &outbuf, &outb);
-
 
944
    if(res == -1 && errno == E2BIG) {
-
 
945
	R_AllocStringBuffer(2*cbuff.bufsize, &cbuff);
-
 
946
	goto top_of_loop;
-
 
947
    } else if(res == -1 && (errno == EILSEQ || errno == EINVAL)) {
-
 
948
	if(outb < 13) {
-
 
949
	    R_AllocStringBuffer(2*cbuff.bufsize, &cbuff);
-
 
950
	    goto top_of_loop;
-
 
951
	}
-
 
952
	if (ienc == CE_UTF8) {
-
 
953
	    /* if starting in UTF-8, use \uxxxx */
-
 
954
	    /* This must be the first byte */
-
 
955
	    size_t clen;
-
 
956
	    wchar_t wc;
-
 
957
	    clen = utf8toucs(&wc, inbuf);
-
 
958
	    if(clen > 0 && inb >= clen) {
-
 
959
		inbuf += clen; inb -= clen;
-
 
960
# ifndef Win32
-
 
961
		if((unsigned int) wc < 65536) {
-
 
962
# endif
-
 
963
		    snprintf(outbuf, 9, "<U+%04X>", (unsigned int) wc);
-
 
964
		    outbuf += 8; outb -= 8;
-
 
965
# ifndef Win32
-
 
966
		} else {
-
 
967
		    snprintf(outbuf, 13, "<U+%08X>", (unsigned int) wc);
-
 
968
		    outbuf += 12; outb -= 12;
-
 
969
		}
-
 
970
# endif
-
 
971
	    } else {
-
 
972
		snprintf(outbuf, 5, "<%02x>", (unsigned char)*inbuf);
-
 
973
		outbuf += 4; outb -= 4;
-
 
974
		inbuf++; inb--;
-
 
975
	    }
-
 
976
	} else {
-
 
977
	    snprintf(outbuf, 5, "<%02x>", (unsigned char)*inbuf);
-
 
978
	    outbuf += 4; outb -= 4;
-
 
979
	    inbuf++; inb--;
-
 
980
	}
-
 
981
	goto next_char;
-
 
982
    }
-
 
983
    *outbuf = '\0';
-
 
984
    SEXP Sans = install(cbuff.data);
-
 
985
    R_FreeStringBuffer(&cbuff);
-
 
986
    return Sans;
-
 
987
}
-
 
988
 
885
/* This may return a R_alloc-ed result, so the caller has to manage the
989
/* This may return a R_alloc-ed result, so the caller has to manage the
886
   R_alloc stack */
990
   R_alloc stack */
887
const char *translateChar0(SEXP x)
991
const char *translateChar0(SEXP x)
888
{
992
{
889
    if(TYPEOF(x) != CHARSXP)
993
    if(TYPEOF(x) != CHARSXP)