X
Пользователь приглашает вас присоединиться к открытой игре игре с друзьями .
[{{mminutes}}:{{sseconds}}] Ожидаем начала...    
.NET class String
(1)       Используют 5 человек

Комментарии

Ни одного комментария.
Написать тут
Описание:
source code
Автор:
zxserzh
Создан:
7 апреля 2011 в 15:45 (текущая версия от 7 апреля 2011 в 17:34)
Публичный:
Нет
Тип словаря:
Тексты
Цельные тексты, разделяемые пустой строкой (единственный текст на словарь также допускается).
Содержание:
1 // ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: String
**
**
** Purpose: Contains headers for the String class. Actual implementations
** are in String.cpp
**
**
===========================================================*/
namespace System {
using System.Text;
using System;
using System.Runtime.ConstrainedExecution;
using System.Globalization;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using va_list = System.ArgIterator;
//
// For Information on these methods, please see COMString.cpp
//
2 // The String class represents a static string of characters. Many of
// the String methods perform some type of transformation on the current
// instance and return the result as a new String. All comparison methods are
// implemented as a part of String. As with arrays, character positions
// (indices) are zero-based.
//
// When passing a null string into a constructor in VJ and VC, the null should be
// explicitly type cast to a String.
// For Example:
// String s = new String((String)null);
// Text.Out.WriteLine(s);
//
3 [System.Runtime.InteropServices.ComVisible(true)]
[Serializable] public sealed class String : IComparable, ICloneable, IConvertible, IEnumerable
#if GENERICS_WORK
, IComparable<String>, IEnumerable<char>, IEquatable<String>
#endif
{
//
//NOTE NOTE NOTE NOTE
//These fields map directly onto the fields in an EE StringObject. See object.h for the layout.
//
[NonSerialized]private int m_arrayLength;
[NonSerialized]private int m_stringLength;
[NonSerialized]private char m_firstChar;
//private static readonly char FmtMsgMarkerChar='%';
//private static readonly char FmtMsgFmtCodeChar='!';
//These are defined in Com99/src/vm/COMStringCommon.h and must be kept in [....].
private const int TrimHead = 0;
private const int TrimTail = 1;
private const int TrimBoth = 2;

// The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field which we can access
//from native.
public static readonly String Empty = "";

//
//Native Static Methods
//
4 // Joins an array of strings together as one string with a separator between each original string.
//
public static String Join (String separator, String[] value) {
if (value==null) {
throw new ArgumentNullException("value");
}
return Join(separator, value, 0, value.Length);
}
#if WIN64
private const int charPtrAlignConst = 3;
private const int alignConst = 7;
#else
private const int charPtrAlignConst = 1;
private const int alignConst = 3;
#endif

internal char FirstChar { get { return m_firstChar; } }
// Joins an array of strings together as one string with a separator between each original string.
//
public unsafe static String Join(String separator, String[] value, int startIndex, int count) {
//Treat null as empty string.
if (separator == null) {
separator = String.Empty;
}
//Range check the array
5 if (value == null) {
throw new ArgumentNullException("value");
}

if (startIndex < 0) {
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
}
if (count < 0) {
throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
}

if (startIndex > value.Length - count) {
throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
}
//If count is 0, that skews a whole bunch of the calculations below, so just special case that.
6 if (count == 0) {
return String.Empty;
}

int jointLength = 0;
//Figure out the total length of the strings in value
int endIndex = startIndex + count - 1;
for (int stringToJoinIndex = startIndex; stringToJoinIndex <= endIndex; stringToJoinIndex++) {
if (value[stringToJoinIndex] != null) {
jointLength += value[stringToJoinIndex].Length;
}
}

//Add enough room for the separator.
jointLength += (count - 1) * separator.Length;

// Note that we may not catch all overflows with this check (since we could have wrapped around the 4gb range any number of times
// and landed back in the positive range.) The input array might be modifed from other threads,
// so we have to do an overflow check before each append below anyway. Those overflows will get caught down there.
if ((jointLength < 0) || ((jointLength + 1) < 0) ) {
throw new OutOfMemoryException();
}
7 //If this is an empty string, just return.
if (jointLength == 0) {
return String.Empty;
}
string jointString = FastAllocateString( jointLength );
fixed (char * pointerToJointString = &jointString.m_firstChar) {
UnSafeCharBuffer charBuffer = new UnSafeCharBuffer( pointerToJointString, jointLength);
// Append the first string first and then append each following string prefixed by the separator.
charBuffer.AppendString( value[startIndex] );
for (int stringToJoinIndex = startIndex + 1; stringToJoinIndex <= endIndex; stringToJoinIndex++) {
charBuffer.AppendString( separator );
charBuffer.AppendString( value[stringToJoinIndex] );
}
BCLDebug.Assert(*(pointerToJointString + charBuffer.Length) == '\0', "String must be null-terminated!");
}
return jointString;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int nativeCompareOrdinal(String strA, String strB, bool bIgnoreCase);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int nativeCompareOrdinalEx(String strA, int indexA, String strB, int indexB, int count);
//This will not work in case-insensitive mode for any character greater than 0x80.
//We'll throw an ArgumentException.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe internal static extern int nativeCompareOrdinalWC(String strA, char *strBChars, bool bIgnoreCase, out bool success);
//
// This is a helper method for the security team. They need to uppercase some strings (guaranteed to be less
// than 0x80) before security is fully initialized. Without security initialized, we can't grab resources (the nlp's)
// from the assembly. This provides a workaround for that problem and should NOT be used anywhere else.
//
internal unsafe static string SmallCharToUpper(string strIn) {
BCLDebug.Assert(strIn != null, "strIn");
//
// Get the length and pointers to each of the buffers. Walk the length
// of the string and copy the characters from the inBuffer to the outBuffer,
// capitalizing it if necessary. We assert that all of our characters are
// less than 0x80.
//
int length = strIn.Length;
String strOut = FastAllocateString(length);
fixed (char * inBuff = &strIn.m_firstChar, outBuff = &strOut.m_firstChar) {
char c;

int upMask = ~0x20;
for(int i = 0; i < length; i++) {
c = inBuff[i];
BCLDebug.Assert((int)c < 0x80, "(int)c < 0x80");
8 //
// 0x20 is the difference between upper and lower characters in the lower
// 128 ASCII characters. And this bit off to make the chars uppercase.
//
if (c >= 'a' && c <= 'z') {
c = (char)((int)c & upMask);
}
outBuff[i] = c;
}

BCLDebug.Assert(outBuff[length]=='\0', "outBuff[length]=='\0'");
}
return strOut;
}
//
//
// NATIVE INSTANCE METHODS
//
//
//
// Search/Query methods
//
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
9 private unsafe static bool EqualsHelper(String strA, String strB)
{
int length = strA.Length;
if (length != strB.Length) return false;

fixed(char* ap = strA) fixed(char* bp = strB)
{
char* a = ap;
char* b = bp;
// unroll the loop
#if AMD64
// for AMD64 bit platform we unroll by 12 and
// check 3 qword at a time. This is less code
// than the 32 bit case and is shorter
// pathlength
while (length >= 12)
{
if (*(long*)a != *(long*)b) break;
if (*(long*)(a+4) != *(long*)(b+4)) break;
if (*(long*)(a+8) != *(long*)(b+8)) break;
a += 12; b += 12; length -= 12;
}
#else
while (length >= 10)
{
if (*(int*)a != *(int*)b) break;
if (*(int*)(a+2) != *(int*)(b+2)) break;
if (*(int*)(a+4) != *(int*)(b+4)) break;
if (*(int*)(a+6) != *(int*)(b+6)) break;
if (*(int*)(a+8) != *(int*)(b+8)) break;
a += 10; b += 10; length -= 10;
}
#endif
10 // This depends on the fact that the String objects are
// always zero terminated and that the terminating zero is not included
// in the length. For odd string sizes, the last compare will include
// the zero terminator.
while (length > 0)
{
if (*(int*)a != *(int*)b) break;
a += 2; b += 2; length -= 2;
}
return (length <= 0);
11 }
}

private unsafe static int CompareOrdinalHelper(String strA, String strB)
{
BCLDebug.Assert(strA != null && strB != null, "strings cannot be null!");
int length = Math.Min(strA.Length, strB.Length);
int diffOffset = -1;

fixed(char* ap = strA) fixed(char* bp = strB)
{
char* a = ap;
char* b = bp;
// unroll the loop
while (length >= 10)
{
if (*(int*)a != *(int*)b) {
diffOffset = 0;
break;
}
if (*(int*)(a+2) != *(int*)(b+2)) {
diffOffset = 2;
break;
}

if (*(int*)(a+4) != *(int*)(b+4)) {
diffOffset = 4;
break;
}
if (*(int*)(a+6) != *(int*)(b+6)) {
12 diffOffset = 6;
break;
}

if (*(int*)(a+8) != *(int*)(b+8)) {
diffOffset = 8;
break;
}
a += 10;
b += 10;
length -= 10;
}

if( diffOffset != -1) {
// we already see a difference in the unrolled loop above
a += diffOffset;
b += diffOffset;
int order;
if ( (order = (int)*a - (int)*b) != 0) {
return order;
}
BCLDebug.Assert( *(a+1) != *(b+1), "This byte must be different if we reach here!");
return ((int)*(a+1) - (int)*(b+1));
}
// now go back to slower code path and do comparison on 4 bytes one time.
// Following code also take advantage of the fact strings will
// use even numbers of characters (runtime will have a extra zero at the end.)
// so even if length is 1 here, we can still do the comparsion.
while (length > 0) {
if (*(int*)a != *(int*)b) {
13 break;
}
a += 2;
b += 2;
length -= 2;
}
if( length > 0) {
int c;
// found a different int on above loop
if ( (c = (int)*a - (int)*b) != 0) {
return c;
}
BCLDebug.Assert( *(a+1) != *(b+1), "This byte must be different if we reach here!");
return ((int)*(a+1) - (int)*(b+1));
}

// At this point, we have compared all the characters in at least one string.
// The longer string will be larger.
return strA.Length - strB.Length;
}
}
// Determines whether two strings match.
14 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public override bool Equals(Object obj) {
String str = obj as String;
if (str == null)
{
// exception will be thrown later for null this
if (this != null) return false;
}

return EqualsHelper(this, str);
}

// Determines whether two strings match.
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public bool Equals(String value) {
if (value == null)
{
// exception will be thrown later for null this
if (this != null) return false;
}

return EqualsHelper(this, value);
}
public bool Equals(String value, StringComparison comparisonType) {
if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
15 if( (Object)this == (Object)value) {
return true;
}
if( (Object)value == null) {
return false;
}
switch (comparisonType) {
case StringComparison.CurrentCulture:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.None) == 0);

case StringComparison.CurrentCultureIgnoreCase:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.IgnoreCase) == 0);
case StringComparison.InvariantCulture:
return (CultureInfo.InvariantCulture.CompareInfo.Compare(this, value, CompareOptions.None) == 0);

case StringComparison.InvariantCultureIgnoreCase:
return (CultureInfo.InvariantCulture.CompareInfo.Compare(this, value, CompareOptions.IgnoreCase) == 0);

case StringComparison.Ordinal:
return this.Equals(value);
case StringComparison.OrdinalIgnoreCase:
if( this.Length != value.Length)
return false;
else {
// If both strings are ASCII strings, we can take the fast path.
if (this.IsAscii() && value.IsAscii()) {
return (String.nativeCompareOrdinal(this, value, true) == 0);
}
// Take the slow path.
return (TextInfo.CompareOrdinalIgnoreCase(this, value) == 0);
}

default:
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
}
16 // Determines whether two Strings match.
public static bool Equals(String a, String b) {
if ((Object)a==(Object)b) {
return true;
}

if ((Object)a==null || (Object)b==null) {
return false;
}

return EqualsHelper(a, b);
}

public static bool Equals(String a, String b, StringComparison comparisonType) {
if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
if ((Object)a==(Object)b) {
return true;
}

if ((Object)a==null || (Object)b==null) {
return false;
}
17 switch (comparisonType) {
case StringComparison.CurrentCulture:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0);

case StringComparison.CurrentCultureIgnoreCase:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0);

case StringComparison.InvariantCulture:
return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0);
case StringComparison.InvariantCultureIgnoreCase:
return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0);

case StringComparison.Ordinal:
return EqualsHelper(a, b);

case StringComparison.OrdinalIgnoreCase:
if( a.Length != b.Length)
return false;
else {
// If both strings are ASCII strings, we can take the fast path.
if (a.IsAscii() && b.IsAscii()) {
return (String.nativeCompareOrdinal(a, b, true) == 0);
}
// Take the slow path.
return (TextInfo.CompareOrdinalIgnoreCase(a, b) == 0);
}
default:
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
}

Связаться
Выделить
Выделите фрагменты страницы, относящиеся к вашему сообщению
Скрыть сведения
Скрыть всю личную информацию
Отмена