Changeset 7b87e1d in mainline for uspace/lib/sif/src/sif.c
- Timestamp:
- 2018-08-02T11:39:22Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 233a3a06
- Parents:
- 1c398db2
- git-author:
- Jiri Svoboda <jiri@…> (2018-08-01 17:38:51)
- git-committer:
- Jiri Svoboda <jiri@…> (2018-08-02 11:39:22)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/sif/src/sif.c
r1c398db2 r7b87e1d 60 60 */ 61 61 62 #include <adt/list.h> 63 #include <adt/odict.h> 62 64 #include <errno.h> 63 65 #include <stdio.h> … … 69 71 static errno_t sif_export_node(sif_node_t *, FILE *); 70 72 static errno_t sif_import_node(sif_node_t *, FILE *, sif_node_t **); 73 static sif_attr_t *sif_node_first_attr(sif_node_t *); 74 static sif_attr_t *sif_node_next_attr(sif_attr_t *); 75 static void sif_attr_delete(sif_attr_t *); 76 static void *sif_attr_getkey(odlink_t *); 77 static int sif_attr_cmp(void *, void *); 71 78 72 79 /** Create new SIF node. 73 80 * 74 * @param parent Parent onde81 * @param parent Parent node 75 82 * @return Pointer to new node on success or @c NULL if out of memory 76 83 */ … … 84 91 85 92 node->parent = parent; 93 odict_initialize(&node->attrs, sif_attr_getkey, sif_attr_cmp); 86 94 list_initialize(&node->children); 87 95 … … 92 100 * 93 101 * Delete a SIF node that has been already unlinked from the tree. 102 * This will also delete any attributes or child nodes. 94 103 * 95 104 * @param node Node … … 97 106 static void sif_node_delete(sif_node_t *node) 98 107 { 108 sif_attr_t *attr; 109 sif_node_t *child; 110 99 111 if (node == NULL) 100 112 return; 101 113 114 assert(!link_used(&node->lparent)); 115 102 116 if (node->ntype != NULL) 103 117 free(node->ntype); 104 118 119 attr = sif_node_first_attr(node); 120 while (attr != NULL) { 121 odict_remove(&attr->lattrs); 122 sif_attr_delete(attr); 123 attr = sif_node_first_attr(node); 124 } 125 126 child = sif_node_first_child(node); 127 while (child != NULL) { 128 list_remove(&child->lparent); 129 sif_node_delete(child); 130 child = sif_node_first_child(node); 131 } 132 105 133 free(node); 134 } 135 136 /** Create new SIF attribute. 137 * 138 * @param node Containing node 139 * @return Pointer to new node on success or @c NULL if out of memory 140 */ 141 static sif_attr_t *sif_attr_new(sif_node_t *node) 142 { 143 sif_attr_t *attr; 144 145 attr = calloc(1, sizeof(sif_attr_t)); 146 if (attr == NULL) 147 return NULL; 148 149 attr->node = node; 150 return attr; 151 } 152 153 /** Delete SIF attribute. 154 * 155 * Delete a SIF attribute that has been already unlinked from is node. 156 * 157 * @param attr Attribute 158 */ 159 static void sif_attr_delete(sif_attr_t *attr) 160 { 161 if (attr == NULL) 162 return; 163 164 assert(!odlink_used(&attr->lattrs)); 165 166 if (attr->aname != NULL) 167 free(attr->aname); 168 if (attr->avalue != NULL) 169 free(attr->avalue); 170 171 free(attr); 106 172 } 107 173 … … 114 180 */ 115 181 errno_t sif_create(const char *fname, sif_sess_t **rsess) 182 { 183 sif_sess_t *sess; 184 sif_node_t *root = NULL; 185 sif_trans_t *trans = NULL; 186 errno_t rc; 187 FILE *f; 188 189 sess = calloc(1, sizeof(sif_sess_t)); 190 if (sess == NULL) 191 return ENOMEM; 192 193 root = sif_node_new(NULL); 194 if (root == NULL) { 195 rc = ENOMEM; 196 goto error; 197 } 198 199 root->ntype = str_dup("sif"); 200 if (root->ntype == NULL) { 201 rc = ENOMEM; 202 goto error; 203 } 204 205 f = fopen(fname, "w"); 206 if (f == NULL) { 207 rc = EIO; 208 goto error; 209 } 210 211 sess->f = f; 212 sess->root = root; 213 214 /* Run a dummy trasaction to marshall initial repo state to file */ 215 rc = sif_trans_begin(sess, &trans); 216 if (rc != EOK) 217 goto error; 218 219 rc = sif_trans_end(trans); 220 if (rc != EOK) 221 goto error; 222 223 *rsess = sess; 224 return EOK; 225 error: 226 if (trans != NULL) 227 sif_trans_abort(trans); 228 sif_node_delete(root); 229 free(sess); 230 return rc; 231 } 232 233 /** Open an existing SIF repository. 234 * 235 * @param fname File name 236 * @param rsess Place to store pointer to new session. 237 * 238 * @return EOK on success or error code 239 */ 240 errno_t sif_open(const char *fname, sif_sess_t **rsess) 116 241 { 117 242 sif_sess_t *sess; … … 124 249 return ENOMEM; 125 250 126 root = sif_node_new(NULL); 127 if (root == NULL) { 128 rc = ENOMEM; 129 goto error; 130 } 131 132 root->ntype = str_dup("sif"); 133 if (root->ntype == NULL) { 134 rc = ENOMEM; 135 goto error; 136 } 137 138 f = fopen(fname, "w"); 251 f = fopen(fname, "r+"); 139 252 if (f == NULL) { 140 253 rc = EIO; 141 254 goto error; 142 255 } 256 257 rc = sif_import_node(NULL, f, &root); 258 if (rc != EOK) 259 goto error; 260 261 if (str_cmp(root->ntype, "sif") != 0) { 262 rc = EIO; 263 goto error; 264 } 265 266 sess->root = root; 143 267 144 268 sess->f = f; … … 152 276 } 153 277 154 /** Open an existing SIF repository.155 *156 * @param fname File name157 * @param rsess Place to store pointer to new session.158 *159 * @return EOK on success or error code160 */161 errno_t sif_open(const char *fname, sif_sess_t **rsess)162 {163 sif_sess_t *sess;164 sif_node_t *root = NULL;165 errno_t rc;166 FILE *f;167 168 sess = calloc(1, sizeof(sif_sess_t));169 if (sess == NULL)170 return ENOMEM;171 172 f = fopen(fname, "r+");173 if (f == NULL) {174 rc = EIO;175 goto error;176 }177 178 rc = sif_import_node(NULL, f, &root);179 if (rc != EOK)180 goto error;181 182 if (str_cmp(root->ntype, "sif") != 0) {183 rc = EIO;184 goto error;185 }186 187 sess->root = root;188 189 sess->f = f;190 sess->root = root;191 *rsess = sess;192 return EOK;193 error:194 sif_node_delete(root);195 free(sess);196 return rc;197 }198 199 278 /** Close SIF session. 200 279 * … … 274 353 const char *sif_node_get_attr(sif_node_t *node, const char *aname) 275 354 { 276 return NULL; 355 odlink_t *link; 356 sif_attr_t *attr; 357 358 link = odict_find_eq(&node->attrs, (void *)aname, NULL); 359 if (link == NULL) 360 return NULL; 361 362 attr = odict_get_instance(link, sif_attr_t, lattrs); 363 return attr->avalue; 277 364 } 278 365 … … 296 383 297 384 /** Commit SIF transaction. 385 * 386 * Commit and free the transaction. If an error is returned, that means 387 * the transaction has not been freed (and sif_trans_abort() must be used). 298 388 * 299 389 * @param trans Transaction … … 320 410 void sif_trans_abort(sif_trans_t *trans) 321 411 { 412 free(trans); 322 413 } 323 414 … … 461 552 void sif_node_destroy(sif_trans_t *trans, sif_node_t *node) 462 553 { 463 sif_node_t *child;464 465 child = sif_node_first_child(node);466 while (child != NULL) {467 sif_node_destroy(trans, child);468 child = sif_node_first_child(node);469 }470 471 554 list_remove(&node->lparent); 472 555 sif_node_delete(node); … … 483 566 */ 484 567 errno_t sif_node_set_attr(sif_trans_t *trans, sif_node_t *node, 485 const char *aname, const char *value) 486 { 568 const char *aname, const char *avalue) 569 { 570 odlink_t *link; 571 sif_attr_t *attr; 572 char *cvalue; 573 574 link = odict_find_eq(&node->attrs, (void *)aname, NULL); 575 576 if (link != NULL) { 577 attr = odict_get_instance(link, sif_attr_t, lattrs); 578 cvalue = str_dup(avalue); 579 if (cvalue == NULL) 580 return ENOMEM; 581 582 free(attr->avalue); 583 attr->avalue = cvalue; 584 } else { 585 attr = sif_attr_new(node); 586 if (attr == NULL) 587 return ENOMEM; 588 589 attr->aname = str_dup(aname); 590 if (attr->aname == NULL) { 591 sif_attr_delete(attr); 592 return ENOMEM; 593 } 594 595 attr->avalue = str_dup(avalue); 596 if (attr->avalue == NULL) { 597 sif_attr_delete(attr); 598 return ENOMEM; 599 } 600 601 odict_insert(&attr->lattrs, &node->attrs, NULL); 602 } 603 487 604 return EOK; 488 605 } … … 500 617 const char *aname) 501 618 { 619 odlink_t *link; 620 sif_attr_t *attr; 621 622 link = odict_find_eq(&node->attrs, (void *)aname, NULL); 623 if (link == NULL) 624 return; 625 626 attr = odict_get_instance(link, sif_attr_t, lattrs); 627 odict_remove(link); 628 sif_attr_delete(attr); 502 629 } 503 630 … … 601 728 } 602 729 730 /** Import SIF attribute from file. 731 * 732 * @param node Node under which attribute shou 733 * @param f File 734 * @param rattr Place to store pointer to imported SIF attribute 735 * @return EOK on success, EIO on I/O error 736 */ 737 static errno_t sif_import_attr(sif_node_t *node, FILE *f, sif_attr_t **rattr) 738 { 739 errno_t rc; 740 char *aname = NULL; 741 char *avalue = NULL; 742 sif_attr_t *attr; 743 int c; 744 745 rc = sif_import_string(f, &aname); 746 if (rc != EOK) 747 goto error; 748 749 c = fgetc(f); 750 if (c != '=') { 751 rc = EIO; 752 goto error; 753 } 754 755 rc = sif_import_string(f, &avalue); 756 if (rc != EOK) 757 goto error; 758 759 attr = sif_attr_new(node); 760 if (attr == NULL) { 761 rc = ENOMEM; 762 goto error; 763 } 764 765 attr->aname = aname; 766 attr->avalue = avalue; 767 768 *rattr = attr; 769 return EOK; 770 error: 771 if (aname != NULL) 772 free(aname); 773 if (avalue != NULL) 774 free(avalue); 775 return rc; 776 } 777 778 779 /** Export SIF attribute to file. 780 * 781 * @param attr SIF attribute 782 * @param f File 783 * @return EOK on success, EIO on I/O error 784 */ 785 static errno_t sif_export_attr(sif_attr_t *attr, FILE *f) 786 { 787 errno_t rc; 788 789 rc = sif_export_string(attr->aname, f); 790 if (rc != EOK) 791 return rc; 792 793 if (fputc('=', f) == EOF) 794 return EIO; 795 796 rc = sif_export_string(attr->avalue, f); 797 if (rc != EOK) 798 return rc; 799 800 return EOK; 801 } 802 603 803 /** Export SIF node to file. 604 804 * … … 610 810 { 611 811 errno_t rc; 812 sif_attr_t *attr; 612 813 sif_node_t *child; 613 814 … … 615 816 if (rc != EOK) 616 817 return rc; 818 819 /* Attributes */ 820 821 if (fputc('(', f) == EOF) 822 return EIO; 823 824 attr = sif_node_first_attr(node); 825 while (attr != NULL) { 826 rc = sif_export_attr(attr, f); 827 if (rc != EOK) 828 return rc; 829 830 attr = sif_node_next_attr(attr); 831 } 832 833 if (fputc(')', f) == EOF) 834 return EIO; 835 836 /* Child nodes */ 617 837 618 838 if (fputc('{', f) == EOF) … … 646 866 sif_node_t *node = NULL; 647 867 sif_node_t *child; 868 sif_attr_t *attr; 648 869 char *ntype; 649 870 int c; … … 659 880 node->ntype = ntype; 660 881 882 /* Attributes */ 883 661 884 c = fgetc(f); 662 if (c != ' {') {885 if (c != '(') { 663 886 rc = EIO; 664 887 goto error; … … 671 894 } 672 895 673 while (c != ' }') {896 while (c != ')') { 674 897 ungetc(c, f); 675 898 676 rc = sif_import_ node(node, f, &child);899 rc = sif_import_attr(node, f, &attr); 677 900 if (rc != EOK) 678 901 goto error; 679 902 680 list_append(&child->lparent, &node->children);903 odict_insert(&attr->lattrs, &node->attrs, NULL); 681 904 682 905 c = fgetc(f); … … 687 910 } 688 911 912 /* Child nodes */ 913 914 c = fgetc(f); 915 if (c != '{') { 916 rc = EIO; 917 goto error; 918 } 919 920 c = fgetc(f); 921 if (c == EOF) { 922 rc = EIO; 923 goto error; 924 } 925 926 while (c != '}') { 927 ungetc(c, f); 928 929 rc = sif_import_node(node, f, &child); 930 if (rc != EOK) 931 goto error; 932 933 list_append(&child->lparent, &node->children); 934 935 c = fgetc(f); 936 if (c == EOF) { 937 rc = EIO; 938 goto error; 939 } 940 } 941 689 942 *rnode = node; 690 943 return EOK; … … 694 947 } 695 948 949 /** Get first attribute or a node. 950 * 951 * @param node SIF node 952 * @return First attribute or @c NULL if there is none 953 */ 954 static sif_attr_t *sif_node_first_attr(sif_node_t *node) 955 { 956 odlink_t *link; 957 958 link = odict_first(&node->attrs); 959 if (link == NULL) 960 return NULL; 961 962 return odict_get_instance(link, sif_attr_t, lattrs); 963 } 964 965 /** Get next attribute or a node. 966 * 967 * @param cur Current attribute 968 * @return Next attribute or @c NULL if there is none 969 */ 970 static sif_attr_t *sif_node_next_attr(sif_attr_t *cur) 971 { 972 odlink_t *link; 973 974 link = odict_next(&cur->lattrs, &cur->node->attrs); 975 if (link == NULL) 976 return NULL; 977 978 return odict_get_instance(link, sif_attr_t, lattrs); 979 } 980 981 /** Get key callback for ordered dictionary of node attributes. 982 * 983 * @param link Ordered dictionary link of attribute 984 * @return Pointer to attribute name 985 */ 986 static void *sif_attr_getkey(odlink_t *link) 987 { 988 return (void *)odict_get_instance(link, sif_attr_t, lattrs)->aname; 989 } 990 991 /** Comparison callback for ordered dictionary of node attributes. 992 * 993 * @param a Name of first attribute 994 * @param b Name of second attribute 995 * @return Less than zero, zero or greater than zero, if a < b, a == b, a > b, 996 * respectively. 997 */ 998 static int sif_attr_cmp(void *a, void *b) 999 { 1000 char *ca, *cb; 1001 1002 ca = (char *)a; 1003 cb = (char *)b; 1004 1005 return str_cmp(ca, cb); 1006 } 1007 696 1008 /** @} 697 1009 */
Note:
See TracChangeset
for help on using the changeset viewer.