isotree 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +2 -2
  4. data/README.md +22 -1
  5. data/ext/isotree/ext.cpp +26 -0
  6. data/ext/isotree/extconf.rb +3 -3
  7. data/lib/isotree.rb +1 -0
  8. data/lib/isotree/isolation_forest.rb +86 -1
  9. data/lib/isotree/version.rb +1 -1
  10. data/vendor/cereal/LICENSE +24 -0
  11. data/vendor/cereal/README.md +85 -0
  12. data/vendor/cereal/include/cereal/access.hpp +351 -0
  13. data/vendor/cereal/include/cereal/archives/adapters.hpp +163 -0
  14. data/vendor/cereal/include/cereal/archives/binary.hpp +169 -0
  15. data/vendor/cereal/include/cereal/archives/json.hpp +1019 -0
  16. data/vendor/cereal/include/cereal/archives/portable_binary.hpp +334 -0
  17. data/vendor/cereal/include/cereal/archives/xml.hpp +956 -0
  18. data/vendor/cereal/include/cereal/cereal.hpp +1089 -0
  19. data/vendor/cereal/include/cereal/details/helpers.hpp +422 -0
  20. data/vendor/cereal/include/cereal/details/polymorphic_impl.hpp +796 -0
  21. data/vendor/cereal/include/cereal/details/polymorphic_impl_fwd.hpp +65 -0
  22. data/vendor/cereal/include/cereal/details/static_object.hpp +127 -0
  23. data/vendor/cereal/include/cereal/details/traits.hpp +1411 -0
  24. data/vendor/cereal/include/cereal/details/util.hpp +84 -0
  25. data/vendor/cereal/include/cereal/external/base64.hpp +134 -0
  26. data/vendor/cereal/include/cereal/external/rapidjson/allocators.h +284 -0
  27. data/vendor/cereal/include/cereal/external/rapidjson/cursorstreamwrapper.h +78 -0
  28. data/vendor/cereal/include/cereal/external/rapidjson/document.h +2652 -0
  29. data/vendor/cereal/include/cereal/external/rapidjson/encodedstream.h +299 -0
  30. data/vendor/cereal/include/cereal/external/rapidjson/encodings.h +716 -0
  31. data/vendor/cereal/include/cereal/external/rapidjson/error/en.h +74 -0
  32. data/vendor/cereal/include/cereal/external/rapidjson/error/error.h +161 -0
  33. data/vendor/cereal/include/cereal/external/rapidjson/filereadstream.h +99 -0
  34. data/vendor/cereal/include/cereal/external/rapidjson/filewritestream.h +104 -0
  35. data/vendor/cereal/include/cereal/external/rapidjson/fwd.h +151 -0
  36. data/vendor/cereal/include/cereal/external/rapidjson/internal/biginteger.h +290 -0
  37. data/vendor/cereal/include/cereal/external/rapidjson/internal/diyfp.h +271 -0
  38. data/vendor/cereal/include/cereal/external/rapidjson/internal/dtoa.h +245 -0
  39. data/vendor/cereal/include/cereal/external/rapidjson/internal/ieee754.h +78 -0
  40. data/vendor/cereal/include/cereal/external/rapidjson/internal/itoa.h +308 -0
  41. data/vendor/cereal/include/cereal/external/rapidjson/internal/meta.h +186 -0
  42. data/vendor/cereal/include/cereal/external/rapidjson/internal/pow10.h +55 -0
  43. data/vendor/cereal/include/cereal/external/rapidjson/internal/regex.h +740 -0
  44. data/vendor/cereal/include/cereal/external/rapidjson/internal/stack.h +232 -0
  45. data/vendor/cereal/include/cereal/external/rapidjson/internal/strfunc.h +69 -0
  46. data/vendor/cereal/include/cereal/external/rapidjson/internal/strtod.h +290 -0
  47. data/vendor/cereal/include/cereal/external/rapidjson/internal/swap.h +46 -0
  48. data/vendor/cereal/include/cereal/external/rapidjson/istreamwrapper.h +128 -0
  49. data/vendor/cereal/include/cereal/external/rapidjson/memorybuffer.h +70 -0
  50. data/vendor/cereal/include/cereal/external/rapidjson/memorystream.h +71 -0
  51. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/inttypes.h +316 -0
  52. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/stdint.h +300 -0
  53. data/vendor/cereal/include/cereal/external/rapidjson/ostreamwrapper.h +81 -0
  54. data/vendor/cereal/include/cereal/external/rapidjson/pointer.h +1414 -0
  55. data/vendor/cereal/include/cereal/external/rapidjson/prettywriter.h +277 -0
  56. data/vendor/cereal/include/cereal/external/rapidjson/rapidjson.h +656 -0
  57. data/vendor/cereal/include/cereal/external/rapidjson/reader.h +2230 -0
  58. data/vendor/cereal/include/cereal/external/rapidjson/schema.h +2497 -0
  59. data/vendor/cereal/include/cereal/external/rapidjson/stream.h +223 -0
  60. data/vendor/cereal/include/cereal/external/rapidjson/stringbuffer.h +121 -0
  61. data/vendor/cereal/include/cereal/external/rapidjson/writer.h +709 -0
  62. data/vendor/cereal/include/cereal/external/rapidxml/license.txt +52 -0
  63. data/vendor/cereal/include/cereal/external/rapidxml/manual.html +406 -0
  64. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml.hpp +2624 -0
  65. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_iterators.hpp +175 -0
  66. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_print.hpp +428 -0
  67. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_utils.hpp +123 -0
  68. data/vendor/cereal/include/cereal/macros.hpp +154 -0
  69. data/vendor/cereal/include/cereal/specialize.hpp +139 -0
  70. data/vendor/cereal/include/cereal/types/array.hpp +79 -0
  71. data/vendor/cereal/include/cereal/types/atomic.hpp +55 -0
  72. data/vendor/cereal/include/cereal/types/base_class.hpp +203 -0
  73. data/vendor/cereal/include/cereal/types/bitset.hpp +176 -0
  74. data/vendor/cereal/include/cereal/types/boost_variant.hpp +164 -0
  75. data/vendor/cereal/include/cereal/types/chrono.hpp +72 -0
  76. data/vendor/cereal/include/cereal/types/common.hpp +129 -0
  77. data/vendor/cereal/include/cereal/types/complex.hpp +56 -0
  78. data/vendor/cereal/include/cereal/types/concepts/pair_associative_container.hpp +73 -0
  79. data/vendor/cereal/include/cereal/types/deque.hpp +62 -0
  80. data/vendor/cereal/include/cereal/types/forward_list.hpp +68 -0
  81. data/vendor/cereal/include/cereal/types/functional.hpp +43 -0
  82. data/vendor/cereal/include/cereal/types/list.hpp +62 -0
  83. data/vendor/cereal/include/cereal/types/map.hpp +36 -0
  84. data/vendor/cereal/include/cereal/types/memory.hpp +425 -0
  85. data/vendor/cereal/include/cereal/types/optional.hpp +66 -0
  86. data/vendor/cereal/include/cereal/types/polymorphic.hpp +483 -0
  87. data/vendor/cereal/include/cereal/types/queue.hpp +132 -0
  88. data/vendor/cereal/include/cereal/types/set.hpp +103 -0
  89. data/vendor/cereal/include/cereal/types/stack.hpp +76 -0
  90. data/vendor/cereal/include/cereal/types/string.hpp +61 -0
  91. data/vendor/cereal/include/cereal/types/tuple.hpp +123 -0
  92. data/vendor/cereal/include/cereal/types/unordered_map.hpp +36 -0
  93. data/vendor/cereal/include/cereal/types/unordered_set.hpp +99 -0
  94. data/vendor/cereal/include/cereal/types/utility.hpp +47 -0
  95. data/vendor/cereal/include/cereal/types/valarray.hpp +89 -0
  96. data/vendor/cereal/include/cereal/types/variant.hpp +109 -0
  97. data/vendor/cereal/include/cereal/types/vector.hpp +112 -0
  98. data/vendor/cereal/include/cereal/version.hpp +52 -0
  99. data/vendor/isotree/LICENSE +1 -1
  100. data/vendor/isotree/README.md +2 -1
  101. data/vendor/isotree/src/RcppExports.cpp +44 -4
  102. data/vendor/isotree/src/Rwrapper.cpp +141 -51
  103. data/vendor/isotree/src/crit.cpp +1 -1
  104. data/vendor/isotree/src/dealloc.cpp +1 -1
  105. data/vendor/isotree/src/dist.cpp +6 -6
  106. data/vendor/isotree/src/extended.cpp +5 -5
  107. data/vendor/isotree/src/fit_model.cpp +30 -19
  108. data/vendor/isotree/src/helpers_iforest.cpp +26 -11
  109. data/vendor/isotree/src/impute.cpp +7 -7
  110. data/vendor/isotree/src/isoforest.cpp +7 -7
  111. data/vendor/isotree/src/isotree.hpp +27 -5
  112. data/vendor/isotree/src/merge_models.cpp +1 -1
  113. data/vendor/isotree/src/mult.cpp +1 -1
  114. data/vendor/isotree/src/predict.cpp +20 -16
  115. data/vendor/isotree/src/serialize.cpp +1 -1
  116. data/vendor/isotree/src/sql.cpp +545 -0
  117. data/vendor/isotree/src/utils.cpp +36 -44
  118. metadata +98 -92
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6121fa6837526e05ea0124e69c189dea6e0c94a303a003ed8f5db5e8469e54b3
4
- data.tar.gz: eb4a955ffa47876af4ece7ce7006635af4b43e29475055cf0046d61cbb54d443
3
+ metadata.gz: a5974c65c4adc4fd79ee7770f324c906a2788534f3fe6f381d61711e7cdce78c
4
+ data.tar.gz: d401e7c5aaabcd5dcffd5e4f54d93ea4d0966698854e70d3475fd79a92e1e241
5
5
  SHA512:
