Implement OnigRegExp.getCaptureTree natively

This commit is contained in:
Corey Johnson & Nathan Sobo
2012-08-07 16:20:02 -07:00
parent 088b1a1398
commit 827b3e29d3
5 changed files with 46 additions and 49 deletions

View File

@@ -13,7 +13,7 @@ public:
NSString *sourceString = [NSString stringWithUTF8String:source->GetStringValue().ToString().c_str()];
m_regex = [[OnigRegexp compile:sourceString] retain];
}
~OnigRegexpUserData() {
[m_regex release];
}
@@ -22,64 +22,68 @@ public:
OnigResult *result = [m_regex search:stringFromCefV8Value(string) start:index->GetIntValue()];
if ([result count] == 0) return CefV8Value::CreateNull();
CefRefPtr<CefV8Value> resultArray = CefV8Value::CreateArray();
CefRefPtr<CefV8Value> indicesArray = CefV8Value::CreateArray();
for (int i = 0; i < [result count]; i++) {
resultArray->SetValue(i, CefV8Value::CreateString([[result stringAt:i] UTF8String]));
indicesArray->SetValue(i, CefV8Value::CreateInt([result locationAt:i]));
}
resultArray->SetValue("index", CefV8Value::CreateInt([result locationAt:0]), V8_PROPERTY_ATTRIBUTE_NONE);
resultArray->SetValue("indices", indicesArray, V8_PROPERTY_ATTRIBUTE_NONE);
return resultArray;
}
CefRefPtr<CefV8Value> GetCaptureTree(CefRefPtr<CefV8Value> string, CefRefPtr<CefV8Value> index) {
CefRefPtr<CefV8Value> GetCaptureTree(CefRefPtr<CefV8Value> string, CefRefPtr<CefV8Value> index) {
OnigResult *result = [m_regex search:stringFromCefV8Value(string) start:index->GetIntValue()];
if ([result count] == 0) return CefV8Value::CreateNull();
if ([result count] == 0) return CefV8Value::CreateNull();
return BuildCaptureTree(result);
}
CefRefPtr<CefV8Value> BuildCaptureTree(OnigResult *result) {
int currentIndex = 0;
return BuildCaptureTree(result, currentIndex);
int index = 0;
return BuildCaptureTree(result, index);
}
CefRefPtr<CefV8Value> BuildCaptureTree(OnigResult *result, int &currentIndex) {
int index = currentIndex++;
NSString *text = [result stringAt:index];
int startPosition = [result locationAt:index];
CefRefPtr<CefV8Value> BuildCaptureTree(OnigResult *result, int &index) {
int currentIndex = index++;
NSString *text = [result stringAt:currentIndex];
int startPosition = [result locationAt:currentIndex];
int endPosition = startPosition + [text length];
CefRefPtr<CefV8Value> childCaptures;
while (currentIndex < [result count] && [result locationAt:currentIndex] < endPosition) {
if ([result lengthAt:currentIndex] == 0) continue;
if (!childCaptures.get()) childCaptures = CefV8Value::CreateArray();
childCaptures->SetValue(childCaptures->GetArrayLength(), BuildCaptureTree(result));
while (index < [result count] && [result locationAt:index] < endPosition) {
if ([result lengthAt:index] == 0) {
index++;
}
else {
if (!childCaptures.get()) childCaptures = CefV8Value::CreateArray();
childCaptures->SetValue(childCaptures->GetArrayLength(), BuildCaptureTree(result, index));
}
}
CefRefPtr<CefV8Value> tree = CefV8Value::CreateObject(NULL, NULL);
tree->SetValue("index", CefV8Value::CreateInt(index), V8_PROPERTY_ATTRIBUTE_NONE);
tree->SetValue("index", CefV8Value::CreateInt(currentIndex), V8_PROPERTY_ATTRIBUTE_NONE);
tree->SetValue("text", CefV8Value::CreateString([text UTF8String]), V8_PROPERTY_ATTRIBUTE_NONE);
tree->SetValue("position", CefV8Value::CreateInt(startPosition), V8_PROPERTY_ATTRIBUTE_NONE);
if (childCaptures.get()) tree->SetValue("captures", childCaptures, V8_PROPERTY_ATTRIBUTE_NONE);
return tree;
}
CefRefPtr<CefV8Value> CaptureCount() {
return CefV8Value::CreateInt([m_regex captureCount]);
}
OnigRegexp *m_regex;
IMPLEMENT_REFCOUNTING(OnigRegexpUserData);
};
OnigRegexpExtension::OnigRegexpExtension() : CefV8Handler() {
OnigRegexpExtension::OnigRegexpExtension() : CefV8Handler() {
NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"src/stdlib/onig-reg-exp-extension.js"];
NSString *extensionCode = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
CefRegisterExtension("v8/oniguruma", [extensionCode UTF8String], this);
@@ -90,20 +94,31 @@ bool OnigRegexpExtension::Execute(const CefString& name,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) {
if (name == "buildOnigRegExp") {
if (name == "buildOnigRegExp") {
CefRefPtr<CefBase> userData = new OnigRegexpUserData(arguments[0]);
retval = CefV8Value::CreateObject(userData, NULL);
return true;
}
else if (name == "search") {
CefRefPtr<CefV8Value> string = arguments[0];
CefRefPtr<CefV8Value> index = arguments.size() > 1 ? arguments[1] : CefV8Value::CreateInt(0);
OnigRegexpUserData *userData = (OnigRegexpUserData *)object->GetUserData().get();
retval = userData->Search(string, index);
return true;
}
else if (name == "getCaptureTree") {
CefRefPtr<CefV8Value> string = arguments[0];
CefRefPtr<CefV8Value> index = arguments.size() > 1 ? arguments[1] : CefV8Value::CreateInt(0);
OnigRegexpUserData *userData = (OnigRegexpUserData *)object->GetUserData().get();
retval = userData->GetCaptureTree(string, index);
return true;
}
else if (name == "getCaptureCount") {
OnigRegexpUserData *userData = (OnigRegexpUserData *)object->GetUserData().get();
retval = userData->CaptureCount();
return true;
}
return true;
return false;
}

View File

@@ -40,5 +40,5 @@ describe "OnigRegExp", ->
it "returns undefined if there was no match", ->
regex = new OnigRegExp('x')
expect(regex.getCaptureTree('y')).toBeUndefined()
expect(regex.getCaptureTree('y')).toBeNull()

View File

@@ -7,7 +7,6 @@ fs = require 'fs'
_ = require 'underscore'
$ = require 'jquery'
{CoffeeScript} = require 'coffee-script'
require 'onig-reg-exp'
windowAdditions =
rootViewParentSelector: 'body'

View File

@@ -1,6 +1,7 @@
(function() {
native function buildOnigRegExp(source);
native function search(string, index);
native function getCaptureTree(source, index);
native function getCaptureCount();
function OnigRegExp(source) {
@@ -12,6 +13,7 @@
}
OnigRegExp.prototype.search = search;
OnigRegExp.prototype.getCaptureTree = getCaptureTree;
OnigRegExp.prototype.getCaptureCount = getCaptureCount;
this.OnigRegExp = OnigRegExp;

View File

@@ -1,19 +0,0 @@
OnigRegExp.prototype.getCaptureTree = (string, startPosition) ->
buildCaptureTree = (captures, startPositions, totalCaptures=captures.length) ->
index = totalCaptures - captures.length
text = captures.shift()
startPosition = startPositions.shift()
endPosition = startPosition + text.length
tree = { index, text, position: startPosition }
childCaptures = []
while startPositions[0] < endPosition
subtree = buildCaptureTree(captures, startPositions, totalCaptures)
childCaptures.push(subtree) if subtree.text.length
tree.captures = childCaptures if childCaptures.length
tree
if match = @search(string, startPosition)
buildCaptureTree(match, match.indices)