-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathncbind.hpp
2380 lines (2055 loc) · 87.2 KB
/
ncbind.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef _ncbind_hpp_
#define _ncbind_hpp_
#include <windows.h>
#include "tp_stub.h"
#include "ncb_invoke.hpp"
////////////////////////////////////////
// ログ出力用マクロ
#define NCB_WARN(n) TVPAddLog(ttstr(n))
#define NCB_WARN_2(a,b) TVPAddLog(ttstr(a) + ttstr(b))
#define NCB_WARN_W(str) NCB_WARN(TJS_W(str))
#if (defined(DEBUG) || defined(_DEBUG))
#define NCB_LOG(n) NCB_WARN(n)
#define NCB_LOG_2(a,b) NCB_WARN_2(a,b)
#define NCB_LOG_W(str) NCB_WARN_W(str)
#else
#define NCB_LOG_VOID ((void)0)
#define NCB_LOG(n) NCB_LOG_VOID
#define NCB_LOG_2(a,b) NCB_LOG_VOID
#define NCB_LOG_W(str) NCB_LOG_VOID
#endif
////////////////////////////////////////
// 共通型定義
struct ncbTypedefs {
typedef tjs_char const* NameT;
typedef tjs_uint32 FlagsT;
typedef tjs_int32 IdentT;
typedef MethodCaller CallerT;
typedef tTJSNativeInstanceType InstanceTypeT;
typedef tTJSNativeClassForPlugin ClassObjectT;
/// 型の受け渡しで使用
template <typename T> struct Tag { typedef T Type; };
/// 場合わけで使用
template <int N> struct NumTag { enum { n = N }; };
template <bool B> struct BoolTag { enum { b = B }; };
// tTJSVariant::Type() ラッパ (ここでいいのか微妙だけど)
static inline tTJSVariantType GetVariantType(tTJSVariant const &var) { return (const_cast<tTJSVariant*>(&var))->Type(); }
// static inline tTJSVariantType GetVariantType(tTJSVariant &var) { return var.Type(); }
// コールバック型
typedef tTJSNativeClassMethodCallback CallbackT;
// インスタンスに変換して渡すコールバック
template <class T>
struct CallbackWithInstance {
typedef tjs_error (TJS_INTF_METHOD *Type)(tTJSVariant *result, tjs_int numparams, tTJSVariant **param, T *nativeInstance);
};
template <typename A, typename B> struct TypeEqual { enum { NotEqual, Result = false }; };
template <typename A> struct TypeEqual<A, A> { enum { Equal, Result = true }; };
template <bool F, int A, int B> struct IntSelect { enum { Result = B }; };
template < int A, int B> struct IntSelect< true, A, B> { enum { Result = A }; };
template <bool F, typename A, typename B> struct TypeSelect { typedef B Result; };
template < typename A, typename B> struct TypeSelect<true, A, B> { typedef A Result; };
template <bool F, typename ERR> struct TypeAssert { typedef void Result; };
template < typename ERR> struct TypeAssert<true, ERR> { typedef typename ERR::CompileError Result; };
};
/// サブクラスフラグ
template <class T>
struct ncbSubClassCheck { enum { IsSubClass = false }; };
////////////////////////////////////////
/// NativeClass 名前/ID/クラスオブジェクト保持用
template <class T>
struct ncbClassInfo {
typedef T NativeClassT;
typedef ncbTypedefs::NameT NameT;
typedef ncbTypedefs::IdentT IdentT;
typedef ncbTypedefs::ClassObjectT ClassObjectT;
/// プロパティ取得
static inline NameT GetName() { return _info.name; }
static inline IdentT GetID() { return _info.id; }
static inline ClassObjectT *GetClassObject() { return _info.obj; }
static inline bool IsSubClass() { return ncbSubClassCheck<NativeClassT>::IsSubClass; }
/// イニシャライザ
static inline bool Set(NameT name, IdentT id, ClassObjectT *obj) {
if (_info.initialized) return false;
_info.name = name;
_info.id = id;
_info.obj = obj;
return (_info.initialized = true);
}
/// 再初期化
static inline void Clear() {
_info.name = 0;
_info.id = 0;
_info.obj = 0;
_info.initialized = false;
}
private:
typedef struct info {
info() : initialized(false), name(0), id(0), obj(0) {}
bool initialized;
NameT name;
IdentT id;
ClassObjectT *obj;
} InfoT;
static InfoT _info;
};
template <> struct ncbClassInfo<void> {};
template <class T> typename ncbClassInfo<T>::InfoT ncbClassInfo<T>::_info;
////////////////////////////////////////
/// インスタンスアダプタ
template <class T>
struct ncbInstanceAdaptor : public tTJSNativeInstance {
typedef T NativeClassT;
typedef ncbInstanceAdaptor<NativeClassT> AdaptorT;
typedef ncbClassInfo<NativeClassT> ClassInfoT;
/*constructor*/ ncbInstanceAdaptor() : _instance(0), _sticky(false) {}
/*destructor*/ ~ncbInstanceAdaptor() { _deleteInstance(); }
// TJS2 オブジェクトが作成されるときに呼ばれる
//tjs_error TJS_INTF_METHOD Construct(tjs_int numparams, tTJSVariant **param, iTJSDispatch2 *tjs_obj);
// …のだが,TJS_BEGIN_NATIVE_CONSTRUCTOR マクロから呼ばれるので
// 上記マクロを使用せずに独自実装しているここでは使用しない(⇒ncbNativeClassConstructor)
/// オブジェクトが無効化されるときに呼ばれる
void TJS_INTF_METHOD Invalidate() { _deleteInstance(); }
private:
/// 実インスタンスへのポインタ
NativeClassT *_instance;
/// deleteしないフラグ
bool _sticky;
/// 実インスタンス破棄
void _deleteInstance() {
if (_instance && !_sticky) delete _instance;
_instance = 0;
_sticky = false;
}
public:
void setSticky() { _sticky = true; }
//--------------------------------------
// staticヘルパ関数
/// iTJSDispatch2 から Adaptor を取得
static AdaptorT *GetAdaptor(iTJSDispatch2 *obj, bool err = false) {
iTJSNativeInstance* adp = 0;
if (!obj) {
if (err) TVPThrowExceptionMessage(TJS_W("No instance."));
return 0;
}
if (TJS_FAILED(obj->NativeInstanceSupport(TJS_NIS_GETINSTANCE, ClassInfoT::GetID(), &adp))) {
if (err) TVPThrowExceptionMessage(TJS_W("Invalid instance type."));
return 0;
}
return static_cast<AdaptorT*>(adp);
}
/// iTJSDispatch2 から NativeClassインスタンスを取得
static NativeClassT *GetNativeInstance(iTJSDispatch2 *obj, bool err = false) {
AdaptorT *adp = GetAdaptor(obj, err);
return adp ? adp->_instance : 0;
}
/// NativeClassインスタンスを設定
static bool SetNativeInstance(iTJSDispatch2 *obj, NativeClassT *instance, bool err = false) {
AdaptorT *adp = GetAdaptor(obj, err);
if (!adp) return false;
adp->_instance = instance;
return true;
}
/// アダプタを生成しつつNativeClassインスタンスを設定
static bool SetAdaptorWithNativeInstance(iTJSDispatch2 *obj, NativeClassT *instance, bool err = false) {
AdaptorT *adp = GetAdaptor(obj, false);
if (adp) {
if (adp->_instance) adp->_deleteInstance();
} else if (!(adp = new AdaptorT())) {
if (err) TVPThrowExceptionMessage(TJS_W("Create adaptor failed."));
return false;
}
adp->_instance = instance;
iTJSNativeInstance *ni = static_cast<iTJSNativeInstance*>(adp);
if (TJS_FAILED(obj->NativeInstanceSupport(TJS_NIS_REGISTER, ClassInfoT::GetID(), &ni))) {
if (err) TVPThrowExceptionMessage(TJS_W("Adaptor registration failed."));
return false;
}
return true;
}
/// クラスオブジェクトからAdaptorインスタンスを生成してinstanceを代入
static iTJSDispatch2* CreateAdaptor(NativeClassT *inst, bool sticky = false, bool err = false) {
typename ClassInfoT::ClassObjectT *clsobj = ClassInfoT::GetClassObject();
if (!clsobj) {
if (err) TVPThrowExceptionMessage(TJS_W("No class object."));
return 0;
}
iTJSDispatch2 *global = TVPGetScriptDispatch(), *obj = 0;
tTJSVariant dummy, *param = &dummy;
// 引数が1つでかつvoidであれば実インスタンスをnewしない動作になる
tjs_error r = clsobj->CreateNew(0, 0, 0, &obj, 1, ¶m, global);
if (global) global->Release();
if (TJS_FAILED(r) || !obj) {
if (err) TVPThrowExceptionMessage(TJS_W("Can't create instance"));
return 0;
}
AdaptorT *adp = GetAdaptor(obj, err);
if (adp) {
adp->_instance = inst;
if (sticky) adp->setSticky();
}
return obj;
}
/// 空の Adaptor を生成する (tTJSNativeClassForPlugin型の関数)
static iTJSNativeInstance* TJS_INTF_METHOD CreateEmptyAdaptor() {
return static_cast<iTJSNativeInstance*>(new AdaptorT());
}
};
////////////////////////////////////////
/// 型変換用ヘルパテンプレート
struct ncbTypeConvertor {
/// FROM から TO へ変換できるか
template <typename FROM, typename TO>
struct Conversion {
private:
typedef char OK;
typedef struct { char ng[2]; } NG;
static OK check(TO);
static NG check(...);
static FROM wrap();
public:
enum {
Exists = (sizeof(check(wrap())) == sizeof(OK)),
Same = false
};
};
template <typename T> struct Conversion<T, T> { enum { Exists = true, Same = true }; };
template <typename T> struct Conversion<T, void> { enum { Exists = false, Same = false }; };
template <typename T> struct Conversion<void, T> { enum { Exists = false, Same = false }; };
// template <> struct Conversion<void, void> { enum { Exists = false, Same = true }; };
#define NCB_INNER_CONVERSION_SPECIALIZATION \
template <> struct ncbTypeConvertor::Conversion<void, void> { enum { Exists = false, Same = true }; };
/// 修飾子取り外し(ポインタ,参照,const等を外した素の型が typedef される)
template <typename T> struct Stripper { typedef T Type; };
template <typename T> struct Stripper<T*> { typedef typename Stripper<T>::Type Type; };
template <typename T> struct Stripper<T&> { typedef typename Stripper<T>::Type Type; };
template <typename T> struct Stripper<const T> { typedef typename Stripper<T>::Type Type; };
// template <typename T> struct Stripper<volatile T> { typedef typename Stripper<T>::Type Type; };
/// ポインタ取得
template <typename T> struct ToPointer { static T* Get(T &t) { return &t; } };
template <typename T> struct ToPointer<T&> { static T* Get(T &t) { return &t; } };
template <typename T> struct ToPointer<T*> { static T* Get(T* t) { return t; } };
template <typename T> struct ToPointer<T const&> { static T* Get(T const &t) { return const_cast<T*>(&t); } };
template <typename T> struct ToPointer<T const*> { static T* Get(T const *t) { return const_cast<T*>( t); } };
/// ポインタ⇒修飾子変換
template <typename T> struct ToTarget { static T& Get(T *t) { return *t; } };
template <typename T> struct ToTarget<T&> { static T& Get(T *t) { return *t; } };
template <typename T> struct ToTarget<T*> { static T* Get(T *t) { return t; } };
/// const外し
template <typename T> struct NonConst { typedef T Type; };
template <typename T> struct NonConst<const T> { typedef T Type; };
template <typename T> struct NonConst<const T&> { typedef T& Type; };
template <typename T> struct NonConst<const T*> { typedef T* Type; };
/// reference 外し
template <typename T> struct NonReference { typedef T Type; };
template <typename T> struct NonReference<T&> { typedef T Type; };
// 直コピー動作
struct DirectCopy {
template <typename DST, typename SRC>
inline void operator()(DST &dst, SRC const &src) const { dst = src; }
};
// キャスト動作
template <typename CAST>
struct CastCopy {
template <typename DST, typename SRC>
inline void operator()(DST &dst, SRC const &src) const { dst = static_cast<DST>(static_cast<CAST>(src)); }
};
// 型特殊化が存在するかのマップ用
template <typename T, bool SRCF>
struct SpecialMap {
enum { Exists = false, Modifier = false, IsSource = SRCF };
typedef T Type;
};
/// 動作未定(コンパイルエラー用)
struct NCB_COMPILE_ERROR_NoImplement;
// コンバータ動作選択
struct SelectConvertorTypeBase {
protected:
/// 3項演算子
template <bool EXP, class THEN, class ELSE> struct ifelse { typedef ELSE Type; };
template < class THEN, class ELSE> struct ifelse<true, THEN, ELSE> { typedef THEN Type; };
/// 特殊化が存在するか調べるテンプレート
template <typename T, bool IsSrcF>
struct hasSpecial {
typedef typename Stripper<T>::Type StripT;
typedef SpecialMap<T, IsSrcF> ThisMapT;
typedef SpecialMap<StripT, IsSrcF> StripMapT;
enum {
exthis = ThisMapT::Exists,
exstrip = StripMapT::Exists && StripMapT::Modifier,
Exists = exthis | exstrip,
};
typedef typename ifelse<exthis, typename ThisMapT::Type,
/* */typename ifelse<exstrip, typename StripMapT::Type, void>::Type
/* */>::Type Type;
};
template <typename T> struct wrap { typedef T Type; };
template <typename SRC, typename DST>
struct directSelect {
typedef typename ifelse<Conversion<SRC, DST>::Exists, DirectCopy, NCB_COMPILE_ERROR_NoImplement>::Type Type;
};
};
/// コンバータのタイプを調べる
template <typename SRC, typename DST>
struct SelectConvertorType : public SelectConvertorTypeBase {
private:
typedef hasSpecial<SRC, true > SrcSpecialT;
typedef hasSpecial<DST, false> DstSpecialT;
struct specialSelect {
typedef typename ifelse<DstSpecialT::Exists, typename DstSpecialT::Type, typename SrcSpecialT::Type>::Type Type;
};
typedef typename ifelse<
SrcSpecialT::Exists || DstSpecialT::Exists, specialSelect, directSelect<SRC, DST>
>::Type select;
public:
typedef typename select::Type Type;
};
};
// ncbTypeConvertor::Conversion の特殊化
NCB_INNER_CONVERSION_SPECIALIZATION
#undef NCB_INNER_CONVERSION_SPECIALIZATION
//--------------------------------------
/// 返り値の型を正確に取りたい場合,コンバータはこれを継承する
struct ncbStrictResultConvertor {};
//--------------------------------------
// TypeConvertor関連の各種マクロ
/// SpecialMap に登録するマクロ
#define NCB_TYPECONV_MAPSET(mapsel, type, conv, mod) \
template <> struct ncbTypeConvertor::SpecialMap<type, mapsel> { \
enum { Exists = true, Modifier = mod, IsSource = mapsel }; \
typedef conv Type; \
}
#define NCB_TYPECONV_SRCMAP_SET(type, conv, mod) NCB_TYPECONV_MAPSET(true, type, conv, mod)
#define NCB_TYPECONV_DSTMAP_SET(type, conv, mod) NCB_TYPECONV_MAPSET(false, type, conv, mod)
/// DirectCopy動作としてマップに登録
#define NCB_TYPECONV_DIRECT(type) \
NCB_TYPECONV_SRCMAP_SET(type, ncbTypeConvertor::DirectCopy, false); \
NCB_TYPECONV_DSTMAP_SET(type, ncbTypeConvertor::DirectCopy, false)
/// Cast動作としてマップに登録
#define NCB_TYPECONV_CAST(type, cast) \
NCB_TYPECONV_SRCMAP_SET(type, ncbTypeConvertor::CastCopy<cast>, false); \
NCB_TYPECONV_DSTMAP_SET(type, ncbTypeConvertor::CastCopy<cast>, false)
/// 数値キャストで登録
#define NCB_TYPECONV_CAST_INTEGER(type) NCB_TYPECONV_CAST(type, tTVInteger)
#define NCB_TYPECONV_CAST_REAL(type) NCB_TYPECONV_CAST(type, tTVReal)
/// 数値はキャストで変換する
NCB_TYPECONV_CAST_INTEGER( signed char);
NCB_TYPECONV_CAST_INTEGER( unsigned char);
NCB_TYPECONV_CAST_INTEGER( signed int);
NCB_TYPECONV_CAST_INTEGER( unsigned int);
NCB_TYPECONV_CAST_INTEGER( signed short);
NCB_TYPECONV_CAST_INTEGER(unsigned short);
NCB_TYPECONV_CAST_INTEGER( signed long);
NCB_TYPECONV_CAST_INTEGER( unsigned long);
NCB_TYPECONV_CAST_REAL( float);
NCB_TYPECONV_CAST_REAL( double);
NCB_TYPECONV_CAST( bool, bool);
// ナロー文字変換
struct ncbNarrowCharConvertor {
/// 一時的にバッファを確保してそこに NarrowStr として書き込む
struct ToNChar {
/// Constructor (メソッドが呼ばれる前)
ToNChar() : _nstr(0) {}
/// Destructor (メソッドが呼ばれた後)
~ToNChar() {
if (_nstr) {
// NCB_LOG_W("~ncbVariatToNChar > delete[]");
delete[] _nstr;
}
}
/// 引き数を受け渡すためのファンクタ
template <typename DST>
inline void operator()(DST &dst, tTJSVariant const &src) {
if (ncbTypedefs::GetVariantType(src) == tvtString) {
tTJSString s(src.AsStringNoAddRef());
tjs_int len = s.GetNarrowStrLen();
// NCB_LOG_W("ncbVariatToNChar::operator() > new tjs_nchar[]");
_nstr = new tjs_nchar[len+1];
s.ToNarrowStr(_nstr, len+1);
}
dst = static_cast<DST>(_nstr);
}
private:
tjs_nchar *_nstr;
};
struct ToVariant {
template <typename SRC>
inline void operator()(tTJSVariant &dst, SRC const &src) const {
// NCB_LOG_2("ncbNCharToVariatTo::operator() : ", src);
dst = tTJSString(src);
}
};
};
// Narrow文字列として登録するマクロ
#define NCB_TYPECONV_NARROW_STRING(type) \
NCB_TYPECONV_SRCMAP_SET(type, ncbNarrowCharConvertor::ToVariant, false); \
NCB_TYPECONV_DSTMAP_SET(type, ncbNarrowCharConvertor::ToNChar, false)
/// signed char と char って別物なのかすら?
NCB_TYPECONV_NARROW_STRING( char const*);
NCB_TYPECONV_NARROW_STRING( signed char const*);
NCB_TYPECONV_NARROW_STRING(unsigned char const*);
// ワイド文字変換
struct ncbWideCharConvertor {
struct ToWChar {
template <typename DST>
inline void operator()(DST &dst, tTJSVariant const &src) {
dst = static_cast<DST>(src.GetString());
}
};
};
// Wide文字列として登録するマクロ
#define NCB_TYPECONV_WIDE_STRING(type) \
NCB_TYPECONV_SRCMAP_SET(type, ncbTypeConvertor::CastCopy<tjs_char const*>, false); \
NCB_TYPECONV_DSTMAP_SET(type, ncbWideCharConvertor::ToWChar, false)
NCB_TYPECONV_WIDE_STRING(tjs_char const*);
/// std::stringなどを c_str() で受け渡す
template <class StringT>
struct ncbStringConvertor {
typedef ncbTypedefs DefsT;
typedef ncbTypeConvertor ConvT;
typedef DefsT::NumTag<sizeof(typename StringT::value_type)> SizeTagT;
template <class STR>
inline void operator()(tTJSVariant &dst, STR const &src) const {
dst = (ConvT::ToPointer<STR const&>::Get(src))->c_str();
}
template <class STR>
inline void operator()(STR &dst, tTJSVariant const &src) {
if (ncbTypedefs::GetVariantType(src) == tvtString) {
tTJSString str(src.AsStringNoAddRef());
set(str, SizeTagT());
}
dst = ConvT::ToTarget<STR>::Get(&_temp);
}
inline void set(tTJSString const &str, DefsT::NumTag<sizeof(tjs_nchar)>) { // for Narrow char
tjs_int len = str.GetNarrowStrLen();
tjs_nchar tmp[len+1];
str.ToNarrowStr(tmp, len+1);
_temp.assign(tmp, len);
}
inline void set(tTJSString const &str, DefsT::NumTag<sizeof(tjs_char)>) { // for Wide char
_temp = str.c_str();
}
private:
StringT _temp;
};
#define NCB_TYPECONV_STL_STRING(type) \
NCB_TYPECONV_SRCMAP_SET(type, ncbStringConvertor<type>, true); \
NCB_TYPECONV_DSTMAP_SET(type, ncbStringConvertor<type>, true)
/// ネイティブインスタンスアダプタで Boxing/Unboxing する
struct ncbNativeObjectBoxing {
typedef tTJSVariant VarT;
typedef ncbTypeConvertor ConvT;
/// Boxing
struct Boxing : public ncbStrictResultConvertor {
template <typename T> struct box { static T* Get(T const &t) { return new T(t); } enum { Sticky = false }; };
template <typename T> struct box<T&> { static T* Get(T &t) { return &t ; } enum { Sticky = true }; };
template <typename T> struct box<T const&> { static T* Get(T const &t) { return const_cast<T*>(&t); } enum { Sticky = true }; };
template <typename T> struct box<T*> { static T* Get(T *t) { return t ; } enum { Sticky = false }; };
template <typename T> struct box<T const*> { static T* Get(T const *t) { return const_cast<T*>( t); } enum { Sticky = false }; };
template <typename SRC>
inline void operator ()(VarT &dst, SRC src, ncbTypedefs::Tag<SRC> const&) const {
typedef SRC TargetT;
typedef typename ConvT::Stripper<TargetT>::Type ClassT;
typedef ncbInstanceAdaptor<ClassT> AdaptorT;
ClassT *p = box<TargetT>::Get(src); //< コピー/参照/ポインタ場合分け
bool const s = box<TargetT>::Sticky; //< sticky フラグ
iTJSDispatch2 *adpobj = AdaptorT::CreateAdaptor(p, s); //< アダプタTJSオブジェクト生成
dst = tTJSVariant(adpobj, adpobj); //< Variantにコピー
adpobj->Release(); //< コピー済みなのでadaptorは不要
}
// for reference
template <typename SRC>
inline void operator ()(VarT &dst, SRC &src, ncbTypedefs::Tag<SRC&> const &tag) const {
operator()<SRC&> (dst, src, tag);
}
};
/// Unboxing
struct Unboxing {
template <typename DST>
inline void operator ()(DST &dst, VarT const &src) const {
typedef DST TargetT;
typedef typename ConvT::Stripper<TargetT>::Type ClassT;
typedef ncbInstanceAdaptor<ClassT> AdaptorT;
iTJSDispatch2 *obj = src.AsObjectNoAddRef(); //< 参照カウンタ増加なしでDispatchオブジェクト取得
ClassT *p = AdaptorT::GetNativeInstance(obj, true); //< 実インスタンスのポインタを取得
dst = ConvT::ToTarget<TargetT>::Get(p); //< 必要とされる型に変換して返す
}
};
};
/// ボックス化する型として登録するマクロ
#define NCB_TYPECONV_BOXING(type) \
NCB_TYPECONV_SRCMAP_SET(type, ncbNativeObjectBoxing::Boxing, true); \
NCB_TYPECONV_DSTMAP_SET(type, ncbNativeObjectBoxing::Unboxing, true)
/// 特殊化用のマクロ (自動変換でなく直で指定する場合はこのマクロを使用する)
#define NCB_SET_TOVARIANT_CONVERTOR(type, convertor) \
template <> struct ncbTypeConvertor::SelectConvertorType<type, tTJSVariant> { typedef convertor Type; }
#define NCB_SET_TOVALUE_CONVERTOR(type, convertor) \
template <> struct ncbTypeConvertor::SelectConvertorType<tTJSVariant, type> { typedef convertor Type; }
#define NCB_SET_CONVERTOR(type, convertor) \
NCB_SET_TOVARIANT_CONVERTOR(type, convertor); \
NCB_SET_TOVALUE_CONVERTOR( type, convertor) \
/// 返り値なしの場合のダミーの TOVARIANT を登録
NCB_SET_TOVARIANT_CONVERTOR(void, struct {});
// iTJSDispatch2*を引き数・返り値にする場合
struct ncbDispatchConvertor {
inline void operator ()(tTJSVariant &dst, iTJSDispatch2* &src) const {
dst = tTJSVariant(src, src);
src->Release();
}
inline void operator ()(iTJSDispatch2* &dst, tTJSVariant const &src) const {
dst = src.AsObjectNoAddRef();
}
inline void operator ()(iTJSDispatch2 const* &dst, tTJSVariant const &src) const {
dst = src.AsObjectNoAddRef();
}
};
NCB_SET_TOVARIANT_CONVERTOR(iTJSDispatch2*, ncbDispatchConvertor);
NCB_SET_TOVALUE_CONVERTOR( iTJSDispatch2*, ncbDispatchConvertor);
NCB_SET_TOVALUE_CONVERTOR( iTJSDispatch2 const*, ncbDispatchConvertor);
/*
型変換を直で書きたい時は
struct CustomType; // 変換する対象の型
struct CustomConvertor { // コンバータ
void operator ()(tTJSVariant &dst, CustomType const &src);
void operator ()(CustomType const &src, tTJSVariant &dst);
};
NCB_SET_CONVERTOR(CustomType, CustomConvertor);
といったような感じで適当に
*/
// Dicionary/Array 向けラッパ(手抜き実装)
struct ncbPropAccessor {
typedef ncbTypedefs DefsT;
typedef DefsT::NameT NameT;
typedef DefsT::FlagsT FlagsT;
typedef DefsT::NameT KeyT;
typedef tjs_int32 IndexT;
typedef tjs_int CountT;
typedef tjs_uint32 SizeT;
typedef tjs_error ErrorT;
typedef tjs_uint32* HintT;
typedef tTJSVariant VariantT;
ncbPropAccessor(iTJSDispatch2 *obj, bool addref = true) : _obj(obj) {
if (addref) _obj->AddRef();
}
ncbPropAccessor(tTJSVariant var) : _obj(var.AsObject()) {
//_obj->AddRef();
}
ncbPropAccessor(NameT name) {
tTJSVariant val;
iTJSDispatch2 *global = TVPGetScriptDispatch();
if (global) {
global->PropGet(0, name, 0, &val, global);
}
_obj = val.AsObject();
}
virtual ~ncbPropAccessor() {
if (_obj) {
_obj->Release();
}
}
CountT GetCount() const {
CountT sz;
ErrorT r = _obj->GetCount(&sz, 0, 0, _obj);
return (r == TJS_S_OK) ? sz : 0;
}
CountT GetArrayCount() const {
VariantT var;
_obj->PropGet(0, L"count", 0, &var, _obj);
return (CountT)var;
}
template <typename TargetT>
TargetT GetValue(IndexT ofs, DefsT::Tag<TargetT> const &tag, FlagsT f = 0) {
VariantT var;
_obj->PropGetByNum(f, ofs, &var, _obj);
return _toTarget(var, tag);
}
template <typename TargetT>
TargetT GetValue(iTJSDispatch2 *obj, IndexT ofs, DefsT::Tag<TargetT> const &tag, FlagsT f = 0) {
VariantT var;
_obj->PropGetByNum(f, ofs, &var, obj);
return _toTarget(var, tag);
}
tjs_int getIntValue(IndexT ofs, tjs_int defaultValue=0) {
if (HasValue(ofs)) {
return GetValue(ofs, DefsT::Tag<tjs_int>());
} else {
return defaultValue;
}
}
tjs_real getRealValue(IndexT ofs, tjs_real defaultValue=0) {
if (HasValue(ofs)) {
return GetValue(ofs, DefsT::Tag<tjs_real>());
} else {
return defaultValue;
}
}
ttstr getStrValue(IndexT ofs, ttstr const &defaultValue=ttstr("")) {
if (HasValue(ofs)) {
return GetValue(ofs, DefsT::Tag<ttstr>());
} else {
return defaultValue;
}
}
template <typename TargetT>
TargetT GetValue(KeyT key, DefsT::Tag<TargetT> const &tag, FlagsT f = 0, HintT hint = 0) {
VariantT var;
_obj->PropGet(f, key, hint, &var, _obj);
return _toTarget(var, tag);
}
template <typename TargetT>
TargetT GetValue(iTJSDispatch2* obj, KeyT key, DefsT::Tag<TargetT> const &tag, FlagsT f = 0, HintT hint = 0) {
VariantT var;
_obj->PropGet(f, key, hint, &var, obj);
return _toTarget(var, tag);
}
tjs_int getIntValue(KeyT key, tjs_int defaultValue=0) {
if (HasValue(key)) {
return GetValue(key, DefsT::Tag<tjs_int>());
} else {
return defaultValue;
}
}
tjs_real getRealValue(KeyT key, tjs_real defaultValue=0) {
if (HasValue(key)) {
return GetValue(key, DefsT::Tag<tjs_real>());
} else {
return defaultValue;
}
}
ttstr getStrValue(KeyT key, ttstr const &defaultValue=ttstr("")) {
if (HasValue(key)) {
return GetValue(key, DefsT::Tag<ttstr>());
} else {
return defaultValue;
}
}
bool checkVariant(IndexT ofs, VariantT &var) {
return TJS_SUCCEEDED(_obj->PropGetByNum(TJS_MEMBERMUSTEXIST, ofs, &var, _obj));
}
bool checkVariant(KeyT key, VariantT &var) {
return TJS_SUCCEEDED(_obj->PropGet(TJS_MEMBERMUSTEXIST, key, 0, &var, _obj));
}
bool HasValue(IndexT ofs, tTJSVariantType *type = 0) {
VariantT var;
bool ret = TJS_SUCCEEDED(_obj->PropGetByNum(TJS_MEMBERMUSTEXIST, ofs, &var, _obj));
if (ret && type) *type = var.Type();
return ret;
}
bool HasValue(iTJSDispatch2 *obj, IndexT ofs, tTJSVariantType *type = 0) {
VariantT var;
bool ret = TJS_SUCCEEDED(_obj->PropGetByNum(TJS_MEMBERMUSTEXIST, ofs, &var, obj));
if (ret && type) *type = var.Type();
return ret;
}
bool HasValue(KeyT key, HintT hint = 0, tTJSVariantType *type = 0) {
VariantT var;
bool ret = TJS_SUCCEEDED(_obj->PropGet(TJS_MEMBERMUSTEXIST, key, hint, &var, _obj));
if (ret && type) *type = var.Type();
return ret;
}
bool HasValue(iTJSDispatch2 *obj, KeyT key, HintT hint = 0, tTJSVariantType *type = 0) {
VariantT var;
bool ret = TJS_SUCCEEDED(_obj->PropGet(TJS_MEMBERMUSTEXIST, key, hint, &var, obj));
if (ret && type) *type = var.Type();
return ret;
}
template <typename TargetT>
bool SetValue(IndexT ofs, TargetT const &val, FlagsT f = TJS_MEMBERENSURE) {
VariantT var;
_toVariant(var, val);
return (_obj->PropSetByNum(f, ofs, &var, _obj) == TJS_S_OK);
}
template <typename TargetT>
bool SetValue(iTJSDispatch2 *obj, IndexT ofs, TargetT const &val, FlagsT f = TJS_MEMBERENSURE) {
VariantT var;
_toVariant(var, val);
return (_obj->PropSetByNum(f, ofs, &var, obj) == TJS_S_OK);
}
template <typename TargetT>
bool SetValue(KeyT key, TargetT const &val, FlagsT f = TJS_MEMBERENSURE, HintT hint = 0) {
VariantT var;
_toVariant(var, val);
return (_obj->PropSet(f, key, hint, &var, _obj) == TJS_S_OK);
}
template <typename TargetT>
bool SetValue(iTJSDispatch2 *obj, KeyT key, TargetT const &val, FlagsT f = TJS_MEMBERENSURE, HintT hint = 0) {
VariantT var;
_toVariant(var, val);
return (_obj->PropSet(f, key, hint, &var, obj) == TJS_S_OK);
}
bool IsValid() const { return _obj != 0; }
iTJSDispatch2* GetDispatch() const { return _obj; }
operator iTJSDispatch2* () const { return _obj; }
#undef FOREACH_START
#define FOREACH_START 1
#undef FOREACH_END
#define FOREACH_END FOREACH_MAX
#define FCALL_PRM_EXT(num) tTJSVariant param ## num
#define FCALL_SET_EXT(num) params[ num - 1 ] = ¶m ## num;
// FuncCallを任意個数のtTJSVariantを引数で受けるようなメソッドを展開
#undef FOREACH
#define FOREACH \
tjs_error TJS_INTF_METHOD FuncCall(tjs_uint32 flag, const tjs_char *membername, tjs_uint32 *hint, tTJSVariant *result, FOREACH_COMMA_EXT(FCALL_PRM_EXT) ) { \
tTJSVariant *params[FOREACH_COUNT]; FOREACH_SPACE_EXT(FCALL_SET_EXT) \
return _obj->FuncCall(flag, membername, hint, result, FOREACH_COUNT, params, _obj); \
}
#include FOREACH_INCLUDE
#undef FOREACH
#define FOREACH \
tjs_error TJS_INTF_METHOD FuncCall(iTJSDispatch2 *obj, tjs_uint32 flag, const tjs_char *membername, tjs_uint32 *hint, tTJSVariant *result, FOREACH_COMMA_EXT(FCALL_PRM_EXT) ) { \
tTJSVariant *params[FOREACH_COUNT]; FOREACH_SPACE_EXT(FCALL_SET_EXT) \
return _obj->FuncCall(flag, membername, hint, result, FOREACH_COUNT, params, obj); \
}
#include FOREACH_INCLUDE
#undef FCALL_PRM_EXT
#undef FCALL_SET_EXT
// 引数なしの場合だけ特殊
tjs_error TJS_INTF_METHOD FuncCall(tjs_uint32 flag, const tjs_char *membername, tjs_uint32 *hint, tTJSVariant *result) {
return _obj->FuncCall(flag, membername, hint, result, 0, NULL, _obj);
}
tjs_error TJS_INTF_METHOD FuncCall(iTJSDispatch2 *obj, tjs_uint32 flag, const tjs_char *membername, tjs_uint32 *hint, tTJSVariant *result) {
return _obj->FuncCall(flag, membername, hint, result, 0, NULL, obj);
}
protected:
iTJSDispatch2 *_obj;
template <typename TargetT>
TargetT _toTarget(VariantT &v, DefsT::Tag<TargetT> const&) {
typedef typename ncbTypeConvertor::SelectConvertorType<VariantT, TargetT>::Type ToTargetT;
TargetT r;
ToTargetT conv;
conv(r, v);
return r;
}
template <typename TargetT>
void _toVariant(VariantT &v, TargetT const &r) {
typedef typename ncbTypeConvertor::SelectConvertorType<TargetT, VariantT>::Type ToVariantT;
ToVariantT conv;
conv(v, r);
}
VariantT _toTarget( VariantT &v, DefsT::Tag<VariantT> const&) { return v; }
void _toVariant(VariantT &v, VariantT const &r) { v = r; }
iTJSDispatch2* _toTarget( VariantT &v, DefsT::Tag<iTJSDispatch2*> const&) { return v; }
void _toVariant(VariantT &v, iTJSDispatch2* const &r) { v = VariantT(r, r); }
void _toVariant(VariantT &v, ncbPropAccessor const &r) { _toVariant(v, r._obj); }
void _toVariant(VariantT &v, ncbPropAccessor* const &r) { _toVariant(v, r->_obj); }
};
struct ncbArrayAccessor : public ncbPropAccessor {
ncbArrayAccessor() : ncbPropAccessor(TJSCreateArrayObject(), false) {}
};
struct ncbDictionaryAccessor : public ncbPropAccessor {
ncbDictionaryAccessor() : ncbPropAccessor(TJSCreateDictionaryObject(), false) {}
};
////////////////////////////////////////
/// メソッドオブジェクト(と,そのタイプとフラグ)を受け渡すためのインターフェース
struct ncbIMethodObject {
typedef iTJSDispatch2* DispatchT;
typedef ncbTypedefs::FlagsT FlagsT;
typedef ncbTypedefs::InstanceTypeT TypesT;
virtual DispatchT GetDispatch() const = 0;
virtual FlagsT GetFlags() const = 0;
virtual TypesT GetType() const = 0;
virtual void Release() const = 0;
};
////////////////////////////////////////
/// メソッド呼び出し用ベースクラス
struct ncbNativeClassMethodBase : public tTJSDispatch {
typedef tTJSDispatch BaseT;
typedef ncbNativeClassMethodBase ThisClassT;
typedef ncbTypedefs DefsT;
typedef DefsT::NameT NameT;
typedef DefsT::FlagsT FlagsT;
typedef DefsT::InstanceTypeT TypesT;
typedef ncbIMethodObject const* iMethodT;
typedef tTJSNativeInstanceType MethodTypeT;
/// constructor
ncbNativeClassMethodBase(MethodTypeT t) : _type(t), _name(0) {
_imethod = this;
switch (t) { // タイプ名を設定
// case nitClass: _name = TJS_W("Class"); break; // クラスになることはありえない
case nitMethod: _name = TJS_W("Function"); break;
case nitProperty: _name = TJS_W("Property"); break;
default: break;
}
}
~ncbNativeClassMethodBase() {}
/// IsInstanceOf 実装
tjs_error TJS_INTF_METHOD IsInstanceOf(
tjs_uint32 flag, const tjs_char *membername, tjs_uint32 *hint,
const tjs_char *classname, iTJSDispatch2 *objthis)
{
// 自分自身(membername==0)で比較クラス名が_nameならTRUE,それ以外は丸投げ
return (!membername && _name && !TJS_stricmp(classname, _name)) ? TJS_S_TRUE
: BaseT::IsInstanceOf(flag, membername, hint, classname, objthis);
}
private:
MethodTypeT const _type;
NameT _name;
// privateで隠蔽してみる
typedef DefsT::CallerT CallerT;
//--------------------------------------
/// TJSNativeClassRegisterNCM に渡すタイプ
virtual TypesT GetType() const { return _type; }
/// TJSNativeClassRegisterNCM に渡すフラグ
virtual FlagsT GetFlags() const { return 0; }
/// IMethod 実装
struct iMethod : public ncbIMethodObject {
typedef ncbNativeClassMethodBase MethodObjectT;
void operator = (MethodObjectT *mo) { _this = mo; }
DispatchT GetDispatch() const { return static_cast<DispatchT>(_this); }
FlagsT GetFlags() const { return _this->GetFlags(); }
TypesT GetType() const { return _this->GetType(); }
void Release() const {}
private:
MethodObjectT *_this;
} _imethod;
protected:
/// IMethod 取得
iMethodT GetIMethod() const { return &_imethod; }
//--------------------------------------
protected:
/// tMethodTraitsラッパー
template <typename T>
struct traits {
typedef CallerT::tMethodTraits<T> TraitsT;
typedef typename TraitsT::ResultType ResultT;
typedef typename TraitsT::ClassType ClassT;
typedef typename TraitsT::ArgsType ArgsT;
enum { ArgsCount = TraitsT::ArgsCount };
};
//--------------------------------------
private:
/// 引数/返り値の引き渡し用ファンクタ (ncb_invoke.hpp/MethodCallerに渡すために必要)
template <typename METHOD>
struct paramsFunctor {
typedef traits<METHOD> TraitsT;
// 旧テンプレパラメタ
typedef typename TraitsT::ResultT RES;
typedef typename TraitsT::ArgsT ARGS;
enum { ARGC = TraitsT::ArgsCount };
typedef tTJSVariant VariantT;
typedef ncbTypeConvertor ConvT;
typedef typename ConvT::SelectConvertorType<RES, VariantT>::Type ResultConvT;
enum { StrictResult = ncbTypeConvertor::Conversion<ResultConvT*, ncbStrictResultConvertor*>::Exists };
template <typename T> struct TypeWrap { typedef T Type; static inline T Restore(Type t) { return t; } };
template <typename T> struct TypeWrap<T&> { typedef T* Type; static inline T& Restore(Type t) { return *t; } };
template <typename T> struct TypeWrap<T const&> { typedef T const* Type; static inline T const& Restore(Type t) { return *t; } };
template <typename T> struct ArgsExtor { typedef typename ConvT::SelectConvertorType<VariantT, typename TypeWrap<T>::Type>::Type Type; };
typedef CallerT::tArgsExtract<ArgsExtor, ARGS, ARGC> ArgsConvT;
/* ArgsConvT は以下のように展開される:
struct ArgsConvT {
ncbToValueConvertor<ARGS::Arg1Type> t1; // 一番目の引数の ncbToValueConvertor
ncbToValueConvertor<ARGS::Arg2Type> t2; // 二番目の
:
ncbToValueConvertor<ARGS::Arg[ARGC]Type> tARGC; // ARGC番目の
}; */
/// constructor
paramsFunctor(VariantT *r, tjs_int n, VariantT const *const *p) : _numparams(n), _result(r),_param(p) {}
/// 引数を NativeClassMethod へ引渡し
template <int N, typename T>
inline T operator ()(CallerT::tNumTag<N> const& /*index*/, CallerT::tTypeTag<T> const& /*type*/) {
typedef typename TypeWrap<T>::Type ParamT;
ParamT ret;
// N番目の ncbToValueConvertor を取り出して変換
(CallerT::tArgsSelect<ArgsConvT, N>::Get(_aconv))(ret, (_numparams >= N) ? *(_param[N - 1]) : VariantT());
return TypeWrap<T>::Restore(ret);
}
/// NativeClassMethod の返り値なし
inline bool operator ()() const { return true; }
/// NativeClassMethod の返り値をresultへ格納
template <typename ResultT>
inline bool operator()(ResultT r, CallerT::tTypeTag<ResultT> const&) {
return SetResult(r, DefsT::Tag<ResultT>(), DefsT::BoolTag<StrictResult>());
}
// StrictResult = false
template <typename ResultT>
inline bool SetResult(ResultT r, DefsT::Tag<ResultT> const&, DefsT::BoolTag<false> const&) {
if (_result) _rconv(*_result, r); // ncbToVariantConvertor で返り値に変換
return true;
}
// StrictResult = true
template <typename ResultT>
inline bool SetResult(ResultT r, DefsT::Tag<ResultT> const &tag, DefsT::BoolTag<true> const&) {
if (_result) _rconv(*_result, r, tag);
return true;
}
// for reference
template <typename ResultT>
inline bool operator()(ResultT &r, CallerT::tTypeTag<ResultT&> const& tag) {
return operator()<ResultT &>(r, tag);
}
template <typename ResultT, bool B>
inline bool SetResult(ResultT &r, DefsT::Tag<ResultT&> const &tag, DefsT::BoolTag<B> const &sel) {
return SetResult<ResultT &>(r, tag, sel);
}