commit ce63fe31e903229c517536c73e3bf6a0afd7b8f5 Author: Roberto Alsina Date: Thu Aug 8 12:35:18 2024 -0300 A thing diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..163eb75 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.cr] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bbd4a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf + +# Libraries don't need dependency lock +# Dependencies will be locked in applications that use them +/shard.lock diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..930c197 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Roberto Alsina + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a26f9a1 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# cre2 + +TODO: Write a description here + +## Installation + +1. Add the dependency to your `shard.yml`: + + ```yaml + dependencies: + cre2: + github: your-github-user/cre2 + ``` + +2. Run `shards install` + +## Usage + +```crystal +require "cre2" +``` + +TODO: Write usage instructions here + +## Development + +TODO: Write development instructions here + +## Contributing + +1. Fork it () +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create a new Pull Request + +## Contributors + +- [Roberto Alsina](https://github.com/your-github-user) - creator and maintainer diff --git a/shard.yml b/shard.yml new file mode 100644 index 0000000..ac7e28d --- /dev/null +++ b/shard.yml @@ -0,0 +1,9 @@ +name: cre2 +version: 0.1.0 + +authors: + - Roberto Alsina + +crystal: '>= 1.13.0' + +license: MIT diff --git a/spec/cre2_spec.cr b/spec/cre2_spec.cr new file mode 100644 index 0000000..4f49f4c --- /dev/null +++ b/spec/cre2_spec.cr @@ -0,0 +1,9 @@ +require "./spec_helper" + +describe Cre2 do + # TODO: Write tests + + it "works" do + false.should eq(true) + end +end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr new file mode 100644 index 0000000..6ab8f93 --- /dev/null +++ b/spec/spec_helper.cr @@ -0,0 +1,2 @@ +require "spec" +require "../src/cre2" diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..4667226 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,5 @@ +all: cre2.o +clean: + rm -f cre2.o +cre2.o: cre2.cpp cre2.h + g++ -O3 -c -o cre2.o cre2.cpp diff --git a/src/cre2.cpp b/src/cre2.cpp new file mode 100644 index 0000000..7f07a7f --- /dev/null +++ b/src/cre2.cpp @@ -0,0 +1,122 @@ +#include +#include "cre2.h" + +#define TO_OPT(opt) (reinterpret_cast(opt)) + +cre2_options *cre2_opt_new(void) { + return reinterpret_cast(new RE2::Options()); +} + +void cre2_opt_delete(cre2_options *opt) { + delete TO_OPT(opt); +} + + +#define OPT_bool(name) \ +void cre2_opt_##name(cre2_options *opt, int flag) { \ + TO_OPT(opt)->set_##name(bool(flag)); \ +} + +OPT_bool(posix_syntax) +OPT_bool(longest_match) +OPT_bool(log_errors) +OPT_bool(literal) +OPT_bool(never_nl) +OPT_bool(dot_nl) +OPT_bool(case_sensitive) +OPT_bool(perl_classes) +OPT_bool(word_boundary) +OPT_bool(one_line) + +#undef OPT_BOOL + + +void cre2_opt_encoding(cre2_options *opt, encoding_t enc) { + switch (enc) { + case CRE2_UTF8: + TO_OPT(opt)->set_encoding(RE2::Options::EncodingUTF8); + break; + case CRE2_Latin1: + TO_OPT(opt)->set_encoding(RE2::Options::EncodingLatin1); + break; + } +} + +void cre2_opt_max_mem(cre2_options *opt, int m) { + TO_OPT(opt)->set_max_mem(m); +} + + +#define TO_RE2(re) (reinterpret_cast(re)) +#define TO_CONST_RE2(re) (reinterpret_cast(re)) + +cre2 *cre2_new(const char *pattern, int patternlen, const cre2_options *opt) { + re2::StringPiece pattern_re2(pattern, patternlen); + return reinterpret_cast( + new RE2(pattern_re2, *reinterpret_cast(opt))); +} + +void cre2_delete(cre2 *re) { + delete TO_RE2(re); +} + + +int cre2_error_code(const cre2 *re) { + return int(TO_CONST_RE2(re)->error_code()); +} + +const char *cre2_error_string(const cre2 *re) { + return TO_CONST_RE2(re)->error().c_str(); +} + +void cre2_error_arg(const cre2 *re, struct string_piece *arg) { + const std::string &argstr = TO_CONST_RE2(re)->error_arg(); + arg->data = argstr.data(); + arg->length = argstr.length(); +} + +int cre2_num_capturing_groups(const cre2 *re) { + return TO_CONST_RE2(re)->NumberOfCapturingGroups(); +} + +int cre2_program_size(const cre2 *re) { + return TO_CONST_RE2(re)->ProgramSize(); +} + + +int cre2_match( + const cre2 *re + , const char *text + , int textlen + , int startpos + , int endpos + , anchor_t anchor + , struct string_piece *match + , int nmatch) { + + re2::StringPiece text_re2(text, textlen); + // FIXME: exceptions? + re2::StringPiece *match_re2 = new re2::StringPiece[nmatch]; + + RE2::Anchor anchor_re2 = RE2::UNANCHORED; + switch (anchor) { + case CRE2_ANCHOR_START: + anchor_re2 = RE2::ANCHOR_START; break; + case CRE2_ANCHOR_BOTH: + anchor_re2 = RE2::ANCHOR_BOTH; break; + } + + bool ret = TO_CONST_RE2(re) + ->Match(text_re2, startpos, endpos, anchor_re2, match_re2, nmatch); + + if (ret) { + for (int i=0; i