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