Exemplo n.º 1
0
        public static void SetPreviousByte(StringIO /*!*/ self, [DefaultProtocol] int b)
        {
            // MRI: this checks if the IO is readable although it actually modifies the string:
            MutableString content = self.GetReadableContent();

            int pos = self._position - 1;

            if (pos >= 0)
            {
                int length = content.GetByteCount();
                try {
                    if (pos >= length)
                    {
                        content.Append(0, pos - length);
                        content.Append(unchecked ((byte)b));
                    }
                    else
                    {
                        content.SetByte(pos, unchecked ((byte)b));
                    }
                    self._position = pos;
                } catch (InvalidOperationException) {
                    throw RubyExceptions.CreateIOError("not modifiable string");
                }
            }
        }
Exemplo n.º 2
0
        private static MutableString ReadLine(MutableString /*!*/ content, MutableString separator, ref int position)
        {
            int length = content.GetByteCount();

            if (position >= length)
            {
                return(null);
            }

            int oldPosition = position;

            if (separator == null)
            {
                position = length;
            }
            else if (separator.IsEmpty)
            {
                // skip initial ends of line:
                while (oldPosition < length && content.GetByte(oldPosition) == '\n')
                {
                    oldPosition++;
                }

                position = content.IndexOf(ParagraphSeparator, oldPosition);
                position = (position != -1) ? position + 1 : length;
            }
            else
            {
                position = content.IndexOf(separator, oldPosition);
                position = (position != -1) ? position + separator.Length : length;
            }

            return(content.GetSlice(oldPosition, position - oldPosition));
        }
Exemplo n.º 3
0
        public static int Write(StringIO /*!*/ self, [NotNull] MutableString /*!*/ value)
        {
            var content      = self.GetWritableContent();
            int length       = content.GetByteCount();
            var bytesWritten = value.GetByteCount();
            int pos;

            if ((self._mode & IOMode.WriteAppends) != 0)
            {
                pos = length;
            }
            else
            {
                pos = self._position;
            }

            try {
                content.WriteBytes(pos, value, 0, bytesWritten);
            } catch (InvalidOperationException) {
                throw RubyExceptions.CreateIOError("not modifiable string");
            }

            content.TaintBy(value);
            self._position = pos + bytesWritten;
            return(bytesWritten);
        }
Exemplo n.º 4
0
 public static Win32API /*!*/ Reinitialize(Win32API /*!*/ self,
                                           [DefaultProtocol, NotNull] MutableString /*!*/ libraryName,
                                           [DefaultProtocol, NotNull] MutableString /*!*/ functionName,
                                           [DefaultProtocol, NotNull] MutableString /*!*/ parameterTypes,
                                           [DefaultProtocol, NotNull] MutableString /*!*/ returnType)
 {
     return(self.Reinitialize(
                GetFunction(libraryName, functionName),
                MakeSignature(parameterTypes.GetByteCount(), parameterTypes.GetByte),
                returnType.IsEmpty ? ArgType.None : ToArgType(returnType.GetByte(0))
                ));
 }
Exemplo n.º 5
0
        private static int ReadUtf8CodePoint(MutableString/*!*/ data, ref int index) {
            int length = data.GetByteCount();
            if (index >= length) {
                return -1;
            }
            int b = data.GetByte(index++);
            int count, mask;
            if ((b & 0x80) == 0) {
                count = 1;
                mask = 0xff;
            } else if ((b & 0xe0) == 0xc0) {
                count = 2;
                mask = 0x1f;
            } else if ((b & 0xf0) == 0xe0) {
                count = 3;
                mask = 0x0f;
            } else if ((b & 0xf8) == 0xf0) {
                count = 4;
                mask = 0x07;
            } else if ((b & 0xfc) == 0xf8) {
                count = 5;
                mask = 0x03;
            } else if ((b & 0xfe) == 0xfc) {
                count = 6;
                mask = 0x01;
            } else {
                throw RubyExceptions.CreateArgumentError("malformed UTF-8 character");
            }

            int codepoint = b & mask;
            for (int i = 1; i < count; i++) {
                if (index >= length) {
                    throw RubyExceptions.CreateArgumentError(
                        "malformed UTF-8 character (expected {0} bytes, given {1} bytes)", count, i
                    );
                }
                b = data.GetByte(index++);
                if ((b & 0xc0) != 0x80) {
                    throw RubyExceptions.CreateArgumentError("malformed UTF-8 character");
                }

                codepoint = (codepoint << 6) | (b & 0x3f);
            }

            int requiredCount;
            int mark;
            GetCodePointByteCount(codepoint, out requiredCount, out mark);
            if (requiredCount != count) {
                throw RubyExceptions.CreateArgumentError("redundant UTF-8 sequence");
            }
            return codepoint;
        }
