Skip to content

Commit

Permalink
Merge pull request lucee#496 from Yamaha32088/LDEV-1682
Browse files Browse the repository at this point in the history
fixes LDEV-1682
  • Loading branch information
micstriit authored May 24, 2018
2 parents 91f88eb + 6fb0f4e commit 10f3f1d
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 54 deletions.
17 changes: 13 additions & 4 deletions core/src/main/java/lucee/runtime/functions/string/REFind.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,26 @@
import org.apache.oro.text.regex.MalformedPatternException;

public final class REFind extends BIF {

public static Object call(PageContext pc , String regExpr, String str) throws ExpressionException {
return call(pc,regExpr,str,1,false);
}

public static Object call(PageContext pc , String regExpr, String str, double start) throws ExpressionException {
return call(pc,regExpr,str,start,false);
}

public static Object call(PageContext pc , String regExpr, String str, double start, boolean returnsubexpressions) throws ExpressionException {
return call(pc,regExpr,str,start,returnsubexpressions,"one");
}

public static Object call(PageContext pc , String regExpr, String str, double start, boolean returnsubexpressions, String scope) throws ExpressionException {
try {
if(returnsubexpressions)
return Perl5Util.find(regExpr,str,(int)start,true);
return new Double(Perl5Util.indexOf(regExpr,str,(int)start,true));
boolean isMatchAll = scope.equalsIgnoreCase("all");
if(returnsubexpressions) {
return Perl5Util.find(regExpr,str,(int)start,true,isMatchAll);
}
return Perl5Util.indexOf(regExpr,str,(int)start,true,isMatchAll);
} catch (MalformedPatternException e) {
throw new FunctionException(pc,"reFind",1,"regularExpression",e.getMessage());
}
Expand All @@ -59,4 +68,4 @@ public Object invoke(PageContext pc, Object[] args) throws PageException {

throw new FunctionException(pc, "REFind", 2, 4, args.length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,22 @@ public final class REFindNoCase extends BIF {
public static Object call(PageContext pc , String regExpr, String str) throws ExpressionException {
return call(pc,regExpr,str,1,false);
}

public static Object call(PageContext pc , String regExpr, String str, double start) throws ExpressionException {
return call(pc,regExpr,str,start,false);
}

public static Object call(PageContext pc , String regExpr, String str, double start, boolean returnsubexpressions) throws ExpressionException {
return call(pc,regExpr,str,start,returnsubexpressions,"one");
}

public static Object call(PageContext pc , String regExpr, String str, double start, boolean returnsubexpressions, String scope) throws ExpressionException {
try {
if(returnsubexpressions)
return Perl5Util.find(regExpr,str,(int)start,false);
return new Double(Perl5Util.indexOf(regExpr,str,(int)start,false));
boolean isMatchAll = scope.equalsIgnoreCase("all");
if(returnsubexpressions) {
return Perl5Util.find(regExpr,str,(int)start,false,isMatchAll);
}
return Perl5Util.indexOf(regExpr,str,(int)start,false,isMatchAll);
} catch (MalformedPatternException e) {
throw new FunctionException(pc,"reFindNoCase",1,"regularExpression",e.getMessage());
}
Expand All @@ -63,4 +71,4 @@ public Object invoke(PageContext pc, Object[] args) throws PageException {

throw new FunctionException(pc, "REFindNoCase", 2, 4, args.length);
}
}
}
97 changes: 66 additions & 31 deletions core/src/main/java/lucee/runtime/regex/Perl5Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public final class Perl5Util {
* @return position of the first occurence
* @throws MalformedPatternException
*/
public static int indexOf(String strPattern, String strInput, int offset, boolean caseSensitive) throws MalformedPatternException {
public static Object indexOf(String strPattern, String strInput, int offset, boolean caseSensitive, boolean matchAll) throws MalformedPatternException {
//Perl5Compiler compiler = new Perl5Compiler();
PatternMatcherInput input = new PatternMatcherInput(strInput);
Perl5Matcher matcher = new Perl5Matcher();
Expand All @@ -69,8 +69,20 @@ public static int indexOf(String strPattern, String strInput, int offset, boolea

if(offset <= strInput.length()) input.setCurrentOffset(offset - 1);

if(offset <= strInput.length() && matcher.contains(input, pattern)) {
return matcher.getMatch().beginOffset(0) + 1;
if(offset <= strInput.length()) {
Array matches = new ArrayImpl();
while(matcher.contains(input, pattern)) {
int match = matcher.getMatch().beginOffset(0) + 1;
if(!matchAll) {
return new Double(match);
}

matches.appendEL(match);
}

if(matches.size() != 0) {
return matches;
}
}
return 0;
}
Expand All @@ -86,50 +98,76 @@ public static int indexOf(String strPattern, String strInput, int offset, boolea
* @return
* @throws MalformedPatternException
*/
public static Struct find(String strPattern, String strInput, int offset, boolean caseSensitive) throws MalformedPatternException {

public static Object find(String strPattern, String strInput, int offset, boolean caseSensitive, boolean matchAll) throws MalformedPatternException {
Perl5Matcher matcher = new Perl5Matcher();
PatternMatcherInput input = new PatternMatcherInput(strInput);

Array matches = new ArrayImpl();

int compileOptions=caseSensitive ? 0 : Perl5Compiler.CASE_INSENSITIVE_MASK;
compileOptions+=Perl5Compiler.SINGLELINE_MASK;
if(offset < 1) offset = 1;

Pattern pattern = getPattern(strPattern,compileOptions);

Pattern pattern = getPattern(strPattern,compileOptions);


if(offset <= strInput.length()) input.setCurrentOffset(offset - 1);

if(offset <= strInput.length() && matcher.contains(input, pattern)) {
MatchResult result = matcher.getMatch();

int groupCount = result.groups();
Array posArray = new ArrayImpl();
Array lenArray = new ArrayImpl();
for(int i = 0; i < groupCount; i++) {
int off = result.beginOffset(i);
posArray.appendEL(Integer.valueOf(off + 1));
lenArray.appendEL(Integer.valueOf(result.endOffset(i) - off));
}
Struct struct = new StructImpl();
struct.setEL("pos", posArray);
struct.setEL("len", lenArray);
return struct;

if(offset <= strInput.length()) {
input.setCurrentOffset(offset - 1);

while(matcher.contains(input, pattern)) {
Struct matchStruct = getMatchStruct(matcher.getMatch());
if(!matchAll) {
return matchStruct;
}

matches.appendEL(matchStruct);
}

if(matches.size() != 0) {
return matches;
}
}

Array posArray = new ArrayImpl();
Array lenArray = new ArrayImpl();
Array matchArray = new ArrayImpl();
posArray.appendEL(Constants.INTEGER_0);
lenArray.appendEL(Constants.INTEGER_0);
matchArray.appendEL("");

Struct struct = new StructImpl();
struct.setEL("pos", posArray);
struct.setEL("len", lenArray);
struct.setEL("match", matchArray);

if(matchAll) {
matches.appendEL(struct);
return matches;
}

return struct;
}

public static Struct getMatchStruct(MatchResult result) {
int groupCount = result.groups();

Array posArray = new ArrayImpl();
Array lenArray = new ArrayImpl();
Array matchArray = new ArrayImpl();

for(int i = 0; i < groupCount; i++) {
int off = result.beginOffset(i);
posArray.appendEL(Integer.valueOf(off + 1));
lenArray.appendEL(Integer.valueOf(result.endOffset(i) - off));
matchArray.appendEL(result.toString());
}

Struct struct = new StructImpl();
struct.setEL("pos", posArray);
struct.setEL("len", lenArray);
struct.setEL("match", matchArray);

return struct;
}


public static Array match(String strPattern, String strInput, int offset, boolean caseSensitive) throws MalformedPatternException {

Expand Down Expand Up @@ -258,9 +296,6 @@ else if('\\'==c) {
}

public static void main(String[] args) throws MalformedPatternException {
find(
"<function[^>]*>.*?</function>",
"<function name=\"susi2\" some=\"1\">\n<argument name=\"susi\">\naaa</function>",
1,false);

}
}
40 changes: 26 additions & 14 deletions core/src/main/java/resource/fld/core-base.fld
Original file line number Diff line number Diff line change
Expand Up @@ -13495,28 +13495,34 @@ You can find a list of all available timezones in the Lucee administrator (Setti
<name>reg_expression</name>
<type>string</type>
<required>Yes</required>
<description>Regular expression for which to search. Case sensitive.</description>
</argument>
<description>Regular expression for which to search. Case sensitive.</description>
</argument>
<argument>
<name>string</name>
<type>string</type>
<required>Yes</required>
<description>String in which
<description>String in which
to search.</description>
</argument>
</argument>
<argument>
<name>start</name>
<type>number</type>
<required>No</required>
<default>1</default>
<description>A positive integer. Position in the string at which to start search. The default value is 1.</description>
</argument>
<description>A positive integer. Position in the string at which to start search. The default value is 1.</description>
</argument>
<argument>
<name>returnsubexpressions</name>
<type>boolean</type>
<required>No</required>
<description></description>
</argument>
</argument>
<argument>
<name>scope</name>
<type>string</type>
<required>No</required>
<description></description>
</argument>
<return>
<type>any</type>
</return>
Expand All @@ -13536,26 +13542,26 @@ You can find a list of all available timezones in the Lucee administrator (Setti
<type>string</type>
<required>Yes</required>
<description>Regular expression for which to search. Case-insensitive.</description>
</argument>
</argument>
<argument>
<name>string</name>
<type>string</type>
<required>Yes</required>
<description>String in which
<description>String in which
to search.</description>
</argument>
</argument>
<argument>
<name>start</name>
<type>number</type>
<required>No</required>
<default>1</default>
<description></description>
</argument>
<description></description>
</argument>
<argument>
<name>returnsubexpressions</name>
<type>boolean</type>
<required>No</required>
<description>True: if the regular expression is found, the first array
<description>True: if the regular expression is found, the first array
element contains the length and position, respectively,
of the first match.
If the regular expression contains parentheses that
Expand All @@ -13566,7 +13572,13 @@ You can find a list of all available timezones in the Lucee administrator (Setti
contain one element with the value 0.
False: the function returns the position in the string
where the match begins. Default.</description>
</argument>
</argument>
<argument>
<name>scope</name>
<type>string</type>
<required>No</required>
<description></description>
</argument>
<return>
<type>any</type>
</return>
Expand Down
2 changes: 1 addition & 1 deletion test/tickets/_LDEV1682.cfc → test/tickets/LDEV1682.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ component extends="org.lucee.cfml.test.LuceeTestCase"{

it(title="Checking REFind() returns struct with matching value", body = function( currentSpec ) {
var testString = "I'm testing RE expression {%1%} test Letter";
var result = refind("{%\d%}", testString, 1 , true);
var result = refind("{%\d%}", testString, 1 , true, "all");
expect(isArray(result)).toBe(true);
if(isArray(result)){
expect(structkeyList(result[1])).toBe("MATCH,LEN,POS");
Expand Down

0 comments on commit 10f3f1d

Please sign in to comment.