1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ut_Inlines.h
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: $
16 *---------------------------------------------------------------------------*/
17
18 /*
19 * 小物なユーティリティインライン関数を定義します。
20 */
21
22 #ifndef NW_UT_INLINES_H_
23 #define NW_UT_INLINES_H_
24
25 #include <nw/types.h>
26 #include <cstring>
27 #include <cstdio>
28 #include <cstdarg>
29 #include <limits>
30 #include <functional>
31 #include <algorithm>
32
33 #if defined( NW_COMPILER_MSVC )
34 #include <iosfwd>
35 #else
36 #include <string>
37 #endif
38
39 namespace nw {
40 namespace ut {
41
42 template <typename T>
43 NW_INLINE T Min(T a, T b);
44
45 //----------------------------------------
46 //! @name 文字列操作関連
47 //@{
48
49 namespace internal{
50
51 //---------------------------------------------------------------------------
52 //! @brief 文字列をコピーします。
53 //!
54 //! src 文字列を srcCount 分コピーし、必ず nul の終端文字を追加します。
55 //! destCount が srcCount 小さい場合は切り詰めてコピーされますが、
56 //! 必ず nul 終端文字が挿入されます。
57 //!
58 //! @tparam 文字の型です。
59 //!
60 //! @param[in] dest コピー先のバッファのアドレスです。
61 //! @param[in] destCount コピー先のバッファサイズです。
62 //! @param[in] src コピー元の文字列のアドレスです。
63 //! @param[in] srcCount コピーするサイズです。
64 //!
65 //! @return コピーした文字数を返します。
66 //---------------------------------------------------------------------------
67 template<typename TChar>
68 NW_INLINE size_t
strncpy_t(TChar * dest,std::size_t destCount,const TChar * src,std::size_t srcCount)69 strncpy_t(
70 TChar* dest,
71 std::size_t destCount,
72 const TChar* src,
73 std::size_t srcCount)
74 {
75 size_t length = 0;
76 while ( length < ut::Min((destCount - 1), srcCount) )
77 {
78 *dest = *src;
79 ++dest;
80 ++src;
81 ++length;
82
83 if (*src == std::char_traits<TChar>::to_char_type('\0'))
84 {
85 break;
86 }
87 }
88
89 *dest = std::char_traits<TChar>::to_char_type('\0');
90
91 return length;
92 }
93 }
94
95 //---------------------------------------------------------------------------
96 //! @brief 文字列をコピーします。
97 //!
98 //! src 文字列をコピーし、必ず nul の終端文字を追加します。
99 //! destCount が src の大きさより小さい場合は切り詰めてコピーされますが、
100 //! 必ず nul 終端文字が挿入されます。
101 //!
102 //! @param[in] dest コピー先のバッファのアドレスです。
103 //! @param[in] destCount コピー先のバッファサイズです。
104 //! @param[in] src コピー元の文字列のアドレスです。
105 //!
106 //! @return コピーした文字数を返します。
107 //---------------------------------------------------------------------------
108 NW_INLINE size_t
strcpy(char * dest,std::size_t destCount,const char * src)109 strcpy(
110 char* dest,
111 std::size_t destCount,
112 const char* src)
113 {
114 return ut::internal::strncpy_t(dest, destCount, src, destCount-1);
115 }
116
117 //---------------------------------------------------------------------------
118 //! @brief 文字列をコピーします。
119 //!
120 //! src 文字列をコピーし、必ず nul の終端文字を追加します。
121 //! destCount が src の大きさより小さい場合は切り詰めてコピーされますが、
122 //! 必ず nul 終端文字が挿入されます。
123 //!
124 //! @param[in] dest コピー先のバッファのアドレスです。
125 //! @param[in] destCount コピー先のバッファサイズです。
126 //! @param[in] src コピー元の文字列のアドレスです。
127 //!
128 //! @return コピーした文字数を返します。
129 //---------------------------------------------------------------------------
130 NW_INLINE size_t
wcsncpy(wchar_t * dest,std::size_t destCount,const wchar_t * src)131 wcsncpy(
132 wchar_t* dest,
133 std::size_t destCount,
134 const wchar_t* src)
135 {
136 return ut::internal::strncpy_t(dest, destCount, src, destCount-1);
137 }
138
139 //---------------------------------------------------------------------------
140 //! @brief 文字列をコピーします。
141 //!
142 //! src 文字列を srcCount 分コピーし、必ず nul の終端文字を追加します。
143 //! destCount が srcCount 小さい場合は切り詰めてコピーされますが、
144 //! 必ず nul 終端文字が挿入されます。
145 //!
146 //! @param[in] dest コピー先のバッファのアドレスです。
147 //! @param[in] destCount コピー先のバッファサイズです。
148 //! @param[in] src コピー元の文字列のアドレスです。
149 //! @param[in] srcCount コピーするサイズです。
150 //!
151 //! @return コピーした文字数を返します。
152 //---------------------------------------------------------------------------
153 NW_INLINE size_t
strncpy(char * dest,std::size_t destCount,const char * src,std::size_t srcCount)154 strncpy(
155 char* dest,
156 std::size_t destCount,
157 const char* src,
158 std::size_t srcCount)
159 {
160 return ut::internal::strncpy_t(dest, destCount, src, srcCount);
161 }
162
163 //---------------------------------------------------------------------------
164 //! @brief 文字列をコピーします。
165 //!
166 //! src 文字列を srcCount 分コピーし、必ず nul の終端文字を追加します。
167 //! destCount が srcCount 小さい場合は切り詰めてコピーされますが、
168 //! 必ず nul 終端文字が挿入されます。
169 //!
170 //! @param[in] dest コピー先のバッファのアドレスです。
171 //! @param[in] destCount コピー先のバッファサイズです。
172 //! @param[in] src コピー元の文字列のアドレスです。
173 //! @param[in] srcCount コピーするサイズです。
174 //!
175 //! @return コピーした文字数を返します。
176 //---------------------------------------------------------------------------
177 NW_INLINE size_t
wcsncpy(wchar_t * dest,std::size_t destCount,const wchar_t * src,std::size_t srcCount)178 wcsncpy(
179 wchar_t* dest,
180 std::size_t destCount,
181 const wchar_t* src,
182 std::size_t srcCount)
183 {
184 return ut::internal::strncpy_t(dest, destCount, src, srcCount);
185 }
186
187
188 //---------------------------------------------------------------------------
189 //! @brief 文字列を追加します。
190 //!
191 //! source 文字列を count 分コピーし、必ず null の終端文字を追加します。
192 //! destCount が srcCount 小さい場合は切り詰めて追加されますが、
193 //! 必ず nul 終端文字が挿入されます。
194 //!
195 //! @param[in] dest 追加先のバッファのアドレスです。
196 //! @param[in] destCount コピー先のサイズです。
197 //! @param[in] src 追加元の文字列のアドレスです。
198 //! @param[in] srcCount 追加するサイズです。
199 //!
200 //! @return 追加した文字数を返します。
201 //---------------------------------------------------------------------------
202 NW_INLINE size_t
strncat(char * dest,std::size_t destCount,const char * src,std::size_t srcCount)203 strncat(
204 char* dest,
205 std::size_t destCount,
206 const char* src,
207 std::size_t srcCount)
208 {
209 #ifdef NW_COMPILER_MSVC
210 #pragma warning(push)
211 #pragma warning(disable : 4996)
212 #endif
213 size_t length = std::strlen(dest);
214 if (destCount <= length + srcCount)
215 {
216 srcCount = destCount - length - 1;
217 }
218
219 char* result = std::strncat( dest, src, srcCount );
220
221 dest[destCount-1] = '\0';
222
223 return srcCount;
224
225 #ifdef NW_COMPILER_MSVC
226 #pragma warning(pop)
227 #endif
228 }
229
230 //---------------------------------------------------------------------------
231 //! @brief 指定されたデータを書式指定して書き込みます。
232 //!
233 //! source 文字列を count 分書き込み、必ず null の終端文字を追加します。
234 //!
235 //! @param[out] dest 書き込み先のバッファのアドレスです。
236 //! @param[in] destCount 書き込み先のサイズです。
237 //! @param[in] srcCount 書き込むサイズです。特に指定がない場合は、(destCount - 1) を入力してください。
238 //! @param[in] format 書式です。
239 //! @param[in] vargs 引数リストです。
240 //!
241 //! @return 文字列の長さを返します。
242 //---------------------------------------------------------------------------
243 NW_INLINE int
vsnprintf(char * dest,std::size_t destCount,std::size_t srcCount,const char * format,va_list vargs)244 vsnprintf(
245 char* dest,
246 std::size_t destCount,
247 std::size_t srcCount,
248 const char* format,
249 va_list vargs)
250 {
251 #ifdef NW_COMPILER_MSVC
252 #pragma warning(push)
253 #pragma warning(disable : 4996)
254 #endif
255
256 #ifdef NW_COMPILER_MSVC
257 int result = ::vsnprintf( dest, srcCount, format, vargs );
258 #else
259 int result = std::vsnprintf( dest, srcCount, format, vargs );
260 #endif
261
262 dest[destCount - 1] = '\0';
263
264 return result;
265
266 #ifdef NW_COMPILER_MSVC
267 #pragma warning(pop)
268 #endif
269 }
270
271 //---------------------------------------------------------------------------
272 //! @brief 指定されたデータを書式指定して書き込みます。
273 //!
274 //! source 文字列を count 分書き込み、必ず null の終端文字を追加します。
275 //!
276 //! @param[out] dest 書き込み先のバッファのアドレスです。
277 //! @param[in] destCount 書き込み先のサイズです。
278 //! @param[in] srcCount 書き込むサイズです。特に指定がない場合は、(destCount - 1) を入力してください。
279 //! @param[in] format 書式です。
280 //! @param[in] vargs 引数リストです。
281 //!
282 //! @return 文字列の長さを返します。
283 //---------------------------------------------------------------------------
284 NW_INLINE int
vsnwprintf(wchar_t * dest,std::size_t destCount,std::size_t srcCount,const wchar_t * format,va_list vargs)285 vsnwprintf(
286 wchar_t* dest,
287 std::size_t destCount,
288 std::size_t srcCount,
289 const wchar_t* format,
290 va_list vargs)
291 {
292 #ifdef NW_COMPILER_MSVC
293 #pragma warning(push)
294 #pragma warning(disable : 4996)
295 #endif
296
297 #ifdef NW_COMPILER_MSVC
298 int result = ::_vsnwprintf( dest, srcCount, format, vargs );
299 #else
300 int result = std::vswprintf( dest, srcCount, format, vargs );
301 #endif
302
303 dest[destCount - 1] = L'\0';
304
305 return result;
306
307 #ifdef NW_COMPILER_MSVC
308 #pragma warning(pop)
309 #endif
310 }
311
312 //---------------------------------------------------------------------------
313 //! @brief 指定されたデータを書式指定して書き込みます。
314 //!
315 //! source 文字列を count 分書き込み、必ず null の終端文字を追加します。
316 //!
317 //! @param[out] dest 書き込み先のバッファのアドレスです。
318 //! @param[in] destCount 書き込み先のサイズです。
319 //! @param[in] srcCount 書き込むサイズです。特に指定がない場合は、(destCount - 1) を入力してください。
320 //! @param[in] format 書式です。
321 //!
322 //! @return 文字列の長さを返します。
323 //---------------------------------------------------------------------------
324 NW_INLINE int
snprintf(char * dest,std::size_t destCount,std::size_t srcCount,const char * format,...)325 snprintf(
326 char* dest,
327 std::size_t destCount,
328 std::size_t srcCount,
329 const char* format,
330 ...)
331 {
332 std::va_list vargs;
333 va_start(vargs, format);
334
335 int result = vsnprintf(dest, destCount, srcCount, format, vargs);
336
337 va_end(vargs);
338 return result;
339 }
340
341 //---------------------------------------------------------------------------
342 //! @brief 指定されたデータを書式指定して書き込みます。
343 //!
344 //! source 文字列を count 分書き込み、必ず null の終端文字を追加します。
345 //!
346 //! @param[out] dest 書き込み先のバッファのアドレスです。
347 //! @param[in] destCount 書き込み先のサイズです。
348 //! @param[in] srcCount 書き込むサイズです。特に指定がない場合は、(destCount - 1) を入力してください。
349 //! @param[in] format 書式です。
350 //!
351 //! @return 文字列の長さを返します。
352 //---------------------------------------------------------------------------
353 NW_INLINE int
snwprintf(wchar_t * dest,std::size_t destCount,std::size_t srcCount,const wchar_t * format,...)354 snwprintf(
355 wchar_t* dest,
356 std::size_t destCount,
357 std::size_t srcCount,
358 const wchar_t* format,
359 ...)
360 {
361 std::va_list vargs;
362 va_start(vargs, format);
363
364 int result = vsnwprintf(dest, destCount, srcCount, format, vargs);
365
366 va_end(vargs);
367 return result;
368 }
369
370 //---------------------------------------------------------------------------
371 //! @brief 文字列を小文字として比較します。
372 //!
373 //! @param[in] string1 比較対象の文字列です。
374 //! @param[in] string2 比較対象の文字列です。
375 //!
376 //! @return 比較結果を返します。
377 //---------------------------------------------------------------------------
378 NW_INLINE int
stricmp(const char * string1,const char * string2)379 stricmp(
380 const char *string1,
381 const char *string2)
382 {
383 #ifdef NW_COMPILER_MSVC
384 return ::_stricmp(string1, string2);
385 #else
386 return std::strcasecmp(string1, string2);
387 #endif
388 }
389
390 //@}
391
392 //----------------------------------------
393 //! @name 数値関連
394 //@{
395
396 //---------------------------------------------------------------------------
397 //! @brief 引数の絶対値を返します。
398 //!
399 //! @param[in] a
400 //!
401 //! @return a の絶対値
402 //---------------------------------------------------------------------------
403 template <typename T>
404 NW_INLINE T
Abs(T a)405 Abs(T a)
406 {
407 return (a < 0) ? static_cast<T>(-a) : a;
408 }
409
410 //---------------------------------------------------------------------------
411 //! @brief 引数の絶対値を返します。
412 //!
413 //! @param[in] a
414 //!
415 //! @return a の絶対値
416 //---------------------------------------------------------------------------
417 template<>
418 NW_INLINE float
419 Abs<float>(register float a)
420 {
421 #ifdef GEKKO
422 register float ret;
423 asm{ fabs ret, a }
424 return ret;
425 #else
426 return (a < 0) ? -a : a;
427 #endif
428 }
429
430
431 //---------------------------------------------------------------------------
432 //! @brief 2つの数値を比較して小さい方の値を返します。
433 //!
434 //! @param[in] a, b 比較する数値
435 //!
436 //! @return a, b のうち小さい方の値を返します。
437 //---------------------------------------------------------------------------
438 template <typename T>
439 NW_INLINE T
Min(T a,T b)440 Min(T a, T b)
441 {
442 return (a > b) ? b: a;
443 }
444
445
446
447 //---------------------------------------------------------------------------
448 //! @brief 2つの数値を比較して大きい方の値を返します。
449 //!
450 //! @param[in] a, b 比較する数値
451 //!
452 //! @return a, b のうち大きい方の値を返します。
453 //---------------------------------------------------------------------------
454 template <typename T>
455 NW_INLINE T
Max(T a,T b)456 Max(T a, T b)
457 {
458 return (a < b) ? b: a;
459 }
460
461
462 //---------------------------------------------------------------------------
463 //! @brief low から high の範囲に収まる値を返します。
464 //!
465 //! @param[in] x 比較する数値
466 //! @param[in] low 最小値
467 //! @param[in] high 最大値
468 //!
469 //! @return x < low ならば low, x > high ならば high それ以外は x を返します。
470 //---------------------------------------------------------------------------
471 template <typename T>
472 NW_INLINE T
Clamp(T x,T low,T high)473 Clamp(T x, T low, T high)
474 {
475 return (x > high) ? high : ( (x < low) ? low : x );
476 }
477
478
479
480 //---------------------------------------------------------------------------
481 //! @brief x を base の倍数に切り上げます。
482 //!
483 //! @param[in] x 切り上げる数。
484 //! @param[in] base 切り上げの基準となる値。
485 //! 2の累乗でなければなりません。
486 //!
487 //! @return x を base の倍数に切り上げた値を返します。
488 //---------------------------------------------------------------------------
489 template <typename ValueT> ValueT RoundUp(ValueT x, unsigned int base);
490
491 template <typename ValueT>
492 NW_INLINE void*
RoundUp(ValueT * x,unsigned int base)493 RoundUp(ValueT* x, unsigned int base)
494 {
495 IntPtr value = reinterpret_cast<IntPtr>(x);
496 IntPtr rounded = (value + (base - 1)) & ~(base - 1);
497
498 return reinterpret_cast<void*>(rounded);
499 }
500
501 template <typename ValueT>
502 NW_INLINE const void*
RoundUp(const ValueT * x,unsigned int base)503 RoundUp(const ValueT* x, unsigned int base)
504 {
505 IntPtr value = reinterpret_cast<IntPtr>(x);
506 IntPtr rounded = (value + (base - 1)) & ~(base - 1);
507
508 return reinterpret_cast<const void*>(rounded);
509 }
510
511 template <typename ValueT>
512 NW_INLINE ValueT
RoundUp(ValueT x,unsigned int base)513 RoundUp(ValueT x, unsigned int base)
514 {
515 return static_cast<ValueT>( (x + (base - 1)) & ~(base - 1) );
516 }
517
518
519 //---------------------------------------------------------------------------
520 //! @brief x を base の倍数に切り下げます。
521 //!
522 //! @param[in] x 切り下げる数。
523 //! @param[in] base 切り下げの基準となる値。2の累乗でなければなりません。
524 //!
525 //! @return x を base の倍数に切り下げた値を返します。
526 //---------------------------------------------------------------------------
527 template <typename ValueT> ValueT RoundDown(ValueT x, unsigned int base);
528
529 template <typename ValueT>
530 NW_INLINE void*
RoundDown(ValueT * x,unsigned int base)531 RoundDown(ValueT* x, unsigned int base)
532 {
533 IntPtr value = reinterpret_cast<IntPtr>(x);
534 IntPtr rounded = value & ~(base - 1);
535
536 return reinterpret_cast<void*>(rounded);
537 }
538
539 template <typename ValueT>
540 NW_INLINE const void*
RoundDown(const ValueT * x,unsigned int base)541 RoundDown(const ValueT* x, unsigned int base)
542 {
543 IntPtr value = reinterpret_cast<IntPtr>(x);
544 IntPtr rounded = value & ~(base - 1);
545
546 return reinterpret_cast<const void*>(rounded);
547 }
548
549 template <typename ValueT>
550 NW_INLINE ValueT
RoundDown(ValueT x,unsigned int base)551 RoundDown(ValueT x, unsigned int base)
552 {
553 return static_cast<ValueT>( x & ~(base - 1) );
554 }
555
556
557 //---------------------------------------------------------------------------
558 //! @brief x を y で割って端数を切り上げます。
559 //!
560 //! @param[in] x 割られる数
561 //! @param[in] y 割る数
562 //!
563 //! @return x を y で割って端数を切り上げた値を返します。
564 //---------------------------------------------------------------------------
565 NW_INLINE int
DivUp(int x,int y)566 DivUp(int x, int y)
567 {
568 return (x + (y-1)) / y;
569 }
570
571 //---------------------------------------------------------------------------
572 //! @brief 浮動少数点型を比較するための等値比較関数オブジェクトです。
573 //!
574 //! @tparam ValueT 比較する型です。
575 //---------------------------------------------------------------------------
576 template<typename ValueT>
577 class
578 CloseAtTolerance
579 {
580 public:
581 //! @brief コンストラクタです。
582 //!
583 //! @param[in] tolerance 誤差許容値です。
584 //!
CloseAtTolerance(ValueT tolerance)585 CloseAtTolerance(ValueT tolerance) : m_Tolerance(tolerance) {}
586
587 //! @brief コンストラクタです。
588 //!
589 //! @param[in] numberOfRoundingError 丸め誤差の数です。
590 //!
CloseAtTolerance(int numberOfRoundingError)591 CloseAtTolerance(int numberOfRoundingError)
592 : m_Tolerance(numberOfRoundingError * std::numeric_limits<ValueT>::epsilon() * 0.5f) {}
593
594 //! @brief 許容範囲内かどうか比較します。
595 //!
596 //! @param[in] lhs 左辺です。
597 //! @param[in] rhs 右辺です。
598 //! @return lhs と rhs の値が許容範囲内であれば true を返します。
599 //!
operator()600 bool operator()(ValueT lhs, ValueT rhs) const
601 {
602 ValueT diff = Abs(lhs - rhs);
603 return
604 diff <= (m_Tolerance * Abs(lhs)) &&
605 diff <= (m_Tolerance * Abs(rhs));
606 }
607
608 private:
609 ValueT m_Tolerance;
610 };
611
612 //---------------------------------------------------------------------------
613 //! @brief 浮動少数点型を比較するための等値比較関数オブジェクトです。
614 //!
615 //! @tparam ValueT 比較する型です。
616 //---------------------------------------------------------------------------
617 template<typename ValueT>
618 class
619 CloseAtToleranceWeak
620 {
621 public:
622 //! @brief コンストラクタです。
623 //!
624 //! @param[in] tolerance 誤差許容値です。
625 //!
CloseAtToleranceWeak(ValueT tolerance)626 CloseAtToleranceWeak(ValueT tolerance) : m_Tolerance(tolerance) {}
627
628 //! @brief コンストラクタです。
629 //!
630 //! @param[in] numberOfRoundingError 丸め誤差の数です。
631 //!
CloseAtToleranceWeak(int numberOfRoundingError)632 CloseAtToleranceWeak(int numberOfRoundingError)
633 : m_Tolerance(numberOfRoundingError * std::numeric_limits<ValueT>::epsilon() * 0.5f) {}
634
635 //! @brief 許容範囲内かどうか比較します。
636 //!
637 //! @param[in] lhs 左辺です。
638 //! @param[in] rhs 右辺です。
639 //! @return lhs と rhs の値が許容範囲内であれば true を返します。
640 //!
operator()641 bool operator()(ValueT lhs, ValueT rhs) const
642 {
643 ValueT diff = Abs(lhs - rhs);
644 return
645 diff <= (m_Tolerance * Abs(lhs)) ||
646 diff <= (m_Tolerance * Abs(rhs));
647 }
648
649 private:
650 ValueT m_Tolerance;
651 };
652
653 //---------------------------------------------------------------------------
654 //! @brief 浮動少数点型の誤差範囲を考慮した等値比較です。
655 //!
656 //! @param[in] lhs 左辺です。
657 //! @param[in] rhs 右辺です。
658 //!
659 //! @return 等値と判断されたら true を返します。
660 //---------------------------------------------------------------------------
661 template<typename ValueT>
662 NW_INLINE bool
FloatEquals(ValueT lhs,ValueT rhs)663 FloatEquals(ValueT lhs, ValueT rhs)
664 {
665 return CloseAtTolerance<ValueT>(std::numeric_limits<ValueT>::epsilon())(lhs, rhs);
666 }
667
668 //---------------------------------------------------------------------------
669 //! @brief 浮動少数点型の誤差範囲を考慮したほぼ等値比較です。
670 //!
671 //! @param[in] lhs 左辺です。
672 //! @param[in] rhs 右辺です。
673 //!
674 //! @return 等値と判断されたら true を返します。
675 //---------------------------------------------------------------------------
676 template<typename ValueT>
677 NW_INLINE bool
FloatEqualsWeak(ValueT lhs,ValueT rhs)678 FloatEqualsWeak(ValueT lhs, ValueT rhs)
679 {
680 return CloseAtToleranceWeak<ValueT>(std::numeric_limits<ValueT>::epsilon())(lhs, rhs);
681 }
682
683 //@}
684
685 //----------------------------------------
686 //! @name ビット操作関連
687 //@{
688
689 //---------------------------------------------------------------------------
690 //! @brief ビット列から部分ビット列を抜き出します。
691 //!
692 //! @param[in] bits 抜き出し元のビット列
693 //! @param[in] pos 抜き出すビット列の最下位ビットのbits中での位置
694 //! @param[in] len 抜き出すビット長
695 //!
696 //! @return 抽出したビット列。
697 //---------------------------------------------------------------------------
698 template <typename OutputT>
699 NW_INLINE OutputT
700 BitExtract(OutputT bits, int pos, int len=1)
701 {
702 const OutputT mask = static_cast<OutputT>( ( 1UL << len ) - 1 );
703 return static_cast<OutputT>( (bits >> pos) & mask );
704 }
705
706
707 //---------------------------------------------------------------------------
708 //! @brief エンディアンを反転します。
709 //!
710 //! @param[in] x 反転する数。
711 //!
712 //! @return x のエンディアンを反転して返します。
713 //---------------------------------------------------------------------------
714 NW_INLINE u32
ReverseEndian(u32 x)715 ReverseEndian( u32 x )
716 {
717 return static_cast<u32>(
718 BitExtract( x, 0, 8 ) << 24 |
719 BitExtract( x, 8, 8 ) << 16 |
720 BitExtract( x, 16, 8 ) << 8 |
721 BitExtract( x, 24, 8 ) << 0
722 );
723 }
724
725 NW_INLINE s32
ReverseEndian(s32 x)726 ReverseEndian( s32 x )
727 {
728 return static_cast<s32>(
729 BitExtract( x, 0, 8 ) << 24 |
730 BitExtract( x, 8, 8 ) << 16 |
731 BitExtract( x, 16, 8 ) << 8 |
732 BitExtract( x, 24, 8 ) << 0
733 );
734 }
735
736 NW_INLINE u16
ReverseEndian(u16 x)737 ReverseEndian( u16 x )
738 {
739 return static_cast<u16>(
740 BitExtract( x, 0, 8 ) << 8 |
741 BitExtract( x, 8, 8 ) << 0
742 );
743 }
744
745 NW_INLINE s16
ReverseEndian(s16 x)746 ReverseEndian( s16 x )
747 {
748 return static_cast<s16>(
749 BitExtract( x, 0, 8 ) << 8 |
750 BitExtract( x, 8, 8 ) << 0
751 );
752 }
753
754 //@}
755
756 //----------------------------------------
757 //! @name ポインタ操作関連
758 //@{
759
760 //---------------------------------------------------------------------------
761 //! @brief ポインタからIntPtrへのキャストをおこないます。
762 //!
763 //! @param[in] ptr ポインタ
764 //!
765 //! @return ptrをIntPtrにキャストした値を返します。
766 //---------------------------------------------------------------------------
767 NW_INLINE IntPtr
GetIntPtr(const void * ptr)768 GetIntPtr( const void* ptr )
769 {
770 return reinterpret_cast<IntPtr>( ptr );
771 }
772
773
774 //---------------------------------------------------------------------------
775 //! @brief 2つのポインタアドレスのオフセット値をlongで取得します。
776 //!
777 //! @param[in] start 開始アドレス
778 //! @param[in] end 終了アドレス
779 //!
780 //! @return 2つのポインタのオフセット値
781 //---------------------------------------------------------------------------
782 NW_INLINE PtrDiff
GetOffsetFromPtr(const void * start,const void * end)783 GetOffsetFromPtr( const void* start, const void* end )
784 {
785 return static_cast<PtrDiff>(GetIntPtr(end) - GetIntPtr(start));
786 }
787
788
789 //---------------------------------------------------------------------------
790 //! @brief ポインタにオフセット値を加えます。
791 //!
792 //! @param[in] ptr ポインタ
793 //! @param[in] offset オフセット値
794 //!
795 //! @return voidポインタ型にoffsetバイトを加えたアドレスを引数と同型のポインタとして返します。
796 //---------------------------------------------------------------------------
797 template <typename T>
798 NW_INLINE void*
AddOffsetToPtr(void * ptr,T offset)799 AddOffsetToPtr( void* ptr, T offset )
800 {
801 return reinterpret_cast<void*>( GetIntPtr(ptr) + offset );
802 }
803 template <typename T>
804 NW_INLINE const void*
AddOffsetToPtr(const void * ptr,T offset)805 AddOffsetToPtr( const void* ptr, T offset )
806 {
807 return reinterpret_cast<const void*>( GetIntPtr(ptr) + offset );
808 }
809
810
811 //---------------------------------------------------------------------------
812 //! @brief ポインタにオフセット値を加えます。
813 //!
814 //! @param[in] ptr ポインタ
815 //! @param[in] offset オフセット値
816 //!
817 //! @return voidポインタ型にoffsetバイトを加えたアドレスを引数と同型のポインタとして返します。
818 //---------------------------------------------------------------------------
819 NW_INLINE void*
AddU32ToPtr(void * ptr,u32 offset)820 AddU32ToPtr( void* ptr, u32 offset )
821 {
822 return AddOffsetToPtr( ptr, offset );
823 }
824 NW_INLINE const void*
AddU32ToPtr(const void * ptr,u32 offset)825 AddU32ToPtr( const void* ptr, u32 offset )
826 {
827 return AddOffsetToPtr( ptr, offset );
828 }
829
830 //---------------------------------------------------------------------------
831 //! @brief 2つのポインタアドレスを比較します。
832 //!
833 //! @param[in] a 比較元のポインタ
834 //! @param[in] b 比較対象となるポインタ
835 //!
836 //! @return > 0 aの指すアドレスがbの指すアドレスよりも大きい場合
837 //! = 0 aの指すアドレスとbの指すアドレスが等しい場合
838 //! < 0 aの指すアドレスがbの指すアドレスよりも小さい場合
839 //---------------------------------------------------------------------------
840 NW_INLINE int
ComparePtr(const void * a,const void * b)841 ComparePtr( const void* a, const void* b )
842 {
843 return static_cast<int>( GetIntPtr( a ) - GetIntPtr( b ) );
844 }
845
846 namespace internal {
847
848 //--------------------------------------------------------------------------
849 //! @brief ビット列から値を取り出します。
850 //!
851 //! @param[in] bits 元のビット列です。
852 //! @param[in] width ビット幅です。
853 //! @param[in] shift シフト値です。
854 //!
855 //! @return ビット長とシフト値から取得した値を返します。
856 //---------------------------------------------------------------------------
857 NW_INLINE u32
ReadBits(u32 bits,s32 width,s32 shift)858 ReadBits(u32 bits, s32 width, s32 shift)
859 {
860 return (u32(bits) >> shift) & ((0x1U << width) - 1);
861 }
862
863 //--------------------------------------------------------------------------
864 //! @brief ビット長とシフト値を指定してマスクされたビット列を取得します。
865 //!
866 //! @param[in] value ビット列に対して設定する値です。
867 //! @param[in] width ビット幅です。
868 //! @param[in] shift シフト値です。
869 //!
870 //! @return ビット長とシフト値から生成したビット列を返します。
871 //---------------------------------------------------------------------------
872 template <typename T>
873 NW_INLINE u32
MakeBits(T value,s32 width,s32 shift)874 MakeBits(T value, s32 width, s32 shift)
875 {
876 return (u32(value) & ((0x1U << width) - 1)) << shift;
877 }
878
879 //--------------------------------------------------------------------------
880 //! @brief ビット列に特定の値を書き込みます。
881 //!
882 //! @param[in] bits 元ビット列です。
883 //! @param[in] value ビット列の一部を置き換える為の値です。
884 //! @param[in] width ビット幅です。
885 //! @param[in] shift シフト値です。
886 //!
887 //! @return 置き換え後のビット列を返します。
888 //---------------------------------------------------------------------------
889 template <typename T>
890 NW_INLINE u32
WriteBits(u32 bits,T value,s32 width,s32 shift)891 WriteBits(u32 bits, T value, s32 width, s32 shift)
892 {
893 u32 mask = (0x1U << width) - 1;
894
895 return (bits & ~(mask << shift)) | ((u32(value) & mask) << shift);
896 }
897
898 template <typename T>
899 __forceinline
900 bool
TestBit(T bits,int pos)901 TestBit(
902 T bits,
903 int pos
904 )
905 {
906 const T mask = T(1 << pos);
907
908 return 0 != (bits & mask);
909 }
910
911 template <typename T>
912 __forceinline
913 T
GetBits(T bits,int pos,int len)914 GetBits(
915 T bits,
916 int pos,
917 int len
918 )
919 {
920 NW_ASSERT(len <= 32);
921 const u32 mask = ~(0xFFFFFFFFU << len);
922
923 return T((bits >> pos) & mask);
924 }
925
926 } // internal
927
928 //@}
929
930 //----------------------------------------
931 //! @name オブジェクト破棄
932 //@{
933
934 //---------------------------------------------------------------------------
935 //! @brief オブジェクトを削除後に0を設定するためのインライン関数です。
936 //!
937 //! @tparam TObject 削除するオブジェクトの型です。
938 //!
939 //! @param[in] object 削除するオブジェクトです。
940 //---------------------------------------------------------------------------
941 template<typename TObject>
942 NW_INLINE void
SafeDestroy(TObject * & object)943 SafeDestroy(
944 TObject*& object
945 )
946 {
947 if (object == NULL) { return; }
948 object->Destroy();
949 object = NULL;
950 }
951
952 //---------------------------------------------------------------------------
953 //! @brief SafeDestroy でオブジェクトを破棄するためのデリーターです。
954 //!
955 //! @tparam TObject 削除するオブジェクトの型です。
956 //---------------------------------------------------------------------------
957 template<typename TObject>
958 struct SafeDestroyer : public std::unary_function<TObject&, void>
959 {
960 //! オブジェクトを破棄します。
operatorSafeDestroyer961 void operator()(TObject& object) const
962 {
963 SafeDestroy(object);
964 }
965 };
966
967 //---------------------------------------------------------------------------
968 //! @brief SafeDestroy でコンテナ要素の全てのオブジェクトを破棄するための関数です。
969 //!
970 //! @tparam TArray 削除するオブジェクトの型です。
971 //!
972 //! @param[in] array 削除するオブジェクトの配列です。
973 //---------------------------------------------------------------------------
974 template<typename TArray>
975 NW_INLINE void
SafeDestroyAll(TArray & array)976 SafeDestroyAll(
977 TArray& array
978 )
979 {
980 std::for_each(array.begin(), array.end(), SafeDestroyer<typename TArray::value_type>());
981 array.clear();
982 }
983
984 //@}
985
986 } /* namespace ut */
987 } /* namespace nw */
988
989 #endif // NW_UT_INLINES_H_
990