From: David M. <da...@as...> - 2010-12-19 07:57:25
|
On Dec 18, 2010, at 6:30 PM, Alan W. Irwin wrote: > On 2010-12-18 11:34-0800 David MacMahon wrote: > >> Am I missing something? > > See their example 1d where they check for truncation. Instead of > taking an error return at that point as they did in their sample code > the user could instead realloc if they liked as in your original > suggestion. Thanks, I did miss something! :-) The strlcpy model seems very similar to the WIN32 convention, only better in that it is more rigorously documented vis-a-vis NUL termination. > Just because it appears to be better documented on the > null-termination guarantee issue, I suggest we adopt the strlcpy > model. This gives the user in any language freedom to do anything > they like if the returned size (which never counts the null > terminator) is >= the value of n in the call. I agree! > For high-level languages > like Python where the uses don't have to worry about allocation, they > could just call the function again with n chosen to be the previous > returned value + 1. For high level languages like Python, any (re-)allocation could happen in the bindings and therefore be hidden from the end user. > Also, I don't think we should use the wrinkle present in > GetShortPathName of doing something special for the NULL buffer, > size=0 call. That does add a bit of convenience (but is not a > necessity) for languages such as C where the buffer is alloced > beforehand, I agree about not treating a NULL pointer as a special case, but strlcpy inherently treats size=0 as a special case (i.e. no NUL terminator). When size=0, strlcpy ignores the pointer and gives the same result as the WIN32 convention (though the WIN32 convention requires the pointer to be NULL). > but that wrinkle makes no sense for higher level languages > such as Python where the correctly sized buffer is created as needed. > For example, a typical Python call to plgfnam is > > fnam = plgfnam() > > With plgnfnam that would be changed to something like > > (needed_size, fnam) = plgnfnam(100) > if needed_size >= 100: > # Oops, 100 was too small. > fname = plgnfnam(needed_size+1)[1] This is an example of why I like to hand code language bindings. IMHO, the plgnfnam function, if it is even exposed in the scripting language, should take no arguments and always return a string containing the entire contents. Why make the user provide an initial guess? This requires them to check whether their guess was big enough and try again (without forgetting the "+1") if it wasn't. How inconvenient! Why not just do all of that for them inside the bindings for the high-level language's plgfnam call (which would call plgnfnam under the covers)? Dave |