FreeBASIC  0.91.0
swap_str.c
Go to the documentation of this file.
1 /* swap for strings */
2 
3 #include "fb.h"
4 
5 FBCALL void fb_StrSwap( void *str1, ssize_t size1, int fillrem1,
6  void *str2, ssize_t size2, int fillrem2 )
7 {
8  char *p1, *p2;
9  ssize_t len1, len2;
10 
11  if( (str1 == NULL) || (str2 == NULL) )
12  return;
13 
14  /* both var-len? */
15  if( (size1 == -1) && (size2 == -1) )
16  {
17  FBSTRING td;
18 
19  /* just swap the descriptors */
20  td.data = ((FBSTRING *)str1)->data;
21  td.len = ((FBSTRING *)str1)->len;
22  td.size = ((FBSTRING *)str1)->size;
23 
24  ((FBSTRING *)str1)->data = ((FBSTRING *)str2)->data;
25  ((FBSTRING *)str1)->len = ((FBSTRING *)str2)->len;
26  ((FBSTRING *)str1)->size = ((FBSTRING *)str2)->size;
27 
28  ((FBSTRING *)str2)->data = td.data;
29  ((FBSTRING *)str2)->len = td.len;
30  ((FBSTRING *)str2)->size = td.size;
31 
32  return;
33  }
34 
35  FB_STRSETUP_FIX( str1, size1, p1, len1 );
36  FB_STRSETUP_FIX( str2, size2, p2, len2 );
37 
38  /* Same length? Only need to do an fb_MemSwap() */
39  if( len1 == len2 ) {
40  if( len1 > 0 ) {
41  fb_MemSwap( (unsigned char *)p1,
42  (unsigned char *)p2,
43  len1 );
44  /* null terminators don't need to change */
45  }
46  return;
47  }
48 
49  /* Note: user-allocated zstrings are assumed to be large enough */
50 
51  /* Is one of them a var-len string? Might need to be (re)allocated */
52  if( (size1 == -1) || (size2 == -1) )
53  {
54  FBSTRING td = { 0 };
55  fb_StrAssign( &td, -1, str1, size1, FALSE );
56  fb_StrAssign( str1, size1, str2, size2, fillrem1 );
57  fb_StrAssign( str2, size2, &td, -1, fillrem2 );
58  fb_StrDelete( &td );
59  return;
60  }
61 
62  /* Both are fixed-size/user-allocated [z]strings */
63 
64  /* Make str1/str2 be the smaller/larger string respectively */
65  if( len1 > len2 ) {
66  {
67  char* p = p1;
68  p1 = p2;
69  p2 = p;
70  }
71 
72  {
73  ssize_t len = len1;
74  len1 = len2;
75  len2 = len;
76  }
77 
78  {
79  ssize_t size = size1;
80  size1 = size2;
81  size2 = size;
82  }
83 
84  {
85  int fillrem = fillrem1;
86  fillrem1 = fillrem2;
87  fillrem2 = fillrem;
88  }
89  }
90 
91  /* MemSwap as much as possible (i.e. the smaller length) */
92  if( len1 > 0 ) {
93  fb_MemSwap( (unsigned char *)p1,
94  (unsigned char *)p2,
95  len1 );
96  }
97 
98  /* and copy over the remainder from larger to smaller, unless it's
99  a fixed-size [z]string that doesn't have enough room left (not even
100  for the null terminator) */
101  if( (size1 > 0) && (len2 >= size1) ) {
102  len2 = len1;
103  } else if( len2 > len1 ) {
104  FB_MEMCPYX( (unsigned char *)(p1 + len1),
105  (unsigned char *)(p2 + len1),
106  len2 - len1 );
107  }
108 
109  /* set null terminators */
110  p1[len2] = '\0';
111  p2[len1] = '\0';
112 
113  /* Clear remainder of the larger (now smaller) string with nulls if
114  requested (see also fb_StrAssign()). We can assume that the strings
115  were originally cleared properly, because uninitialized strings
116  mustn't be used in rvalues, FB_STRSETUP_FIX() doesn't handle that.
117  The smaller (now larger) string doesn't need to be touched, as it's
118  remainder didn't increase */
119  if( fillrem2 ) {
120  ssize_t used2 = len1 + 1;
121  if( size2 > used2 ) {
122  memset( p2 + used2, 0, size2 - used2 );
123  }
124  }
125 }