1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
|
/*
* xmltree.h
*
* $Id$
*
* This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
* project.
*
* Copyright (C) 1998-2012 OpenLink Software
*
* This project is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; only version 2 of the License, dated June 1991.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _XMLTREE_H
#define _XMLTREE_H
#include "uname_const_decl.h"
#include "xpath.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "langfunc.h"
#include "xmlparser.h"
#ifdef __cplusplus
}
#endif
/*
#ifdef DEBUG
#define XPATH_DEBUG
#endif
*/
#define MAX_XML_LNAME_LENGTH 500 /* for local names, namespace prefixes and namespace URIs */
#define MAX_XML_QNAME_LENGTH (2*MAX_XML_LNAME_LENGTH + 1) /* for qualified names (that have semicolons) */
#define XP_TRANSLATE_HOST 1
void bx_out_value (caddr_t * qst, dk_session_t * out, db_buf_t val, wcharset_t *tgt_charset, wcharset_t *src_charset, int dks_esc_mode);
typedef struct xml_entity_s xml_entity_t;
typedef struct xml_tree_doc_s xml_tree_doc_t;
typedef struct xml_lazy_doc_s xml_lazy_doc_t;
typedef struct xper_doc_s xper_doc_t;
typedef struct xml_doc_s xml_doc_t;
#ifdef MALLOC_DEBUG
#define xe_copy(XE) dbg_xe_copy(__FILE__,__LINE__,(XE))
#define xe_cut(XE,QI) dbg_xe_cut(__FILE__,__LINE__,(XE),(QI))
#define xe_clone(XE,QI) dbg_xe_clone(__FILE__,__LINE__,(XE),(QI))
#define xe_attribute(XE,S,N,AVAL,ANAME) dbg_xe_attribute(__FILE__,__LINE__,(XE),(S),(N),(AVAL),(ANAME))
#define xe_string_value(XE,RET,DTP) dbg_xe_string_value(__FILE__,__LINE__,(XE),(RET),(DTP))
#endif
/* These bits control the handling of transitions from a subdocument to
an outer document.
'SIDEWAY' means that if 'up' happens then it must try find
a sibling of the original node and go down there, so it will be
moving left or right in the tree.
'MAY_TRANSIT' means that
if the result of 'up' is a root of generic entity (GE) is reached then
the reference node in a parent document should be made current.
This is because the XPath does not handle roots of GEs and top-level nodes of
GE are children of the parent of the reference entity node in the parent doc.
*/
#define XE_UP_SIDEWAY 0x01 /*!< Tells xe_up() to go down to the sibling if 'up' */
#define XE_UP_SIDEWAY_FWD 0x02 /*!< Tells xe_up() to move forward (not backward); has no meaning if XE_UP_SIDEWAY bit is not set */
#define XE_UP_SIDEWAY_WR 0x04 /*!< Tells xe_up() to use word-range optimization; has no meaning if XE_UP_SIDEWAY bit is not set */
#define XE_UP_MAY_TRANSIT_ONCE 0x40 /*!< Tells xe_up() that transition is allowed but not not a recursive one */
#define XE_UP_MAY_TRANSIT 0x80 /*!< Tells xe_up() that any number of transitions is allowed if GEreferences are top-level children of each other. */
/*! Table of virtual functions for XML entities */
typedef struct xe_class_s
{
/* An explicit #ifdef is used instead of usual
DBG_NAME(typ,name,(DBG_PARAMS ...))
style in order to bypass a bug in browsing info builder of Visual Studio. */
#ifdef MALLOC_DEBUG
xml_entity_t * (* dbg_xe_copy) (DBG_PARAMS xml_entity_t * xe);
/*! Cut the copy of given entity, turning it into a new document. */
xml_entity_t * (* dbg_xe_cut) (DBG_PARAMS xml_entity_t *xe, query_instance_t *qi);
/*! Clone given entity by copying the root document and placing the entity into the same logical path on the copy */
xml_entity_t * (* dbg_xe_clone) (DBG_PARAMS xml_entity_t *xe, query_instance_t *qi);
/*! Searches an entity for attributes whose names matches \c node, starting from \c start index */
int (* dbg_xe_attribute) (DBG_PARAMS xml_entity_t * xe, int start, XT * node, caddr_t * ret, caddr_t * name_ret);
/*! Returns the string value of an entity casted to \c dtp
according to section 5 'Data Model' of XML Path Language (XPath) Version 1.0 W3C Recommendation 16 November 1999 */
void (* dbg_xe_string_value) (DBG_PARAMS xml_entity_t * xe, caddr_t * ret, dtp_t dtp);
#else
xml_entity_t * (* xe_copy) (xml_entity_t * xe);
/*! Cut the copy of given entity, turning it into a new document. */
xml_entity_t * (* xe_cut) (xml_entity_t *xe, query_instance_t *qi);
/*! Clone given entity by copying the root document and placing the entity into the same logical path on the copy */
xml_entity_t * (* xe_clone) (xml_entity_t *xe, query_instance_t *qi);
/*! Searches an entity for attributes whose names matches \c node, starting from \c start index */
int (* xe_attribute) (xml_entity_t * xe, int start, XT * node, caddr_t * ret, caddr_t * name_ret);
/*! Returns the string value of an entity casted to \c dtp
according to section 5 'Data Model' of XML Path Language (XPath) Version 1.0 W3C Recommendation 16 November 1999 */
void (* xe_string_value) (xml_entity_t * xe, caddr_t * ret, dtp_t dtp);
#endif
int (* xe_string_value_is_nonempty) (xml_entity_t * xe);
/*! Tries to go up to parent and maybe through entity reference(s). */
int (* xe_up) (xml_entity_t * xe, XT * node, int up_flags);
/*! Tries to go down through entity reference(s). If down, tries to find first child of the root. If not down, tests given node. */
int (* xe_down) (xml_entity_t * xe, XT * node);
/*! Tries to go down through entity reference(s). If down, tries to find last child of the root. If not down, tests given node. */
int (* xe_down_rev) (xml_entity_t * xe, XT * node);
/*! Tries to find the first child of the current node that matches \c node_test. */
int (* xe_first_child) (xml_entity_t * xe, XT * node_test);
/*! Tries to find the last child of the current node that matches \c node_test. */
int (* xe_last_child) (xml_entity_t * xe, XT * node_test);
/*! Tries to get count of children of the current node.
When some child is a reference then xe_down is used and the number of child of the root of the referenced doc is added to the total. */
int (* xe_get_child_count_any) (xml_entity_t * xe);
/*! Tries to find the next sibling that matches \c node_test. */
int (* xe_next_sibling) (xml_entity_t * xe, XT * node_test);
/*! Tries to find the next sibling that matches \c node_test, skipping siblings with no text hits without processing.
'wr' stands for 'Word-Range optimization' */
int (* xe_next_sibling_wr) (xml_entity_t * xe, XT * node_test);
/*! Tries to find the previous sibling that matches \c node_test. */
int (* xe_prev_sibling) (xml_entity_t * xe, XT * node_test);
/*! Tries to find the previous sibling that matches \c node_test, skipping siblings with no text hits without processing.
'wr' stands for 'Word-Range optimization' */
int (* xe_prev_sibling_wr) (xml_entity_t * xe, XT * node_test);
/*! Returns string value of attribute with given name if it exists, otherwise returns NULL */
caddr_t (* xe_attrvalue) (xml_entity_t * xe, caddr_t qname);
/*! Returns string value of current attribute of attribute entity, can't return NULL, can GPF on non-attribute entity */
caddr_t (* xe_currattrvalue) (xml_entity_t * xe);
/*! Returns number of attributes with user data, (i.e. excluding xmlns:... attributes) */
size_t (* xe_data_attribute_count) (xml_entity_t * xe);
/*! Returns name of element if attribute or element node; special name if texts etc. */
caddr_t (* xe_element_name) (xml_entity_t * xe);
/*! Returns name of attribute if attribute node; name of element if element node; special name if texts etc. */
caddr_t (* xe_ent_name) (xml_entity_t * xe);
/*! Returns the string that is an XML text representation of the entity */
void (* xe_serialize) (xml_entity_t * xe, dk_session_t * ses);
/*! The destructor */
void (* xe_destroy) (xml_entity_t * xe);
/*! Fills \c start and \c end with word positions of the first and the last words in main text of the entity.
Refer to fields \c xewr_main_beg and \c xewr_main_end of struct xe_word_ranges_s. */
void (* xe_word_range) (xml_entity_t * xe, wpos_t * start, wpos_t * end);
/*! Fills \c start and \c this_end and \c last_end with word positions of the first and the last words in attributes of the entity.
\c this_end relates to the last attribute of the current entity whereas \c last_end relates to the last attribute in the whole subtree.
Refer to fields \c xewr_attr_beg, \c xewr_attr_this_end and \c xewr_attr_tree_end of struct xe_word_ranges_s. */
void (* xe_attr_word_range) (xml_entity_t * xe, wpos_t * start, wpos_t * this_end, wpos_t * last_end);
/* IvAn/XperUpdate/000904 xe_log_update added */
void (* xe_log_update) (xml_entity_t * xe, dk_session_t * log);
/*! Builds dk_set_t (<CODE>path[0]</CODE>) with the full path to given entity, in form
(NONCOUNTED root document pointer, addr of root's children, addr of root's children's children ...)
The first item of the set is the outermost document where entity is located and
every next item specifies the step to the depth of hierarchy.
For XML trees, the step is the index of children, for XPERs it is the position in BLOB.
\c path should be pointer to NULL dk_set, and the result will be made by pushing steps there,
from innermost level to root.
Please note that the pointer to the root will NOT be counted and the pointer may become dangling,
so the resulting path may be invalidated on any change of \c xe XML entity.
The function returns 1 if the path is valid, 0 if it is made based on obsolete entity in changed tree. */
int (* xe_get_logical_path) (xml_entity_t * xe, dk_set_t *path);
/*! Returns additional DTD, not associated with document but stored inside, e.g. partial DTD saved in XPER BLOB.
It is important that the refcounter of the returned value is not incremented on return.
If passed somewhere outside "auto" scope, refcounter should be incremented! */
struct dtd_s * (* xe_get_addon_dtd) (xml_entity_t * xe);
/*! Returns pointer to system identifier of given "generic entity reference" name */
const char * (* xe_get_sysid) (xml_entity_t *xe, const char *ref_name);
/*! Checks whether the name of the current element matches \c wname_node. For element entities only! */
int (* xe_element_name_test) (xml_entity_t *xe, XT *wname_node);
/*! Checks whether the name of the current node matches \c wname_node. */
int (* xe_ent_name_test) (xml_entity_t *xe, XT *wname_node);
/*! Checks whether the current node matches condition \c node. */
int (* xe_ent_node_test) (xml_entity_t *xe, XT *node);
/*! Finds if two given entities refers to the same fragment of the same document */
int (* xe_is_same_as) (const xml_entity_t *this_xe, const xml_entity_t *that_xe);
/*! Returns a node with given ID in the document of given entity or NULL. Can change the current entity. */
xml_entity_t * (* xe_deref_id) (xml_entity_t *xe, const char * idbegin, size_t idlength);
/*! Returns a node that is \c path away from the current entity or NULL if failed. Can change the current entity. */
xml_entity_t * (* xe_follow_path) (xml_entity_t *xe, ptrlong *path, size_t path_depth);
/*! Returns an xte_head with all attributes and element name cloned from 'this' entity */
caddr_t * (* xe_copy_to_xte_head) (xml_entity_t *xe);
/*! Returns an xte_tree with all children and attributes and element name cloned from 'this' entity */
caddr_t * (* xe_copy_to_xte_subtree) (xml_entity_t *xe);
/*! Returns a vector of xte_tree-s with all children of 'this' entity; generic references will be be extended. */
caddr_t ** (* xe_copy_to_xte_forest) (xml_entity_t *xe);
/*! Emulates an input of the current entity into \c parser */
void (* xe_emulate_input) (xml_entity_t *xe, struct vxml_parser_s *parser);
/*! Composes a new (or returns a cached) entity that is a root of a document that will become a subdocument of \c from_doc.
This is not always an external reference of the current entity, it can also be a document retrieved by xpf_document() */
struct xml_entity_s * (* xe_reference) (query_instance_t * qi, caddr_t base, caddr_t ref, xml_doc_t * from_doc, caddr_t *err_ret);
caddr_t (* xe_find_expanded_name_by_qname) (xml_entity_t *xe, const char *qname, int use_default);
dk_set_t (* xe_namespace_scope) (xml_entity_t *xe, int use_default);
} xe_class_t;
/*! Finds if two given entities have identical name, attributes and content */
int xe_are_equal (xml_entity_t *this_xe, xml_entity_t *that_xe);
/*! For an entity, returns a fingerprint of xe_are_equal.
If xe_are_equal(A,B) then xe_equal_fingerprint(A) == xe_equal_fingerprint(B) */
ptrlong xe_equal_fingerprint (xml_entity_t *xe);
/*! Finds if two given entities have identical name and attributes, but content may differ */
int xe_have_equal_heads (xml_entity_t *this_xe, xml_entity_t *that_xe);
/*! For an entity, returns a fingerprint of xe_are_equal_heads.
If xe_are_equal_heads(A,B) then xe_equal_heads_fingerprint(A) == xe_equal_heads_fingerprint(B) */
ptrlong xe_equal_heads_fingerprint (xml_entity_t *xe);
#ifdef MALLOC_DEBUG
extern xml_entity_t * dbg_xte_copy(DBG_PARAMS xml_entity_t * xe);
#define XE_IS_TREE(xe) (dbg_xte_copy == ((xml_entity_t *)(xe))->_->dbg_xe_copy)
extern xml_entity_t * dbg_xp_copy(DBG_PARAMS xml_entity_t * xe);
#define XE_IS_PERSISTENT(xe) (dbg_xp_copy == ((xml_entity_t *)(xe))->_->dbg_xe_copy)
#else
extern xml_entity_t * xte_copy(xml_entity_t * xe);
#define XE_IS_TREE(xe) (xte_copy == ((xml_entity_t *)(xe))->_->xe_copy)
extern xml_entity_t * xlazye_copy(xml_entity_t * xe);
#define XE_IS_LAZY(xe) (xlazye_copy == ((xml_entity_t *)(xe))->_->xe_copy)
extern xml_entity_t * xp_copy(xml_entity_t * xe);
#define XE_IS_PERSISTENT(xe) (xp_copy == ((xml_entity_t *)(xe))->_->xe_copy)
#endif
/* 'Base class' members that are common for all sorts of XML entities:
'_' is a pointer to table of virtual functions of the instance;
'xe_attr_name' is an expanded name of attribute for attribute nodes, NULL otherwise;
'xe_nth_attr' is an index of the attribute in the list of all attributes of an element (unused in non-attribute nodes);
'xd', 'xtd', 'xpd' is a pointer to document where the entity resides;
'xe_referer' is a pointer to parent document, NULL for entities in standalone and in top-level docs;
*/
#define XE_MEMBERS \
xe_class_t * _; \
caddr_t xe_attr_name; \
int xe_nth_attr; \
union { \
xml_doc_t * xd; \
xml_tree_doc_t * xtd; \
xml_lazy_doc_t * xlazyd; \
xper_doc_t * xpd; \
} xe_doc; \
xml_entity_t * xe_referer;
/*! Base class for xml_tree_ent_t, xper_entity_t, (map_entity_t in future) */
struct xml_entity_s
{
XE_MEMBERS
};
/* Set of parameters that configures the default serialization of an XML document. */
#define XOUT_MEMBERS \
caddr_t xout_method; \
caddr_t xout_version; \
caddr_t xout_encoding; \
int xout_encoding_meta; \
int xout_omit_xml_declaration; \
int xout_standalone; \
caddr_t xout_doctype_public; \
caddr_t xout_doctype_system; \
id_hash_t * xout_cdata_section_elements; \
int xout_indent; \
caddr_t xout_media_type; \
int xout_default_ns;
/* This is to track memory leaks and double free of XML documents.
See where the document is created and put an appropriate breakpoint */
#ifdef MALLOC_DEBUG
#define XD_DBG_MEMBERS \
const char * xd_dbg_file; \
int xd_dbg_line;
#else
#define XD_DBG_MEMBERS
#endif
/* 'Base class' members that are common for all sorts of XML documents:
'xd_type' is unused and I have no idea what was the initial intention, will kill it;
'xd_qi' is the creator of the document: neither XML document nor XML entity can survive the end of query or be passed from one query instance to other;
'xd_xqi' is the creator of the document if it is composed or loaded to memory by XPath or XQuery expression;
'xd_ref_count' is the reference counter of the document to free it when the last user disappears, users are entities in the document and members of 'xd_referenced_entities' or 'xd_cached_docs';
'xd_cost' is the cost of the reloading of the document; the more it costs the later it should be removed from cache;
'xd_weight' is the estimate of the size of the document in memory, in kbytes; note that this includes referenced entities.
'xd_top_doc' is a pointer to document that references to this one;
'xd_uri' is an uri where the document comes from (maybe a fake string), that is used as base uri for subdocuments;
'xd_referenced_entities' lists all loaded generic entities that are in this document, it may be non-NULL for top-level docs only;
'xd_cached_docs' lists all documents that were loaded by XPath processor when this document was a part of initial content, it may be non-NULL for top-level docs only;
'xd_dtd' is a DTD of the document or NULL;
'xd_id_dict' maps values of ID attributes to logical paths to nodes with these IDs, this is for id() XPath function and for XQuery pointer operator, this requires DTD data and IdCache=ENABLE, otherwise it will be NULL;
'xd_id_scan' is for incremental filling of 'xd_id_dict';
'xd_default_lh' is a default language of the document, this is for free-text indexing;
'xd_ns_2dict' is two-way dictionary that maps namespace prefixes to URIs and vice versa, this is to preserve prefixes used in input document when the in-memory document is serialized;
'xd_dom_lock_count' is number of locks set by users of XML entity to prevent mutation, e.g., no one can mutate a context document of XQuery is progress;
'xd_dom_mutation' is set if a document is patched by DOM mutation function like XMLReplace, this makes it invalid input for, e.g., XSLT compiler;
*/
#define XD_MEMBERS \
int xd_type; \
query_instance_t * xd_qi; \
xp_instance_t * xd_xqi; \
int xd_ref_count; \
struct xml_doc_s * xd_top_doc; \
caddr_t xd_uri; \
dk_set_t xd_referenced_entities; \
ptrlong xd_cost; \
ptrlong xd_weight; \
struct dtd_s *xd_dtd; \
id_hash_t *xd_id_dict; \
caddr_t xd_id_scan; \
struct lang_handler_s *xd_default_lh; \
xml_ns_2dict_t xd_ns_2dict; \
int xd_dom_lock_count; \
int xd_dom_mutation; \
int xd_namespaces_are_valid; \
XOUT_MEMBERS \
XD_DBG_MEMBERS
#define xe_ns_2dict_extend(tgt,src) \
xml_ns_2dict_extend ( \
&(((xml_entity_t *)(tgt))->xe_doc.xd->xd_ns_2dict), \
&(((xml_entity_t *)(src))->xe_doc.xd->xd_ns_2dict) )
#define XD_DOM_LOCK(xd) (xd)->xd_dom_lock_count++
#ifdef DEBUG
#define XD_DOM_RELEASE(xd) do { \
if (0 >= (xd)->xd_dom_lock_count) GPF_T; \
(xd)->xd_dom_lock_count--; \
} while (0)
#define XTD_DOM_MUTATE(xtd) do { \
if ((xtd)->xd_dom_lock_count) GPF_T; \
(xtd)->xd_dom_mutation++; \
if (NULL != xtd->xtd_wrs) \
{ \
id_hash_free (xtd->xtd_wrs); \
xtd->xtd_wrs = NULL; \
} \
} while (0)
#else
#define XD_DOM_RELEASE(xd) (xd)->xd_dom_lock_count--
#define XTD_DOM_MUTATE(xtd) do { \
(xtd)->xd_dom_mutation++; \
if (NULL != xtd->xtd_wrs) \
{ \
id_hash_free (xtd->xtd_wrs); \
xtd->xtd_wrs = NULL; \
} \
} while (0)
#endif
#define XD_ID_SCAN_COMPLETED ((caddr_t)1)
struct xml_doc_s
{
XD_MEMBERS
};
struct xe_word_ranges_s
{
wpos_t xewr_main_beg; /*!< Position of opening tag / of the first word of text */
wpos_t xewr_main_end; /*!< Position of closing tag / of the last word of text */
wpos_t xewr_attr_beg; /*!< Position of start mark of the first attribute of opening tag or counter's value */
wpos_t xewr_attr_this_end; /*!< Position of end mark of the last attribute of opening tag or counter's value */
wpos_t xewr_attr_tree_end; /*!< Position of end mark of the last attribute in whole subtree, i.e. counter's value */
};
typedef struct xe_word_ranges_s xe_word_ranges_t;
#define XTD_MEMBERS \
caddr_t * xtd_tree; \
id_hash_t * xtd_wrs; \
dk_set_t xtd_garbage_boxes; \
dk_set_t xtd_garbage_trees;
struct xml_tree_doc_s
{
XD_MEMBERS
XTD_MEMBERS
};
typedef struct xml_doc_cache_stdkey_s xml_doc_cache_stdkey_t;
#define XPER_MEMBERS \
blob_handle_t * xpd_bh; \
int xpd_state; \
id_hash_t * xpd_wrs;
struct xper_doc_s
{
XD_MEMBERS
XPER_MEMBERS
};
struct xml_lazy_doc_s
{
XD_MEMBERS
union {
struct { XTD_MEMBERS } xtd_stub;
struct { XPER_MEMBERS } xper_stub;
} stub;
dk_set_t xlazyd_entities;
xml_doc_cache_stdkey_t *xlazyd_cache_key;
};
typedef struct xte_bmk_s
{
caddr_t * xteb_current; /*!< An subtree that is selected at some level of nesting (i.e. a subtree of either a current entity or one of its ancestors */
int xteb_child_no; /*!< Index of the subtree referred by this->xteb_current in the list of children of its parent. */
} xte_bmk_t;
typedef struct xml_tree_ent_s
{
XE_MEMBERS
xte_bmk_t * xte_stack_buf; /*!< Buffer for stack of ancestors of current subtree (and for current subtree) */
xte_bmk_t * xte_stack_top; /*!< Pointer to the top element of the stack (i.e. to info about current subtree */
xte_bmk_t * xte_stack_max; /*!< Pointer to the past-the-buffer-end of the stack */
} xml_tree_ent_t;
typedef struct xml_lazy_ent_s
{
XE_MEMBERS
} xml_lazy_ent_t;
#define xte_current xte_stack_top->xteb_current
#define xte_child_no xte_stack_top->xteb_child_no
#define XTE_HAS_PARENT(xte) ((xte)->xte_stack_top > (xte)->xte_stack_buf)
#define XTE_HAS_2PARENTS(xte) (((xte)->xte_stack_top - (xte)->xte_stack_buf) >= 2)
#define XTE_PARENT_SUBTREE(xte) ((xte)->xte_stack_top[-1].xteb_current)
#define XTE_ADD_STACK_POS(xte) \
do { \
xte->xte_stack_top++; \
if (xte->xte_stack_top >= xte->xte_stack_max) \
{ size_t stack_elems = (xte->xte_stack_max - xte->xte_stack_buf); \
size_t stack_sz = stack_elems * sizeof (xte_bmk_t); \
xte_bmk_t * newstack = (xte_bmk_t *) dk_alloc (stack_sz * 2); \
memcpy (newstack, xte->xte_stack_buf, stack_sz); \
dk_free (xte->xte_stack_buf, stack_sz); \
xte->xte_stack_buf = newstack; \
xte->xte_stack_top = newstack + stack_elems; \
xte->xte_stack_max = newstack + (stack_elems * 2); \
} \
} while (0)
#ifdef DEBUG
#define XTE_SUB_STACK_POS(xte) do { if (xte->xte_stack_top-- <= xte->xte_stack_buf) GPF_T; } while (0)
#else
#define XTE_SUB_STACK_POS(xte) xte->xte_stack_top--
#endif
typedef int32 xperpos_t;
typedef struct xper_entity_s
{
XE_MEMBERS
char xper_type; /*!< type of this entity, one of XML_MKUP_XXX constants */
xperpos_t xper_pos; /*!< position of this entity in in the BLOB */
xperpos_t xper_first_child; /*!< position of the first child of the entity, or 0 */
caddr_t xper_name; /*!< qualified tag name or the text of comment */
xperpos_t xper_left; /*!< position of left neighbor, zero if there are no siblings at left, or 0 */
xperpos_t xper_right; /*!< position of right neighbor, zero if there are no siblings at right, or 0 */
xperpos_t xper_parent; /*!< position of parent, zero for root entity */
xperpos_t xper_end; /*!< position of end tag record, coupled with given start tag, 0 if not applicable */
wpos_t xper_start_word; /*!< index of start tag in whole list of document's words */
wpos_t xper_end_word; /*!< index of end tag in whole list of document's words */
xperpos_t xper_ns_pos; /*!< position of namespace */
caddr_t xper_text; /*!< textual data */
xperpos_t xper_next_item; /*!< position of the next item (text or entity) after the end of current one, 0 if not set. */
xperpos_t xper_cut_pos; /*!< value of \c xper_pos, where xper_cut_xper() was called last time */
struct xper_entity_s *xper_cut_ent; /*!< root entity for caching xper_cut_xper() result for \c xper_cut_pos position */
} xper_entity_t;
typedef struct xml_ent_un_s
{
/* union of all entity subclasses. Instances must be of this since
* an entity may transition between instances of different subclasses when traversing a reference */
union {
xml_tree_ent_t xte;
xml_lazy_ent_t xlazye;
xper_entity_t xper;
} _;
} xml_entity_un_t;
/* These sequences of bytes are placed in front of XPER or packed LONG XML blobs.
I hope that these sequences are senseless in any encoding. */
#define XPACK_PREFIX_LEN 4
#define XPER_PREFIX "\xE8\xED\xEC\001" /* Persistent XML. */
#define XPACK_PREFIX "\xE8\xED\xEC\003" /* Packed serialization of an XML tree. */
#define XE_PLAIN_TEXT 0
#define XE_PLAIN_TEXT_OR_SERIALIZED_VECTOR 1
#define XE_XPER_SERIALIZATION 2
#define XE_XPACK_SERIALIZATION 3
#define XE_ENTITY_READY 4
#define XPACK_START_DTD 0xFF /* Byte that indicates that next datum is DTD serialization as a single string */
/* More #define XPACK_START_xxx may appear here in the future. Their values _must_ be greater than 0xE0. */
extern void xpi_free (xp_instance_t * xqi);
#define XPI_OK 0
#define XPI_AT_END 100
#ifdef XPATH_DEBUG
extern void xqi_check_slots (xp_instance_t * xqi);
#else
#define xqi_check_slots(xqi)
#endif
#ifdef XPATH_DEBUG
extern ptrlong xqi_set_debug_start;
extern ptrlong xqi_set_odometer;
#define XP_SET(p, v) \
do { \
caddr_t *p_tmp = (caddr_t *)(p); \
caddr_t v_tmp = (caddr_t) v; \
if (p_tmp != (caddr_t *)(p)) \
GPF_T1 ("Side effect in first argument of XP_SET macro"); \
if (IS_BOX_POINTER (v_tmp) && (v_tmp == p_tmp[0])) \
GPF_T1 ("Self-assignment in XP_SET"); \
if (xqi_set_odometer >= 0) \
xqi_set_odometer++; \
if (xqi_set_odometer >= xqi_set_debug_start) \
dk_check_tree (p_tmp[0]); \
dk_free_tree (p_tmp[0]); \
if (xqi_set_odometer >= xqi_set_debug_start) \
dk_check_tree (v_tmp); \
p_tmp[0] = v_tmp; \
} while (0)
#else
#define XP_SET(p, v) \
do { \
dk_free_tree (((caddr_t *)(p))[0]); \
((caddr_t *)(p))[0] = v; \
} while (0)
#endif
#ifdef XPATH_DEBUG
#define XQI_SET(xqi, cell_idx_expn, val_expn) \
do { \
caddr_t __val = (val_expn); \
xqst_t __cell_idx = (cell_idx_expn); \
caddr_t *__cell = ((caddr_t*) (xqi))+__cell_idx; \
if (0 == __cell_idx) \
GPF_T1 ("Zero cell idx in XQI_SET"); \
if (xqi_set_odometer >= 0) \
xqi_set_odometer++; \
if (xqi_set_odometer >= xqi_set_debug_start) \
dk_check_tree (__cell[0]); \
if (IS_BOX_POINTER (__val) && (__val == __cell[0])) \
GPF_T1 ("Self-assignment in xqi_set()"); \
dk_free_tree (__cell[0]); \
if (xqi_set_odometer >= xqi_set_debug_start) \
dk_check_tree (__val); \
__cell[0] = __val; \
if (xqi_set_odometer >= xqi_set_debug_start) \
xqi_check_slots (xqi); \
} while(0)
#else
#define XQI_SET(xqi, cell_idx_expn, val_expn) \
do { \
caddr_t __val = (val_expn); \
xqst_t __cell_idx = (cell_idx_expn); \
caddr_t *__cell = ((caddr_t*) (xqi))+__cell_idx; \
dk_free_tree (__cell[0]); \
__cell[0] = __val; \
} while(0)
#endif
#define XQI_GET(xqi, cell_idx) \
(((caddr_t*)(xqi))[cell_idx])
#define XQI_SET_INT(xqi, cell_idx, val) \
( ((ptrlong *) (xqi))[cell_idx] = (val))
#define XQI_GET_INT(xqi, cell_idx) \
(((ptrlong*)(xqi))[cell_idx])
#define XQI_ADDRESS(xqi, cell_idx) \
(&(((caddr_t *)(xqi))[cell_idx]))
extern xp_instance_t * xp_eval (xp_query_t * xqr, xml_entity_t * ctx);
extern void xqi_eval (xp_instance_t * xqi, XT * tree, xml_entity_t * ctx_xe);
extern caddr_t xqi_value (xp_instance_t * xqi, XT * tree, dtp_t dtp);
extern caddr_t xqi_raw_value (xp_instance_t * xqi, XT * tree);
extern int xqi_next (xp_instance_t * xqi, XT * tree);
#define XI_INITIAL 1 /* the step's init is the context node to init the iterator */
#define XI_AT_END 2 /* upon next, get next of input and init the iterator by that */
#define XI_RESULT 3 /* the current of the iterator is at step.iterator, next will step this iterator */
#define XI_NO_ATTRIBUTE -1
int xi_next (xp_instance_t * xqi, XT * tree);
#if 0
extern int xt_is_ret_boolean (XT * tree);
extern int xt_is_ret_node_set (XT * tree);
#endif
extern int xt_predict_returned_type (XT * tree);
extern caddr_t xp_box_number (caddr_t n);
typedef void (* xp_func_t) (xp_instance_t * xqi, XT * tree, xml_entity_t * ctx_xe);
extern caddr_t xp_box_number (caddr_t n);
typedef struct xp_node_s
{
struct xp_node_s * xn_parent;
caddr_t * xn_attrs;
dk_set_t xn_children;
caddr_t * xn_namespaces;
long xn_n_children;
struct xparse_ctx_s * xn_xp;
} xp_node_t;
typedef struct xslt_template_uses_s
{
long xstu_byname_calls;
long xstu_find_calls;
long xstu_find_hits;
long xstu_find_match_calls;
long xstu_find_match_hits;
} xslt_template_uses_t;
typedef struct xslt_template_s
{
caddr_t xst_name;
caddr_t xst_mode;
float xst_priority;
int xst_match_attributes;
XT * xst_node_test; /*!< Can be NULL unlike other places, NULL if there's no full optimization */
xp_query_t * xst_match;
caddr_t * xst_tree;
struct xslt_sheet_s * xst_sheet;
int xst_simple;
int xst_union_member_idx;
xslt_template_uses_t xst_total_uses;
xslt_template_uses_t xst_new_uses;
} xslt_template_t;
typedef struct xslt_number_format_s
{
caddr_t xsnf_name;
caddr_t xsnf_decimal_sep;
caddr_t xsnf_grouping_sep;
caddr_t xsnf_infinity;
caddr_t xsnf_minus_sign;
caddr_t xsnf_NaN;
caddr_t xsnf_percent;
caddr_t xsnf_per_mille;
caddr_t xsnf_zero_digit;
caddr_t xsnf_digit;
caddr_t xsnf_pattern_sep;
} xslt_number_format_t;
extern caddr_t xslt_format_number (numeric_t value, caddr_t format, xslt_number_format_t * nf);
typedef struct xslt_sheet_stats_s
{
long xshu_calls;
long xshu_abends;
} xslt_sheet_stats_t;
typedef struct xslt_sheet_mode_s
{
caddr_t xstm_name;
xslt_template_t ** xstm_attr_templates;
xslt_template_t ** xstm_nonattr_templates;
} xslt_sheet_mode_t;
typedef struct xslt_sheet_s
{
shuric_t xsh_shuric;
struct xslt_sheet_s ** xsh_imported_sheets;
caddr_t * xsh_raw_tree; /*!< The stylesheet entity in its (almost) original form */
caddr_t * xsh_compiled_tree; /*!< The compiled version of stylesheet entity. To be removed soon! */
dk_set_t xsh_new_templates; /*!< Temporary set of templates used by the XSLT optimizer to prevent memory leaks on abend. */
xslt_template_t ** xsh_all_templates;
dk_hash_t * xsh_all_templates_byname;
xslt_sheet_mode_t xsh_default_mode;
dk_hash_t * xsh_named_modes;
xqi_binding_t * xsh_globals;
dk_set_t xsh_formats;
xml_ns_2dict_t xsh_ns_2dict; /*!< Dictionary of namespace that are declared in the stylesheet (or imported) and will extend the xd_ns_2dict of the resulting tree */
caddr_t xsh_top_excl_res_prefx; /*!< String that is an attribute value expression (string with expressions in {...}) that is value of exclude-result-prefixes attr of xsl:stylesheet element */
caddr_t xsh_sparql_preamble; /*!< A string that is inserted at the front of any SPARQL query that is executed by for-each-row */
XOUT_MEMBERS
xslt_sheet_stats_t xsh_total_uses;
xslt_sheet_stats_t xsh_new_uses;
} xslt_sheet_t;
#define XSNF_NEW \
(xslt_number_format_t *) dk_alloc_box_zero (11 * sizeof (caddr_t), DV_ARRAY_OF_POINTER);
extern xslt_number_format_t *xsnf_default;
/*! Context of an XML parsers (XML, XSLT, RDF/XML, RDFa, Microdata) */
typedef struct xparse_ctx_s
{
struct xparse_ctx_s * xp_parent; /*!< Context of parent parser (not-NULL when a parser reads GE (generic entity) nested in other document) */
xp_node_t * xp_top; /*!< Topmost node of the (currently incomplete) tree */
xp_node_t * xp_current; /*!< Current node (innermost not-yet-closed tag) */
xp_node_t * xp_free_list; /*!< Free-list, to avoid costly dk_alloc() overhead for every node */
long xp_bytes;
query_instance_t * xp_qi; /*!< Query that launched the parser */
dk_session_t * xp_strses;
caddr_t xp_id;
caddr_t xp_id_limit;
jmp_buf xp_error_ctx;
caddr_t xp_error_msg;
#ifdef XP_TRANSLATE_HOST
caddr_t xp_schema;
caddr_t xp_net_loc; /*!< [login] hostname [port] */
caddr_t xp_path; /*!< with starting '/' but with no params or query */
#endif
xslt_sheet_t * xp_sheet;
dk_set_t xp_checked_functions;
struct vxml_parser_s * xp_parser; /*!< The XML parser itself */
xslt_template_t * xp_template;
struct xml_doc_cache_s * xp_doc_cache;
xqi_binding_t * xp_globals;
xqi_binding_t * xp_locals;
xqi_binding_t * xp_prepared_parameters;
caddr_t xp_mode;
xml_entity_t * xp_current_xe;
long xp_position;
long xp_size;
dk_hash_t * xp_temps;
caddr_t xp_xslt_start;
caddr_t xp_keys;
id_hash_t * xp_id_dict;
caddr_t xp_boxed_name;
id_hash_t * xp_namespaces;
int xp_namespaces_are_valid;
caddr_t xp_top_excl_res_prefx; /*!< The value of exclude-result-prefixes XSLT attribute */
struct triple_feed_s *xp_tf; /*!< Triple feeder (for both RDF/XML and RDFa) */
struct xp_rdfxml_locals_s * xp_rdfxml_locals;
struct xp_rdfxml_locals_s * xp_rdfxml_free_list;
struct xp_rdfa_locals_s * xp_rdfa_locals;
struct xp_rdfa_locals_s * xp_rdfa_free_list;
struct xp_mdata_locals_s * xp_mdata_locals;
struct xp_mdata_locals_s * xp_mdata_free_list;
struct xp_tmp_s * xp_tmp;
} xparse_ctx_t;
extern void xp_free_rdf_parser_fields (xparse_ctx_t * xp);
extern void xp_element (void *userdata, char * name, vxml_parser_attrdata_t *attrdata);
extern void xp_element_end (void *userdata, const char * name);
extern void xp_id (void *userdata, char * name);
extern void xp_character (vxml_parser_t * parser, char * s, int len);
extern void xp_entity (vxml_parser_t * parser, const char * refname, int reflen, int isparam, const xml_def_4_entity_t *edef);
extern void xp_pi (vxml_parser_t * parser, const char *target, const char *data);
extern void xp_comment (vxml_parser_t * parser, const char *text);
#define XP_CTX_POS(xp, sz, pos) xp->xp_position = pos, xp->xp_size = sz
#define XP_CTX_POS_GET(xp, sz, pos) pos = xp->xp_position, sz = xp->xp_size
#define XP_STRSES_FLUSH_NOCHECK(xp) \
{ \
caddr_t text = strses_string ((xp)->xp_strses); \
strses_flush ((xp)->xp_strses); \
dk_set_push (&((xp)->xp_current->xn_children), (void*) text); \
(xp)->xp_current->xn_n_children++; \
}
#define XP_STRSES_FLUSH(xp) \
do { \
size_t xp_strses_length = strses_length ((xp)->xp_strses); \
if (0 != xp_strses_length) \
{ \
if (xp_strses_length & ~0xffffff) \
sqlr_new_error ("42000", "SR596", "Unable to place abnormally long string into XML tree, %ld bytes is above 16Mb limit", (long)xp_strses_length); \
XP_STRSES_FLUSH_NOCHECK(xp); \
if ((xp)->xp_current->xn_n_children >= MAX_BOX_ELEMENTS) \
sqlr_new_error ("42000", "SR596", "Unable to place abnormally long XML tree, %ld elements are above %ld limit", (long)(xp)->xp_current->xn_n_children, MAX_BOX_ELEMENTS); \
} \
} while (0)
#define XTE_HEAD(x) (((caddr_t **)x)[0])
#define XTE_HEAD_NAME(x) (((caddr_t *)x)[0])
extern void xn_xslt_attributes (xp_node_t * xn);
typedef struct xp_query_env_s
{
int xqre_allow_sql_extensions;
caddr_t xqre_base_uri;
xp_node_t * xqre_nsctx_xn; /*!< Namespace context as xp_node_t * */
xml_entity_t *xqre_nsctx_xe; /*!< Namespace context as xml_entity_t * */
wcharset_t *xqre_query_charset;
int xqre_query_charset_is_set;
dk_set_t *xqre_checked_functions;
dk_set_t *xqre_sql_columns;
int xqre_key_gen;
} xp_query_env_t;
extern xp_query_env_t xqre_default;
extern xp_query_t * xp_query_parse (query_instance_t * qi, char * str, ptrlong predicate_type, caddr_t * err_ret, xp_query_env_t *xqre);
extern caddr_t xp_query_lex_analyze (caddr_t str, char predicate_type, xp_node_t * nsctx, wcharset_t *query_charset);
/* IvAn/SmartXContains/001025 WR-optimization added */
/* \brief Enables WR-optimization for given xpath subtree, if it's possible
\arg xqr - whole query
\arg subtree - current xpath tree to try to optimize
\arg target_is_wr - flags if current tree is an input for wr-optimized xpath step,
If so, it may be optimized even if it is has no optimization hints by itself. */
extern void xp_query_enable_wr (xp_query_t * xqr, XT *subtree, int target_is_wr);
extern caddr_t bif_xslt (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args);
extern caddr_t bif_xtree_doc (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args);
extern void xpf_processXSLT (xp_instance_t * xqi, XT * tree, xml_entity_t * ctx_xe);
extern xml_entity_t * xte_copy (xml_entity_t * xe);
extern void xslt_init (void);
extern int xqi_truth_value (xp_instance_t * xqi, XT * tree);
extern int xqi_truth_value_of_box (caddr_t val);
extern int xqi_pred_truth_value (xp_instance_t * xqi, XT * tree);
extern xp_instance_t *xqr_instance (xp_query_t * xqr, query_instance_t * qi);
extern void xn_error (xp_node_t * xn, const char * msg);
extern int xqi_is_next_value (xp_instance_t * xqi, XT * tree);
extern int xqi_is_value (xp_instance_t * xqi, XT * tree);
extern void xslt_instantiate_1 (xparse_ctx_t * xp, caddr_t * xstree);
extern void xslt_process_children (xparse_ctx_t * xp, xml_entity_t * xe);
extern void xp_free (xparse_ctx_t * xp);
#define xqi_free(q) dk_free_box ((caddr_t) q)
extern int xe_destroy (caddr_t box);
extern void xe_sqlnarrow_string_value (xml_entity_t * xe, caddr_t * ret, dtp_t dtp);
extern int xe_down_transit (xml_entity_t * xe);
extern int xe_destroy (caddr_t box);
extern const char * xe_get_sysid (xml_entity_t *xe, const char *ref_name);
extern const char * xe_get_sysid_base_uri(xml_entity_t *xe);
#if 0
int dv_is_node_set (caddr_t x);
#define DV_IS_NODE_SET(q) dv_is_node_set((caddr_t) q)
#endif
extern caddr_t xte_attr_value (caddr_t * xte, char * name, int reqd);
extern caddr_t xp_string (query_instance_t * qi, caddr_t val);
extern void DBG_NAME(xe_string_value_1) (DBG_PARAMS xml_entity_t * xe, caddr_t * ret, dtp_t dtp);
extern xml_tree_ent_t *DBG_NAME(xte_from_tree) (DBG_PARAMS caddr_t tree, query_instance_t * qi);
#ifdef MALLOC_DEBUG
#define xe_string_value_1(XE,RET,DTP) dbg_xe_string_value_1(__FILE__, __LINE__, (XE), (RET), (DTP))
#define xte_from_tree(TREE,QI) dbg_xte_from_tree(__FILE__, __LINE__, (TREE), (QI))
#endif
extern void xte_copy_output_elements (struct xml_tree_ent_s *xte, struct xslt_sheet_s *sheet);
extern ptrlong xqi_set_debug_start; /* Value of xqi_set_odometer where rigorous memory testing must be started */
extern ptrlong xqi_set_odometer; /* Debugging counter of xqi_set operations, set to negative to avoid counting */
extern caddr_t xqi_set (xp_instance_t * xqi, int n, caddr_t v);
extern shuric_vtable_t shuric_vtable__xmlschema;
extern shuric_vtable_t shuric_vtable__xqr;
extern shuric_vtable_t shuric_vtable__xslt;
extern shuric_t *shuric_load_xml_by_qi (query_instance_t * qi, caddr_t base, caddr_t ref,
caddr_t * err_ret, shuric_t *loaded_by, shuric_vtable_t *vt, const char *caller);
extern xslt_sheet_t * xslt_sheet (query_instance_t * qi, caddr_t base, caddr_t ref,
caddr_t * err_ret, shuric_t *loaded_by);
extern caddr_t xte_attr_value_eval (xparse_ctx_t * xp, caddr_t * xte, char * name, int reqd);
extern caddr_t xn_ns_name (xp_node_t * xn, char * name, int use_default);
extern void xslt_traverse_inner (xparse_ctx_t * xp, xslt_sheet_t * first_xsh);
extern xslt_sheet_t * xslt_compiled_sheet (caddr_t href, caddr_t base_uri);
extern void xslt_instantiate (xparse_ctx_t * xp, xslt_template_t * xst, xml_entity_t * xe);
#define xslt_traverse_1(XP) xslt_traverse_inner ((XP), NULL)
extern caddr_t xml_get_ns_uri (client_connection_t *cli, caddr_t pref, ptrlong persistent, int ret_in_mp_box);
extern void DBG_NAME(xte_string_value_from_tree) (DBG_PARAMS caddr_t * current, caddr_t * ret, dtp_t dtp);
#ifdef MALLOC_DEBUG
#define xte_string_value_from_tree(C,RET,DTP) dbg_xte_string_value_from_tree (__FILE__,__LINE__,(C),(RET),(DTP))
#endif
extern dk_set_t xn_namespace_scope (xp_node_t * xn);
extern void xte_serialize (xml_entity_t * xe, dk_session_t * ses);
extern query_instance_t * qi_top_qi (query_instance_t * qi);
#define xte_is_entity(e) (DV_ARRAY_OF_POINTER == DV_TYPE_OF ((e)))
extern int xsl_is_qnames_attr (char * attr);
extern int xslt_non_whitespace (caddr_t elt);
/* \brief Finds if there are any hits in current row between two given positions */
extern int txs_is_hit_in (text_node_t * txs, caddr_t * qst, xml_entity_t * xe);
extern void bif_text_init (void);
extern void bif_ap_init (void);
extern void xml_tree_init (void);
extern void xml_lazy_init (void);
extern void xn_free (xpath_node_t * xn);
extern void xn_input (xpath_node_t * xn, caddr_t * inst, caddr_t *state);
extern caddr_t xn_text_query (xpath_node_t * xn, query_instance_t * qi, caddr_t xp_str);
xml_schema_t * xs_allocate (void);
extern void xmls_set_view_def (void * sc, xml_view_t * xv);
extern int xml_is_sch_qname (char *tag, char *attr); /* What of attribute values to be expanded as QName */
extern int xml_is_soap_qname (char *tag, char *attr);
extern int xml_is_wsdl_qname (char *tag, char *attr);
extern char * xml_find_attribute (caddr_t *entity, const char *szName, const char *szURI);
extern char * xte_output_method (xml_tree_ent_t * xte);
extern xqi_binding_t *xqi_find_binding (xp_instance_t * xqi, caddr_t name);
extern xqi_binding_t *xqi_push_internal_binding (xp_instance_t * xqi, caddr_t name);
extern void xqi_pop_internal_binding (xp_instance_t * xqi);
extern void xqi_pop_internal_bindings (xp_instance_t * xqi, xqi_binding_t *bottom_xb);
extern void xqi_remove_internal_binding (xp_instance_t * xqi, caddr_t name);
extern caddr_t list_to_array_of_xqval (dk_set_t l);
extern caddr_t xml_deserialize_from_blob (caddr_t bh, lock_trx_t *lt, caddr_t *qst, caddr_t uri);
extern void xte_serialize_packed (caddr_t *tree, dtd_t *dtd, dk_session_t * ses);
extern void xte_deserialize_packed (dk_session_t *ses, caddr_t **ret_tree, dtd_t **ret_dtd);
extern void dtd_save_str_to_buffer (unsigned char **tail_ptr, char *str);
extern int dtd_get_buffer_length (dtd_t * dtd);
extern void dtd_save_to_buffer (dtd_t *dtd, unsigned char *buf, size_t buf_len);
extern void dtd_load_from_buffer (dtd_t *res, caddr_t dtd_string);
extern void xe_insert_external_dtd (xml_entity_t *xe);
extern caddr_t xte_sum64 (caddr_t *curr);
extern caddr_t xml_make_tree (query_instance_t * qi, caddr_t text, caddr_t *err_ret,
const char *enc, lang_handler_t *lh, struct dtd_s **ret_dtd);
extern int xe_strses_serialize_utf8 (xml_entity_t * xe, dk_session_t * strses, int set_encoding);
extern void xe_serialize (xml_entity_t * xe, dk_session_t * ses);
extern caddr_t xml_get_cli_or_global_ns_prefix (caddr_t * qst, const char *uri, ptrlong persistent);
extern void xte_replace_strings_with_unames (caddr_t **tree);
extern int xe_compare_content (xml_entity_t *xe1, xml_entity_t *xe2, int compare_uris_and_dtds);
#ifdef XTREE_DEBUG
extern void xte_tree_check (box_t box);
#else
#define xte_tree_check(box)
#endif
/* If the position of entity A is compared with position of B, then the result is coded as... */
#define XE_CMP_A_NULL_B_VALID -4 /*!< entity cmp result if (NULL == A) && (NULL != B) */
#define XE_CMP_A_DOC_LT_B -3 /*!< entity cmp result if A and B are in different docs and A's doc ptr < B's doc ptr */
#define XE_CMP_A_IS_BEFORE_B -2 /*!< entity cmp result if A and B are in same doc and A is before B (and not an ancestor of B) */
#define XE_CMP_A_IS_ANCESTOR_OF_B -1 /*!< entity cmp result if A and B are in same doc and A is an ancestor of B */
#define XE_CMP_A_IS_EQUAL_TO_B 0 /*!< entity cmp result if A and B are equal entities or both are NULLs */
#define XE_CMP_A_IS_DESCENDANT_OF_B 1 /*!< entity cmp result if A and B are in same doc and A is an descendant of B */
#define XE_CMP_A_IS_AFTER_B 2 /*!< entity cmp result if A and B are in same doc and A is after B (and not an descendant of B) */
#define XE_CMP_A_DOC_GT_B 3 /*!< entity cmp result if A and B are in different docs and A's doc ptr > B's doc ptr */
#define XE_CMP_A_VALID_B_NULL 4 /*!< entity cmp result if (NULL != A) && (NULL == B) */
extern int xe_compare_logical_paths (ptrlong *lp_A, size_t lp_A_len, ptrlong *lp_B, size_t lp_B_len);
#ifdef MALLOC_DEBUG
#define box_cast_to_UTF8(qst,data) dbg_box_cast_to_UTF8(__FILE__, __LINE__, (qst), (data))
extern caddr_t dbg_box_cast_to_UTF8 (DBG_PARAMS caddr_t * qst, caddr_t data);
#else
extern caddr_t box_cast_to_UTF8 (caddr_t * qst, caddr_t data);
#endif
extern caddr_t box_cast_to_UTF8_xsd (caddr_t *qst, caddr_t data);
extern caddr_t box_cast_to_UTF8_uname (caddr_t *qst, caddr_t raw_name);
#define XQ_SQL_COLUMN_FORMAT "sql:column(%s)"
#define BOX_DV_UNAME_CONCAT4(qname,nsuri,local,local_len) \
do { \
ccaddr_t _nsuri = (nsuri); \
int _nsuri_len = box_length_inline (_nsuri) - 1; \
ccaddr_t _local = (local); \
int _local_len = (local_len); \
int _qname_len = _nsuri_len + _local_len; \
caddr_t _qname = box_dv_ubuf (_qname_len); \
memcpy (_qname, _nsuri, _nsuri_len); \
memcpy (_qname + _nsuri_len, _local, _local_len); \
_qname[_qname_len] = '\0'; \
(qname) = box_dv_uname_from_ubuf (_qname); \
} while (0)
#define BOX_DV_UNAME_CONCAT(qname,nsuri,local) \
do { \
ccaddr_t _local1 = (local); \
int _local1_len = box_length_inline (_local1) - 1; \
BOX_DV_UNAME_CONCAT4(qname,nsuri,_local1,_local1_len); \
} while (0)
#define BOX_DV_UNAME_COLONCONCAT5(qname,nsuri,nsuri_len,local,local_len) \
do { \
ccaddr_t _nsuri5 = (nsuri); \
int _nsuri5_len = (nsuri_len); \
ccaddr_t _local5 = (local); \
int _local5_len = (local_len); \
int _qname5_len = _nsuri5_len + _local5_len + 1; \
caddr_t _qname5 = box_dv_ubuf (_qname5_len); \
memcpy (_qname5, _nsuri5, _nsuri5_len); \
_qname5[_nsuri5_len++] = ':'; \
memcpy (_qname5 + _nsuri5_len, _local5, _local5_len); \
_qname5[_qname5_len] = '\0'; \
(qname) = box_dv_uname_from_ubuf (_qname5); \
} while (0)
#define BOX_DV_UNAME_COLONCONCAT4(qname,nsuri,local,local_len) \
do { \
ccaddr_t _nsuri4 = (nsuri); \
ccaddr_t _local4 = (local); \
int _local4_len = (local_len); \
int _nsuri4_len = box_length_inline (_nsuri4) - 1; \
BOX_DV_UNAME_COLONCONCAT5(qname,_nsuri4,_nsuri4_len,_local4,_local4_len); \
} while (0)
#define BOX_DV_UNAME_COLONCONCAT(qname,nsuri,local) \
do { \
ccaddr_t _local1 = (local); \
int _local1_len = box_length_inline (_local1) - 1; \
BOX_DV_UNAME_COLONCONCAT4(qname,nsuri,_local1,_local1_len); \
} while (0)
extern int xt_node_test_match_impl (XT * node_test, caddr_t qname);
#define xt_node_test_match(NT,Q) (((XT *)XP_NODE == (NT)) ? 1 : xt_node_test_match_impl(NT,Q))
extern int xt_node_test_match_parts (XT * node_test, char *name, size_t name_len, caddr_t ns);
/* Data feeders to retrieve source XML texts from various sources */
extern size_t file_read (void *read_cd, char *buf, size_t bsize);
/* \brief Forward-only iterator for dk_session_t. */
typedef struct dk_session_fwd_iter_s
{
dk_session_t *dsfi_dorigin; /*!< Data origin = session to iterate */
buffer_elt_t *dsfi_buffer; /*!< Pointer to buffer from buffer chain of dk_session_t */
size_t dsfi_offset; /*!< Offset in dsfi_buffer, where first unread char resides */
size_t dsfi_file_len; /*!< Length of the file visible as dsfi_dorigin->dks_session->ses_file */
size_t dsfi_file_offset; /*!< Offset in dsfi_dorigin->dks_session->ses_file, where first unread char resides */
} dk_session_fwd_iter_t;
extern void dsfi_reset (dk_session_fwd_iter_t * iter, dk_session_t * ses);
extern size_t dsfi_read (void *read_cd, char *buf, size_t bsize);
typedef struct bh_from_client_fwd_iter_s
{
blob_handle_t *bcfi_bh;
client_connection_t *bcfi_cli;
} bh_from_client_fwd_iter_t;
extern void bcfi_reset (bh_from_client_fwd_iter_t * iter, blob_handle_t *bh, client_connection_t *cli);
extern size_t bcfi_read (void *read_cd, char *buf, size_t bsize);
extern void bcfi_abend (void *read_cd);
typedef struct bh_from_disk_fwd_iter_s
{
blob_handle_t *bdfi_bh;
query_instance_t *bdfi_qi;
int bdfi_page_idx;
size_t bdfi_page_data_pos;
size_t bdfi_total_pos;
} bh_from_disk_fwd_iter_t;
extern void bdfi_reset (bh_from_disk_fwd_iter_t * iter, blob_handle_t *bh, query_instance_t *qi);
extern size_t bdfi_read (void *read_cd, char *buf, size_t bsize);
typedef struct xml_read_iter_env_s
{
bh_from_client_fwd_iter_t xrie_bcfi;
bh_from_disk_fwd_iter_t xrie_bdfi;
dk_session_fwd_iter_t xrie_dsfi;
xml_read_func_t xrie_iter;
xml_read_abend_func_t xrie_iter_abend;
void * xrie_iter_data;
s_size_t xrie_text_len;
int xrie_text_is_wide;
}
xml_read_iter_env_t;
extern int xml_set_xml_read_iter (query_instance_t * qi, caddr_t text, xml_read_iter_env_t *xrie, const char **enc_ret);
#define XDC_DOCUMENT 0 /*!< Storage type of dependant documents that are not external resources */
#define XDC_COLLECTION 1 /*!< Storage type of lists of resources in collections */
struct xml_doc_cache_stdkey_s
{
ptrlong xdcs_type;
caddr_t xdcs_abs_uri;
ptrlong xdcs_parser_mode;
caddr_t xdcs_enc_name;
lang_handler_t **xdcs_lang_ptr;
caddr_t xdcs_dtd_cfg;
};
/* This is a collection of XML document cache */
typedef struct xml_doc_cache_s
{
void *xdc_owner; /*!< Cache owner, e.g., to clean on owner's free */
size_t xdc_total_weight; /*!< Total size of all docs in cache, in kbytes */
size_t xdc_yellow_weight; /*!< Yellow mark: if exceeded then some docs should be freed */
size_t xdc_red_weight; /*!< Red mark: if exceeded then all docs should be freed */
id_hash_t * xdc_res_cache; /*!< Hashtable of all dependant documents that are not external references */
} xml_doc_cache_t;
xml_doc_cache_t *xml_doc_cache_alloc (void *owner);
void xml_doc_cache_free (xml_doc_cache_t *xdc);
caddr_t xml_doc_cache_get_copy (xml_doc_cache_t *xdc, ccaddr_t key);
void xml_doc_cache_add_copy (xml_doc_cache_t **xdc_ptr, ccaddr_t key, caddr_t doc);
void xml_doc_cache_shrink (xml_doc_cache_t *xdc, size_t weight_limit);
#define XE_IS_VALID_VALUE_FOR_XML_COL(val) (DV_BLOB_XPER_HANDLE != DV_TYPE_OF (val) && (DV_XML_ENTITY != DV_TYPE_OF (val) || (XE_IS_TREE (val))))
extern xml_lazy_ent_t *DBG_NAME(xlazye_from_cache_key) (DBG_PARAMS xml_doc_cache_stdkey_t *cache_key, query_instance_t *qi);
#ifdef MALLOC_DEBUG
#define xlazye_from_cache_key(key,qi) dbg_xlazye_from_cache_key(__FILE__, __LINE__, (key), (qi))
#endif
extern caddr_t xe_make_copy (caddr_t box);
#endif /* _XMLTREE_H */
|