1 /* $OpenBSD: paste.c,v 1.8 2009/12/03 22:50:10 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/time.h> 21 22 #include <string.h> 23 24 #include "tmux.h" 25 26 /* 27 * Stack of paste buffers. Note that paste buffer data is not necessarily a C 28 * string! 29 */ 30 31 void 32 paste_init_stack(struct paste_stack *ps) 33 { 34 ARRAY_INIT(ps); 35 } 36 37 void 38 paste_free_stack(struct paste_stack *ps) 39 { 40 while (paste_free_top(ps) == 0) 41 ; 42 } 43 44 /* Return each item of the stack in turn. */ 45 struct paste_buffer * 46 paste_walk_stack(struct paste_stack *ps, uint *idx) 47 { 48 struct paste_buffer *pb; 49 50 pb = paste_get_index(ps, *idx); 51 (*idx)++; 52 return (pb); 53 } 54 55 /* Get the top item on the stack. */ 56 struct paste_buffer * 57 paste_get_top(struct paste_stack *ps) 58 { 59 if (ARRAY_LENGTH(ps) == 0) 60 return (NULL); 61 return (ARRAY_FIRST(ps)); 62 } 63 64 /* Get an item by its index. */ 65 struct paste_buffer * 66 paste_get_index(struct paste_stack *ps, u_int idx) 67 { 68 if (idx >= ARRAY_LENGTH(ps)) 69 return (NULL); 70 return (ARRAY_ITEM(ps, idx)); 71 } 72 73 /* Free the top item on the stack. */ 74 int 75 paste_free_top(struct paste_stack *ps) 76 { 77 struct paste_buffer *pb; 78 79 if (ARRAY_LENGTH(ps) == 0) 80 return (-1); 81 82 pb = ARRAY_FIRST(ps); 83 ARRAY_REMOVE(ps, 0); 84 85 xfree(pb->data); 86 xfree(pb); 87 88 return (0); 89 } 90 91 /* Free an item by index. */ 92 int 93 paste_free_index(struct paste_stack *ps, u_int idx) 94 { 95 struct paste_buffer *pb; 96 97 if (idx >= ARRAY_LENGTH(ps)) 98 return (-1); 99 100 pb = ARRAY_ITEM(ps, idx); 101 ARRAY_REMOVE(ps, idx); 102 103 xfree(pb->data); 104 xfree(pb); 105 106 return (0); 107 } 108 109 /* 110 * Add an item onto the top of the stack, freeing the bottom if at limit. Note 111 * that the caller is responsible for allocating data. 112 */ 113 void 114 paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit) 115 { 116 struct paste_buffer *pb; 117 118 if (size == 0) 119 return; 120 121 while (ARRAY_LENGTH(ps) >= limit) { 122 pb = ARRAY_LAST(ps); 123 xfree(pb->data); 124 xfree(pb); 125 ARRAY_TRUNC(ps, 1); 126 } 127 128 pb = xmalloc(sizeof *pb); 129 ARRAY_INSERT(ps, 0, pb); 130 131 pb->data = data; 132 pb->size = size; 133 } 134 135 136 /* 137 * Replace an item on the stack. Note that the caller is responsible for 138 * allocating data. 139 */ 140 int 141 paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size) 142 { 143 struct paste_buffer *pb; 144 145 if (size == 0) 146 return (0); 147 148 if (idx >= ARRAY_LENGTH(ps)) 149 return (-1); 150 151 pb = ARRAY_ITEM(ps, idx); 152 xfree(pb->data); 153 154 pb->data = data; 155 pb->size = size; 156 157 return (0); 158 } 159