public override object Call1(Class last_class, object ary, Frame caller, Proc block, object fmt) { int p, pend, idx; int len, items, ptr; string fmtString, fromString; char type; object from; int plen; System.Text.StringBuilder res; fmtString = String.StringValue(fmt, caller); p = 0; pend = fmtString.Length; res = new System.Text.StringBuilder(); items = ((Array)ary).Count; idx = 0; while (p < pend) { if (fmtString.Length != pend) { new RuntimeError("format string modified"); } type = fmtString[p++]; if (char.IsWhiteSpace(type)) //TEST: IsWhiteSpace() must be equivalent to isspace() { continue; } if (type == '#') //eat comments { while ((p < pend) && (fmtString[p] != '\n')) { p++; } continue; } if (p < pend && (fmtString[p] == '_' || fmtString[p] == '!')) //'_' and '!' can only come after "sSiIlL" { const string natstr = "sSiIlL"; if (natstr.IndexOf(type) != -1) { p++; } else { throw new ArgumentError(string.Format(CultureInfo.InvariantCulture, "'{0}' allowed only after types {1}", fmtString[p], natstr)).raise(caller); } } if (p < pend && fmtString[p] == '*') /* set data length */ { if ("@Xxu".IndexOf(type) != -1) { len = 0; } else { len = items; } p++; } else if (p < pend && char.IsDigit(fmtString[p])) { int numStart = p; int numEnd = p + 1; while (numEnd < pend) { if (char.IsDigit(fmtString[numEnd])) { numEnd++; } else { break; } } len = int.Parse(fmtString.Substring(numStart, numEnd - numStart), CultureInfo.InvariantCulture); } else { len = 1; } switch (type) { case 'A': goto case 'Z'; case 'a': goto case 'Z'; case 'B': goto case 'Z'; case 'b': goto case 'Z'; case 'H': goto case 'Z'; case 'h': goto case 'Z'; case 'Z': from = Pack.NEXTFROM(caller, ary, ref idx, ref items); if (from == null) { fromString = ""; ptr = 0; plen = 0; } else { fromString = String.StringValue(from, caller); ptr = 0; plen = fromString.Length; } if (fmtString[p - 1] == '*') { len = plen; } switch (type) { case 'a': /* arbitrary binary string (null padded) */ goto case 'Z'; case 'A': /* ASCII string (space padded) */ goto case 'Z'; case 'Z': /* null terminated ASCII string */ if (plen >= len) { res.Append(fromString.Substring(0, len)); if (fmtString[p - 1] == '*' && type == 'Z') { res.Append("\0"); } } else { res.Append(fromString); len -= plen; if (type == 'A') { res.Append(' ', len); } else //type == 'Z' or type == 'a' { res.Append('\0', len); } } break; case 'b': /* bit string (ascending) */ { int aByte = 0; int i, j = 0; if (len > plen) { j = (len - plen + 1) / 2; len = plen; } for (i = 0; i++ < len; ptr++) { if ((fromString[ptr] & 1) > 0) { aByte |= 128; } if ((i & 7) > 0) { aByte >>= 1; } else { char c = (char)aByte; res.Append((char)c); aByte = 0; } } if ((len & 7) > 0) { char c; aByte >>= 7 - (len & 7); c = (char)aByte; res.Append(c); } len = j; res.Append('\0', len); //goto grow; } break; case 'B': /* bit string (descending) */ { int aByte = 0; int i, j = 0; if (len > plen) { j = (len - plen + 1) / 2; len = plen; } for (i = 0; i++ < len; ptr++) { aByte |= fromString[ptr] & 1; if ((i & 7) > 0) { aByte <<= 1; } else { char c = (char)aByte; res.Append(c); aByte = 0; } } if ((len & 7) > 0) { char c; aByte <<= 7 - (len & 7); c = (char)aByte; res.Append(c); } len = j; res.Append('\0', len); //goto grow; } break; case 'h': /* hex string (low nibble first) */ { int aByte = 0; int i, j = 0; if (len > plen) { j = (len - plen + 1) / 2; len = plen; } for (i = 0; i++ < len; ptr++) { if (char.IsLetter(fromString[ptr])) { aByte |= (((fromString[ptr] & 15) + 9) & 15) << 4; } else { aByte |= (fromString[ptr] & 15) << 4; } if ((i & 1) > 0) { aByte >>= 4; } else { char c = (char)aByte; res.Append(c); aByte = 0; } } if ((len & 1) > 0) { char c = (char)aByte; res.Append(c); } len = j; res.Append('\0', len); //goto grow; } break; case 'H': /* hex string (high nibble first) */ { int aByte = 0; int i, j = 0; if (len > plen) { j = (len - plen + 1) / 2; len = plen; } for (i = 0; i++ < len; ptr++) { if (char.IsLetter(fromString[ptr])) { aByte |= ((fromString[ptr] & 15) + 9) & 15; } else { aByte |= fromString[ptr] & 15; } if ((i & 1) > 0) { aByte <<= 4; } else { char c = (char)aByte; res.Append(c); aByte = 0; } } if ((len & 1) > 0) { char c = (char)aByte; res.Append(c); } len = j; res.Append('\0', len); } break; } break; case 'c': /* signed char */ goto case 'C'; case 'C': /* unsigned char */ while (len-- > 0) { char c; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); c = (char)(Pack.num2i32(from, caller) & 0xFF); res.Append(c); } break; case 's': /* signed short */ goto case 'S'; case 'S': /* unsigned short */ while (len-- > 0) { ushort s; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); s = (ushort)Pack.num2i32(from, caller); byte[] b = System.BitConverter.GetBytes(s); Pack.rb_str_buf_cat(res, b, 2); } break; case 'i': /* signed int */ goto case 'L'; case 'I': /* unsigned int */ goto case 'L'; case 'l': /* signed long */ goto case 'L'; case 'L': /* unsigned long */ while (len-- > 0) { uint i; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); i = Pack.num2i32(from, caller); byte[] b = System.BitConverter.GetBytes(i); Pack.rb_str_buf_cat(res, b, 4); } break; case 'q': /* signed quad (64bit) int */ goto case 'Q'; case 'Q': /* unsigned quad (64bit) int */ while (len-- > 0) { ulong ul; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); ul = Pack.num2i64(from, caller); byte[] b = System.BitConverter.GetBytes(ul); Pack.rb_str_buf_cat(res, b, 8); } break; case 'n': /* unsigned short (network byte-order) */ while (len-- > 0) { ushort s; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); s = (ushort)Pack.num2i32(from, caller); byte[] b = System.BitConverter.GetBytes(s); if (!Pack.isBigEndian()) { Pack.swap(b); } Pack.rb_str_buf_cat(res, b, 2); } break; case 'N': /* unsigned long (network byte-order) */ while (len-- > 0) { uint l; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); l = Pack.num2i32(from, caller); byte[] b = System.BitConverter.GetBytes(l); if (!Pack.isBigEndian()) { Pack.swap(b); } Pack.rb_str_buf_cat(res, b, 4); } break; case 'v': /* unsigned short (VAX byte-order) */ while (len-- > 0) { from = Pack.NEXTFROM(caller, ary, ref idx, ref items); ushort s; s = (ushort)Pack.num2i32(from, caller); byte[] b = System.BitConverter.GetBytes(s); if (Pack.isBigEndian()) { Pack.swap(b); } Pack.rb_str_buf_cat(res, b, 2); } break; case 'V': /* unsigned long (VAX byte-order) */ while (len-- > 0) { from = Pack.NEXTFROM(caller, ary, ref idx, ref items); uint l; l = Pack.num2i32(from, caller); byte[] s = System.BitConverter.GetBytes(l); if (Pack.isBigEndian()) { Pack.swap(s); } Pack.rb_str_buf_cat(res, s, 4); } break; case 'f': /* single precision float in native format */ goto case 'F'; case 'F': /* ditto */ while (len-- > 0) { float f; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); f = (float)((Float)Float.rb_Float(from, caller)).value; byte[] s = System.BitConverter.GetBytes(f); Pack.rb_str_buf_cat(res, s, 4); } break; case 'e': /* single precision float in VAX byte-order */ while (len-- > 0) { float f; byte[] ftmp; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); f = (float)((Float)Float.rb_Float(from, caller)).value; ftmp = System.BitConverter.GetBytes(f); if (Pack.isBigEndian()) { Pack.swap(ftmp); } Pack.rb_str_buf_cat(res, ftmp, 4); } break; case 'E': /* double precision float in VAX byte-order */ while (len-- > 0) { double d; byte[] dtmp; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); d = ((Float)Float.rb_Float(from, caller)).value; dtmp = System.BitConverter.GetBytes(d); if (Pack.isBigEndian()) { Pack.swap(dtmp); } Pack.rb_str_buf_cat(res, dtmp, 8); } break; case 'd': /* double precision float in native format */ goto case 'D'; case 'D': /* ditto */ while (len-- > 0) { double d; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); d = ((Float)Float.rb_Float(from, caller)).value; Pack.rb_str_buf_cat(res, System.BitConverter.GetBytes(d), 8); } break; case 'g': /* single precision float in network byte-order */ while (len-- > 0) { float f; byte[] ftmp; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); f = (float)((Float)Float.rb_Float(from, caller)).value; ftmp = System.BitConverter.GetBytes(f); if (!Pack.isBigEndian()) { Pack.swap(ftmp); } Pack.rb_str_buf_cat(res, ftmp, 4); } break; case 'G': /* double precision float in network byte-order */ while (len-- > 0) { double d; byte[] dtmp; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); d = ((Float)Float.rb_Float(from, caller)).value; dtmp = System.BitConverter.GetBytes(d); if (!Pack.isBigEndian()) { Pack.swap(dtmp); } Pack.rb_str_buf_cat(res, dtmp, 8); } break; case 'x': /* null byte */ //grow: res.Append('\0', len); break; case 'X': /* back up byte */ //shrink: plen = res.Length; if (plen < len) { throw new ArgumentError("X outside of string").raise(caller); } res.Length = plen - len; break; case '@': /* null fill to absolute position */ len -= res.Length; if (len > 0) res.Append('\0', len); //goto grow: len = -len; if (len > 0) goto case 'X'; break; case '%': throw new ArgumentError("% is not supported").raise(caller); //FIX when merge. case 'U': /* Unicode character */ while (len-- > 0) { int l; char[] buf = new char[8]; int le; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); from = Integer.rb_to_int(from, caller); l = Numeric.rb_num2long(from, caller); if (l < 0) { throw new RangeError("pack(U): value out of range").raise(caller); } le = Pack.uv_to_utf8(caller, buf, (uint)l); Pack.rb_str_buf_cat(res, buf, le); } break; case 'u': /* uuencoded string */ goto case 'm'; case 'm': /* base64 encoded string */ string frmString; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); frmString = String.StringValue(from, caller); ptr = 0; plen = frmString.Length; if (len <= 2) { len = 45; } else { len = len / 3 * 3; } while (plen > 0) { int todo; if (plen > len) { todo = len; } else { todo = plen; } Pack.encodes(res, frmString.Substring(ptr), todo, type); plen -= todo; ptr += todo; } break; case 'M': /* quoted-printable encoded string */ from = String.ObjectAsString(Pack.NEXTFROM(caller, ary, ref idx, ref items), caller); if (len <= 1) { len = 72; } Pack.qpencodes(res, from, len); break; case 'P': /* pointer to packed byte string */ throw new NotImplementedError("The pack(\"P\") method is not implemented on this platform").raise(caller); case 'p': /* pointer to string */ throw new NotImplementedError("The pack(\"p\") method is not implemented on this platform").raise(caller); case 'w': /* BER compressed integer */ while (len-- > 0) { uint ul; System.Text.StringBuilder buf = new System.Text.StringBuilder(); char c; int bufs, bufe; //char c, *bufs, *bufe; from = Pack.NEXTFROM(caller, ary, ref idx, ref items); if (from is Bignum) { object big128 = new Bignum(128); while (from is Bignum) { from = Ruby.Methods.rb_big_divmod.singleton.Call1(last_class, from, caller, null, big128); c = (char)(Numeric.rb_num2long(((Array)from).value[1], caller) | 0x80); Pack.rb_str_buf_cat(buf, new char[] { c }, 1); from = ((Array)from).value[0]; } } { int l = Numeric.rb_num2long(from, caller); if (l < 0) { throw new ArgumentError("cannot compress negative numbers").raise(caller); } ul = (uint)l; } while (ul > 0) { c = (char)((ul & 0x7f) | 0x80); Pack.rb_str_buf_cat(buf, new char[] { c }, 1); ul >>= 7; } if (buf.Length > 0) { bufs = 0; bufe = buf.Length - 1; buf[bufs] = (char)(buf[bufs] & 0x7f); /* clear continue bit */ while (bufs < bufe) /* reverse */ { c = buf[bufs]; buf[bufs++] = buf[bufe]; buf[bufe--] = c; } Pack.rb_str_buf_cat(res, buf.ToString().ToCharArray(), buf.Length); } else { c = (char)0; Pack.rb_str_buf_cat(res, new char[] { c }, 1); } } break; default: break; } } return new String(res.ToString()); }
public override object Call1(Class last_class, object str, Frame caller, Proc block, object fmt) { string hexdigits = "0123456789abcdef0123456789ABCDEFx"; string fmtString, strString; int s, send; //str int p, pend; //fmt object ary; char type; int len; bool star = false; int tmp; fmtString = String.StringValue(fmt, caller); strString = String.StringValue(str, caller); s = 0; send = strString.Length; p = 0; pend = fmtString.Length; ary = new Array(); while (p < pend) { type = fmtString[p++]; if (char.IsWhiteSpace(type)) continue; if (type == '#') //eat comments { while ((p < pend) && (fmtString[p] != '\n')) { p++; } continue; } if (p < pend && (fmtString[p] == '_' || fmtString[p] == '!')) //'_' and '!' can only come after "sSiIlL" { const string natstr = "sSiIlL"; if (natstr.IndexOf(type) != -1) { p++; } else { throw new ArgumentError(string.Format(CultureInfo.InvariantCulture, "'{0}' allowed only after types {1}", fmtString[p], natstr)).raise(caller); } } if (p >= pend) { len = 1; } else if (fmtString[p] == '*') { star = true; len = send - s; p++; } else if (p < pend && char.IsDigit(fmtString[p])) { int numStart = p; int numEnd = p + 1; while (numEnd < pend) { if (char.IsDigit(fmtString[numEnd])) { numEnd++; } else { break; } } len = int.Parse(fmtString.Substring(numStart, numEnd - numStart), CultureInfo.InvariantCulture); } else { len = (type != '@') ? 1 : 0; } int t; switch (type) { case '%': throw new ArgumentError("% is not supported").raise(caller); case 'A': if (len > send - s) { len = send - s; } int end = len; t = s + len - 1; while (t >= s) { if (strString[t] != ' ' && strString[t] != '\0') break; t--; len--; } ((Array)ary).value.Add(String.infected_str_new(s, len, strString)); s += end; break; case 'Z': { t = s; if (len > send - s) len = send - s; while (t < s + len && t <= send && strString[t] != '\0') t++; ((Array)ary).value.Add(String.infected_str_new(s, t - s, strString)); if (t < send) t++; s = star ? t : s + len; } break; case 'a': if (len > send - s) len = send - s; ((Array)ary).value.Add(String.infected_str_new(s, len, strString)); s += len; break; case 'b': { System.Text.StringBuilder bitStrBuilder = new System.Text.StringBuilder(); object bitstr; int bits; int i; if ((p > 0 && fmtString[p - 1] == '*') || len > (send - s) * 8) { len = (send - s) * 8; } bits = 0; for (i = 0; i < len; i++) { if ((i & 7) > 0) { bits >>= 1; } else { bits = (byte)strString[s++]; } bitStrBuilder.Append(((bits & 1) > 0) ? '1' : '0'); } bitstr = new String(bitStrBuilder.ToString()); ((Array)ary).value.Add(bitstr); } break; case 'B': { System.Text.StringBuilder bitStrBuilder = new System.Text.StringBuilder(); object bitstr; int bits; int i; if ((p > 0 && fmtString[p - 1] == '*') || len > (send - s) * 8) { len = (send - s) * 8; } bits = 0; for (i = 0; i < len; i++) { if ((i & 7) > 0) { bits <<= 1; } else { bits = strString[s++]; } bitStrBuilder.Append(((bits & 128) > 0) ? '1' : '0'); } bitstr = new String(bitStrBuilder.ToString()); ((Array)ary).value.Add(bitstr); } break; case 'h': { System.Text.StringBuilder bitStrBuilder = new System.Text.StringBuilder(); object bitstr; int bits; int i; if ((p > 0 && fmtString[p - 1] == '*') || len > (send - s) * 8) { len = (send - s) * 2; } bits = 0; for (i = 0; i < len; i++) { if ((i & 1) > 0) { bits >>= 4; } else { bits = strString[s++]; } bitStrBuilder.Append(hexdigits[bits & 15]); } bitstr = new String(bitStrBuilder.ToString()); ((Array)ary).value.Add(bitstr); } break; case 'H': { System.Text.StringBuilder bitStrBuilder = new System.Text.StringBuilder(); object bitstr; int bits; int i; if ((p > 0 && fmtString[p - 1] == '*') || len > (send - s) * 8) { len = (send - s) * 2; } bits = 0; for (i = 0; i < len; i++) { if ((i & 1) > 0) { bits <<= 4; } else { bits = strString[s++]; } bitStrBuilder.Append(hexdigits[(bits >> 4) & 15]); } bitstr = new String(bitStrBuilder.ToString()); ((Array)ary).value.Add(bitstr); } break; case 'c': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 1); while (len-- > 0) { int c = (byte)strString[s++]; if (c > 127) c -= 256; //integer is signed ((Array)ary).value.Add(c); } tmp = Pack.PACK_ITEM_ADJUST(ary, tmp); break; case 'C': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 1); while (len-- > 0) { int c = (byte)strString[s++]; ((Array)ary).value.Add(c); } tmp = Pack.PACK_ITEM_ADJUST(ary, tmp); break; case 's': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 2); while (len-- > 0) { short sTmp; sTmp = System.BitConverter.ToInt16(new byte[] { (byte)strString[s], (byte)strString[s + 1] }, 0); s += 2; ((Array)ary).value.Add((int)sTmp); } tmp = Pack.PACK_ITEM_ADJUST(ary, tmp); break; case 'S': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 2); while (len-- > 0) { ushort sTmp; sTmp = System.BitConverter.ToUInt16(new byte[] { (byte)strString[s], (byte)strString[s + 1] }, 0); s += 2; ((Array)ary).value.Add((int)sTmp); } tmp = Pack.PACK_ITEM_ADJUST(ary, tmp); break; case 'i': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 4); while (len-- > 0) { int sTmp; sTmp = System.BitConverter.ToInt32(new byte[] { (byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3]}, 0); s += 4; ((Array)ary).value.Add(sTmp); } tmp = Pack.PACK_ITEM_ADJUST(ary, tmp); break; case 'I': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 4); while (len-- > 0) { uint sTmp; sTmp = System.BitConverter.ToUInt32(new byte[] { (byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3]}, 0); s += 4; ((Array)ary).value.Add(Bignum.rb_uint2inum(sTmp, caller)); } tmp = Pack.PACK_ITEM_ADJUST(ary, tmp); break; case 'l': goto case 'i'; case 'L': goto case 'I'; case 'q': //signed quadword tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 8); while (len-- > 0) { long qTmp = System.BitConverter.ToInt64(new byte[]{(byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3], (byte)strString[s + 4], (byte)strString[s + 5], (byte)strString[s + 6], (byte)strString[s + 7]}, 0); s += 8; ((Array)ary).value.Add(Pack.i64_2_num(qTmp, caller)); } tmp = Pack.PACK_ITEM_ADJUST(ary, tmp); break; case 'Q': //unsigned quadword tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 8); while (len-- > 0) { ulong QTmp = System.BitConverter.ToUInt64(new byte[]{(byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3], (byte)strString[s + 4], (byte)strString[s + 5], (byte)strString[s + 6], (byte)strString[s + 7]}, 0); s += 8; ((Array)ary).value.Add(Pack.ui64_2_num(QTmp, caller)); } break; case 'n': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 2); while (len-- > 0) { ushort nTmp = 0; byte[] nTmpArray = new byte[] { (byte)strString[s], (byte)strString[s + 1] }; if (!Pack.isBigEndian()) { Pack.swap(nTmpArray); } nTmp = System.BitConverter.ToUInt16(nTmpArray, 0); s += 2; ((Array)ary).value.Add((int)nTmp); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'N': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 4); while (len-- > 0) { uint NTmp = 0; byte[] NTmpArray = new byte[] { (byte)strString[s], (byte)strString[s + 1], (byte)strString[2], (byte)strString[3]}; if (!Pack.isBigEndian()) { Pack.swap(NTmpArray); } NTmp = System.BitConverter.ToUInt32(NTmpArray, 0); s += 4; ((Array)ary).value.Add(Bignum.rb_uint2inum(NTmp, caller)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'v': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 2); while (len-- > 0) { ushort vTmp = 0; byte[] vTmpArray = new byte[] { (byte)strString[s], (byte)strString[s + 1] }; if (Pack.isBigEndian()) { Pack.swap(vTmpArray); } vTmp = System.BitConverter.ToUInt16(vTmpArray, 0); s += 2; ((Array)ary).value.Add((int)vTmp); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'V': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 4); while (len-- > 0) { uint VTmp = 0; byte[] VTmpArray = new byte[] { (byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3]}; if (Pack.isBigEndian()) { Pack.swap(VTmpArray); } VTmp = System.BitConverter.ToUInt32(VTmpArray, 0); s += 4; ((Array)ary).value.Add(Bignum.rb_uint2inum(VTmp, caller)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'f': goto case 'F'; case 'F': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 4); while (len-- > 0) { float FTmp; FTmp = System.BitConverter.ToSingle(new byte[] { (byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3] }, 0); s += 4; ((Array)ary).value.Add(new Float(FTmp)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'e': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 4); while (len-- > 0) { float eTmp; byte[] eTmpArray = new byte[]{ (byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3]}; if (Pack.isBigEndian()) { Pack.swap(eTmpArray); } s += 4; eTmp = System.BitConverter.ToSingle(eTmpArray, 0); ((Array)ary).value.Add(new Float(eTmp)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'E': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 8); while (len-- > 0) { double ETmp; byte[] ETmpArray = new byte[]{(byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3], (byte)strString[s + 4], (byte)strString[s + 5], (byte)strString[s + 6], (byte)strString[s + 7]}; if (Pack.isBigEndian()) { Pack.swap(ETmpArray); } s += 8; ETmp = System.BitConverter.ToDouble(ETmpArray, 0); ((Array)ary).value.Add(new Float(ETmp)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'D': goto case 'd'; case 'd': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 8); while (len-- > 0) { double dTmp; byte[] dTmpArray = new byte[]{(byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3], (byte)strString[s + 4], (byte)strString[s + 5], (byte)strString[s + 6], (byte)strString[s + 7]}; s += 8; dTmp = System.BitConverter.ToDouble(dTmpArray, 0); ((Array)ary).value.Add(new Float(dTmp)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'g': tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 4); while (len-- > 0) { float gTmp; byte[] gTmpArray = new byte[]{ (byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3]}; if (!Pack.isBigEndian()) { Pack.swap(gTmpArray); } s += 4; gTmp = System.BitConverter.ToSingle(gTmpArray, 0); ((Array)ary).value.Add(new Float(gTmp)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; case 'G': { tmp = Pack.PACK_LENGTH_ADJUST(s, send, ref len, star, 8); while (len-- > 0) { double GTmp; byte[] GTmpArray = new byte[]{(byte)strString[s], (byte)strString[s + 1], (byte)strString[s + 2], (byte)strString[s + 3], (byte)strString[s + 4], (byte)strString[s + 5], (byte)strString[s + 6], (byte)strString[s + 7]}; if (!Pack.isBigEndian()) { Pack.swap(GTmpArray); } s += 8; GTmp = System.BitConverter.ToDouble(GTmpArray, 0); ((Array)ary).value.Add(new Float(GTmp)); } tmp = Pack.PACK_ITEM_ADJUST(ary, (int)tmp); break; } case 'U': if (len > send - s) len = send - s; while (len > 0 && s < send) { int alen = send - s; uint l; l = (uint)Pack.utf8_to_uv(caller, strString, s, ref alen); s += alen; len--; ((Array)ary).value.Add(Bignum.rb_uint2inum(l, caller)); } break; case 'u': { object buf = String.infected_str_new(0, (send - s) * 3/4, strString); string ptrString = ((String)buf).value; System.Text.StringBuilder ptrStringBuilder = new System.Text.StringBuilder(ptrString); int ptr = 0; int total = 0; while (s < send && strString[s] > ' ' && strString[s] < 'a') { int a, b, c, d; char[] hunk = new char[4]; hunk[3] = '\0'; len = (strString[s++] - ' ') & 0x3f; total += len; if (total > ((String)buf).value.Length) { len -= total - ((String)buf).value.Length; total = ((String)buf).value.Length; } while (len > 0) { int mlen = len > 3 ? 3 : len; if (s < send && strString[s] >= ' ') a = (strString[s++] - ' ') & 0x3f; else a = 0; if (s < send && strString[s] >= ' ') b = (strString[s++] - ' ') & 0x3f; else b = 0; if (s < send && strString[s] >= ' ') c = (strString[s++] - ' ') & 0x3f; else c = 0; if (s < send && strString[s] >= ' ') d = (strString[s++] - ' ') & 0x3f; else d = 0; hunk[0] = (char)(byte)(a << 2 | b >> 4); hunk[1] = (char)(byte)(b << 4 | c >> 2); hunk[2] = (char)(byte)(c << 6 | d); for(int j = 0; j < mlen; j++){ ptrStringBuilder[ptr + j] = hunk[j]; } ptr += mlen; len -= mlen; } if (s < send && strString[s] == '\r') s++; if (s < send && strString[s] == '\n') s++; else if(s < send && (s + 1 == send || strString[s + 1] == '\n')){ s += 2; /* possible checksum byte */ } } ptrStringBuilder.Length = total; ((String)buf).value = ptrStringBuilder.ToString(); ((Array)ary).value.Add(buf); } break; case 'm': { object buf = String.infected_str_new(0, (send - s) * 3 / 4, strString); System.Text.StringBuilder ptrString = new System.Text.StringBuilder(((String)buf).value); int ptr = 0; int a = -1, b = -1, c = 0, d = 0; if (first > 0) { int i; first = 0; for (i = 0; i < 256; i++) { b64_xtable[i] = -1; } for (i = 0; i < 64; i++) { b64_xtable[(int)Pack.b64_table[i]] = i; } } while (s < send) { while (strString[s] == '\r' || strString[s] == '\n') { s++; } if ((a = b64_xtable[(int)strString[s]]) == -1) break; if (!(s+1 < send) || (b = b64_xtable[(int)strString[s + 1]]) == -1) break; if (!(s+2 < send) || (c = b64_xtable[(int)strString[s + 2]]) == -1) break; if (!(s+3 < send) || (d = b64_xtable[(int)strString[s + 3]]) == -1) break; ptrString[ptr++] = (char)(byte)(a << 2 | b >> 4); ptrString[ptr++] = (char)(byte)(b << 4 | c >> 2); ptrString[ptr++] = (char)(byte)(c << 6 | d); s += 4; } if (a != -1 && b != -1) { if (s + 2 < send && strString[ptr++] == '=') ptrString[ptr++] = (char)(byte)(a << 2 | b >> 4); if (c != -1 && s + 3 < send && strString[s + 3] == '=') { ptrString[ptr++] = (char)(byte)(a << 2 | b >> 4); ptrString[ptr++] = (char)(byte)(b << 4 | c >> 2); } } ptrString.Length = ptr; ((String)buf).value = ptrString.ToString(); ((Array)ary).value.Add(buf); } break; case 'M': { object buf = String.infected_str_new(0, send - s, strString); System.Text.StringBuilder ptrString = new System.Text.StringBuilder(((String)buf).value); int ptr = 0; int c1, c2; while(s < send){ if (strString[s] == '=') { if (++s == send) break; if (strString[s] != '\n') { if ((c1 = Pack.hex2num(strString[s])) == -1) break; if (++s == send) break; if ((c2 = Pack.hex2num(strString[s])) == -1) break; ptrString[ptr++] = (char)(byte)(c1 << 4 | c2); } } else { ptrString[ptr++] = strString[s]; } s++; } ptrString.Length = ptr; ((String)buf).value = ptrString.ToString(); ((Array)ary).value.Add(buf); } break; case 'X': if (len > s) throw new ArgumentError("X outside of string").raise(caller); s -= len; break; case 'x': if (len > send - s) throw new ArgumentError("X outside of string").raise(caller); s += len; break; case 'P': /* pointer to packed byte string */ throw new NotImplementedError("The pack(\"P\") method is not implemented on this platform").raise(caller); case 'p': /* pointer to string */ throw new NotImplementedError("The pack(\"p\") method is not implemented on this platform").raise(caller); case 'w': { uint ul = 0; uint ulmask = ((uint)0xfe) << 4 - 1 * 8; while (len > 0 && s < send) { ul <<= 7; ul |= (byte)(strString[s] & 0x7f); if (!((strString[s++] & 0x80) > 0)) { ((Array)ary).value.Add(Bignum.rb_uint2inum(ul, caller)); len--; ul = 0; } else if ((ul & ulmask) > 0) { object big = new Bignum(ul); object big128 = new Bignum(128); while (s < send) { big = Ruby.Methods.rb_big_mul.singleton.Call1(last_class, big, caller, null, big128); big = Ruby.Methods.rb_big_plus.singleton.Call1(last_class, big, caller, null, Bignum.rb_uint2inum((byte)(strString[s] & 0x7f), caller)); } if (!((strString[s++] & 0x80) > 0)) { ((Array)ary).value.Add(big); len--; ul = 0; break; } } } } break; default: break; } } return ary; }
private Bignum rb_big_rand(Bignum max, double rand) { Bignum b = new Bignum(max.value * rand); return new Bignum(b.value % max.value); }
public override object Call(Class last_class, object recv, Frame caller, Proc block, Array args) { object fmt; string fmtString; int p, end; System.Text.StringBuilder result = new System.Text.StringBuilder(); int width, prec, flags = Sprintf.FNONE; int nextArg = 1; int posArg = 0; //int tainted = 0; object nextValue; object tmp = null; object str; fmt = args[0]; //if (OBJ_TAINTED(fmt)) tainted = 1; fmtString = String.StringValue(fmt, caller); // fmt = rb_str_new4(fmt); - tainted work being done in this method p = 0; //p = RSTRING(fmt)->ptr; end = fmtString.Length; for (; p < end; p++) { int t; int n; for (t = p; t < end && fmtString[t] != '%'; t++) ; //skip over preceding chars result.Append(fmtString.Substring(p, t - p)); if (t >= end) { /* end of fmt string */ goto sprint_exit; } p = t + 1; /* skip '%' */ width = prec = -1; nextValue = null; retry: switch (fmtString[p]) { case ' ': flags |= Sprintf.FSPACE; //leave a space at the start of positive numbers. p++; goto retry; case '#': flags |= Sprintf.FSHARP; p++; goto retry; case '+': flags |= Sprintf.FPLUS; p++; goto retry; case '-': flags |= Sprintf.FMINUS; p++; goto retry; case '0': flags |= Sprintf.FZERO; p++; goto retry; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; for (; p < end && char.IsDigit(fmtString[p]); p++) { n = 10 * n + (fmtString[p] - '0'); } if (p >= end) { throw new ArgumentError("malformed format string - %[0-9]").raise(caller); } if (fmtString[p] == '$') { if (nextValue != null) { throw new ArgumentError(string.Format(CultureInfo.InvariantCulture, "value given twice - {0}$", n)).raise(caller); } nextValue = Sprintf.GETPOSARG(caller, n, ref posArg, args); p++; goto retry; } width = n; flags |= Sprintf.FWIDTH; goto retry; case '*': if ((flags & Sprintf.FWIDTH) > 0) { throw new ArgumentError("width given twice").raise(caller); } flags |= Sprintf.FWIDTH; width = Sprintf.GETASTER(ref t, ref p, out n, end, fmtString, ref posArg, ref nextArg, nextValue, tmp, args, caller); if (width < 0) { flags |= Sprintf.FMINUS; width = -width; } p++; goto retry; case '.': if ((flags & Sprintf.FPREC) > 0) { throw new ArgumentError("precision given twice").raise(caller); } flags |= Sprintf.FPREC; prec = 0; p++; if (fmtString[p] == '*') { prec = Sprintf.GETASTER(ref t, ref p, out n, end, fmtString, ref posArg, ref nextArg, nextValue, tmp, args, caller); if (prec < 0) /* ignore negative precision */ { flags &= ~Sprintf.FPREC; } p++; goto retry; } for (; p < end && char.IsDigit(fmtString[p]); p++) { prec = 10 * prec + (fmtString[p] - '0'); } if (p >= end) { throw new ArgumentError("malformed format string - %%.[0-9]").raise(caller); } goto retry; case '\n': p--; goto case '%'; case '\0': goto case '%'; case '%': if (flags != Sprintf.FNONE) { throw new ArgumentError("illegal format character - %").raise(caller); } result.Append("%"); break; case 'c': { object val = Sprintf.GETARG(caller, ref posArg, ref nextArg, nextValue, args); int c; if (!((flags & Sprintf.FMINUS) > 0)) { while (--width > 0) { result.Append(" "); } } c = Numeric.rb_num2long(val, caller) & 0xff; result.Append((char)(byte)c); while (--width > 0) { result.Append(" "); } } break; case 's': goto case 'p'; case 'p': { object arg = Sprintf.GETARG(caller, ref posArg, ref nextArg, nextValue, args); int len; if (fmtString[p] == 'p') arg = Object.Inspect(arg, caller); str = String.ObjectAsString(arg, caller); //if (OBJ_TAINTED(str)) tainted = 1; len = ((String)str).value.Length; if ((flags & Sprintf.FPREC) > 0) { if (prec < len) { len = prec; } } if ((flags & Sprintf.FWIDTH) > 0) { if (width > len) { width -= len; if (!((flags & Sprintf.FMINUS) > 0)) { while (width-- > 0) { result.Append(' '); } } result.Append(((String)str).value.Substring(0, len)); if ((flags & Sprintf.FMINUS) > 0) { while (width-- > 0) { result.Append(' '); } } break; } } result.Append(((String)str).value.Substring(0, len)); } break; case 'd': case 'i': case 'o': case 'x': case 'X': case 'b': case 'B': case 'u': { object val = Sprintf.GETARG(caller, ref posArg, ref nextArg, nextValue, args); string prefix = ""; int sign = 0; int v = 0; int bignum = 0; int numBase = 0; char sc = '\0'; string fbuf = ""; string nbuf = ""; int s = 0; string sString = ""; int tt = 0; string ttString = ""; object tmp2; //int pos; int len; switch (fmtString[p]) { case 'd': goto case 'i'; case 'i': sign = 1; break; case 'o': case 'x': case 'X': case 'b': case 'B': case 'u': default: if ((flags & (Sprintf.FPLUS | Sprintf.FSPACE)) > 0) sign = 1; break; } if ((flags & Sprintf.FSHARP) > 0) { switch (fmtString[p]) { case 'o': prefix = "0"; break; case 'x': prefix = "0x"; break; case 'X': prefix = "0X"; break; case 'b': prefix = "0b"; break; case 'B': prefix = "0B"; break; } if (prefix.Length > 0) { width -= prefix.Length; } } bin_retry: if (val is Float) { val = new Bignum(((Float)val).value); if (val is int) goto bin_retry; bignum = 1; } else if (val is String) { val = String.rb_str_to_inum(val, caller, 0, true); //TEST - should base be 0? goto bin_retry; } else if (val is Bignum) { bignum = 1; } else if (val is int) { v = (int)val; } else { val = Integer.rb_Integer(val, caller); goto bin_retry; } switch (fmtString[p]) { case 'o': numBase = 8; break; case 'x': case 'X': numBase = 16; break; case 'b': case 'B': numBase = 2; break; case 'u': case 'd': case 'i': default: numBase = 10; break; } if (bignum == 0) { if (numBase == 2) { val = new Bignum(v); goto bin_retry; } if (sign != 0) { char c = fmtString[p]; if (c == 'i') c = 'd'; /* %d and %i are identical */ if (v < 0) { v = -v; sc = '-'; width--; } else if ((flags & Sprintf.FPLUS) > 0) { sc = '+'; width--; } else if ((flags & Sprintf.FSPACE) > 0) { sc = ' '; width--; } fbuf = Sprintf.sprintf("%%l%c", c); nbuf = Sprintf.sprintf(fbuf, v); s = 0;//s = nbuf; sString = nbuf; goto format_integer; } s = 0;//s = nbuf; if (v < 0) { if (numBase == 10) { Errors.rb_warning("negative number for %%u specifier"); } if (!((flags & (Sprintf.FPREC | Sprintf.FZERO)) > 0)) { nbuf = nbuf.Insert(s, ".."); s += 2; } } fbuf = Sprintf.sprintf("%%l%c", fmtString[p] == 'X' ? 'x' : fmtString[p]); nbuf = nbuf.Substring(0, s) + Sprintf.sprintf(fbuf, v); if (v < 0) { char d = '\0'; Sprintf.remove_sign_bits(nbuf.Substring(s), numBase); switch (numBase) { case 16: d = 'f'; break; case 8: d = '7'; break; } if (d != '\0' && (nbuf[s] != d)) { nbuf.Insert(s, d.ToString()); } } s = 0;//s = nbuf; sString = nbuf; goto format_integer; } //bignums between here and format_integer if (sign > 0) { tmp2 = ((Bignum)val).value.ToString((uint)numBase); //tmp2 = rb_big2str(val, numBase); s = 0; sString = (string)tmp2; if (sString[s] == '-') { s++; sc = '-'; width--; } else if ((flags & Sprintf.FPLUS) > 0) { sc = '+'; width--; } else if ((flags & Sprintf.FSPACE) > 0) { sc = ' '; width--; } goto format_integer; } //negative bignum from now on if (((Bignum)val).value < (IronMath.integer.make(0))) { val = new Bignum(((Bignum)val).value); //must be equivalent to rb_big_2comp(val); TEST new Bignum(~((Bignum)val).value); } tmp2 = new String(((Bignum)val).value.ToString((uint)numBase)); //tmp2 = rb_big2str(val, numBase); s = 0;// s = RSTRING(tmp2)->ptr; sString = ((String)tmp2).value; if (sString[s] == '-') { if (numBase == 10) { Errors.rb_warning("negative number for %%u specifier"); s++; } else { sString = Sprintf.remove_sign_bits(sString.Substring(++s), numBase); tmp2 = new String(); tt = 0; ttString = ((String)tmp2).value; if (!((flags & (Sprintf.FPREC | Sprintf.FZERO)) > 0)) { ttString.Insert(tt, ".."); tt += 2; } switch (numBase) { case 16: if (sString[0] != 'f') { ttString += "f"; //strcpy(t++, "f"); tt++; } break; case 8: if (sString[0] != 'f') { ttString += "7"; //strcpy(t++, "7"); tt++; } break; case 2: if (sString[0] != 'f') { ttString += "1"; //strcpy(t++, "1"); tt++; } break; } ttString += sString; //check //strcpy(t, s); bignum = 2; } } s = 0; sString = ((String)tmp2).value; format_integer: //pos = -1; len = sString.Length; if (fmtString[p] == 'X') { sString = sString.ToUpperInvariant(); } if ((flags & (Sprintf.FZERO | Sprintf.FPREC)) == Sprintf.FZERO) { prec = width; width = 0; } else { if (prec < len) prec = len; width -= prec; } if (!((flags & Sprintf.FMINUS) > 0)) { while (width-- > 0) { result.Append(' '); } } if (sc != '\0') { result.Append(sc); } if (prefix.Length > 0) { result.Append(prefix); } if (bignum == 0 && v < 0) { char c = Sprintf.sign_bits(numBase, fmtString[p]); while (len < prec--) { result.Append(c); } } else { char c; if ((bignum != 0) && ((Bignum)val).value < (IronMath.integer.make(0))) { c = Sprintf.sign_bits(numBase, fmtString[p]); } else { c = '0'; } while (len < prec--) { result.Append(c); } } result.Append(sString.Substring(s, len)); while (width-- > 0) { result.Append(' '); } } break; case 'f': case 'g': case 'G': case 'e': case 'E': { object val = Sprintf.GETARG(caller, ref posArg, ref nextArg, nextValue, args); double fval; int i = 0; int need = 6; string fbuf; fval = Float.rb_Float(val, caller).value; if (double.IsNaN(fval) || double.IsInfinity(fval)) { string expr; if (double.IsNaN(fval)) { expr = "NaN"; } else { expr = "Inf"; } need = expr.Length; if ((!double.IsNaN(fval) && fval < 0.0) || ((flags & Sprintf.FPLUS) != 0)) { need++; } if (((flags & Sprintf.FWIDTH) != 0) && need < width) { need = width; } //TODO - may need a blen count. // sprintf(&buf[blen], "%*s", need, ""); if ((flags & Sprintf.FMINUS) != 0) { if (!double.IsNaN(fval) && fval < 0.0) { result.Append('-'); //buf[blen++] = '-'; } else if ((flags & Sprintf.FPLUS) != 0) { result.Append('+'); //buf[blen++] = '+'; } else if ((flags & Sprintf.FSPACE) != 0) { result.Append(' '); //blen++; } result.Append(expr); //strncpy(&buf[blen], expr, strlen(expr)); } else if ((flags & Sprintf.FZERO) != 0) { if (!double.IsNaN(fval) && fval < 0.0) { result.Append('-');//buf[blen++] = '-'; need--; } else if ((flags & Sprintf.FPLUS) != 0) { result.Append('+'); //buf[blen++] = '+'; need--; } else if ((flags & Sprintf.FSPACE) != 0) { result.Append(' '); //blen++; need--; } while (need-- - expr.Length > 0) { result.Append('0'); } result.Append(expr); //strncpy(&buf[blen], expr, strlen(expr)); } else { if (!double.IsNaN(fval) && fval < 0.0) //run this - may need a blen count. //could buffer overflow - check this out result[need - expr.Length - 1] = '-'; //buf[blen + need - strlen(expr) - 1] = '-'; else if ((flags & Sprintf.FPLUS) != 0) result[need - expr.Length - 1] = '-'; //buf[blen + need - strlen(expr) - 1] = '+'; //TODO - may need a blen count //strncpy(&buf[blen + need - strlen(expr)], expr, strlen(expr)); } //blen += strlen(&buf[blen]); break; } fbuf = Sprintf.fmt_setup(fmtString[p], flags, width, prec); need = 0; if (fmtString[p] != 'e' && fmtString[p] != 'E') { i = int.MinValue; object frexpResult = Ruby.Methods.math_frexp.singleton.Call1(last_class, null, caller, block, new Float(fval)); i = (int)((Array)frexpResult).value[1]; //get the exponent if (i > 0) { need = Sprintf.BIT_DIGITS(i); } } need += ((flags & Sprintf.FPREC) > 0) ? prec : 6; if (((flags & Sprintf.FWIDTH) != 0) && need < width) { need = width; } need += 20; result.Append(Sprintf.sprintf(fbuf, fval)); // sprintf(&buf[blen], fbuf, fval); //may need to include belen calcs? // blen += strlen(&buf[blen]); } break; default: if (char.IsLetterOrDigit(fmtString[p]) || fmtString[p] == ' ') throw new ArgumentError(string.Format(CultureInfo.InvariantCulture, "malformed format string - %{0}", fmtString)).raise(caller); else throw new ArgumentError("malformed format string").raise(caller); } flags = Sprintf.FNONE; } sprint_exit: // /* XXX - We cannot validiate the number of arguments because // * the format string may contain `n$'-style argument selector. // */ if (Eval.Test(Options.ruby_verbose.value) && posArg >= 0 && nextArg < args.Count) { throw new ArgumentError("too many arguments for format string").raise(caller); } String res = new String(result.ToString()); //TODO: // if (tainted) OBJ_TAINT(result); return res; }
public override object Call1(Class last_class, object recv, Frame caller, Proc block, object param0) { if (recv is int) recv = new Bignum((double)(int)recv); if (param0 is int) { return Bignum.NormaliseUsing(((Bignum)recv).value * (int)param0); } else if (param0 is Bignum) { return Bignum.NormaliseUsing(((Bignum)recv).value * ((Bignum)param0).value); } else if (param0 is Float) { return new Float((double)((Bignum)recv).value * ((Float)param0).value); } else { return Numeric.rb_num_coerce_bin(recv, param0, "*", caller); } }
internal static object r_object0(Frame caller, load_arg arg, object proc, ref int ivp, object extmod) { object v = null; int type = r_byte(caller, arg); int id; switch (type) { case TYPE_LINK: //TEST: id = r_long(caller, arg); v = Ruby.Methods.rb_hash_aref.singleton.Call1(null, arg.data, caller, null, id); if (v == null) { throw new ArgumentError("dump format error (unlinked)").raise(caller); } return v; case TYPE_IVAR: //TEST: { int ivar = 1; v = r_object0(caller, arg, null, ref ivar, extmod); if (ivar > 0) r_ivar(caller, v, arg); } break; case TYPE_EXTENDED: //TEST: { object m = path2module(r_unique(caller, arg), caller); if (extmod == null) { extmod = new Array(); ((Array)extmod).value.Add(m); } int temp = 0; v = r_object0(caller, arg, null, ref temp, extmod); while (((Array)extmod).value.Count > 0) { m = ((Array)extmod).value[((Array)extmod).value.Count - 1]; ((Array)extmod).value.RemoveAt(((Array)extmod).value.Count - 1); Class.rb_extend_object(caller, v, (Class)m); } } break; case TYPE_UCLASS: { object c = path2class(caller, r_unique(caller, arg)); if (((Class)c)._type == Class.Type.Singleton) { throw new TypeError("singleton can't be loaded").raise(caller); } int temp = 0; v = r_object0(caller, arg, null, ref temp, extmod); if (rb_special_const_p(v) || v is Object || (v is Class && ((Class)v)._type == Class.Type.Class)) { throw new ArgumentError("dump format error (user class)").raise(caller); } if ((v is Class && ((Class)v)._type == Class.Type.Module) || !RTEST(Ruby.Methods.rb_class_inherited_p.singleton.Call1(null, c, caller, null, ((Basic)v).my_class))) { object tmp = new Object((Class)c); //TODO: Write this comparison //if (TYPE(v) != TYPE(tmp)) //{ // throw new ArgumentError("dump format error (user class)").raise(caller); //} } ((Basic)v).my_class = (Class)c; } break; case TYPE_NIL: v = null; break; case TYPE_TRUE: v = true; break; case TYPE_FALSE: v = false; break; case TYPE_FIXNUM: { v = r_long(caller, arg); } break; case TYPE_FLOAT: { double d; object str = r_bytes(caller, arg); string ptr = ((String)str).value; if (ptr.Equals("nan")) { d = double.NaN; } else if (ptr.Equals("inf")) { d = double.PositiveInfinity; } else if (ptr.Equals("-inf")) { d = double.NegativeInfinity; } else if (ptr.Equals("-0")) { d = -0.0; } else { int e = 0; d = String.strtod(ptr, 0, out e); d = load_mantissa(d, ptr.Substring(e), ((String)str).value.Length - e); } v = new Float(d); r_entry(caller, v, arg); } break; case TYPE_BIGNUM: { int len; uint[] digits; object data; int sign = ((char)r_byte(caller, arg) == '+') ? 1 : -1; len = r_long(caller, arg); data = r_bytes0(caller, len * 2, arg); int bigLen = (len + 1) * 2 / SIZEOF_BDIGITS; //extract data to bytes digits = new uint[bigLen]; byte[] digitData = new byte[bigLen * SIZEOF_BDIGITS]; char[] charDigitData = ((String)data).value.ToCharArray(); for (int i = 0; i < ((String)data).value.Length; i++) { digitData[i] = (byte)charDigitData[i]; } //save data to digits for (int uintCount = 0; uintCount < digits.Length; uintCount++) { digits[uintCount] = System.BitConverter.ToUInt32(digitData, (uintCount * 4)); } v = new Bignum(new IronMath.integer(sign, digits)); r_entry(caller, v, arg); } break; case TYPE_STRING: v = r_entry(caller, r_string(caller, arg), arg); break; case TYPE_REGEXP: { object str = r_bytes(caller, arg); int options = r_byte(caller, arg); v = r_entry(caller, new Regexp(((String)str).value, options), arg); } break; case TYPE_ARRAY: { int len = r_long(caller, arg); v = new Array(); r_entry(caller, v, arg); while (len-- > 0) { ((Array)v).value.Add(r_object(caller, arg)); } } break; case TYPE_HASH: case TYPE_HASH_DEF: { int len = r_long(caller, arg); v = new Hash(); r_entry(caller, v, arg); while (len-- > 0) { object key = r_object(caller, arg); object value = r_object(caller, arg); ((Hash)v).Add(key, value); } if (type == TYPE_HASH_DEF) { ((Hash)v).defaultValue = r_object(caller, arg); } } break; case TYPE_STRUCT: { Class klass; object mem; object[] values; int len; int slot; string klassPath = r_unique(caller, arg); klass = (Class)path2class(caller, klassPath); mem = Ruby.Methods.rb_struct_s_members.singleton.Call0(klass, klass, caller, null); if (mem == null) { throw new TypeError("uninitialized struct").raise(caller); } len = r_long(caller, arg); values = new object[len]; for (int i = 0; i < len; i++) { slot = r_symbol(caller, arg); if ((string)((Array)mem).value[i] != Symbol.rb_id2name((uint)slot)) { string errorString = string.Format(CultureInfo.InvariantCulture, "struct {0} not compatible (:{1} for :{2})", rb_class2name(klass, caller), Symbol.rb_id2name((uint)slot), ((Array)mem).value[i]); throw new TypeError(errorString).raise(caller); } values[i] = r_object(caller, arg); } v = Ruby.Methods.rb_class_new_instance.singleton.Call(klass, klass, caller, null, new Array(values)); r_entry(caller, v, arg); } break; case TYPE_USERDEF: { object klass = path2class(caller, r_unique(caller, arg)); object data; if (!Eval.RespondTo(klass, s_load)) { throw new TypeError(string.Format(CultureInfo.InvariantCulture, "class {0} needs to have method `_load'", rb_class2name(klass, caller))).raise(caller); } data = r_string(caller, arg); if (ivp > 0) { r_ivar(caller, data, arg); ivp = 0; } v = Eval.CallPrivate1(klass, caller, s_load, null, data); r_entry(caller, v, arg); } break; case TYPE_USRMARSHAL: { object klass = path2class(caller, r_unique(caller, arg)); object data; v = Ruby.Methods.rb_obj_alloc.singleton.Call0(null, klass, caller, null); if (extmod != null) { while (((Array)extmod).value.Count > 0) { object m = ((Array)extmod).value[((Array)extmod).value.Count - 1]; ((Array)extmod).value.RemoveAt(((Array)extmod).value.Count - 1); Class.rb_extend_object(caller, v, (Class)m); } } if (!Eval.RespondTo(v, s_mload)) { throw new TypeError(string.Format(CultureInfo.InvariantCulture, "instance of {0} needs to have method `marshal_load'", rb_class2name(klass, caller))).raise(caller); } r_entry(caller, v, arg); data = r_object(caller, arg); Eval.CallPrivate1(v, caller, s_mload, null, data); } break; case TYPE_OBJECT: { object klass = path2class(caller, r_unique(caller, arg)); v = Ruby.Methods.rb_obj_alloc.singleton.Call0(null, klass, caller, null); if (!(v is Object)) { throw new ArgumentError("dump format error").raise(caller); } r_entry(caller, v, arg); r_ivar(caller, v, arg); } break; case TYPE_DATA://TEST { object klass = path2class(caller, r_unique(caller, arg)); if (Eval.RespondTo(klass, s_alloc)) { type_data_warn = true; //TEST: static int warn = Qtrue; - test that this is equivalent note the 'STATIC' keyword if (type_data_warn) { Errors.rb_warn("define `allocate' instead of `_alloc'"); type_data_warn = false; } v = Eval.CallPrivate0(klass, caller, s_alloc, null); } else { v = Ruby.Methods.rb_obj_alloc.singleton.Call0(null, klass, caller, null); } if (!(v is Data)) { throw new ArgumentError("dump format error").raise(caller); } r_entry(caller, v, arg); if (!Eval.RespondTo(v, s_load_data)) { throw new TypeError(string.Format(CultureInfo.InvariantCulture, "class {0} needs to have instance method `_load_data'", rb_class2name(klass, caller))).raise(caller); } int temp = 0; Eval.CallPrivate1(v, caller, s_load_data, null, r_object0(caller, arg, null, ref temp, extmod)); } break; case TYPE_MODULE_OLD: //TEST: { object str = r_bytes(caller, arg); v = rb_path2class(caller, ((String)str).value); r_entry(caller, v, arg); } break; case TYPE_CLASS: { object str = r_bytes(caller, arg); v = path2class(caller, ((String)str).value); r_entry(caller, v, arg); } break; case TYPE_MODULE: //TEST: { object str = r_bytes(caller, arg); v = path2module(((String)str).value, caller); r_entry(caller, v, arg); } break; case TYPE_SYMBOL: //TEST: v = new Symbol((uint)r_symreal(caller, arg)); break; case TYPE_SYMLINK: //TEST: return new Symbol((uint)r_symlink(caller, arg)); default: throw new ArgumentError(string.Format(CultureInfo.InvariantCulture, "dump format error(0x{0})", type)).raise(caller); } if (proc != null) //TEST: { Eval.CallPrivate1(proc, caller, "call", null, v); } return v; }
internal static ulong rb_big2uquad_pack(Bignum b, Frame caller) { if (b.value < 0) { Bignum positiveBignum = new Bignum(b.value * -1); return ((ulong)((long)rb_big2uquad(positiveBignum, caller) * -1) & 0xFFFFFFFFFFFFFFFF); } else { return rb_big2uquad(b, caller); } }
internal static ulong rb_big2uquad(Bignum b, Frame caller) { if (b.value > ulong.MaxValue || b.value < ulong.MinValue) { throw new RangeError("bignum too big to convert into `quad int'").raise(caller); } return b.value.ToUInt64(); }
internal static uint rb_big2ulong_pack(Bignum b, Frame caller) { if (b.value < 0) { Bignum positiveBignum = new Bignum(b.value * -1); return (uint)((rb_big2ulong(positiveBignum, caller) * -1) & 0xFFFFFFFF); } else { return rb_big2ulong(b, caller); } }
internal static uint rb_big2ulong(Bignum b, Frame caller) { if (b.value > uint.MaxValue || b.value < uint.MinValue) { throw new RangeError("bignum too big to convert into `unsigned long'").raise(caller); } return b.value.ToUInt32(); }
public override object Call(Class last_class, object recv, Frame caller, Proc block, Array argv) { IO io = (IO)recv; int whence = IO.SEEK_SET; IO fptr; long pos; if (Class.rb_scan_args(caller, argv, 1, 1, false) == 2) { whence = Numeric.rb_num2long(argv[1], caller); } pos = Numeric.rb_num2long(argv[0], caller); fptr = IO.GetOpenFile(caller, io); if ((fptr.mode & IO.FMODE_WRITABLE) > 0 && (fptr.mode & IO.FMODE_WBUF) > 0) { Errors.rb_warn("sysseek for buffered IO"); } try { SeekOrigin so; if (whence == IO.SEEK_END) so = SeekOrigin.End; else if (whence == IO.SEEK_CUR) so = SeekOrigin.Current; else //if (whence == IO.SEEK_SET) // default to begin so = SeekOrigin.Begin; pos = fptr.f.Seek(pos, so); } catch (System.IO.IOException ioe) { throw SystemCallError.rb_sys_fail(fptr._path, ioe, caller).raise(caller); } if (pos == -1) throw SystemCallError.rb_sys_fail(fptr._path, new IOException(), caller).raise(caller); Bignum bpos = new Bignum(pos); return Bignum.NormaliseUsing(bpos.value); }