The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
listkey.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * listkey.cpp - code for base class 'ListKey'. ListKey is the basis
4  * for all types of keys that have lists of specified
5  * indexes (e.g. a list of verses, place, etc.)
6  *
7  * $Id: listkey.cpp 3808 2020-10-02 13:23:34Z scribe $
8  *
9  * Copyright 1997-2013 CrossWire Bible Society (http://www.crosswire.org)
10  * CrossWire Bible Society
11  * P. O. Box 2528
12  * Tempe, AZ 85280-2528
13  *
14  * This program is free software; you can redistribute it and/or modify it
15  * under the terms of the GNU General Public License as published by the
16  * Free Software Foundation version 2.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * General Public License for more details.
22  *
23  */
24 
25 
26 #include <utilstr.h>
27 #include <stdlib.h>
28 #include <swkey.h>
29 #include <listkey.h>
30 #include <string.h>
31 
33 
34 static const char *classes[] = {"ListKey", "SWKey", "SWObject", 0};
35 static const SWClass classdef(classes);
36 
37 /******************************************************************************
38  * ListKey Constructor - initializes instance of ListKey
39  *
40  * ENT: ikey - text key
41  */
42 
43 ListKey::ListKey(const char *ikey): SWKey(ikey) {
44  arraymax = 0;
45  clear();
46  init();
47 }
48 
49 
50 ListKey::ListKey(ListKey const &k) : SWKey(k.keytext) {
51  arraymax = k.arraymax;
52  arraypos = k.arraypos;
53  arraycnt = k.arraycnt;
54  array = (arraymax)?(SWKey **)malloc(k.arraymax * sizeof(SWKey *)):0;
55  for (int i = 0; i < arraycnt; i++)
56  array[i] = k.array[i]->clone();
57  init();
58 }
59 
60 
61 void ListKey::init() {
62  myClass = &classdef;
63  // this is a listkey, bound is always set
64  boundSet = true;
65 }
66 
67 
69 {
70  return new ListKey(*this);
71 }
72 
73 /******************************************************************************
74  * ListKey Destructor - cleans up instance of ListKey
75  */
76 
78 {
79  clear();
80 }
81 
82 
83 /******************************************************************************
84  * ListKey::clear - Clears out elements of list
85  */
86 
88 {
89  int loop;
90 
91  if (arraymax) {
92  for (loop = 0; loop < arraycnt; loop++)
93  delete array[loop];
94 
95  free(array);
96  arraymax = 0;
97  }
98  arraycnt = 0;
99  arraypos = 0;
100  array = 0;
101 }
102 
103 
104 /******************************************************************************
105  * ListKey::copyFrom Equates this ListKey to another ListKey object
106  *
107  * ENT: ikey - other ListKey object
108  */
109 
110 void ListKey::copyFrom(const ListKey &ikey) {
111  clear();
112 
113  arraymax = ikey.arraymax;
114  arraypos = ikey.arraypos;
115  arraycnt = ikey.arraycnt;
116  array = (arraymax)?(SWKey **)malloc(ikey.arraymax * sizeof(SWKey *)):0;
117  for (int i = 0; i < arraycnt; i++)
118  array[i] = ikey.array[i]->clone();
119 
120  setToElement(0);
121 }
122 
123 
124 /******************************************************************************
125  * ListKey::add - Adds an element to the list
126  */
127 
128 void ListKey::add(const SWKey &ikey) {
129  if (++arraycnt > arraymax) {
130  array = (SWKey **) ((array) ? realloc(array, (arraycnt + 32) * sizeof(SWKey *)) : calloc(arraycnt + 32, sizeof(SWKey *)));
131  arraymax = arraycnt + 32;
132  }
133  array[arraycnt-1] = ikey.clone();
135 }
136 
137 
138 
139 /******************************************************************************
140  * ListKey::setPosition(SW_POSITION) - Positions this key
141  *
142  * ENT: p - position
143  *
144  * RET: *this
145  */
146 
148  switch (p) {
149  case 1: // GCC won't compile P_TOP
150  setToElement(0, p);
151  break;
152  case 2: // GCC won't compile P_BOTTOM
153  setToElement(arraycnt-1, p);
154  break;
155  }
156 }
157 
158 
159 /******************************************************************************
160  * ListKey::increment - Increments a number of elements
161  */
162 
163 void ListKey::increment(int step) {
164  if (step < 0) {
165  decrement(step*-1);
166  return;
167  }
168  popError(); // clear error
169  for(; step && !popError(); step--) {
170  if (arraypos < arraycnt && arraycnt) {
171  if (array[arraypos]->isBoundSet())
172  (*(array[arraypos]))++;
173  if ((array[arraypos]->popError()) || (!array[arraypos]->isBoundSet())) {
174  setToElement(arraypos+1);
175  }
176  else SWKey::setText((const char *)(*array[arraypos]));
177  }
178  else error = KEYERR_OUTOFBOUNDS;
179  }
180 }
181 
182 
183 /******************************************************************************
184  * ListKey::decrement - Decrements a number of elements
185  */
186 
187 void ListKey::decrement(int step) {
188  if (step < 0) {
189  increment(step*-1);
190  return;
191  }
192  popError(); // clear error
193  for(; step && !popError(); step--) {
194  if (arraypos > -1 && arraycnt) {
195  if (array[arraypos]->isBoundSet())
196  (*(array[arraypos]))--;
197  if ((array[arraypos]->popError()) || (!array[arraypos]->isBoundSet())) {
198  setToElement(arraypos-1, BOTTOM);
199  }
200  else SWKey::setText((const char *)(*array[arraypos]));
201  }
202  else error = KEYERR_OUTOFBOUNDS;
203  }
204 }
205 
206 
207 /******************************************************************************
208  * ListKey::getCount - Returns number of elements in list
209  */
210 
211 int ListKey::getCount() const {
212  return arraycnt;
213 }
214 
215 
216 /******************************************************************************
217  * ListKey::setToElement - Sets key to element number
218  *
219  * ENT: ielement - element number to set to
220  * pos - set the subkey element to position (TOP) or BOTTOM
221  *
222  * RET: error status
223  */
224 
225 char ListKey::setToElement(int ielement, SW_POSITION pos) {
226  arraypos = ielement;
227  if (arraypos >= arraycnt) {
228  arraypos = (arraycnt>0)?arraycnt - 1:0;
230  }
231  else {
232  if (arraypos < 0) {
233  arraypos = 0;
235  }
236  else {
237  error = 0;
238  }
239  }
240 
241  if (arraycnt) {
242  if (array[arraypos]->isBoundSet())
243  (*array[arraypos]) = pos;
244  SWKey::setText((const char *)(*array[arraypos]));
245  }
246  else SWKey::setText("");
247 
248  return error;
249 }
250 
251 
252 /******************************************************************************
253  * ListKey::getElement - Gets a key element number
254  *
255  * ENT: pos - element number to get (or default current)
256  *
257  * RET: Key or null on error
258  */
259 
260 const SWKey *ListKey::getElement(int pos) const {
261  if (pos < 0)
262  pos = arraypos;
263 
264  if (pos >=arraycnt)
266 
267  return (error) ? 0:array[pos];
268 }
269 
271  const ListKey &self = *this;
272  return const_cast<SWKey *>(self.getElement(pos));
273 }
274 
275 
276 
277 /******************************************************************************
278  * ListKey::remove - Removes current element from list
279  */
280 
282  if ((arraypos > -1) && (arraypos < arraycnt)) {
283  delete array[arraypos];
284  if (arraypos < arraycnt - 1)
285  memmove(&array[arraypos], &array[arraypos+1], (arraycnt - arraypos - 1) * sizeof(SWKey *));
286  arraycnt--;
287 
288  setToElement((arraypos)?arraypos-1:0);
289  }
290 }
291 
292 
293 /******************************************************************************
294  * ListKey::getRangeText - returns parsable range text for this key
295  */
296 
297 const char *ListKey::getRangeText() const {
298  char *buf = new char[(arraycnt + 1) * 255];
299  buf[0] = 0;
300  for (int i = 0; i < arraycnt; i++) {
301  strcat(buf, array[i]->getRangeText());
302  if (i < arraycnt-1)
303  strcat(buf, "; ");
304  }
305  stdstr(&rangeText, buf);
306  delete [] buf;
307  return rangeText;
308 }
309 
310 
311 /******************************************************************************
312  * ListKey::getOSISRefRangeText - returns parsable range text for this key
313  */
314 
315 const char *ListKey::getOSISRefRangeText() const {
316  char *buf = new char[(arraycnt + 1) * 255];
317  buf[0] = 0;
318  for (int i = 0; i < arraycnt; i++) {
319  strcat(buf, array[i]->getOSISRefRangeText());
320  if (i < arraycnt-1)
321  strcat(buf, ";");
322  }
323  stdstr(&rangeText, buf);
324  delete [] buf;
325  return rangeText;
326 }
327 
328 
329 /******************************************************************************
330  * ListKey::getShortRangeText - returns short parsable range text for this key
331  */
332 
333 const char *ListKey::getShortRangeText() const {
334  SWBuf buf;
335  for (int i = 0; i < arraycnt; i++) {
336  buf += array[i]->getShortRangeText();
337  if (i < arraycnt-1)
338  buf += "; ";
339  }
340  stdstr(&rangeText, buf.c_str());
341  return rangeText;
342 }
343 
344 
345 /******************************************************************************
346  * ListKey::getText - returns text key if (const char *) cast is requested
347  */
348 
349 const char *ListKey::getText() const {
350  int pos = arraypos;
351  SWKey *key = (pos >= arraycnt || !arraycnt) ? 0:array[pos];
352  return (key) ? key->getText() : keytext;
353 }
354 
355 const char *ListKey::getShortText() const {
356  int pos = arraypos;
357  SWKey *key = (pos >= arraycnt || !arraycnt) ? 0:array[pos];
358  return (key) ? key->getShortText() : keytext;
359 }
360 
361 
362 void ListKey::setText(const char *ikey) {
363  // at least try to set the current element to this text
364  for (arraypos = 0; arraypos < arraycnt; arraypos++) {
365  SWKey *key = array[arraypos];
366  if (key) {
367  if (key->isTraversable() && key->isBoundSet()) {
368  key->setText(ikey);
369  if (!key->popError())
370  break;
371  }
372  else {
373  if (!strcmp(key->getText(), ikey))
374  break;
375  }
376  }
377  }
378  if (arraypos >= arraycnt) {
379  error = 1;
380  arraypos = arraycnt-1;
381  }
382 
383  SWKey::setText(ikey);
384 }
385 
386 // This sort impl sucks. Let's change it to a quicksort or some other efficient algol
388  for (int i = 0; i < arraycnt; i++) {
389  for (int j = i; j < arraycnt; j++) {
390  if (*array[j] < *array[i]) {
391  SWKey *tmp = array[i];
392  array[i] = array[j];
393  array[j] = tmp;
394  }
395  }
396  }
397 }
398 
400 
virtual void setText(const char *ikey)
Definition: swkey.cpp:162
virtual bool isBoundSet() const
Definition: swkey.h:189
virtual void decrement(int step=1)
Definition: listkey.cpp:187
#define SWORD_NAMESPACE_START
Definition: defs.h:39
virtual const char * getShortRangeText() const
Definition: swkey.h:187
virtual int getCount() const
Definition: listkey.cpp:211
virtual const char * getShortText() const
Definition: swkey.h:185
Definition: swbuf.h:47
int arraycnt
Definition: listkey.h:45
ListKey(const char *ikey=0)
Definition: listkey.cpp:43
int pos
Definition: regex.c:5534
virtual const char * getShortText() const
Definition: listkey.cpp:355
virtual void copyFrom(const ListKey &ikey)
Definition: listkey.cpp:110
const SWClass * myClass
Definition: swobject.h:55
virtual void remove()
Definition: listkey.cpp:281
#define BOTTOM
Definition: swkey.h:69
char * keytext
Definition: swkey.h:102
virtual void clear()
Definition: listkey.cpp:87
static const SWClass classdef(classes)
virtual SWKey * clone() const
Definition: listkey.cpp:68
virtual SWKey * getElement(int pos=-1)
Definition: listkey.cpp:270
virtual SWKey * clone() const
Definition: swkey.cpp:75
bool boundSet
Definition: swkey.h:104
static SWORD_NAMESPACE_START const char * classes[]
Definition: listkey.cpp:34
virtual const char * getText() const
Definition: swkey.cpp:184
virtual char setToElement(int ielement, SW_POSITION pos=TOP)
Definition: listkey.cpp:225
SWORD_NAMESPACE_START char * stdstr(char **ipstr, const char *istr, unsigned int memPadFactor=1)
Definition: utilstr.h:44
int arraymax
Definition: listkey.h:44
char * malloc()
free(preg->fastmap)
const char * c_str() const
Definition: swbuf.h:158
int arraypos
Definition: listkey.h:43
char * realloc()
virtual const char * getShortRangeText() const
Definition: listkey.cpp:333
virtual void sort()
Definition: listkey.cpp:387
virtual void increment(int step=1)
Definition: listkey.cpp:163
#define KEYERR_OUTOFBOUNDS
Definition: swkey.h:35
virtual char popError()
Definition: swkey.cpp:147
SWKey ** array
Definition: listkey.h:46
virtual void setText(const char *ikey)
Definition: listkey.cpp:362
char * rangeText
Definition: swkey.h:103
void init()
Definition: listkey.cpp:61
virtual const char * getRangeText() const
Definition: listkey.cpp:297
virtual void add(const SWKey &ikey)
Definition: listkey.cpp:128
char error
Definition: swkey.h:106
virtual void setPosition(SW_POSITION pos)
Definition: listkey.cpp:147
virtual const char * getText() const
Definition: listkey.cpp:349
virtual bool isTraversable() const
Definition: swkey.h:222
#define SWORD_NAMESPACE_END
Definition: defs.h:40
Definition: swkey.h:77
virtual const char * getOSISRefRangeText() const
Definition: listkey.cpp:315
virtual ~ListKey()
Definition: listkey.cpp:77