Project

General

Profile

Feature #6440 » patch.diff

Glass_saga (Masaki Matsushita), 05/16/2012 12:49 PM

View differences:

marshal.c
81 81

  
82 82
static ID s_dump, s_load, s_mdump, s_mload;
83 83
static ID s_dump_data, s_load_data, s_alloc, s_call;
84
static ID s_getbyte, s_read, s_write, s_binmode;
84
static ID s_getbyte, s_read, s_readpartial, s_write, s_binmode;
85 85

  
86 86
typedef struct {
87 87
    VALUE newclass;
......
958 958

  
959 959
struct load_arg {
960 960
    VALUE src;
961
    char *buf;
962
    long buflen;
961 963
    long offset;
964
    int partial;
962 965
    st_table *symbols;
963 966
    st_table *data;
964 967
    VALUE proc;
......
1030 1033
	    c = (unsigned char)RSTRING_PTR(arg->src)[arg->offset++];
1031 1034
	}
1032 1035
	else {
1036
	  too_short:
1033 1037
	    rb_raise(rb_eArgError, "marshal data too short");
1034 1038
	}
1035 1039
    }
1036 1040
    else {
1037
	VALUE src = arg->src;
1038
	VALUE v = rb_funcall2(src, s_getbyte, 0, 0);
1039
	check_load_arg(arg, s_getbyte);
1040
	if (NIL_P(v)) rb_eof_error();
1041
	c = (unsigned char)NUM2CHR(v);
1041
	if (arg->buflen == 0) {
1042
	    VALUE str, n = LONG2NUM(BUFSIZ);
1043

  
1044
	    if (arg->partial)
1045
		str = rb_funcall2(arg->src, s_readpartial, 1, &n);
1046
	    else
1047
		str = rb_funcall2(arg->src, s_read, 1, &n);
1048

  
1049
	    check_load_arg(arg, s_read);
1050
	    if (NIL_P(str)) goto too_short;
1051
	    StringValue(str);
1052
	    arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
1053
	    memcpy(arg->buf, RSTRING_PTR(str), RSTRING_LEN(str));
1054
	    arg->offset = 0;
1055
	    arg->buflen = RSTRING_LEN(str);
1056
	}
1057
	c = (unsigned char)arg->buf[arg->offset++];
1058
	arg->buflen--;
1042 1059
    }
1043 1060
    return c;
1044 1061
}
......
1091 1108
    return x;
1092 1109
}
1093 1110

  
1111
static VALUE
1112
r_bytes1(long len, struct load_arg *arg)
1113
{
1114
    VALUE str, n = LONG2NUM(len);
1115

  
1116
    str = rb_funcall2(arg->src, s_read, 1, &n);
1117
    check_load_arg(arg, s_read);
1118

  
1119
    if (NIL_P(str)) {
1120
      too_short:
1121
	rb_raise(rb_eArgError, "marshal data too short");
1122
    }
1123
    StringValue(str);
1124
    if (RSTRING_LEN(str) < len) goto too_short;
1125

  
1126
    arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
1127

  
1128
    return str;
1129
}
1130

  
1131
static VALUE
1132
r_bytes1_partial(long len, struct load_arg *arg)
1133
{
1134
    long buflen = arg->buflen;
1135
    long tmp_len, need = len - buflen;
1136
    VALUE n = LONG2NUM(need > BUFSIZ ? need : BUFSIZ);
1137
    VALUE str, tmp;
1138
    const char *tmp_ptr;
1139

  
1140
    tmp = rb_funcall2(arg->src, s_readpartial, 1, &n);
1141

  
1142
    check_load_arg(arg, s_read);
1143
    if (NIL_P(tmp)) {
1144
      too_short:
1145
	rb_raise(rb_eArgError, "marshal data too short");
1146
    }
1147
    StringValue(tmp);
1148

  
1149
    tmp_ptr = RSTRING_PTR(tmp);
1150
    tmp_len = RSTRING_LEN(tmp);
1151

  
1152
    if (tmp_len < need) {
1153
	VALUE fill;
1154

  
1155
	/* retry */
1156
	n = LONG2NUM(need-tmp_len);
1157
	fill = rb_funcall2(arg->src, s_read, 1, &n);
1158

  
1159
	if (NIL_P(fill)) goto too_short;
1160
	StringValue(fill);
1161
	if (RSTRING_LEN(fill) < need-tmp_len) goto too_short;
1162

  
1163
	rb_str_concat(tmp, fill);
1164
	tmp_len = RSTRING_LEN(tmp);
1165
    }
1166

  
1167
    arg->infection |= (int)FL_TEST(tmp, MARSHAL_INFECTION);
1168
    str = rb_str_new(arg->buf+arg->offset, buflen);
1169
    rb_str_cat(str, tmp_ptr, need);
1170
    if (tmp_len-need > 0)
1171
	memcpy(arg->buf, tmp_ptr+need, tmp_len-need);
1172

  
1173
    arg->offset = 0;
1174
    arg->buflen = tmp_len - need;
1175

  
1176
    return str;
1177
}
1178

  
1094 1179
#define r_bytes(arg) r_bytes0(r_long(arg), (arg))
1095 1180

  
1096 1181
static VALUE
......
1105 1190
	    arg->offset += len;
1106 1191
	}
1107 1192
	else {
1108
	  too_short:
1109 1193
	    rb_raise(rb_eArgError, "marshal data too short");
1110 1194
	}
1111 1195
    }
1112 1196
    else {
1113
	VALUE src = arg->src;
1114
	VALUE n = LONG2NUM(len);
1115
	str = rb_funcall2(src, s_read, 1, &n);
1116
	check_load_arg(arg, s_read);
1117
	if (NIL_P(str)) goto too_short;
1118
	StringValue(str);
1119
	if (RSTRING_LEN(str) != len) goto too_short;
1120
	arg->infection |= (int)FL_TEST(str, MARSHAL_INFECTION);
1197
	if (len <= arg->buflen) {
1198
	    str = rb_str_new(arg->buf+arg->offset, len);
1199
	    arg->offset += len;
1200
	    arg->buflen -= len;
1201
	}
1202
	else {
1203
	    if (arg->partial)
1204
		str = r_bytes1_partial(len, arg);
1205
	    else
1206
		str = r_bytes1(len, arg);
1207
	}
1121 1208
    }
1122 1209
    return str;
1123 1210
}
......
1784 1871
    arg->data    = st_init_numtable();
1785 1872
    arg->compat_tbl = st_init_numtable();
1786 1873
    arg->proc = 0;
1874
    arg->partial = 0;
1875

  
1876
    if(NIL_P(v)) {
1877
	if (rb_respond_to(port, s_readpartial)) arg->partial = 1;
1878
	arg->buf = xmalloc(BUFSIZ);
1879
    }
1787 1880

  
1788 1881
    major = r_byte(arg);
1789 1882
    minor = r_byte(arg);
......
1921 2014
    s_call = rb_intern("call");
1922 2015
    s_getbyte = rb_intern("getbyte");
1923 2016
    s_read = rb_intern("read");
2017
    s_readpartial = rb_intern("readpartial");
1924 2018
    s_write = rb_intern("write");
1925 2019
    s_binmode = rb_intern("binmode");
1926 2020