Skip to content

Commit 4a48d8e

Browse files
committed
ly common UPDATE pattern code handling functions
1 parent 05e73b4 commit 4a48d8e

File tree

4 files changed

+115
-62
lines changed

4 files changed

+115
-62
lines changed

src/ly_common.c

Lines changed: 99 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,34 @@ ly_version_proj_str(void)
100100
return LY_PROJ_VERSION;
101101
}
102102

103+
/**
104+
* @brief Callback for comparing two pattern records.
105+
*/
106+
static ly_bool
107+
ly_ctx_ht_pattern_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data))
108+
{
109+
struct ly_pattern_ht_rec *val1 = val1_p;
110+
struct ly_pattern_ht_rec *val2 = val2_p;
111+
112+
/* compare the pattern strings, if they match we can use the stored
113+
* serialized value to create the pcre2 code for the pattern */
114+
return !strcmp(val1->pattern, val2->pattern);
115+
}
116+
117+
/**
118+
* @brief Callback for freeing a pattern record.
119+
*/
120+
static void
121+
ly_ctx_ht_pattern_free_cb(void *val_p)
122+
{
123+
struct ly_pattern_ht_rec *val = val_p;
124+
125+
if (val->serialized_pattern) {
126+
/* free the pcode */
127+
pcre2_serialize_free(val->serialized_pattern);
128+
}
129+
}
130+
103131
/**
104132
* @brief Remove private context data from the sized array and free its contents.
105133
*
@@ -369,34 +397,6 @@ ly_ctx_data_dict_get(const struct ly_ctx *ctx)
369397
return shared_data ? shared_data->data_dict : NULL;
370398
}
371399

372-
/**
373-
* @brief Callback for comparing two pattern records.
374-
*/
375-
static ly_bool
376-
ly_ctx_ht_pattern_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data))
377-
{
378-
struct ly_pattern_ht_rec *val1 = val1_p;
379-
struct ly_pattern_ht_rec *val2 = val2_p;
380-
381-
/* compare the pattern strings, if they match we can use the stored
382-
* serialized value to create the pcre2 code for the pattern */
383-
return !strcmp(val1->pattern, val2->pattern);
384-
}
385-
386-
/**
387-
* @brief Callback for freeing a pattern record.
388-
*/
389-
static void
390-
ly_ctx_ht_pattern_free_cb(void *val_p)
391-
{
392-
struct ly_pattern_ht_rec *val = val_p;
393-
394-
if (val->serialized_pattern) {
395-
/* free the pcode */
396-
pcre2_serialize_free(val->serialized_pattern);
397-
}
398-
}
399-
400400
LY_ERR
401401
ly_ctx_data_add(const struct ly_ctx *ctx)
402402
{
@@ -454,7 +454,6 @@ ly_ctx_data_del(const struct ly_ctx *ctx)
454454
{
455455
struct ly_ctx_private_data *private_data;
456456
struct ly_ctx_shared_data *shared_data;
457-
LY_ARRAY_COUNT_TYPE idx;
458457

459458
/* WR LOCK */
460459
pthread_rwlock_wrlock(&ly_ctx_data_rwlock);
@@ -547,57 +546,101 @@ ly_pcode_deserialize(const uint8_t *serialized_code, pcre2_code **pcode)
547546
return LY_SUCCESS;
548547
}
549548

550-
LY_ERR
551-
ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode)
549+
/**
550+
* @brief Get a compiled PCRE2 pattern code from the context's pattern hash table.
551+
*
552+
* @param[in] ctx Context to get the pattern code from.
553+
* @param[in] pattern Pattern string to search for.
554+
* @param[in] pattern_ht Pattern hash table to search in.
555+
* @param[out] pcode Optional compiled pattern code, must be freed by the caller.
556+
* If NULL, the function only checks if the pattern exists in the hash table.
557+
* @return LY_SUCCESS on success, LY_ENOTFOUND if the pattern was not found,
558+
* other LY_ERR values on error.
559+
*/
560+
static LY_ERR
561+
_ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern,
562+
struct ly_ht *pattern_ht, pcre2_code **pcode)
552563
{
553-
LY_ERR ret = LY_SUCCESS;
554-
struct ly_ctx_shared_data *ctx_data;
564+
LY_ERR rc = LY_SUCCESS;
555565
uint32_t hash;
556566
struct ly_pattern_ht_rec rec = {0}, *found_rec = NULL;
557-
pcre2_code *pcode_tmp = NULL;
558-
uint8_t *serialized_pcode = NULL;
559-
560-
assert(ctx && pattern);
561567

562-
ctx_data = ly_ctx_shared_data_get(ctx);
563-
LY_CHECK_RET(!ctx_data, LY_EINT);
568+
assert(ctx && pattern && pattern_ht);
564569

565-
/* try to find the record */
570+
/* use the pattern as a key */
566571
rec.pattern = pattern;
567572
rec.serialized_pattern = NULL;
568573
hash = lyht_hash(pattern, strlen(pattern));
569574

570-
if (!lyht_find(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec)) {
575+
/* try to find the record */
576+
LY_CHECK_GOTO(rc = lyht_find(pattern_ht, &rec, hash, (void **)&found_rec), cleanup);
577+
578+
if (pcode) {
571579
/* found it, deserialize the pcode */
572-
LY_CHECK_GOTO(ret = ly_pcode_deserialize(found_rec->serialized_pattern, &pcode_tmp), cleanup);
573-
if (pcode) {
574-
*pcode = pcode_tmp;
575-
pcode_tmp = NULL;
576-
}
580+
LY_CHECK_GOTO(rc = ly_pcode_deserialize(found_rec->serialized_pattern, pcode), cleanup);
581+
}
582+
583+
cleanup:
584+
return rc;
585+
}
586+
587+
LY_ERR
588+
ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode)
589+
{
590+
LY_ERR rc = LY_SUCCESS;
591+
struct ly_ctx_shared_data *ctx_data;
592+
593+
ctx_data = ly_ctx_shared_data_get(ctx);
594+
LY_CHECK_RET(!ctx_data, LY_EINT);
595+
596+
rc = _ly_ctx_get_pattern_code(ctx, pattern, ctx_data->pattern_ht, pcode);
597+
if (rc) {
598+
LOGERR(ctx, rc, "Failed to get pattern code for \"%s\".", pattern);
599+
}
600+
601+
return rc;
602+
}
603+
604+
LY_ERR
605+
ly_ctx_compile_and_cache_pattern_code(const struct ly_ctx *ctx, const char *pattern)
606+
{
607+
LY_ERR rc = LY_SUCCESS;
608+
struct ly_ctx_shared_data *ctx_data;
609+
uint8_t *serialized_pcode = NULL;
610+
pcre2_code *pcode_tmp = NULL;
611+
struct ly_pattern_ht_rec rec = {0};
612+
uint32_t hash;
613+
614+
ctx_data = ly_ctx_shared_data_get(ctx);
615+
LY_CHECK_RET(!ctx_data, LY_EINT);
616+
617+
/* check for existing pattern code */
618+
rc = _ly_ctx_get_pattern_code(ctx, pattern, ctx_data->pattern_ht, NULL);
619+
LY_CHECK_GOTO(rc && (rc != LY_ENOTFOUND), cleanup);
620+
if (!rc) {
621+
/* pattern is already compiled and stored, nothing to do */
577622
goto cleanup;
578623
}
579624

580625
/* record not found, we need to compile the pattern and insert it */
581-
LY_CHECK_GOTO(ret = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup);
626+
LY_CHECK_GOTO(rc = lys_compile_type_pattern_check(ctx, pattern, &pcode_tmp), cleanup);
582627

583628
/* serialize the pcode */
584-
LY_CHECK_GOTO(ret = ly_pcode_serialize(pcode_tmp, &serialized_pcode), cleanup);
585-
rec.serialized_pattern = serialized_pcode;
629+
LY_CHECK_GOTO(rc = ly_pcode_serialize(pcode_tmp, &serialized_pcode), cleanup);
586630

587631
/* insert the record */
588-
LY_CHECK_GOTO(ret = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, (void **)&found_rec), cleanup);
632+
hash = lyht_hash(pattern, strlen(pattern));
633+
rec.pattern = pattern;
634+
rec.serialized_pattern = serialized_pcode;
635+
LY_CHECK_GOTO(rc = lyht_insert_no_check(ctx_data->pattern_ht, &rec, hash, NULL), cleanup);
589636

