244 lines
9.5 KiB
C#
244 lines
9.5 KiB
C#
|
// ==++==
|
||
|
//
|
||
|
// 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.Diagnostics;
|
||
|
using System.Globalization;
|
||
|
using System.Threading;
|
||
|
using System.Collections;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using Microsoft.Bartok.Runtime;
|
||
|
|
||
|
//
|
||
|
// The String class represents a static string of characters.
|
||
|
//
|
||
|
//| <include path='docs/doc[@for="String"]/*' />
|
||
|
[CCtorIsRunDuringStartup]
|
||
|
[AccessedByRuntime("referenced from c++")]
|
||
|
public sealed partial class String : IComparable, IEnumerable {
|
||
|
|
||
|
//
|
||
|
//NOTE NOTE NOTE NOTE
|
||
|
//These fields map directly onto the fields in an EE StringObject. See object.h for the layout.
|
||
|
//Be careful changing these fields or adding any new fields.
|
||
|
//
|
||
|
[RequiredByBartok]
|
||
|
private int m_arrayLength;
|
||
|
[AccessedByRuntime("referenced from c++")]
|
||
|
private int m_stringLength;
|
||
|
[AccessedByRuntime("referenced from c++")]
|
||
|
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 sync.
|
||
|
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.
|
||
|
//| <include path='docs/doc[@for="String.Empty"]/*' />
|
||
|
public static readonly String Empty = "";
|
||
|
|
||
|
//
|
||
|
// Constructors
|
||
|
//
|
||
|
|
||
|
// Creates a new string with the characters copied in from ptr. If
|
||
|
// ptr is null, a string initialized to ";<;No Object>;"; (i.e.,
|
||
|
// String.NullString) is created.
|
||
|
//
|
||
|
// Issue: This method is only accessible from VC.
|
||
|
//| <include path='docs/doc[@for="String.String"]/*' />
|
||
|
[CLSCompliant(false), MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
unsafe public extern String(char *value);
|
||
|
//| <include path='docs/doc[@for="String.String1"]/*' />
|
||
|
[CLSCompliant(false), MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
unsafe public extern String(char *value, int startIndex, int length);
|
||
|
|
||
|
//| <include path='docs/doc[@for="String.String2"]/*' />
|
||
|
[CLSCompliant(false), MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
unsafe public extern String(sbyte *value);
|
||
|
//| <include path='docs/doc[@for="String.String3"]/*' />
|
||
|
[CLSCompliant(false), MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
unsafe public extern String(sbyte *value, int startIndex, int length);
|
||
|
|
||
|
// Creates a new string from the characters in a subarray. The new string will
|
||
|
// be created from the characters in value between startIndex and
|
||
|
// startIndex + length - 1.
|
||
|
//
|
||
|
//| <include path='docs/doc[@for="String.String7"]/*' />
|
||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
public extern String(char [] value, int startIndex, int length);
|
||
|
|
||
|
// Creates a new string from the characters in a subarray. The new string will be
|
||
|
// created from the characters in value.
|
||
|
//
|
||
|
//| <include path='docs/doc[@for="String.String5"]/*' />
|
||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
public extern String(char [] value);
|
||
|
|
||
|
//| <include path='docs/doc[@for="String.String6"]/*' />
|
||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||
|
public extern String(char c, int count);
|
||
|
|
||
|
/**
|
||
|
* Creates a new string with the characters copied in from <i>ptr</i>. If
|
||
|
* <i>ptr</i> is null, a string initialized to
|
||
|
* "<No Object>" (i.e., <code>String.NullString</code>)
|
||
|
* is created.
|
||
|
*
|
||
|
* Issue: This method is only accessible from VC.
|
||
|
* @issue The verifier needs to recognize that this is not necessarily
|
||
|
* secure.
|
||
|
*
|
||
|
* @param ptr this is a WCHAR *.
|
||
|
*
|
||
|
*/
|
||
|
//| <include path='docs/doc[@for="String.String"]/*' />
|
||
|
[CLSCompliant(false)]
|
||
|
public unsafe static String StringCTOR(char *valuePtr) {
|
||
|
// See also Lightning\Src\VM\COMString.cpp::StringInitWCHARPtr
|
||
|
if (valuePtr == null) {
|
||
|
return String.Empty;
|
||
|
}
|
||
|
// First figure out how many characters the string has
|
||
|
int count = 0;
|
||
|
char *cursor = valuePtr;
|
||
|
int c = *cursor;
|
||
|
while (c != 0) {
|
||
|
count++;
|
||
|
cursor++;
|
||
|
c = *cursor;
|
||
|
}
|
||
|
// Allocate and fill in the string object
|
||
|
if (count == 0) {
|
||
|
return String.Empty;
|
||
|
}
|
||
|
else {
|
||
|
String result = FastAllocateString(count);
|
||
|
FillStringCharPtr(result, 0, valuePtr, count);
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//| <include path='docs/doc[@for="String.String1"]/*' />
|
||
|
[CLSCompliant(false)]
|
||
|
public unsafe static String StringCTOR(char *valuePtr, int startIndex,
|
||
|
int length) {
|
||
|
// See also Lightning\Src\VM\COMString.cpp::StringInitWCHARPtrPartial
|
||
|
if (valuePtr == null) {
|
||
|
return String.Empty;
|
||
|
}
|
||
|
if (length < 0) {
|
||
|
throw new ArgumentOutOfRangeException("length is negative");
|
||
|
}
|
||
|
if (startIndex < 0) {
|
||
|
throw new ArgumentOutOfRangeException("startIndex is negative");
|
||
|
}
|
||
|
if (length == 0) {
|
||
|
return String.Empty;
|
||
|
}
|
||
|
else {
|
||
|
String result = FastAllocateString(length);
|
||
|
FillStringCharPtr(result, 0, valuePtr + startIndex, length);
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//| <include path='docs/doc[@for="String.String1"]/*' />
|
||
|
[CLSCompliant(false)]
|
||
|
public unsafe static String StringCTOR(byte *valuePtr, int startIndex,
|
||
|
int length) {
|
||
|
// See also Lightning\Src\VM\COMString.cpp::StringInitWCHARPtrPartial
|
||
|
if (valuePtr == null) {
|
||
|
return String.Empty;
|
||
|
}
|
||
|
if (length < 0) {
|
||
|
throw new ArgumentOutOfRangeException("length is negative");
|
||
|
}
|
||
|
if (startIndex < 0) {
|
||
|
throw new ArgumentOutOfRangeException("startIndex is negative");
|
||
|
}
|
||
|
if (length == 0) {
|
||
|
return String.Empty;
|
||
|
}
|
||
|
else {
|
||
|
String result = FastAllocateString(length);
|
||
|
FillStringBytePtr(result, 0, valuePtr + startIndex, length);
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//| <include path='docs/doc[@for="String.String2"]/*' />
|
||
|
[CLSCompliant(false)]
|
||
|
public unsafe static String StringCTOR(sbyte *valuePtr) {
|
||
|
// See also Lightning\Src\VM\COMString.cpp::StringInitCharPtr
|
||
|
return StringInitCharHelper(valuePtr, -1);
|
||
|
}
|
||
|
|
||
|
//| <include path='docs/doc[@for="String.String3"]/*' />
|
||
|
[CLSCompliant(false)]
|
||
|
public unsafe static String StringCTOR(sbyte *valuePtr, int startIndex,
|
||
|
int length) {
|
||
|
// See also Lightning\Src\VM\COMString.cpp::StringInitCharPtrPartial
|
||
|
if (startIndex < 0) {
|
||
|
throw new ArgumentOutOfRangeException("startIndex is negative");
|
||
|
}
|
||
|
if (length < 0) {
|
||
|
throw new ArgumentOutOfRangeException("length is negative");
|
||
|
}
|
||
|
return StringInitCharHelper(valuePtr + startIndex, length);
|
||
|
}
|
||
|
|
||
|
private unsafe static String StringInitCharHelper(sbyte *valuePtr,
|
||
|
int length) {
|
||
|
// See also Lightning\Src\VM\COMString.cpp::StringInitCharHelper
|
||
|
throw new Exception("StringInitCharHelper is not implemented in Bartok!");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Other special methods
|
||
|
//
|
||
|
|
||
|
/// This is an EE implemented function so that the JIT can recognise it and
|
||
|
/// treat it specially by eliminating checks on character fetches.
|
||
|
[NoHeapAllocation]
|
||
|
private int InternalLength() {
|
||
|
// See also Lightning\Src\VM\COMString.cpp::Length
|
||
|
// See also Lightning\Src\VM\object.h::GetStringLength
|
||
|
return this.m_stringLength;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This is just designed to prevent compiler warnings.
|
||
|
// This field is used from native, but we need to prevent the compiler warnings.
|
||
|
//
|
||
|
#if _DEBUG
|
||
|
private void DontTouchThis() {
|
||
|
m_arrayLength = 0;
|
||
|
m_stringLength = 0;
|
||
|
m_firstChar = m_firstChar;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
}
|