Exemplo n.º 6
0
        public static int Send(ConversionStorage <int> /*!*/ fixnumCast, RubyBasicSocket /*!*/ self,
                               [DefaultProtocol, NotNull] MutableString /*!*/ message, object flags, [DefaultProtocol, NotNull] MutableString /*!*/ to)
        {
            Protocols.CheckSafeLevel(fixnumCast.Context, 4, "send");
            // Convert the parameters
            SocketFlags socketFlags = ConvertToSocketFlag(fixnumCast, flags);
            // Unpack the socket address information from the to parameter
            SocketAddress address = new SocketAddress(AddressFamily.InterNetwork);

            for (int i = 0; i < to.GetByteCount(); i++)
            {
                address[i] = to.GetByte(i);
            }
            EndPoint toEndPoint = self.Socket.LocalEndPoint.Create(address);

            return(self.Socket.SendTo(message.ConvertToBytes(), socketFlags, toEndPoint));
        }
Exemplo n.º 7
0
        public static int Send(RubyContext /*!*/ context, RubyBasicSocket /*!*/ self, object message, object flags, object to)
        {
            Protocols.CheckSafeLevel(context, 4, "send");
            // Convert the parameters
            SocketFlags   socketFlags  = ConvertToSocketFlag(context, flags);
            MutableString strMessage   = Protocols.CastToString(context, message);
            MutableString strToAddress = Protocols.CastToString(context, to);
            // Unpack the socket address information from the to parameter
            SocketAddress address = new SocketAddress(AddressFamily.InterNetwork);

            for (int i = 0; i < strToAddress.GetByteCount(); i++)
            {
                address[i] = strToAddress.GetByte(i);
            }
            EndPoint toEndPoint = self.Socket.LocalEndPoint.Create(address);

            return(self.Socket.SendTo(strMessage.ConvertToBytes(), socketFlags, toEndPoint));
        }
