GitHub

@@ -1081,6 +1081,85 @@ io_print(mrb_state *mrb, mrb_value io)

10811081

return mrb_nil_value();

10821082

}

108310831084+

/*

1085+

* call-seq:

1086+

* ios.putc(obj) -> obj

1087+

*

1088+

* If obj is Integer, write the byte (mod 256).

1089+

* If obj is String, write the first character.

1090+

* Returns obj.

1091+

*/

1092+

static mrb_value

1093+

io_putc(mrb_state *mrb, mrb_value io)

1094+

{

1095+

struct mrb_io *fptr = io_get_write_fptr(mrb, io);

1096+

int fd = io_get_write_fd(fptr);

1097+

mrb_value c = mrb_get_arg1(mrb);

1098+

const char *ptr;

1099+

mrb_int write_len;

1100+1101+

io_prepare_write(mrb, fptr);

1102+1103+

if (mrb_integer_p(c)) {

1104+

unsigned char byte = (unsigned char)(mrb_integer(c) & 0xff);

1105+

ssize_t n;

1106+

do {

1107+

n = write(fd, &byte, 1);

1108+

} while (n == -1 && errno == EINTR);

1109+

if (n == -1) mrb_sys_fail(mrb, "write");

1110+

return c;

1111+

}

1112+1113+

mrb_value str;

1114+

if (mrb_string_p(c)) {

1115+

str = c;

1116+

}

1117+

else {

1118+

str = mrb_obj_as_string(mrb, c);

1119+

}

1120+1121+

ptr = RSTRING_PTR(str);

1122+

mrb_int len = RSTRING_LEN(str);

1123+1124+

if (len == 0) return c;

1125+1126+

#ifdef MRB_UTF8_STRING

1127+

/* Determine UTF-8 character length from first byte */

1128+

unsigned char first = (unsigned char)ptr[0];

1129+

if (first < 0x80) {

1130+

write_len = 1; /* ASCII */

1131+

}

1132+

else if ((first & 0xE0) == 0xC0) {

1133+

write_len = 2; /* 2-byte UTF-8 */

1134+

}

1135+

else if ((first & 0xF0) == 0xE0) {

1136+

write_len = 3; /* 3-byte UTF-8 */

1137+

}

1138+

else if ((first & 0xF8) == 0xF0) {

1139+

write_len = 4; /* 4-byte UTF-8 */

1140+

}

1141+

else {

1142+

write_len = 1; /* Invalid UTF-8, write single byte */

1143+

}

1144+

if (write_len > len) write_len = len;

1145+

#else

1146+

write_len = 1; /* Non-UTF8: write single byte */

1147+

#endif

1148+1149+

/* Write the character bytes */

1150+

while (write_len > 0) {

1151+

ssize_t n = write(fd, ptr, write_len);

1152+

if (n == -1) {

1153+

if (errno == EINTR) continue;

1154+

mrb_sys_fail(mrb, "write");

1155+

}

1156+

ptr += n;

1157+

write_len -= n;

1158+

}

1159+1160+

return c;

1161+

}

1162+10841163

/*

10851164

* call-seq:

10861165

* ios << obj -> ios

@@ -2180,6 +2259,7 @@ mrb_init_io(mrb_state *mrb)

21802259

mrb_define_method_id(mrb, io, MRB_SYM(write), io_write, MRB_ARGS_ANY()); /* 15.2.20.5.20 */

21812260

mrb_define_method_id(mrb, io, MRB_SYM(puts), io_puts, MRB_ARGS_ANY());

21822261

mrb_define_method_id(mrb, io, MRB_SYM(print), io_print, MRB_ARGS_ANY());

2262+

mrb_define_method_id(mrb, io, MRB_SYM(putc), io_putc, MRB_ARGS_REQ(1));

21832263

mrb_define_method_id(mrb, io, MRB_OPSYM(lshift), io_lshift, MRB_ARGS_REQ(1));

21842264

mrb_define_method_id(mrb, io, MRB_SYM(pread), io_pread, MRB_ARGS_ANY()); /* Ruby 2.5 feature */

21852265

mrb_define_method_id(mrb, io, MRB_SYM(pwrite), io_pwrite, MRB_ARGS_ANY()); /* Ruby 2.5 feature */

Read the original on github.com ↗