Esempio n. 1
0
        public static object OpenIO([NotNull]BlockParam/*!*/ block, RubyClass/*!*/ self, [Optional]MutableString initialString, [Optional]MutableString mode) {
            MutableStringStream stream = new MutableStringStream(initialString ?? MutableString.CreateBinary());
            string ioMode = (mode != null) ? mode.ConvertToString() : "rb+";
            RubyIO io = new StringIO(self.Context, stream, ioMode);

            object result;
            block.Yield(io, out result);
            if (!io.Closed) {
                io.Close();
            }
            return result;
        }
Esempio n. 2
0
        public static RubyArray/*!*/ Unpack(RubyContext/*!*/ context, MutableString/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ format) {
            RubyArray result = new RubyArray(1 + self.Length / 2);
            using (MutableStringStream stream = new MutableStringStream(self)) {
                BinaryReader reader = new BinaryReader(stream);
                foreach (ArrayOps.FormatDirective directive in ArrayOps.FormatDirective.Enumerate(format.ToString())) {
                    int count, maxCount;
                    byte[] buffer;
                    MutableString str;
                    int nilCount = 0;
                    switch (directive.Directive) {
                        case '@':
                            stream.Position = directive.Count.HasValue ? directive.Count.Value : stream.Position;
                            break;

                        case 'A':
                        case 'a':
                            maxCount = (int)(stream.Length - stream.Position);
                            count = directive.Count.HasValue ? directive.Count.Value : maxCount;
                            if (count > maxCount) {
                                count = maxCount;
                            }
                            buffer = reader.ReadBytes(count);
                            str = MutableString.CreateBinary(buffer);
                            if (directive.Directive == 'A') {
                                // TODO: efficiency?
                                for (int pos = count - 1; pos >= 0; pos--) {
                                    if (buffer[pos] != 0 && buffer[pos] != 0x20) {
                                        break;
                                    }
                                    str.Remove(pos, 1);
                                }
                            }
                            result.Add(str);
                            break;

                        case 'Z':
                            maxCount = (int)(stream.Length - stream.Position);
                            count = directive.Count.HasValue ? directive.Count.Value : maxCount;
                            if (count > maxCount) {
                                count = maxCount;
                            }
                            buffer = reader.ReadBytes(count);
                            str = MutableString.CreateBinary(buffer);
                            for (int pos = 0; pos < count; pos++) {
                                if (buffer[pos] == 0) {
                                    str.Remove(pos, count - pos);
                                    break;
                                }
                            }
                            result.Add(str);
                            break;

                        case 'c':
                            count = CalculateCounts(stream, directive.Count, sizeof(sbyte), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadSByte());
                            }
                            break;

                        case 'C':
                            count = CalculateCounts(stream, directive.Count, sizeof(byte), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadByte());
                            }
                            break;

                        case 'i':
                        case 'l':
                            count = CalculateCounts(stream, directive.Count, sizeof(int), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadInt32());
                            }
                            break;

                        case 'I':
                        case 'L':
                            count = CalculateCounts(stream, directive.Count, sizeof(uint), out nilCount);
                            for (int j = 0; j < count; j++) {
                                unchecked {
                                    result.Add((int)reader.ReadUInt32());
                                }
                            }
                            break;

                        case 'm':
                            // TODO: Recognize "==" as end of base 64 encoding
                            int len = (int)(stream.Length - stream.Position);
                            char[] base64 = reader.ReadChars(len);
                            byte[] data = Convert.FromBase64CharArray(base64, 0, len);
                            result.Add(MutableString.CreateBinary(data));
                            break;

                        case 's':
                            count = CalculateCounts(stream, directive.Count, sizeof(short), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadInt16());
                            }
                            break;

                        case 'S':
                            count = CalculateCounts(stream, directive.Count, sizeof(ushort), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadUInt16());
                            }
                            break;

                        case 'U':
                            maxCount = (int)(stream.Length - stream.Position);
                            count = directive.Count.HasValue ? directive.Count.Value : maxCount;
                            int readCount = directive.Count.HasValue ? Encoding.UTF8.GetMaxByteCount(count) : count;
                            if (readCount > maxCount) {
                                readCount = maxCount;
                            }
                            long startPosition = stream.Position;
                            char[] charData = Encoding.UTF8.GetChars(reader.ReadBytes(readCount));
                            if (charData.Length > count) {
                                int actualCount = Encoding.UTF8.GetByteCount(charData, 0, count);
                                stream.Position = startPosition + actualCount;
                            } else if (charData.Length < count) {
                                count = charData.Length;
                            }
                            for (int j = 0; j < count; j++) {
                                result.Add((int)charData[j]);
                            }
                            break;

                        case 'X':
                            int len3 = directive.Count.HasValue ? directive.Count.Value : 0;
                            if (len3 > stream.Position) {
                                throw RubyExceptions.CreateArgumentError("X outside of string");
                            }
                            stream.Position -= len3;
                            break;

                        case 'x':
                            int len4 = directive.Count.HasValue ? directive.Count.Value : 0;
                            stream.Position += len4;
                            break;

                        case 'h':
                        case 'H':
                            maxCount = (int)(stream.Length - stream.Position) * 2;
                            result.Add(ToHex(reader, Math.Min(directive.Count ?? maxCount, maxCount), directive.Directive == 'h'));
                            break;

                        default:
                            throw RubyExceptions.CreateArgumentError(
                                String.Format("Unknown format directive '{0}'", directive.Directive));
                    }
                    for (int i = 0; i < nilCount; i++) {
                        result.Add(null);
                    }
                }
            }
            return result;
        }
