TooN 2.1
|
00001 // -*- c++ -*- 00002 00003 // Copyright (C) 2009 Ed Rosten (er258@cam.ac.uk) 00004 // 00005 // This file is part of the TooN Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 2, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // You should have received a copy of the GNU General Public License along 00017 // with this library; see the file COPYING. If not, write to the Free 00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00019 // USA. 00020 00021 // As a special exception, you may use this file as part of a free software 00022 // library without restriction. Specifically, if other files instantiate 00023 // templates or use macros or inline functions from this file, or you compile 00024 // this file and link it with other files to produce an executable, this 00025 // file does not by itself cause the resulting executable to be covered by 00026 // the GNU General Public License. This exception does not however 00027 // invalidate any other reasons why the executable file might be covered by 00028 // the GNU General Public License. 00029 00030 namespace TooN { 00031 00032 namespace Internal 00033 { 00034 template<bool StaticBad> 00035 struct BadSlice; 00036 00037 ///@internal 00038 ///@brief A static slice is OK. 00039 ///This class is used after it has been determined that a slice is OK. 00040 ///It does nothing except provide a callable function. By contrast, 00041 ///if the slice is not OK, then the class is not specified and the function 00042 ///is therefore not callable, and a compile error results. 00043 ///@ingroup gInternal 00044 template<> 00045 struct BadSlice<0>{ 00046 static void check(){} ///<This function does nothing: it merely exists. 00047 }; 00048 00049 ///@internal 00050 ///@brief Check if a slice is OK. 00051 ///This class is used to see if a slice is OK. It provides a 00052 ///callable function which checks the run-time slice information. 00053 ///If the compile time information is bad, then it will not compile 00054 ///at all. Otherwise, the sizes are checked at run-time. The check 00055 ///will be optimized away if the sizes are known statically. 00056 ///@ingroup gInternal 00057 template<int Size, int Start, int Length> 00058 struct CheckSlice 00059 { 00060 00061 ///@internal 00062 ///@brief choose a number statically or dynamically. 00063 template<int Num> struct N 00064 { 00065 static int n(int num) 00066 { 00067 return (Num==Dynamic||Num==Resizable)?num:Num; 00068 } 00069 }; 00070 00071 ///@internal 00072 ///@brief Check the slice. 00073 ///This is full static checking, which is stricter than 00074 ///mixed chacking. For instance, none of the slice parameters. This 00075 ///should be used in addition to the other check function. 00076 ///are allowed to be -1 (Dynamic). 00077 static void check() 00078 { 00079 //Sanity check all basic static sizes 00080 BadSlice<!(Size== Dynamic || Size==Resizable || Size > 0)>::check(); 00081 BadSlice<!(Start >= 0)>::check(); 00082 BadSlice<!(Length >= 0)>::check(); 00083 BadSlice<(Size != Dynamic && Size != Resizable && (Start + Length > Size))>::check(); 00084 } 00085 00086 ///@internal 00087 ///@brief Check the slice. 00088 ///The policy is that static sized where present are used. 00089 ///However, for extra debugging one can test to see if the 00090 ///static and dynamic sizes are mismatched. 00091 ///any sense whatsoever. 00092 ///@param size Vector size 00093 ///@param start Start position of the slice 00094 ///@param length Length of the slice. 00095 static void check(int size, int start, int length) 00096 { 00097 //Sanity check all basic static sizes 00098 BadSlice<!(Size == Dynamic || Size==Resizable || Size > 0)>::check(); 00099 BadSlice<!(Start == Dynamic || Start >= 0)>::check(); 00100 BadSlice<!(Length == Dynamic || Length >= 0)>::check(); 00101 00102 //We can make sure Length <= Size, even if Start is unknown 00103 BadSlice<(Size!=Dynamic && Size != Resizable && Length != Dynamic && Length > Size)>::check(); 00104 00105 //We can make sure Start < Size even if Length is unknown 00106 BadSlice<(Start != Dynamic && Size != Dynamic && Size != Resizable && Start > Size)>::check(); 00107 00108 BadSlice<(Size != Dynamic && Size != Resizable && Start != Dynamic && Length != Dynamic && Start + Length > Size)>::check(); 00109 #ifndef TOON_NDEBUG_MISMATCH 00110 if(Start != Dynamic && Size != Resizable && Start != start) 00111 { 00112 std::cerr << "TooN slice: mismatch between static and dynamic start.\n"; 00113 std::abort(); 00114 } 00115 if(Length != Dynamic && Size != Resizable && Length != length) 00116 { 00117 std::cerr << "TooN slice: mismatch between static and dynamic length.\n"; 00118 std::abort(); 00119 } 00120 if(Size != Dynamic && Size != Resizable && Size != size) 00121 { 00122 std::cerr << "TooN slice: mismatch between static and dynamic size.\n"; 00123 std::abort(); 00124 } 00125 #endif 00126 if( N<Start>::n(start) + N<Length>::n(length) > N<Size>::n(size) || 00127 N<Start>::n(start) < 0 || 00128 N<Length>::n(length) < 0) 00129 { 00130 #ifdef TOON_TEST_INTERNALS 00131 throw Internal::SliceError(); 00132 #elif !defined TOON_NDEBUG_SLICE 00133 std::cerr << "TooN slice out of range" << std::endl; 00134 std::abort(); 00135 #endif 00136 } 00137 } 00138 }; 00139 00140 #ifdef TOON_TEST_INTERNALS 00141 template<bool StaticBad> 00142 struct BadSlice{ 00143 static void check(){ 00144 throw Internal::StaticSliceError(); 00145 } 00146 }; 00147 #endif 00148 } 00149 00150 }