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_FINDBYLWCHOST(ring, element, lwc_hostname) \ 70 /*LOG("RING_FINDBYHOST(%s, %s)", #ring, hostname);*/ \ 71 if (ring) { \ 72 bool found = false; \ 73 element = ring; \ 74 do { \ 75 if (lwc_string_isequal(element->host, lwc_hostname, \ 76 &found) == lwc_error_ok && \ 77 found == true) { \ 78 break; \ 79 } \ 80 element = element->r_next; \ 81 } while (element != ring); \ 82 if (!found) element = 0; \ 83 } else element = 0 84 85 /** Measure the size of a ring and put it in the supplied variable */ 86 #define RING_GETSIZE(ringtype, ring, sizevar) \ 87 /*LOG("RING_GETSIZE(%s)", #ring);*/ \ 88 if (ring) { \ 89 ringtype *p = ring; \ 90 sizevar = 0; \ 91 do { \ 92 sizevar++; \ 93 p = p->r_next; \ 94 } while (p != ring); \ 95 } else sizevar = 0 96 97 /** Count the number of elements in the ring which match the provided lwc_hostname */ 98 #define RING_COUNTBYLWCHOST(ringtype, ring, sizevar, lwc_hostname) \ 99 /*LOG("RING_COUNTBYHOST(%s, %s)", #ring, hostname);*/ \ 100 if (ring) { \ 101 ringtype *p = ring; \ 102 sizevar = 0; \ 103 do { \ 104 bool matches = false; \ 105 /* nsurl guarantees lowercase host */ \ 106 if (lwc_string_isequal(p->host, lwc_hostname, \ 107 &matches) == lwc_error_ok) \ 108 if (matches) \ 109 sizevar++; \ 110 p = p->r_next; \ 111 } while (p != ring); \ 112 } else sizevar = 0 113 114 /* 115 * Ring iteration works as follows: 116 * 117 * RING_ITERATE_START(ringtype, ring, iteratorptr) { 118 * code_using(iteratorptr); 119 * } RING_ITERATE_END(ring, iteratorptr); 120 * 121 * If you want to stop iterating (e.g. you found your answer) 122 * RING_ITERATE_STOP(ring, iteratorptr); 123 * You *MUST* abort the iteration if you do something to modify 124 * the ring such as deleting or adding an element. 125 */ 126 127 #define RING_ITERATE_START(ringtype, ring, iteratorptr) \ 128 if (ring != NULL) { \ 129 ringtype *iteratorptr = ring; \ 130 do { \ 131 do { \ 132 133 #define RING_ITERATE_STOP(ring, iteratorptr) \ 134 goto iteration_end_ring##_##iteratorptr 135 136 #define RING_ITERATE_END(ring, iteratorptr) \ 137 } while (false); \ 138 iteratorptr = iteratorptr->r_next; \ 139 } while (iteratorptr != ring); \ 140 } \ 141 iteration_end_ring##_##iteratorptr: 142 143 #endif 144