590-
if (pcode) {
591-
/* transfer pcode ownership to the caller */
592-
*pcode = pcode_tmp;
593-
pcode_tmp = NULL;
594-
}
637+
/* dont free the serialized pcode, it is now owned by the record in the hash table */
595638
serialized_pcode = NULL;
596639

597640
cleanup:
598641
pcre2_code_free(pcode_tmp);
599642
pcre2_serialize_free(serialized_pcode);
600-
return ret;
643+
return rc;
601644
}
602645

603646
void *

src/ly_common.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,15 +483,25 @@ void ly_ctx_ht_leafref_links_rec_free(void *val_p);
483483
struct lys_module *ly_ctx_get_module_implemented2(const struct ly_ctx *ctx, const char *name, size_t name_len);
484484

485485
/**
486-
* @brief Gets or creates a PCRE2 pattern code in the context's pattern hash table.
486+
* @brief Get a compiled PCRE2 pattern code from the context's pattern hash table.
487487
*
488-
* If the pattern is not found, it is compiled, serialized and cached in @p ctx .
488+
* @param[in] ctx Context to get the pattern code from.
489+
* @param[in] pattern Pattern string to search for.
490+
* @param[out] pcode Compiled pattern code.
491+
* @return LY_ERR value.
492+
*/
493+
LY_ERR ly_ctx_get_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode);
494+
495+
/**
496+
* @brief Compile a pattern string into a PCRE2 code and store it in the context's pattern hash table.
497+
*
498+
* If the pattern is already compiled and stored, it is not recompiled.
489499
*
490500
* @param[in] ctx Context to get or create the pattern code in.
491501
* @param[in] pattern Pattern string to search for or to compile and store.
492-
* @param[out] pcode Optional pointer to the pattern code, if not NULL, it will be set to the compiled pattern code.
502+
* @return LY_ERR value.
493503
*/
494-
LY_ERR ly_ctx_get_or_create_pattern_code(const struct ly_ctx *ctx, const char *pattern, pcre2_code **pcode);
504+
LY_ERR ly_ctx_compile_and_cache_pattern_code(const struct ly_ctx *ctx, const char *pattern);
495505

