@@ -1587,6 +1587,115 @@ lys_new_type(const struct ly_ctx *ctx, LY_DATA_TYPE basetype, const char *tpdf_n
15871587 return rc ;
15881588}
15891589
1590+ /**
1591+ * @brief Check that a compiled type can be reused and shared.
1592+ *
1593+ * @param[in] type_p Parsed type.
1594+ * @param[in] type_c Compiled type.
1595+ * @param[in] pattern_format Global pattern format.
1596+ * @return 1 if @p type_c can be shared;
1597+ * @return 0 otherwise.
1598+ */
1599+ static ly_bool
1600+ lys_compile_type_share_compiled (const struct lysp_type * type_p , const struct lysc_type * type_c , ly_bool pattern_format )
1601+ {
1602+ LYA_COUNT_T u ;
1603+ struct lysc_type_union * type_un ;
1604+ struct lysc_type_str * type_str = NULL ;
1605+
1606+ if (!type_c ) {
1607+ /* no compiled type to share */
1608+ return 0 ;
1609+ }
1610+
1611+ if (type_p && (type_p -> flags || type_p -> exts )) {
1612+ /* special type flags or extensions to be compiled */
1613+ return 0 ;
1614+ }
1615+
1616+ /* learn whether the type has a leafref, in which case it cannot be shared because it may resolve to a different
1617+ * real type for every instantiation */
1618+ if (type_c -> basetype == LY_TYPE_LEAFREF ) {
1619+ /* leafref type */
1620+ return 0 ;
1621+ } else if (type_c -> basetype == LY_TYPE_UNION ) {
1622+ /* union with a leafref */
1623+ type_un = (struct lysc_type_union * )type_c ;
1624+ LYA_FOR (type_un -> types , u ) {
1625+ if (type_un -> types [u ]-> basetype == LY_TYPE_LEAFREF ) {
1626+ return 0 ;
1627+ }
1628+ }
1629+ }
1630+
1631+ /* check for patterns and their format */
1632+ if (type_c -> basetype == LY_TYPE_STRING ) {
1633+ type_str = (struct lysc_type_str * )type_c ;
1634+
1635+ if (type_str -> patterns && (type_str -> patterns [0 ]-> format != pattern_format )) {
1636+ return 0 ;
1637+ }
1638+ } else if (type_c -> basetype == LY_TYPE_UNION ) {
1639+ type_un = (struct lysc_type_union * )type_c ;
1640+ LYA_FOR (type_un -> types , u ) {
1641+ if (type_un -> types [u ]-> basetype == LY_TYPE_STRING ) {
1642+ type_str = (struct lysc_type_str * )type_un -> types [u ];
1643+
1644+ if (type_str -> patterns && (type_str -> patterns [0 ]-> format != pattern_format )) {
1645+ return 0 ;
1646+ }
1647+ }
1648+ }
1649+ }
1650+
1651+ return 1 ;
1652+ }
1653+
1654+ /**
1655+ * @brief Find a specific parsed type in the typedef chain.
1656+ *
1657+ * @param[in] tpdf_chain Set with the typedef chain.
1658+ * @param[in] tpdf_chain_last Index of @p tpdf_chain not to cross in descending order.
1659+ * @param[in] with_enum Set if looking for the first type with enums.
1660+ * @param[in] with_bits Set if looking for the first type with bits.
1661+ * @param[in] compiled Set if looking for the parsed type of this compiled type.
1662+ * @return Found parsed type.
1663+ */
1664+ static const struct lysp_type *
1665+ lys_compile_type_find_parsed (const struct ly_set * tpdf_chain , uint32_t tpdf_chain_last , ly_bool with_enum , ly_bool with_bits ,
1666+ const struct lysc_type * compiled )
1667+ {
1668+ const struct lysp_type * parsed = NULL ;
1669+ const struct lys_type_item * tpdf_item ;
1670+ uint32_t i ;
1671+
1672+ assert (tpdf_chain -> count > tpdf_chain_last );
1673+ assert ((with_enum && !with_bits && !compiled ) || (!with_enum && with_bits && !compiled ) || (!with_enum && !with_bits && compiled ));
1674+
1675+ i = tpdf_chain -> count ;
1676+ do {
1677+ -- i ;
1678+ tpdf_item = tpdf_chain -> objs [i ];
1679+
1680+ if (with_enum && tpdf_item -> tpdf -> type .enums ) {
1681+ /* enums */
1682+ parsed = & tpdf_item -> tpdf -> type ;
1683+ } else if (with_bits && tpdf_item -> tpdf -> type .bits ) {
1684+ /* bits */
1685+ parsed = & tpdf_item -> tpdf -> type ;
1686+ } else if (compiled ) {
1687+ /* original type, must be the first */
1688+ parsed = & tpdf_item -> tpdf -> type ;
1689+ assert (!parsed -> compiled || (parsed -> compiled == compiled ));
1690+ assert (!compiled -> name || (compiled -> name == tpdf_item -> tpdf -> name ));
1691+ assert (!strcmp (lys_datatype2str (compiled -> basetype ), parsed -> name ));
1692+ }
1693+ } while (!parsed && (i > tpdf_chain_last ));
1694+
1695+ assert (parsed );
1696+ return parsed ;
1697+ }
1698+
15901699/**
15911700 * @brief The core of the lys_compile_type() - compile information about the given type (from typedef or leaf/leaf-list).
15921701 *
@@ -1624,6 +1733,7 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_
16241733 const struct lysp_type * base_type_p ;
16251734 struct lysc_prefix * prefixes ;
16261735 uint32_t i ;
1736+ ly_bool pattern_format , share_base ;
16271737
16281738 /* alloc and init */
16291739 rc = lys_new_type (ctx -> ctx , basetype , tpdfname , type );
@@ -1655,20 +1765,7 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_
16551765 (struct lysc_type_bitenum_item * * )& bits -> bits ), cleanup );
16561766 } else if (base ) {
16571767 /* recompile bits from the first superior type with bits */
1658- assert (tpdf_chain -> count > tpdf_chain_last );
1659- base_type_p = NULL ;
1660- i = tpdf_chain -> count ;
1661- do {
1662- -- i ;
1663- tpdf_item = tpdf_chain -> objs [i ];
1664-
1665- if (tpdf_item -> tpdf -> type .bits ) {
1666- base_type_p = & tpdf_item -> tpdf -> type ;
1667- break ;
1668- }
1669- } while (i > tpdf_chain_last );
1670- assert (base_type_p );
1671-
1768+ base_type_p = lys_compile_type_find_parsed (tpdf_chain , tpdf_chain_last , 0 , 1 , NULL );
16721769 LY_CHECK_GOTO (rc = lys_compile_type_enums (ctx , base_type_p -> bits , basetype , NULL ,
16731770 (struct lysc_type_bitenum_item * * )& bits -> bits ), cleanup );
16741771 } else {
@@ -1754,20 +1851,7 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_
17541851 base ? ((struct lysc_type_enum * )base )-> enums : NULL , & enumeration -> enums ), cleanup );
17551852 } else if (base ) {
17561853 /* recompile enums from the first superior type with enums */
1757- assert (tpdf_chain -> count > tpdf_chain_last );
1758- base_type_p = NULL ;
1759- i = tpdf_chain -> count ;
1760- do {
1761- -- i ;
1762- tpdf_item = tpdf_chain -> objs [i ];
1763-
1764- if (tpdf_item -> tpdf -> type .enums ) {
1765- base_type_p = & tpdf_item -> tpdf -> type ;
1766- break ;
1767- }
1768- } while (i > tpdf_chain_last );
1769- assert (base_type_p );
1770-
1854+ base_type_p = lys_compile_type_find_parsed (tpdf_chain , tpdf_chain_last , 1 , 0 , NULL );
17711855 LY_CHECK_GOTO (rc = lys_compile_type_enums (ctx , base_type_p -> enums , basetype , NULL , & enumeration -> enums ), cleanup );
17721856 } else {
17731857 /* type derived from enumerations built-in type must contain at least one enum */
@@ -1876,6 +1960,7 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_
18761960 assert (!prefixes [0 ].prefix );
18771961 prefixes [0 ].mod = ctx -> cur_mod ;
18781962 } else if (base ) {
1963+ /* make a copy */
18791964 LY_CHECK_GOTO (rc = lyxp_expr_dup (ctx -> ctx , ((struct lysc_type_leafref * )base )-> path , 0 , 0 , & lref -> path ), cleanup );
18801965 LY_CHECK_GOTO (rc = lyplg_type_prefix_data_dup (ctx -> ctx , LY_VALUE_SCHEMA_RESOLVED ,
18811966 ((struct lysc_type_leafref * )base )-> prefixes , (void * * )& lref -> prefixes ), cleanup );
@@ -1928,15 +2013,38 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_
19282013 goto cleanup ;
19292014 }
19302015 } else if (base ) {
1931- /* copy all the types */
2016+ /* copy all the types if possible */
19322017 const struct lysc_type_union * un_base = (struct lysc_type_union * )base ;
19332018 LYA_COUNT_T u ;
19342019
1935- LYA_PREALLOC (un -> types , LYA_COUNT (un_base -> types ), LOGMEM (ctx -> ctx ); rc = LY_EMEM ; goto cleanup );
2020+ pattern_format = lys_compile_type_patterns_has_oc_posix_ext (ctx -> pmod );
2021+ share_base = 1 ;
19362022 LYA_FOR (un_base -> types , u ) {
1937- un -> types [u ] = un_base -> types [u ];
1938- LY_ATOMIC_INC_BARRIER (un -> types [u ]-> refcount );
1939- LYA_INCREMENT (un -> types );
2023+ if (un_base -> types [u ]-> exts || !lys_compile_type_share_compiled (NULL , un_base -> types [u ], pattern_format )) {
2024+ /* cannot be shared */
2025+ share_base = 0 ;
2026+ break ;
2027+ }
2028+ }
2029+
2030+ if (share_base ) {
2031+ LYA_PREALLOC (un -> types , LYA_COUNT (un_base -> types ), LOGMEM (ctx -> ctx ); rc = LY_EMEM ; goto cleanup );
2032+ LYA_FOR (un_base -> types , u ) {
2033+ un -> types [u ] = un_base -> types [u ];
2034+ LY_ATOMIC_INC_BARRIER (un -> types [u ]-> refcount );
2035+ LYA_INCREMENT (un -> types );
2036+ }
2037+ } else {
2038+ /* free the prepared type */
2039+ lydict_remove (ctx -> ctx , (* type )-> name );
2040+ free (* type );
2041+ * type = NULL ;
2042+
2043+ /* recompile the union */
2044+ base_type_p = lys_compile_type_find_parsed (tpdf_chain , tpdf_chain_last , 0 , 0 , base );
2045+ rc = lys_compile_type (ctx , context_pnode , context_flags , context_name , base_type_p , type , NULL , NULL );
2046+ LY_CHECK_GOTO (rc , cleanup );
2047+ assert (* type );
19402048 }
19412049 } else {
19422050 /* type derived from union built-in type must contain at least one type */
@@ -1978,64 +2086,6 @@ lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_
19782086 return rc ;
19792087}
19802088
1981- /**
1982- * @brief Check that a compiled type can be reused and shared.
1983- *
1984- * @param[in] type_p Parsed type.
1985- * @param[in] type_c Compiled type.
1986- * @param[in] pattern_format Global pattern format.
1987- * @return 1 if @p type_c can be shared;
1988- * @return 0 otherwise.
1989- */
1990- static ly_bool
1991- lys_compile_type_share_compiled (const struct lysp_type * type_p , const struct lysc_type * type_c , ly_bool pattern_format )
1992- {
1993- LYA_COUNT_T u ;
1994- struct lysc_type_union * type_un ;
1995- struct lysc_type_str * type_str = NULL ;
1996-
1997- if (!type_c || type_p -> flags || type_p -> exts ) {
1998- /* no compiled type to share, special type flags, or extensions */
1999- return 0 ;
2000- }
2001-
2002- /* learn whether the type has a leafref, in which case it cannot be shared because it may resolve to a different
2003- * real type for every instantiation */
2004- if (type_c -> basetype == LY_TYPE_LEAFREF ) {
2005- /* leafref type */
2006- return 0 ;
2007- } else if (type_c -> basetype == LY_TYPE_UNION ) {
2008- /* union with a leafref */
2009- type_un = (struct lysc_type_union * )type_c ;
2010- LYA_FOR (type_un -> types , u ) {
2011- if (type_un -> types [u ]-> basetype == LY_TYPE_LEAFREF ) {
2012- return 0 ;
2013- }
2014- }
2015- }
2016-
2017- /* check for patterns and their format */
2018- if (type_c -> basetype == LY_TYPE_STRING ) {
2019- type_str = (struct lysc_type_str * )type_c ;
2020- } else if (type_c -> basetype == LY_TYPE_UNION ) {
2021- type_un = (struct lysc_type_union * )type_c ;
2022- LYA_FOR (type_un -> types , u ) {
2023- if (type_un -> types [u ]-> basetype == LY_TYPE_STRING ) {
2024- type_str = (struct lysc_type_str * )type_un -> types [u ];
2025- break ;
2026- }
2027- }
2028- }
2029- if (!type_str || !type_str -> patterns ) {
2030- return 1 ;
2031- }
2032-
2033- if (pattern_format != type_str -> patterns [0 ]-> format ) {
2034- return 0 ;
2035- }
2036- return 1 ;
2037- }
2038-
20392089LY_ERR
20402090lys_compile_type_find_tpdf (struct lysc_ctx * ctx , const struct lysp_node * context_pnode , uint16_t context_flags ,
20412091 const char * context_name , const struct lysp_type * type_p , const char * * units , struct lysp_qname * * dflt ,
@@ -2193,14 +2243,10 @@ lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t
21932243 ret = ly_set_add (& ctx -> tpdf_chain , tctx , 1 , NULL );
21942244 LY_CHECK_GOTO (ret , cleanup );
21952245
2196- if (lys_compile_type_share_compiled ( & tctx -> tpdf -> type , tctx -> tpdf -> type .compiled , pattern_format ) ) {
2246+ if (tctx -> tpdf -> type .compiled ) {
21972247 /* already compiled, reuse */
21982248 base = tctx -> tpdf -> type .compiled ;
21992249 continue ;
2200- } else if (tctx -> tpdf -> type .compiled ) {
2201- /* cannot reuse, replace the compiled type with our new compiled type */
2202- LY_ATOMIC_DEC_BARRIER (tctx -> tpdf -> type .compiled -> refcount );
2203- ((struct lysp_tpdf * )tctx -> tpdf )-> type .compiled = NULL ;
22042250 }
22052251
22062252 /* try to find loaded user type plugins */
0 commit comments