TooN: internal/slice_error.hh Source File

TooN 2.0.0-beta8

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

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 }