6
- metadata.gz: 22eb873ac7cff7cd5a1e0e7c04e6c47e895c06d8e0e52cd5ee2c4ab31b652203737186fe2dfd84298ea9cdf5327bed0c4d22e67ec9fb787179eae978f922b127
7
- data.tar.gz: bcc62a52fa71bf6e3175108a473e834b8a730ea0a94dd8adc017057a23a9bf56d451c3b955b3aafacd2cd9e6f4c237c31ce4f7a3eefd4d11aaed25183def3b92
6
+ metadata.gz: d00de0c3902b4f7fd3e13e08f0738ec4daf8be173f60cf46f49318e76f5be3c4ef3edd925f83074e03b4fe181aa6384d43c749f5f72247cf08d44f6811a6fe80
7
+ data.tar.gz: 70195ae442c2e4762b2f900a82a891d8f991ace1e521d625f910a1b5e3482334a299674c255e1aebf855728ee169ab5886428baf6df9a5e436bc73f3aff6dda6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.1.5 (2021-03-14)
2
+
3
+ - Updated Isotree to 0.1.25
4
+ - Added support for exporting and importing models
5
+
1
6
  ## 0.1.4 (2020-08-22)
2
7
 
3
8
  - Added `missing_action`, `new_categ_action`, `categ_split_type`, `coefs`, `depth_imp`, and `weigh_imp_rows` options
