~ubuntu-branches/ubuntu/jaunty/pennmush/jaunty

« back to all changes in this revision

Viewing changes to src/bufferq.c

  • Committer: Bazaar Package Importer
  • Author(s): Ervin Hearn III
  • Date: 2004-12-06 20:05:16 UTC
  • Revision ID: james.westby@ubuntu.com-20041206200516-ggvxci2ktgughxsl
Tags: upstream-1.7.7p40
ImportĀ upstreamĀ versionĀ 1.7.7p40

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * \file bufferq.c
 
3
 *
 
4
 * \brief Code for managing queues of buffers, a handy data structure.
 
5
 *
 
6
 *
 
7
 */
 
8
 
 
9
#include "copyrite.h"
 
10
#include "config.h"
 
11
 
 
12
#include <stdio.h>
 
13
#ifdef I_UNISTD
 
14
#include <unistd.h>
 
15
#endif
 
16
#include <string.h>
 
17
#include <stddef.h>
 
18
#include <stdarg.h>
 
19
#include <stdlib.h>
 
20
#ifdef I_SYS_TIME
 
21
#include <sys/time.h>
 
22
#endif
 
23
#include <time.h>
 
24
#ifdef I_SYS_TYPES
 
25
#include <sys/types.h>
 
26
#endif
 
27
 
 
28
#include "conf.h"
 
29
#include "externs.h"
 
30
#include "flags.h"
 
31
#include "dbdefs.h"
 
32
#include "bufferq.h"
 
33
#include "mymalloc.h"
 
34
#include "log.h"
 
35
#include "confmagic.h"
 
36
 
 
37
#define BUFFERQLINEOVERHEAD     (2*sizeof(int)+sizeof(time_t)+sizeof(dbref))
 
38
 
 
39
static void shift_bufferq(BUFFERQ * bq, int space_needed);
 
40
 
 
41
/** Add data to a buffer queue.
 
42
 * \param bq pointer to buffer queue.
 
43
 * \param type caller-specific integer
 
44
 * \param player caller-specific dbref
 
45
 * \param msg caller-specific string to add.
 
46
 */
 
47
void
 
48
add_to_bufferq(BUFFERQ * bq, int type, dbref player, const char *msg)
 
49
{
 
50
  int len = strlen(msg);
 
51
  int room = len + 1 + BUFFERQLINEOVERHEAD;
 
52
  if (!bq)
 
53
    return;
 
54
  if (room > bq->buffer_size)
 
55
    return;
 
56
  if ((bq->buffer_end > bq->buffer) &&
 
57
      ((bq->buffer_size - (bq->buffer_end - bq->buffer)) < room))
 
58
    shift_bufferq(bq, room);
 
59
  memcpy(bq->buffer_end, &len, sizeof(len));
 
60
  bq->buffer_end += sizeof(len);
 
61
  memcpy(bq->buffer_end, &player, sizeof(player));
 
62
  bq->buffer_end += sizeof(player);
 
63
  memcpy(bq->buffer_end, &type, sizeof(type));
 
64
  bq->buffer_end += sizeof(type);
 
65
  memcpy(bq->buffer_end, &mudtime, sizeof(time_t));
 
66
  bq->buffer_end += sizeof(time_t);
 
67
  memcpy(bq->buffer_end, msg, len + 1);
 
68
  bq->buffer_end += len + 1;
 
69
  strcpy(bq->last_string, msg);
 
70
  bq->last_type = type;
 
71
  bq->num_buffered++;
 
72
}
 
73
 
 
74
 
 
75
static void
 
76
shift_bufferq(BUFFERQ * bq, int space_needed)
 
77
{
 
78
  char *p = bq->buffer;
 
79
  int size, jump;
 
80
  int skipped = 0;
 
81
 
 
82
  while ((space_needed > 0) && (p < bq->buffer_end)) {
 
83
    /* First 4 bytes is the size of the first string, not including \0 */
 
84
    memcpy(&size, p, sizeof(size));
 
85
    /* Jump to the start of the next string */
 
86
    jump = size + BUFFERQLINEOVERHEAD + 1;
 
87
    p += jump;
 
88
    space_needed -= jump;
 
89
    skipped++;
 
90
  }
 
91
 
 
92
  if ((p != bq->buffer_end) && (space_needed > 0)) {
 
93
    /* Not good. We couldn't get the space we needed even after we
 
94
     * emptied the buffer. This should never happen, but if it does,
 
95
     * we'll just log a fault and do nothing.
 
96
     */
 
97
    do_rawlog(LT_ERR, "Unable to get enough buffer queue space");
 
98
    return;
 
99
  }
 
100
 
 
101
  /* Shift everything here and after up to the front
 
102
   * At this point, p may be pointing at the very end of the buffer,
 
103
   * in which case, we just move it to the front with no shifting.
 
104
   */
 
105
  if (p < bq->buffer_end)
 
106
    memmove(bq->buffer, p, bq->buffer_end - p);
 
107
  bq->buffer_end -= (p - bq->buffer);
 
108
  bq->num_buffered -= skipped;
 
109
}
 
110
 
 
111
/** Allocate memory for a buffer queue to hold a given number of lines.
 
112
 * \param bq pointer to buffer queue.
 
113
 * \param lines lines to allocate for buffer queue.
 
114
 * \retval address of allocated buffer queue.
 
115
 */
 
116
BUFFERQ *
 
117
allocate_bufferq(int lines)
 
