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