mbgtools-lx  4.2.8
str_util.c
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: str_util.c 1.5 2018/08/23 13:07:16 martin REL_M $
5  *
6  * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
7  *
8  * Description:
9  * Meinberg Library module providing portable, safe string functions.
10  *
11  * -----------------------------------------------------------------------
12  * $Log: str_util.c $
13  * Revision 1.5 2018/08/23 13:07:16 martin
14  * Moved the snprintf() safety checks to new inline functions that
15  * can also be used called from specific kernel mode functions.
16  * Unified variable naming.
17  * More common __attribute__ syntax.
18  * Revision 1.4 2018/06/25 13:22:42 martin
19  * Many functios return int rather than size_t, like standard
20  * library functions.
21  * do_str_copy_safe() now returns the number of chars copied.
22  * Revision 1.3 2016/10/24 08:10:04 thomas-b
23  * Fixed counter var check in mbg_memcpy_reversed
24  * Revision 1.2 2016/08/05 12:31:04 martin
25  * New functions mbg_memcpy() and mbg_memcpy_reversed().
26  * Moved string trim functions from cfg_util module here.
27  * Fixed some compiler warnings.
28  * Revision 1.1 2015/08/25 15:57:21 martin
29  * Initial revision.
30  *
31  **************************************************************************/
32 
33 #define _STR_UTIL
34  #include <str_util.h>
35 #undef _STR_UTIL
36 
37 #include <stdio.h>
38 #include <string.h>
39 
40 
41 #if defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI )
42  #define mbg_vsnprintf _vsnprintf
43 #else
44  #define mbg_vsnprintf vsnprintf
45 #endif
46 
47 
48 #if defined( MBG_TGT_DOS )
49 
50 static /*HDR*/
51 // Under DOS we use the Borland C/C++ v3.1 compiler by default, which
52 // doesn't provide a vsnprintf() function, so we use a simple replacement
53 // here. Since we share most of the source code between several target
54 // systems we assume that if our code works properly for other targets
55 // which really provide a vsnprintf() function then it also works properly
56 // under DOS. ;-)
57 int vsnprintf( char *s, size_t max_len, const char *fmt, va_list args )
58 {
59  (void) max_len; // quiet compiler warning "not used"
60 
61  return vsprintf( s, fmt, args );
62 
63 } // vsnprintf
64 
65 #endif
66 
67 
68 
69 /*HDR*/
120 __attribute__( ( format( printf, 3, 0 ) ) )
121 int vsnprintf_safe( char *s, size_t max_len, const char *fmt, va_list args )
122 {
123  size_t n;
124 
125  if ( !mbg_buffer_specs_valid( s, max_len ) )
126  return 0; // nothing to do anyway
127 
128  n = mbg_vsnprintf( s, max_len, fmt, args );
129 
130  // Do some common checks to avoid subsequent buffer overflows, etc.
131  return mbg_chk_snprint_results( n, s, max_len );
132 
133 } // vsnprintf_safe
134 
135 
136 
137 /*HDR*/
155 __attribute__( ( format( printf, 3, 4 ) ) )
156 int snprintf_safe( char *s, size_t max_len, const char * fmt, ... )
157 {
158  va_list args;
159  int len;
160 
161  va_start( args, fmt );
162  len = vsnprintf_safe( s, max_len, fmt, args );
163  va_end( args);
164 
165  return len;
166 
167 } // snprintf_safe
168 
169 
170 
171 static __mbg_inline
172 /* (explicitly excluded from doxygen)
173  * @brief A portable, safe implementation of a copy function
174  *
175  * This is the basic function used to implemment ::strncpy_safe and
176  * ::sn_cpy_safe. This function takes care that the copied string
177  * is always terminated by 0, but any remaining buffer space
178  * is *not* filled up with '0' characters.
179  *
180  * @param[out] dst Pointer to the output buffer
181  * @param[in] src Pointer to the input buffer
182  * @param[in] n Number of characters to copy at most
183  * @param[in,out] p_i Pointer to a counter variable
184  *
185  * @return The number of characters copied.
186  *
187  * @see ::vsnprintf_safe
188  * @see ::snprintf_safe
189  * @see ::strncpy_safe
190  * @see ::sn_cpy_str_safe
191  * @see ::sn_cpy_char_safe
192  */
193 size_t do_str_copy_safe( char *dst, const char *src, size_t n )
194 {
195  size_t i = 0;
196 
197  if ( n > 0 )
198  {
199  for (;;)
200  {
201  *dst = *src;
202 
203  if ( *dst == 0 )
204  break; // just copied the terminating 0, done
205 
206  if ( --n == 0 ) // no more space left in buffer
207  {
208  *dst = 0; // force terminating 0
209  break;
210  }
211 
212  i++; // count normal characters
213  src++;
214  dst++;
215  }
216  }
217 
218  return i;
219 
220 } // do_str_copy_safe
221 
222 
223 
224 /*HDR*/
247 char *strncpy_safe( char *dst, const char *src, size_t max_len )
248 {
249  do_str_copy_safe( dst, src, max_len );
250 
251  return dst;
252 
253 } // strncpy_safe
254 
255 
256 
257 /*HDR*/
276 int sn_cpy_str_safe( char *dst, size_t max_len, const char *src )
277 {
278  size_t n = do_str_copy_safe( dst, src, max_len );
279 
280  return _int_from_size_t( n );
281 
282 } // sn_cpy_str_safe
283 
284 
285 
286 /*HDR*/
306 int sn_cpy_char_safe( char *dst, size_t max_len, char c )
307 {
308  size_t n;
309  char tmp_str[2];
310 
311  tmp_str[0] = c;
312  tmp_str[1] = 0;
313 
314  n = do_str_copy_safe( dst, tmp_str, max_len );
315 
316  return _int_from_size_t( n );
317 
318 } // sn_cpy_char_safe
319 
320 
321 
322 /*HDR*/
329 {
330  char *cp;
331 
332  // set all trailing spaces to 0
333  for ( cp = &s[strlen( s )]; cp > s; )
334  {
335  --cp;
336 
337  if ( *cp >= ' ' )
338  break;
339 
340  *cp = 0;
341  }
342 
343 } // trim_trailing_whitespace
344 
345 
346 
347 /*HDR*/
353 void trim_leading_whitespace( char *s )
354 {
355  char *srcp;
356  char *dstp;
357 
358  // Search the first non-space character.
359  for ( srcp = s; *srcp; srcp++ )
360  if ( *srcp > ' ' )
361  break;
362 
363  // If there are leading spaces then srcp now
364  // points behind the beginning of the string,
365  // otherwise there's nothing to do.
366  if ( srcp > s )
367  {
368  // Copy the remaining string.
369  dstp = s;
370 
371  while ( *srcp )
372  *dstp++ = *srcp++;
373 
374  *dstp = 0;
375  }
376 
377 } // trim_leading_whitespace
378 
379 
380 
381 /*HDR*/
387 void trim_whitespace( char *s )
388 {
391 
392 } // trim_whitespace
393 
394 
395 
396 /*HDR*/
412 void mbg_memcpy( void *dst, const void *src, size_t n_bytes )
413 {
414  uint8_t *dstp = (uint8_t *) dst;
415  uint8_t *srcp = (uint8_t *) src;
416 
417  while ( n_bytes-- )
418  *dstp++ = *srcp++;
419 
420 } // mbg_memcpy
421 
422 
423 
424 /*HDR*/
438 void mbg_memcpy_reversed( void *dst, const void *src, size_t n_bytes )
439 {
440  if ( n_bytes ) // just to be sure it isn't 0
441  {
442  uint8_t *dstp = ( (uint8_t *) dst ) + n_bytes;
443  uint8_t *srcp = ( (uint8_t *) src ) + n_bytes;
444 
445  while ( n_bytes-- )
446  *(--dstp) = *(--srcp);
447  }
448 
449 } // mbg_memcpy_reversed
450 
451 
452 
char * strncpy_safe(char *dst, const char *src, size_t max_len)
A portable, safe implementation of strncpy()
Definition: str_util.c:247
static __mbg_inline size_t do_str_copy_safe(char *dst, const char *src, size_t n)
Definition: str_util.c:193
#define _int_from_size_t(_n)
Definition: words.h:662
int sn_cpy_str_safe(char *dst, size_t max_len, const char *src)
A function to copy a string safely, returning the number of characters copied.
Definition: str_util.c:276
#define mbg_vsnprintf
Definition: str_util.c:44
int vsnprintf_safe(char *s, size_t max_len, const char *fmt, va_list args)
A portable, safe implementation of vsnprintf()
Definition: str_util.c:121
unsigned char uint8_t
Definition: words.h:210
void trim_trailing_whitespace(char *s)
Trim whitespace at the end of a string.
Definition: str_util.c:328
void trim_whitespace(char *s)
Trim both leading and trailing whitespace from a string.
Definition: str_util.c:387
void mbg_memcpy(void *dst, const void *src, size_t n_bytes)
Copy array of bytes starting at beginning of buffer.
Definition: str_util.c:412
static __mbg_inline bool mbg_buffer_specs_valid(char *s, size_t max_len)
Check if the buffer plus size parameters passed to a function are valid.
Definition: str_util.h:88
void mbg_memcpy_reversed(void *dst, const void *src, size_t n_bytes)
Copy an array of bytes in reversed order, starting at end of buffer.
Definition: str_util.c:438
static __mbg_inline int mbg_chk_snprint_results(size_t n, char *s, size_t max_len)
Check the results of an snprintf()-like function.
Definition: str_util.h:123
int snprintf_safe(char *s, size_t max_len, const char *fmt,...)
A portable, safe implementation of snprintf()
Definition: str_util.c:156
void trim_leading_whitespace(char *s)
Trim whitespace at the beginning of a string.
Definition: str_util.c:353
int sn_cpy_char_safe(char *dst, size_t max_len, char c)
A function to copy a character safely to a string buffer.
Definition: str_util.c:306