Exemplo n.º 8
0
        /// <summary>
        /// Returns true if the string binary representation contains bytes from set: 0..0x1f + 0x7f..0xff - [0x0a, 0x0d].
        /// </summary>
        internal static bool ContainsBinaryData(MutableString /*!*/ str)
        {
            if (!str.IsAscii())
            {
                return(true);
            }

            // for ascii strings we can iterate over bytes or characters without converting the string repr:
            for (int i = 0; i < str.GetByteCount(); i++)
            {
                byte b = str.GetByte(i);
                if (b < 0x20 && b != 0x0a && b != 0x0d || b >= 0x7f)
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 9
0
        public static object GetChecksum(MutableString/*!*/ self, [DefaultProtocol, DefaultParameterValue(16)]int bitCount) {
            int length = self.GetByteCount();
            uint mask = (bitCount > 31) ? 0xffffffff : (1U << bitCount) - 1;
            uint sum = 0;
            for (int i = 0; i < length; i++) {
                byte b = self.GetByte(i);
                try {
                    checked { sum = (sum + b) & mask; }
                } catch (OverflowException) {
                    return GetBigChecksum(self, i, sum, bitCount);
                }
            }

            return (sum > Int32.MaxValue) ? (BigInteger)sum : (object)(int)sum;
        }
Exemplo n.º 10
0
 public static MutableString GetSubstring(ConversionStorage<int>/*!*/ fixnumCast, MutableString/*!*/ self, [NotNull]Range/*!*/ range) {
     int begin, count;
     if (!NormalizeSubstringRange(fixnumCast, range, self.GetByteCount(), out begin, out count)) {
         return null;
     }
     return (count < 0) ? self.CreateInstance().TaintBy(self) : GetSubstring(self, begin, count);
 }
Exemplo n.º 11
0
 public static object GetChar(MutableString/*!*/ self, [DefaultProtocol]int index) {
     return InExclusiveRangeNormalized(self.GetByteCount(), ref index) ? ScriptingRuntimeHelpers.Int32ToObject(self.GetByte(index)) : null;
 }
Exemplo n.º 12
0
        public static object LastIndexOf(MutableString/*!*/ self,
            int character, [DefaultProtocol, DefaultParameterValue(Int32.MaxValue)]int start) {

            if (!self.IsBinaryEncoded && !self.Encoding.IsKCoding && !self.IsAscii()) {
                throw RubyExceptions.CreateTypeError("type mismatch: Fixnum given");
            }

            int byteCount = self.GetByteCount();
            start = IListOps.NormalizeIndex(byteCount, start);
            if (start < 0 || character < 0 || character > 255) {
                return null;
            }

            if (start >= byteCount) {
                start = byteCount - 1;
            }
            
            int result = self.LastIndexOf((byte)character, start);
            return (result != -1) ? ScriptingRuntimeHelpers.Int32ToObject(result) : null;
        }
Exemplo n.º 13
0
 public static int GetLength(MutableString/*!*/ self) {
     return (self.Encoding.IsKCoding) ? self.GetByteCount() : self.GetCharCount();
 }
Exemplo n.º 14
0
        public MutableString ReadLine(MutableString/*!*/ separator, RubyEncoding/*!*/ encoding, bool preserveEndOfLines) {
            int b = ReadByteNormalizeEoln(preserveEndOfLines);
            if (b == -1) {
                return null;
            }

            int separatorOffset = 0;
            int separatorLength = separator.GetByteCount();
            MutableString result = MutableString.CreateBinary(encoding);

            do {
                result.Append((byte)b);

                if (b == separator.GetByte(separatorOffset)) {
                    if (separatorOffset == separatorLength - 1) {
                        break;
                    }
                    separatorOffset++;
                } else if (separatorOffset > 0) {
                    separatorOffset = 0;
                }

                b = ReadByteNormalizeEoln(preserveEndOfLines);
            } while (b != -1);

            return result;
        }
Exemplo n.º 15
0
        // count == Int32.MaxValue means means no bound
        public int AppendBytes(MutableString/*!*/ buffer, int count, bool preserveEndOfLines) {
            ContractUtils.RequiresNotNull(buffer, "buffer");
            ContractUtils.Requires(count >= 0, "count");

            if (count == 0) {
                return 0;
            }

            bool readAll = count == Int32.MaxValue;

            buffer.SwitchToBytes();
            int initialBufferSize = buffer.GetByteCount();
            if (preserveEndOfLines) {
                AppendRawBytes(buffer, count);
            } else {
                // allocate 3 more bytes at the end for a backstop and possible LF:
                byte[] bytes = Utils.EmptyBytes;

                int done = initialBufferSize;
                bool eof;
                do {
                    AppendRawBytes(buffer, readAll ? 1024 : count);
                    int end = buffer.GetByteCount();
                    int bytesRead = end - done;
                    if (bytesRead == 0) {
                        break;
                    }

                    eof = bytesRead < count;

                    buffer.EnsureCapacity(end + 3);
                    bytes = buffer.GetByteArray();

                    if (bytes[end - 1] == CR && PeekByte(0) == LF) {
                        ReadByte();
                        bytes[end++] = LF;
                    }

                    // insert backstop:
                    bytes[end] = CR;
                    bytes[end + 1] = LF;

                    int last = IndexOfCrLf(bytes, done);
                    count -= last - done;
                    done = last;
                    while (last < end) {
                        int next = IndexOfCrLf(bytes, last + 2);
                        int chunk = next - last - 1;
                        Buffer.BlockCopy(bytes, last + 1, bytes, done, chunk);
                        done += chunk;
                        count -= chunk;
                        last = next;
                    }
                    buffer.Remove(done);
                } while (readAll || count > 0 && !eof);
            }

            if (readAll) {
                buffer.TrimExcess();
            }

            return buffer.GetByteCount() - initialBufferSize;
        }
Exemplo n.º 16
0
        private void AppendRawBytes(MutableString/*!*/ buffer, int count) {
            Debug.Assert(count > 0);

            int remaining = count;

            if (_bufferCount > 0) {
                int c = Math.Min(_bufferCount, count);
                buffer.Append(_buffer, _bufferStart, c);
                ConsumeBuffered(c);
                remaining -= c;
            }

            if (count == Int32.MaxValue) {
                const int chunk = 1024;

                int done = buffer.GetByteCount();
                int bytesRead;
                do {
                    buffer.Append(_stream, chunk);
                    bytesRead = buffer.GetByteCount() - done;
                    done += bytesRead;
                } while (bytesRead == chunk);
            } else {
                buffer.Append(_stream, remaining);
            }
        }
Exemplo n.º 17
0
        private static MutableString ReadLine(MutableString/*!*/ content, MutableString separator, ref int position) {
            int length = content.GetByteCount();
            if (position >= length) {
                return null;
            }

            int oldPosition = position;

            if (separator == null) {
                position = length;
            } else if (separator.IsEmpty) {
                // skip initial ends of line:
                while (oldPosition < length && content.GetByte(oldPosition) == '\n') {
                    oldPosition++;
                }

                position = content.IndexOf(ParagraphSeparator, oldPosition);
                position = (position != -1) ? position + 1 : length;
            } else {
                position = content.IndexOf(separator, oldPosition);
                position = (position != -1) ? position + separator.Length : length;
            }

            return content.GetSlice(oldPosition, position - oldPosition);
        }
Exemplo n.º 18
0
 public static int GetByteCount(MutableString/*!*/ self) {
     return self.GetByteCount();
 }
Exemplo n.º 19
0
        private static void FromHex(BinaryWriter/*!*/ writer, MutableString/*!*/ str, int nibbleCount, bool swap) {
            int maxCount = Math.Min(nibbleCount, str.GetByteCount());
            for (int i = 0, j = 0; i < (nibbleCount + 1) / 2; i++, j += 2) {
                int hiNibble = (j < maxCount) ? FromHexDigit(str.GetByte(j)) : 0;
                int loNibble = (j + 1 < maxCount) ? FromHexDigit(str.GetByte(j + 1)) : 0;
                Debug.Assert(hiNibble >= 0 && hiNibble < 16 && loNibble >= 0 && loNibble < 16);

                int c = (swap) ? (loNibble << 4) | hiNibble : (hiNibble << 4) | loNibble;
                writer.Write((byte)c);
            }
        }
Exemplo n.º 20
0
        private static void WriteBits(Stream/*!*/ stream, int? countDef, bool reverse, MutableString/*!*/ str)
        {
            int length = str.GetByteCount();
            int count = countDef ?? length;

            int bits = Math.Min(count, length);
            int paddingBits = (8 - bits % 8) % 8;

            long resultLength = stream.Length +
                (bits + paddingBits) / 8 +
                ((count - bits) + (count - bits) % 2) / 2;

            // estimate the total length:
            stream.SetLength(resultLength);

            int b = 0;
            int i = 0;
            int s = reverse ? 0 : 7;
            int ds = reverse ? +1 : -1;
            while (i < bits) {
                b |= (str.GetByte(i++) & 1) << s;
                s += ds;
                if (i % 8 == 0) {
                    stream.WriteByte((byte)b);
                    b = 0;
                    s = reverse ? 0 : 7;
                }
            }

            if (paddingBits > 0) {
                stream.WriteByte((byte)b);
            }

            stream.Position = resultLength;
        }
Exemplo n.º 21
0
        public static MutableString/*!*/ Join(JoinConversionStorage/*!*/ conversions, IList/*!*/ self, MutableString separator) {
            var parts = new List<MutableString>(self.Count);
            bool? isBinary = (separator != null) ? separator.IsBinary : (bool?)null;
            Dictionary<object, bool> seen = null;
            
            // build a list of strings to join:
            JoinRecursive(conversions, self, parts, ref isBinary, ref seen);
            if (parts.Count == 0) {
                return MutableString.CreateEmpty();
            }

            if (separator != null && separator.IsBinary != isBinary && !separator.IsAscii()) {
                isBinary = true;
            }

            // calculate length:
            MutableString any = separator;
            int length = (separator != null) ? (isBinary.HasValue && isBinary.Value ? separator.GetByteCount() : separator.GetCharCount()) * (parts.Count - 1) : 0;
            for (int i = 0, n = parts.Count; i < n; i++) {
                var part = parts[i];
                if (part != null) {
                    length += (isBinary.HasValue && isBinary.Value) ? part.GetByteCount() : part.GetCharCount();
                    if (any == null) {
                        any = part;
                    }
                }
            }

            if (any == null) {
                return MutableString.CreateEmpty();
            }

            var result = isBinary.HasValue && isBinary.Value ? 
                MutableString.CreateBinary(length, any.Encoding) :
                MutableString.CreateMutable(length, any.Encoding);

            for (int i = 0, n = parts.Count; i < n; i++) {
                var part = parts[i];

                if (separator != null && i > 0) {
                    result.Append(separator);
                }

                if (part != null) {
                    result.Append(part);
                    result.TaintBy(part);
                }
            }

            if (separator != null) {
                result.TaintBy(separator);
            }
            if (!result.IsTainted || !result.IsUntrusted) {
                result.TaintBy(self, conversions.Context);
            }
            return result;
        }
Exemplo n.º 22
0
        /// <summary>
        /// Printable characters: [33, 60], [62, 126], space (32), tab (9) but not at the end of line
        /// Escaped: others =XX
        /// Soft eolns (could be inserted anywhere, Ruby: after each count + 1 characters): =\n
        /// </summary>
        private static void WritePrintedQuotable(Stream/*!*/ stream, MutableString/*!*/ str, int bytesPerLine)
        {
            bytesPerLine++;
            int lineLength = 0;
            int length = str.GetByteCount();
            for (int i = 0; i < length; i++) {
                byte c = str.GetByte(i);
                if (c >= 33 && c <= 60 || c >= 62 && c <= 126 || c == 9 || c == 32) {
                    stream.WriteByte(c);
                    lineLength++;
                } else if (c == (byte)'\n') {
                    stream.WriteByte(c);
                    lineLength = 0;
                } else {
                    stream.WriteByte((byte)'=');
                    stream.WriteByte((byte)(c >> 4).ToUpperHexDigit());
                    stream.WriteByte((byte)(c & 0x0f).ToUpperHexDigit());
                    lineLength += 3;
                }

                if (lineLength >= bytesPerLine) {
                    stream.WriteByte((byte)'=');
                    stream.WriteByte((byte)'\n');
                    lineLength = 0;
                }
            }

            if (lineLength > 0) {
                stream.WriteByte((byte)'=');
                stream.WriteByte((byte)'\n');
            }
        }
Exemplo n.º 23
0
        private void AppendRawBytes(MutableString/*!*/ buffer, int count) {
            Debug.Assert(count > 0);

            int remaining = count;

            while (_bufferSize > 0) {
                buffer.Append(ReadBufferByte());
                remaining--;
            }

            if (count == Int32.MaxValue) {
                const int chunk = 1024;

                int done = buffer.GetByteCount();
                int bytesRead;
                do {
                    buffer.Append(_stream, chunk);
                    bytesRead = buffer.GetByteCount() - done;
                    done += bytesRead;
                } while (bytesRead == chunk);
            } else {
                buffer.Append(_stream, remaining);
            }
        }
Exemplo n.º 24
0
        /*!*/
        public static RubyArray Unpack(MutableString/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ format)
        {
            RubyArray result = new RubyArray(1 + self.Length / 2);

            // TODO: encodings
            int position = 0;
            int length = self.GetByteCount();
            foreach (FormatDirective directive in FormatDirective.Enumerate(format.ToString())) {
                int count, maxCount;
                int nilCount = 0;
                switch (directive.Directive) {
                    case '@':
                        if (directive.Count.HasValue) {
                            if (directive.Count.Value > length) {
                                throw RubyExceptions.CreateArgumentError("@ outside of string");
                            }
                            position = directive.Count.Value > 0 ? directive.Count.Value : 0;
                        } else {
                            position = length;
                        }
                        break;

                    case 'A':
                    case 'a':
                    case 'Z':
                        result.Add(ReadString(self, directive.Directive, directive.Count, ref position));
                        break;

                    case 'B':
                    case 'b':
                        result.Add(ReadBits(self, directive.Count, ref position, directive.Directive == 'b'));
                        break;

                    case 'c':
                        count = CalculateCounts(length - position, directive.Count, sizeof(sbyte), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add((int)unchecked((sbyte)self.GetByte(position++)));
                        }
                        break;

                    case 'C':
                        count = CalculateCounts(length - position, directive.Count, sizeof(byte), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add((int)self.GetByte(position++));
                        }
                        break;

                    case 'd': // 8-byte native-endian
                    case 'D':
                        count = CalculateCounts(length - position, directive.Count, sizeof(double), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(ReadDouble(self, ref position, false));
                        }
                        break;

                    case 'e': // 4-byte little-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(float), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add((double)ReadSingle(self, ref position, !BitConverter.IsLittleEndian));
                        }
                        break;

                    case 'E': // 8-byte little-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(double), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(ReadDouble(self, ref position, !BitConverter.IsLittleEndian));
                        }
                        break;

                    case 'f': // 4-byte native-endian
                    case 'F':
                        count = CalculateCounts(length - position, directive.Count, sizeof(float), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add((double)ReadSingle(self, ref position, false));
                        }
                        break;

                    case 'g': // 4-byte big-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(float), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add((double)ReadSingle(self, ref position, BitConverter.IsLittleEndian));
                        }
                        break;

                    case 'G': // 8-byte big-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(double), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(ReadDouble(self, ref position, BitConverter.IsLittleEndian));
                        }
                        break;

                    case 'i':
                    case 'l': // signed 4-byte native-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(int), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(unchecked((int)ReadUInt32(self, ref position, false)));
                        }
                        break;

                    case 'I':
                    case 'L': // unsigned 4-byte native-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(uint), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(Protocols.Normalize(ReadUInt32(self, ref position, false)));
                        }
                        break;

                    case 'N': // unsigned 4-byte big-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(uint), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(Protocols.Normalize(ReadUInt32(self, ref position, BitConverter.IsLittleEndian)));
                        }
                        break;

                    case 'n': // unsigned 2-byte big-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(ushort), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(ScriptingRuntimeHelpers.Int32ToObject(ReadUInt16(self, ref position, BitConverter.IsLittleEndian)));
                        }
                        break;

                    case 'v': // unsigned 2-byte little-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(ushort), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(ScriptingRuntimeHelpers.Int32ToObject(ReadUInt16(self, ref position, !BitConverter.IsLittleEndian)));
                        }
                        break;

                    case 'V': // unsigned 4-byte little-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(uint), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(Protocols.Normalize(ReadUInt32(self, ref position, !BitConverter.IsLittleEndian)));
                        }
                        break;

                    case 'q': // signed 8-byte native-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(long), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(Protocols.Normalize(unchecked((long)ReadUInt64(self, ref position, false))));
                        }
                        break;

                    case 'Q': // unsigned 8-byte native-endian
                        count = CalculateCounts(length - position, directive.Count, sizeof(ulong), out nilCount);
                        nilCount = 0;
                        for (int j = 0; j < count; j++) {
                            result.Add(Protocols.Normalize(ReadUInt64(self, ref position, false)));
                        }
                        break;

                    case 'm': // Base64
                        result.Add(ReadBase64(self, ref position));
                        break;

                    case 'M': // quoted-printable, MIME encoding
                        result.Add(ReadQuotedPrintable(self, ref position));
                        break;

                    case 's':
                        count = CalculateCounts(length - position, directive.Count, sizeof(short), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(ScriptingRuntimeHelpers.Int32ToObject(unchecked((short)ReadUInt16(self, ref position, !BitConverter.IsLittleEndian))));
                        }
                        break;

                    case 'S':
                        count = CalculateCounts(length - position, directive.Count, sizeof(ushort), out nilCount);
                        for (int j = 0; j < count; j++) {
                            result.Add(ScriptingRuntimeHelpers.Int32ToObject(ReadUInt16(self, ref position, !BitConverter.IsLittleEndian)));
                        }
                        break;

                    case 'U':
                        count = directive.Count ?? Int32.MaxValue;
                        for (int i = 0; i < count; i++) {
                            int cp = ReadUtf8CodePoint(self, ref position);
                            if (cp == -1) {
                                break;
                            }
                            result.Add(cp);
                        }
                        break;

                    case 'w': // BER encoding
                        count = directive.Count ?? Int32.MaxValue;
                        for (int i = 0; i < count; i++) {
                            object value = ReadBer(self, ref position);

                            if (value == null) {
                                break;
                            }
                            result.Add(value);
                        }
                        break;

                    case 'u': // UU decoding
                        result.Add(ReadUU(self, ref position));
                        break;

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

                    case 'x':
                        int newPos = directive.Count.HasValue ? (int)position + directive.Count.Value : (int)length;
                        if (newPos > length) {
                            throw RubyExceptions.CreateArgumentError("X outside of string");
                        }
                        position = newPos;
                        break;

                    case 'h':
                    case 'H':
                        maxCount = (int)(length - position) * 2;
                        result.Add(ToHex(self, ref position, Math.Min(directive.Count ?? maxCount, maxCount), directive.Directive == 'h'));
                        break;
                }
                for (int i = 0; i < nilCount; i++) {
                    result.Add(null);
                }
            }
            return result;
        }
