Skip to content

Commit

Permalink
(feat) pcre2_config
Browse files Browse the repository at this point in the history
  • Loading branch information
alexey-pelykh committed Jun 22, 2024
1 parent 1dac202 commit ef165db
Show file tree
Hide file tree
Showing 6 changed files with 520 additions and 5 deletions.
2 changes: 1 addition & 1 deletion PCRE2_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Here's the list of the PCRE2 API functions exposed via `org.pcre4j.api.IPcre2` a
|| [pcre2_compile_context_copy](https://www.pcre.org/current/doc/html/pcre2_compile_context_copy.html) | Copy a compile context |
|| [pcre2_compile_context_create](https://www.pcre.org/current/doc/html/pcre2_compile_context_create.html) | Create a compile context |
|| [pcre2_compile_context_free](https://www.pcre.org/current/doc/html/pcre2_compile_context_free.html) | Free a compile context |
| | [pcre2_config](https://www.pcre.org/current/doc/html/pcre2_config.html) | Show build-time configuration options |
| | [pcre2_config](https://www.pcre.org/current/doc/html/pcre2_config.html) | Show build-time configuration options |
| | [pcre2_convert_context_copy](https://www.pcre.org/current/doc/html/pcre2_convert_context_copy.html) | Copy a convert context |
| | [pcre2_convert_context_create](https://www.pcre.org/current/doc/html/pcre2_convert_context_create.html) | Create a convert context |
| | [pcre2_convert_context_free](https://www.pcre.org/current/doc/html/pcre2_convert_context_free.html) | Free a convert context |
Expand Down
42 changes: 42 additions & 0 deletions api/src/main/java/org/pcre4j/api/IPcre2.java
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,48 @@ public interface IPcre2 {
public static final int CONFIG_COMPILED_WIDTHS = 14;
public static final int CONFIG_TABLES_LENGTH = 15;

/**
* Get the amount of memory needed to store the information referred to by {@param what} about the optional features
* of the PCRE2 library.
* <p>
* Suitable for any information except:
* {@link #CONFIG_JITTARGET} Target architecture for the JIT compiler
* {@link #CONFIG_UNICODE_VERSION} Unicode version
* {@link #CONFIG_VERSION} PCRE2 version
*
* @param what the information to query the memory requirements for
* @return the amount of memory needed to store the information referred to by {@param what}.
*/
public int config(int what);

/**
* Get the information referred to by {@param what} about the optional features of the PCRE2 library.
* <p>
* Suitable for any information except:
* {@link #CONFIG_JITTARGET} Target architecture for the JIT compiler
* {@link #CONFIG_UNICODE_VERSION} Unicode version
* {@link #CONFIG_VERSION} PCRE2 version
*
* @param what the information to query
* @param where the array to store the information
* @return Non-negative value on success, otherwise a negative error code.
*/
public int config(int what, int[] where);

/**
* Get the information referred to by {@param what} about the optional features of the PCRE2 library.
* <p>
* Suitable only for the following information:
* {@link #CONFIG_JITTARGET} Target architecture for the JIT compiler
* {@link #CONFIG_UNICODE_VERSION} Unicode version
* {@link #CONFIG_VERSION} PCRE2 version
*
* @param what the information to query
* @param where a buffer to store the information
* @return Non-negative value on success, otherwise a negative error code.
*/
public int config(int what, ByteBuffer where);

/**
* Create a new general context.
*
Expand Down
81 changes: 81 additions & 0 deletions ffm/src/main/java/org/pcre4j/ffm/Pcre2.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class Pcre2 implements IPcre2 {
private static final Linker LINKER = Linker.nativeLinker();
private static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup();

private final MethodHandle pcre2_config;

private final MethodHandle pcre2_general_context_create;
private final MethodHandle pcre2_general_context_copy;
private final MethodHandle pcre2_general_context_free;
Expand Down Expand Up @@ -76,6 +78,14 @@ public Pcre2(String library, String suffix) {
System.loadLibrary(library);
}

pcre2_config = LINKER.downcallHandle(
SYMBOL_LOOKUP.find("pcre2_config" + suffix).orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_INT, // int
ValueLayout.JAVA_INT, // int
ValueLayout.ADDRESS // void*
)
);

pcre2_general_context_create = LINKER.downcallHandle(
SYMBOL_LOOKUP.find("pcre2_general_context_create" + suffix).orElseThrow(),
FunctionDescriptor.of(ValueLayout.ADDRESS, // pcre2_general_context*
Expand Down Expand Up @@ -229,6 +239,66 @@ public Pcre2(String library, String suffix) {
);
}

@Override
public int config(int what) {
try (var arena = Arena.ofConfined()) {
final var pWhat = MemorySegment.ofAddress(0);

return (int) pcre2_config.invokeExact(
what,
pWhat
);
} catch (Throwable e) {
throw new RuntimeException(e);

Check warning on line 252 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L251-L252

Added lines #L251 - L252 were not covered by tests
}
}

@Override
public int config(int what, int[] where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");

Check warning on line 259 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L259

Added line #L259 was not covered by tests
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");

Check warning on line 262 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L262

Added line #L262 was not covered by tests
}

try (var arena = Arena.ofConfined()) {
final var pWhere = arena.allocateArray(ValueLayout.JAVA_INT, 1);

final var result = (int) pcre2_config.invokeExact(
what,
pWhere
);

where[0] = pWhere.get(ValueLayout.JAVA_INT, 0);

return result;
} catch (Throwable e) {
throw new RuntimeException(e);

Check warning on line 277 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L276-L277

Added lines #L276 - L277 were not covered by tests
}
}

@Override
public int config(int what, ByteBuffer where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");

Check warning on line 284 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L284

Added line #L284 was not covered by tests
}
if (!where.isDirect()) {
throw new IllegalArgumentException("where must be direct");

Check warning on line 287 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L287

Added line #L287 was not covered by tests
}

try (var arena = Arena.ofConfined()) {
final var pWhere = MemorySegment.ofBuffer(where);

return (int) pcre2_config.invokeExact(
what,
pWhere
);
} catch (Throwable e) {
throw new RuntimeException(e);

Check warning on line 298 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L297-L298

Added lines #L297 - L298 were not covered by tests
}
}

@Override
public long generalContextCreate(long privateMalloc, long privateFree, long memoryData) {
try (var arena = Arena.ofConfined()) {
Expand Down Expand Up @@ -322,6 +392,9 @@ public void compileContextFree(long ccontext) {

@Override
public long compile(String pattern, int options, int[] errorcode, long[] erroroffset, long ccontext) {
if (pattern == null) {
throw new IllegalArgumentException("pattern must not be null");

Check warning on line 396 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L396

Added line #L396 was not covered by tests
}
if (errorcode == null || errorcode.length < 1) {
throw new IllegalArgumentException("errorcode must be an array of length 1");
}
Expand Down Expand Up @@ -576,6 +649,10 @@ public void matchContextFree(long mcontext) {

@Override
public int match(long code, String subject, int startoffset, int options, long matchData, long mcontext) {
if (subject == null) {
throw new IllegalArgumentException("subject must not be null");

Check warning on line 653 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L653

Added line #L653 was not covered by tests
}

try (var arena = Arena.ofConfined()) {
final var pCode = MemorySegment.ofAddress(code);
final var pszSubject = arena.allocateUtf8String(subject);
Expand Down Expand Up @@ -613,6 +690,10 @@ public int getOvectorCount(long matchData) {

@Override
public void getOvector(long matchData, long[] ovector) {
if (ovector == null) {
throw new IllegalArgumentException("ovector must not be null");

Check warning on line 694 in ffm/src/main/java/org/pcre4j/ffm/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

ffm/src/main/java/org/pcre4j/ffm/Pcre2.java#L694

Added line #L694 was not covered by tests
}

try (var arena = Arena.ofConfined()) {
final var pMatchData = MemorySegment.ofAddress(matchData);

Expand Down
78 changes: 78 additions & 0 deletions jna/src/main/java/org/pcre4j/jna/Pcre2.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,39 @@ public Pcre2(String libraryName, String suffix) {
);
}

@Override
public int config(int what) {
return library.pcre2_config(what, Pointer.NULL);
}

@Override
public int config(int what, int[] where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");

Check warning on line 71 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L71

Added line #L71 was not covered by tests
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");

Check warning on line 74 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L74

Added line #L74 was not covered by tests
}

IntByReference whereRef = new IntByReference();
int result = library.pcre2_config(what, whereRef.getPointer());
where[0] = whereRef.getValue();
return result;
}

@Override
public int config(int what, ByteBuffer where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");

Check warning on line 86 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L86

Added line #L86 was not covered by tests
}
if (!where.isDirect()) {
throw new IllegalArgumentException("where must be a direct buffer");

Check warning on line 89 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L89

Added line #L89 was not covered by tests
}

Pointer pWhere = Native.getDirectBufferPointer(where);
return library.pcre2_config(what, pWhere);
}

@Override
public long generalContextCreate(long privateMalloc, long privateFree, long memoryData) {
Pointer gContext = library.pcre2_general_context_create(
Expand Down Expand Up @@ -100,6 +133,16 @@ public void compileContextFree(long ccontext) {

@Override
public long compile(String pattern, int options, int[] errorcode, long[] erroroffset, long ccontext) {
if (pattern == null) {
throw new IllegalArgumentException("pattern must not be null");

Check warning on line 137 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L137

Added line #L137 was not covered by tests
}
if (errorcode == null || errorcode.length < 1) {
throw new IllegalArgumentException("errorcode must be an array of length 1");

Check warning on line 140 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L140

Added line #L140 was not covered by tests
}
if (erroroffset == null || erroroffset.length < 1) {
throw new IllegalArgumentException("erroroffset must be an array of length 1");

Check warning on line 143 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L143

Added line #L143 was not covered by tests
}

IntByReference errorCodeRef = new IntByReference();
LongByReference errorOffsetRef = new LongByReference();

Expand Down Expand Up @@ -127,6 +170,13 @@ public void codeFree(long code) {

@Override
public int getErrorMessage(int errorcode, ByteBuffer buffer) {
if (buffer == null) {
throw new IllegalArgumentException("buffer must not be null");

Check warning on line 174 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L174

Added line #L174 was not covered by tests
}
if (!buffer.isDirect()) {
throw new IllegalArgumentException("buffer must be direct");

Check warning on line 177 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L177

Added line #L177 was not covered by tests
}

Pointer pszBuffer = Native.getDirectBufferPointer(buffer);
return library.pcre2_get_error_message(errorcode, pszBuffer, buffer.capacity());
}
Expand All @@ -138,6 +188,13 @@ public int patternInfo(long code, int what) {

@Override
public int patternInfo(long code, int what, int[] where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");

Check warning on line 192 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L192

Added line #L192 was not covered by tests
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");

Check warning on line 195 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L195

Added line #L195 was not covered by tests
}

IntByReference whereRef = new IntByReference();
int result = library.pcre2_pattern_info(new Pointer(code), what, whereRef.getPointer());
where[0] = whereRef.getValue();
Expand All @@ -146,6 +203,13 @@ public int patternInfo(long code, int what, int[] where) {

@Override
public int patternInfo(long code, int what, long[] where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");

Check warning on line 207 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L207

Added line #L207 was not covered by tests
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");

Check warning on line 210 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L210

Added line #L210 was not covered by tests
}

LongByReference whereRef = new LongByReference();
int result = library.pcre2_pattern_info(new Pointer(code), what, whereRef.getPointer());
where[0] = whereRef.getValue();
Expand All @@ -154,6 +218,10 @@ public int patternInfo(long code, int what, long[] where) {

@Override
public int patternInfo(long code, int what, ByteBuffer where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");

Check warning on line 222 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L222

Added line #L222 was not covered by tests
}

PointerByReference whereRef = new PointerByReference();
int result = library.pcre2_pattern_info(new Pointer(code), what, whereRef.getPointer());
where.put(whereRef.getValue().getByteArray(0, where.capacity()));
Expand Down Expand Up @@ -196,6 +264,10 @@ public void matchContextFree(long mcontext) {

@Override
public int match(long code, String subject, int startoffset, int options, long matchData, long mcontext) {
if (subject == null) {
throw new IllegalArgumentException("subject must not be null");

Check warning on line 268 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L268

Added line #L268 was not covered by tests
}

final var pszSubject = subject.getBytes(StandardCharsets.UTF_8);

return library.pcre2_match(
Expand All @@ -216,11 +288,17 @@ public int getOvectorCount(long matchData) {

@Override
public void getOvector(long matchData, long[] ovector) {
if (ovector == null) {
throw new IllegalArgumentException("ovector must not be null");

Check warning on line 292 in jna/src/main/java/org/pcre4j/jna/Pcre2.java

View check run for this annotation

Codecov / codecov/patch

jna/src/main/java/org/pcre4j/jna/Pcre2.java#L292

Added line #L292 was not covered by tests
}

Pointer pOvector = library.pcre2_get_ovector_pointer(new Pointer(matchData));
pOvector.read(0, ovector, 0, ovector.length);
}

private interface Library extends com.sun.jna.Library {
int pcre2_config(int what, Pointer where);

Pointer pcre2_general_context_create(Pointer malloc, Pointer free, Pointer memoryData);

Pointer pcre2_general_context_copy(Pointer gcontext);
Expand Down
Loading

0 comments on commit ef165db

Please sign in to comment.