digitalmars.D.bugs - [Issue 1393] New: Phobos needs strnlen()
- d-bugmail puremagic.com (68/68) Jul 31 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1393
- d-bugmail puremagic.com (31/31) Aug 14 2007 http://d.puremagic.com/issues/show_bug.cgi?id=1393
http://d.puremagic.com/issues/show_bug.cgi?id=1393
Summary: Phobos needs strnlen()
Product: D
Version: 1.015
Platform: PC
OS/Version: Linux
Status: NEW
Severity: enhancement
Priority: P2
Component: Phobos
AssignedTo: bugzilla digitalmars.com
ReportedBy: cdunn2001 gmail.com
std.c.string needs strnlen(). Here is why:
struct Person{
char name[32];
char addr[128];
};
A bunch of these could be stored on disk. After loading, we want to compare
'name' to another array. But how? We can use strncmp(), but we need to know
the length of 'name'. It is NOT 32. We cannot use strlen() safely on 'name'
because it might not be null-terminated.
We need to do this:
---
int compare(char[] lhs, char[] rhs){
char* lptr = cast(char*)lhs;
char* rptr = cast(char*)rhs;
ulong len_lhs = strnlen(lptr, lhs.length);
ulong len_rhs = strnlen(rptr, rhs.length);
int comp = std.c.string.strncmp(lptr, rptr, min!(uint)(len_lhs, len_rhs));
if (comp) return comp;
if (len_lhs < len_rhs) return -1;
else if (len_lhs > len_rhs) return 1;
else return 0;
}
bool foo(Person* p){
return !compare(p.name, "Christopher");
}
---
Of course, std.string.strlen(char[] s) could also be useful. It should return
the length to the first null, or s.length. And my compare() function could be
there too. But those are not critical. strnlen() is. If it's not there,
people will use strlen() and cause buffer overflows.
From the Linux man page:
------------------------
SYNOPSIS
#include <string.h>
size_t strnlen(const char *s, size_t maxlen);
DESCRIPTION
The strnlen function returns the number of characters in the string
pointed to by s, not including the terminating '\0' character, but at
most maxlen. In doing this, strnlen looks only at the first maxlen
characters at s and never beyond s+maxlen.
RETURN VALUE
The strnlen function returns strlen(s), if that is less than maxlen, or
maxlen if there is no '\0' character among the first maxlen characters
pointed to by s.
CONFORMING TO
This function is a GNU extension.
-----------
And here is a simple implementation:
ulong strnlen(char* s, ulong maxlen){
for(ulong i=0; i<maxlen; ++i){
if (!s[i]) return i;
}
return maxlen;
}
[I used ulong, since a UNIX string could be an entire file.]
--
Jul 31 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1393
cdunn2001 gmail.com changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |RESOLVED
Resolution| |WORKSFORME
Derek Parnell suggested slicing as a solution:
import std.string;
/** Return a slice of the leftmost portion of 'x'
up to but not including the first 'c' */
string lefts(string x, char c)
{
int p;
p = std.string.find(x,c);
if (p < 0)
p = x.length;
return x[0..p];
}
int compare(string lhs, string rhs, char d = '\0')
{
return std.string.cmp( lefts(lhs,d), lefts(rhs,d) );
}
and use it like ...
char[32] NameA = '\0';
char[56] NameB = '\0';
NameA[0..5] = "derek";
NameB[0..7] = "parnell";
result = compare(NameA, NameB);
This is simple enough for me.
--
Aug 14 2007








d-bugmail puremagic.com