496506
/******************************************************************************
497507
* Dictionary

src/plugins_types.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ lyplg_type_validate_patterns(const struct ly_ctx *ctx, struct lysc_pattern **pat
536536

537537
LY_ARRAY_FOR(patterns, u) {
538538
/* get the compiled pattern */
539-
LY_CHECK_RET(ly_ctx_get_or_create_pattern_code(ctx, patterns[u]->expr, &pcode));
539+
LY_CHECK_RET(ly_ctx_get_pattern_code(ctx, patterns[u]->expr, &pcode));
540540

541541
/* match the pattern */
542542
r = ly_pattern_code_match(pcode, str, str_len, err);

src/schema_compile_node.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ lys_compile_type_patterns(struct lysc_ctx *ctx, const struct lysp_restr *pattern
13871387
++(*pattern)->refcount;
13881388

13891389
/* compile and insert the pattern into the context hash table, if it wasnt already compiled */
1390-
LY_CHECK_GOTO(ret = ly_ctx_get_or_create_pattern_code(ctx->ctx, &patterns_p[u].arg.str[1], NULL), done);
1390+
LY_CHECK_GOTO(ret = ly_ctx_compile_and_cache_pattern_code(ctx->ctx, &patterns_p[u].arg.str[1]), done);
13911391

13921392
if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) {
13931393
(*pattern)->inverted = 1;

0 commit comments

Comments
 (0)