Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers smallest_generator.h Source File

smallest_generator.h

Go to the documentation of this file.
00001 ///\file
00002 
00003 /******************************************************************************
00004 The MIT License(MIT)
00005 
00006 Embedded Template Library.
00007 https://github.com/ETLCPP/etl
00008 https://www.etlcpp.com
00009 
00010 Copyright(c) 2014 jwellbelove
00011 
00012 Permission is hereby granted, free of charge, to any person obtaining a copy
00013 of this software and associated documentation files(the "Software"), to deal
00014 in the Software without restriction, including without limitation the rights
00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00016 copies of the Software, and to permit persons to whom the Software is
00017 furnished to do so, subject to the following conditions :
00018 
00019 The above copyright notice and this permission notice shall be included in all
00020 copies or substantial portions of the Software.
00021 
00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00028 SOFTWARE.
00029 ******************************************************************************/
00030 
00031 /*[[[cog
00032 import cog
00033 cog.outl("#if 0")
00034 ]]]*/
00035 /*[[[end]]]*/
00036 #error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
00037 /*[[[cog
00038 import cog
00039 cog.outl("#endif")
00040 ]]]*/
00041 /*[[[end]]]*/
00042 
00043 /*[[[cog
00044 import cog
00045 cog.outl("//***************************************************************************")
00046 cog.outl("// This file has been auto generated. Do not edit this file.")
00047 cog.outl("//***************************************************************************")
00048 ]]]*/
00049 /*[[[end]]]*/
00050 
00051 //***************************************************************************
00052 // To generate to header file, run this at the command line.
00053 // Note: You will need Python and COG installed.
00054 //
00055 // python -m cogapp -d -e -osmallest.h -DNTypes=<n> smallest_generator.h
00056 // Where <n> is the number of types to support.
00057 //
00058 // e.g.
00059 // To generate handlers for up to 16 types...
00060 // python -m cogapp -d -e -osmallest.h -DNTypes=16 smallest_generator.h
00061 //
00062 // See generate.bat
00063 //***************************************************************************
00064 
00065 #ifndef __ETL_SMALLEST__
00066 #define __ETL_SMALLEST__
00067 
00068 #include <stdint.h>
00069 
00070 #include "platform.h "
00071 #include "integral_limits.h "
00072 
00073 ///\defgroup smallest smallest
00074 ///\ingroup utilities
00075 
00076 namespace etl
00077 {
00078   /*[[[cog
00079   import cog
00080   cog.outl("//***************************************************************************")
00081   cog.outl("/// Template to determine the smallest type and size.")
00082   cog.outl("/// Supports up to %s types." % NTypes)
00083   cog.outl("/// Defines 'value_type' which is the type of the smallest parameter.")
00084   cog.outl("/// Defines 'size' which is the size of the smallest parameter.")
00085   cog.outl("///\ingroup smallest")
00086   cog.outl("//***************************************************************************")
00087   cog.out("template <typename T1, ")
00088   for n in range(2, int(NTypes)):
00089       cog.out("typename T%s = void, " % n)
00090       if n % 4 == 0:
00091           cog.outl("")
00092           cog.out("          ")
00093   cog.outl("typename T%s = void>" % int(NTypes))
00094   cog.outl("struct smallest_type")
00095   cog.outl("{")
00096   cog.outl("private:")
00097   cog.outl("")
00098   cog.outl("  // Declaration.")
00099   cog.outl("  template <const bool Boolean, typename TrueType, typename FalseType>")
00100   cog.outl("  struct choose_type;")
00101   cog.outl("")
00102   cog.outl("  // Specialisation for 'true'.")
00103   cog.outl("  // Defines 'type' as 'TrueType'.")
00104   cog.outl("  template <typename TrueType, typename FalseType>")
00105   cog.outl("  struct choose_type<true, TrueType, FalseType>")
00106   cog.outl("  {")
00107   cog.outl("    typedef TrueType type;")
00108   cog.outl("  };")
00109   cog.outl("")
00110   cog.outl("  // Specialisation for 'false'. ")
00111   cog.outl("  // Defines 'type' as 'FalseType'.")
00112   cog.outl("  template <typename TrueType, typename FalseType>")
00113   cog.outl("  struct choose_type<false, TrueType, FalseType>")
00114   cog.outl("  {")
00115   cog.outl("    typedef FalseType type;")
00116   cog.outl("  };")
00117   cog.outl("")
00118   cog.outl("public:")
00119   cog.outl("")
00120   cog.outl("  // Define 'smallest_other' as 'smallest_type' with all but the first parameter. ")
00121   cog.out("  typedef typename smallest_type<")
00122   for n in range(2, int(NTypes)):
00123       cog.out("T%s, " % n)
00124       if n % 16 == 0:
00125           cog.outl("")
00126           cog.out("                                ")
00127   cog.outl("T%s>::type smallest_other;" % int(NTypes))
00128   cog.outl("")
00129   cog.outl("  // Set 'type' to be the smallest of the first parameter and any of the others.")
00130   cog.outl("  // This is recursive.")
00131   cog.outl("  typedef typename choose_type<(sizeof(T1) < sizeof(smallest_other)), // Boolean")
00132   cog.outl("                                T1,                                   // TrueType")
00133   cog.outl("                                smallest_other>                       // FalseType")
00134   cog.outl("                                ::type type;                          // The smallest type of the two.")
00135   cog.outl("")
00136   cog.outl("  // The size of the smallest type.")
00137   cog.outl("  enum")
00138   cog.outl("  {")
00139   cog.outl("    size = sizeof(type)")
00140   cog.outl("  };")
00141   cog.outl("};")
00142   cog.outl("")
00143   cog.outl("//***************************************************************************")
00144   cog.outl("// Specialisation for one template parameter.")
00145   cog.outl("//***************************************************************************")
00146   cog.outl("template <typename T1>")
00147   cog.out("struct smallest_type<T1,   ")
00148   for n in range(2, int(NTypes)):
00149       cog.out("void, ")
00150       if n % 8 == 0:
00151           cog.outl("")
00152           cog.out("                     ")
00153   cog.outl("void>")
00154   cog.outl("{")
00155   cog.outl("  typedef T1 type;")
00156   cog.outl("")
00157   cog.outl("  enum")
00158   cog.outl("  {")
00159   cog.outl("    size = sizeof(type)")
00160   cog.outl("  };")
00161   cog.outl("};")
00162   ]]]*/
00163   /*[[[end]]]*/
00164   
00165   namespace __private_smallest__
00166   {
00167     //*************************************************************************
00168     // Determine the type to hold the number of bits based on the index.
00169     //*************************************************************************
00170     template <const int index>
00171     struct best_fit_uint_type;
00172     
00173     //*************************************************************************
00174     // Less than or equal to 8 bits.
00175     //*************************************************************************
00176     template <>
00177     struct best_fit_uint_type<0>
00178     {
00179       typedef uint_least8_t type;
00180     };
00181 
00182     //*************************************************************************
00183     // 9 to 16 bits.
00184     //*************************************************************************
00185     template <>
00186     struct best_fit_uint_type<1>
00187     {
00188       typedef uint_least16_t type;
00189     };
00190 
00191     //*************************************************************************
00192     // 17 to 31 bits.
00193     //*************************************************************************
00194     template <>
00195     struct best_fit_uint_type<2>
00196     {
00197       typedef uint_least32_t type;
00198     };
00199 
00200     //*************************************************************************
00201     // Greater than 32 bits.
00202     //*************************************************************************
00203     template <>
00204     struct best_fit_uint_type<3>
00205     {
00206       typedef uint_least64_t type;
00207     };
00208 
00209     //*************************************************************************
00210     // Determine the type to hold the number of bits based on the index.
00211     //*************************************************************************
00212     template <const int index>
00213     struct best_fit_int_type;
00214 
00215     //*************************************************************************
00216     // Less than or equal to 8 bits.
00217     //*************************************************************************
00218     template <>
00219     struct best_fit_int_type<0>
00220     {
00221       typedef int_least8_t type;
00222     };
00223 
00224     //*************************************************************************
00225     // 9 to 16 bits.
00226     //*************************************************************************
00227     template <>
00228     struct best_fit_int_type<1>
00229     {
00230       typedef int_least16_t type;
00231     };
00232 
00233     //*************************************************************************
00234     // 17 to 31 bits.
00235     //*************************************************************************
00236     template <>
00237     struct best_fit_int_type<2>
00238     {
00239       typedef int_least32_t type;
00240     };
00241 
00242     //*************************************************************************
00243     // Greater than 32 bits.
00244     //*************************************************************************
00245     template <>
00246     struct best_fit_int_type<3>
00247     {
00248       typedef int_least64_t type;
00249     };
00250   }
00251 
00252   //***************************************************************************
00253   /// Template to determine the smallest unsigned int type that can contain a 
00254   /// value with the specified number of bits.
00255   /// Defines 'type' which is the type of the smallest unsigned integer.
00256   ///\ingroup smallest
00257   //***************************************************************************
00258   template <const size_t NBITS>
00259   struct smallest_uint_for_bits
00260   {
00261   private:
00262     
00263     // Determines the index of the best unsigned type for the required number of bits.
00264     static const int TYPE_INDEX = ((NBITS >  8) ? 1 : 0) + 
00265                                   ((NBITS > 16) ? 1 : 0) +
00266                                   ((NBITS > 32) ? 1 : 0);
00267 
00268   public:
00269 
00270     typedef typename __private_smallest__::best_fit_uint_type<TYPE_INDEX>::type type;
00271   };
00272 
00273   //***************************************************************************
00274   /// Template to determine the smallest signed int type that can contain a 
00275   /// value with the specified number of bits.
00276   /// Defines 'type' which is the type of the smallest signed integer.
00277   ///\ingroup smallest
00278   //***************************************************************************
00279   template <const size_t NBITS>
00280   struct smallest_int_for_bits
00281   {
00282   private:
00283 
00284     // Determines the index of the best unsigned type for the required number of bits.
00285     static const int TYPE_INDEX = ((NBITS >  8) ? 1 : 0) +
00286                                   ((NBITS > 16) ? 1 : 0) +
00287                                   ((NBITS > 32) ? 1 : 0);
00288 
00289   public:
00290 
00291     typedef typename __private_smallest__::best_fit_int_type<TYPE_INDEX>::type type;
00292   };
00293 
00294   //***************************************************************************
00295   /// Template to determine the smallest unsigned int type that can contain the
00296   /// specified unsigned value.
00297   /// Defines 'type' which is the type of the smallest unsigned integer.
00298   ///\ingroup smallest
00299   //***************************************************************************
00300   template <const uintmax_t VALUE>
00301   struct smallest_uint_for_value
00302   {
00303   private:
00304 
00305     // Determines the index of the best unsigned type for the required value.
00306     static const int TYPE_INDEX = ((VALUE > UINT_LEAST8_MAX)  ? 1 : 0) +
00307                                   ((VALUE > UINT16_MAX) ? 1 : 0) + 
00308                                   ((VALUE > UINT32_MAX) ? 1 : 0);
00309 
00310   public:
00311 
00312     typedef typename __private_smallest__::best_fit_uint_type<TYPE_INDEX>::type type;
00313   };
00314 
00315   //***************************************************************************
00316   /// Template to determine the smallest int type that can contain the
00317   /// specified signed value.
00318   /// Defines 'type' which is the type of the smallest signed integer.
00319   ///\ingroup smallest
00320   //***************************************************************************
00321   template <const intmax_t VALUE>
00322   struct smallest_int_for_value
00323   {
00324   private:
00325 
00326     // Determines the index of the best signed type for the required value.
00327     static const int TYPE_INDEX = (((VALUE > INT_LEAST8_MAX)  || (VALUE < INT_LEAST8_MIN))  ? 1 : 0) + 
00328                                   (((VALUE > INT16_MAX) || (VALUE < INT16_MIN)) ? 1 : 0) +
00329                                   (((VALUE > INT32_MAX) || (VALUE < INT32_MIN)) ? 1 : 0);
00330 
00331   public:
00332 
00333     typedef typename __private_smallest__::best_fit_int_type<TYPE_INDEX>::type type;
00334   };
00335 }
00336 
00337 #endif
00338