118
{
 
119
  BUFFERQ *bq;
 
120
  int bytes = lines * (BUFFER_LEN + BUFFERQLINEOVERHEAD);
 
121
  bq = mush_malloc(sizeof(BUFFERQ), "bufferq");
 
122
  bq->buffer = mush_malloc(bytes, "bufferq.buffer");
 
123
  *bq->buffer = '\0';
 
124
  bq->buffer_end = bq->buffer;
 
125
  bq->num_buffered = 0;
 
126
  bq->buffer_size = bytes;
 
127
  strcpy(bq->last_string, "");
 
128
  bq->last_type = 0;
 
129
  return bq;
 
130
}
 
131
 
 
132
/** Free memory of a buffer queue.
 
133
 * \param bq pointer to buffer queue.
 
134
 */
 
135
void
 
136
free_bufferq(BUFFERQ * bq)
 
137
{
 
138
  if (!bq)
 
139
    return;
 
140
  if (bq->buffer)
 
141
    mush_free(bq->buffer, "bufferq.buffer");
 
142
  mush_free(bq, "bufferq");
 
143
}
 
144
 
 
145
/** Reallocate a buffer queue (to change its size)
 
146
 * \param bq pointer to buffer queue.
 
147
 * \param lines new number of lines to store in buffer queue.
 
148
 * \retval address of reallocated buffer queue.
 
149
 */
 
150
BUFFERQ *
 
151
reallocate_bufferq(BUFFERQ * bq, int lines)
 
152
{
 
153
  char *newbuff;
 
154
  ptrdiff_t bufflen;
 
155
  int bytes = lines * (BUFFER_LEN + 2 * BUFFERQLINEOVERHEAD);
 
156
  /* If we were accidentally called without a buffer, deal */
 
157
  if (!bq) {
 
158
    return allocate_bufferq(lines);
 
159
  }
 
160
  /* Are we not changing size? */
 
161
  if (bq->buffer_size == bytes)
 
162
    return bq;
 
163
  if (bq->buffer_size > bytes) {
 
164
    /* Shrinking the buffer */
 
165
    if ((bq->buffer_end - bq->buffer) >= bytes)
 
166
      shift_bufferq(bq, bq->buffer_end - bq->buffer - bytes);
 
167
  }
 
168
  bufflen = bq->buffer_end - bq->buffer;
 
169
  newbuff = realloc(bq->buffer, bytes);
 
170
  if (newbuff) {
 
171
    bq->buffer = newbuff;
 
172
    bq->buffer_end = bq->buffer + bufflen;
 
173
    bq->buffer_size = bytes;
 
174
  }
 
175
  return bq;
 
176
}
 
177
 
 
178
 
 
179
 
 
180
/** Iterate through messages in a bufferq.
 
181
 * This function returns the next message in a bufferq, given
 
182
 * a pointer to the start of entry (which is modified).
 
183
 * It returns NULL when there are no more messages to get.
 
184
 * Call this in a loop to get all messages; do not intersperse
 
185
 * with calls to insert messages!
 
186
 * \param bq pointer to buffer queue structure.
 
187
 * \param p address of pointer to track start of next entry. If that's
 
188
 *   the address of a null pointer, reset to beginning.
 
189
 * \param player address of pointer to return player data in
 
190
 * \param type address of pointer to return type value in.
 
191
 * \param timestamp address of pointer to return timestamp in.
 
192
 * \return next message text or NULL if no more.
 
193
 */
 
194
char *
 
195
iter_bufferq(BUFFERQ * bq, char **p, dbref *player, int *type,
 
196
             time_t * timestamp)
 
197
{
 
198
  static char tbuf1[BUFFER_LEN];
 
199
  int size;
 
200
 
 
201
  if (!p || !bq || !bq->buffer || (bq->buffer == bq->buffer_end))
 
202
    return NULL;
 
203
 
 
204
  if (*p == bq->buffer_end)
 
205
    return NULL;
 
206
 
 
207
  if (!*p)
 
208
    *p = bq->buffer;            /* Reset to beginning */
 
209
 
 
210
  memcpy(&size, *p, sizeof(size));
 
211
  *p += sizeof(size);
 
212
  memcpy(player, *p, sizeof(dbref));
 
213
  *p += sizeof(dbref);
 
214
  memcpy(type, *p, sizeof(int));
 
215
  *p += sizeof(int);
 
216
  memcpy(timestamp, *p, sizeof(time_t));
 
217
  *p += sizeof(time_t);
 
218
  memcpy(tbuf1, *p, size + 1);
 
219
  *p += size + 1;
 
220
  return tbuf1;
 
221
}
 
222
 
 
223
/** Size of bufferq buffer in lines.
 
224
 * \param bq pointer to buffer queue.
 
225
 * \return size of buffer queue in lines
 
226
 */
 
227
int
 
228
bufferq_lines(BUFFERQ * bq)
 
229
{
 
230
  if (bq && bq->buffer)
 
231
    return bq->buffer_size / (BUFFER_LEN + BUFFERQLINEOVERHEAD);
 
232
  else
 
233
    return 0;
 
234
}
 
235
 
 
236
/** Is a buffer queue empty?
 
237
 * \param bq pointer to buffer queue.
 
238
 * \retval 1 the buffer queue is empty (has no messages).
 
239
 * \retval 0 the buffer queue is not empty (has messages).
 
240
 */
 
241
int
 
242
isempty_bufferq(BUFFERQ * bq)
 
243
{
 
244
  if (!bq || !bq->buffer)
 
245
    return 1;
 
246
  if (bq->buffer == bq->buffer_end)
 
247
    return 1;
 
248
  return 0;
 
249
}