Exemple #1
0
  /*
   * This is a primitive so #initialize_copy can work.
   */
  Regexp* Regexp::initialize(STATE, String* pattern, Fixnum* options) {
    const UChar *pat;
    const UChar *end;
    OnigErrorInfo err_info;
    OnigOptionType opts;
    OnigEncoding enc;
    int err, num_names, kcode;

    pat = (UChar*)pattern->byte_address();
    end = pat + pattern->size();

    opts  = options->to_native();
    kcode = opts & KCODE_MASK;
    opts &= OPTION_MASK;

    if(kcode == 0) {
      enc = current_encoding(state);
    } else {
      // Don't attempt to fix the encoding later, it's been specified by the
      // user.
      enc = get_enc_from_kcode(kcode);
      forced_encoding_ = true;
    }

    thread::Mutex::LockGuard lg(state->shared().onig_lock());

    err = onig_new(&this->onig_data, pat, end, opts, enc, ONIG_SYNTAX_RUBY, &err_info);

    if(err != ONIG_NORMAL) {
      UChar onig_err_buf[ONIG_MAX_ERROR_MESSAGE_LEN];
      char err_buf[1024];
      onig_error_code_to_str(onig_err_buf, err, &err_info);
      snprintf(err_buf, 1024, "%s: %s", onig_err_buf, pat);

      Exception::regexp_error(state, err_buf);
      return 0;
    }

    this->source(state, pattern);

    num_names = onig_number_of_names(this->onig_data);

    if(num_names == 0) {
      this->names(state, nil<LookupTable>());
    } else {
      struct _gather_data gd;
      gd.state = state;
      LookupTable* tbl = LookupTable::create(state);
      gd.tbl = tbl;
      onig_foreach_name(this->onig_data, (int (*)(const OnigUChar*, const OnigUChar*,int,int*,OnigRegex,void*))_gather_names, (void*)&gd);
      this->names(state, tbl);
    }

    make_managed(state);

    return this;
  }
Exemple #2
0
  void Regexp::maybe_recompile(STATE) {
    const UChar *pat;
    const UChar *end;
    OnigEncoding enc;
    OnigErrorInfo err_info;
    int err;

    if(forced_encoding_) return;

    enc = current_encoding(state);
    if(enc == onig_data->enc) return;

    pat = (UChar*)source()->c_str();
    end = pat + source()->size();

    int options = onig_data->options;
    OnigEncoding orig_enc = onig_data->enc;

    err = onig_new(&this->onig_data, pat, end, options,
                   enc, ONIG_SYNTAX_RUBY, &err_info);

    // If it doesn't work out, then abort and reset the encoding back
    // and say that it's forced.
    if(err != ONIG_NORMAL) {

      err = onig_new(&this->onig_data, pat, end, options,
                     orig_enc, ONIG_SYNTAX_RUBY, &err_info);

      // Ok, wtf. Well, no way to proceed now.
      if(err != ONIG_NORMAL) {
        OnigUChar buf[1024];
        onig_error_code_to_str((UChar*)buf, err, &err_info);
        std::cout << "Fatal ONIG error: " << buf << "\n";
        assert(err == ONIG_NORMAL);
      }

      forced_encoding_ = true;
    }

    make_managed(state);
  }