Skip to content

Commit

Permalink
add mkCharLen for strings with known length and pssobly embedded nuls
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.r-project.org/R/trunk@43074 00db46b3-68df-0310-9c12-caf00c1e9a41
  • Loading branch information
ripley committed Oct 3, 2007
1 parent 8b70b34 commit 1ea81fd
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 16 deletions.
2 changes: 2 additions & 0 deletions src/include/Rinternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ SEXP Rf_match(SEXP, SEXP, int);
SEXP Rf_namesgets(SEXP, SEXP);
SEXP Rf_mkChar(const char *);
SEXP Rf_mkCharEnc(const char *, int);
SEXP Rf_mkCharLen(const char *, int);
Rboolean Rf_NonNullStringMatch(SEXP, SEXP);
int Rf_ncols(SEXP);
int Rf_nrows(SEXP);
Expand Down Expand Up @@ -906,6 +907,7 @@ int R_system(const char *);
#define match Rf_match
#define mkChar Rf_mkChar
#define mkCharEnc Rf_mkCharEnc
#define mkCharLen Rf_mkCharLen
#define mkString Rf_mkString
#define namesgets Rf_namesgets
#define ncols Rf_ncols
Expand Down
6 changes: 2 additions & 4 deletions src/main/character.c
Original file line number Diff line number Diff line change
Expand Up @@ -2459,7 +2459,7 @@ SEXP attribute_hidden do_charToRaw(SEXP call, SEXP op, SEXP args, SEXP env)
/* <UTF8> rawToChar should work at byte level */
SEXP attribute_hidden do_rawToChar(SEXP call, SEXP op, SEXP args, SEXP env)
{
SEXP ans, c, x = CAR(args);
SEXP ans, x = CAR(args);
int i, nc = LENGTH(x), multiple, len;
char buf[2];

Expand All @@ -2482,9 +2482,7 @@ SEXP attribute_hidden do_rawToChar(SEXP call, SEXP op, SEXP args, SEXP env)
PROTECT(ans = allocVector(STRSXP, 1));
/* String is not necessarily 0-terminated and may contain nuls
so don't use mkChar */
c = allocString(len); /* adds zero terminator */
memcpy(CHAR_RW(c), RAW(x), len);
SET_STRING_ELT(ans, 0, c);
SET_STRING_ELT(ans, 0, mkCharLen((const char *)RAW(x), len));
}
UNPROTECT(1);
return ans;
Expand Down
5 changes: 1 addition & 4 deletions src/main/connections.c
Original file line number Diff line number Diff line change
Expand Up @@ -3217,7 +3217,6 @@ static SEXP readFixedString(Rconnection con, int len)
{
char *buf;
int pos, m;
SEXP ans;

#ifdef SUPPORT_UTF8
if(utf8locale) {
Expand Down Expand Up @@ -3249,9 +3248,7 @@ static SEXP readFixedString(Rconnection con, int len)
pos = m;
}
/* String may contain nuls so don't use mkChar */
ans = allocString(pos);
memcpy(CHAR_RW(ans), buf, pos);
return ans;
return mkCharLen(buf, pos);
}


Expand Down
21 changes: 17 additions & 4 deletions src/main/envir.c
Original file line number Diff line number Diff line change
Expand Up @@ -3212,6 +3212,18 @@ SEXP attribute_hidden do_envprofile(SEXP call, SEXP op, SEXP args, SEXP rho)
return ans;
}

/*
Version for strings with embedded nuls:
these do not currently go in the cache,
and do not have an encoding.
*/
SEXP mkCharLen(const char *name, int len)
{
SEXP c = allocString(len);
memcpy(CHAR_RW(c), name, len);
return c;
}


#ifndef USE_CHAR_HASHING
SEXP mkChar(const char *name)
Expand Down Expand Up @@ -3244,8 +3256,8 @@ SEXP mkCharEnc(const char *name, int enc)
/* We can reuse the hash structure, but need separate code for get/set
of values since our keys are char* and not SEXP symbol types.
Experience has shown that it is better to use a different hash function:
this is the simplest known good one and is likely to be replaced.
Experience has shown that it is better to use a different hash function,
and a power of 2 for the hash size.
*/

/* char_hash_size MUST be a power of 2 and char_hash_mask ==
Expand All @@ -3257,8 +3269,9 @@ static unsigned int char_hash_mask = 65535;

static unsigned int char_hash(const char *s)
{
/* djb2 as from http://www.cse.yorku.ca/~oz/hash.html */
char *p;
unsigned int h = 0;
unsigned int h = 5381;
for (p = (char *) s; *p; p++)
h = ((h << 5) + h) + (*p);
return h;
Expand Down Expand Up @@ -3373,7 +3386,7 @@ SEXP mkCharEnc(const char *name, int enc)
}
if (cval == R_NilValue) {
/* no cached value; need to allocate one and add to the cache */
PROTECT(cval = allocString(strlen(name)));
PROTECT(cval = allocString(len));
strcpy(CHAR_RW(cval), name);
switch(enc) {
case 0:
Expand Down
5 changes: 1 addition & 4 deletions src/main/sysutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,10 +506,7 @@ SEXP attribute_hidden do_iconv(SEXP call, SEXP op, SEXP args, SEXP env)
nout = cbuff.bufsize - 1 - outb;
for(j = 0; j < nout; j++) if(!*p++) {has_nul = TRUE; break;}
if(has_nul) {
si = allocString(nout);
memcpy(CHAR_RW(si), cbuff.data, nout);
if(isLatin1) SET_LATIN1(si);
if(isUTF8) SET_UTF8(si);
si = mkCharLen(cbuff.data, nout);
} else {
if(isLatin1) si = mkCharEnc(cbuff.data, LATIN1_MASK);
else if(isUTF8) si = mkCharEnc(cbuff.data, UTF8_MASK);
Expand Down

0 comments on commit 1ea81fd

Please sign in to comment.