adeyblue wrote:return all FBStrings descriptors by value - or
each take another pointer to a descriptor to fill in - or
Allocate() all FBStrings descriptors?
I've been down this road a few times now and I have a few ideas. I started implementation for var-len wstrings, but this should be dealt with first.
- on windows, ensure that allocate (aka malloc) is thread safe and uses the same process heap in DLL's - maybe some old versions of windows don't?
- caller is in control of descriptors - which could be allocated on the stack or on the heap (if that makes sense for the situation)
- avoid allocating descriptors on the heap (or more accurately, separately) if it isn't needed; which would allow arrays and structs containing string descriptors to be allocated fully in one allocation - except for actual string data.
- passing in an extra pointer to receive the result seems like the most straight forward approach.
- However, currently in fbc for procedures that return structs byval: if the struct is larger than 2 registers - which for string descriptors it is, then the caller will allocate a hidden variable and pass in a hidden pointer to the procedure to receive the result. Currently there's no way to expose the hidden pointer in fbc code. But if there was, we could act on the byval return result directly.
- Ideally, if the byval result is passed returned through a hidden pointer, then the pointer can also be passed as an argument to another string function and the temporary result is automatically cleaned up when the hidden variable goes out of scope. The compiler will know that it is temporary, so in the case of assignment or as another returned string, should be able to optimize by copying the descriptor only.
Maybe:
Code: Select all
function fb_StrMid FBCALL _
( _
byval src as const FBSTRING ptr, _
start as ssize_t, _
_len as ssize_t _
) as FBSTRING '' byval return through hidden pointer
'' not legal in current fbc - for concept only
#define dst *function
'' expect that dst descriptor is already initialized to zero
assert( dst <> NULL )
assert( dst.data = NULL )
assert( dst.len = 0 )
assert( dst.size = 0 )
dim as ssize_t src_len
if ( (src <> NULL) and (src->data <> NULL) andalso (FB_STRSIZE( src ) > 0) ) then
src_len = FB_STRSIZE( src )
if ( (start > 0) and (start <= src_len) and (_len <> 0) ) then
start -= 1
if ( _len < 0 ) then
_len = src_len
end if
if ( start + _len > src_len ) then
_len = src_len - start
end if
if( fb_hStrAlloc( dst, _len ) <> NULL ) then
FB_MEMCPY( dst->data, src->data + start, _len )
/' null term '/
dst->data[_len] = 0
else
'' memory error
end if
'' solve out to no-operation
return *function
end function