Exemplo n.º 25
0
        public static object EachByte(BlockParam block, MutableString/*!*/ self) {
            if (block == null && !self.IsEmpty) {
                throw RubyExceptions.NoBlockGiven();
            }

            // MRI allows the string to be changed during iteration
            int i = 0;
            while (i < self.GetByteCount()) {
                object result;
                if (block.Yield(ScriptingRuntimeHelpers.Int32ToObject((int)self.GetByte(i)), out result)) {
                    return result;
                }
                i++;
            }
            return self;
        }
Exemplo n.º 26
0
        public static void WriteBase64(Stream/*!*/ stream, MutableString/*!*/ str, int bytesPerLine)
        {
            ContractUtils.RequiresNotNull(stream, "stream");
            ContractUtils.RequiresNotNull(str, "str");
            ContractUtils.Requires(bytesPerLine > 2, "bytesPerLine");

            bytesPerLine = bytesPerLine - bytesPerLine % 3;
            int a, b, c;
            int length = str.GetByteCount();
            int remainingBytes = length % 3;
            int triples = length - remainingBytes;
            byte[] table = _Base64Table;
            int lineLength = 0;
            for (int i = 0; i < triples; i += 3) {
                a = str.GetByte(i);
                b = str.GetByte(i + 1);
                c = str.GetByte(i + 2);

                stream.WriteByte(table[(a & 0xfc) >> 2]);
                stream.WriteByte(table[((a & 3) << 4) | ((b & 240) >> 4)]);
                stream.WriteByte(table[((b & 15) << 2) | ((c & 0xc0) >> 6)]);
                stream.WriteByte(table[c & 0x3f]);
                lineLength += 3;

                if (lineLength == bytesPerLine) {
                    stream.WriteByte((byte)'\n');
                    lineLength = 0;
                }
            }

            if (remainingBytes == 0) {
                if (lineLength != 0) {
                    stream.WriteByte((byte)'\n');
                }
                return;
            }

            a = str.GetByte(triples);
            stream.WriteByte(table[(a & 0xfc) >> 2]);
            switch (remainingBytes) {
                case 1:
                    stream.WriteByte(table[(a & 3) << 4]);
                    stream.WriteByte((byte)'=');
                    break;

                case 2:
                    b = str.GetByte(triples + 1);
                    stream.WriteByte(table[((a & 3) << 4) | ((b & 240) >> 4)]);
                    stream.WriteByte(table[(b & 15) << 2]);
                    break;
            }
            stream.WriteByte((byte)'=');
            stream.WriteByte((byte)'\n');
        }
