@@ -445,16 +445,9 @@ xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key,
445
445
if (dealloc )
446
446
dealloc (entry -> payload , entry -> key );
447
447
entry -> payload = payload ;
448
- return (0 );
449
- } else {
450
- /*
451
- * xmlHashAddEntry found an existing entry.
452
- *
453
- * TODO: We should return a different error code here to
454
- * distinguish from malloc failures.
455
- */
456
- return (-1 );
457
448
}
449
+
450
+ return (0 );
458
451
}
459
452
460
453
/*
@@ -589,7 +582,7 @@ xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key,
589
582
590
583
hash -> nbElems ++ ;
591
584
592
- return (0 );
585
+ return (1 );
593
586
}
594
587
595
588
/**
@@ -604,6 +597,60 @@ xmlHashDefaultDeallocator(void *entry, const xmlChar *key ATTRIBUTE_UNUSED) {
604
597
xmlFree (entry );
605
598
}
606
599
600
+ /**
601
+ * xmlHashAdd:
602
+ * @hash: hash table
603
+ * @key: string key
604
+ * @payload: pointer to the payload
605
+ *
606
+ * Add a hash table entry. If an entry with this key already exists,
607
+ * payload will not be updated and 0 is returned. This return value
608
+ * can't be distinguished from out-of-memory errors, so this function
609
+ * should be used with care.
610
+ *
611
+ * Returns 1 on success, 0 if an entry exists and -1 in case of error.
612
+ */
613
+ int
614
+ xmlHashAdd (xmlHashTablePtr hash , const xmlChar * key , void * payload ) {
615
+ return (xmlHashUpdateInternal (hash , key , NULL , NULL , payload , NULL , 0 ));
616
+ }
617
+
618
+ /**
619
+ * xmlHashAdd2:
620
+ * @hash: hash table
621
+ * @key: first string key
622
+ * @key2: second string key
623
+ * @payload: pointer to the payload
624
+ *
625
+ * Add a hash table entry with two strings as key.
626
+ *
627
+ * See xmlHashAdd.
628
+ */
629
+ int
630
+ xmlHashAdd2 (xmlHashTablePtr hash , const xmlChar * key ,
631
+ const xmlChar * key2 , void * payload ) {
632
+ return (xmlHashUpdateInternal (hash , key , key2 , NULL , payload , NULL , 0 ));
633
+ }
634
+
635
+ /**
636
+ * xmlHashAdd3:
637
+ * @hash: hash table
638
+ * @key: first string key
639
+ * @key2: second string key
640
+ * @key3: third string key
641
+ * @payload: pointer to the payload
642
+ *
643
+ * Add a hash table entry with three strings as key.
644
+ *
645
+ * See xmlHashAdd.
646
+ */
647
+ int
648
+ xmlHashAdd3 (xmlHashTablePtr hash , const xmlChar * key ,
649
+ const xmlChar * key2 , const xmlChar * key3 ,
650
+ void * payload ) {
651
+ return (xmlHashUpdateInternal (hash , key , key2 , key3 , payload , NULL , 0 ));
652
+ }
653
+
607
654
/**
608
655
* xmlHashAddEntry:
609
656
* @hash: hash table
@@ -615,11 +662,21 @@ xmlHashDefaultDeallocator(void *entry, const xmlChar *key ATTRIBUTE_UNUSED) {
615
662
* can't be distinguished from out-of-memory errors, so this function
616
663
* should be used with care.
617
664
*
665
+ * NOTE: This function doesn't allow to distinguish malloc failures from
666
+ * existing entries. Use xmlHashAdd instead.
667
+ *
618
668
* Returns 0 on success and -1 in case of error.
619
669
*/
620
670
int
621
671
xmlHashAddEntry (xmlHashTablePtr hash , const xmlChar * key , void * payload ) {
622
- return (xmlHashUpdateInternal (hash , key , NULL , NULL , payload , NULL , 0 ));
672
+ int res = xmlHashUpdateInternal (hash , key , NULL , NULL , payload , NULL , 0 );
673
+
674
+ if (res == 0 )
675
+ res = -1 ;
676
+ else if (res == 1 )
677
+ res = 0 ;
678
+
679
+ return (res );
623
680
}
624
681
625
682
/**
@@ -638,7 +695,14 @@ xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload) {
638
695
int
639
696
xmlHashAddEntry2 (xmlHashTablePtr hash , const xmlChar * key ,
640
697
const xmlChar * key2 , void * payload ) {
641
- return (xmlHashUpdateInternal (hash , key , key2 , NULL , payload , NULL , 0 ));
698
+ int res = xmlHashUpdateInternal (hash , key , key2 , NULL , payload , NULL , 0 );
699
+
700
+ if (res == 0 )
701
+ res = -1 ;
702
+ else if (res == 1 )
703
+ res = 0 ;
704
+
705
+ return (res );
642
706
}
643
707
644
708
/**
659
723
xmlHashAddEntry3 (xmlHashTablePtr hash , const xmlChar * key ,
660
724
const xmlChar * key2 , const xmlChar * key3 ,
661
725
void * payload ) {
662
- return (xmlHashUpdateInternal (hash , key , key2 , key3 , payload , NULL , 0 ));
726
+ int res = xmlHashUpdateInternal (hash , key , key2 , key3 , payload , NULL , 0 );
727
+
728
+ if (res == 0 )
729
+ res = -1 ;
730
+ else if (res == 1 )
731
+ res = 0 ;
732
+
733
+ return (res );
663
734
}
664
735
665
736
/**
@@ -677,8 +748,13 @@ xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key,
677
748
int
678
749
xmlHashUpdateEntry (xmlHashTablePtr hash , const xmlChar * key ,
679
750
void * payload , xmlHashDeallocator dealloc ) {
680
- return (xmlHashUpdateInternal (hash , key , NULL , NULL , payload ,
681
- dealloc , 1 ));
751
+ int res = xmlHashUpdateInternal (hash , key , NULL , NULL , payload ,
752
+ dealloc , 1 );
753
+
754
+ if (res == 1 )
755
+ res = 0 ;
756
+
757
+ return (res );
682
758
}
683
759
684
760
/**
699
775
xmlHashUpdateEntry2 (xmlHashTablePtr hash , const xmlChar * key ,
700
776
const xmlChar * key2 , void * payload ,
701
777
xmlHashDeallocator dealloc ) {
702
- return (xmlHashUpdateInternal (hash , key , key2 , NULL , payload ,
703
- dealloc , 1 ));
778
+ int res = xmlHashUpdateInternal (hash , key , key2 , NULL , payload ,
779
+ dealloc , 1 );
780
+
781
+ if (res == 1 )
782
+ res = 0 ;
783
+
784
+ return (res );
704
785
}
705
786
706
787
/**
722
803
xmlHashUpdateEntry3 (xmlHashTablePtr hash , const xmlChar * key ,
723
804
const xmlChar * key2 , const xmlChar * key3 ,
724
805
void * payload , xmlHashDeallocator dealloc ) {
725
- return (xmlHashUpdateInternal (hash , key , key2 , key3 , payload ,
726
- dealloc , 1 ));
806
+ int res = xmlHashUpdateInternal (hash , key , key2 , key3 , payload ,
807
+ dealloc , 1 );
808
+
809
+ if (res == 1 )
810
+ res = 0 ;
811
+
812
+ return (res );
727
813
}
728
814
729
815
/**
@@ -1037,21 +1123,23 @@ xmlHashScanFull3(xmlHashTablePtr hash, const xmlChar *key,
1037
1123
}
1038
1124
}
1039
1125
1040
- /**
1041
- * xmlHashCopy :
1126
+ /*
1127
+ * xmlHashCopySafe :
1042
1128
* @hash: hash table
1043
- * @copy: copier function for items in the hash
1129
+ * @copyFunc: copier function for items in the hash
1130
+ * @deallocFunc: deallocation function in case of errors
1044
1131
*
1045
- * Copy the hash @ table using @copy to copy payloads.
1132
+ * Copy the hash table using @copyFunc to copy payloads.
1046
1133
*
1047
1134
* Returns the new table or NULL if a memory allocation failed.
1048
1135
*/
1049
1136
xmlHashTablePtr
1050
- xmlHashCopy (xmlHashTablePtr hash , xmlHashCopier copy ) {
1137
+ xmlHashCopySafe (xmlHashTablePtr hash , xmlHashCopier copyFunc ,
1138
+ xmlHashDeallocator deallocFunc ) {
1051
1139
const xmlHashEntry * entry , * end ;
1052
1140
xmlHashTablePtr ret ;
1053
1141
1054
- if ((hash == NULL ) || (copy == NULL ))
1142
+ if ((hash == NULL ) || (copyFunc == NULL ))
1055
1143
return (NULL );
1056
1144
1057
1145
ret = xmlHashCreate (hash -> size );
@@ -1064,12 +1152,42 @@ xmlHashCopy(xmlHashTablePtr hash, xmlHashCopier copy) {
1064
1152
end = & hash -> table [hash -> size ];
1065
1153
1066
1154
for (entry = hash -> table ; entry < end ; entry ++ ) {
1067
- if (entry -> hashValue != 0 )
1068
- xmlHashAddEntry3 (ret , entry -> key , entry -> key2 , entry -> key3 ,
1069
- copy (entry -> payload , entry -> key ));
1155
+ if (entry -> hashValue != 0 ) {
1156
+ void * copy ;
1157
+
1158
+ copy = copyFunc (entry -> payload , entry -> key );
1159
+ if (copy == NULL )
1160
+ goto error ;
1161
+ if (xmlHashAdd3 (ret , entry -> key , entry -> key2 , entry -> key3 ,
1162
+ copy ) <= 0 ) {
1163
+ if (deallocFunc != NULL )
1164
+ deallocFunc (copy , entry -> key );
1165
+ goto error ;
1166
+ }
1167
+ }
1070
1168
}
1071
1169
1072
1170
return (ret );
1171
+
1172
+ error :
1173
+ xmlHashFree (ret , deallocFunc );
1174
+ return (NULL );
1175
+ }
1176
+
1177
+ /*
1178
+ * xmlHashCopy:
1179
+ * @hash: hash table
1180
+ * @copy: copier function for items in the hash
1181
+ *
1182
+ * DEPRECATED: Leaks memory in error case.
1183
+ *
1184
+ * Copy the hash table using @copy to copy payloads.
1185
+ *
1186
+ * Returns the new table or NULL if a memory allocation failed.
1187
+ */
1188
+ xmlHashTablePtr
1189
+ xmlHashCopy (xmlHashTablePtr hash , xmlHashCopier copy ) {
1190
+ return (xmlHashCopySafe (hash , copy , NULL ));
1073
1191
}
1074
1192
1075
1193
/**
0 commit comments