TooN 2.1
internal/slice_error.hh
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 }