Merge branch 'upstream-llpkgc' into llpkgc-integration
# By llpkgc upstream * upstream-llpkgc: llpkgc 2024-07-18 (7958a1de)
This commit is contained in:
commit
4b1b35bad3
1
Utilities/cmllpkgc/.gitattributes
vendored
Normal file
1
Utilities/cmllpkgc/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* -whitespace
|
205
Utilities/cmllpkgc/llpkgc.c
Normal file
205
Utilities/cmllpkgc/llpkgc.c
Normal file
@ -0,0 +1,205 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "llpkgc.h"
|
||||
|
||||
#define CALLBACK_MAYBE(PARSER, NAME) \
|
||||
do { \
|
||||
const llpkgc_settings_t* settings; \
|
||||
settings = (const llpkgc_settings_t*) (PARSER)->settings; \
|
||||
if(settings == NULL || settings->NAME == NULL) { \
|
||||
err = 0; \
|
||||
break; \
|
||||
} \
|
||||
err = settings->NAME((PARSER)); \
|
||||
} while(0)
|
||||
|
||||
#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
|
||||
do { \
|
||||
const llpkgc_settings_t* settings; \
|
||||
settings = (const llpkgc_settings_t*) (PARSER)->settings; \
|
||||
if(settings == NULL || settings->NAME == NULL) { \
|
||||
err = 0; \
|
||||
break; \
|
||||
} \
|
||||
err = settings->NAME((PARSER), (START), (LEN)); \
|
||||
if(err == -1) { \
|
||||
err = PCE_USER; \
|
||||
llpkgc_set_error_reason((PARSER), "Span callback error in " #NAME); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
void llpkgc_init(llpkgc_t* parser, const llpkgc_settings_t* settings) {
|
||||
llpkgc__internal_init(parser);
|
||||
|
||||
parser->settings = (void*) settings;
|
||||
}
|
||||
|
||||
void llpkgc_reset(llpkgc_t* parser) {
|
||||
llpkgc_settings_t* settings = parser->settings;
|
||||
void* data = parser->data;
|
||||
|
||||
llpkgc__internal_init(parser);
|
||||
|
||||
parser->settings = settings;
|
||||
parser->data = data;
|
||||
}
|
||||
|
||||
void llpkgc_settings_init(llpkgc_settings_t* settings) {
|
||||
memset(settings, 0, sizeof(*settings));
|
||||
}
|
||||
|
||||
llpkgc_errno_t llpkgc_execute(llpkgc_t* parser, const char* data, size_t len) {
|
||||
return llpkgc__internal_execute(parser, data, data + len);
|
||||
}
|
||||
|
||||
llpkgc_errno_t llpkgc_finish(llpkgc_t* parser) {
|
||||
if(parser->error != 0)
|
||||
return parser->error;
|
||||
|
||||
int err;
|
||||
// ToDo: Better handling of user callback errors here
|
||||
if(parser->unfinished_ == 1) {
|
||||
parser->reason = "Invalid EOF state";
|
||||
parser->error = PCE_UNFINISHED;
|
||||
return PCE_UNFINISHED;
|
||||
} else if(parser->unfinished_ == 2) {
|
||||
CALLBACK_MAYBE(parser, on_value_literal_complete);
|
||||
if(err != PCE_OK) {
|
||||
parser->error = err;
|
||||
return err;
|
||||
}
|
||||
CALLBACK_MAYBE(parser, on_value_complete);
|
||||
if(err != PCE_OK) {
|
||||
parser->error = err;
|
||||
return err;
|
||||
}
|
||||
} else if(parser->unfinished_ == 3) {
|
||||
CALLBACK_MAYBE(parser, on_value_complete);
|
||||
if(err != PCE_OK) {
|
||||
parser->error = err;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
CALLBACK_MAYBE(parser, on_pkgc_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
void llpkgc_pause(llpkgc_t* parser) {
|
||||
if(parser->error != PCE_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = PCE_PAUSED;
|
||||
parser->reason = "Paused";
|
||||
}
|
||||
|
||||
void llpkgc_resume(llpkgc_t* parser) {
|
||||
if(parser->error != PCE_PAUSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
parser->error = 0;
|
||||
}
|
||||
|
||||
llpkgc_errno_t llpkgc_get_errno(const llpkgc_t* parser) {
|
||||
return parser->error;
|
||||
}
|
||||
|
||||
const char* llpkgc_get_error_reason(const llpkgc_t* parser) {
|
||||
return parser->reason;
|
||||
}
|
||||
|
||||
void llpkgc_set_error_reason(llpkgc_t* parser, const char* reason) {
|
||||
parser->reason = reason;
|
||||
}
|
||||
|
||||
const char* llpkgc_get_error_pos(const llpkgc_t* parser) {
|
||||
return parser->error_pos;
|
||||
}
|
||||
|
||||
const char* llpkgc_errno_name(llpkgc_errno_t err) {
|
||||
switch(err) {
|
||||
case PCE_OK:
|
||||
return "PCE_OK";
|
||||
case PCE_INTERNAL:
|
||||
return "PCE_INTERNAL";
|
||||
case PCE_PAUSED:
|
||||
return "PCE_PAUSED";
|
||||
case PCE_USER:
|
||||
return "PCE_USER";
|
||||
case PCE_UNFINISHED:
|
||||
return "PCE_UNFINISHED";
|
||||
}
|
||||
return "INVALID_ERRNO";
|
||||
}
|
||||
|
||||
int llpkgc__line_begin(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
s->unfinished_ = 1;
|
||||
CALLBACK_MAYBE(s, on_line_begin);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__key_span(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
SPAN_CALLBACK_MAYBE(s, on_key, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__keyword_complete(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
s->unfinished_ = 3;
|
||||
CALLBACK_MAYBE(s, on_keyword_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__variable_complete(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
s->unfinished_ = 3;
|
||||
CALLBACK_MAYBE(s, on_variable_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__vallit_span(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
if(s->escaped_) {
|
||||
--endp;
|
||||
s->escaped_ = 0;
|
||||
}
|
||||
s->unfinished_ = 2;
|
||||
SPAN_CALLBACK_MAYBE(s, on_value_literal, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__vallit_complete(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
s->unfinished_ = 3;
|
||||
CALLBACK_MAYBE(s, on_value_literal_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__valvar_span(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
s->unfinished_ = 1;
|
||||
SPAN_CALLBACK_MAYBE(s, on_value_variable, p, endp - p);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__valvar_complete(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
s->unfinished_ = 3;
|
||||
CALLBACK_MAYBE(s, on_value_variable_complete);
|
||||
return err;
|
||||
}
|
||||
|
||||
int llpkgc__value_complete(llpkgc_t* s, const char* p, const char* endp) {
|
||||
int err;
|
||||
s->unfinished_ = 0;
|
||||
CALLBACK_MAYBE(s, on_value_complete);
|
||||
return err;
|
||||
}
|
143
Utilities/cmllpkgc/llpkgc.h
Normal file
143
Utilities/cmllpkgc/llpkgc.h
Normal file
@ -0,0 +1,143 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef INCLUDE_LLPKGC_API_H_
|
||||
#define INCLUDE_LLPKGC_API_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
#include "llpkgc__internal.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define LLPKGC_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define LLPKGC_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
typedef llpkgc__internal_t llpkgc_t;
|
||||
typedef struct llpkgc_settings_s llpkgc_settings_t;
|
||||
|
||||
typedef int (*llpkgc_data_cb)(llpkgc_t*, const char* at, size_t length);
|
||||
typedef int (*llpkgc_cb)(llpkgc_t*);
|
||||
|
||||
struct llpkgc_settings_s {
|
||||
/* Possible return values 0, -1, PCE_USER */
|
||||
llpkgc_data_cb on_key;
|
||||
llpkgc_data_cb on_value_literal;
|
||||
llpkgc_data_cb on_value_variable;
|
||||
|
||||
/* Possible return values 0, -1, `PCE_PAUSED` */
|
||||
llpkgc_cb on_line_begin;
|
||||
llpkgc_cb on_keyword_complete;
|
||||
llpkgc_cb on_variable_complete;
|
||||
llpkgc_cb on_value_literal_complete;
|
||||
llpkgc_cb on_value_variable_complete;
|
||||
llpkgc_cb on_value_complete;
|
||||
llpkgc_cb on_pkgc_complete;
|
||||
};
|
||||
|
||||
enum llpkgc_errno {
|
||||
PCE_OK = 0,
|
||||
PCE_INTERNAL = 1,
|
||||
PCE_PAUSED = 2,
|
||||
PCE_USER = 3,
|
||||
PCE_UNFINISHED = 4,
|
||||
};
|
||||
typedef enum llpkgc_errno llpkgc_errno_t;
|
||||
|
||||
/* Initialize the parser with user settings.
|
||||
*
|
||||
* NOTE: lifetime of `settings` has to be at least the same as the lifetime of
|
||||
* the `parser` here. In practice, `settings` has to be either a static
|
||||
* variable or be allocated with `malloc`, `new`, etc.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
void llpkgc_init(llpkgc_t* parser, const llpkgc_settings_t* settings);
|
||||
|
||||
/* Reset an already initialized parser back to the start state, preserving the
|
||||
* existing callback settings and user data.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
void llpkgc_reset(llpkgc_t* parser);
|
||||
|
||||
/* Initialize the settings object */
|
||||
LLPKGC_EXPORT
|
||||
void llpkgc_settings_init(llpkgc_settings_t* settings);
|
||||
|
||||
/* Parse full or partial pc data, invoking user callbacks along the way.
|
||||
*
|
||||
* If any of `llpkgc_data_cb` returns errno not equal to `PCE_OK` - the parsing
|
||||
* interrupts, and such errno is returned from `llpkgc_execute()`. If
|
||||
* `PCE_PAUSED` was used as an errno, the execution can be resumed with
|
||||
* `llpkgc_resume()` call.
|
||||
*
|
||||
* NOTE: if this function ever returns a non-pause type error, it will continue
|
||||
* to return the same error upon each successive call up until `llpkgc_init()`
|
||||
* or `llpkgc_reset()` are called.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
llpkgc_errno_t llpkgc_execute(llpkgc_t* parser, const char* data, size_t len);
|
||||
|
||||
/* This method should be called when the input has reached EOF
|
||||
*
|
||||
* This method will invoke `on_pkgc_complete()` callback if the file was
|
||||
* terminated safely. Otherwise an error code will be returned.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
llpkgc_errno_t llpkgc_finish(llpkgc_t* parser);
|
||||
|
||||
/* Make further calls of `llpkgc_execute()` return `PCE_PAUSED` and set
|
||||
* appropriate error reason.
|
||||
*
|
||||
* Important: do not call this from user callbacks! User callbacks must return
|
||||
* `PCE_PAUSED` if pausing is required.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
void llpkgc_pause(llpkgc_t* parser);
|
||||
|
||||
/* Might be called to resume the execution after the pause in user's callback.
|
||||
* See `llpkgc_execute()` above for details.
|
||||
*
|
||||
* Call this only if `llpkgc_execute()` returns `PCE_PAUSED`.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
void llpkgc_resume(llpkgc_t* parser);
|
||||
|
||||
/* Returns the latest return error */
|
||||
LLPKGC_EXPORT
|
||||
llpkgc_errno_t llpkgc_get_errno(const llpkgc_t* parser);
|
||||
|
||||
/* Returns the verbal explanation of the latest returned error.
|
||||
*
|
||||
* Note: User callback should set error reason when returning the error. See
|
||||
* `llpkgc_set_error_reason()` for details.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
const char* llpkgc_get_error_reason(const llpkgc_t* parser);
|
||||
|
||||
/* Assign verbal description to the returned error. Must be called in user
|
||||
* callbacks right before returning the errno.
|
||||
*
|
||||
* Note: `PCE_USER` error code might be useful in user callbacks.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
void llpkgc_set_error_reason(llpkgc_t* parser, const char* reason);
|
||||
|
||||
/* Returns the pointer to the last parsed byte before the returned error. The
|
||||
* pointer is relative to the `data` argument of `llpkgc_execute()`.
|
||||
*
|
||||
* Note: this method might be useful for counting the number of parsed bytes.
|
||||
*/
|
||||
LLPKGC_EXPORT
|
||||
const char* llpkgc_get_error_pos(const llpkgc_t* parser);
|
||||
|
||||
/* Returns textual name of error code */
|
||||
LLPKGC_EXPORT
|
||||
const char* llpkgc_errno_name(llpkgc_errno_t err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* INCLUDE_LLPKGC_API_H_ */
|
1069
Utilities/cmllpkgc/llpkgc__internal.c
Normal file
1069
Utilities/cmllpkgc/llpkgc__internal.c
Normal file
File diff suppressed because it is too large
Load Diff
37
Utilities/cmllpkgc/llpkgc__internal.h
Normal file
37
Utilities/cmllpkgc/llpkgc__internal.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
/* This code was generated by llpkgc, do not edit it by hand
|
||||
See: https://gitlab.kitware.com/utils/llpkgc */
|
||||
|
||||
|
||||
#ifndef INCLUDE_LLPKGC__INTERNAL_H_
|
||||
#define INCLUDE_LLPKGC__INTERNAL_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct llpkgc__internal_s llpkgc__internal_t;
|
||||
struct llpkgc__internal_s {
|
||||
int32_t _index;
|
||||
void* _span_pos0;
|
||||
void* _span_cb0;
|
||||
int32_t error;
|
||||
const char* reason;
|
||||
const char* error_pos;
|
||||
void* data;
|
||||
void* _current;
|
||||
void* settings;
|
||||
uint8_t unfinished_;
|
||||
uint8_t escaped_;
|
||||
};
|
||||
|
||||
int llpkgc__internal_init(llpkgc__internal_t* s);
|
||||
int llpkgc__internal_execute(llpkgc__internal_t* s, const char* p, const char* endp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* INCLUDE_LLPKGC__INTERNAL_H_ */
|
Loading…
Reference in New Issue
Block a user