Theolizer  Version.1.2.0
serializer for C++ / Do you want to update your classes easily ?
7d.destinations.h
[詳解]
1 //############################################################################
2 /*!
3  @brief ドキュメント・ファイル-使用方法(個別)
4  @ingroup Documents
5  @file 7d.destinations.h
6  @author Yoshinori Tahara
7  @date 2017/01/23 Created
8 */
9 /*
10  © 2016 Theoride Technology (http://theolizer.com/) All Rights Reserved.
11  "Theolizer" is a registered trademark of Theoride Technology.
12 
13  "Theolizer" License
14  In the case where you are in possession of a valid “Theolizer” License,
15  you may use this file in accordance with the terms and conditions of
16  the use license determined by Theoride Technology.
17 
18  General Public License Version 3 ("GPLv3")
19  You may use this file in accordance with the terms and conditions of
20  GPLv3 published by Free Software Foundation.
21  Please confirm the contents of GPLv3 at https://www.gnu.org/licenses/gpl.txt .
22  A copy of GPLv3 is also saved in a LICENSE.TXT file.
23 
24  商用ライセンス
25  あなたが有効なTheolizer商用ライセンスを保持している場合、
26  セオライド テクノロジーの定める使用許諾書の条件に従って、
27  このファイルを取り扱うことができます。
28 
29  General Public License Version 3(以下GPLv3)
30  Free Software Foundationが公表するGPLv3の使用条件に従って、
31  あなたはこのファイルを取り扱うことができます。
32  GPLv3の内容を https://www.gnu.org/licenses/gpl.txt にて確認して下さい。
33  またGPLv3のコピーをLICENSE.TXTファイルにおいてます。
34 */
35 //############################################################################
36 
37 /*!
38  @page Destinations 保存先指定について
39 ここでは、保存先指定について説明します。
40 
41 <br>
42 //############################################################################
43 @section HowToSpecifySaving 1.指定方法
44 //############################################################################
45 
46 @subsection HowToSpecifySaving11 1-1.シリアライズの有無指定
47 クラスや構造体に含まれるメンバ変数をシリアライズするかしないか指定できます。
48 指定方法は2種類あります。
49 侵入型半自動クラスについて指定可能です。(*1)
50 
51 1. デフォルト保存クラス:メンバ変数をデフォルトでシリアライズするクラス<br>
52 シリアライズ指定していないメンバ変数はシリアライズ対象となります。<br>
53 
54 2. デフォルト非保存クラス:メンバ変数をデフォルトではシリアライズしないクラス
55 シリアライズ指定していないメンバ変数はシリアライズ対象としません。
56 
57 <div style="padding: 10px; margin-bottom: 10px; border: 1px solid #333333; border-radius: 10px; background-color: #d0d0d0;">
58 <b>(*1)</b><br>
59 非侵入型完全自動クラスのメンバ変数への指定も可能ですが、クラス定義ソースの修正が必要であるため、現状では意味がありません(侵入する必要がある)ので、非サポートとします。
60 </div>
61 
62 @subsection HowToSpecifySaving12 1-2.保存先指定
63 Theolizerは、クラスを複数のファイルや通信先に分割して保存/回復できます。<br>
64 そのためには<br>
65 
66 1. 保存先を定義する<br>
67 特殊なenum型を定義するイメージです。
68 
69 2. 侵入型半自動クラスのメンバ変数に保存先を指定する。
70 複数の保存先を指定できます。
71 
72 3. シリアライザをコンストラクトする際に保存先を指定する。
73 通常は保存先を1つ指定しますが、複数指定することも可能です。
74 
75 これにより、2と3で指定された保存先集合間に共通な保存先がある場合、2のメンバ変数が3で生成したシリアライザに渡したstreamへ保存、streamから回復されます。
76 
77 なお、両者とも保存先を明示的に指定しなかった場合、「保存先無し」の意味ではなく「全ての保存先」の意味になります。2に保存先を明示的に指定していない場合、3でどの保存先を指定しても常にシリアライズされます。また、3で保存先を明示的に指定していない場合、2にどの保存先を指定していても常にシリアライズされます。
78 
79 @subsection HowToSpecifySaving13 1-3.指定方法
80 
81 @subsubsection HowToSpecifySaving131 1-3-1.保存先の定義方法
82 THEOLIZER_DESTINATIONS()マクロで定義します。<br>
83 通常のenum型の定義と同じく、保存先を用いる場所全てより前に定義して下さい。<br>
84 構文は次の通りです。<br>
85 
86 THEOLIZER_DESTINATIONS(前THEOLIZER_DESTINATIONS()マクロ最後の保存先, 保存先0, 保存先1, ... );<br>
87 
88 マクロ展開の都合上、THEOLIZER_DESTINATIONS()1つで最大8つの保存先を定義できます。8つを超える保存先を定義したい場合、THEOLIZER_DESTINATIONS()を続けて記述して下さい。例えは保存先を12個定義したい場合は、下記のようになります。
89 
90 @code
91 THEOLIZER_DESTINATIONS(All, Dest0, Dest1, Dest2, Dest3, Dest4, Dest5, Dest6, Dest7);
92 THEOLIZER_DESTINATIONS(Dest7, Dest8, Dest9, Dest10, Dest11);
93 @endcode
94 シンボルはAll以外を自由に使って頂いて良いです。文字はenum型のシンボル名に使えるものを全て使えます。<br>
95 なお、Allは事前定義しています。「全ての保存先」の意味を持ち、内部的に使用しています。
96 
97 また、各保存先はtheolizer::destination名前空間に配置されます。また、この名前空間にはtheolizerDの別名を定義しています。例えばDest1はtheolizerD::Dest1として指定します。
98 
99 @subsubsection HowToSpecifySaving132 1-3-2.デフォルト保存/非保存クラスの指定方法
100 @ref HalfAutoClass をTHEOLIZER_INTRUSIVE()マクロで指定しますが、その先頭パラメータで指定します。<br>
101 デフォルト保存クラス :THEOLIZER_INTRUSIVE(<b>CS</b>, (クラス名), バージョン番号);<br>
102 デフォルト非保存クラス:THEOLIZER_INTRUSIVE(<b>CN</b>, (クラス名), バージョン番号);<br>
103 
104 @subsubsection HowToSpecifySaving133 1-3-3.メンバ変数への指定方法
105 メンバ変数への指定にはTHEOLIZER_ANNOTATE()マクロをメンバ変数定義の最後、;の前に書きます。<br>
106 保存しない:THEOLIZER_ANNOTATE(<b>FN</b>)<br>
107 保存する :THEOLIZER_ANNOTATE(<b>FS</b>)<br>
108 保存し、保存先も指定する:THEOLIZER_ANNOTATE(FS:`<保存先のリスト>`))<br>
109 
110 @subsubsection HowToSpecifySaving134 1-3-4.シリアライザへの指定方法
111 
112 `シリアライザ名<保存先のリスト> インスタンス名(パラメータ);`の構文で指定します。
113 
114 @subsection HowToSpecifySaving14 1-4.サンプル・ソース
115 
116 @subsubsection HowToSpecifySaving141 1-4-1.保存の有無指定
117 
118 <br>
119 <b>デフォルト保存クラス例</b> (source/reference_and_test/basic2/test_destinations.h)<br>
120 
121 @snippet basic2/test_destinations.h DefaultSave
122 
123 <b>説明:</b>
124 |メンバ変数|指定|説明|
125 |----------|----|----|
126 |mNoAnnotate|指定無し|デフォルト保存クラスなので、シリアライズされます|
127 |mAnnotateSave|保存する|シリアライズされます|
128 |mAnnotateNonSave|保存しない|シリアライズされません|
129 
130 
131 <b>デフォルト非保存クラス例</b> (source/reference_and_test/basic2/test_destinations.h)<br>
132 
133 @snippet basic2/test_destinations.h DefaultNonSave
134 
135 <b>説明:</b>
136 |メンバ変数|指定|説明|
137 |----------|----|----|
138 |mNoAnnotate|指定無し|デフォルト非保存クラスなので、シリアライズされません|
139 |mAnnotateSave|保存する|シリアライズされます|
140 |mAnnotateNonSave|保存しない|シリアライズされません|
141 
142 <br>
143 <b>保存と回復ソース:(source/reference_and_test/basic2/test_destinations.cpp)</b><br>
144 
145 @snippet basic2/test_destinations.cpp DefaultSave
146 
147 以上の実行で保存されるファイルは次の通りです。
148 @code
149 
150 {
151  "SerialzierName":"JsonTheolizer",
152  "GlobalVersionNo":1,
153  "TypeInfoList":[1]
154 }
155 {
156  "mNoAnnotate":100,
157  "mAnnotateSave":200
158 }
159 {
160  "mAnnotateSave":2000
161 }
162 
163 @endcode
164 
165 <br>
166 @subsubsection HowToSpecifySaving142 1-4-2.保存先指定
167 
168 保存先を指定したクラスをポリモーフィックに保存/回復するサンプルを示します。保存先をマスター・ファイルと取引ファイルへ分割するケースを使います。できるだけ小さなサンプルにしていますので少し違和感があると思いますが、雰囲気は掴めると思います。
169 
170 なお、このように基底クラスへのポインタから保存/回復することもできますし、普通にクラス・インスタンスを直接保存/回復することもできます。
171 
172 <b>保存先の定義</b> (source/reference_and_test/basic/common.h)<br>
173 
174 @dontinclude basic/common.h
175 @skip THEOLIZER_DESTINATIONS
176 @until );
177 
178 <b>クラス例</b> (source/reference_and_test/basic2/test_destinations.h)<br>
179 
180 顧客管理を想定してます。BaseCustomerを基底クラスとし、法人の顧客をCorporateCustomer、個人の顧客をIndividualCustomerで管理する想定です。基底クラスで名前を記録し、派生クラスはそれぞれ、資本金と売掛金残高、誕生日と提供したポイント数を記録します。名前と資本金と誕生日はマスター・ファイル、売掛金とポイント数は取引ファイルへ保存します。
181 
182 @snippet basic2/test_destinations.h DestinationPoly
183 
184 <b>保存ソース:(source/reference_and_test/basic2/test_destinations.cpp)</b><br>
185 
186 @snippet basic2/test_destinations.cpp save DestinationPoly
187 
188 これにて次のように保存されます。
189 
190 <b>tutorise_destinationsMaster.json:</b><br>
191 @code
192 
193 {
194  "SerialzierName":"JsonTheolizer",
195  "GlobalVersionNo":1,
196  "TypeInfoList":[1]
197 }
198 [
199  2,
200  [
201  [1,"CorporateCustomer",{
202  "(BaseCustomer)":{
203  "mName":"Theoride Technology"
204  },
205  "mCapitalStock":2000000
206  }]
207  ],
208  [
209  [2,"IndividualCustomer",{
210  "(BaseCustomer)":{
211  "mName":"Yossi Tahara"
212  },
213  "mBirthday":"1962\/01\/01"
214  }]
215  ]
216 ]
217 
218 @endcode
219 
220 誕生日が`\`でエスケープされているのは、Jsonの仕様によるものです。
221 
222 <b>tutorise_destinationsTrade.json:</b><br>
223 @code
224 
225 {
226  "SerialzierName":"JsonTheolizer",
227  "GlobalVersionNo":1,
228  "TypeInfoList":[1]
229 }
230 [
231  2,
232  [
233  [1,"CorporateCustomer",{
234  "(BaseCustomer)":{
235  },
236  "mTradeAccounts":500000
237  }]
238  ],
239  [
240  [2,"IndividualCustomer",{
241  "(BaseCustomer)":{
242  },
243  "mPoint":12000
244  }]
245  ]
246 ]
247 
248 @endcode
249 
250 <b>保存データのまとめ:</b><br>
251 
252 |クラス|メンバ変数|内容|保存先|
253 |------|----------|----|------|
254 |CorporateCustomer|mName|"Theoride Technology"|マスター・ファイル|
255 ||mCapitalStock|2,000,000|マスター・ファイル|
256 ||mTradeAccounts|500,000|取引ファイル|
257 |IndividualCustomer|mName|"Yossi Tahara"|マスター・ファイル|
258 ||mBirthday|1962/01/01|マスター・ファイル|
259 ||mPoint|12,000|取引ファイル|
260 
261 <br>
262 <b>回復ソース:(source/reference_and_test/basic2/test_destinations.cpp)</b><br>
263 
264 @snippet basic2/test_destinations.cpp load DestinationPoly
265 
266 THEOLIZER_PROCESS(aSerializerMaster, aList);にてマスター・ファイルから回復してます。<br>
267 THEOLIZER_PROCESS(aSerializerTrade, aList);にて取引ファイルから同じインスタンスへ回復してます。<br>
268 これにより分割して保存したクラスを合成して回復します。<br>
269 以上により回復したデータは次のようになります。
270 
271 @code
272 
273 {
274  "SerialzierName":"JsonTheolizer",
275  "GlobalVersionNo":1,
276  "TypeInfoList":[1]
277 }
278 [
279  2,
280  [
281  [1,"CorporateCustomer",{
282  "(BaseCustomer)":{
283  "mName":"Theoride Technology"
284  },
285  "mCapitalStock":2000000,
286  "mTradeAccounts":500000
287  }]
288  ],
289  [
290  [2,"IndividualCustomer",{
291  "(BaseCustomer)":{
292  "mName":"Yossi Tahara"
293  },
294  "mBirthday":"1962\/01\/01",
295  "mPoint":12000
296  }]
297  ]
298 ]
299 
300 @endcode
301 
302 <b>回復結果のまとめ:</b><br>
303 
304 |クラス|メンバ変数|内容|
305 |------|----------|----|
306 |CorporateCustomer|mName|"Theoride Technology"|
307 ||mCapitalStock|2,000,000|
308 ||mTradeAccounts|500,000|
309 |IndividualCustomer|mName|"Yossi Tahara"|
310 ||mBirthday|1962/01/01|
311 ||mPoint|12,000|
312 
313 <br>
314 @subsubsection HowToSpecifySaving143 1-4-3.間違い易い指定について
315 クラス・インスタンスをメンバ変数として持つクラスについて、注意点があります。他のクラスを含むクラスを親クラス、他のクラスに含まれるクラスを子クラスとします。<br>
316 この時、親クラス側で子クラス型のメンバ変数に保存先をAと指定し、子クラスのメンバ変数xに保存先をBとしていた場合、親クラスをBへ保存した時にxが保存されません。これは仕様ですがミスし易い部分です。<br>
317 
318 以下具体例で説明します。<br>
319 親クラスをDestinationParent、子クラスをDestinationChildとします。<br>
320 親クラスはDestinationChild型のmDestinationChildメンバ変数を持っていて、これは保存先としてDestAを指定します。子クラスは2つのメンバ変数mAnnotateAとmAnnotateBを持ち、それぞれ保存先としてDestA、DestBを指定します。<br>
321 
322 <b>保存先の定義</b> (source/reference_and_test/basic/common.h)<br>
323 
324 @dontinclude basic/common.h
325 @skip THEOLIZER_DESTINATIONS
326 @skip );
327 @skip THEOLIZER_DESTINATIONS
328 @until );
329 
330 <b>クラス例</b> (source/reference_and_test/basic2/test_destinations.h)<br>
331 
332 @snippet basic2/test_destinations.h DestinationChild/Parent
333 
334 <b>保存ソース:(source/reference_and_test/basic2/test_destinations.cpp)</b><br>
335 
336 これにて次のように保存されます。
337 
338 <b>tutorise_destinationsA.json:</b><br>
339 @code
340 
341 {
342  "SerialzierName":"JsonTheolizer",
343  "GlobalVersionNo":1,
344  "TypeInfoList":[1]
345 }
346 {
347  "mAnnotateA":100,
348  "mDestinationChild":{
349  "mAnnotateA":300
350  }
351 }
352 
353 @endcode
354 
355 mDestinationChildのmAnnotateBはDestBのみ保存なので、tutorise_destinationsA.jsonには保存されません。
356 
357 <b>tutorise_destinationsB.json:</b><br>
358 @code
359 
360 {
361  "SerialzierName":"JsonTheolizer",
362  "GlobalVersionNo":1,
363  "TypeInfoList":[1]
364 }
365 {
366  "mAnnotateB":200
367 }
368 
369 @endcode
370 
371 tutorise_destinationsB.jsonには、指示通りmDestinationChildが含まれません。
372 上記のどちらにもmDestinationChildのmAnnotateBが保存されないことに注意して下さい。
373 
374 <b>回復ソース:(source/reference_and_test/basic2/test_destinations.cpp)</b><br>
375 
376 @snippet basic2/test_destinations.cpp load DestinationChild/Parent
377 
378 以上により回復したデータは次のようになります。<b>mDestinationChild.mAnnotateBが0のままです。</b>
379 これはミスを誘発し易いですので、子クラスに保存先を指定する際は慎重に行って下さい。<br>
380 なお、基底クラスには親クラス側に保存先を指定できていため、同様のミスは発生しません。
381 
382 @code
383 
384 {
385  "SerialzierName":"JsonTheolizer",
386  "GlobalVersionNo":1,
387  "TypeInfoList":[1]
388 }
389 {
390  "mAnnotateA":100,
391  "mAnnotateB":200,
392  "mDestinationChild":{
393  "mAnnotateA":300,
394  "mAnnotateB":0
395  }
396 }
397 
398 @endcode
399 
400 <br>
401 //############################################################################
402 @section TestSpecifySaving 2.網羅的な使用例(自動テスト)の説明
403 //############################################################################
404 
405 @subsection TestSpecifySaving21 2-1.保存の有無指定のテスト
406 これは使い方説明で用いたDefaultSaveとDefaultNonSaveの保存/回復を、全てのシリアライザ、全ての書式でテストしています。
407 
408 <b>source/reference_and_test/basic2/test_destinations.cpp</b>でテスト関数を定義してます。<br>
409 
410 1. 保存処理<br>
411 template<class tSerializer><br>
412 void saveSpecifySaving(tSerializer& iSerializer)の前2つ<br>
413 <br>
414 
415 2. 回復処理<br>
416 template<class tSerializer><br>
417 void loadSpecifySaving(tSerializer& iSerializer)の前2つ<br>
418 
419 <br>
420 @subsection TestSpecifySaving22 2-2.保存先指定のテスト
421 <b>source/reference_and_test/basic2/test_destinations.h</b>でテスト用のクラスを定義してます。<br>
422 
423 DestinationTestChildクラスとDestinationTestParentクラスを用います。両方ともデフォルト保存型です。<br>
424 前者はint型、後者はDestinationTestChild型のメンバ変数を下記のように持ちます。
425 
426 |メンバ変数|保存先指定|
427 |----------|----------|
428 |mNoAnnotate|保存先指定無し|
429 |mAnnotateA|DestAへ保存|
430 |mAnnotateB|DestBへ保存|
431 |mAnnotateAB|DestAとDestBの両方へ保存|
432 |mAnnotateC|DestCへ保存|
433 |mAnnotateN|非保存指定|
434 
435 <b>source/reference_and_test/basic2/test_destinations.cpp</b>でテスト関数を定義してます。<br>
436 下記組み合わせでテストしています。
437 
438 |シリアライザ|テストしている関数|
439 |------------|------------------|
440 |保存先指定無し|saveSpecifySaving()とloadSpecifySaving()内の最後の1つ|
441 |DestAのみ|saveDestinations()の先頭で保存し、loadDestinations()で単独回復|
442 |DestBのみ|saveDestinations()の2番目で保存し、loadDestinations()で合成回復|
443 |DestAとDestB|saveDestinations()とloadDestinations()の最後の1つ|
444 
445 以上により、下記組み合わせのテストを行っています。
446 
447 |シリアライザ|メンバ変数|保存先指定されたメンバ変数内のメンバ変数|
448 |------------|----------|----------------------------------------|
449 |指定無し|指定無し|指定無し(mNoAnnotate)|
450 ||単独指定有り|親と同じ指定有り(mAnnotateA, mAnnotateB)|
451 |||親と一部同じ複数指定有り(mAnnotateAB)|
452 |||親と異なる指定有り(mAnnotateC)|
453 |||保存無し指定(mAnnotateN)|
454 ||複数指定有り|上記と同じセット|
455 ||保存無し指定|上記と同じセット|
456 |単独指定有り(DestA)|上記と同じセット|上記と同じセット|
457 |単独指定有りで合成回復(DestB)|上記と同じセット|上記と同じセット|
458 |複数指定(DestA,DestB)|上記と同じセット|上記と同じセット|
459 
460 */