Exemplo n.º 27
0
        public static object Index(MutableString/*!*/ self, 
            int character, [DefaultProtocol, Optional]int start) {

            if (!self.IsBinaryEncoded && !self.Encoding.IsKCoding && !self.IsAscii()) {
                throw RubyExceptions.CreateTypeError("type mismatch: Fixnum given");
            }

            if (!NormalizeStart(self.GetByteCount(), ref start) || character < 0 || character > 255) {
                return null;
            }

            int result = self.IndexOf((byte)character, start);
            return (result != -1) ? ScriptingRuntimeHelpers.Int32ToObject(result) : null;
        }
Exemplo n.º 28
0
        /*!*/
        private static MutableString ReadBase64(MutableString/*!*/ data, ref int offset)
        {
            int length = data.GetByteCount();
            var result = MutableString.CreateBinary();

            while (true) {
                // The following should exactly match MRI handling of incomplete input:
                int a = DecodeBase64Byte(data, length, true, ref offset);
                int b = DecodeBase64Byte(data, length, true, ref offset);
                int c = DecodeBase64Byte(data, length, false, ref offset);
                int d = (c != -2) ? DecodeBase64Byte(data, length, false, ref offset) : -2;
                if (a == -1 || b == -1 || c == -1 || d == -1) {
                    break;
                }

                int buffer = (a << 18) | (b << 12);
                result.Append((byte)((buffer >> 16) & 0xff));

                if (c == -2) {
                    break;
                }
                buffer |= (c << 6);
                result.Append((byte)((buffer >> 8) & 0xff));

                if (d == -2) {
                    break;
                }
                buffer |= d;
                result.Append((byte)(buffer & 0xff));
            }

            return result;
        }
