Collection.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* Collection.cpp
  2. *
  3. * Copyright (C) 1992-2012,2015,2016,2017 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "Collection.h"
  19. #include <string>
  20. /********** class Collection **********/
  21. void _CollectionOfDaata_v_copy (_CollectionOfDaata* me, _CollectionOfDaata* thee) {
  22. thy at._elements = nullptr; // set to null in case the inherited v_copy crashes
  23. my structDaata :: v_copy (thee);
  24. thy _ownershipInitialized = my _ownershipInitialized;
  25. thy _ownItems = my _ownItems;
  26. thy _capacity = my _capacity;
  27. thy size = my size;
  28. if (my _capacity > 0) {
  29. thy at._elements = Melder_calloc (Daata, my _capacity); // filled with null pointers
  30. thy at._elements --; // immediately turn from base-0 into base-1 // BUG use NUMvector
  31. }
  32. for (integer i = 1; i <= my size; i ++) {
  33. Daata item = my at [i];
  34. if (my _ownItems) {
  35. Melder_require (Thing_isa (item, classDaata),
  36. U"Cannot copy item of class ", Thing_className (item), U".");
  37. thy at [i] = Data_copy (item).releaseToAmbiguousOwner();
  38. } else {
  39. thy at [i] = item; // reference copy: if me doesn't own the items, then thee shouldn't either // NOTE: the items don't have to be Daata
  40. }
  41. }
  42. }
  43. bool _CollectionOfDaata_v_equal (_CollectionOfDaata* me, _CollectionOfDaata* thee) {
  44. if (! my structDaata :: v_equal (thee)) return false;
  45. if (my size != thy size) return false;
  46. for (integer i = 1; i <= my size; i ++) {
  47. Melder_require (Thing_isa (my at [i], classDaata),
  48. U"Collection::equal: cannot compare items of class ", Thing_className (my at [i]), U".");
  49. Melder_require (Thing_isa (thy at [i], classDaata),
  50. U"Collection::equal: cannot compare items of class ", Thing_className (thy at [i]), U".");
  51. bool equal = Data_equal (my at [i], thy at [i]);
  52. //Melder_casual (U"classCollection_equal: ", equal,
  53. // U", item ", i,
  54. // U", types ", Thing_className (my item [i]), U" and ", Thing_className (thy item [i]));
  55. if (! equal) return false;
  56. }
  57. return true;
  58. }
  59. bool _CollectionOfDaata_v_canWriteAsEncoding (_CollectionOfDaata* me, int encoding) {
  60. for (integer i = 1; i <= my size; i ++) {
  61. Daata data = my at [i];
  62. if (data -> name && ! Melder_isEncodable (data -> name.get(), encoding)) return false;
  63. if (! Data_canWriteAsEncoding (data, encoding)) return false;
  64. }
  65. return true;
  66. }
  67. void _CollectionOfDaata_v_writeText (_CollectionOfDaata* me, MelderFile file) {
  68. texputi32 (file, my size, U"size");
  69. texputintro (file, U"item []: ", my size ? nullptr : U"(empty)");
  70. for (integer i = 1; i <= my size; i ++) {
  71. Daata thing = my at [i];
  72. ClassInfo classInfo = thing -> classInfo;
  73. texputintro (file, U"item [", Melder_integer (i), U"]:");
  74. Melder_require (Thing_isa (thing, classDaata) && Data_canWriteText (thing),
  75. U"Objects of class ", classInfo -> className, U" cannot be written.");
  76. texputw16 (file,
  77. classInfo -> version > 0 ?
  78. Melder_cat (classInfo -> className, U" ", classInfo -> version) :
  79. classInfo -> className,
  80. U"class", 0,0,0,0,0);
  81. texputw16 (file, thing -> name.get(), U"name");
  82. Data_writeText (thing, file);
  83. texexdent (file);
  84. }
  85. texexdent (file);
  86. }
  87. void _CollectionOfDaata_v_readText (_CollectionOfDaata* me, MelderReadText text, int formatVersion) {
  88. if (formatVersion < 0) {
  89. autostring8 line = Melder_32to8 (MelderReadText_readLine (text));
  90. long_not_integer l_size;
  91. Melder_require (line && sscanf (line.get(), "%ld", & l_size) == 1 && l_size >= 0,
  92. U"Collection::readText: cannot read size.");
  93. my _grow (l_size);
  94. for (integer i = 1; i <= l_size; i ++) {
  95. do {
  96. line = Melder_32to8 (MelderReadText_readLine (text));
  97. if (! line)
  98. Melder_throw (U"Missing object line.");
  99. } while (! strnequ (line.get(), "Object ", 7));
  100. long_not_integer itemNumberRead; // %ld
  101. char klas [200], nameTag [2000];
  102. int_not_integer n = 0; // %n
  103. integer stringsRead = sscanf (line.get(), "Object %ld: class %199s %1999s%n", & itemNumberRead, klas, nameTag, & n);
  104. Melder_require (stringsRead >= 2,
  105. U"Collection::readText: cannot read header of object ", i, U".");
  106. Melder_require (itemNumberRead == i,
  107. U"Collection::readText: read item number ", itemNumberRead, U" while expecting ", i, U".");
  108. Melder_require (stringsRead < 3 || strequ (nameTag, "name"),
  109. U"Collection::readText: wrong header at object ", i, U".");
  110. my at [i] = (Daata) Thing_newFromClassName (Melder_peek8to32 (klas), nullptr).releaseToAmbiguousOwner();
  111. my size ++;
  112. Melder_require (Thing_isa (my at [i], classDaata) && Data_canReadText (my at [i]),
  113. U"Cannot read item of class ", Thing_className (my at [i]), U" in collection.");
  114. Data_readText (my at [i], text, -1);
  115. if (stringsRead == 3) {
  116. char *location = & line [n];
  117. if (*location == ' ') n ++; // skip space character
  118. integer length = strlen (location);
  119. if (length > 0 && location [length - 1] == '\n')
  120. location [length - 1] = '\0';
  121. Thing_setName (my at [i], Melder_peek8to32 (line.get()+n));
  122. }
  123. }
  124. } else {
  125. int32 l_size = texgeti32 (text);
  126. my _grow (l_size);
  127. for (int32 i = 1; i <= l_size; i ++) {
  128. autostring32 className = texgetw16 (text);
  129. int elementFormatVersion;
  130. my at [i] = (Daata) Thing_newFromClassName (className.get(), & elementFormatVersion).releaseToAmbiguousOwner();
  131. my size ++;
  132. Melder_require (Thing_isa (my at [i], classDaata) && Data_canReadText (my at [i]),
  133. U"Cannot read item of class ", Thing_className (my at [i]), U" in collection.");
  134. autostring32 objectName = texgetw16 (text);
  135. Thing_setName (my at [i], objectName.get());
  136. Data_readText (my at [i], text, elementFormatVersion);
  137. }
  138. }
  139. }
  140. void _CollectionOfDaata_v_writeBinary (_CollectionOfDaata* me, FILE *f) {
  141. binputi32 (my size, f);
  142. for (integer i = 1; i <= my size; i ++) {
  143. Daata thing = my at [i];
  144. ClassInfo classInfo = thing -> classInfo;
  145. Melder_require (Thing_isa (thing, classDaata) && Data_canWriteBinary (thing),
  146. U"Objects of class ", classInfo -> className, U" cannot be written.");
  147. binputw8 (classInfo -> version > 0 ?
  148. Melder_cat (classInfo -> className, U" ", classInfo -> version) : classInfo -> className, f);
  149. binputw16 (thing -> name.get(), f);
  150. Data_writeBinary ((Daata) thing, f);
  151. }
  152. }
  153. void _CollectionOfDaata_v_readBinary (_CollectionOfDaata* me, FILE *f, int formatVersion) {
  154. if (formatVersion < 0) {
  155. int32 l_size = bingeti32 (f);
  156. if (l_size < 0)
  157. Melder_throw (U"Empty collection.");
  158. my _grow (l_size);
  159. for (int32 i = 1; i <= l_size; i ++) {
  160. char klas [200], name [2000];
  161. Melder_require (fscanf (f, "%199s%1999s", klas, name) == 2,
  162. U"Cannot read class and name.");
  163. my at [i] = (Daata) Thing_newFromClassName (Melder_peek8to32 (klas), nullptr).releaseToAmbiguousOwner();
  164. my size ++;
  165. Melder_require (Thing_isa (my at [i], classDaata),
  166. U"Cannot read item of class ", Thing_className (my at [i]), U".");
  167. Melder_require (fgetc (f) == ' ',
  168. U"Cannot read space.");
  169. Data_readBinary (my at [i], f, -1);
  170. if (strcmp (name, "?"))
  171. Thing_setName (my at [i], Melder_peek8to32 (name));
  172. }
  173. } else {
  174. int32 l_size = bingeti32 (f);
  175. if (Melder_debug == 44)
  176. Melder_casual (U"structCollection :: v_readBinary: Reading ", l_size, U" objects");
  177. my _grow (l_size);
  178. for (int32 i = 1; i <= l_size; i ++) {
  179. autostring8 klas = bingets8 (f);
  180. if (Melder_debug == 44)
  181. Melder_casual (U"structCollection :: v_readBinary: Reading object of type ", Melder_peek8to32 (klas.get()));
  182. int elementFormatVersion;
  183. my at [i] = (Daata) Thing_newFromClassName (Melder_peek8to32 (klas.get()), & elementFormatVersion).releaseToAmbiguousOwner();
  184. my size ++;
  185. Melder_require (Thing_isa (my at [i], classDaata) && Data_canReadBinary (my at [i]),
  186. U"Objects of class ", Thing_className (my at [i]), U" cannot be read.");
  187. autostring32 name = bingetw16 (f);
  188. if (Melder_debug == 44)
  189. Melder_casual (U"structCollection :: v_readBinary: Reading object with name ", name.get());
  190. Thing_setName (my at [i], name.get());
  191. Data_readBinary (my at [i], f, elementFormatVersion);
  192. }
  193. }
  194. }
  195. struct structData_Description theCollectionOfDaata_v_description [] = {
  196. { U"size", integerwa, Melder_offsetof (CollectionOf<structThing>*, size), sizeof (integer), nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr },
  197. { U"items", objectwa, Melder_offsetof (CollectionOf<structThing>*, at), sizeof (Daata), U"Daata", & theClassInfo_Daata, 1, nullptr, U"size", nullptr, nullptr },
  198. { }
  199. };
  200. #define _Collection_implement(klas,genericClass,itemClass,parentClass,version) \
  201. static Thing _##klas##_new () { return new genericClass<struct##itemClass>; } \
  202. struct structClassInfo theClassInfo_##klas = { U"" #klas, & theClassInfo_##parentClass, \
  203. sizeof (genericClass<struct##itemClass>), _##klas##_new, version, 0, nullptr}; \
  204. ClassInfo class##klas = & theClassInfo_##klas
  205. _Collection_implement (Collection, CollectionOf, Thing, Daata, 0);
  206. _Collection_implement (Ordered, OrderedOf, Daata, Collection, 0);
  207. _Collection_implement (Sorted, SortedOf, Daata, Collection, 0);
  208. _Collection_implement (SortedSet, SortedSetOf, Daata, Sorted, 0);
  209. Thing_implement (StringList, Ordered, 0);
  210. Thing_implement (StringSet, SortedSet, 0);
  211. /* End of file Collection.cpp */