15#define STRINGIO_VERSION "3.0.1"
20#if defined(HAVE_FCNTL_H) || defined(_WIN32)
22#elif defined(HAVE_SYS_FCNTL_H)
26#ifndef RB_INTEGER_TYPE_P
27# define RB_INTEGER_TYPE_P(c) (FIXNUM_P(c) || RB_TYPE_P(c, T_BIGNUM))
30#ifndef RB_PASS_CALLED_KEYWORDS
31# define rb_funcallv_kw(recv, mid, arg, argv, kw_splat) rb_funcallv(recv, mid, arg, argv)
32# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
35#ifndef HAVE_RB_IO_EXTRACT_MODEENC
36#define rb_io_extract_modeenc strio_extract_modeenc
39 int *oflags_p,
int *fmode_p,
struct rb_io_enc_t *convconfig_p)
44 int has_enc = 0, has_vmode = 0;
46 convconfig_p->enc = convconfig_p->enc2 = 0;
83 if (!
NIL_P(opthash)) {
120static VALUE strio_unget_bytes(
struct StringIO *,
const char *,
long);
123#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
124#define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
125#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
151 if (--
ptr->count <= 0) {
157strio_memsize(
const void *p)
172#define check_strio(self) ((struct StringIO*)rb_check_typeddata((self), &strio_data_type))
199 if (
len > rlen)
len = rlen;
202 return enc_subseq(
str, pos,
len, enc);
205#define StringIO(obj) get_strio(obj)
207#define STRIO_READABLE FL_USER4
208#define STRIO_WRITABLE FL_USER5
209#define STRIO_READWRITE (STRIO_READABLE|STRIO_WRITABLE)
211#define STRIO_MODE_SET_P(strio, mode) \
212 ((RBASIC(strio)->flags & STRIO_##mode) && \
213 ((struct StringIO*)DATA_PTR(strio))->flags & FMODE_##mode)
214#define CLOSED(strio) (!STRIO_MODE_SET_P(strio, READWRITE))
215#define READABLE(strio) STRIO_MODE_SET_P(strio, READABLE)
216#define WRITABLE(strio) STRIO_MODE_SET_P(strio, WRITABLE)
218static VALUE sym_exception;
249strio_s_allocate(
VALUE klass)
278 if (
len < 1)
return 0;
279 switch ((
unsigned char)p[0]) {
282 if ((
unsigned char)p[1] == 0xBB &&
len > 2) {
283 if ((
unsigned char)p[2] == 0xBF) {
292 if ((
unsigned char)p[1] == 0xFF) {
300 if ((
unsigned char)p[1] == 0xFE) {
301 if (
len >= 4 && (
unsigned char)p[2] == 0 && (
unsigned char)p[3] == 0) {
312 if ((
unsigned char)p[1] == 0 && (
unsigned char)p[2] == 0xFE && (
unsigned char)p[3] == 0xFF) {
324 int bomlen, idx = detect_bom(
ptr->string, &bomlen);
341 VALUE string, vmode, opt;
366 ptr->string = string;
371 ptr->enc = convconfig.enc;
381strio_finalize(
VALUE self)
421strio_false(
VALUE self)
441strio_self(
VALUE self)
485strio_get_string(
VALUE self)
507 return ptr->string = string;
518strio_close(
VALUE self)
521 RBASIC(self)->flags &= ~STRIO_READWRITE;
533strio_close_read(
VALUE self)
539 RBASIC(self)->flags &= ~STRIO_READABLE;
551strio_close_write(
VALUE self)
557 RBASIC(self)->flags &= ~STRIO_WRITABLE;
568strio_closed(
VALUE self)
582strio_closed_read(
VALUE self)
596strio_closed_write(
VALUE self)
604strio_to_read(
VALUE self)
622 if (strio_to_read(self))
return Qfalse;
633 if (copy == orig)
return copy;
639 RBASIC(copy)->flags &= ~STRIO_READWRITE;
656strio_get_lineno(
VALUE self)
683strio_binmode(
VALUE self)
695#define strio_fcntl strio_unimpl
697#define strio_flush strio_self
699#define strio_fsync strio_0
714 return strio_copy(self, *
argv);
727strio_get_pos(
VALUE self)
758strio_rewind(
VALUE self)
812strio_get_sync(
VALUE self)
818#define strio_set_sync strio_first
820#define strio_tell strio_get_pos
830strio_each_byte(
VALUE self)
836 while ((
ptr = strio_to_read(self)) !=
NULL) {
850strio_getc(
VALUE self)
865 return enc_subseq(
str, pos,
len, enc);
875strio_getbyte(
VALUE self)
894 check_modifiable(
ptr);
896 if (pos +
len > olen) {
921 check_modifiable(
ptr);
957 check_modifiable(
ptr);
962 const char cc =
NUM2INT(v) & 0xFF;
963 strio_unget_bytes(
ptr, &cc, 1);
978strio_unget_bytes(
struct StringIO *
ptr,
const char *cp,
long cl)
980 long pos =
ptr->pos,
len, rest;
987 long ex = (rest < 0 ? cl-pos : cl+rest);
991 if (rest < 0)
memmove(s + cl, s + pos, -rest);
1000 if (rest > cl) memset(s +
len, 0, rest - cl);
1015strio_readchar(
VALUE self)
1029strio_readbyte(
VALUE self)
1044strio_each_char(
VALUE self)
1050 while (!
NIL_P(c = strio_getc(self))) {
1064strio_each_codepoint(
VALUE self)
1073 ptr = readable(self);
1075 while ((
ptr = strio_to_read(self)) !=
NULL) {
1077 RSTRING_END(
ptr->string), &n, enc);
1086bm_init_skip(
long *
skip,
const char *pat,
long m)
1090 for (c = 0; c < (1 <<
CHAR_BIT); c++) {
1094 skip[(
unsigned char)*pat++] = m;
1099bm_search(
const char *little,
long llen,
const char *big,
long blen,
const long *
skip)
1107 while (j >= 0 && big[k] == little[j]) {
1111 if (j < 0)
return k + 1;
1112 i +=
skip[(
unsigned char)big[i]];
1157 static ID keywords[1];
1160 keywords[0] = rb_intern_const(
"chomp");
1169chomp_newline_width(
const char *s,
const char *e)
1171 if (e > s && *--e ==
'\n') {
1172 if (e > s && *--e ==
'\r')
return 2;
1181 const char *s, *e, *p;
1193 if (
limit > 0 && (
size_t)
limit < (
size_t)(e - s)) {
1198 w = chomp_newline_width(s, e);
1200 str = strio_substr(
ptr,
ptr->pos, e - s - w, enc);
1204 while (p[(p + 1 < e) && (*p ==
'\r') && 0] ==
'\n') {
1211 while ((p = memchr(p,
'\n', e - p)) && (p != e)) {
1214 w = (arg->
chomp ? 1 : 0);
1217 else if (*p ==
'\r' && p < e && p[1] ==
'\n') {
1219 w = (arg->
chomp ? 2 : 0);
1223 if (!w && arg->
chomp) {
1224 w = chomp_newline_width(s, e);
1231 w = (arg->
chomp ? (p > s && *(p-1) ==
'\r') + 1 : 0);
1233 str = strio_substr(
ptr,
ptr->pos, e - s - w, enc);
1238 for (p = s; p + n <= e; ++p) {
1240 e = p + (arg->
chomp ? 0 : n);
1248 bm_init_skip(
skip, p, n);
1249 if ((pos = bm_search(p, n, s, e - s,
skip)) >= 0) {
1250 e = s + pos + (arg->
chomp ? 0 : n);
1254 str = strio_substr(
ptr,
ptr->pos, e - s - w, enc);
1280 str = strio_getline(&arg, readable(self));
1328 while (!
NIL_P(line = strio_getline(&arg, readable(self)))) {
1354 while (!
NIL_P(line = strio_getline(&arg, readable(self)))) {
1374 while (
argc-- > 0) {
1376 len += strio_write(self, *
argv++);
1396 if (converted ==
str && enc2 != ascii8bit && enc2 != usascii) {
1402 if (
len == 0)
return 0;
1403 check_modifiable(
ptr);
1408 if (
ptr->pos == olen) {
1409 if (enc == ascii8bit || enc2 == ascii8bit) {
1431#define strio_addstr rb_io_addstr
1440#define strio_print rb_io_print
1448#define strio_printf rb_io_printf
1462 check_modifiable(
ptr);
1470 strio_write(self,
str);
1480#define strio_puts rb_io_puts
1520 if (len <= ptr->pos) {
1544 if (
len > rest)
len = rest;
1592 val = strio_read(
argc,
argv, self);
1604#define strio_syswrite rb_io_write
1615#define strio_isatty strio_false
1617#define strio_pid strio_nil
1619#define strio_fileno strio_nil
1629strio_size(
VALUE self)
1632 if (
NIL_P(
string)) {
1671strio_external_encoding(
VALUE self)
1686strio_internal_encoding(
VALUE self)
1706 VALUE ext_enc, int_enc, opt;
1710 if (
NIL_P(ext_enc)) {
1725strio_set_encoding_by_bom(
VALUE self)
1729 if (!set_encoding_by_bom(
ptr))
return Qnil;
1758#ifdef HAVE_RB_EXT_RACTOR_SAFE
1861 rb_define_method(mWritable,
"write_nonblock", strio_syswrite_nonblock, -1);
VALUE rb_ary_push(VALUE ary, VALUE item)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
char * strchr(char *, char)
#define rb_utf8_encindex()
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
rb_encoding * rb_ascii8bit_encoding(void)
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
rb_encoding * rb_enc_from_index(int index)
rb_encoding * rb_enc_get(VALUE obj)
void rb_enc_copy(VALUE obj1, VALUE obj2)
rb_encoding * rb_enc_find(const char *name)
rb_encoding * rb_default_external_encoding(void)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
rb_encoding * rb_to_encoding(VALUE enc)
rb_encoding * rb_usascii_encoding(void)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
VALUE rb_enc_associate_index(VALUE obj, int idx)
int rb_enc_find_index(const char *name)
int rb_enc_codelen(int c, rb_encoding *enc)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
void rb_gc_mark(VALUE ptr)
void rb_include_module(VALUE klass, VALUE module)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_define_module_under(VALUE outer, const char *name)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
int rb_block_given_p(void)
Determines if the current method is given a block.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
void rb_notimplement(void)
void rb_syserr_fail(int e, const char *mesg)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_warn(const char *fmt,...)
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
VALUE rb_cObject
Object class.
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
void skip(file *in, unsigned n)
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
VALUE rb_hash_aref(VALUE hash, VALUE key)
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
#define rb_enc_mbcput(c, buf, enc)
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
#define ENCODING_MAXNAMELEN
VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc)
#define rb_enc_right_char_head(s, p, e, enc)
VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE *, int)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
VALUE rb_call_super(int, const VALUE *)
#define RETURN_ENUMERATOR(obj, argc, argv)
void rb_error_arity(int, int, int)
void rb_ext_ractor_safe(bool flag)
void rb_lastline_set(VALUE)
VALUE rb_str_resize(VALUE, long)
#define rb_str_new(str, len)
void rb_str_set_len(VALUE, long)
VALUE rb_str_substr(VALUE, long, long)
void rb_str_modify(VALUE)
VALUE rb_check_string_type(VALUE)
VALUE rb_str_subseq(VALUE, long, long)
void rb_str_modify_expand(VALUE, long)
VALUE rb_str_buf_append(VALUE, VALUE)
VALUE rb_obj_as_string(VALUE)
#define rb_str_new_cstr(str)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
ID rb_intern(const char *)
void rb_define_const(VALUE, const char *, VALUE)
int rb_io_modestr_fmode(const char *modestr)
#define FMODE_SETENC_BY_BOM
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
int rb_io_oflags_fmode(int oflags)
struct rb_io_enc_t rb_io_enc_t
VALUE rb_io_taint_check(VALUE)
void * memmove(void *, const void *, size_t)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
#define MEMCPY(p1, p2, type, n)
#define MEMCMP(p1, p2, type, n)
#define MEMZERO(p, type, n)
#define SafeStringValue(v)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
#define StringValueCStr(v)
#define TypedData_Wrap_Struct(klass, data_type, sval)
@ RUBY_TYPED_FREE_IMMEDIATELY
#define RB_INTEGER_TYPE_P(obj)
#define RB_PASS_CALLED_KEYWORDS
size_t strlen(const char *)
#define rb_io_extract_modeenc
char strio_flags_check[(STRIO_READABLE/FMODE_READABLE==STRIO_WRITABLE/FMODE_WRITABLE) *2 - 1]
#define check_strio(self)