Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Ungureanu <teromario@yahoo.com>2017-06-02 10:03:47 +0300
committerMarek Safar <marek.safar@gmail.com>2017-06-02 10:03:47 +0300
commit045232ef52603abcf570b771777489549301826b (patch)
treebbeea33bb03c3b61ff89ca397bf3bc12cb9ba109 /mcs/class/Mono.Posix
parenta560146b7ce6fe9ac36c69c7818c288befe8f113 (diff)
[Posix] Optimize string marshal code by using unsafe code (#4964)
Diffstat (limited to 'mcs/class/Mono.Posix')
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixEncoding.cs32
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixMarshal.cs45
2 files changed, 55 insertions, 22 deletions
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixEncoding.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixEncoding.cs
index 1d8e40ca45c..d869b1b90c6 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/UnixEncoding.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixEncoding.cs
@@ -300,17 +300,35 @@ public class UnixEncoding : Encoding
throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
}
+ unsafe {
+ fixed (char* p = s) {
+ fixed (byte* b = bytes) {
+ return GetBytes (p + charIndex, charCount, b + byteIndex, bytes.Length - byteIndex);
+ }
+ }
+ }
+ }
+
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException (bytes == null ? "bytes" : "chars");
+
+ if (charCount < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException (charCount < 0 ? "charCount" : "byteCount");
+
// Convert the characters into bytes.
char ch;
- int length = bytes.Length;
+ int length = byteCount;
uint pair;
- int posn = byteIndex;
+ int posn = 0;
+ int charIndex = 0;
while (charCount > 0) {
// Fetch the next UTF-16 character pair value.
- ch = s[charIndex++];
+ ch = chars [charIndex++];
if (ch >= '\uD800' && ch <= '\uDBFF' && charCount > 1) {
// This may be the start of a surrogate pair.
- pair = (uint)(s[charIndex]);
+ pair = (uint)(chars[charIndex]);
if (pair >= (uint)0xDC00 && pair <= (uint)0xDFFF) {
pair = (pair - (uint)0xDC00) +
((((uint)ch) - (uint)0xD800) << 10) +
@@ -326,7 +344,7 @@ public class UnixEncoding : Encoding
}
charCount -= 2;
if (charCount >= 0) {
- bytes[posn++] = (byte) s [charIndex++];
+ bytes[posn++] = (byte)chars [charIndex++];
}
continue;
} else {
@@ -365,7 +383,7 @@ public class UnixEncoding : Encoding
}
// Return the final count to the caller.
- return posn - byteIndex;
+ return posn;
}
// Internal version of "GetCharCount" which can handle a rolling
@@ -394,7 +412,7 @@ public class UnixEncoding : Encoding
uint leftSoFar = (leftOverCount & (uint)0x0F);
uint leftSize = ((leftOverCount >> 4) & (uint)0x0F);
while (count > 0) {
- ch = (uint)(bytes[index++]);
+ ch = (uint)(bytes [index++]);
++next_raw;
--count;
if (leftSize == 0) {
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixMarshal.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixMarshal.cs
index 334b6f2a49b..0b01eb19ad4 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/UnixMarshal.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixMarshal.cs
@@ -325,27 +325,42 @@ namespace Mono.Unix {
if (encoding == null)
throw new ArgumentNullException ("encoding");
- int min_byte_count = encoding.GetMaxByteCount(1);
- char[] copy = s.ToCharArray (index, count);
- byte[] marshal = new byte [encoding.GetByteCount (copy) + min_byte_count];
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException ((index < 0 ? "index" : "count"),
+ "Non - negative number required.");
- int bytes_copied = encoding.GetBytes (copy, 0, copy.Length, marshal, 0);
+ if (s.Length - index < count)
+ throw new ArgumentOutOfRangeException ("s", "Index and count must refer to a location within the string.");
- if (bytes_copied != (marshal.Length-min_byte_count))
- throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
+ int null_terminator_count = encoding.GetMaxByteCount (1);
+ int length_without_null = encoding.GetByteCount (s);
+ int marshalLength = checked (length_without_null + null_terminator_count);
- IntPtr mem = AllocHeap (marshal.Length);
+ IntPtr mem = AllocHeap (marshalLength);
if (mem == IntPtr.Zero)
throw new UnixIOException (Native.Errno.ENOMEM);
- bool copied = false;
- try {
- Marshal.Copy (marshal, 0, mem, marshal.Length);
- copied = true;
- }
- finally {
- if (!copied)
- FreeHeap (mem);
+ unsafe {
+ fixed (char* p = s) {
+ byte* marshal = (byte*)mem;
+ int bytes_copied;
+
+ try {
+ bytes_copied = encoding.GetBytes (p + index, count, marshal, marshalLength);
+ } catch {
+ FreeHeap (mem);
+ throw;
+ }
+
+ if (bytes_copied != length_without_null) {
+ FreeHeap (mem);
+ throw new NotSupportedException ("encoding.GetBytes() doesn't equal encoding.GetByteCount()!");
+ }
+
+ marshal += length_without_null;
+ for (int i = 0; i < null_terminator_count; ++i)
+ marshal[i] = 0;
+ }
}
return mem;