Subversion Repositories Kolibri OS

Rev

Rev 3584 | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2006, 2007 Daniel Silverstone <dsilvers@digital-scurf.org>
  3.  *
  4.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  5.  *
  6.  * NetSurf is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; version 2 of the License.
  9.  *
  10.  * NetSurf is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. /** \file
  20.  * Ring list structure.
  21.  *
  22.  * Rings are structures which have an r_next pointer and an r_prev
  23.  * pointer which are always initialised and always point at the next
  24.  * or previous element respectively.
  25.  *
  26.  * The degenerate case of a single element in the ring simply points
  27.  * at itself in both directions. A zero element ring is NULL.
  28.  *
  29.  * Some of the ring functions are specific to the fetcher but may be
  30.  * of use to others and are thus included here.
  31.  */
  32.  
  33. #ifndef _NETSURF_UTILS_RING_H_
  34. #define _NETSURF_UTILS_RING_H_
  35.  
  36.  
  37. /** Insert the given item into the specified ring.
  38.  * Assumes that the element is zeroed as appropriate.
  39.  */
  40. #define RING_INSERT(ring,element) \
  41.         /*LOG(("RING_INSERT(%s, %p(%s))", #ring, element, element->host));*/ \
  42.         if (ring) { \
  43.                 element->r_next = ring; \
  44.                 element->r_prev = ring->r_prev; \
  45.                 ring->r_prev = element; \
  46.                 element->r_prev->r_next = element; \
  47.         } else \
  48.                 ring = element->r_prev = element->r_next = element
  49.  
  50. /** Remove the given element from the specified ring.
  51.  * Will zero the element as needed
  52.  */
  53. #define RING_REMOVE(ring, element) \
  54.         /*LOG(("RING_REMOVE(%s, %p(%s)", #ring, element, element->host));*/ \
  55.         if (element->r_next != element ) { \
  56.                 /* Not the only thing in the ring */ \
  57.                 element->r_next->r_prev = element->r_prev; \
  58.                 element->r_prev->r_next = element->r_next; \
  59.                 if (ring == element) ring = element->r_next; \
  60.         } else { \
  61.                 /* Only thing in the ring */ \
  62.                 ring = 0; \
  63.         } \
  64.         element->r_next = element->r_prev = 0
  65.  
  66. /** Find the element (by hostname) in the given ring, leave it in the
  67.  * provided element variable
  68.  */
  69. #define RING_FINDBYHOST(ring, element, hostname) \
  70.         /*LOG(("RING_FINDBYHOST(%s, %s)", #ring, hostname));*/ \
  71.         if (ring) { \
  72.                 bool found = false; \
  73.                 element = ring; \
  74.                 do { \
  75.                         if (strcasecmp(element->host, hostname) == 0) { \
  76.                                 found = true; \
  77.                                 break; \
  78.                         } \
  79.                         element = element->r_next; \
  80.                 } while (element != ring); \
  81.                 if (!found) element = 0; \
  82.         } else element = 0
  83.  
  84. /** Find the element (by hostname) in the given ring, leave it in the
  85.  * provided element variable
  86.  */
  87. #define RING_FINDBYLWCHOST(ring, element, lwc_hostname) \
  88.         /*LOG(("RING_FINDBYHOST(%s, %s)", #ring, hostname));*/ \
  89.         if (ring) { \
  90.                 bool found = false; \
  91.                 element = ring; \
  92.                 do { \
  93.                         if (lwc_string_isequal(element->host, lwc_hostname, \
  94.                                         &found) == lwc_error_ok && \
  95.                                         found == true) { \
  96.                                 break; \
  97.                         } \
  98.                         element = element->r_next; \
  99.                 } while (element != ring); \
  100.                 if (!found) element = 0; \
  101.         } else element = 0
  102.  
  103. /** Measure the size of a ring and put it in the supplied variable */
  104. #define RING_GETSIZE(ringtype, ring, sizevar) \
  105.         /*LOG(("RING_GETSIZE(%s)", #ring));*/ \
  106.         if (ring) { \
  107.                 ringtype *p = ring; \
  108.                 sizevar = 0; \
  109.                 do { \
  110.                         sizevar++; \
  111.                         p = p->r_next; \
  112.                 } while (p != ring); \
  113.         } else sizevar = 0
  114.  
  115. /** Count the number of elements in the ring which match the provided hostname */
  116. #define RING_COUNTBYHOST(ringtype, ring, sizevar, hostname) \
  117.         /*LOG(("RING_COUNTBYHOST(%s, %s)", #ring, hostname));*/ \
  118.         if (ring) { \
  119.                 ringtype *p = ring; \
  120.                 sizevar = 0; \
  121.                 do { \
  122.                         if (strcasecmp(p->host, hostname) == 0) \
  123.                                 sizevar++; \
  124.                         p = p->r_next; \
  125.                 } while (p != ring); \
  126.         } else sizevar = 0
  127.  
  128. /** Count the number of elements in the ring which match the provided lwc_hostname */
  129. #define RING_COUNTBYLWCHOST(ringtype, ring, sizevar, lwc_hostname) \
  130.         /*LOG(("RING_COUNTBYHOST(%s, %s)", #ring, hostname));*/ \
  131.         if (ring) { \
  132.                 ringtype *p = ring; \
  133.                 sizevar = 0; \
  134.                 do { \
  135.                         bool matches = false; \
  136.                         /* nsurl guarantees lowercase host */ \
  137.                         if (lwc_string_isequal(p->host, lwc_hostname, \
  138.                                         &matches) == lwc_error_ok) \
  139.                                 if (matches) \
  140.                                         sizevar++; \
  141.                         p = p->r_next; \
  142.                 } while (p != ring); \
  143.         } else sizevar = 0
  144.  
  145. /*
  146.  * Ring iteration works as follows:
  147.  *
  148.  * RING_ITERATE_START(ringtype, ring, iteratorptr) {
  149.  *    code_using(iteratorptr);
  150.  * } RING_ITERATE_END(ring, iteratorptr);
  151.  *
  152.  * If you want to stop iterating (e.g. you found your answer)
  153.  * RING_ITERATE_STOP(ring, iteratorptr);
  154.  * You *MUST* abort the iteration if you do something to modify
  155.  * the ring such as deleting or adding an element.
  156.  */
  157.  
  158. #define RING_ITERATE_START(ringtype, ring, iteratorptr) \
  159.         if (ring != NULL) {                             \
  160.                 ringtype *iteratorptr = ring;           \
  161.                 do {                                    \
  162.                         do {                            \
  163.                        
  164. #define RING_ITERATE_STOP(ring, iteratorptr)    \
  165.         goto iteration_end_ring##_##iteratorptr
  166.  
  167. #define RING_ITERATE_END(ring, iteratorptr)             \
  168.                         } while (false);                \
  169.                         iteratorptr = iteratorptr->r_next;      \
  170.                 } while (iteratorptr != ring);          \
  171.         }                                               \
  172.         iteration_end_ring##_##iteratorptr:
  173.  
  174. #endif
  175.