Esempio n. 3
0
        public static MutableString/*!*/ Pack(
            ConversionStorage<IntegerValue>/*!*/ integerConversion, 
            ConversionStorage<MutableString>/*!*/ stringCast, 
            RubyContext/*!*/ context, RubyArray/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ format) {

            using (MutableStringStream stream = new MutableStringStream()) {
                BinaryWriter writer = new BinaryWriter(stream);
                int i = 0;
                foreach (FormatDirective directive in FormatDirective.Enumerate(format.ConvertToString())) {
                    int remaining = (self.Count - i);
                    int count = directive.Count.HasValue ? directive.Count.Value : remaining;
                    if (count > remaining) {
                        count = remaining;
                    }

                    MutableString str;
                    switch (directive.Directive) {
                        case '@':
                            count = 0;
                            stream.Position = directive.Count.HasValue ? directive.Count.Value : 1;
                            break;

                        case 'A':
                        case 'a':
                        case 'Z':
                            count = 1;
                            str = Protocols.CastToString(stringCast, self[i]);
                            char[] cstr = (str == null) ? new char[0] : str.ToString().ToCharArray();
                            int dataLen;
                            int paddedLen;
                            if (directive.Count.HasValue) {
                                paddedLen = directive.Count.Value;
                                dataLen = Math.Min(cstr.Length, paddedLen);
                            } else {
                                paddedLen = cstr.Length;
                                dataLen = cstr.Length;
                            }
                            writer.Write(cstr, 0, dataLen);
                            if (paddedLen > dataLen) {
                                byte fill = (directive.Directive == 'A') ? (byte)' ' : (byte)0;
                                for (int j = 0; j < (paddedLen - dataLen); j++) {
                                    writer.Write(fill);
                                }
                            }
                            if (directive.Directive == 'Z' && !directive.Count.HasValue) {
                                writer.Write((byte)0);
                            }
                            break;

                        case 'Q':
                        case 'q':
                            for (int j = 0; j < count; j++) {
                                writer.Write(Protocols.CastToUInt64Unchecked(integerConversion, self[i + j]));
                            }
                            break;

                        case 'l':
                        case 'i':
                            for (int j = 0; j < count; j++) {
                                writer.Write(unchecked((int)Protocols.CastToUInt32Unchecked(integerConversion, self[i + j])));
                            }
                            break;

                        case 'L':
                        case 'I':
                            for (int j = 0; j < count; j++) {
                                writer.Write(Protocols.CastToUInt32Unchecked(integerConversion, self[i + j]));
                            }
                            break;

                        case 'N': // unsigned 4-byte big-endian
                            WriteUInt32(integerConversion, writer, self, i, count, BitConverter.IsLittleEndian);
                            break;

                        case 'n': // unsigned 2-byte big-endian
                            WriteUInt16(integerConversion, writer, self, i, count, BitConverter.IsLittleEndian);
                            break;

                        case 'V': // unsigned 4-byte little-endian
                            WriteUInt32(integerConversion, writer, self, i, count, !BitConverter.IsLittleEndian);
                            break;

                        case 'v': // unsigned 2-byte little-endian
                            WriteUInt16(integerConversion, writer, self, i, count, !BitConverter.IsLittleEndian);
                            break;

                        case 's':
                            for (int j = 0; j < count; j++) {
                                writer.Write(unchecked((short)Protocols.CastToUInt32Unchecked(integerConversion, self[i + j])));
                            }
                            break;

                        case 'S':
                            for (int j = 0; j < count; j++) {
                                writer.Write(unchecked((ushort)Protocols.CastToUInt32Unchecked(integerConversion, self[i + j])));
                            }
                            break;

                        case 'c':
                            for (int j = 0; j < count; j++) {
                                writer.Write(unchecked((sbyte)Protocols.CastToUInt32Unchecked(integerConversion, self[i + j])));
                            }
                            break;

                        case 'C':
                            for (int j = 0; j < count; j++) {
                                writer.Write(unchecked((byte)Protocols.CastToUInt32Unchecked(integerConversion, self[i + j])));
                            }
                            break;

                        case 'm':
                            count = 1;
                            str = Protocols.CastToString(stringCast, self[i]);
                            char[] base64 = Convert.ToBase64String(str.ToByteArray()).ToCharArray();
                            for (int j = 0; j < base64.Length; j += 60) {
                                int len = base64.Length - j;
                                if (len > 60) {
                                    len = 60;
                                }
                                writer.Write(base64, j, len);
                                writer.Write('\n');
                            }
                            break;

                        case 'U':
                            char[] buffer = new char[count];
                            for (int j = 0; j < count; j++) {
                                buffer[j] = unchecked((char)Protocols.CastToUInt32Unchecked(integerConversion, self[i + j]));
                            }
                            writer.Write(Encoding.UTF8.GetBytes(buffer));
                            break;

                        case 'X':
                            count = 0;
                            int len3 = directive.Count.HasValue ? directive.Count.Value : 0;
                            if (len3 > stream.Position) {
                                throw RubyExceptions.CreateArgumentError("X outside of string");
                            }
                            stream.Position -= len3;
                            break;

                        case 'x':
                            count = 0;
                            int len4 = directive.Count.HasValue ? directive.Count.Value : 0;
                            for (int j = 0; j < len4; j++) {
                                writer.Write((byte)0);
                            }
                            break;

                        case 'h':
                        case 'H':
                            // MRI skips null, unlike in "m" directive:
                            if (self[i] != null) {
                                str = Protocols.CastToString(stringCast, self[i]);
                                FromHex(writer, str, directive.Count ?? str.GetByteCount(), directive.Directive == 'h');
                            }
                            break;

                        default:
                            throw RubyExceptions.CreateArgumentError(
                                String.Format("Unknown format directive '{0}'", directive.Directive));
                    }
                    i += count;
                    if (i >= self.Count) {
                        break;
                    }
                }
                stream.SetLength(stream.Position);
                return stream.String;
            }
        }
