[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / namespaceutil.cpp
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