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