1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/***
6* mbusafecrt.c - implementaion of support functions and data for MBUSafeCRT
7*
8
9*
10* Purpose:
11* This file contains the implementation of support functions and
12* data for MBUSafeCRT declared in mbusafecrt.h and mbusafecrt_internal.h.
13****/
14
15#include "pal/palinternal.h"
16#include <string.h>
17#include <errno.h>
18#include <limits.h>
19
20#include "mbusafecrt_internal.h"
21
22/* global data */
23tSafeCRT_AssertFuncPtr sMBUSafeCRTAssertFunc = NULL;
24
25/***
26* MBUSafeCRTSetAssertFunc - Set the function called when an assert fails.
27****/
28
29void MBUSafeCRTSetAssertFunc( tSafeCRT_AssertFuncPtr inAssertFuncPtr )
30{
31 /* set it */
32 sMBUSafeCRTAssertFunc = inAssertFuncPtr;
33}
34
35/***
36* _putc_nolock - putc for the miniFILE stream.
37****/
38
39int _putc_nolock( char inChar, miniFILE* inStream )
40{
41 int returnValue = EOF;
42
43 inStream->_cnt -= sizeof( char );
44
45 if ( ( inStream->_cnt ) >= 0 )
46 {
47 *( inStream->_ptr ) = inChar;
48 inStream->_ptr += sizeof( char );
49 returnValue = ( int )inChar;
50 }
51
52 return returnValue;
53}
54
55/***
56* _putwc_nolock - putwc for the miniFILE stream.
57****/
58
59int _putwc_nolock( wchar_t inChar, miniFILE* inStream )
60{
61 int returnValue = WEOF;
62
63 inStream->_cnt -= sizeof( wchar_t );
64
65 if ( ( inStream->_cnt ) >= 0 )
66 {
67 *( ( wchar_t* )( inStream->_ptr ) ) = inChar;
68 inStream->_ptr += sizeof( wchar_t );
69 returnValue = ( int )inChar;
70 }
71
72 return returnValue;
73}
74
75/***
76* _getc_nolock - getc for the miniFILE stream.
77****/
78
79int _getc_nolock( miniFILE* inStream )
80{
81 int returnValue = EOF;
82
83 if ( ( inStream->_cnt ) >= ( int )( sizeof( char ) ) )
84 {
85 inStream->_cnt -= sizeof( char );
86 returnValue = ( int )( *( inStream->_ptr ) );
87 inStream->_ptr += sizeof( char );
88 }
89
90 return returnValue;
91}
92
93/***
94* _getwc_nolock - getc for the miniFILE stream.
95****/
96
97int _getwc_nolock( miniFILE* inStream )
98{
99 int returnValue = EOF;
100
101 if ( ( inStream->_cnt ) >= ( int )( sizeof( wchar_t ) ) )
102 {
103 inStream->_cnt -= sizeof( wchar_t );
104 returnValue = ( int )( *( ( wchar_t* )( inStream->_ptr ) ) );
105 inStream->_ptr += sizeof( wchar_t );
106 }
107
108 return returnValue;
109}
110
111/***
112* _ungetc_nolock - ungetc for the miniFILE stream.
113****/
114
115int _ungetc_nolock( char inChar, miniFILE* inStream )
116{
117 int returnValue = EOF;
118
119 if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( char ) ) )
120 {
121 inStream->_cnt += sizeof( char );
122 inStream->_ptr -= sizeof( char );
123 return ( int )inChar;
124 }
125
126 return returnValue;
127}
128
129/***
130* _ungetwc_nolock - ungetwc for the miniFILE stream.
131****/
132
133int _ungetwc_nolock( wchar_t inChar, miniFILE* inStream )
134{
135 int returnValue = WEOF;
136
137 if ( ( size_t )( ( inStream->_ptr ) - ( inStream->_base ) ) >= ( sizeof( wchar_t ) ) )
138 {
139 inStream->_cnt += sizeof( wchar_t );
140 inStream->_ptr -= sizeof( wchar_t );
141 returnValue = ( unsigned short )inChar;
142 }
143
144 return returnValue;
145}
146
147
148/***
149* _safecrt_cfltcvt - convert a float to an ascii string.
150****/
151
152/* routine used for floating-point output */
153#define FORMATSIZE 30
154
155// taken from output.inl
156#define FL_ALTERNATE 0x00080 /* alternate form requested */
157
158errno_t _safecrt_cfltcvt(double *arg, char *buffer, size_t sizeInBytes, int type, int precision, int flags)
159{
160 char format[FORMATSIZE];
161 size_t formatlen = 0;
162 int retvalue;
163
164 if (flags & 1)
165 {
166 type -= 'a' - 'A';
167 }
168 formatlen = 0;
169 format[formatlen++] = '%';
170 if (flags & FL_ALTERNATE)
171 {
172 format[formatlen++] = '#';
173 }
174 format[formatlen++] = '.';
175 _itoa_s(precision, format + formatlen, FORMATSIZE - formatlen, 10);
176 formatlen = strlen(format);
177 format[formatlen++] = (char)type;
178 format[formatlen] = 0;
179
180 buffer[sizeInBytes - 1] = 0;
181 retvalue = snprintf(buffer, sizeInBytes, format, *arg);
182 if (buffer[sizeInBytes - 1] != 0 || retvalue <= 0)
183 {
184 buffer[0] = 0;
185 return EINVAL;
186 }
187 return 0;
188}
189
190
191/***
192* _safecrt_fassign - convert a string into a float or double.
193****/
194
195void _safecrt_fassign(int flag, void* argument, char* number )
196{
197 if ( flag != 0 ) // double
198 {
199 double dblValue = strtod(number, NULL);
200 *( ( double* )argument ) = dblValue;
201 }
202 else // float
203 {
204 float fltValue = strtof(number, NULL);
205 *( ( float* )argument ) = fltValue;
206 }
207}
208
209
210/***
211* _safecrt_wfassign - convert a wchar_t string into a float or double.
212****/
213
214void _safecrt_wfassign(int flag, void* argument, wchar_t* number )
215{
216 // We cannot use system functions for this - they
217 // assume that wchar_t is four bytes, while we assume
218 // two. So, we need to convert to a regular char string
219 // without using any system functions. To do this,
220 // we'll assume that the numbers are in the 0-9 range and
221 // do a simple conversion.
222
223 char* numberAsChars = ( char* )number;
224 int position = 0;
225
226 // do the convert
227 while ( number[ position ] != 0 )
228 {
229 numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF );
230 position++;
231 }
232 numberAsChars[ position ] = ( char )( number[ position ] & 0x00FF );
233
234 // call the normal char version
235 _safecrt_fassign( flag, argument, numberAsChars );
236}
237
238
239/***
240* _minimal_chartowchar - do a simple char to wchar conversion.
241****/
242
243int _minimal_chartowchar( wchar_t* outWChar, const char* inChar )
244{
245 *outWChar = ( wchar_t )( ( unsigned short )( ( unsigned char )( *inChar ) ) );
246 return 1;
247}
248
249
250