Esempio n. 4
0
        /*!*/
        public static MutableString Pack(
            ConversionStorage<IntegerValue>/*!*/ integerConversion,
            ConversionStorage<double>/*!*/ floatConversion,
            ConversionStorage<MutableString>/*!*/ stringCast,
            ConversionStorage<MutableString>/*!*/ tosConversion,
            RubyArray/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ format)
        {
            // TODO: encodings

            using (MutableStringStream stream = new MutableStringStream()) {
                int i = 0;
                foreach (FormatDirective directive in FormatDirective.Enumerate(format.ConvertToString())) {
                    int count = directive.Count ?? self.Count - i;

                    MutableString str;
                    switch (directive.Directive) {
                        case '@':
                            count = 0;
                            stream.SetLength(stream.Position = directive.Count.HasValue ? directive.Count.Value : 1);
                            break;

                        case 'A':
                        case 'a':
                        case 'Z':
                            count = 1;
                            WriteString(stream, directive, ToMutableString(stringCast, stream, GetPackArg(self, i)));
                            break;

                        case 'B':
                        case 'b':
                            count = 1;
                            WriteBits(
                                stream,
                                directive.Count,
                                directive.Directive == 'b',
                                str = GetPackArg(self, i) != null ? ToMutableString(stringCast, stream, GetPackArg(self, i)) : MutableString.FrozenEmpty
                            );
                            break;

                        case 'c':
                        case 'C':
                            for (int j = 0; j < count; j++) {
                                stream.WriteByte(unchecked((byte)Protocols.CastToUInt32Unchecked(integerConversion, GetPackArg(self, i + j))));
                            }
                            break;

                        case 'd': // 8-byte native-endian
                        case 'D':
                            WriteDouble(floatConversion, stream, self, i, count, false);
                            break;

                        case 'e': // 4-byte little-endian
                            WriteSingle(floatConversion, stream, self, i, count, !BitConverter.IsLittleEndian);
                            break;

                        case 'E': // 8-byte little-endian
                            WriteDouble(floatConversion, stream, self, i, count, !BitConverter.IsLittleEndian);
                            break;

                        case 'f': // 4-byte native-endian
                        case 'F':
                            WriteSingle(floatConversion, stream, self, i, count, false);
                            break;

                        case 'g': // 4-byte big-endian
                            WriteSingle(floatConversion, stream, self, i, count, BitConverter.IsLittleEndian);
                            break;

                        case 'G': // 8-byte big-endian
                            WriteDouble(floatConversion, stream, self, i, count, BitConverter.IsLittleEndian);
                            break;

                        case 'h':
                        case 'H':
                            // MRI skips null, unlike in "m" directive:
                            if (GetPackArg(self, i) != null) {
                                str = ToMutableString(stringCast, stream, GetPackArg(self, i));
                                FromHex(stream, str, directive.Count ?? str.GetByteCount(), directive.Directive == 'h');
                            }
                            count = 1;
                            break;

                        case 'Q':
                        case 'q': // (un)signed 8-byte native-endian
                            WriteUInt64(integerConversion, stream, self, i, count, false);
                            break;

                        case 'l':
                        case 'i':
                        case 'L':
                        case 'I': // (un)signed 4-byte native-endian
                            WriteUInt32(integerConversion, stream, self, i, count, false);
                            break;

                        case 'N': // (un)signed 4-byte big-endian
                            WriteUInt32(integerConversion, stream, self, i, count, BitConverter.IsLittleEndian);
                            break;

                        case 'n': // (un)signed 2-byte big-endian
                            WriteUInt16(integerConversion, stream, self, i, count, BitConverter.IsLittleEndian);
                            break;

                        case 'V': // (un)signed 4-byte little-endian
                            WriteUInt32(integerConversion, stream, self, i, count, !BitConverter.IsLittleEndian);
                            break;

                        case 'v': // (un)signed 2-byte little-endian
                            WriteUInt16(integerConversion, stream, self, i, count, !BitConverter.IsLittleEndian);
                            break;

                        case 's': // (un)signed 2-byte native-endian
                        case 'S':
                            WriteUInt16(integerConversion, stream, self, i, count, false);
                            break;

                        case 'm': // Base64
                            if (GetPackArg(self, i) == null) {
                                throw RubyExceptions.CreateTypeConversionError("nil", "String");
                            }
                            WriteBase64(stream, ToMutableString(stringCast, stream, GetPackArg(self, i)),
                                (directive.Count.HasValue && directive.Count.Value > 2) ? directive.Count.Value : 45
                            );
                            count = 1;
                            break;

                        case 'M': // quoted-printable, MIME encoding
                            count = 1;
                            if (GetPackArg(self, i) != null) {
                                var site = tosConversion.GetSite(ConvertToSAction.Make(tosConversion.Context));
                                MutableString s = site.Target(site, GetPackArg(self, i));
                                stream.String.TaintBy(s);
                                WritePrintedQuotable(stream, s,
                                    (directive.Count.HasValue && directive.Count.Value >= 2) ? directive.Count.Value : 72
                                );
                            }
                            break;

                        case 'u': // UU-encoded
                            if (GetPackArg(self, i) == null) {
                                throw RubyExceptions.CreateTypeConversionError("nil", "String");
                            }
                            RubyEncoder.EncodeUU(ToMutableString(stringCast, stream, GetPackArg(self, i)).ToByteArray(),
                                (directive.Count.HasValue && directive.Count.Value > 2) ? directive.Count.Value : 45,
                                stream
                            );
                            count = 1;
                            break;

                        case 'w': // BER-encoded
                            for (int j = 0; j < count; j++) {
                                WriteBer(stream, Protocols.CastToInteger(integerConversion, GetPackArg(self, i + j)));
                            }
                            break;

                        case 'U': // UTF8 code point
                            for (int j = 0; j < count; j++) {
                                RubyEncoder.WriteUtf8CodePoint(stream, Protocols.CastToInteger(integerConversion, GetPackArg(self, i + j)).ToInt32());
                            }
                            break;

                        case 'X':
                            count = 0;
                            int len3 = directive.Count.HasValue ? directive.Count.Value : 0;
                            if (len3 > stream.Position) {
                                throw RubyExceptions.CreateArgumentError("X outside of string");
                            }
                            stream.String.Write((int)stream.Position - len3, 0, len3);
                            stream.Position -= len3;
                            break;

                        case 'x':
                            count = 0;
                            int len4 = directive.Count.HasValue ? directive.Count.Value : 0;
                            stream.String.Write((int)stream.Position, 0, len4);
                            stream.Position += len4;
                            break;

                        default:
                            count = 0;
                            break;
                    }

                    i += count;
                }
                stream.SetLength(stream.Position);
                return stream.String.TaintBy(format);
            }
        }
