Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers intrusive_links.h Source File

intrusive_links.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 http://www.etlcpp.com
00009 
00010 Copyright(c) 2016 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 #ifndef __ETL_INTRUSIVE_LINKS__
00032 #define __ETL_INTRUSIVE_LINKS__
00033 
00034 #include <assert.h>
00035 #include <utility>
00036 
00037 #include "platform.h "
00038 #include "nullptr.h "
00039 #include "type_traits.h "
00040 #include "exception.h "
00041 #include "error_handler.h "
00042 
00043 #undef ETL_FILE
00044 #define ETL_FILE "22"
00045 
00046 //*****************************************************************************
00047 // Note:
00048 // The link functions work slightly differently to the STL 'insert' convention
00049 // in that the second link parameter will be inserted after the first.
00050 // i.e.
00051 // If the list contains '1', '2', '3', '4' and "link_splice '2','5'" is invoked the
00052 // resulting list will contain '1', '2', '5', '3', '4'
00053 // This is to maintain consistency between forward and bidirectional links
00054 // and also is intuitive.
00055 //*****************************************************************************
00056 
00057 namespace etl
00058 {
00059   //***************************************************************************
00060   /// Link exception.
00061   //***************************************************************************
00062   class link_exception : public etl::exception
00063   {
00064   public:
00065 
00066     link_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
00067       : exception(reason_, file_name_, line_number_)
00068     {
00069     }
00070   };
00071 
00072   //***************************************************************************
00073   /// not unlinked exception.
00074   //***************************************************************************
00075   class not_unlinked_exception : public etl::link_exception
00076   {
00077   public:
00078 
00079     not_unlinked_exception(string_type file_name_, numeric_type line_number_)
00080       : link_exception(ETL_ERROR_TEXT("link:still linked", ETL_FILE"A"), file_name_, line_number_)
00081     {
00082     }
00083   };
00084 
00085   //***************************************************************************
00086   /// A forward link.
00087   //***************************************************************************
00088   template <const size_t ID_>
00089   struct forward_link
00090   {
00091       enum
00092       {
00093         ID = ID_,
00094       };
00095 
00096       void clear()
00097       {
00098         etl_next = std::nullptr;
00099       }
00100 
00101       bool is_linked() const
00102       {
00103         return etl_next != std::nullptr;
00104       }
00105 
00106       forward_link* etl_next;
00107   };
00108 
00109   // Reference, Reference
00110   template <typename TLink>
00111   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00112   link(TLink& lhs, TLink& rhs)
00113   {
00114     lhs.etl_next = &rhs;
00115   }
00116 
00117   // Reference, Reference
00118   template <typename TLink>
00119   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00120   link_splice(TLink& lhs, TLink& rhs)
00121   {
00122     rhs.etl_next = lhs.etl_next;
00123     lhs.etl_next = &rhs;
00124   }
00125 
00126   // Pointer, Pointer
00127   template <typename TLink>
00128   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00129   link(TLink* lhs, TLink* rhs)
00130   {
00131     if (lhs != std::nullptr)
00132     {
00133       lhs->etl_next = rhs;
00134     }
00135   }
00136 
00137   // Pointer, Pointer
00138   template <typename TLink>
00139   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00140   link_splice(TLink* lhs, TLink* rhs)
00141   {
00142     if (lhs != std::nullptr)
00143     {
00144       if (rhs != std::nullptr)
00145       {
00146           rhs->etl_next = lhs->etl_next;
00147       }
00148 
00149       lhs->etl_next = rhs;
00150     }
00151   }
00152 
00153   // Reference, Pointer
00154   template <typename TLink>
00155   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00156   link(TLink& lhs, TLink* rhs)
00157   {
00158     lhs.etl_next = rhs;
00159   }
00160 
00161   // Reference, Pointer
00162   template <typename TLink>
00163   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00164   link_splice(TLink& lhs, TLink* rhs)
00165   {
00166     if (rhs != std::nullptr)
00167     {
00168       rhs->etl_next = lhs.etl_next;
00169     }
00170 
00171     lhs.etl_next = rhs;
00172   }
00173 
00174   // Pointer, Reference
00175   template <typename TLink>
00176   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00177   link(TLink* lhs, TLink& rhs)
00178   {
00179     if (lhs != std::nullptr)
00180     {
00181       lhs->etl_next = &rhs;
00182     }
00183   }
00184 
00185   // Pointer, Reference
00186   template <typename TLink>
00187   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00188   link_splice(TLink* lhs, TLink& rhs)
00189   {
00190     if (lhs != std::nullptr)
00191     {
00192       rhs.etl_next  = lhs->etl_next;
00193       lhs->etl_next = &rhs;
00194     }
00195   }
00196 
00197   // Reference, Reference, Reference
00198   template <typename TLink>
00199   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00200   link_splice(TLink& lhs, TLink& first, TLink& last)
00201   {
00202     last.etl_next = lhs.etl_next;
00203     lhs.etl_next  = &first;
00204   }
00205 
00206   // Pointer, Reference, Reference
00207   template <typename TLink>
00208   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00209   link_splice(TLink* lhs, TLink& first, TLink& last)
00210   {
00211     if (lhs != std::nullptr)
00212     {
00213       last.etl_next = lhs->etl_next;
00214       lhs->etl_next  = &first;
00215     }
00216     else
00217     {
00218       last.etl_next = std::nullptr;
00219     }
00220   }
00221 
00222   // Reference
00223   template <typename TLink>
00224   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00225   unlink_after(TLink& node)
00226   {
00227     if (node.etl_next != std::nullptr)
00228     {
00229       TLink* unlinked_node = node.etl_next;
00230       node.etl_next = unlinked_node->etl_next;
00231     }
00232   }
00233 
00234   // Reference, Reference
00235   template <typename TLink>
00236   typename etl::enable_if<etl::is_same<TLink, etl::forward_link<TLink::ID> >::value, void>::type
00237   unlink_after(TLink& before, TLink& last)
00238   {
00239     before.etl_next = last.etl_next;
00240   }
00241 
00242   //***************************************************************************
00243   /// A bidirectional link.
00244   //***************************************************************************
00245   template <const size_t ID_>
00246   struct bidirectional_link
00247   {
00248       enum
00249       {
00250         ID = ID_,
00251       };
00252 
00253       void clear()
00254       {
00255         etl_previous = std::nullptr;
00256         etl_next     = std::nullptr;
00257       }
00258 
00259       bool is_linked() const
00260       {
00261         return (etl_previous != std::nullptr) || (etl_next != std::nullptr);
00262       }
00263 
00264       void reverse()
00265       {
00266         std::swap(etl_previous, etl_next);
00267       }
00268 
00269       bidirectional_link* etl_previous;
00270       bidirectional_link* etl_next;
00271 
00272     void unlink()
00273     {
00274         // Connect the previous link with the next.
00275         if (etl_previous != std::nullptr)
00276         {
00277           etl_previous->etl_next = etl_next;
00278         }
00279 
00280         // Connect the next link with the previous.
00281         if (etl_next != std::nullptr)
00282         {
00283           etl_next->etl_previous = etl_previous;
00284         }
00285     }
00286   };
00287 
00288   // Reference, Reference
00289   template <typename TLink>
00290   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00291   link(TLink& lhs, TLink& rhs)
00292   {
00293     lhs.etl_next     = &rhs;
00294     rhs.etl_previous = &lhs;
00295   }
00296 
00297   // Reference, Reference
00298   template <typename TLink>
00299   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00300   link_splice(TLink& lhs, TLink& rhs)
00301   {
00302     rhs.etl_next     = lhs.etl_next;
00303     rhs.etl_previous = &lhs;
00304 
00305     if (lhs.etl_next != std::nullptr)
00306     {
00307       lhs.etl_next->etl_previous = &rhs;
00308     }
00309 
00310     lhs.etl_next = &rhs;
00311   }
00312 
00313   // Pointer, Pointer
00314   template <typename TLink>
00315   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00316   link(TLink* lhs, TLink* rhs)
00317   {
00318     if (lhs != std::nullptr)
00319     {
00320       lhs->etl_next = rhs;
00321     }
00322 
00323     if (rhs != std::nullptr)
00324     {
00325       rhs->etl_previous = lhs;
00326     }
00327   }
00328 
00329   // Pointer, Pointer
00330   template <typename TLink>
00331   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00332   link_splice(TLink* lhs, TLink* rhs)
00333   {
00334     if (rhs != std::nullptr)
00335     {
00336       if (lhs != std::nullptr)
00337       {
00338         rhs->etl_next = lhs->etl_next;
00339       }
00340 
00341       rhs->etl_previous = lhs;
00342     }
00343 
00344     if (lhs != std::nullptr)
00345     {
00346       if (lhs->etl_next != std::nullptr)
00347       {
00348         lhs->etl_next->etl_previous = rhs;
00349       }
00350 
00351       lhs->etl_next = rhs;
00352     }
00353   }
00354 
00355   // Reference, Pointer
00356   template <typename TLink>
00357   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00358   link(TLink& lhs, TLink* rhs)
00359   {
00360     lhs.etl_next = rhs;
00361 
00362     if (rhs != std::nullptr)
00363     {
00364       rhs->etl_previous = &lhs;
00365     }
00366   }
00367 
00368   // Reference, Pointer
00369   template <typename TLink>
00370   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00371   link_splice(TLink& lhs, TLink* rhs)
00372   {
00373     if (rhs != std::nullptr)
00374     {
00375       rhs->etl_next     = lhs.etl_next;
00376       rhs->etl_previous = &lhs;
00377     }
00378 
00379     if (lhs.etl_next != std::nullptr)
00380     {
00381       lhs.etl_next->etl_previous = rhs;
00382     }
00383 
00384     lhs.etl_next = rhs;
00385   }
00386 
00387   // Pointer, Reference
00388   template <typename TLink>
00389   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00390   link(TLink* lhs, TLink& rhs)
00391   {
00392     if (lhs != std::nullptr)
00393     {
00394       lhs->etl_next = &rhs;
00395     }
00396 
00397     rhs.etl_previous = lhs;
00398   }
00399 
00400   // Pointer, Reference
00401   template <typename TLink>
00402   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00403   link_splice(TLink* lhs, TLink& rhs)
00404   {
00405     if (lhs != std::nullptr)
00406     {
00407       rhs.etl_next = lhs->etl_next;
00408     }
00409 
00410     rhs.etl_previous = lhs;
00411 
00412     if (lhs != std::nullptr)
00413     {
00414       if (lhs->etl_next != std::nullptr)
00415       {
00416         lhs->etl_next->etl_previous = &rhs;
00417       }
00418 
00419       lhs->etl_next = &rhs;
00420     }
00421   }
00422 
00423   // Reference, Reference, Reference
00424   template <typename TLink>
00425   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00426   link_splice(TLink& lhs, TLink& first, TLink& last)
00427   {
00428     last.etl_next = lhs.etl_next;
00429     first.etl_previous = &lhs;
00430 
00431     if (last.etl_next != std::nullptr)
00432     {
00433       last.etl_next->etl_previous = &last;
00434     }
00435 
00436     lhs.etl_next = &first;
00437   }
00438 
00439   // Pointer, Reference, Reference
00440   template <typename TLink>
00441   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00442   link_splice(TLink* lhs, TLink& first, TLink& last)
00443   {
00444     if (lhs != std::nullptr)
00445     {
00446       last.etl_next = lhs->etl_next;
00447     }
00448     else
00449     {
00450       last.etl_next = std::nullptr;
00451     }
00452 
00453     first.etl_previous = lhs;
00454 
00455     if (last.etl_next != std::nullptr)
00456     {
00457       last.etl_next->etl_previous = &last;
00458     }
00459 
00460     if (lhs != std::nullptr)
00461     {
00462       lhs->etl_next = &first;
00463     }
00464   }
00465 
00466   // Reference
00467   template <typename TLink>
00468   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00469   unlink(TLink& node)
00470   {
00471     node.unlink();
00472   }
00473 
00474   // Reference Reference
00475   template <typename TLink>
00476   typename etl::enable_if<etl::is_same<TLink, etl::bidirectional_link<TLink::ID> >::value, void>::type
00477   unlink(TLink& first, TLink& last)
00478   {
00479     if (&first == &last)
00480     {
00481       first.unlink();
00482     }
00483     else
00484     {
00485       if (last.etl_next != std::nullptr)
00486       {
00487         last.etl_next->etl_previous = first.etl_previous;
00488       }
00489 
00490       if (first.etl_previous != std::nullptr)
00491       {
00492         first.etl_previous->etl_next = last.etl_next;
00493       }
00494     }
00495   }
00496 
00497   //***************************************************************************
00498   /// A binary tree link.
00499   //***************************************************************************
00500   template <const size_t ID_>
00501   struct tree_link
00502   {
00503       enum
00504       {
00505         ID = ID_,
00506       };
00507 
00508       void clear()
00509       {
00510         etl_parent = std::nullptr;
00511         etl_left   = std::nullptr;
00512         etl_right  = std::nullptr;
00513       }
00514 
00515       bool is_linked() const
00516       {
00517         return (etl_parent != std::nullptr) || (etl_left != std::nullptr) || (etl_right != std::nullptr);
00518       }
00519 
00520       tree_link* etl_parent;
00521       tree_link* etl_left;
00522       tree_link* etl_right;
00523   };
00524 
00525   // Reference, Reference
00526   template <typename TLink>
00527   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00528   link_left(TLink& parent, TLink& leaf)
00529   {
00530     parent.etl_left = &leaf;
00531     leaf.etl_parent = &parent;
00532   }
00533 
00534   template <typename TLink>
00535   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00536   link_right(TLink& parent, TLink& leaf)
00537   {
00538     parent.etl_right = &leaf;
00539     leaf.etl_parent  = &parent;
00540   }
00541 
00542   // Pointer, Pointer
00543   template <typename TLink>
00544   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00545   link_left(TLink* parent, TLink* leaf)
00546   {
00547     if (parent != std::nullptr)
00548     {
00549       parent->etl_left = leaf;
00550     }
00551 
00552     if (leaf != std::nullptr)
00553     {
00554       leaf->etl_parent = parent;
00555     }
00556   }
00557 
00558   template <typename TLink>
00559   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00560   link_right(TLink* parent, TLink* leaf)
00561   {
00562     if (parent != std::nullptr)
00563     {
00564       parent->etl_right = leaf;
00565     }
00566 
00567     if (leaf != std::nullptr)
00568     {
00569       leaf->etl_parent = parent;
00570     }
00571   }
00572 
00573   // Reference, Pointer
00574   template <typename TLink>
00575   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00576   link_left(TLink& parent, TLink* leaf)
00577   {
00578     parent.etl_left = leaf;
00579 
00580     if (leaf != std::nullptr)
00581     {
00582       leaf->etl_parent = &parent;
00583     }
00584   }
00585 
00586   template <typename TLink>
00587   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00588   link_right(TLink& parent, TLink* leaf)
00589   {
00590     parent.etl_right = leaf;
00591 
00592     if (leaf != std::nullptr)
00593     {
00594       leaf->etl_parent = &parent;
00595     }
00596   }
00597 
00598   // Pointer, Reference
00599   template <typename TLink>
00600   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00601   link_left(TLink* parent, TLink& leaf)
00602   {
00603     if (parent != std::nullptr)
00604     {
00605       parent->etl_left = &leaf;
00606     }
00607 
00608     leaf.etl_parent = parent;
00609   }
00610 
00611   template <typename TLink>
00612   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00613   link_right(TLink* parent, TLink& leaf)
00614   {
00615     if (parent != std::nullptr)
00616     {
00617       parent->etl_right = &leaf;
00618     }
00619 
00620     leaf.etl_parent = parent;
00621   }
00622 
00623   // Reference, Reference
00624   template <typename TLink>
00625   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00626   link_rotate_left(TLink& parent, TLink& leaf)
00627   {
00628      parent.etl_right = leaf.etl_left;
00629 
00630      if (parent.etl_right != std::nullptr)
00631      {
00632        parent.etl_right->etl_parent = &parent;
00633      }
00634 
00635      leaf.etl_parent   = parent.etl_parent;
00636      parent.etl_parent = &leaf;
00637      leaf.etl_left     = &parent;
00638   }
00639 
00640   template <typename TLink>
00641   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00642   link_rotate_right(TLink& parent, TLink& leaf)
00643   {
00644      parent.etl_left = leaf.etl_right;
00645 
00646      if (parent.etl_left != std::nullptr)
00647      {
00648        parent.etl_left->etl_parent = &parent;
00649      }
00650 
00651      leaf.etl_parent   = parent.etl_parent;
00652      parent.etl_parent = &leaf;
00653      leaf.etl_right    = &parent;
00654   }
00655 
00656   // Pointer, Pointer
00657   template <typename TLink>
00658   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00659   link_rotate_left(TLink* parent, TLink* leaf)
00660   {
00661     if ((parent != std::nullptr) && (leaf != std::nullptr))
00662     {
00663       link_rotate_left(*parent, *leaf);
00664     }
00665   }
00666 
00667   template <typename TLink>
00668   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00669   link_rotate_right(TLink* parent, TLink* leaf)
00670   {
00671     if ((parent != std::nullptr) && (leaf != std::nullptr))
00672     {
00673       link_rotate_right(*parent, *leaf);
00674     }
00675   }
00676 
00677   // Reference, Pointer
00678   template <typename TLink>
00679   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00680   link_rotate_left(TLink& parent, TLink* leaf)
00681   {
00682     if (leaf != std::nullptr)
00683     {
00684       link_rotate_left(parent, *leaf);
00685     }
00686   }
00687 
00688   template <typename TLink>
00689   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00690   link_rotate_right(TLink& parent, TLink* leaf)
00691   {
00692     if (leaf != std::nullptr)
00693     {
00694       link_rotate_right(parent, *leaf);
00695     }
00696   }
00697 
00698   // Pointer, Reference
00699   template <typename TLink>
00700   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00701   link_rotate_left(TLink* parent, TLink& leaf)
00702   {
00703     if (parent != std::nullptr)
00704     {
00705       link_rotate_left(*parent, leaf);
00706     }
00707   }
00708 
00709   template <typename TLink>
00710   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00711   link_rotate_right(TLink* parent, TLink& leaf)
00712   {
00713     if (parent != std::nullptr)
00714     {
00715       link_rotate_right(*parent, leaf);
00716     }
00717   }
00718 
00719   // Reference, Reference
00720   /// Automatically detects whether a left or right rotate is expected.
00721   template <typename TLink>
00722   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00723   link_rotate(TLink& parent, TLink& leaf)
00724   {
00725     if (parent.etl_left == &leaf)
00726     {
00727       etl::link_rotate_right(parent, leaf);
00728     }
00729     else
00730     {
00731       etl::link_rotate_left(parent, leaf);
00732     }
00733   }
00734 
00735   // Pointer, Pointer
00736   /// Automatically detects whether a left or right rotate is expected.
00737   template <typename TLink>
00738   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00739   link_rotate(TLink* parent, TLink* leaf)
00740   {
00741     if ((parent != std::nullptr) && (leaf != std::nullptr))
00742     {
00743       if (parent->etl_left == leaf)
00744       {
00745         etl::link_rotate_right(*parent, *leaf);
00746       }
00747       else
00748       {
00749         etl::link_rotate_left(*parent, *leaf);
00750       }
00751     }
00752   }
00753 
00754   // Reference, Pointer
00755   /// Automatically detects whether a left or right rotate is expected.
00756   template <typename TLink>
00757   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00758   link_rotate(TLink& parent, TLink* leaf)
00759   {
00760     if (leaf != std::nullptr)
00761     {
00762       if (parent.etl_left == leaf)
00763       {
00764         etl::link_rotate_right(parent, *leaf);
00765       }
00766       else
00767       {
00768         etl::link_rotate_left(parent, *leaf);
00769       }
00770     }
00771   }
00772 
00773   // Pointer, Reference
00774   /// Automatically detects whether a left or right rotate is expected.
00775   template <typename TLink>
00776   typename etl::enable_if<etl::is_same<TLink, etl::tree_link<TLink::ID> >::value, void>::type
00777   link_rotate(TLink* parent, TLink& leaf)
00778   {
00779     if (parent != std::nullptr)
00780     {
00781       if (parent->etl_left == &leaf)
00782       {
00783         etl::link_rotate_right(*parent, leaf);
00784       }
00785       else
00786       {
00787         etl::link_rotate_left(*parent, leaf);
00788       }
00789     }
00790   }
00791 }
00792 
00793 #undef ETL_FILE
00794 #endif
00795