// Sebastien Pouliot <sebastien@ximian.com>
//
// (C) 2001 Ximian, Inc. http://www.ximian.com
-// Copyright (C) 2004 Novell (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using System.Text;
using System.Collections;
using System.Globalization;
using System.Runtime.CompilerServices;
+#if NET_2_0
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+#endif
+
namespace System
{
[Serializable]
- public sealed class String : IConvertible, IComparable, ICloneable, IEnumerable
+#if NET_2_0
+ [ComVisible (true)]
+ public sealed class String : IConvertible, ICloneable, IEnumerable, IComparable, IComparable<String>, IEquatable <String>
+#else
+ public sealed class String : IConvertible, ICloneable, IEnumerable, IComparable
+#endif
{
[NonSerialized] private int length;
[NonSerialized] private char start_char;
return !Equals (a, b);
}
+#if NET_2_0
+ [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
public override bool Equals (Object obj)
{
return Equals (this, obj as String);
}
+#if NET_2_0
+ [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
public bool Equals (String value)
{
return Equals (this, value);
return InternalSplit (separator, count);
}
- public String Substring (int startIndex)
+#if NET_2_0
+ [ComVisible (false)]
+ [MonoTODO]
+ public String[] Split (char[] separator, int count, StringSplitOptions options)
+ {
+ if (separator == null || separator.Length == 0)
+ return Split (WhiteChars, count, options);
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", "Count cannot be less than zero.");
+ if ((options != StringSplitOptions.None) && (options != StringSplitOptions.RemoveEmptyEntries))
+ throw new ArgumentException ("options must be one of the values in the StringSplitOptions enumeration", "options");
+
+ bool removeEmpty = (options & StringSplitOptions.RemoveEmptyEntries) == StringSplitOptions.RemoveEmptyEntries;
+
+ if (!removeEmpty)
+ return Split (separator, count);
+ else
+ throw new NotImplementedException ();
+ }
+
+ [ComVisible (false)]
+ public String[] Split (string[] separator, int count, StringSplitOptions options)
+ {
+ if (separator == null || separator.Length == 0)
+ return Split (WhiteChars, count, options);
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException ("count", "Count cannot be less than zero.");
+ if ((options != StringSplitOptions.None) && (options != StringSplitOptions.RemoveEmptyEntries))
+ throw new ArgumentException ("Illegal enum value: " + options + ".", "options");
+
+ bool removeEmpty = (options & StringSplitOptions.RemoveEmptyEntries) == StringSplitOptions.RemoveEmptyEntries;
+
+ if (count == 0 || (this == String.Empty && removeEmpty))
+ return new String [0];
+
+ ArrayList arr = new ArrayList ();
+
+ int pos = 0;
+ while (pos < this.Length) {
+ int matchIndex = -1;
+ int matchPos = Int32.MaxValue;
+
+ // Find the first position where any of the separators matches
+ for (int i = 0; i < separator.Length; ++i) {
+ string sep = separator [i];
+ if (sep == null || sep == String.Empty)
+ continue;
+
+ int match = IndexOf (sep, pos);
+ if (match > -1 && match < matchPos) {
+ matchIndex = i;
+ matchPos = match;
+ }
+ }
+
+ if (matchIndex == -1)
+ break;
+
+ if (matchPos == pos && removeEmpty) {
+ pos = matchPos + separator [matchIndex].Length;
+ }
+ else {
+ arr.Add (this.Substring (pos, matchPos - pos));
+
+ pos = matchPos + separator [matchIndex].Length;
+
+ if (arr.Count == count - 1) {
+ break;
+ }
+ }
+ }
+
+ if (arr.Count == 0)
+ return new String [] { this };
+ else {
+ if (removeEmpty && pos == this.Length) {
+ String[] res = new String [arr.Count];
+ arr.CopyTo (0, res, 0, arr.Count);
+
+ return res;
+ }
+ else {
+ String[] res = new String [arr.Count + 1];
+ arr.CopyTo (0, res, 0, arr.Count);
+ res [arr.Count] = this.Substring (pos);
+
+ return res;
+ }
+ }
+ }
+
+ [ComVisible (false)]
+ public String[] Split (char[] separator, StringSplitOptions options)
+ {
+ return Split (separator, Int32.MaxValue, options);
+ }
+
+ [ComVisible (false)]
+ public String[] Split (String[] separator, StringSplitOptions options)
+ {
+ return Split (separator, Int32.MaxValue, options);
+ }
+#endif
+
+ public unsafe String Substring (int startIndex)
{
if (startIndex < 0 || startIndex > this.length)
throw new ArgumentOutOfRangeException ("startIndex");
- string tmp = InternalAllocateStr (this.length - startIndex);
- InternalStrcpy (tmp, 0, this, startIndex, length - startIndex);
-
+ int newlen = this.length - startIndex;
+ string tmp = InternalAllocateStr (newlen);
+ if (newlen != 0) {
+ fixed (char *dest = tmp, src = this) {
+ memcpy ((byte*)dest, (byte*)(src + startIndex), newlen * 2);
+ }
+ }
return tmp;
}
- public String Substring (int startIndex, int length)
+ public unsafe String Substring (int startIndex, int length)
{
if (length < 0)
throw new ArgumentOutOfRangeException ("length", "< 0");
return String.Empty;
string tmp = InternalAllocateStr (length);
- InternalStrcpy (tmp, 0, this, startIndex, length);
+ fixed (char *dest = tmp, src = this) {
+ memcpy ((byte*)dest, (byte*)(src + startIndex), length * 2);
+ }
return tmp;
}
private static readonly char[] WhiteChars = { (char) 0x9, (char) 0xA, (char) 0xB, (char) 0xC, (char) 0xD,
+#if NET_2_0
+ (char) 0x85, (char) 0x1680, (char) 0x2028, (char) 0x2029,
+#endif
(char) 0x20, (char) 0xA0, (char) 0x2000, (char) 0x2001, (char) 0x2002, (char) 0x2003, (char) 0x2004,
(char) 0x2005, (char) 0x2006, (char) 0x2007, (char) 0x2008, (char) 0x2009, (char) 0x200A, (char) 0x200B,
(char) 0x3000, (char) 0xFEFF };
+ public String Trim ()
+ {
+ return InternalTrim (WhiteChars, 0);
+ }
+
public String Trim (params char[] trimChars)
{
if (trimChars == null || trimChars.Length == 0)
public bool EndsWith (String value)
{
- if (value == null)
- throw new ArgumentNullException ("value");
-
- if (value == String.Empty)
- return true;
-
- if (value.length > this.length)
- return false;
+ return EndsWith (value, false, CultureInfo.CurrentCulture);
+ }
- return (0 == Compare (this, length - value.length, value, 0, value.length));
+#if NET_2_0
+ public
+#else
+ internal
+#endif
+ bool EndsWith (String value, bool ignoreCase, CultureInfo culture)
+ {
+ return (culture.CompareInfo.IsSuffix (this, value,
+ ignoreCase ? CompareOptions.IgnoreCase :
+ CompareOptions.None));
}
public int IndexOfAny (char [] anyOf)
{
if (anyOf == null)
throw new ArgumentNullException ("anyOf");
- if (startIndex < 0 || startIndex >= this.length)
- throw new ArgumentOutOfRangeException ("sourceIndex");
+ if (startIndex < 0 || startIndex > this.length)
+ throw new ArgumentOutOfRangeException ("startIndex");
return InternalIndexOfAny (anyOf, startIndex, this.length - startIndex);
}
if (anyOf == null)
throw new ArgumentNullException ("anyOf");
- if (startIndex < 0 || startIndex > this.length)
+ if (startIndex < 0 || startIndex >= this.length)
throw new ArgumentOutOfRangeException ();
if (this.length == 0)
if (anyOf == null)
throw new ArgumentNullException ("anyOf");
- if ((startIndex < 0) || (startIndex > this.Length))
+ if ((startIndex < 0) || (startIndex >= this.Length))
throw new ArgumentOutOfRangeException ("startIndex", "< 0 || > this.Length");
if ((count < 0) || (count > this.Length))
throw new ArgumentOutOfRangeException ("count", "< 0 || > this.Length");
if (startIndex - count + 1 < 0)
throw new ArgumentOutOfRangeException ("startIndex - count + 1 < 0");
- if (value == String.Empty)
+ if (value.Length == 0)
return 0;
if (startIndex == 0 && this.length == 0)
return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf (this, value, startIndex, count);
}
+#if NET_2_0
+ public bool Contains (String value)
+ {
+ return IndexOf (value) != -1;
+ }
+
+ public static bool IsNullOrEmpty (String value)
+ {
+ return (value == null) || (value.Length == 0);
+ }
+
+ public string Remove (int startIndex)
+ {
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException ("startIndex", "StartIndex can not be less than zero");
+ if (startIndex >= this.length)
+ throw new ArgumentOutOfRangeException ("startIndex", "StartIndex must be less than the length of the string");
+
+ return Remove (startIndex, this.length - startIndex);
+ }
+#endif
+
public String PadLeft (int totalWidth)
{
return PadLeft (totalWidth, ' ');
public bool StartsWith (String value)
{
- if (value == null)
- throw new ArgumentNullException ("value");
-
- if (value == String.Empty)
- return true;
-
- if (this.length < value.length)
- return false;
+ return StartsWith (value, false, CultureInfo.CurrentCulture);
+ }
- return (0 == Compare (this, 0, value, 0 , value.length));
+#if NET_2_0
+ public
+#else
+ internal
+#endif
+ bool StartsWith (String value, bool ignoreCase, CultureInfo culture)
+ {
+ return (culture.CompareInfo.IsPrefix (this, value,
+ ignoreCase ? CompareOptions.IgnoreCase :
+ CompareOptions.None));
}
/* This method is culture insensitive */
if (oldValue == null)
throw new ArgumentNullException ("oldValue");
- if (oldValue == String.Empty)
+ if (oldValue.Length == 0)
throw new ArgumentException ("oldValue is the empty string.");
- if (this == String.Empty)
+ if (this.Length == 0)
return this;
-
- if (oldValue.Length == 0 || oldValue[0] == '\0') {
- return(this);
- }
if (newValue == null)
newValue = String.Empty;
return InternalReplace (oldValue, newValue, CultureInfo.CurrentCulture.CompareInfo);
}
- public String Remove (int startIndex, int count)
+ public unsafe String Remove (int startIndex, int count)
{
if (startIndex < 0)
throw new ArgumentOutOfRangeException ("startIndex", "< 0");
if (startIndex > this.length - count)
throw new ArgumentOutOfRangeException ("startIndex + count > this.length");
- return InternalRemove (startIndex, count);
+ String tmp = InternalAllocateStr (this.length - count);
+
+ fixed (char *dest = tmp, src = this) {
+ char *dst = dest;
+ memcpy ((byte*)dst, (byte*)src, startIndex * 2);
+ int skip = startIndex + count;
+ dst += startIndex;
+ memcpy ((byte*)dst, (byte*)(src + skip), (length - skip) * 2);
+ }
+ return tmp;
}
public String ToLower ()
{
- // CurrentCulture can never be invariant or null
- return InternalToLower (CultureInfo.CurrentCulture);
+ return ToLower (CultureInfo.CurrentCulture);
}
public String ToLower (CultureInfo culture)
if (culture.LCID == 0x007F) { // Invariant
return ToLowerInvariant ();
}
- return InternalToLower (culture);
+ return culture.TextInfo.ToLower (this);
}
+#if NET_2_0
+ public unsafe String ToLowerInvariant ()
+#else
internal unsafe String ToLowerInvariant ()
+#endif
{
string tmp = InternalAllocateStr (length);
fixed (char* source = &start_char, dest = tmp) {
public String ToUpper ()
{
- // CurrentCulture can never be invariant or null
- return InternalToUpper (CultureInfo.CurrentCulture);
+ return ToUpper (CultureInfo.CurrentCulture);
}
public String ToUpper (CultureInfo culture)
if (culture.LCID == 0x007F) { // Invariant
return ToUpperInvariant ();
}
- return InternalToUpper (culture);
+ return culture.TextInfo.ToUpper (this);
}
+#if NET_2_0
+ public unsafe String ToUpperInvariant ()
+#else
internal unsafe String ToUpperInvariant ()
+#endif
{
string tmp = InternalAllocateStr (length);
fixed (char* source = &start_char, dest = tmp) {
return this;
}
- public String Trim ()
- {
- return Trim (null);
- }
-
public static String Format (String format, Object arg0)
{
return Format (null, format, new Object[] {arg0});
// pad formatted string and append to result
if (width > str.length) {
- string pad = new String (' ', width - str.length);
+ const char padchar = ' ';
+ int padlen = width - str.length;
if (left_align) {
result.Append (str);
- result.Append (pad);
+ result.Append (padchar, padlen);
}
else {
- result.Append (pad);
+ result.Append (padchar, padlen);
result.Append (str);
}
}
}
if (start < format.length)
- result.Append (format.Substring (start));
+ result.Append (format, start, format.Length - start);
}
- public static String Copy (String str)
+ public unsafe static String Copy (String str)
{
if (str == null)
throw new ArgumentNullException ("str");
int length = str.length;
String tmp = InternalAllocateStr (length);
- InternalStrcpy (tmp, 0, str);
+ if (length != 0) {
+ fixed (char *dest = tmp, src = str) {
+ memcpy ((byte*)dest, (byte*)src, length * 2);
+ }
+ }
return tmp;
}
return obj.ToString ();
}
- public static String Concat (Object obj1, Object obj2)
+ public unsafe static String Concat (Object obj1, Object obj2)
{
string s1, s2;
return s1;
String tmp = InternalAllocateStr (s1.Length + s2.Length);
- InternalStrcpy (tmp, 0, s1);
- InternalStrcpy (tmp, s1.length, s2);
+ if (s1.Length != 0) {
+ fixed (char *dest = tmp, src = s1) {
+ memcpy ((byte*)dest, (byte*)src, s1.length * 2);
+ }
+ }
+ if (s2.Length != 0) {
+ fixed (char *dest = tmp, src = s2) {
+ memcpy ((byte*)(dest + s1.Length), (byte*)src, s2.length * 2);
+ }
+ }
return tmp;
}
return Concat (s1, s2, s3);
}
- //
- // Do *not* remove `internal' from that method
- //
- internal static String Concat (Object obj1, Object obj2, Object obj3, Object obj4)
+#if ! BOOTSTRAP_WITH_OLDLIB
+ [CLSCompliant(false)]
+ public static String Concat (Object obj1, Object obj2, Object obj3,
+ Object obj4, __arglist)
{
string s1, s2, s3, s4;
else
s3 = obj3.ToString ();
- if (obj4 == null)
- s4 = String.Empty;
- else
- s4 = obj4.ToString ();
+ ArgIterator iter = new ArgIterator (__arglist);
+ int argCount = iter.GetRemainingCount();
- return Concat (s1, s2, s3, s4);
-
+ StringBuilder sb = new StringBuilder ();
+ if (obj4 != null)
+ sb.Append (obj4.ToString ());
+
+ for (int i = 0; i < argCount; i++) {
+ TypedReference typedRef = iter.GetNextArg ();
+ sb.Append (TypedReference.ToObject (typedRef));
+ }
+
+ s4 = sb.ToString ();
+
+ return Concat (s1, s2, s3, s4);
}
+#endif
- public static String Concat (String s1, String s2)
+ public unsafe static String Concat (String s1, String s2)
{
if (s1 == null) {
if (s2 == null)
String tmp = InternalAllocateStr (s1.length + s2.length);
- InternalStrcpy (tmp, 0, s1);
- InternalStrcpy (tmp, s1.length, s2);
+ if (s1.Length != 0) {
+ fixed (char *dest = tmp, src = s1) {
+ memcpy ((byte*)dest, (byte*)src, s1.length * 2);
+ }
+ }
+ if (s2.Length != 0) {
+ fixed (char *dest = tmp, src = s2) {
+ memcpy ((byte*)(dest + s1.Length), (byte*)src, s2.length * 2);
+ }
+ }
return tmp;
}
- public static String Concat (String s1, String s2, String s3)
+ public unsafe static String Concat (String s1, String s2, String s3)
{
if (s1 == null){
if (s2 == null){
//return InternalConcat (s1, s2, s3);
String tmp = InternalAllocateStr (s1.length + s2.length + s3.length);
- InternalStrcpy (tmp, 0, s1);
- InternalStrcpy (tmp, s1.length, s2);
- InternalStrcpy (tmp, s1.length + s2.length, s3);
+ if (s1.Length != 0) {
+ fixed (char *dest = tmp, src = s1) {
+ memcpy ((byte*)dest, (byte*)src, s1.length * 2);
+ }
+ }
+ if (s2.Length != 0) {
+ fixed (char *dest = tmp, src = s2) {
+ memcpy ((byte*)(dest + s1.Length), (byte*)src, s2.length * 2);
+ }
+ }
+ if (s3.Length != 0) {
+ fixed (char *dest = tmp, src = s3) {
+ memcpy ((byte*)(dest + s1.Length + s2.Length), (byte*)src, s3.length * 2);
+ }
+ }
return tmp;
}
- public static String Concat (String s1, String s2, String s3, String s4)
+ public unsafe static String Concat (String s1, String s2, String s3, String s4)
{
if (s1 == null && s2 == null && s3 == null && s4 == null)
return String.Empty;
String tmp = InternalAllocateStr (s1.length + s2.length + s3.length + s4.length);
- InternalStrcpy (tmp, 0, s1);
- InternalStrcpy (tmp, s1.length, s2);
- InternalStrcpy (tmp, s1.length + s2.length, s3);
- InternalStrcpy (tmp, s1.length + s2.length + s3.length, s4);
+ if (s1.Length != 0) {
+ fixed (char *dest = tmp, src = s1) {
+ memcpy ((byte*)dest, (byte*)src, s1.length * 2);
+ }
+ }
+ if (s2.Length != 0) {
+ fixed (char *dest = tmp, src = s2) {
+ memcpy ((byte*)(dest + s1.Length), (byte*)src, s2.length * 2);
+ }
+ }
+ if (s3.Length != 0) {
+ fixed (char *dest = tmp, src = s3) {
+ memcpy ((byte*)(dest + s1.Length + s2.Length), (byte*)src, s3.length * 2);
+ }
+ }
+ if (s4.Length != 0) {
+ fixed (char *dest = tmp, src = s4) {
+ memcpy ((byte*)(dest + s1.Length + s2.Length + s3.Length), (byte*)src, s4.length * 2);
+ }
+ }
return tmp;
}
return InternalJoin (String.Empty, values, 0, values.Length);
}
- public String Insert (int startIndex, String value)
+ public unsafe String Insert (int startIndex, String value)
{
if (value == null)
throw new ArgumentNullException ("value");
if (startIndex < 0 || startIndex > this.length)
throw new ArgumentOutOfRangeException ();
- return InternalInsert (startIndex, value);
+ if (value.Length == 0)
+ return this;
+ if (this.Length == 0)
+ return value;
+ String tmp = InternalAllocateStr (this.length + value.length);
+
+ fixed (char *dest = tmp, src = this, val = value) {
+ char *dst = dest;
+ memcpy ((byte*)dst, (byte*)src, startIndex * 2);
+ dst += startIndex;
+ memcpy ((byte*)dst, (byte*)val, value.length * 2);
+ dst += value.length;
+ memcpy ((byte*)dst, (byte*)(src + startIndex), (length - startIndex) * 2);
+ }
+ return tmp;
}
if (str[ptr] == ',') {
// White space between ',' and number or sign.
- int start = ++ptr;
+ ++ptr;
while (Char.IsWhiteSpace (str [ptr]))
++ptr;
+ int start = ptr;
format = str.Substring (start, ptr - start);
}
}
+#if NET_2_0
+ [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public unsafe override int GetHashCode ()
+ {
+ fixed (char * c = this) {
+ char * cc = c;
+ char * end = cc + length - 1;
+ int h = 0;
+ for (;cc < end; cc += 2) {
+ h = (h << 5) - h + *cc;
+ h = (h << 5) - h + cc [1];
+ }
+ ++end;
+ if (cc < end)
+ h = (h << 5) - h + *cc;
+ return h;
+ }
+ }
+
+ /* helpers used by the runtime as well as above or eslewhere in corlib */
+ internal static unsafe void memset (byte *dest, int val, int len)
+ {
+ if (len < 8) {
+ while (len != 0) {
+ *dest = (byte)val;
+ ++dest;
+ --len;
+ }
+ return;
+ }
+ if (val != 0) {
+ val = val | (val << 8);
+ val = val | (val << 16);
+ }
+ // align to 4
+ int rest = (int)dest & 3;
+ if (rest != 0) {
+ rest = 4 - rest;
+ len -= rest;
+ do {
+ *dest = (byte)val;
+ ++dest;
+ --rest;
+ } while (rest != 0);
+ }
+ while (len >= 16) {
+ ((int*)dest) [0] = val;
+ ((int*)dest) [1] = val;
+ ((int*)dest) [2] = val;
+ ((int*)dest) [3] = val;
+ dest += 16;
+ len -= 16;
+ }
+ while (len >= 4) {
+ ((int*)dest) [0] = val;
+ dest += 4;
+ len -= 4;
+ }
+ // tail bytes
+ while (len > 0) {
+ *dest = (byte)val;
+ dest++;
+ len--;
+ }
+ }
+
+ internal static unsafe void memcpy4 (byte *dest, byte *src, int size) {
+ /*while (size >= 32) {
+ // using long is better than int and slower than double
+ // FIXME: enable this only on correct alignment or on platforms
+ // that can tolerate unaligned reads/writes of doubles
+ ((double*)dest) [0] = ((double*)src) [0];
+ ((double*)dest) [1] = ((double*)src) [1];
+ ((double*)dest) [2] = ((double*)src) [2];
+ ((double*)dest) [3] = ((double*)src) [3];
+ dest += 32;
+ src += 32;
+ size -= 32;
+ }*/
+ while (size >= 16) {
+ ((int*)dest) [0] = ((int*)src) [0];
+ ((int*)dest) [1] = ((int*)src) [1];
+ ((int*)dest) [2] = ((int*)src) [2];
+ ((int*)dest) [3] = ((int*)src) [3];
+ dest += 16;
+ src += 16;
+ size -= 16;
+ }
+ while (size >= 4) {
+ ((int*)dest) [0] = ((int*)src) [0];
+ dest += 4;
+ src += 4;
+ size -= 4;
+ }
+ while (size > 0) {
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ dest += 1;
+ src += 1;
+ --size;
+ }
+ }
+ static unsafe void memcpy2 (byte *dest, byte *src, int size) {
+ while (size >= 8) {
+ ((short*)dest) [0] = ((short*)src) [0];
+ ((short*)dest) [1] = ((short*)src) [1];
+ ((short*)dest) [2] = ((short*)src) [2];
+ ((short*)dest) [3] = ((short*)src) [3];
+ dest += 8;
+ src += 8;
+ size -= 8;
+ }
+ while (size >= 2) {
+ ((short*)dest) [0] = ((short*)src) [0];
+ dest += 2;
+ src += 2;
+ size -= 2;
+ }
+ if (size > 0)
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ }
+ static unsafe void memcpy1 (byte *dest, byte *src, int size) {
+ while (size >= 8) {
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ ((byte*)dest) [1] = ((byte*)src) [1];
+ ((byte*)dest) [2] = ((byte*)src) [2];
+ ((byte*)dest) [3] = ((byte*)src) [3];
+ ((byte*)dest) [4] = ((byte*)src) [4];
+ ((byte*)dest) [5] = ((byte*)src) [5];
+ ((byte*)dest) [6] = ((byte*)src) [6];
+ ((byte*)dest) [7] = ((byte*)src) [7];
+ dest += 8;
+ src += 8;
+ size -= 8;
+ }
+ while (size >= 2) {
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ ((byte*)dest) [1] = ((byte*)src) [1];
+ dest += 2;
+ src += 2;
+ size -= 2;
+ }
+ if (size > 0)
+ ((byte*)dest) [0] = ((byte*)src) [0];
+ }
+ static unsafe void memcpy (byte *dest, byte *src, int size) {
+ // FIXME: if pointers are not aligned, try to align them
+ // so a faster routine can be used. Handle the case where
+ // the pointers can't be reduced to have the same alignment
+ // (just ignore the issue on x86?)
+ if ((((int)dest | (int)src) & 3) != 0) {
+ if (((int)dest & 1) != 0 && ((int)src & 1) != 0 && size >= 1) {
+ dest [0] = src [0];
+ ++dest;
+ ++src;
+ --size;
+ }
+ if (((int)dest & 2) != 0 && ((int)src & 2) != 0 && size >= 2) {
+ ((short*)dest) [0] = ((short*)src) [0];
+ dest += 2;
+ src += 2;
+ size -= 2;
+ }
+ if ((((int)dest | (int)src) & 1) != 0) {
+ memcpy1 (dest, src, size);
+ return;
+ }
+ if ((((int)dest | (int)src) & 2) != 0) {
+ memcpy2 (dest, src, size);
+ return;
+ }
+ }
+ memcpy4 (dest, src, size);
+ }
+
[CLSCompliant (false), MethodImplAttribute (MethodImplOptions.InternalCall)]
unsafe public extern String (char *value);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public extern String (char c, int count);
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- public extern override int GetHashCode ();
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern static string InternalJoin (string separator, string[] value, int sIndex, int count);
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern String InternalInsert (int sourceIndex, String value);
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern String InternalReplace (char oldChar, char newChar);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern String InternalReplace (String oldValue, string newValue, CompareInfo comp);
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern String InternalRemove (int sIndex, int count);
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern void InternalCopyTo (int sIndex, char[] dest, int destIndex, int count);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern String InternalPad (int width, char chr, bool right);
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern String InternalToLower (CultureInfo culture);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern String InternalToUpper (CultureInfo culture);
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal extern static String InternalAllocateStr (int length);