PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/runtime/RegEx.cpp

https://github.com/Jerrydj/snow
C++ | 133 lines | 111 code | 20 blank | 2 comment | 10 complexity | 5a9c0cae8aa4ca934d16418ab55c5e03 MD5 | raw file
Possible License(s): 0BSD
  1. #include "RegEx.h"
  2. #include "Exception.h"
  3. namespace snow {
  4. RegEx::RegEx(const Ptr<String>& zpattern, OnigOptionType compilation_options, OnigEncoding encoding, OnigSyntaxType* syntax)
  5. : ThinObject(regex_prototype()), m_Handle(NULL)
  6. {
  7. const OnigUChar* cstr = (const OnigUChar*)zpattern->c_str();
  8. int len = zpattern->length();
  9. OnigErrorInfo err_info;
  10. int r = onig_new(&m_Handle, cstr, &cstr[len], compilation_options, encoding, syntax, &err_info);
  11. if (r != ONIG_NORMAL) {
  12. OnigUChar err_msg[ONIG_MAX_ERROR_MESSAGE_LEN];
  13. onig_error_code_to_str(err_msg, r, &err_info);
  14. // TODO: Consider this...
  15. throw_exception(gc_new<String>("Regular Expression Error: %", gc_new<String>((const char*)err_msg)));
  16. }
  17. }
  18. RegEx::~RegEx() {
  19. onig_free(m_Handle);
  20. }
  21. Ptr<Array> RegEx::search(const Ptr<String>& str, OnigOptionType options) {
  22. HandleScope();
  23. Handle<RegEx> THIS = this;
  24. Handle<String> string = str;
  25. Handle<Array> results = gc_new<Array>();
  26. const OnigUChar* string_start = (const OnigUChar*)string->c_str();
  27. size_t len = string->length();
  28. const OnigUChar* string_end = &string_start[len];
  29. const OnigUChar* search_start = string_start;
  30. const OnigUChar* search_range = string_end;
  31. OnigRegion* region = onig_region_new();
  32. int result = 0;
  33. while (result >= 0)
  34. {
  35. OnigOptionType extra_options = result == 0 ? 0 : ONIG_OPTION_NOTBOL;
  36. result = onig_search(THIS->m_Handle, string_start, string_end, &search_start[result], search_range, region, options | extra_options);
  37. if (result >= 0)
  38. {
  39. for (int i = 0; i < region->num_regs; ++i) {
  40. size_t match_len = region->end[i] - region->beg[i];
  41. char match_string[match_len+1];
  42. memcpy(match_string, &string_start[region->beg[i]], match_len);
  43. match_string[match_len] = '\0';
  44. results->push(gc_new<String>(match_string));
  45. result = result > region->end[i] ? result : region->end[i];
  46. }
  47. }
  48. }
  49. onig_region_free(region, 1);
  50. return results;
  51. }
  52. int RegEx::number_of_names() const {
  53. return onig_number_of_names(m_Handle);
  54. }
  55. static int add_names_to_array(const OnigUChar* start, const OnigUChar* end, int num_groups, int*, regex_t*, void* arg) {
  56. HandleScope _;
  57. Handle<Array>* parray = (Handle<Array>*)arg;
  58. size_t len = end-start;
  59. char* cstr = new char[len+1];
  60. cstr[len] = '\0';
  61. Handle<String> string = gc_new<String>(cstr);
  62. delete[] cstr;
  63. (*parray)->push(string);
  64. return 0;
  65. }
  66. Ptr<Array> RegEx::names() {
  67. HandleScope _;
  68. Handle<RegEx> THIS = this;
  69. Handle<Array> array = gc_new<Array>();
  70. array->preallocate(number_of_names());
  71. onig_foreach_name(THIS->m_Handle, add_names_to_array, &array);
  72. return array;
  73. }
  74. int RegEx::number_of_groups() const {
  75. return onig_number_of_captures(m_Handle);
  76. }
  77. /// RegExMatch --------------------------
  78. Ptr<String> RegExMatch::get_match(int group) const {
  79. if (!m_Matches)
  80. return NULL;
  81. ASSERT((size_t)group <= m_Matches->length());
  82. VALUE str = (*m_Matches)[group-1];
  83. Ptr<String> s = object_cast<String>(str);
  84. ASSERT(s);
  85. return s;
  86. }
  87. void RegExMatch::set_match(int group, const Ptr<String>& str) {
  88. HandleScope _;
  89. Handle<RegExMatch> THIS = this;
  90. if (!THIS->m_Matches) {
  91. THIS->m_Matches = gc_new<Array>();
  92. THIS->m_Matches->preallocate(THIS->m_RegEx->number_of_groups());
  93. }
  94. THIS->m_Matches->set_by_index(group-1, str);
  95. }
  96. Ptr<Array> RegExMatch::get_matches(const Ptr<String>& group_name) {
  97. HandleScope _;
  98. Handle<RegExMatch> THIS = this;
  99. const UChar* start = (const OnigUChar*)group_name->c_str();
  100. size_t len = group_name->length();
  101. const UChar* end = &start[len];
  102. int* group_numbers;
  103. int r = onig_name_to_group_numbers(THIS->m_RegEx->m_Handle, start, end, &group_numbers);
  104. if (r <= 0)
  105. return NULL;
  106. Handle<Array> array = gc_new<Array>();
  107. array->preallocate(r);
  108. for (int i = 0; i < r; ++i) {
  109. array->push(get_match(group_numbers[i]));
  110. }
  111. return array;
  112. }
  113. }