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 | // NamespaceUtil.cpp |
6 | // |
7 | |
8 | // |
9 | // Helpers for converting namespace separators. |
10 | // |
11 | //***************************************************************************** |
12 | #include "stdafx.h" |
13 | #include "corhdr.h" |
14 | #include "corhlpr.h" |
15 | #include "sstring.h" |
16 | #include "utilcode.h" |
17 | |
18 | #ifndef _ASSERTE |
19 | #define _ASSERTE(foo) |
20 | #endif |
21 | |
22 | #include "nsutilpriv.h" |
23 | |
24 | |
25 | //***************************************************************************** |
26 | // Determine how many chars large a fully qualified name would be given the |
27 | // two parts of the name. The return value includes room for every character |
28 | // in both names, as well as room for the separator and a final terminator. |
29 | //***************************************************************************** |
30 | int ns::GetFullLength( // Number of chars in full name. |
31 | const WCHAR *szNameSpace, // Namspace for value. |
32 | const WCHAR *szName) // Name of value. |
33 | { |
34 | STATIC_CONTRACT_NOTHROW; |
35 | STATIC_CONTRACT_GC_NOTRIGGER; |
36 | STATIC_CONTRACT_FORBID_FAULT; |
37 | |
38 | int iLen = 1; // Null terminator. |
39 | if (szNameSpace) |
40 | iLen += (int)wcslen(szNameSpace); |
41 | if (szName) |
42 | iLen += (int)wcslen(szName); |
43 | if (szNameSpace && *szNameSpace && szName && *szName) |
44 | ++iLen; |
45 | return iLen; |
46 | } //int ns::GetFullLength() |
47 | |
48 | int ns::GetFullLength( // Number of chars in full name. |
49 | LPCUTF8 szNameSpace, // Namspace for value. |
50 | LPCUTF8 szName) // Name of value. |
51 | { |
52 | STATIC_CONTRACT_NOTHROW; |
53 | STATIC_CONTRACT_GC_NOTRIGGER; |
54 | STATIC_CONTRACT_FORBID_FAULT; |
55 | |
56 | |
57 | int iLen = 1; |
58 | if (szNameSpace) |
59 | iLen += (int)strlen(szNameSpace); |
60 | if (szName) |
61 | iLen += (int)strlen(szName); |
62 | if (szNameSpace && *szNameSpace && szName && *szName) |
63 | ++iLen; |
64 | return iLen; |
65 | } //int ns::GetFullLength() |
66 | |
67 | |
68 | //***************************************************************************** |
69 | // Scan the string from the rear looking for the first valid separator. If |
70 | // found, return a pointer to it. Else return null. This code is smart enough |
71 | // to skip over special sequences, such as: |
72 | // a.b..ctor |
73 | // ^ |
74 | // | |
75 | // The ".ctor" is considered one token. |
76 | //***************************************************************************** |
77 | WCHAR *ns::FindSep( // Pointer to separator or null. |
78 | const WCHAR *szPath) // The path to look in. |
79 | { |
80 | STATIC_CONTRACT_NOTHROW; |
81 | STATIC_CONTRACT_GC_NOTRIGGER; |
82 | STATIC_CONTRACT_FORBID_FAULT; |
83 | |
84 | _ASSERTE(szPath); |
85 | WCHAR *ptr = (WCHAR*)wcsrchr(szPath, NAMESPACE_SEPARATOR_WCHAR); |
86 | if((ptr == NULL) || (ptr == szPath)) return NULL; |
87 | if(*(ptr - 1) == NAMESPACE_SEPARATOR_WCHAR) // here ptr is at least szPath+1 |
88 | --ptr; |
89 | return ptr; |
90 | } //WCHAR *ns::FindSep() |
91 | |
92 | //<TODO>@todo: this isn't dbcs safe if this were ansi, but this is utf8. Still an issue?</TODO> |
93 | LPUTF8 ns::FindSep( // Pointer to separator or null. |
94 | LPCUTF8 szPath) // The path to look in. |
95 | { |
96 | STATIC_CONTRACT_NOTHROW; |
97 | STATIC_CONTRACT_GC_NOTRIGGER; |
98 | STATIC_CONTRACT_FORBID_FAULT; |
99 | STATIC_CONTRACT_SUPPORTS_DAC; |
100 | |
101 | _ASSERTE(szPath); |
102 | LPUTF8 ptr = const_cast<LPUTF8>(strrchr(szPath, NAMESPACE_SEPARATOR_CHAR)); |
103 | if((ptr == NULL) || (ptr == szPath)) return NULL; |
104 | if(*(ptr - 1) == NAMESPACE_SEPARATOR_CHAR) // here ptr is at least szPath+1 |
105 | --ptr; |
106 | return ptr; |
107 | } //LPUTF8 ns::FindSep() |
108 | |
109 | |
110 | |
111 | //***************************************************************************** |
112 | // Take a path and find the last separator (nsFindSep), and then replace the |
113 | // separator with a '\0' and return a pointer to the name. So for example: |
114 | // a.b.c |
115 | // becomes two strings "a.b" and "c" and the return value points to "c". |
116 | //***************************************************************************** |
117 | WCHAR *ns::SplitInline( // Pointer to name portion. |
118 | __inout __inout_z WCHAR *szPath) // The path to split. |
119 | { |
120 | STATIC_CONTRACT_NOTHROW; |
121 | STATIC_CONTRACT_GC_NOTRIGGER; |
122 | STATIC_CONTRACT_FORBID_FAULT; |
123 | |
124 | WCHAR *ptr = ns::FindSep(szPath); |
125 | if (ptr) |
126 | { |
127 | *ptr = 0; |
128 | ++ptr; |
129 | } |
130 | return ptr; |
131 | } // WCHAR *ns::SplitInline() |
132 | |
133 | LPUTF8 ns::SplitInline( // Pointer to name portion. |
134 | __inout __inout_z LPUTF8 szPath) // The path to split. |
135 | { |
136 | STATIC_CONTRACT_NOTHROW; |
137 | STATIC_CONTRACT_GC_NOTRIGGER; |
138 | STATIC_CONTRACT_FORBID_FAULT; |
139 | |
140 | LPUTF8 ptr = ns::FindSep(szPath); |
141 | if (ptr) |
142 | { |
143 | *ptr = 0; |
144 | ++ptr; |
145 | } |
146 | return ptr; |
147 | } // LPUTF8 ns::SplitInline() |
148 | |
149 | void ns::SplitInline( |
150 | __inout __inout_z LPWSTR szPath, // Path to split. |
151 | LPCWSTR &szNameSpace, // Return pointer to namespace. |
152 | LPCWSTR &szName) // Return pointer to name. |
153 | { |
154 | STATIC_CONTRACT_NOTHROW; |
155 | STATIC_CONTRACT_GC_NOTRIGGER; |
156 | STATIC_CONTRACT_FORBID_FAULT; |
157 | |
158 | WCHAR *ptr = SplitInline(szPath); |
159 | if (ptr) |
160 | { |
161 | szNameSpace = szPath; |
162 | szName = ptr; |
163 | } |
164 | else |
165 | { |
166 | szNameSpace = 0; |
167 | szName = szPath; |
168 | } |
169 | } // void ns::SplitInline() |
170 | |
171 | void ns::SplitInline( |
172 | __inout __inout_z LPUTF8 szPath, // Path to split. |
173 | LPCUTF8 &szNameSpace, // Return pointer to namespace. |
174 | LPCUTF8 &szName) // Return pointer to name. |
175 | { |
176 | STATIC_CONTRACT_NOTHROW; |
177 | STATIC_CONTRACT_GC_NOTRIGGER; |
178 | STATIC_CONTRACT_FORBID_FAULT; |
179 | |
180 | LPUTF8 ptr = SplitInline(szPath); |
181 | if (ptr) |
182 | { |
183 | szNameSpace = szPath; |
184 | szName = ptr; |
185 | } |
186 | else |
187 | { |
188 | szNameSpace = 0; |
189 | szName = szPath; |
190 | } |
191 | } // void ns::SplitInline() |
192 | |
193 | |
194 | //***************************************************************************** |
195 | // Split the last parsable element from the end of the string as the name, |
196 | // the first part as the namespace. |
197 | //***************************************************************************** |
198 | int ns::SplitPath( // true ok, false trunction. |
199 | const WCHAR *szPath, // Path to split. |
200 | __out_ecount(cchNameSpace) WCHAR *szNameSpace, // Output for namespace value. |
201 | int cchNameSpace, // Max chars for output. |
202 | __out_ecount(cchName) WCHAR *szName, // Output for name. |
203 | int cchName) // Max chars for output. |
204 | { |
205 | STATIC_CONTRACT_NOTHROW; |
206 | STATIC_CONTRACT_GC_NOTRIGGER; |
207 | STATIC_CONTRACT_FORBID_FAULT; |
208 | |
209 | const WCHAR *ptr = ns::FindSep(szPath); |
210 | size_t iLen = (ptr) ? ptr - szPath : 0; |
211 | size_t iCopyMax; |
212 | int brtn = true; |
213 | if (szNameSpace && cchNameSpace) |
214 | { |
215 | _ASSERTE(cchNameSpace > 1); |
216 | iCopyMax = cchNameSpace - 1; |
217 | iCopyMax = min(iCopyMax, iLen); |
218 | wcsncpy_s(szNameSpace, cchNameSpace, szPath, iCopyMax); |
219 | szNameSpace[iCopyMax] = 0; |
220 | |
221 | if (iLen >= (size_t)cchNameSpace) |
222 | brtn = false; |
223 | } |
224 | |
225 | if (szName && cchName) |
226 | { |
227 | _ASSERTE(cchName > 1); |
228 | iCopyMax = cchName - 1; |
229 | if (ptr) |
230 | ++ptr; |
231 | else |
232 | ptr = szPath; |
233 | iLen = (int)wcslen(ptr); |
234 | iCopyMax = min(iCopyMax, iLen); |
235 | wcsncpy_s(szName, cchName, ptr, iCopyMax); |
236 | szName[iCopyMax] = 0; |
237 | |
238 | if (iLen >= (size_t)cchName) |
239 | brtn = false; |
240 | } |
241 | return brtn; |
242 | } // int ns::SplitPath() |
243 | |
244 | |
245 | int ns::SplitPath( // true ok, false trunction. |
246 | LPCUTF8 szPath, // Path to split. |
247 | __out_ecount_opt (cchNameSpace) LPUTF8 szNameSpace, // Output for namespace value. |
248 | int cchNameSpace, // Max chars for output. |
249 | __out_ecount_opt (cchName) LPUTF8 szName, // Output for name. |
250 | int cchName) // Max chars for output. |
251 | { |
252 | STATIC_CONTRACT_NOTHROW; |
253 | STATIC_CONTRACT_GC_NOTRIGGER; |
254 | STATIC_CONTRACT_FORBID_FAULT; |
255 | |
256 | LPCUTF8 ptr = ns::FindSep(szPath); |
257 | size_t iLen = (ptr) ? ptr - szPath : 0; |
258 | size_t iCopyMax; |
259 | int brtn = true; |
260 | if (szNameSpace && cchNameSpace) |
261 | { |
262 | _ASSERTE(cchNameSpace > 1); |
263 | iCopyMax = cchNameSpace-1; |
264 | iCopyMax = min(iCopyMax, iLen); |
265 | strncpy_s(szNameSpace, cchNameSpace, szPath, iCopyMax); |
266 | szNameSpace[iCopyMax] = 0; |
267 | |
268 | if (iLen >= (size_t)cchNameSpace) |
269 | brtn = false; |
270 | } |
271 | |
272 | if (szName && cchName) |
273 | { |
274 | _ASSERTE(cchName > 1); |
275 | iCopyMax = cchName-1; |
276 | if (ptr) |
277 | ++ptr; |
278 | else |
279 | ptr = szPath; |
280 | iLen = (int)strlen(ptr); |
281 | iCopyMax = min(iCopyMax, iLen); |
282 | strncpy_s(szName, cchName, ptr, iCopyMax); |
283 | szName[iCopyMax] = 0; |
284 | |
285 | if (iLen >= (size_t)cchName) |
286 | brtn = false; |
287 | } |
288 | return brtn; |
289 | } // int ns::SplitPath() |
290 | |
291 | |
292 | //***************************************************************************** |
293 | // Take two values and put them together in a fully qualified path using the |
294 | // correct separator. |
295 | //***************************************************************************** |
296 | int ns::MakePath( // true ok, false truncation. |
297 | __out_ecount(cchChars) WCHAR *szOut, // output path for name. |
298 | int cchChars, // max chars for output path. |
299 | const WCHAR *szNameSpace, // Namespace. |
300 | const WCHAR *szName) // Name. |
301 | { |
302 | STATIC_CONTRACT_NOTHROW; |
303 | STATIC_CONTRACT_GC_NOTRIGGER; |
304 | STATIC_CONTRACT_FORBID_FAULT; |
305 | |
306 | if (cchChars < 1) |
307 | return false; |
308 | |
309 | if (szOut) |
310 | *szOut = 0; |
311 | else |
312 | return false; |
313 | |
314 | if (szNameSpace && *szNameSpace != W('\0')) |
315 | { |
316 | if (wcsncpy_s(szOut, cchChars, szNameSpace, _TRUNCATE) == STRUNCATE) |
317 | return false; |
318 | |
319 | // Add namespace separator if a non-empty name was supplied |
320 | if (szName && *szName != W('\0')) |
321 | { |
322 | if (wcsncat_s(szOut, cchChars, NAMESPACE_SEPARATOR_WSTR, _TRUNCATE) == STRUNCATE) |
323 | { |
324 | return false; |
325 | } |
326 | } |
327 | } |
328 | |
329 | if (szName && *szName) |
330 | { |
331 | if (wcsncat_s(szOut, cchChars, szName, _TRUNCATE) == STRUNCATE) |
332 | return false; |
333 | } |
334 | |
335 | return true; |
336 | } // int ns::MakePath() |
337 | |
338 | int ns::MakePath( // true ok, false truncation. |
339 | __out_ecount(cchChars) LPUTF8 szOut, // output path for name. |
340 | int cchChars, // max chars for output path. |
341 | LPCUTF8 szNameSpace, // Namespace. |
342 | LPCUTF8 szName) // Name. |
343 | { |
344 | STATIC_CONTRACT_NOTHROW; |
345 | STATIC_CONTRACT_GC_NOTRIGGER; |
346 | STATIC_CONTRACT_FORBID_FAULT; |
347 | |
348 | if (cchChars < 1) |
349 | return false; |
350 | |
351 | if (szOut) |
352 | *szOut = 0; |
353 | else |
354 | return false; |
355 | |
356 | if (szNameSpace && *szNameSpace != W('\0')) |
357 | { |
358 | if (strncpy_s(szOut, cchChars, szNameSpace, _TRUNCATE) == STRUNCATE) |
359 | return false; |
360 | |
361 | // Add namespace separator if a non-empty name was supplied |
362 | if (szName && *szName != W('\0')) |
363 | { |
364 | if (strncat_s(szOut, cchChars, NAMESPACE_SEPARATOR_STR, _TRUNCATE) == STRUNCATE) |
365 | { |
366 | return false; |
367 | } |
368 | } |
369 | } |
370 | |
371 | if (szName && *szName) |
372 | { |
373 | if (strncat_s(szOut, cchChars, szName, _TRUNCATE) == STRUNCATE) |
374 | return false; |
375 | } |
376 | |
377 | return true; |
378 | |
379 | } // int ns::MakePath() |
380 | |
381 | int ns::MakePath( // true ok, false truncation. |
382 | __out_ecount(cchChars) WCHAR *szOut, // output path for name. |
383 | int cchChars, // max chars for output path. |
384 | LPCUTF8 szNamespace, // Namespace. |
385 | LPCUTF8 szName) // Name. |
386 | { |
387 | STATIC_CONTRACT_NOTHROW; |
388 | STATIC_CONTRACT_GC_NOTRIGGER; |
389 | STATIC_CONTRACT_FORBID_FAULT; |
390 | |
391 | if (cchChars < 1) |
392 | return false; |
393 | |
394 | if (szOut) |
395 | *szOut = 0; |
396 | else |
397 | return false; |
398 | |
399 | if (szNamespace != NULL && *szNamespace != '\0') |
400 | { |
401 | if (cchChars < 2) |
402 | return false; |
403 | |
404 | int count; |
405 | |
406 | // We use cBuffer - 2 to account for the '.' and at least a 1 character name below. |
407 | count = WszMultiByteToWideChar(CP_UTF8, 0, szNamespace, -1, szOut, cchChars-2); |
408 | if (count == 0) |
409 | return false; // Supply a bigger buffer! |
410 | |
411 | // buffer access is bounded: WszMultiByteToWideChar returns 0 if access doesn't fit in range |
412 | #ifdef _PREFAST_ |
413 | #pragma warning( suppress: 26015 ) |
414 | #endif |
415 | szOut[count-1] = NAMESPACE_SEPARATOR_WCHAR; |
416 | szOut += count; |
417 | cchChars -= count; |
418 | } |
419 | |
420 | if (((cchChars == 0) && (szName != NULL) && (*szName != '\0')) || |
421 | (WszMultiByteToWideChar(CP_UTF8, 0, szName, -1, szOut, cchChars) == 0)) |
422 | return false; // supply a bigger buffer! |
423 | return true; |
424 | } // int ns::MakePath() |
425 | |
426 | int ns::MakePath( // true ok, false out of memory |
427 | CQuickBytes &qb, // Where to put results. |
428 | LPCUTF8 szNameSpace, // Namespace for name. |
429 | LPCUTF8 szName) // Final part of name. |
430 | { |
431 | STATIC_CONTRACT_NOTHROW; |
432 | STATIC_CONTRACT_GC_NOTRIGGER; |
433 | STATIC_CONTRACT_FAULT; |
434 | |
435 | int iLen = 2; |
436 | if (szNameSpace) |
437 | iLen += (int)strlen(szNameSpace); |
438 | if (szName) |
439 | iLen += (int)strlen(szName); |
440 | LPUTF8 szOut = (LPUTF8) qb.AllocNoThrow(iLen); |
441 | if (!szOut) |
442 | return false; |
443 | return ns::MakePath(szOut, iLen, szNameSpace, szName); |
444 | } // int ns::MakePath() |
445 | |
446 | int ns::MakePath( // true ok, false out of memory |
447 | CQuickArray<WCHAR> &qa, // Where to put results. |
448 | LPCUTF8 szNameSpace, // Namespace for name. |
449 | LPCUTF8 szName) // Final part of name. |
450 | { |
451 | STATIC_CONTRACT_NOTHROW; |
452 | STATIC_CONTRACT_GC_NOTRIGGER; |
453 | STATIC_CONTRACT_FAULT; |
454 | |
455 | int iLen = 2; |
456 | if (szNameSpace) |
457 | iLen += (int)strlen(szNameSpace); |
458 | if (szName) |
459 | iLen += (int)strlen(szName); |
460 | WCHAR *szOut = (WCHAR *) qa.AllocNoThrow(iLen); |
461 | if (!szOut) |
462 | return false; |
463 | return ns::MakePath(szOut, iLen, szNameSpace, szName); |
464 | } // int ns::MakePath() |
465 | |
466 | int ns::MakePath( // true ok, false out of memory |
467 | CQuickBytes &qb, // Where to put results. |
468 | const WCHAR *szNameSpace, // Namespace for name. |
469 | const WCHAR *szName) // Final part of name. |
470 | { |
471 | STATIC_CONTRACT_NOTHROW; |
472 | STATIC_CONTRACT_GC_NOTRIGGER; |
473 | STATIC_CONTRACT_FAULT; |
474 | |
475 | int iLen = 2; |
476 | if (szNameSpace) |
477 | iLen += (int)wcslen(szNameSpace); |
478 | if (szName) |
479 | iLen += (int)wcslen(szName); |
480 | WCHAR *szOut = (WCHAR *) qb.AllocNoThrow(iLen * sizeof(WCHAR)); |
481 | if (!szOut) |
482 | return false; |
483 | return ns::MakePath(szOut, iLen, szNameSpace, szName); |
484 | } // int ns::MakePath() |
485 | |
486 | void ns::MakePath( // throws on out of memory |
487 | SString &ssBuf, // Where to put results. |
488 | const SString &ssNameSpace, // Namespace for name. |
489 | const SString &ssName) // Final part of name. |
490 | { |
491 | STATIC_CONTRACT_THROWS; |
492 | STATIC_CONTRACT_GC_NOTRIGGER; |
493 | STATIC_CONTRACT_FAULT; |
494 | |
495 | ssBuf.Clear(); |
496 | |
497 | if (!ssNameSpace.IsEmpty()) |
498 | { |
499 | if (ssName.IsEmpty()) |
500 | { |
501 | ssBuf.Set(ssNameSpace); |
502 | } |
503 | else |
504 | { |
505 | SString s(SString::Literal, NAMESPACE_SEPARATOR_WSTR); |
506 | ssBuf.Set(ssNameSpace, s); |
507 | } |
508 | } |
509 | |
510 | if (!ssName.IsEmpty()) |
511 | { |
512 | ssBuf.Append(ssName); |
513 | } |
514 | } |
515 | |
516 | bool ns::MakeAssemblyQualifiedName( // true ok, false truncation |
517 | __out_ecount(dwBuffer) WCHAR* pBuffer, // Buffer to recieve the results |
518 | int dwBuffer, // Number of characters total in buffer |
519 | const WCHAR *szTypeName, // Namespace for name. |
520 | int dwTypeName, // Number of characters (not including null) |
521 | const WCHAR *szAssemblyName, // Final part of name. |
522 | int dwAssemblyName) // Number of characters (not including null) |
523 | { |
524 | STATIC_CONTRACT_NOTHROW; |
525 | STATIC_CONTRACT_GC_NOTRIGGER; |
526 | STATIC_CONTRACT_FORBID_FAULT; |
527 | |
528 | if (dwBuffer < 2) |
529 | return false; |
530 | |
531 | int iCopyMax = 0; |
532 | _ASSERTE(pBuffer); |
533 | *pBuffer = NULL; |
534 | |
535 | if (szTypeName && *szTypeName != W('\0')) |
536 | { |
537 | _ASSERTE(dwTypeName > 0); |
538 | iCopyMax = min(dwBuffer-1, dwTypeName); |
539 | wcsncpy_s(pBuffer, dwBuffer, szTypeName, iCopyMax); |
540 | dwBuffer -= iCopyMax; |
541 | } |
542 | |
543 | if (szAssemblyName && *szAssemblyName != W('\0')) |
544 | { |
545 | |
546 | if(dwBuffer < ASSEMBLY_SEPARATOR_LEN) |
547 | return false; |
548 | |
549 | for(DWORD i = 0; i < ASSEMBLY_SEPARATOR_LEN; i++) |
550 | pBuffer[iCopyMax+i] = ASSEMBLY_SEPARATOR_WSTR[i]; |
551 | |
552 | dwBuffer -= ASSEMBLY_SEPARATOR_LEN; |
553 | if(dwBuffer == 0) |
554 | return false; |
555 | |
556 | int iCur = iCopyMax + ASSEMBLY_SEPARATOR_LEN; |
557 | _ASSERTE(dwAssemblyName > 0); |
558 | iCopyMax = min(dwBuffer-1, dwAssemblyName); |
559 | wcsncpy_s(pBuffer + iCur, dwBuffer, szAssemblyName, iCopyMax); |
560 | pBuffer[iCur + iCopyMax] = W('\0'); |
561 | |
562 | if (iCopyMax < dwAssemblyName) |
563 | return false; |
564 | } |
565 | else { |
566 | if(dwBuffer == 0) { |
567 | PREFIX_ASSUME(iCopyMax > 0); |
568 | pBuffer[iCopyMax-1] = W('\0'); |
569 | return false; |
570 | } |
571 | else |
572 | pBuffer[iCopyMax] = W('\0'); |
573 | } |
574 | |
575 | return true; |
576 | } // int ns::MakePath() |
577 | |
578 | bool ns::MakeAssemblyQualifiedName( // true ok, false out of memory |
579 | CQuickBytes &qb, // Where to put results. |
580 | const WCHAR *szTypeName, // Namespace for name. |
581 | const WCHAR *szAssemblyName) // Final part of name. |
582 | { |
583 | STATIC_CONTRACT_NOTHROW; |
584 | STATIC_CONTRACT_GC_NOTRIGGER; |
585 | STATIC_CONTRACT_FAULT; |
586 | |
587 | int iTypeName = 0; |
588 | int iAssemblyName = 0; |
589 | if (szTypeName) |
590 | iTypeName = (int)wcslen(szTypeName); |
591 | if (szAssemblyName) |
592 | iAssemblyName = (int)wcslen(szAssemblyName); |
593 | |
594 | int iLen = ASSEMBLY_SEPARATOR_LEN + iTypeName + iAssemblyName + 1; // Space for null terminator |
595 | WCHAR *szOut = (WCHAR *) qb.AllocNoThrow(iLen * sizeof(WCHAR)); |
596 | if (!szOut) |
597 | return false; |
598 | |
599 | bool ret; |
600 | ret = ns::MakeAssemblyQualifiedName(szOut, iLen, szTypeName, iTypeName, szAssemblyName, iAssemblyName); |
601 | _ASSERTE(ret); |
602 | return true; |
603 | } |
604 | |
605 | int ns::MakeNestedTypeName( // true ok, false out of memory |
606 | CQuickBytes &qb, // Where to put results. |
607 | LPCUTF8 szEnclosingName, // Full name for enclosing type |
608 | LPCUTF8 szNestedName) // Full name for nested type |
609 | { |
610 | STATIC_CONTRACT_NOTHROW; |
611 | STATIC_CONTRACT_GC_NOTRIGGER; |
612 | STATIC_CONTRACT_FAULT; |
613 | |
614 | _ASSERTE(szEnclosingName && szNestedName); |
615 | int iLen = 2; |
616 | iLen += (int)strlen(szEnclosingName); |
617 | iLen += (int)strlen(szNestedName); |
618 | LPUTF8 szOut = (LPUTF8) qb.AllocNoThrow(iLen); |
619 | if (!szOut) |
620 | return false; |
621 | return ns::MakeNestedTypeName(szOut, iLen, szEnclosingName, szNestedName); |
622 | } // int ns::MakeNestedTypeName() |
623 | |
624 | int ns::MakeNestedTypeName( // true ok, false truncation. |
625 | __out_ecount (cchChars) LPUTF8 szOut, // output path for name. |
626 | int cchChars, // max chars for output path. |
627 | LPCUTF8 szEnclosingName, // Full name for enclosing type |
628 | LPCUTF8 szNestedName) // Full name for nested type |
629 | { |
630 | STATIC_CONTRACT_NOTHROW; |
631 | STATIC_CONTRACT_GC_NOTRIGGER; |
632 | STATIC_CONTRACT_FORBID_FAULT; |
633 | |
634 | if (cchChars < 1) |
635 | return false; |
636 | |
637 | int iCopyMax = 0, iLen; |
638 | int brtn = true; |
639 | *szOut = 0; |
640 | |
641 | iLen = (int)strlen(szEnclosingName); |
642 | iCopyMax = min(cchChars-1, iLen); |
643 | strncpy_s(szOut, cchChars, szEnclosingName, iCopyMax); |
644 | |
645 | if (iLen >= cchChars) |
646 | brtn = false; |
647 | |
648 | szOut[iCopyMax] = NESTED_SEPARATOR_CHAR; |
649 | int iCur = iCopyMax+1; // iCopyMax characters + nested_separator_char |
650 | cchChars -= iCur; |
651 | if(cchChars == 0) |
652 | return false; |
653 | |
654 | iLen = (int)strlen(szNestedName); |
655 | iCopyMax = min(cchChars-1, iLen); |
656 | strncpy_s(&szOut[iCur], cchChars, szNestedName, iCopyMax); |
657 | szOut[iCur + iCopyMax] = 0; |
658 | |
659 | if (iLen >= cchChars) |
660 | brtn = false; |
661 | |
662 | return brtn; |
663 | } // int ns::MakeNestedTypeName() |
664 | |
665 | void ns::MakeNestedTypeName( // throws on out of memory |
666 | SString &ssBuf, // output path for name. |
667 | const SString &ssEnclosingName, // Full name for enclosing type |
668 | const SString &ssNestedName) // Full name for nested type |
669 | { |
670 | STATIC_CONTRACT_THROWS; |
671 | STATIC_CONTRACT_GC_NOTRIGGER; |
672 | |
673 | ssBuf.Clear(); |
674 | |
675 | ssBuf.Append(ssEnclosingName); |
676 | ssBuf.Append(NESTED_SEPARATOR_WCHAR); |
677 | ssBuf.Append(ssNestedName); |
678 | } |
679 | |
680 | |