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