Esempio n. 5
0
 private static MutableString ToMutableString(ConversionStorage<MutableString>/*!*/ stringCast, MutableStringStream/*!*/ stream, object value)
 {
     var site = stringCast.GetSite(ConvertToStrAction.Make(stringCast.Context));
     var result = site.Target(site, value);
     if (result != null) {
         stream.String.TaintBy(result);
     }
     return result;
 }
Esempio n. 6
0
 /*!*/
 private static MutableString ReadUU(MutableString/*!*/ data, ref int position)
 {
     var input = new MutableStringStream(data);
     var output = new MutableStringStream();
     input.Position = position;
     ReadUU(input, output);
     position = (int)input.Position;
     output.Dispose();
     return output.String;
 }
Esempio n. 7
0
        public static MutableString /*!*/ Pack(RubyContext /*!*/ context, RubyArray /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ format)
        {
            using (MutableStringStream stream = new MutableStringStream()) {
                BinaryWriter writer = new BinaryWriter(stream);
                int          i      = 0;
                foreach (FormatDirective directive in FormatDirective.Enumerate(format.ConvertToString()))
                {
                    int remaining = (self.Count - i);
                    int count     = directive.Count.HasValue ? directive.Count.Value : remaining;
                    if (count > remaining)
                    {
                        count = remaining;
                    }

                    MutableString str;
                    switch (directive.Directive)
                    {
                    case '@':
                        count           = 0;
                        stream.Position = directive.Count.HasValue ? directive.Count.Value : 1;
                        break;

                    case 'A':
                    case 'a':
                    case 'Z':
                        count = 1;
                        char[] cstr = Protocols.CastToString(context, self[i]).ToString().ToCharArray();
                        int    len1 = directive.Count.HasValue ? directive.Count.Value : cstr.Length;
                        int    len2 = (len1 > cstr.Length) ? cstr.Length : len1;
                        writer.Write(cstr, 0, len2);
                        if (len1 > len2)
                        {
                            byte fill = (directive.Directive == 'A') ? (byte)' ' : (byte)0;
                            for (int j = 0; j < (len1 - len2); j++)
                            {
                                writer.Write(fill);
                            }
                        }
                        if (directive.Directive == 'Z' && !directive.Count.HasValue)
                        {
                            writer.Write((byte)0);
                        }
                        break;

                    case 'Q':
                    case 'q':
                        for (int j = 0; j < count; j++)
                        {
                            writer.Write(Protocols.CastToUInt64Unchecked(context, self[i + j]));
                        }
                        break;

                    case 'l':
                    case 'i':
                        for (int j = 0; j < count; j++)
                        {
                            writer.Write(unchecked ((int)Protocols.CastToUInt32Unchecked(context, self[i + j])));
                        }
                        break;

                    case 'L':
                    case 'I':
                        for (int j = 0; j < count; j++)
                        {
                            writer.Write(Protocols.CastToUInt32Unchecked(context, self[i + j]));
                        }
                        break;

                    case 'N':     // unsigned 4-byte big-endian
                        WriteUInt32(writer, self, context, i, count, BitConverter.IsLittleEndian);
                        break;

                    case 'n':     // unsigned 2-byte big-endian
                        WriteUInt16(writer, self, context, i, count, BitConverter.IsLittleEndian);
                        break;

                    case 'V':     // unsigned 4-byte little-endian
                        WriteUInt32(writer, self, context, i, count, !BitConverter.IsLittleEndian);
                        break;

                    case 'v':     // unsigned 2-byte little-endian
                        WriteUInt16(writer, self, context, i, count, !BitConverter.IsLittleEndian);
                        break;

                    case 's':
                        for (int j = 0; j < count; j++)
                        {
                            writer.Write(unchecked ((short)Protocols.CastToUInt32Unchecked(context, self[i + j])));
                        }
                        break;

                    case 'S':
                        for (int j = 0; j < count; j++)
                        {
                            writer.Write(unchecked ((ushort)Protocols.CastToUInt32Unchecked(context, self[i + j])));
                        }
                        break;

                    case 'c':
                        for (int j = 0; j < count; j++)
                        {
                            writer.Write(unchecked ((sbyte)Protocols.CastToUInt32Unchecked(context, self[i + j])));
                        }
                        break;

                    case 'C':
                        for (int j = 0; j < count; j++)
                        {
                            writer.Write(unchecked ((byte)Protocols.CastToUInt32Unchecked(context, self[i + j])));
                        }
                        break;

                    case 'm':
                        count = 1;
                        str   = Protocols.CastToString(context, self[i]);
                        char[] base64 = Convert.ToBase64String(str.ToByteArray()).ToCharArray();
                        for (int j = 0; j < base64.Length; j += 60)
                        {
                            int len = base64.Length - j;
                            if (len > 60)
                            {
                                len = 60;
                            }
                            writer.Write(base64, j, len);
                            writer.Write('\n');
                        }
                        break;

                    case 'U':
                        char[] buffer = new char[count];
                        for (int j = 0; j < count; j++)
                        {
                            buffer[j] = unchecked ((char)Protocols.CastToUInt32Unchecked(context, self[i + j]));
                        }
                        writer.Write(Encoding.UTF8.GetBytes(buffer));
                        break;

                    case 'X':
                        count = 0;
                        int len3 = directive.Count.HasValue ? directive.Count.Value : 0;
                        if (len3 > stream.Position)
                        {
                            throw RubyExceptions.CreateArgumentError("X outside of string");
                        }
                        stream.Position -= len3;
                        break;

                    case 'x':
                        count = 0;
                        int len4 = directive.Count.HasValue ? directive.Count.Value : 0;
                        for (int j = 0; j < len4; j++)
                        {
                            writer.Write((byte)0);
                        }
                        break;

                    case 'h':
                    case 'H':
                        // MRI skips null, unlike in "m" directive:
                        if (self[i] != null)
                        {
                            str = Protocols.CastToString(context, self[i]);
                            FromHex(writer, str, directive.Count ?? str.GetByteCount(), directive.Directive == 'h');
                        }
                        break;

                    default:
                        throw RubyExceptions.CreateArgumentError(
                                  String.Format("Unknown format directive '{0}'", directive.Directive));
                    }
                    i += count;
                    if (i >= self.Count)
                    {
                        break;
                    }
                }
                stream.SetLength(stream.Position);
                return(stream.String);
            }
        }
