mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
8956c5abb5
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>
128 lines
3.4 KiB
C
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)
|
|
{
|
|
}
|