xref: /reactos/sdk/lib/ucrt/mbstring/mbsnbcat.cpp (revision fe11f7a2)
1 /***
2 *mbsnbcat.c - concatenate string2 onto string1, max length n bytes
3 *
4 *       Copyright (c) Microsoft Corporation.  All rights reserved.
5 *
6 *Purpose:
7 *       defines mbsnbcat() - concatenate maximum of n bytes
8 *
9 *******************************************************************************/
10 #ifndef _MBCS
11     #error This file should only be compiled with _MBCS defined
12 #endif
13 
14 #include <corecrt_internal.h>
15 #include <corecrt_internal_mbstring.h>
16 #include <locale.h>
17 #include <string.h>
18 
19 
20 /***
21 * _mbsnbcat - concatenate max cnt bytes onto dst
22 *
23 *Purpose:
24 *       Concatenates src onto dst, with a maximum of cnt bytes copied.
25 *       Handles 2-byte MBCS characters correctly.
26 *
27 *Entry:
28 *       unsigned char *dst - string to concatenate onto
29 *       unsigned char *src - string to concatenate from
30 *       int cnt - number of bytes to copy
31 *
32 *Exit:
33 *       returns dst, with src (at least part) concatenated on
34 *
35 *Exceptions:
36 *       Input parameters are validated. Refer to the validation section of the function.
37 *
38 *******************************************************************************/
39 
40 extern "C" unsigned char * __cdecl _mbsnbcat_l(
41         unsigned char *dst,
42         const unsigned char *src,
43         size_t cnt,
44         _locale_t plocinfo
45         )
46 {
47         unsigned char *start;
48 
49         if (!cnt)
50                 return(dst);
51 
52         /* validation section */
53         _VALIDATE_RETURN(dst != nullptr, EINVAL, nullptr);
54         _VALIDATE_RETURN(src != nullptr, EINVAL, nullptr);
55 
56         _LocaleUpdate _loc_update(plocinfo);
57 
58         _BEGIN_SECURE_CRT_DEPRECATION_DISABLE
59         if (_loc_update.GetLocaleT()->mbcinfo->ismbcodepage == 0)
60             return (unsigned char *)strncat((char *)dst, (const char *)src, cnt);
61         _END_SECURE_CRT_DEPRECATION_DISABLE
62 
63         start = dst;
64         while (*dst++)
65                 ;
66         --dst;          // dst now points to end of dst string
67 
68         /* if last char in string is a lead byte, back up pointer */
69         if ( dst!=start && _mbsbtype_l(start, (int) ((dst - start) - 1), _loc_update.GetLocaleT()) == _MBC_LEAD )
70         {
71             --dst;
72         }
73 
74         /* copy over the characters */
75 
76         while (cnt--) {
77 
78             if ( _ismbblead_l(*src, _loc_update.GetLocaleT()) ) {
79                 *dst++ = *src++;
80                 if (cnt == 0) {   /* write null if cnt exhausted */
81                     dst[-1] = '\0';
82                     break;
83                 }
84                 cnt--;
85                 if ((*dst++ = *src++)=='\0') { /* or if no trail byte */
86                     dst[-2] = '\0';
87                     break;
88                 }
89             }
90             else if ((*dst++ = *src++) == '\0')
91                 break;
92 
93         }
94 
95         if ( dst!=start && _mbsbtype_l(start, (int) ((dst - start) - 1), _loc_update.GetLocaleT()) == _MBC_LEAD )
96         {
97             dst[-1] = '\0';
98         }
99         else
100         {
101             *dst = '\0';
102         }
103 
104         return(start);
105 }
106 
107 extern "C" unsigned char * (__cdecl _mbsnbcat)(
108         unsigned char *dst,
109         const unsigned char *src,
110         size_t cnt
111         )
112 {
113     _BEGIN_SECURE_CRT_DEPRECATION_DISABLE
114     return _mbsnbcat_l(dst, src, cnt, nullptr);
115     _END_SECURE_CRT_DEPRECATION_DISABLE
116 }
117