data/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  BSD 2-Clause License
2
2
 
3
- Copyright (c) 2019, David Cortes
4
- Copyright (c) 2020, Andrew Kane
3
+ Copyright (c) 2020, David Cortes
4
+ Copyright (c) 2020-2021, Andrew Kane
5
5
  All rights reserved.
6
6
 
7
7
  Redistribution and use in source and binary forms, with or without
data/README.md CHANGED
@@ -6,7 +6,7 @@ Learn how [Isolation Forest](https://www.youtube.com/watch?v=RyFQXQf4w4w) works
6
6
 
7
7
  :deciduous_tree: Check out [OutlierTree](https://github.com/ankane/outliertree) for human-readable explanations of outliers
8
8
 
9
- [![Build Status](https://travis-ci.org/ankane/isotree.svg?branch=master)](https://travis-ci.org/ankane/isotree)
9
+ [![Build Status](https://github.com/ankane/isotree/workflows/build/badge.svg?branch=master)](https://github.com/ankane/isotree/actions)
10
10
 
11
11
  ## Installation
12
12
 
@@ -43,6 +43,18 @@ model.predict(data)
43
43
 
44
44
  Scores are between 0 and 1, with higher scores indicating outliers
45
45
 
46
+ Export the model
47
+
48
+ ```ruby
49
+ model.export_model("model.bin")
50
+ ```
51
+
52
+ Import a model
53
+
54
+ ```ruby
55
+ model = IsoTree::IsolationForest.import_model("model.bin")
56
+ ```
57
+
46
58
  ## Parameters
47
59
 
48
60
  Pass parameters - default values below
@@ -116,6 +128,15 @@ gem uninstall isotree --force
116
128
  bundle install
117
129
  ```
118
130
 
131
+ ## Deployment
132
+
133
+ Check out [Trove](https://github.com/ankane/trove) for deploying models.
134
+
135
+ ```sh
136
+ trove push model.bin
137
+ trove push model.bin.metadata
138
+ ```
139
+
119
140
  ## Reference
120
141
 
121
142
  Get the average isolation depth
data/ext/isotree/ext.cpp CHANGED
@@ -151,6 +151,7 @@ void Init_ext()
151
151
  double* col_weights = NULL;
152
152
  Imputer *imputer = NULL;
153
153
  bool impute_at_fit = false;
154
+ bool handle_interrupt = false;
154
155
 
155
156
  fit_iforest(
156
157
  NULL,
@@ -197,6 +198,7 @@ void Init_ext()
197
198
  weigh_imp_rows,
198
199
  impute_at_fit,
199
200
  random_seed,
201
+ handle_interrupt,
200
202
  nthreads
201
203
  );
202
204
 
@@ -257,5 +259,29 @@ void Init_ext()
257
259
  ret.push(outlier_scores[i]);
258
260
  }
259
261
  return ret;
262
+ })
263
+ .define_singleton_method(
264
+ "serialize_ext_isoforest",
265
+ *[](ExtIsoForest& iso, String path) {
266
+ #ifdef _MSC_VER
267
+ // TODO convert to wchar_t
268
+ throw std::runtime_error("Not supported on Windows yet");
269
+ #else
270
+ serialize_ext_isoforest(iso, path.c_str());
271
+ #endif
272
+ })
273
+ .define_singleton_method(
274
+ "deserialize_ext_isoforest",
275
+ *[](String path) {
276
+ ExtIsoForest iso;
277
+
278
+ #ifdef _MSC_VER
279
+ // TODO convert to wchar_t
280
+ throw std::runtime_error("Not supported on Windows yet");
281
+ #else
282
+ deserialize_ext_isoforest(iso, path.c_str());
283
+ #endif
284
+
285
+ return iso;
260
286
  });
261
287
  }
@@ -1,7 +1,6 @@
1
1
  require "mkmf-rice"
2
2
 
3
- # TODO add -D_ENABLE_CEREAL
4
- $CXXFLAGS += " -std=c++11 -D_USE_MERSENNE_TWISTER"
3
+ $CXXFLAGS += " -std=c++11 -D_USE_MERSENNE_TWISTER -D_ENABLE_CEREAL"
5
4
 
6
5
  apple_clang = RbConfig::CONFIG["CC_VERSION_MESSAGE"] =~ /apple clang/i
7
6
 
@@ -13,10 +12,11 @@ end
13
12
 
14
13
  ext = File.expand_path(".", __dir__)
15
14
  isotree = File.expand_path("../../vendor/isotree/src", __dir__)
15
+ cereal = File.expand_path("../../vendor/cereal/include", __dir__)
16
16
 
17
17
  exclude = %w(Rwrapper.cpp RcppExports.cpp)
18
18
  $srcs = Dir["{#{ext},#{isotree}}/*.{cc,cpp}"].reject { |f| exclude.include?(File.basename(f)) }
19
- $INCFLAGS << " -I#{isotree}"
19
+ $INCFLAGS << " -I#{isotree} -I#{cereal}"
20
20
  $VPATH << isotree
21
21
 
22
22
  create_makefile("isotree/ext")
data/lib/isotree.rb CHANGED
@@ -3,6 +3,7 @@ require "isotree/ext"
3
3
 
4
4
  # stdlib
5
5
  require "etc"
6
+ require "json"
6
7
 
7
8
  # modules
8
9
  require "isotree/dataset"
@@ -48,7 +48,7 @@ module IsoTree
48
48
  end
49
49
 
50
50
  def predict(x, output: "score")
51
- raise "Not fit" unless @ext_iso_forest
51
+ check_fit
52
52
 
53
53
  x = Dataset.new(x)
54
54
  prep_predict(x)
@@ -66,8 +66,83 @@ module IsoTree
66
66
  Ext.predict_iforest(@ext_iso_forest, options)
67
67
  end
68
68
 
69
+ # same format as Python so models are compatible
70
+ def export_model(path)
71
+ check_fit
72
+
73
+ File.write("#{path}.metadata", JSON.pretty_generate(export_metadata))
74
+ Ext.serialize_ext_isoforest(@ext_iso_forest, path)
75
+ end
76
+
77
+ def self.import_model(path)
78
+ model = new
79
+ metadata = JSON.parse(File.read("#{path}.metadata"))
80
+ model.send(:import_metadata, metadata)
81
+ model.instance_variable_set(:@ext_iso_forest, Ext.deserialize_ext_isoforest(path))
82
+ model
83
+ end
84
+
69
85
  private
70
86
 
87
+ def export_metadata
88
+ data_info = {
89
+ ncols_numeric: @numeric_columns.size,
90
+ ncols_categ: @categorical_columns.size,
91
+ cols_numeric: @numeric_columns,
92
+ cols_categ: @categorical_columns,
93
+ cat_levels: @categorical_columns.map { |v| @categories[v].keys }
94
+ }
95
+
96
+ # Ruby-specific
97
+ data_info[:sym_numeric] = @numeric_columns.map { |v| v.is_a?(Symbol) }
98
+ data_info[:sym_categ] = @categorical_columns.map { |v| v.is_a?(Symbol) }
99
+
100
+ model_info = {
101
+ ndim: @ndim,
102
+ nthreads: @nthreads,
103
+ build_imputer: false
104
+ }
105
+
106
+ params = {}
107
+ PARAM_KEYS.each do |k|
108
+ params[k] = instance_variable_get("@#{k}")
109
+ end
110
+
111
+ {
112
+ data_info: data_info,
113
+ model_info: model_info,
114
+ params: params
115
+ }
116
+ end
117
+
118
+ def import_metadata(metadata)
119
+ data_info = metadata["data_info"]
120
+ model_info = metadata["model_info"]
121
+ params = metadata["params"]
122
+
123
+ # Ruby-specific
124
+ sym_numeric = data_info["sym_numeric"].to_a
125
+ sym_categ = data_info["sym_categ"].to_a
126
+
127
+ @numeric_columns = data_info["cols_numeric"].map.with_index { |v, i| sym_numeric[i] ? v.to_sym : v }
128
+ @categorical_columns = data_info["cols_categ"].map.with_index { |v, i| sym_categ[i] ? v.to_sym : v }
129
+ @categories = {}
130
+ @categorical_columns.zip(data_info["cat_levels"]) do |col, levels|
131
+ @categories[col] = levels.map.with_index.to_h
132
+ end
133
+
134
+ @ndim = model_info["ndim"]
135
+ @nthreads = model_info["nthreads"]
136
+
137
+ PARAM_KEYS.each do |k|
138
+ instance_variable_set("@#{k}", params[k.to_s])
139
+ end
140
+ end
141
+
142
+ def check_fit
143
+ raise "Not fit" unless @ext_iso_forest
144
+ end
145
+
71
146
  def prep_fit(df)
72
147
  @numeric_columns = df.numeric_columns
73
148
  @categorical_columns = df.categorical_columns
@@ -141,6 +216,16 @@ module IsoTree
141
216
  options
142
217
  end
143
218
 
219
+ PARAM_KEYS = %i(
220
+ sample_size ntrees ntry max_depth
221
+ prob_pick_avg_gain prob_pick_pooled_gain
222
+ prob_split_avg_gain prob_split_pooled_gain min_gain
223
+ missing_action new_categ_action categ_split_type coefs depth_imp
224
+ weigh_imp_rows min_imp_obs random_seed all_perm coef_by_prop
225
+ weights_as_sample_prob sample_with_replacement penalize_range
226
+ weigh_by_kurtosis assume_full_distr
227
+ )
228
+
144
229
  def fit_options
145
230
  keys = %i(
146
231
  sample_size ntrees ndim ntry
@@ -1,3 +1,3 @@
1
1
  module IsoTree
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2014, Randolph Voorhies, Shane Grant
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * Neither the name of cereal nor the
12
+ names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,85 @@
1
+ cereal - A C++11 library for serialization
2
+ ==========================================
3
+
4
+ <img src="http://uscilab.github.io/cereal/assets/img/cerealboxside.png" align="right"/><p>cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone.</p>
5
+
6
+ ### cereal has great documentation
7
+
8
+ Looking for more information on how cereal works and its documentation? Visit [cereal's web page](http://USCiLab.github.com/cereal) to get the latest information.
9
+
10
+ ### cereal is easy to use
11
+
12
+ Installation and use of of cereal is fully documented on the [main web page](http://USCiLab.github.com/cereal), but this is a quick and dirty version:
13
+
14
+ * Download cereal and place the headers somewhere your code can see them
15
+ * Write serialization functions for your custom types or use the built in support for the standard library cereal provides
16
+ * Use the serialization archives to load and save data
17
+
18
+ ```cpp
19
+ #include <cereal/types/unordered_map.hpp>
20
+ #include <cereal/types/memory.hpp>
21
+ #include <cereal/archives/binary.hpp>
22
+ #include <fstream>
23
+
24
+ struct MyRecord
25
+ {
26
+ uint8_t x, y;
27
+ float z;
28
+
29
+ template <class Archive>
30
+ void serialize( Archive & ar )
31
+ {
32
+ ar( x, y, z );
33
+ }
34
+ };
35
+
36
+ struct SomeData
37
+ {
38
+ int32_t id;
39
+ std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;
40
+
41
+ template <class Archive>
42
+ void save( Archive & ar ) const
43
+ {
44
+ ar( data );
45
+ }
46
+
47
+ template <class Archive>
48
+ void load( Archive & ar )
49
+ {
50
+ static int32_t idGen = 0;
51
+ id = idGen++;
52
+ ar( data );
53
+ }
54
+ };
55
+
56
+ int main()
57
+ {
58
+ std::ofstream os("out.cereal", std::ios::binary);
59
+ cereal::BinaryOutputArchive archive( os );
60
+
61
+ SomeData myData;
62
+ archive( myData );
63
+
64
+ return 0;
65
+ }
66
+ ```
67
+
68
+ ### cereal has a mailing list
69
+
70
+ Either get in touch over <a href="mailto:cerealcpp@googlegroups.com">email</a> or [on the web](https://groups.google.com/forum/#!forum/cerealcpp).
71
+
72
+
73
+
74
+ ## cereal has a permissive license
75
+
76
+ cereal is licensed under the [BSD license](http://opensource.org/licenses/BSD-3-Clause).
77
+
78
+ ## cereal build status
79
+
80
+ * master : [![Build Status](https://travis-ci.com/USCiLab/cereal.svg?branch=master)](https://travis-ci.com/USCiLab/cereal)
81
+ [![Build status](https://ci.appveyor.com/api/projects/status/91aou6smj36or0vb/branch/master?svg=true)](https://ci.appveyor.com/project/AzothAmmo/cereal/branch/master)
82
+
83
+ ---
84
+
85
+ Were you looking for the Haskell cereal? Go <a href="https://github.com/GaloisInc/cereal">here</a>.
@@ -0,0 +1,351 @@
1
+ /*! \file access.hpp
2
+ \brief Access control and default construction */
3
+ /*
4
+ Copyright (c) 2014, Randolph Voorhies, Shane Grant
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ * Neither the name of cereal nor the
15
+ names of its contributors may be used to endorse or promote products
16
+ derived from this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
22
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+ #ifndef CEREAL_ACCESS_HPP_
30
+ #define CEREAL_ACCESS_HPP_
31
+
32
+ #include <type_traits>
33
+ #include <iostream>
34
+ #include <cstdint>
35
+ #include <functional>
36
+
37
+ #include "cereal/macros.hpp"
38
+ #include "cereal/specialize.hpp"
39
+ #include "cereal/details/helpers.hpp"
40
+
41
+ namespace cereal
42
+ {
43
+ // ######################################################################
44
+ //! A class that allows cereal to load smart pointers to types that have no default constructor
45
+ /*! If your class does not have a default constructor, cereal will not be able
46
+ to load any smart pointers to it unless you overload LoadAndConstruct
47
+ for your class, and provide an appropriate load_and_construct method. You can also
48
+ choose to define a member static function instead of specializing this class.
49
+
50
+ The specialization of LoadAndConstruct must be placed within the cereal namespace:
51
+
52
+ @code{.cpp}
53
+ struct MyType
54
+ {
55
+ MyType( int x ); // note: no default ctor
56
+ int myX;
57
+
58
+ // Define a serialize or load/save pair as you normally would
59
+ template <class Archive>
60
+ void serialize( Archive & ar )
61
+ {
62
+ ar( myX );
63
+ }
64
+ };
65
+
66
+ // Provide a specialization for LoadAndConstruct for your type
67
+ namespace cereal
68
+ {
69
+ template <> struct LoadAndConstruct<MyType>
70
+ {
71
+ // load_and_construct will be passed the archive that you will be loading
72
+ // from as well as a construct object which you can use as if it were the
73
+ // constructor for your type. cereal will handle all memory management for you.
74
+ template <class Archive>
75
+ static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct )
76
+ {
77
+ int x;
78
+ ar( x );
79
+ construct( x );
80
+ }
81
+
82
+ // if you require versioning, simply add a const std::uint32_t as the final parameter, e.g.:
83
+ // load_and_construct( Archive & ar, cereal::construct<MyType> & construct, std::uint32_t const version )
84
+ };
85
+ } // end namespace cereal
86
+ @endcode
87
+
88
+ Please note that just as in using external serialization functions, you cannot get
89
+ access to non-public members of your class by befriending cereal::access. If you
90
+ have the ability to modify the class you wish to serialize, it is recommended that you
91
+ use member serialize functions and a static member load_and_construct function.
92
+
93
+ load_and_construct functions, regardless of whether they are static members of your class or
94
+ whether you create one in the LoadAndConstruct specialization, have the following signature:
95
+
96
+ @code{.cpp}
97
+ // generally Archive will be templated, but it can be specific if desired
98
+ template <class Archive>
99
+ static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct );
100
+ // with an optional last parameter specifying the version: const std::uint32_t version
101
+ @endcode
102
+
103
+ Versioning behaves the same way as it does for standard serialization functions.
104
+
105
+ @tparam T The type to specialize for
106
+ @ingroup Access */
107
+ template <class T>
108
+ struct LoadAndConstruct
109
+ { };
110
+
111
+ // forward decl for construct
112
+ //! @cond PRIVATE_NEVERDEFINED
113
+ namespace memory_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
114
+ namespace boost_variant_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
115
+ //! @endcond
116
+
117
+ //! Used to construct types with no default constructor
118
+ /*! When serializing a type that has no default constructor, cereal
119
+ will attempt to call either the class static function load_and_construct
120
+ or the appropriate template specialization of LoadAndConstruct. cereal
121
+ will pass that function a reference to the archive as well as a reference
122
+ to a construct object which should be used to perform the allocation once
123
+ data has been appropriately loaded.
124
+
125
+ @code{.cpp}
126
+ struct MyType
127
+ {
128
+ // note the lack of default constructor
129
+ MyType( int xx, int yy );
130
+
131
+ int x, y;
132
+ double notInConstructor;
133
+
134
+ template <class Archive>
135
+ void serialize( Archive & ar )
136
+ {
137
+ ar( x, y );
138
+ ar( notInConstructor );
139
+ }
140
+
141
+ template <class Archive>
142
+ static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct )
143
+ {
144
+ int x, y;
145
+ ar( x, y );
146
+
147
+ // use construct object to initialize with loaded data
148
+ construct( x, y );
149
+
150
+ // access to member variables and functions via -> operator
151
+ ar( construct->notInConstructor );
152
+
153
+ // could also do the above section by:
154
+ double z;
155
+ ar( z );
156
+ construct->notInConstructor = z;
157
+ }
158
+ };
159
+ @endcode
160
+
161
+ @tparam T The class type being serialized
162
+ */
163
+ template <class T>
164
+ class construct
165
+ {
166
+ public:
167
+ //! Construct and initialize the type T with the given arguments
168
+ /*! This will forward all arguments to the underlying type T,
169
+ calling an appropriate constructor.
170
+
171
+ Calling this function more than once will result in an exception
172
+ being thrown.
173
+
174
+ @param args The arguments to the constructor for T
175
+ @throw Exception If called more than once */
176
+ template <class ... Args>
177
+ void operator()( Args && ... args );
178
+ // implementation deferred due to reliance on cereal::access
179
+
180
+ //! Get a reference to the initialized underlying object
181
+ /*! This must be called after the object has been initialized.
182
+
183
+ @return A reference to the initialized object
184
+ @throw Exception If called before initialization */
185
+ T * operator->()
186
+ {
187
+ if( !itsValid )
188
+ throw Exception("Object must be initialized prior to accessing members");
189
+
190
+ return itsPtr;
191
+ }
192
+
193
+ //! Returns a raw pointer to the initialized underlying object
194
+ /*! This is mainly intended for use with passing an instance of
195
+ a constructed object to cereal::base_class.
196
+
197
+ It is strongly recommended to avoid using this function in
198
+ any other circumstance.
199
+
200
+ @return A raw pointer to the initialized type */
201
+ T * ptr()
202
+ {
203
+ return operator->();
204
+ }
205
+
206
+ private:
207
+ template <class Ar, class TT> friend struct ::cereal::memory_detail::LoadAndConstructLoadWrapper;
208
+ template <class Ar, class TT> friend struct ::cereal::boost_variant_detail::LoadAndConstructLoadWrapper;
209
+
210
+ construct( T * p ) : itsPtr( p ), itsEnableSharedRestoreFunction( [](){} ), itsValid( false ) {}
211
+ construct( T * p, std::function<void()> enableSharedFunc ) : // g++4.7 ice with default lambda to std func
212
+ itsPtr( p ), itsEnableSharedRestoreFunction( enableSharedFunc ), itsValid( false ) {}
213
+ construct( construct const & ) = delete;
214
+ construct & operator=( construct const & ) = delete;
215
+
216
+ T * itsPtr;
217
+ std::function<void()> itsEnableSharedRestoreFunction;
218
+ bool itsValid;
219
+ };
220
+
221
+ // ######################################################################
222
+ //! A class that can be made a friend to give cereal access to non public functions
223
+ /*! If you desire non-public serialization functions within a class, cereal can only
224
+ access these if you declare cereal::access a friend.
225
+
226
+ @code{.cpp}
227
+ class MyClass
228
+ {
229
+ private:
230
+ friend class cereal::access; // gives access to the private serialize
231
+
232
+ template <class Archive>
233
+ void serialize( Archive & ar )
234
+ {
235
+ // some code
236
+ }
237
+ };
238
+ @endcode
239
+ @ingroup Access */
240
+ class access
241
+ {
242
+ public:
243
+ // ####### Standard Serialization ########################################
244
+ template<class Archive, class T> inline
245
+ static auto member_serialize(Archive & ar, T & t) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar))
246
+ { return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar); }
247
+
248
+ template<class Archive, class T> inline
249
+ static auto member_save(Archive & ar, T const & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar))
250
+ { return t.CEREAL_SAVE_FUNCTION_NAME(ar); }
251
+
252
+ template<class Archive, class T> inline
253
+ static auto member_save_non_const(Archive & ar, T & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar))
254
+ { return t.CEREAL_SAVE_FUNCTION_NAME(ar); }
255
+
256
+ template<class Archive, class T> inline
257
+ static auto member_load(Archive & ar, T & t) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar))
258
+ { return t.CEREAL_LOAD_FUNCTION_NAME(ar); }
259
+
260
+ template<class Archive, class T> inline
261
+ static auto member_save_minimal(Archive const & ar, T const & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
262
+ { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); }
263
+
264
+ template<class Archive, class T> inline
265
+ static auto member_save_minimal_non_const(Archive const & ar, T & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
266
+ { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); }
267
+
268
+ template<class Archive, class T, class U> inline
269
+ static auto member_load_minimal(Archive const & ar, T & t, U && u) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)))
270
+ { return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)); }
271
+
272
+ // ####### Versioned Serialization #######################################
273
+ template<class Archive, class T> inline
274
+ static auto member_serialize(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version))
275
+ { return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version); }
276
+
277
+ template<class Archive, class T> inline
278
+ static auto member_save(Archive & ar, T const & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version))
279
+ { return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); }
280
+
281
+ template<class Archive, class T> inline
282
+ static auto member_save_non_const(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version))
283
+ { return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); }
284
+
285
+ template<class Archive, class T> inline
286
+ static auto member_load(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar, version))
287
+ { return t.CEREAL_LOAD_FUNCTION_NAME(ar, version); }
288
+
289
+ template<class Archive, class T> inline
290
+ static auto member_save_minimal(Archive const & ar, T const & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
291
+ { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); }
292
+
293
+ template<class Archive, class T> inline
294
+ static auto member_save_minimal_non_const(Archive const & ar, T & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
295
+ { return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); }
296
+
297
+ template<class Archive, class T, class U> inline
298
+ static auto member_load_minimal(Archive const & ar, T & t, U && u, const std::uint32_t version) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version))
299
+ { return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version); }
300
+
301
+ // ####### Other Functionality ##########################################
302
+ // for detecting inheritance from enable_shared_from_this
303
+ template <class T> inline
304
+ static auto shared_from_this(T & t) -> decltype(t.shared_from_this());
305
+
306
+ // for placement new
307
+ template <class T, class ... Args> inline
308
+ static void construct( T *& ptr, Args && ... args )
309
+ {
310
+ new (ptr) T( std::forward<Args>( args )... );
311
+ }
312
+
313
+ // for non-placement new with a default constructor
314
+ template <class T> inline
315
+ static T * construct()
316
+ {
317
+ return new T();
318
+ }
319
+
320
+ template <class T> inline
321
+ static std::false_type load_and_construct(...)
322
+ { return std::false_type(); }
323
+
324
+ template<class T, class Archive> inline
325
+ static auto load_and_construct(Archive & ar, ::cereal::construct<T> & construct) -> decltype(T::load_and_construct(ar, construct))
326
+ {
327
+ T::load_and_construct( ar, construct );
328
+ }
329
+
330
+ template<class T, class Archive> inline
331
+ static auto load_and_construct(Archive & ar, ::cereal::construct<T> & construct, const std::uint32_t version) -> decltype(T::load_and_construct(ar, construct, version))
332
+ {
333
+ T::load_and_construct( ar, construct, version );
334
+ }
335
+ }; // end class access
336
+
337
+ // ######################################################################
338
+ // Deferred Implementation, see construct for more information
339
+ template <class T> template <class ... Args> inline
340
+ void construct<T>::operator()( Args && ... args )
341
+ {
342
+ if( itsValid )
343
+ throw Exception("Attempting to construct an already initialized object");
344
+
345
+ ::cereal::access::construct( itsPtr, std::forward<Args>( args )... );
346
+ itsEnableSharedRestoreFunction();
347
+ itsValid = true;
348
+ }
349
+ } // namespace cereal
350
+
351
+ #endif // CEREAL_ACCESS_HPP_