Exemplo n.º 29
0
        public static object RemoveCharInPlace(RubyContext/*!*/ context, MutableString/*!*/ self, [DefaultProtocol]int index) {
            if (!InExclusiveRangeNormalized(self.GetByteCount(), ref index)) {
                return null;
            }

            // TODO: optimize if the value is not read:
            int result = self.GetByte(index);
            self.Remove(index, 1);
            return result;
        }
Exemplo n.º 30
0
        /*!*/
        private static MutableString ReadBits(MutableString/*!*/ data, int? bitCount, ref int offset, bool lowestFirst)
        {
            int inputSize = data.GetByteCount() - offset;
            int outputSize = inputSize * 8;
            if (bitCount.HasValue) {
                int c = CeilDiv(bitCount.Value, 8);
                if (c <= inputSize) {
                    inputSize = c;
                    outputSize = bitCount.Value;
                }
            }

            var result = MutableString.CreateBinary(outputSize);
            if (outputSize == 0) {
                return result;
            }

            while (true) {
                int b = data.GetByte(offset++);
                for (int i = 0; i < 8; i++) {
                    result.Append((byte)('0' + ((b >> (lowestFirst ? i : 7 - i)) & 1)));
                    if (--outputSize == 0) {
                        return result;
                    }
                }
            }
        }
