xref: /openbsd-src/gnu/usr.bin/perl/cpan/Win32API-File/buffers.h (revision b8851fcc53cbe24fd20b090f26dd149e353f6174)
1b39c5158Smillert /* buffers.h -- Version 1.11 */
2b39c5158Smillert 
3b39c5158Smillert /* The following abbreviations are used at start of parameter names
4b39c5158Smillert  * to indicate the type of data:
5b39c5158Smillert  *	s	string (char * or WCHAR *) [PV]
6b39c5158Smillert  *	sw	wide string (WCHAR *) [PV]
7b39c5158Smillert  *	p	pointer (usually to some structure) [PV]
8b39c5158Smillert  *	a	array (packed array as in C) (usually of some structure) [PV]
9b39c5158Smillert  *		    called a "vector" or "vect" in some places.
10b39c5158Smillert  *	n	generic number [IV, UV, or NV]
11b39c5158Smillert  *	iv	signed integral value [IV]
12b39c5158Smillert  *	u	unsigned integral value [UV]
13b39c5158Smillert  *	d	floating-point number (double) [NV]
14b39c5158Smillert  *	b	boolean (bool) [IV]
15b39c5158Smillert  *	c	count of items [UV]
16b39c5158Smillert  *	l	length (in bytes) [UV]
17b39c5158Smillert  *	lw	length in WCHARs [UV]
18b39c5158Smillert  *	h	a handle [IV]
19b39c5158Smillert  *	r	record (structure) [PV]
20b39c5158Smillert  *	sv	Perl scalar (s, i, u, d, n, or rv) [SV]
21b39c5158Smillert  *	rv	Perl reference (usually to scalar) [RV]
22b39c5158Smillert  *	hv	reference to Perl hash [HV]
23b39c5158Smillert  *	av	reference to Perl array [AV]
24b39c5158Smillert  *	cv	Perl code reference [PVCV]
25b39c5158Smillert  *
26b39c5158Smillert  * Unusual combined types:
27b39c5158Smillert  *	pp	single pointer (to non-Perl data) packed into string [PV]
28b39c5158Smillert  *	pap	vector of pointers (to non-Perl data) packed into string [PV]
29b39c5158Smillert  *
30b39c5158Smillert  * Whether a parameter is for input data, output data, or both is usually
31b39c5158Smillert  * not reflected by the data type prefix.  In cases where this is not
32b39c5158Smillert  * obvious nor reflected in the variable name proper, you can use
33b39c5158Smillert  * the following in front of the data type prefix:
34b39c5158Smillert  *	i	an input parameter given to API (usually omitted)
35b39c5158Smillert  *	o	an Output parameter taken from API
36b39c5158Smillert  *	io	Input given to API then overwritten with Output taken from API
37b39c5158Smillert  */
38b39c5158Smillert 
39b39c5158Smillert /* Buffer arguments are usually followed by an argument (or two) specifying
40b39c5158Smillert  * their size and/or returning the size of data written.  The size can be
41b39c5158Smillert  * measured in bytes ["lSize"] or in characters [for (char *) buffers such as
42b39c5158Smillert  * for *A() routines, these sizes are also called "lSize", but are called
43b39c5158Smillert  * "lwSize" for (WCHAR *) buffers, UNICODE strings, such as for *W() routines].
44b39c5158Smillert  *
45b39c5158Smillert  * Before calling the actual C function, you must make sure the Perl variable
46b39c5158Smillert  * actually has a big enough buffer allocated, and, if the user didn't want
47b39c5158Smillert  * to specify a buffer size, set the buffer size to be correct.  This is what
48b39c5158Smillert  * the grow_*() macros are for.  They also handle special meanings of the
49b39c5158Smillert  * buffer size argument [described below].
50b39c5158Smillert  *
51b39c5158Smillert  * Once the actual C function returns, you must set the Perl variable to know
52b39c5158Smillert  * the size of the written data.  This is what the trunc_*() macros are for.
53b39c5158Smillert  *
54b39c5158Smillert  * The size sometimes does and sometimes doesn't include the trailing '\0'
55898184e3Ssthen  * [or L'\0'], so we always add or subtract 1 in the appropriate places so
56b39c5158Smillert  * we don't care about this detail.
57b39c5158Smillert  *
58b39c5158Smillert  * A call may  1) request a pointer to the buffer size which means that
59b39c5158Smillert  * the buffer size will be overwritten with the size of the data written;
60b39c5158Smillert  * 2) have an extra argument which is a pointer to the place to write the
61b39c5158Smillert  * size of the written data;  3) provide the size of the written data in
62b39c5158Smillert  * the function's return value;  4) format the data so that the length
63b39c5158Smillert  * can be determined by examining the data [such as with '\0'-terminated
64b39c5158Smillert  * strings];  or  5) write fixed-length data [usually sizeof(STRUCT)].
65b39c5158Smillert  * This obviously determines what you should use in the trunc_*() macro
66b39c5158Smillert  # to specify the size of the output value.
67b39c5158Smillert  *
68b39c5158Smillert  * The user can pass in an empty list reference, C<[]>, to indicate C<NULL>
69b39c5158Smillert  * for the pointer to the buffer which means that they don't want that data.
70b39c5158Smillert  *
71b39c5158Smillert  * The user can pass in C<[]> or C<0> to indicate that they don't care about
72b39c5158Smillert  * the buffer size [we aren't programming in C here, after all] and just try
73898184e3Ssthen  * to get the data.  This will work if either the buffer already allocated for
74b39c5158Smillert  * the SV [scalar value] is large enough to hold the data or the API provides
75b39c5158Smillert  * an easy way to determine the required size [and the XS code uses it].
76b39c5158Smillert  *
77b39c5158Smillert  * If the user passes in a numeric value for a buffer size, then the XS
78b39c5158Smillert  * code makes sure that the buffer is at least large enough to hold a value
79b39c5158Smillert  * of that size and then passes in how large the buffer is.  So the buffer
80b39c5158Smillert  * size passed to the API call is the larger of the size requested by the
81*b8851fccSafresh1  * user and the size of the buffer already allocated to the SV.
82b39c5158Smillert  *
83b39c5158Smillert  * The user can also pass in a string consisting of a leading "=" followed
84b39c5158Smillert  * by digits for a buffer size.  This means just use the size specified after
85b39c5158Smillert  * the equals sign, even if the allocated buffer is larger.  The XS code will
86b39c5158Smillert  * still allocate a large enough buffer before the first call.
87b39c5158Smillert  *
88b39c5158Smillert  * If the function is nice enough to tell us that a buffer was too small
89b39c5158Smillert  * [usually via ERROR_MORE_DATA] _and_ how large the buffer needs to be,
90b39c5158Smillert  * then the XS code should enlarge the buffer(s) and repeat the call [once].
91b39c5158Smillert  * This resizing is _not_ done for buffers whose size was specified with a
92b39c5158Smillert  * leading "=".
93b39c5158Smillert  *
94b39c5158Smillert  * Only grow_buf() and perhaps trunc_buf() can be used in a typemap file.
95b39c5158Smillert  * The other macros would be used in the parameter declarations or INPUT:
96b39c5158Smillert  * section [grow_*()], the INIT: section [init_*()], or the OUTPUT: section
97b39c5158Smillert  * [trunc_*()].
98b39c5158Smillert  *
99898184e3Ssthen  * Buffer arguments should be initialised with C<= NO_INIT> [or C<= NULL;>].
100b39c5158Smillert  *
101b39c5158Smillert  * See also the F<typemap> file.  C<oDWORD>, for example, is for an output-
102b39c5158Smillert  * only parameter of type C<DWORD> and you should simply C<#define> it to be
103b39c5158Smillert  * C<DWORD>.  In F<typemap>, C<oDWORD> is treated differently than C<DWORD>
104b39c5158Smillert  * in two ways.
105b39c5158Smillert  *
106b39c5158Smillert  * First, if C<undef> is passed in, a C<DWORD> could generate a warning
107b39c5158Smillert  * when it gets converted to 0 while C<oDWORD> will never generate such a
108b39c5158Smillert  * warning for C<undef>.  This first difference doesn't apply if specific
109b39c5158Smillert  * initialization is specified for the variable, as in C<= init_buf_l($var);>.
110b39c5158Smillert  * In particular, the init_*() macros also convert C<undef> to 0 without
111b39c5158Smillert  * ever producing a warning.
112b39c5158Smillert  *
113b39c5158Smillert  * Second, passing in a read-only SV for a C<oDWORD> parameter will generate
114b39c5158Smillert  * a fatal error on output when we try to update the SV.  For C<DWORD>, we
115b39c5158Smillert  * won't update a read-only SV since passing in a literal constant for a
116b39c5158Smillert  * buffer size is a useful thing to do even though it prevents us from
117b39c5158Smillert  * returning the size of data written via that SV.  Since we should use a
118b39c5158Smillert  * trunc_*() macro to output the actual data, the user should be able to
119b39c5158Smillert  * determine the size of data written based on the size of the scalar we
120b39c5158Smillert  * output anyway.
121b39c5158Smillert  *
122898184e3Ssthen  * This second difference doesn't apply unless the parameter is listed in
123b39c5158Smillert  * the OUTPUT: section without specific output instructions.  We define
124898184e3Ssthen  * no macros for outputting buffer length parameters so be careful to use
125b39c5158Smillert  * C<oDWORD> [for example] for them if and only if they are output-only.
126b39c5158Smillert  *
127b39c5158Smillert  * Note that C<oDWORD> is the same as C<DWORD> in that, if a defined value
128b39c5158Smillert  * is passed in, it is used [and can generate a warning if the value is
129b39c5158Smillert  * "not numeric"].  So although C<oDWORD> is for output-only parameters,
130b39c5158Smillert  * we still initialize the C variable before calling the API.  This is good
131b39c5158Smillert  * in case the parameter isn't always strictly output-only due to upgrades,
132b39c5158Smillert  * bugs, etc.
133b39c5158Smillert  *
134b39c5158Smillert  * Here is a made-up example that shows several cases:
135b39c5158Smillert  *
136b39c5158Smillert  * # Actual GetDataW() returns length of data written to ioswName, not bool.
137b39c5158Smillert  * bool
138b39c5158Smillert  * GetDataW( ioswName, ilwName, oswText, iolwText, opJunk, opRec, ilRec, olRec )
139b39c5158Smillert  *	WCHAR *	ioswName	= NO_INIT
140b39c5158Smillert  *	DWORD	ilwName		= NO_INIT
141b39c5158Smillert  *	WCHAR *	oswText		= NO_INIT
142b39c5158Smillert  *	DWORD	&iolwText	= init_buf_l($arg);
143b39c5158Smillert  *	void *	opJunk		= NO_INIT
144b39c5158Smillert  *	BYTE *	opRec		= NO_INIT
145b39c5158Smillert  *	DWORD	ilRec		= init_buf_l($arg);
146b39c5158Smillert  *	oDWORD	&olRec
147b39c5158Smillert  * PREINIT:
148b39c5158Smillert  *	DWORD	olwName;
149b39c5158Smillert  * INIT:
150b39c5158Smillert  *	grow_buf_lw( ioswName,ST(0), ilwName,ST(1) );
151b39c5158Smillert  *	grow_buf_lw( oswText,ST(2), iolwText,ST(3) );
152b39c5158Smillert  *	grow_buf_typ( opJunk,ST(4),void *, LONG_STRUCT_TYPEDEF );
153b39c5158Smillert  *	grow_buf_l( opRec,ST(5),BYTE *, ilRec,ST(6) );
154b39c5158Smillert  * CODE:
155b39c5158Smillert  *	olwName= GetDataW( ioswName, ilwName, oswText, &iolwText,
156b39c5158Smillert  *			   (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec );
157b39c5158Smillert  *	if(  0 == olwName  &&  ERROR_MORE_DATA == GetLastError()
158b39c5158Smillert  *	 &&  ( autosize(ST(1)) || autosize(ST(3)) || autosize(ST(6)) )  ) {
159b39c5158Smillert  *	    if(  autosize(ST(1))  )
160b39c5158Smillert  *		grow_buf_lw( ioswName,ST(0), ilwName,ST(1) );
161b39c5158Smillert  *	    if(  autosize(ST(3))  )
162b39c5158Smillert  *		grow_buf_lw( oswText,ST(2), iolwText,ST(3) );
163b39c5158Smillert  *	    if(  autosize(ST(6))  )
164b39c5158Smillert  *		grow_buf_l( opRec,ST(5),BYTE *, iolRec,ST(6) );
165b39c5158Smillert  *	    olwName= GetDataW( ioswName, ilwName, oswText, &iolwText,
166b39c5158Smillert  *			       (LONG_STRUCT_TYPEDEF *)opJunk, opRec, &iolRec );
167b39c5158Smillert  *	}
168b39c5158Smillert  *	RETVAL=  0 != olwName;
169b39c5158Smillert  * OUTPUT:
170b39c5158Smillert  *	RETVAL
171b39c5158Smillert  *	ioswName	trunc_buf_lw( RETVAL, ioswName,ST(0), olwName );
172b39c5158Smillert  *	oswText		trunc_buf_lw( RETVAL, oswText,ST(2), iolwText );
173b39c5158Smillert  *	iolwText
174b39c5158Smillert  *	opJunk		trunc_buf_typ(RETVAL,opJunk,ST(4),LONG_STRUCT_TYPEDEF);
175b39c5158Smillert  *	opRec		trunc_buf_l( RETVAL, opRec,ST(5), olRec );
176b39c5158Smillert  *	olRec
177b39c5158Smillert  *
178b39c5158Smillert  * The above example would be more complex and less efficient if we used
179b39c5158Smillert  * C<DWORD * iolwText> in place of C<DWORD  &iolwText>.  The only possible
180b39c5158Smillert  * advantage would be that C<NULL> would be passed in for C<iolwText> if
181b39c5158Smillert  * _both_ C<$oswText> and C<$iolwText> were specified as C<[]>.  The *_pl*()
182b39c5158Smillert  * macros are defined [and C<DWORD *> specified in F<typemap>] so we can
183b39c5158Smillert  * handle those cases but it is usually better to use the *_l*() macros
184b39c5158Smillert  * instead by specifying C<&> instead of C<*>.  Using C<&> instead of C<*>
185b39c5158Smillert  * is usually better when dealing with scalars, even if they aren't buffer
186b39c5158Smillert  * sizes.  But you must use C<*> if it is important for that parameter to
187b39c5158Smillert  * be able to pass C<NULL> to the underlying API.
188b39c5158Smillert  *
189b39c5158Smillert  * In Win32API::, we try to use C<*> for buffer sizes of optional buffers
190b39c5158Smillert  * and C<&> for buffer sizes of required buffers.
191b39c5158Smillert  *
192b39c5158Smillert  * For parameters that are pointers to things other than buffers or buffer
193b39c5158Smillert  * sizes, we use C<*> for "important" parameters [so that using C<[]>
194b39c5158Smillert  * generates an error rather than fetching the value and just throwing it
195b39c5158Smillert  * away], and for optional parameters [in case specifying C<NULL> is or
196b39c5158Smillert  * becomes important].  Otherwise we use C<&> [for "unimportant" but
197b39c5158Smillert  * required parameters] so the user can specify C<[]> if they don't care
198b39c5158Smillert  * about it.  The output handle of an "open" routine is "important".
199b39c5158Smillert  */
200b39c5158Smillert 
201b39c5158Smillert #ifndef Debug
202b39c5158Smillert # define	Debug(list)	/*Nothing*/
203b39c5158Smillert #endif
204b39c5158Smillert 
205b39c5158Smillert /*#ifndef CAST
206b39c5158Smillert  *# ifdef __cplusplus
207b39c5158Smillert  *#  define   CAST(type,expr)	static_cast<type>(expr)
208b39c5158Smillert  *# else*/
209b39c5158Smillert #  define   CAST(type,expr)	(type)(expr)
210b39c5158Smillert /*# endif
211b39c5158Smillert  *#endif*/
212b39c5158Smillert 
213b39c5158Smillert /* Is an argument C<[]>, meaning we should pass C<NULL>? */
214b39c5158Smillert #define null_arg(sv)	(  SvROK(sv)  &&  SVt_PVAV == SvTYPE(SvRV(sv))	\
215b39c5158Smillert 			   &&  -1 == av_len((AV*)SvRV(sv))  )
216b39c5158Smillert 
217b39c5158Smillert #define PV_or_null(sv)	( null_arg(sv) ? NULL : SvPV_nolen(sv) )
218b39c5158Smillert 
219b39c5158Smillert /* Minimum buffer size to use when no buffer existed: */
220b39c5158Smillert #define MIN_GROW_SIZE	128
221b39c5158Smillert 
222b39c5158Smillert #ifdef Debug
223b39c5158Smillert /* Used in Debug() messages to show which macro call is involved: */
224b39c5158Smillert #define string(arg) #arg
225b39c5158Smillert #endif
226b39c5158Smillert 
227b39c5158Smillert /* Simplify using SvGROW() for byte-sized buffers: */
228b39c5158Smillert #define lSvGROW(sv,n)	SvGROW( sv, 0==(n) ? MIN_GROW_SIZE : (n)+1 )
229b39c5158Smillert 
230b39c5158Smillert /* Simplify using SvGROW() for WCHAR-sized buffers: */
231b39c5158Smillert #define lwSvGROW(sv,n)	CAST( WCHAR *,		\
232b39c5158Smillert 	SvGROW( sv, sizeof(WCHAR)*( 0==(n) ? MIN_GROW_SIZE : (n)+1 ) ) )
233b39c5158Smillert 
234b39c5158Smillert /* Whether the buffer size we got lets us change what buffer size we use: */
235b39c5158Smillert #define autosize(sv)	(!(  SvOK(sv)  &&  ! SvROK(sv)		\
236b39c5158Smillert 			 &&  SvPV_nolen(sv)  &&  '=' == *SvPV_nolen(sv)  ))
237b39c5158Smillert 
238b39c5158Smillert /* Get the IV/UV for a parameter that might be C<[]> or C<undef>: */
239b39c5158Smillert #define optIV(sv)	( null_arg(sv) ? 0 : !SvOK(sv) ? 0 : SvIV(sv) )
240b39c5158Smillert #define optUV(sv)	( null_arg(sv) ? 0 : !SvOK(sv) ? 0 : SvUV(sv) )
241b39c5158Smillert 
242b39c5158Smillert /* Allocate temporary storage that will automatically be freed later: */
243b39c5158Smillert #ifndef TempAlloc	/* Can be C<#define>d to be C<_alloca>, for example */
244b39c5158Smillert # define TempAlloc( size )	sv_grow( sv_newmortal(), size )
245b39c5158Smillert #endif
246b39c5158Smillert 
247b39c5158Smillert /* Initialize a buffer size argument of type (DWORD *): */
248b39c5158Smillert #define init_buf_pl( plSize, svSize, tpSize )		STMT_START {	\
249b39c5158Smillert 	if(  null_arg(svSize)  )					\
250b39c5158Smillert 	    plSize= NULL;						\
251b39c5158Smillert 	else {								\
252b39c5158Smillert 	    STRLEN n_a;							\
253b39c5158Smillert 	    *( plSize= CAST( tpSize, TempAlloc(sizeof(*plSize)) ) )=	\
254b39c5158Smillert 	      autosize(svSize) ? optUV(svSize)				\
255b39c5158Smillert 	        : strtoul( 1+SvPV(svSize,n_a), NULL, 10 );		\
256b39c5158Smillert 	} } STMT_END
257b39c5158Smillert /* In INPUT section put ": init_buf_pl($var,$arg,$type);" after var name. */
258b39c5158Smillert 
259b39c5158Smillert /* Initialize a buffer size argument of type DWORD: */
260b39c5158Smillert #define init_buf_l( svSize )						\
261b39c5158Smillert 	(  null_arg(svSize) ? 0 : autosize(svSize) ? optUV(svSize)	\
262b39c5158Smillert 	   : strtoul( 1+SvPV_nolen(svSize), NULL, 10 )  )
263b39c5158Smillert /* In INPUT section put "= init_buf_l($arg);" after variable name. */
264b39c5158Smillert 
265b39c5158Smillert /* Lengths in WCHARs are initialized the same as lengths in bytes: */
266b39c5158Smillert #define init_buf_plw	init_buf_pl
267b39c5158Smillert #define init_buf_lw	init_buf_l
268b39c5158Smillert 
269b39c5158Smillert /* grow_buf_pl() and grow_buf_plw() are included so you can define
270b39c5158Smillert  * parameters of type C<DWORD *>, for example.  In practice, it is
271b39c5158Smillert  * usually better to define such parameters as "DWORD &". */
272b39c5158Smillert 
273b39c5158Smillert /* Grow a buffer where we have a pointer to its size in bytes: */
274b39c5158Smillert #define	grow_buf_pl( sBuf,svBuf,tpBuf, plSize,svSize,tpSize ) STMT_START { \
275b39c5158Smillert 	Debug(("grow_buf_pl( %s==0x%lX,[%s:%ld/%ld, %s==0x%lX:%ld,[%s )\n",\
276b39c5158Smillert 	  string(sBuf),sBuf,strchr(string(svBuf),'('),SvPOK(svBuf)?	\
277b39c5158Smillert 	  SvCUR(svBuf):-1,SvPOK(svBuf)?SvLEN(svBuf):-1,string(plSize),	\
278b39c5158Smillert 	  plSize,plSize?*plSize:-1,strchr(string(svSize),'(')));	\
279b39c5158Smillert 	if(  null_arg(svBuf)  ) {					\
280b39c5158Smillert 	    sBuf= NULL;							\
281b39c5158Smillert 	} else {							\
282b39c5158Smillert 	    STRLEN n_a;							\
283b39c5158Smillert 	    if(  NULL == plSize  )					\
284b39c5158Smillert 		*( plSize= CAST(tpSize,TempAlloc(sizeof(*plSize))) )= 0;\
285b39c5158Smillert 	    if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);		\
286b39c5158Smillert 	    (void) SvPV_force( svBuf, n_a );				\
287b39c5158Smillert 	    sBuf= CAST( tpBuf, lSvGROW( svBuf, *plSize ) );		\
288b39c5158Smillert 	    if(  autosize(svSize)  )   *plSize= SvLEN(svBuf) - 1;	\
289b39c5158Smillert 	    Debug(("more buf_pl( %s==0x%lX,[%s:%ld/%ld, %s==0x%lX:%ld,[%s )\n",\
290b39c5158Smillert 	      string(sBuf),sBuf,strchr(string(svBuf),'('),SvPOK(svBuf)?	\
291b39c5158Smillert 	      SvCUR(svBuf):-1,SvPOK(svBuf)?SvLEN(svBuf):-1,string(plSize),\
292b39c5158Smillert 	      plSize,plSize?*plSize:-1,strchr(string(svSize),'(')));	\
293b39c5158Smillert 	} } STMT_END
294b39c5158Smillert 
295b39c5158Smillert /* Grow a buffer where we have a pointer to its size in WCHARs: */
296b39c5158Smillert #define	grow_buf_plw( sBuf,svBuf, plwSize,svSize,tpSize ) STMT_START {	\
297b39c5158Smillert 	if(  null_arg(svBuf)  ) {					\
298b39c5158Smillert 	    sBuf= NULL;							\
299b39c5158Smillert 	} else {							\
300b39c5158Smillert 	    STRLEN n_a;							\
301b39c5158Smillert 	    if(  NULL == plwSize  )					\
302b39c5158Smillert 		*( plwSize= CAST(tpSize,TempAlloc(sizeof(*plwSize))) )= 0;\
303b39c5158Smillert 	    if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);		\
304b39c5158Smillert 	    (void) SvPV_force( svBuf, n_a );				\
305b39c5158Smillert 	    sBuf= lwSvGROW( svBuf, *plwSize );				\
306b39c5158Smillert 	    if(  autosize(svSize)  )					\
307b39c5158Smillert 		*plwSize= SvLEN(svBuf)/sizeof(WCHAR) - 1;		\
308b39c5158Smillert 	} } STMT_END
309b39c5158Smillert 
310b39c5158Smillert /* Grow a buffer where we have its size in bytes: */
311b39c5158Smillert #define	grow_buf_l( sBuf,svBuf,tpBuf, lSize,svSize )	STMT_START {	\
312b39c5158Smillert 	if(  null_arg(svBuf)  ) {					\
313b39c5158Smillert 	    sBuf= NULL;							\
314b39c5158Smillert 	} else {							\
315b39c5158Smillert 	    STRLEN n_a;							\
316b39c5158Smillert 	    if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);		\
317b39c5158Smillert 	    (void) SvPV_force( svBuf, n_a );				\
318b39c5158Smillert 	    sBuf= CAST( tpBuf, lSvGROW( svBuf, lSize ) );		\
319b39c5158Smillert 	    if(  autosize(svSize)  )   lSize= SvLEN(svBuf) - 1;		\
320b39c5158Smillert 	} } STMT_END
321b39c5158Smillert 
322b39c5158Smillert /* Grow a buffer where we have its size in WCHARs: */
323b39c5158Smillert #define	grow_buf_lw( swBuf,svBuf, lwSize,svSize )	STMT_START {	\
324b39c5158Smillert 	if(  null_arg(svBuf)  ) {					\
325b39c5158Smillert 	    swBuf= NULL;						\
326b39c5158Smillert 	} else {							\
327b39c5158Smillert 	    STRLEN n_a;							\
328b39c5158Smillert 	    if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);		\
329b39c5158Smillert 	    (void) SvPV_force( svBuf, n_a );				\
330b39c5158Smillert 	    swBuf= lwSvGROW( svBuf, lwSize );				\
331b39c5158Smillert 	    if(  autosize(svSize)  )					\
332b39c5158Smillert 		lwSize= SvLEN(svBuf)/sizeof(WCHAR) - 1;			\
333b39c5158Smillert 	} } STMT_END
334b39c5158Smillert 
335b39c5158Smillert /* Grow a buffer that contains the declared fixed data type: */
336b39c5158Smillert #define	grow_buf( pBuf,svBuf, tpBuf )			STMT_START {	\
337b39c5158Smillert 	if(  null_arg(svBuf)  ) {					\
338b39c5158Smillert 	    pBuf= NULL;							\
339b39c5158Smillert 	} else {							\
340b39c5158Smillert 	    STRLEN n_a;							\
341b39c5158Smillert 	    if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);		\
342b39c5158Smillert 	    (void) SvPV_force( svBuf, n_a );				\
343b39c5158Smillert 	    pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(*pBuf) ) );	\
344b39c5158Smillert 	} } STMT_END
345b39c5158Smillert 
346b39c5158Smillert /* Grow a buffer that contains a fixed data type other than that declared: */
347b39c5158Smillert #define	grow_buf_typ( pBuf,svBuf,tpBuf, Type )		STMT_START {	\
348b39c5158Smillert 	if(  null_arg(svBuf)  ) {					\
349b39c5158Smillert 	    pBuf= NULL;							\
350b39c5158Smillert 	} else {							\
351b39c5158Smillert 	    STRLEN n_a;							\
352b39c5158Smillert 	    if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);		\
353b39c5158Smillert 	    (void) SvPV_force( svBuf, n_a );				\
354b39c5158Smillert 	    pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(Type) ) );	\
355b39c5158Smillert 	} } STMT_END
356b39c5158Smillert 
357b39c5158Smillert /* Grow a buffer that contains a list of items of the declared data type: */
358b39c5158Smillert #define	grow_vect( pBuf,svBuf,tpBuf, cItems )		STMT_START {	\
359b39c5158Smillert 	if(  null_arg(svBuf)  ) {					\
360b39c5158Smillert 	    pBuf= NULL;							\
361b39c5158Smillert 	} else {							\
362b39c5158Smillert 	    STRLEN n_a;							\
363b39c5158Smillert 	    if(  ! SvOK(svBuf)  )    sv_setpvn(svBuf,"",0);		\
364b39c5158Smillert 	    (void) SvPV_force( svBuf, n_a );				\
365b39c5158Smillert 	    pBuf= CAST( tpBuf, SvGROW( svBuf, sizeof(*pBuf)*cItems ) );	\
366b39c5158Smillert 	} } STMT_END
367b39c5158Smillert 
368b39c5158Smillert /* If call succeeded, set data length to returned length (in bytes): */
369b39c5158Smillert #define	trunc_buf_l( bOkay, sBuf,svBuf, lSize )		STMT_START {	\
370b39c5158Smillert 	if(  bOkay  &&  NULL != sBuf  ) {				\
371b39c5158Smillert 	    SvPOK_only( svBuf );					\
372b39c5158Smillert 	    SvCUR_set( svBuf, lSize );					\
373b39c5158Smillert 	} } STMT_END
374b39c5158Smillert 
375898184e3Ssthen /* Same as above except we have a pointer to the returned length: */
376b39c5158Smillert #define	trunc_buf_pl( bOkay, sBuf,svBuf, plSize )			\
377b39c5158Smillert 	trunc_buf_l( bOkay, sBuf,svBuf, *plSize )
378b39c5158Smillert 
379b39c5158Smillert /* If call succeeded, set data length to returned length (in WCHARs): */
380b39c5158Smillert #define	trunc_buf_lw( bOkay, sBuf,svBuf, lwSize )	STMT_START {	\
381b39c5158Smillert 	if(  bOkay  &&  NULL != sBuf  ) {				\
382b39c5158Smillert 	    SvPOK_only( svBuf );					\
383b39c5158Smillert 	    SvCUR_set( svBuf, (lwSize)*sizeof(WCHAR) );			\
384b39c5158Smillert 	} } STMT_END
385b39c5158Smillert 
386898184e3Ssthen /* Same as above except we have a pointer to the returned length: */
387b39c5158Smillert #define	trunc_buf_plw( bOkay, swBuf,svBuf, plwSize )			\
388b39c5158Smillert 	trunc_buf_lw( bOkay, swBuf,svBuf, *plwSize )
389b39c5158Smillert 
390b39c5158Smillert /* Set data length for a buffer that contains the declared fixed data type: */
391b39c5158Smillert #define	trunc_buf( bOkay, pBuf,svBuf )			STMT_START {	\
392b39c5158Smillert 	if(  bOkay  &&  NULL != pBuf  ) {				\
393b39c5158Smillert 	    SvPOK_only( svBuf );					\
394b39c5158Smillert 	    SvCUR_set( svBuf, sizeof(*pBuf) );				\
395b39c5158Smillert 	} } STMT_END
396b39c5158Smillert 
397b39c5158Smillert /* Set data length for a buffer that contains some other fixed data type: */
398b39c5158Smillert #define	trunc_buf_typ( bOkay, pBuf,svBuf, Type )	STMT_START {	\
399b39c5158Smillert 	if(  bOkay  &&  NULL != pBuf  ) {				\
400b39c5158Smillert 	    SvPOK_only( svBuf );					\
401b39c5158Smillert 	    SvCUR_set( svBuf, sizeof(Type) );				\
402b39c5158Smillert 	} } STMT_END
403b39c5158Smillert 
404b39c5158Smillert /* Set length for buffer that contains list of items of the declared type: */
405b39c5158Smillert #define	trunc_vect( bOkay, pBuf,svBuf, cItems )		STMT_START {	\
406b39c5158Smillert 	if(  bOkay  &&  NULL != pBuf  ) {				\
407b39c5158Smillert 	    SvPOK_only( svBuf );					\
408b39c5158Smillert 	    SvCUR_set( svBuf, sizeof(*pBuf)*cItems );			\
409b39c5158Smillert 	} } STMT_END
410b39c5158Smillert 
411b39c5158Smillert /* Set data length for a buffer where a '\0'-terminate string was stored: */
412b39c5158Smillert #define	trunc_buf_z( bOkay, sBuf,svBuf )		STMT_START {	\
413b39c5158Smillert 	if(  bOkay  &&  NULL != sBuf  ) {				\
414b39c5158Smillert 	    SvPOK_only( svBuf );					\
415b39c5158Smillert 	    SvCUR_set( svBuf, strlen(sBuf) );				\
416b39c5158Smillert 	} } STMT_END
417b39c5158Smillert 
418b39c5158Smillert /* Set data length for a buffer where a L'\0'-terminate string was stored: */
419b39c5158Smillert #define	trunc_buf_zw( bOkay, sBuf,svBuf )		STMT_START {	\
420b39c5158Smillert 	if(  bOkay  &&  NULL != sBuf  ) {				\
421b39c5158Smillert 	    SvPOK_only( svBuf );					\
422b39c5158Smillert 	    SvCUR_set( svBuf, wcslen(sBuf)*sizeof(WCHAR) );		\
423b39c5158Smillert 	} } STMT_END
424