Files
Yukihiro "Matz" Matsumoto 8956c5abb5 mruby.h: include mruby/presym.h for all source files
Since presym is now mandatory, mruby.h includes presym.h so that
MRB_SYM() macros are available everywhere without explicit include.
Remove redundant #include <mruby/presym.h> from all source files.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-09 16:50:58 +09:00

128 lines
3.4 KiB
C

#include <mruby.h>
#include <mruby/string.h>
#include <mruby/variable.h>
#include <mruby/internal.h>
#define ENC_ASCII_8BIT "ASCII-8BIT"
#define ENC_BINARY "BINARY"
#define ENC_UTF8 "UTF-8"
/*
* call-seq:
* string.valid_encoding? -> true or false
*
* Returns true for a string which is encoded correctly.
*
*/
static mrb_value
str_valid_enc_p(mrb_state *mrb, mrb_value str)
{
#define utf8_islead(c) ((unsigned char)((c)&0xc0) != 0x80)
struct RString *s = mrb_str_ptr(str);
if (RSTR_SINGLE_BYTE_P(s)) return mrb_true_value();
if (RSTR_BINARY_P(s)) return mrb_true_value();
mrb_int byte_len = RSTR_LEN(s);
mrb_int utf8_len = 0;
const char *p = RSTR_PTR(s);
const char *e = p + byte_len;
while (p < e) {
mrb_int len = mrb_utf8len(p, e);
if (len == 1 && (*p & 0x80)) return mrb_false_value();
p += len;
utf8_len++;
}
if (byte_len == utf8_len) RSTR_SET_SINGLE_BYTE_FLAG(s);
return mrb_true_value();
}
static mrb_value
get_encoding(mrb_state *mrb, mrb_sym enc)
{
struct RClass *e = mrb_module_get_id(mrb, MRB_SYM(Encoding));
return mrb_const_get(mrb, mrb_obj_value(e), enc);
}
/*
* call-seq:
* string.encoding -> encoding
*
* Returns the Encoding object that represents the encoding of the string.
* In mruby, this returns either "UTF-8" or "ASCII-8BIT" (BINARY).
*
* "hello".encoding #=> "UTF-8"
* "\xff\xfe".encoding #=> "ASCII-8BIT"
*/
static mrb_value
str_encoding(mrb_state *mrb, mrb_value self)
{
struct RString *s = mrb_str_ptr(self);
if (RSTR_BINARY_P(s)) {
return get_encoding(mrb, MRB_SYM(BINARY));
}
return get_encoding(mrb, MRB_SYM(UTF_8));
}
/*
* call-seq:
* string.force_encoding(encoding) -> string
*
* Changes the encoding of the string to the specified encoding.
* This method modifies the string in place and returns self.
* In mruby, only "UTF-8", "ASCII-8BIT", and "BINARY" are supported.
*
* str = "hello"
* str.force_encoding("ASCII-8BIT") #=> "hello"
* str.encoding #=> "ASCII-8BIT"
*/
static mrb_value
str_force_encoding(mrb_state *mrb, mrb_value self)
{
mrb_value enc;
mrb_get_args(mrb, "S", &enc);
struct RString *s = mrb_str_ptr(self);
if (MRB_STR_CASECMP_P(enc, ENC_ASCII_8BIT) ||
MRB_STR_CASECMP_P(enc, ENC_BINARY)) {
s->flags |= MRB_STR_BINARY;
}
else if (MRB_STR_CASECMP_P(enc, ENC_UTF8)) {
s->flags &= ~MRB_STR_BINARY;
}
else {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "unknown encoding name - %v", enc);
}
return self;
}
void
mrb_mruby_encoding_gem_init(mrb_state* mrb)
{
struct RClass *s = mrb->string_class;
mrb_define_method_id(mrb, s, MRB_SYM_Q(valid_encoding), str_valid_enc_p, MRB_ARGS_NONE());
mrb_define_method_id(mrb, s, MRB_SYM(encoding), str_encoding, MRB_ARGS_NONE());
mrb_define_method_id(mrb, s, MRB_SYM(force_encoding), str_force_encoding, MRB_ARGS_REQ(1));
/* Poorman's Encoding
*
* Encoding - module instead of class
* encodings - supports only UTF-8 and ASCII-8BIT (and its alias BINARY)
* each Encoding - encoding name string instead of Encoding object
*
*/
struct RClass *e = mrb_define_module_id(mrb, MRB_SYM(Encoding));
mrb_value b = mrb_str_new_lit_frozen(mrb, ENC_ASCII_8BIT);
mrb_define_const_id(mrb, e, MRB_SYM(ASCII_8BIT), b);
mrb_define_const_id(mrb, e, MRB_SYM(BINARY), b);
mrb_define_const_id(mrb, e, MRB_SYM(UTF_8), mrb_str_new_lit_frozen(mrb, ENC_UTF8));
}
void
mrb_mruby_encoding_gem_final(mrb_state* mrb)
{
}