Exemplo n.º 31
0
        public static MutableString GetSubstring(MutableString/*!*/ self, [DefaultProtocol]int start, [DefaultProtocol]int count) {
            int byteCount = self.GetByteCount();
            if (!NormalizeSubstringRange(byteCount, ref start, ref count)) {
                return (start == byteCount) ? self.CreateInstance().TaintBy(self) : null;
            }

            return self.CreateInstance().Append(self, start, count).TaintBy(self);
        }
Exemplo n.º 32
0
        /*!*/
        private static MutableString ReadQuotedPrintable(MutableString/*!*/ data, ref int index)
        {
            MutableString result = MutableString.CreateBinary();
            int length = data.GetByteCount();
            int i = index;
            while (i < length) {
                byte c = data.GetByte(i++);
                if (c == '=') {
                    if (i >= length) {
                        break;
                    }

                    c = data.GetByte(i);
                    if (c == '\n') {
                        i++;
                        continue;
                    }
                    if (c == '\r' && i + 1 < length && data.GetByte(i + 1) == '\n') {
                        i += 2;
                        continue;
                    }

                    int hi = Tokenizer.ToDigit(c);
                    if (hi >= 16) {
                        break;
                    }
                    i++;

                    if (i >= length) {
                        break;
                    }

                    int lo = Tokenizer.ToDigit(data.GetByte(i));
                    if (lo >= 16) {
                        break;
                    }

                    i++;
                    result.Append((byte)((hi << 4) | lo));
                } else {
                    result.Append(c);
                }
            }
            index = i;
            return result;
        }