Esempio n. 8
0
 private static MutableString ToMutableString(ConversionStorage<MutableString>/*!*/ stringCast, MutableStringStream/*!*/ stream, object value) {
     var result = Protocols.CastToString(stringCast, value);
     if (result != null) {
         stream.String.TaintBy(result);
     }
     return result;
 }
Esempio n. 9
0
 public static RubyIO CreateIO(RubyClass/*!*/ self, [Optional]MutableString initialString, [Optional]MutableString mode) {
     MutableStringStream stream = new MutableStringStream(initialString ?? MutableString.CreateBinary());
     string ioMode = (mode != null) ? mode.ConvertToString() : "rb+";
     return new StringIO(self.Context, stream, ioMode);
 }
Esempio n. 10
0
 protected StringIO(RubyContext/*!*/ context, MutableStringStream/*!*/ stream, string/*!*/ mode)
     : base(context, stream, mode) {
 }
Esempio n. 11
0
        public static RubyArray/*!*/ Unpack(RubyContext/*!*/ context, MutableString/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ format) {
            RubyArray result = new RubyArray(1 + self.Length / 2);
            using (MutableStringStream stream = new MutableStringStream(self)) {
                BinaryReader reader = new BinaryReader(stream);
                foreach (ArrayOps.FormatDirective directive in ArrayOps.FormatDirective.Enumerate(format.ToString())) {
                    int count, maxCount;
                    byte[] buffer;
                    MutableString str;
                    int nilCount = 0;
                    switch (directive.Directive) {
                        case '@':
                            if (directive.Count.HasValue) {
                                if (directive.Count.Value > stream.Length) {
                                    throw RubyExceptions.CreateArgumentError("@ outside of string");
                                }
                                stream.Position = directive.Count.Value > 0 ? directive.Count.Value : 0;
                            }
                            else {
                                stream.Position = stream.Length;
                            }
                            break;

                        case 'A':
                        case 'a':
                            maxCount = (int)(stream.Length - stream.Position);
                            count = directive.Count.HasValue ? directive.Count.Value : maxCount;
                            if (count > maxCount) {
                                count = maxCount;
                            }
                            buffer = reader.ReadBytes(count);
                            str = MutableString.CreateBinary(buffer);
                            if (directive.Directive == 'A') {
                                // TODO: efficiency?
                                for (int pos = count - 1; pos >= 0; pos--) {
                                    if (buffer[pos] != 0 && buffer[pos] != 0x20) {
                                        break;
                                    }
                                    str.Remove(pos, 1);
                                }
                            }
                            result.Add(str);
                            break;

                        case 'B':
                        case 'b':
                            if (stream.Length - stream.Position != 0) {
                                count = directive.Count.HasValue ? directive.Count.Value : (int)(stream.Length - stream.Position) * 8;
                                buffer = reader.ReadBytes((int)Math.Ceiling((double)count / 8));
                                if (count > buffer.Length * 8) {
                                    count = buffer.Length * 8;
                                }
                                str = MutableString.CreateBinary(count);

                                if ((directive.Directive == 'B' && BitConverter.IsLittleEndian) || (directive.Directive == 'b' && !BitConverter.IsLittleEndian)) {
                                    for (int i = 0; i < buffer.Length; i++) {
                                        byte b = buffer[i];
                                        int r = (b >> 4) | ((b & 0x0F) << 4);
                                        r = ((r & 0xCC) >> 2) | ((r & 0x33) << 2);
                                        r = ((r & 0xAA) >> 1) | ((r & 0x55) << 1);
                                        buffer[i] = (byte)r;
                                    }
                                }

                                for (int b = 0, i = 0; b < count; b++) {
                                    if (b == 8) {
                                        i++;
                                        b = 0;
                                        count -= 8;
                                    }
                                    str.Append(((buffer[i] & (1 << b)) != 0 ? '1' : '0'));
                                }
                            }
                            else {
                                str = MutableString.CreateEmpty();
                            }
                            result.Add(str);
                            break;

                        case 'Z':
                            maxCount = (int)(stream.Length - stream.Position);
                            count = directive.Count.HasValue ? directive.Count.Value : maxCount;
                            if (count > maxCount) {
                                count = maxCount;
                            }
                            buffer = reader.ReadBytes(count);
                            str = MutableString.CreateBinary(buffer);
                            for (int pos = 0; pos < count; pos++) {
                                if (buffer[pos] == 0) {
                                    str.Remove(pos, count - pos);
                                    if (!directive.Count.HasValue) {
                                        stream.Seek(pos - count + 1, SeekOrigin.End);
                                    }
                                    break;
                                }
                            }
                            result.Add(str);
                            break;

                        case 'c':
                            count = CalculateCounts(stream, directive.Count, sizeof(sbyte), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadSByte());
                            }
                            break;

                        case 'C':
                            count = CalculateCounts(stream, directive.Count, sizeof(byte), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadByte());
                            }
                            break;

                        case 'i':
                        case 'l':
                            count = CalculateCounts(stream, directive.Count, sizeof(int), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadInt32());
                            }
                            break;

                        case 'I':
                        case 'L':
                            count = CalculateCounts(stream, directive.Count, sizeof(uint), out nilCount);
                            for (int j = 0; j < count; j++) {
                                uint value = reader.ReadUInt32();
                                if (value <= Int32.MaxValue) {
                                    result.Add((int)value);
                                } else {
                                    result.Add((BigInteger)value);
                                }
                            }
                            break;

                        case 'v':
                            count = CalculateCounts(stream, directive.Count, sizeof(ushort), out nilCount);
                            for (int j = 0; j < count; j++) {
                                ushort value = reader.ReadUInt16();
                                if (!BitConverter.IsLittleEndian) {
                                    value = (ushort)(0x00FF & (value >> 8) |
                                                     0xFF00 & (value << 8));
                                }
                                result.Add((int)value);
                            }
                            break;

                        case 'V':
                            count = CalculateCounts(stream, directive.Count, sizeof(uint), out nilCount);
                            for (int j = 0; j < count; j++) {
                                uint value = reader.ReadUInt32();
                                if (!BitConverter.IsLittleEndian) {
                                    value = (0x000000FF & (value >> 24) |
                                             0x0000FF00 & (value >> 8) |
                                             0x00FF0000 & (value << 8) |
                                             0xFF000000 & (value << 24));
                                }
                                if (value <= Int32.MaxValue) {
                                    result.Add((int)value);
                                }
                                else {
                                    result.Add((BigInteger)value);
                                }
                            }
                            break;

                        case 'q':
                            count = CalculateCounts(stream, directive.Count, sizeof(long), out nilCount);
                            for (int j = 0; j < count; j++) {
                                long value = reader.ReadInt64();
                                if (!BitConverter.IsLittleEndian) {
                                    ulong uvalue = (ulong)value;
                                    uvalue = (0x00000000000000FF & (uvalue >> 56)) |
                                             (0x000000000000FF00 & (uvalue >> 40)) |
                                             (0x0000000000FF0000 & (uvalue >> 24)) |
                                             (0x00000000FF000000 & (uvalue >> 8))  |
                                             (0x000000FF00000000 & (uvalue << 8))  |
                                             (0x0000FF0000000000 & (uvalue << 24)) |
                                             (0x00FF000000000000 & (uvalue << 40)) |
                                             (0xFF00000000000000 & (uvalue << 56));
                                    value = (long)uvalue;
                                }
                                if (value <= Int32.MaxValue && value >= Int32.MinValue) {
                                    result.Add((int)value);
                                }
                                else {
                                    result.Add((BigInteger)value);
                                }
                            }
                            break;

                        case 'Q':
                            count = CalculateCounts(stream, directive.Count, sizeof(ulong), out nilCount);
                            nilCount = 0;
                            for (int j = 0; j < count; j++) {
                                ulong value = reader.ReadUInt64();
                                if (!BitConverter.IsLittleEndian) {
                                    value = (0x00000000000000FF & (value >> 56)) |
                                            (0x000000000000FF00 & (value >> 40)) |
                                            (0x0000000000FF0000 & (value >> 24)) |
                                            (0x00000000FF000000 & (value >> 8))  |
                                            (0x000000FF00000000 & (value << 8))  |
                                            (0x0000FF0000000000 & (value << 24)) |
                                            (0x00FF000000000000 & (value << 40)) |
                                            (0xFF00000000000000 & (value << 56));
                                }
                                if (value <= Int32.MaxValue) {
                                    result.Add((int)value);
                                }
                                else {
                                    result.Add((BigInteger)value);
                                }
                            }
                            break;

                        case 'm':
                            // TODO: Recognize "==" as end of base 64 encoding
                            int len = (int)(stream.Length - stream.Position);
                            char[] base64 = reader.ReadChars(len);
                            byte[] data = Convert.FromBase64CharArray(base64, 0, len);
                            result.Add(MutableString.CreateBinary(data));
                            break;

                        case 's':
                            count = CalculateCounts(stream, directive.Count, sizeof(short), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadInt16());
                            }
                            break;

                        case 'S':
                            count = CalculateCounts(stream, directive.Count, sizeof(ushort), out nilCount);
                            for (int j = 0; j < count; j++) {
                                result.Add((int)reader.ReadUInt16());
                            }
                            break;

                        case 'U':
                            maxCount = (int)(stream.Length - stream.Position);
                            count = directive.Count.HasValue ? directive.Count.Value : maxCount;
                            int readCount = directive.Count.HasValue ? Encoding.UTF8.GetMaxByteCount(count) : count;
                            if (readCount > maxCount) {
                                readCount = maxCount;
                            }
                            long startPosition = stream.Position;
                            char[] charData = Encoding.UTF8.GetChars(reader.ReadBytes(readCount));
                            if (charData.Length > count) {
                                int actualCount = Encoding.UTF8.GetByteCount(charData, 0, count);
                                stream.Position = startPosition + actualCount;
                            } else if (charData.Length < count) {
                                count = charData.Length;
                            }
                            for (int j = 0; j < count; j++) {
                                result.Add((int)charData[j]);
                            }
                            break;

                        case 'X':
                            int len3 = directive.Count.HasValue ? directive.Count.Value : 0;
                            if (len3 > stream.Position) {
                                throw RubyExceptions.CreateArgumentError("X outside of string");
                            }
                            stream.Position -= len3;
                            break;

                        case 'x':
                            int len4 = directive.Count.HasValue ? directive.Count.Value : 0;
                            stream.Position += len4;
                            break;

                        case 'h':
                        case 'H':
                            maxCount = (int)(stream.Length - stream.Position) * 2;
                            result.Add(ToHex(reader, Math.Min(directive.Count ?? maxCount, maxCount), directive.Directive == 'h'));
                            break;

                        default:
                            throw RubyExceptions.CreateArgumentError(
                                String.Format("Unknown format directive '{0}'", directive.Directive));
                    }
                    for (int i = 0; i < nilCount; i++) {
                        result.Add(null);
                    }
                }
            }
            return result;
        }