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 ef887ec commit 6c2e8c6
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);
}
}

@Override
public int config(int what, int[] where) {
if (where == null) {
throw new IllegalArgumentException("where must not be null");
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");
}

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);
}
}

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

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);
}
}

@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");
}
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");
}

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");
}

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");
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");
}

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");
}
if (!where.isDirect()) {
throw new IllegalArgumentException("where must be a direct buffer");
}

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");
}
if (errorcode == null || errorcode.length < 1) {
throw new IllegalArgumentException("errorcode must be an array of length 1");
}
if (erroroffset == null || erroroffset.length < 1) {
throw new IllegalArgumentException("erroroffset must be an array of length 1");
}

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");
}
if (!buffer.isDirect()) {
throw new IllegalArgumentException("buffer must be direct");
}

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");
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");
}

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");
}
if (where.length != 1) {
throw new IllegalArgumentException("where must be an array of length 1");
}

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");
}

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");
}

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");
}

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 6c2e8c6

Please sign in to comment.