Exemplo n.º 33
0
        public static MutableString/*!*/ Join(ConversionStorage<MutableString>/*!*/ tosConversion, IList/*!*/ self, MutableString/*!*/ separator) {
            var parts = new List<MutableString>(self.Count);
            bool partTainted = false;
            bool? isBinary = (separator != null) ? separator.IsBinary : (bool?)null;
            Dictionary<object, bool> seen = null;
            
            JoinRecursive(tosConversion, self, parts, ref isBinary, ref partTainted, ref seen);
            if (parts.Count == 0) {
                return MutableString.CreateEmpty();
            }

            if (separator != null && separator.IsBinary != isBinary && !separator.IsAscii()) {
                isBinary = true;
            }

            MutableString any = separator;
            int length = (separator != null) ? (isBinary.Value ? separator.GetByteCount() : separator.GetCharCount()) * (parts.Count - 1) : 0;
            foreach (MutableString part in parts) {
                if (part != null) {
                    length += (isBinary.Value) ? part.GetByteCount() : part.GetCharCount();
                    if (any == null) {
                        any = part;
                    }
                }
            }

            if (any == null) {
                return MutableString.CreateEmpty();
            }

            var result = isBinary.Value ? 
                MutableString.CreateBinary(length, any.Encoding) :
                MutableString.CreateMutable(length, any.Encoding);

            for (int i = 0; i < parts.Count; i++) {
                if (separator != null && i > 0) {
                    result.Append(separator);
                }
                result.Append(parts[i]);
            }

            result.IsTainted |= partTainted;
            if (!result.IsTainted && (separator != null && separator.IsTainted || tosConversion.Context.IsObjectTainted(self))) {
                result.IsTainted = true;
            }
            return result;
        }
Exemplo n.º 34
0
        /*!*/
        private static MutableString ReadString(MutableString/*!*/ data, int trimMode, int? count, ref int offset)
        {
            int start = offset;
            int e = data.GetByteCount();
            if (count.HasValue) {
                int end = start + count.Value;
                if (end < e) {
                    e = end;
                }
            }

            offset = e;
            byte b;
            switch (trimMode) {
                case 'A':
                    while (--e >= start && ((b = data.GetByte(e)) == 0 || b == ' ')) { }
                    e++;
                    break;

                case 'Z':
                    int i = start;
                    while (i < e && data.GetByte(i) != 0) { i++; }
                    if (!count.HasValue) {
                        offset = i + 1;
                    }
                    e = i;
                    break;
            }

            return data.GetSlice(start, e - start);
        }
Exemplo n.º 35
0
        private static BigInteger GetBigChecksum(MutableString/*!*/ self, int start, BigInteger/*!*/ sum, int bitCount) {
            BigInteger mask = (((BigInteger)1) << bitCount) - 1;

            int length = self.GetByteCount();
            for (int i = start; i < length; i++) {
                sum = (sum + self.GetByte(i)) & mask;
            }
            return sum;
        }
Exemplo n.º 36
0
        /// <summary>
        /// Returns true if the string binary representation contains bytes from set: 0..0x1f + 0x7f..0xff - [0x0a, 0x0d].
        /// </summary>
        internal static bool ContainsBinaryData(MutableString/*!*/ str)
        {
            if (!str.IsAscii()) {
                return true;
            }

            // for ascii strings we can iterate over bytes or characters without converting the string repr:
            for (int i = 0; i < str.GetByteCount(); i++) {
                byte b = str.GetByte(i);
                if (b < 0x20 && b != 0x0a && b != 0x0d || b >= 0x7f) {
                    return true;
                }
            }

            return false;
        }