GnuCOBOL  2.0
A free COBOL compiler
vbkeysio.c File Reference
#include "isinternal.h"
Include dependency graph for vbkeysio.c:

Go to the source code of this file.

Macros

#define VB_MAX_OFF_T   (off_t)9223372036854775807LL
 

Functions

static int itreeload (const int ihandle, const int ikeynumber, const int ilength, unsigned char *pckeyvalue, off_t tdupnumber)
 
void vvbmakekey (const struct keydesc *pskeydesc, char *pcrow_buffer, unsigned char *pckeyvalue)
 
int ivbkeycompare (const int ihandle, const int ikeynumber, int ilength, unsigned char *pckey1, unsigned char *pckey2)
 
int ivbkeysearch (const int ihandle, const int imode, const int ikeynumber, int ilength, unsigned char *pckeyvalue, off_t tdupnumber)
 
int ivbkeylocaterow (const int ihandle, const int ikeynumber, off_t trownumber)
 
int ivbkeyload (const int ihandle, const int ikeynumber, const int imode, const int isetcurr, struct VBKEY **ppskey)
 
void vvbkeyvalueset (const int ihigh, struct keydesc *pskeydesc, unsigned char *pckeyvalue)
 
int ivbkeyinsert (const int ihandle, struct VBTREE *pstree, const int ikeynumber, unsigned char *pckeyvalue, off_t trownode, off_t tdupnumber, struct VBTREE *pschild)
 
int ivbkeydelete (const int ihandle, const int ikeynumber)
 

Macro Definition Documentation

#define VB_MAX_OFF_T   (off_t)9223372036854775807LL

Definition at line 23 of file vbkeysio.c.

Referenced by ivbkeysearch().

Function Documentation

static int itreeload ( const int  ihandle,
const int  ikeynumber,
const int  ilength,
unsigned char *  pckeyvalue,
off_t  tdupnumber 
)
static

Definition at line 31 of file vbkeysio.c.

References VBKEY::ckey, DICTINFO::iindexchanged, VBKEY::iisdummy, VBTREE::iiseof, VBKEY::iishigh, VBTREE::iisroot, VBTREE::iistof, VBTREE::ikeysinnode, VBTREE::ilevel, iserrno, ivbkeycompare(), ivbnodeload(), NULL, VBKEY::pschild, VBTREE::pskeycurr, DICTINFO::pskeycurr, DICTINFO::pskeydesc, VBTREE::pskeyfirst, VBTREE::pskeylast, VBTREE::pskeylist, VBKEY::psnext, VBKEY::psparent, VBTREE::psparent, VBKEY::psprev, DICTINFO::pstree, psvbfile, psvbtreeallocate(), VBKEY::tdupnumber, VBTREE::tnodenumber, VBKEY::trownode, and vvbtreeallfree().

Referenced by ivbkeysearch().

33 {
34  struct VBKEY *pskey;
35  struct VBTREE *pstree;
36  struct DICTINFO *psvbptr;
37  struct keydesc *pskptr;
38  unsigned int idelta, iindex;
39  int iresult = 0;
40 
41  psvbptr = psvbfile[ihandle];
42  pstree = psvbptr->pstree[ikeynumber];
43  pskptr = psvbptr->pskeydesc[ikeynumber];
44  if (!pstree) {
45  pstree = psvbtreeallocate (ihandle);
46  psvbptr->pstree[ikeynumber] = pstree;
47  iserrno = errno;
48  if (!pstree) {
49  goto treeload_exit;
50  }
51  pstree->iisroot = 1;
52  pstree->iistof = 1;
53  pstree->iiseof = 1;
54  iserrno = ivbnodeload (ihandle, ikeynumber, pstree,
55  pskptr->k_rootnode, -1);
56  if (iserrno) {
57  vvbtreeallfree (ihandle, ikeynumber, pstree);
58  psvbptr->pstree[ikeynumber] = NULL;
59  psvbptr->pskeycurr[ikeynumber] = NULL;
60  goto treeload_exit;
61  }
62  } else if (psvbptr->iindexchanged) {
63  iserrno = ivbnodeload (ihandle, ikeynumber, pstree,
64  pskptr->k_rootnode, -1);
65  if (iserrno) {
66  vvbtreeallfree (ihandle, ikeynumber, pstree);
67  psvbptr->pstree[ikeynumber] = NULL;
68  psvbptr->pskeycurr[ikeynumber] = NULL;
69  goto treeload_exit;
70  }
71  }
72  iserrno = EBADFILE;
73  if (pstree->tnodenumber != pskptr->k_rootnode) {
74  goto treeload_exit;
75  }
76  pstree->iisroot = 1;
77  pstree->iistof = 1;
78  pstree->iiseof = 1;
79  while (1) {
80 /* The following code takes a 'bisection' type approach for location of the */
81 /* key entry. It FAR outperforms the original sequential search code. */
82  idelta = 1;
83  iindex = pstree->ikeysinnode;
84  while (iindex) {
85  idelta = idelta << 1;
86  iindex = iindex >> 1;
87  }
88  iindex = idelta;
89  while (idelta) {
90  idelta = idelta >> 1;
91  if (iindex > pstree->ikeysinnode) {
92  iindex -= idelta;
93  continue;
94  }
95  pstree->pskeycurr = pstree->pskeylist[iindex - 1];
96  if (pstree->pskeycurr->iisdummy) {
97  iresult = -1;
98  } else {
99  iresult = ivbkeycompare (ihandle, ikeynumber, ilength,
100  pckeyvalue, pstree->pskeycurr->ckey);
101  }
102  if (iresult == 0) {
103  if (tdupnumber > pstree->pskeycurr->tdupnumber) {
104  iresult = 1;
105  iindex += idelta;
106  continue;
107  }
108  if (tdupnumber < pstree->pskeycurr->tdupnumber) {
109  iresult = -1;
110  iindex -= idelta;
111  continue;
112  }
113  if (tdupnumber == pstree->pskeycurr->tdupnumber) {
114  break;
115  }
116  }
117  if (iresult < 0) {
118  iindex -= idelta;
119  continue;
120  }
121  if (iresult > 0) {
122  iindex += idelta;
123  continue;
124  }
125  }
126  if (iresult > 0 && pstree->pskeycurr->psnext) {
127  pstree->pskeycurr = pstree->pskeylist[iindex];
128  }
129  if (pstree->pskeycurr->iisdummy && pstree->pskeycurr->psprev
130  && pstree->pskeycurr->psprev->iishigh) {
131  pstree->pskeycurr = pstree->pskeycurr->psprev;
132  }
133  iresult = ivbkeycompare (ihandle, ikeynumber, ilength, pckeyvalue,
134  pstree->pskeycurr->ckey);
135  if (iresult == 0 && tdupnumber < pstree->pskeycurr->tdupnumber) {
136  iresult = -1;
137  }
138  if (!pstree->ilevel) {
139  break; /* Exit the while loop */
140  }
141  if (!pstree->pskeycurr) {
142  goto treeload_exit;
143  }
144  if (!pstree->pskeycurr->pschild || psvbptr->iindexchanged) {
145  pskey = pstree->pskeycurr;
146  if (!pstree->pskeycurr->pschild) {
147  pskey->pschild = psvbtreeallocate (ihandle);
148  iserrno = errno;
149  if (!pskey->pschild) {
150  goto treeload_exit;
151  }
152  pskey->pschild->psparent = pskey->psparent;
153  if (pskey->psparent->iistof
154  && pskey == pskey->psparent->pskeyfirst) {
155  pskey->pschild->iistof = 1;
156  }
157  if (pskey->psparent->iiseof
158  && pskey == pskey->psparent->pskeylast->psprev) {
159  pskey->pschild->iiseof = 1;
160  }
161  }
162  iserrno = ivbnodeload (ihandle, ikeynumber, pstree->pskeycurr->pschild,
163  pstree->pskeycurr->trownode, (int)pstree->ilevel);
164  if (iserrno) {
165  vvbtreeallfree (ihandle, ikeynumber, pskey->pschild);
166  pskey->pschild = NULL;
167  goto treeload_exit;
168  }
169  pstree->pskeycurr->psparent = pstree;
170  pstree->pskeycurr->pschild->psparent = pstree;
171  if (pstree->iistof && pstree->pskeycurr == pstree->pskeyfirst) {
172  pstree->pskeycurr->pschild->iistof = 1;
173  }
174  if (pstree->iiseof && pstree->pskeycurr == pstree->pskeylast) {
175  pstree->pskeycurr->pschild->iiseof = 1;
176  }
177  }
178  pstree = pstree->pskeycurr->pschild;
179  }
180  /*
181  * When we get here, iresult is set depending upon whether the located
182  * key was:
183  * -1 LESS than the desired value
184  * 0 EQUAL to the desired value (including a tdupnumber match!)
185  * 1 GREATER than the desired value
186  * By simply adding one to the value, we're cool for a NON-STANDARD
187  * comparison return value.
188  */
189  psvbptr->pskeycurr[ikeynumber] = pstree->pskeycurr;
190  if (!pstree->pskeycurr) {
191  iserrno = EBADFILE;
192  return -1;
193  }
194  iserrno = 0;
195  if (pstree->pskeycurr->iisdummy) {
196  iserrno = EENDFILE;
197  if (pstree->pskeycurr->psprev) {
198  return 0; /* EOF */
199  } else {
200  return 2; /* Empty file! */
201  }
202  }
203  return (iresult + 1);
204 
205 treeload_exit:
206  return -1;
207 }
unsigned char iishigh
Definition: isinternal.h:331
int ivbkeycompare(const int ihandle, const int ikeynumber, int ilength, unsigned char *pckey1, unsigned char *pckey2)
Definition: vbkeysio.c:230
struct VBTREE * psvbtreeallocate(const int ihandle)
Definition: vbmemio.c:88
unsigned char iindexchanged
Definition: isinternal.h:434
struct VBTREE * pschild
Definition: isinternal.h:327
struct VBKEY * pskeylast
Definition: isinternal.h:341
unsigned char ckey[1]
Definition: isinternal.h:334
unsigned char iisroot
Definition: isinternal.h:347
unsigned char iisdummy
Definition: isinternal.h:332
int ivbnodeload(const int ihandle, const int ikeynumber, struct VBTREE *pstree, const off_t tnodenumber, const int iprevlvl)
Definition: vbnodememio.c:285
struct VBTREE * psparent
Definition: isinternal.h:326
struct VBKEY * pskeycurr
Definition: isinternal.h:342
EC ARGUMENT EC EC BOUND EC BOUND EC BOUND EC BOUND TABLE EC DATA EC DATA EC DATA PTR NULL
Definition: exception.def:95
off_t tnodenumber
Definition: isinternal.h:343
struct VBKEY * pskeycurr[32]
Definition: isinternal.h:448
off_t trownode
Definition: isinternal.h:328
unsigned char iiseof
Definition: isinternal.h:349
unsigned int ikeysinnode
Definition: isinternal.h:346
struct VBKEY * psprev
Definition: isinternal.h:325
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
off_t tdupnumber
Definition: isinternal.h:329
void vvbtreeallfree(const int ihandle, const int ikeynumber, struct VBTREE *pstree)
Definition: vbmemio.c:105
struct VBKEY * pskeylist[512]
Definition: isinternal.h:352
unsigned int ilevel
Definition: isinternal.h:345
struct VBTREE * pstree[32]
Definition: isinternal.h:446
struct VBKEY * pskeyfirst
Definition: isinternal.h:340
struct VBTREE * psparent
Definition: isinternal.h:339
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
unsigned char iistof
Definition: isinternal.h:348
struct VBKEY * psnext
Definition: isinternal.h:324
int iserrno
Definition: vbmemio.c:27

Here is the call graph for this function:

Here is the caller graph for this function:

int ivbkeycompare ( const int  ihandle,
const int  ikeynumber,
int  ilength,
unsigned char *  pckey1,
unsigned char *  pckey2 
)

Definition at line 230 of file vbkeysio.c.

References inl_ldint(), inl_ldlong(), inl_ldquad(), lddbl(), ldfloat(), DICTINFO::pskeydesc, psvbfile, and QUADSIZE.

Referenced by ichecktree(), itreeload(), and ivbkeylocaterow().

232 {
233  struct keydesc *pskeydesc;
234  struct keypart *pskptr;
235  off_t tvalue1, tvalue2;
236  int idescbias, ipart, ilengthtocompare;
237  int ivalue1, ivalue2;
238  int n;
239  int lvalue1, lvalue2;
240  float fvalue1, fvalue2;
241  double dvalue1, dvalue2;
242 
243  pskeydesc = psvbfile[ihandle]->pskeydesc[ikeynumber];
244  if (ilength == 0) {
245  ilength = pskeydesc->k_len;
246  }
247  for (ipart = 0; ilength > 0 && ipart < pskeydesc->k_nparts; ipart++) {
248  pskptr = &pskeydesc->k_part[ipart];
249  if (ilength >= pskptr->kp_leng) {
250  ilengthtocompare = pskptr->kp_leng;
251  } else {
252  ilengthtocompare = ilength;
253  }
254  ilength -= ilengthtocompare;
255  if (pskptr->kp_type & ISDESC) {
256  idescbias = -1;
257  } else {
258  idescbias = 1;
259  }
260  switch (pskptr->kp_type & ~ISDESC) {
261  case CHARTYPE:
262 
263  n = memcmp (pckey1, pckey2, (size_t)ilengthtocompare);
264  if (n < 0) {
265  return -idescbias;
266  }
267  if (n > 0) {
268  return idescbias;
269  }
270  pckey1 += ilengthtocompare;
271  pckey2 += ilengthtocompare;
272 /*
273  while (ilengthtocompare--) {
274  if (*pckey1 < *pckey2) {
275  return -idescbias;
276  }
277  if (*pckey1++ > *pckey2++) {
278  return idescbias;
279  }
280  }
281 */
282  break;
283 
284  case INTTYPE:
285  while (ilengthtocompare >= INTSIZE) {
286  ivalue1 = inl_ldint (pckey1);
287  ivalue2 = inl_ldint (pckey2);
288  if (ivalue1 < ivalue2) {
289  return -idescbias;
290  }
291  if (ivalue1 > ivalue2) {
292  return idescbias;
293  }
294  pckey1 += INTSIZE;
295  pckey2 += INTSIZE;
296  ilengthtocompare -= INTSIZE;
297  }
298  break;
299 
300  case LONGTYPE:
301  while (ilengthtocompare >= LONGSIZE) {
302  lvalue1 = inl_ldlong (pckey1);
303  lvalue2 = inl_ldlong (pckey2);
304  if (lvalue1 < lvalue2) {
305  return -idescbias;
306  }
307  if (lvalue1 > lvalue2) {
308  return idescbias;
309  }
310  pckey1 += LONGSIZE;
311  pckey2 += LONGSIZE;
312  ilengthtocompare -= LONGSIZE;
313  }
314  break;
315 
316  case QUADTYPE:
317  while (ilengthtocompare >= QUADSIZE) {
318  tvalue1 = inl_ldquad (pckey1);
319  tvalue2 = inl_ldquad (pckey2);
320  if (tvalue1 < tvalue2) {
321  return -idescbias;
322  }
323  if (tvalue1 > tvalue2) {
324  return idescbias;
325  }
326  pckey1 += QUADSIZE;
327  pckey2 += QUADSIZE;
328  ilengthtocompare -= QUADSIZE;
329  }
330  break;
331 
332  case FLOATTYPE:
333  while (ilengthtocompare >= FLOATSIZE) {
334  fvalue1 = ldfloat (pckey1);
335  fvalue2 = ldfloat (pckey2);
336  if (fvalue1 < fvalue2) {
337  return -idescbias;
338  }
339  if (fvalue1 > fvalue2) {
340  return idescbias;
341  }
342  pckey1 += FLOATSIZE;
343  pckey2 += FLOATSIZE;
344  ilengthtocompare -= FLOATSIZE;
345  }
346  break;
347 
348  case DOUBLETYPE:
349  while (ilengthtocompare >= DOUBLESIZE) {
350  dvalue1 = lddbl (pckey1);
351  dvalue2 = lddbl (pckey2);
352  if (dvalue1 < dvalue2) {
353  return -idescbias;
354  }
355  if (dvalue1 > dvalue2) {
356  return idescbias;
357  }
358  pckey1 += DOUBLESIZE;
359  pckey2 += DOUBLESIZE;
360  ilengthtocompare -= DOUBLESIZE;
361  }
362  break;
363 
364  default:
365  break;
366  }
367  }
368  return 0;
369 }
static int inl_ldint(void *pclocation)
Definition: isinternal.h:170
double lddbl(void *pclocation)
Definition: ishelper.c:504
double ldfloat(void *pclocation)
Definition: ishelper.c:465
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
#define QUADSIZE
Definition: isinternal.h:108
static int inl_ldlong(void *pclocation)
Definition: isinternal.h:209
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
static off_t inl_ldquad(void *pclocation)
Definition: isinternal.h:238

Here is the call graph for this function:

Here is the caller graph for this function:

int ivbkeydelete ( const int  ihandle,
const int  ikeynumber 
)

Definition at line 777 of file vbkeysio.c.

References VBKEY::iisdummy, VBTREE::iiseof, VBKEY::iishigh, VBTREE::iisroot, VBTREE::iistof, VBTREE::ikeysinnode, VBTREE::ilevel, ivbnodefree(), ivbnodeload(), ivbnodesave(), NULL, VBKEY::pschild, VBTREE::pskeycurr, DICTINFO::pskeycurr, DICTINFO::pskeydesc, VBTREE::pskeyfirst, VBTREE::pskeylist, VBKEY::psnext, VBKEY::psparent, VBTREE::psparent, VBKEY::psprev, DICTINFO::pstree, psvbfile, VBKEY::tdupnumber, VBTREE::tnodenumber, VBKEY::trownode, vvbkeyfree(), and vvbtreeallfree().

Referenced by irowdelete(), and irowupdate().

778 {
779  struct DICTINFO *psvbptr;
780  struct VBKEY *pskey, *pskeytemp;
781  struct VBTREE *pstree, *pstreeroot;
782  int iforcerewrite = 0, iposn, iresult;
783 
784  psvbptr = psvbfile[ihandle];
785  pskey = psvbptr->pskeycurr[ikeynumber];
786  /*
787  * We're going to *TRY* to keep the index buffer populated!
788  * However, since it's technically feasible for the current node to be
789  * removed in it's entirety, we can only do this if there is at least 1
790  * other key in the node that's not the dummy entry.
791  * Since the current key is guaranteed to be at the LEAF node level (0),
792  * it's impossible to ever have an iishigh entry in the node.
793  */
794  if (pskey->psnext && pskey->psnext->iisdummy == 0) {
795  psvbptr->pskeycurr[ikeynumber] = pskey->psnext;
796  pskey->psparent->pskeycurr = pskey->psnext;
797  } else {
798  if (pskey->psprev) {
799  psvbptr->pskeycurr[ikeynumber] = pskey->psprev;
800  pskey->psparent->pskeycurr = pskey->psprev;
801  } else {
802  psvbptr->pskeycurr[ikeynumber] = NULL;
803  pskey->psparent->pskeycurr = NULL;
804  }
805  }
806  while (1) {
807  pstree = pskey->psparent;
808  if (pskey->iishigh) {
809  /*
810  * Handle removal of the high key in a node.
811  * Since we're modifying a key OTHER than the one we're
812  * deleting, we need a FULL node rewrite!
813  */
814  if (pskey->psprev) {
815  pskey->pschild = pskey->psprev->pschild;
816  pskey->trownode = pskey->psprev->trownode;
817  pskey->tdupnumber = pskey->psprev->tdupnumber;
818  pskey = pskey->psprev;
819  iforcerewrite = 1;
820  } else {
821  iresult = ivbnodefree (ihandle, pstree->tnodenumber); /* BUG - didn't check iresult */
822  pstree = pstree->psparent;
823  vvbtreeallfree (ihandle, ikeynumber,
824  pstree->pskeycurr->pschild);
825  pskey = pstree->pskeycurr;
826  pskey->pschild = NULL;
827  continue;
828  }
829  }
830  iposn = -1;
831  pskey->psparent->ikeysinnode = 0;
832  for (pskeytemp = pskey->psparent->pskeyfirst; pskeytemp;
833  pskeytemp = pskeytemp->psnext) {
834  if (pskey == pskeytemp) {
835  iposn = pskey->psparent->ikeysinnode;
836  } else {
837  pskey->psparent->pskeylist[pskey->psparent->ikeysinnode] = pskeytemp;
838  pskey->psparent->ikeysinnode++;
839  }
840  }
841  if (pskey->psprev) {
842  pskey->psprev->psnext = pskey->psnext;
843  } else {
844  pstree->pskeyfirst = pskey->psnext;
845  }
846  if (pskey->psnext) {
847  pskey->psnext->psprev = pskey->psprev;
848  }
849  pskey->psparent = NULL;
850  pskey->pschild = NULL;
851  vvbkeyfree (ihandle, ikeynumber, pskey);
852  if (pstree->iisroot
853  && (pstree->pskeyfirst->iishigh
854  || pstree->pskeyfirst->iisdummy)) {
855  pskey = pstree->pskeyfirst;
856  if (!pskey->pschild) {
857  pstreeroot = pstree;
858  } else {
859  pstreeroot = pskey->pschild;
860  pskey->pschild = NULL;
861  }
862  if (pskey->iisdummy) { /* EMPTY FILE! */
863  return ivbnodesave (ihandle, ikeynumber, pstreeroot,
864  pstreeroot->tnodenumber, 0, 0);
865  }
866  iresult = ivbnodeload (ihandle, ikeynumber, pstreeroot, pskey->trownode,
867  (int)pstree->ilevel);
868  if (iresult) {
869  return iresult; /* BUG Corrupt! */
870  }
871  iresult = ivbnodefree (ihandle, pstreeroot->tnodenumber);
872  if (iresult) {
873  return iresult; /* BUG Corrupt! */
874  }
875  pstreeroot->tnodenumber =
876  psvbptr->pskeydesc[ikeynumber]->k_rootnode;
877  pstreeroot->psparent = NULL;
878  pstreeroot->iistof = 1;
879  pstreeroot->iiseof = 1;
880  pstreeroot->iisroot = 1;
881  if (pstree != pstreeroot) {
882  vvbtreeallfree (ihandle, ikeynumber, pstree);
883  }
884  psvbptr->pstree[ikeynumber] = pstreeroot;
885  return ivbnodesave (ihandle, ikeynumber, pstreeroot,
886  pstreeroot->tnodenumber, 0, 0);
887  }
888  if (pstree->pskeyfirst->iisdummy) {
889  /* Handle removal of the last key in a node */
890  iresult = ivbnodefree (ihandle, pstree->tnodenumber);
891  if (iresult) {
892  return iresult; /* BUG Corrupt! */
893  }
894  pstree = pstree->psparent;
895  vvbtreeallfree (ihandle, ikeynumber, pstree->pskeycurr->pschild);
896  pstree->pskeycurr->pschild = NULL;
897  pskey = pstree->pskeycurr;
898  continue;
899  }
900  break;
901  }
902  if (iforcerewrite) {
903  return ivbnodesave (ihandle, ikeynumber, pstree, pstree->tnodenumber, 0, 0);
904  }
905  return ivbnodesave (ihandle, ikeynumber, pstree, pstree->tnodenumber, -1, iposn);
906 }
unsigned char iishigh
Definition: isinternal.h:331
struct VBTREE * pschild
Definition: isinternal.h:327
unsigned char iisroot
Definition: isinternal.h:347
unsigned char iisdummy
Definition: isinternal.h:332
int ivbnodeload(const int ihandle, const int ikeynumber, struct VBTREE *pstree, const off_t tnodenumber, const int iprevlvl)
Definition: vbnodememio.c:285
struct VBTREE * psparent
Definition: isinternal.h:326
struct VBKEY * pskeycurr
Definition: isinternal.h:342
EC ARGUMENT EC EC BOUND EC BOUND EC BOUND EC BOUND TABLE EC DATA EC DATA EC DATA PTR NULL
Definition: exception.def:95
off_t tnodenumber
Definition: isinternal.h:343
struct VBKEY * pskeycurr[32]
Definition: isinternal.h:448
off_t trownode
Definition: isinternal.h:328
unsigned char iiseof
Definition: isinternal.h:349
int ivbnodesave(const int ihandle, const int ikeynumber, struct VBTREE *pstree, const off_t tnodenumber, const int imode, const int iposn)
Definition: vbnodememio.c:416
unsigned int ikeysinnode
Definition: isinternal.h:346
void vvbkeyfree(const int ihandle, const int ikeynumber, struct VBKEY *pskey)
Definition: vbmemio.c:172
struct VBKEY * psprev
Definition: isinternal.h:325
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
off_t tdupnumber
Definition: isinternal.h:329
int ivbnodefree(const int ihandle, const off_t tnodenumber)
Definition: vbindexio.c:67
void vvbtreeallfree(const int ihandle, const int ikeynumber, struct VBTREE *pstree)
Definition: vbmemio.c:105
struct VBKEY * pskeylist[512]
Definition: isinternal.h:352
unsigned int ilevel
Definition: isinternal.h:345
struct VBTREE * pstree[32]
Definition: isinternal.h:446
struct VBKEY * pskeyfirst
Definition: isinternal.h:340
struct VBTREE * psparent
Definition: isinternal.h:339
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
unsigned char iistof
Definition: isinternal.h:348
struct VBKEY * psnext
Definition: isinternal.h:324

Here is the call graph for this function:

Here is the caller graph for this function:

int ivbkeyinsert ( const int  ihandle,
struct VBTREE pstree,
const int  ikeynumber,
unsigned char *  pckeyvalue,
off_t  trownode,
off_t  tdupnumber,
struct VBTREE pschild 
)

Definition at line 727 of file vbkeysio.c.

References VBKEY::ckey, VBKEY::iisnew, VBTREE::ikeysinnode, ivbnodesave(), VBKEY::pschild, VBTREE::pskeycurr, DICTINFO::pskeycurr, DICTINFO::pskeydesc, VBTREE::pskeyfirst, VBTREE::pskeylist, VBKEY::psnext, VBKEY::psparent, VBKEY::psprev, psvbfile, psvbkeyallocate(), VBKEY::tdupnumber, VBTREE::tnodenumber, and VBKEY::trownode.

Referenced by imakekeysfromdata(), inodesplit(), irowinsert(), irowupdate(), and vaddkeyforrow().

730 {
731  struct DICTINFO *psvbptr;
732  struct VBKEY *pskey, *pstempkey;
733  int iposn = 0, iresult;
734 
735  psvbptr = psvbfile[ihandle];
736  pskey = psvbkeyallocate (ihandle, ikeynumber);
737  if (!pskey) {
738  return errno;
739  }
740  if (!psvbptr->pskeycurr[ikeynumber]) {
741  return EBADFILE;
742  }
743  if (!pstree) {
744  pstree = psvbptr->pskeycurr[ikeynumber]->psparent;
745  }
746  pskey->psparent = pstree;
747  pskey->pschild = pschild;
748  pskey->trownode = trownode;
749  pskey->tdupnumber = tdupnumber;
750  pskey->iisnew = 1;
751  memcpy (pskey->ckey, pckeyvalue, (size_t)psvbptr->pskeydesc[ikeynumber]->k_len);
752  pskey->psnext = pstree->pskeycurr;
753  pskey->psprev = pstree->pskeycurr->psprev;
754  if (pstree->pskeycurr->psprev) {
755  pstree->pskeycurr->psprev->psnext = pskey;
756  } else {
757  pstree->pskeyfirst = pskey;
758  }
759  pstree->pskeycurr->psprev = pskey;
760  pstree->pskeycurr = pskey;
761  psvbptr->pskeycurr[ikeynumber] = pskey;
762  pstree->ikeysinnode = 0;
763  for (pstempkey = pstree->pskeyfirst; pstempkey; pstempkey = pstempkey->psnext) {
764  if (pstempkey == pskey) {
765  iposn = pstree->ikeysinnode;
766  }
767  pstree->pskeylist[pstree->ikeysinnode] = pstempkey;
768  pstree->ikeysinnode++;
769  }
770  iresult = ivbnodesave (ihandle, ikeynumber, pskey->psparent,
771  pskey->psparent->tnodenumber, 1, iposn);
772  pskey->iisnew = 0;
773  return iresult;
774 }
struct VBTREE * pschild
Definition: isinternal.h:327
unsigned char ckey[1]
Definition: isinternal.h:334
struct VBKEY * psvbkeyallocate(const int ihandle, const int ikeynumber)
Definition: vbmemio.c:120
struct VBTREE * psparent
Definition: isinternal.h:326
struct VBKEY * pskeycurr
Definition: isinternal.h:342
off_t tnodenumber
Definition: isinternal.h:343
struct VBKEY * pskeycurr[32]
Definition: isinternal.h:448
off_t trownode
Definition: isinternal.h:328
int ivbnodesave(const int ihandle, const int ikeynumber, struct VBTREE *pstree, const off_t tnodenumber, const int imode, const int iposn)
Definition: vbnodememio.c:416
unsigned int ikeysinnode
Definition: isinternal.h:346
struct VBKEY * psprev
Definition: isinternal.h:325
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
off_t tdupnumber
Definition: isinternal.h:329
struct VBKEY * pskeylist[512]
Definition: isinternal.h:352
struct VBKEY * pskeyfirst
Definition: isinternal.h:340
unsigned char iisnew
Definition: isinternal.h:330
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
struct VBKEY * psnext
Definition: isinternal.h:324

Here is the call graph for this function:

Here is the caller graph for this function:

int ivbkeyload ( const int  ihandle,
const int  ikeynumber,
const int  imode,
const int  isetcurr,
struct VBKEY **  ppskey 
)

Definition at line 503 of file vbkeysio.c.

References DICTINFO::iindexchanged, VBKEY::iisdummy, VBTREE::iiseof, VBTREE::iistof, VBTREE::ilevel, ivbnodeload(), NULL, VBKEY::pschild, VBTREE::pskeycurr, DICTINFO::pskeycurr, VBTREE::pskeyfirst, VBTREE::pskeylast, VBKEY::psnext, VBKEY::psparent, VBTREE::psparent, VBKEY::psprev, psvbfile, psvbtreeallocate(), VBKEY::trownode, and vvbtreeallfree().

Referenced by imakekeysfromdata(), irowinsert(), irowupdate(), isread(), isstart(), ivbkeylocaterow(), ivbkeysearch(), and vaddkeyforrow().

505 {
506  struct DICTINFO *psvbptr;
507  struct VBKEY *pskey, *pskeyhold;
508  struct VBTREE *pstree;
509  int iresult;
510 
511  psvbptr = psvbfile[ihandle];
512  pskey = psvbptr->pskeycurr[ikeynumber];
513  if (pskey->psparent->ilevel) {
514  return EBADFILE;
515  }
516  switch (imode) {
517  case ISPREV:
518  if (pskey->psprev) {
519  *ppskey = pskey->psprev;
520  if (isetcurr) {
521  psvbptr->pskeycurr[ikeynumber] = pskey->psprev;
522  pskey->psparent->pskeycurr = pskey->psprev;
523  }
524  return 0;
525  }
526  pstree = pskey->psparent;
527  if (pstree->iistof) {
528  return EENDFILE;
529  }
530  /* Back up the tree until we find a node where there is a < */
531  while (pstree->pskeycurr == pstree->pskeyfirst) {
532  if (pstree->psparent) {
533  pstree = pstree->psparent;
534  } else {
535  break;
536  }
537  }
538  /* Back down the tree selecting the LAST valid key of each */
539  pskey = pstree->pskeycurr->psprev;
540  if (isetcurr) {
541  pstree->pskeycurr = pstree->pskeycurr->psprev;
542  }
543  while (pstree->ilevel && pskey) {
544  if (isetcurr) {
545  pstree->pskeycurr = pskey;
546  }
547  if (!pskey->pschild || psvbptr->iindexchanged) {
548  if (!pskey->pschild) {
549  pskey->pschild = psvbtreeallocate (ihandle);
550  if (!pskey->pschild) {
551  return errno;
552  }
553  pskey->pschild->psparent = pskey->psparent;
554  if (pskey->psparent->iistof
555  && pskey == pskey->psparent->pskeyfirst) {
556  pskey->pschild->iistof = 1;
557  }
558  if (pskey->psparent->iiseof
559  && pskey == pskey->psparent->pskeylast->psprev) {
560  pskey->pschild->iiseof = 1;
561  }
562  }
563  pskeyhold = pskey;
564  iresult = ivbnodeload (ihandle, ikeynumber, pskey->pschild,
565  pskey->trownode, (int)pstree->ilevel);
566  if (iresult) {
567  /* Ooops, make sure the tree is not corrupt */
568  vvbtreeallfree (ihandle, ikeynumber,
569  pskeyhold->pschild);
570  pskeyhold->pschild = NULL;
571  return iresult;
572  }
573  }
574  pstree = pskey->pschild;
575  /* Last key is always the dummy, so backup by one */
576  pskey = pstree->pskeylast->psprev;
577  }
578  if (isetcurr) {
579  pstree->pskeycurr = pskey;
580  psvbptr->pskeycurr[ikeynumber] = pskey;
581  }
582  *ppskey = pskey;
583  break;
584 
585  case ISNEXT:
586  if (pskey->psnext && !pskey->psnext->iisdummy) {
587  *ppskey = pskey->psnext;
588  if (isetcurr) {
589  psvbptr->pskeycurr[ikeynumber] = pskey->psnext;
590  pskey->psparent->pskeycurr = pskey->psnext;
591  }
592  return 0;
593  }
594  pstree = pskey->psparent;
595  if (pstree->iiseof) {
596  return EENDFILE;
597  }
598  pstree = pstree->psparent;
599  /* Back up the tree until we find a node where there is a > */
600  while (1) {
601  if (pstree->pskeylast->psprev != pstree->pskeycurr) {
602  break;
603  }
604  pstree = pstree->psparent;
605  }
606  pskey = pstree->pskeycurr->psnext;
607  if (isetcurr) {
608  pstree->pskeycurr = pstree->pskeycurr->psnext;
609  }
610  /* Back down the tree selecting the FIRST valid key of each */
611  while (pstree->ilevel) {
612  if (isetcurr) {
613  pstree->pskeycurr = pskey;
614  }
615  if (!pskey->pschild || psvbptr->iindexchanged) {
616  if (!pskey->pschild) {
617  pskey->pschild = psvbtreeallocate (ihandle);
618  if (!pskey->pschild) {
619  return errno;
620  }
621  pskey->pschild->psparent = pskey->psparent;
622  if (pskey->psparent->iistof
623  && pskey == pskey->psparent->pskeyfirst) {
624  pskey->pschild->iistof = 1;
625  }
626  if (pskey->psparent->iiseof
627  && pskey == pskey->psparent->pskeylast->psprev) {
628  pskey->pschild->iiseof = 1;
629  }
630  }
631  pskeyhold = pskey;
632  iresult = ivbnodeload (ihandle, ikeynumber, pskey->pschild,
633  pskey->trownode, (int)pstree->ilevel);
634  if (iresult) {
635  /* Ooops, make sure the tree is not corrupt */
636  vvbtreeallfree (ihandle, ikeynumber,
637  pskeyhold->pschild);
638  pskeyhold->pschild = NULL;
639  return iresult;
640  }
641  }
642  pstree = pskey->pschild;
643  pskey = pstree->pskeyfirst;
644  }
645  if (isetcurr) {
646  pstree->pskeycurr = pskey;
647  psvbptr->pskeycurr[ikeynumber] = pskey;
648  }
649  *ppskey = pskey;
650  break;
651 
652  default:
653  break;
654  }
655  return 0;
656 }
struct VBTREE * psvbtreeallocate(const int ihandle)
Definition: vbmemio.c:88
unsigned char iindexchanged
Definition: isinternal.h:434
struct VBTREE * pschild
Definition: isinternal.h:327
struct VBKEY * pskeylast
Definition: isinternal.h:341
unsigned char iisdummy
Definition: isinternal.h:332
int ivbnodeload(const int ihandle, const int ikeynumber, struct VBTREE *pstree, const off_t tnodenumber, const int iprevlvl)
Definition: vbnodememio.c:285
struct VBTREE * psparent
Definition: isinternal.h:326
struct VBKEY * pskeycurr
Definition: isinternal.h:342
EC ARGUMENT EC EC BOUND EC BOUND EC BOUND EC BOUND TABLE EC DATA EC DATA EC DATA PTR NULL
Definition: exception.def:95
struct VBKEY * pskeycurr[32]
Definition: isinternal.h:448
off_t trownode
Definition: isinternal.h:328
unsigned char iiseof
Definition: isinternal.h:349
struct VBKEY * psprev
Definition: isinternal.h:325
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
void vvbtreeallfree(const int ihandle, const int ikeynumber, struct VBTREE *pstree)
Definition: vbmemio.c:105
unsigned int ilevel
Definition: isinternal.h:345
struct VBKEY * pskeyfirst
Definition: isinternal.h:340
struct VBTREE * psparent
Definition: isinternal.h:339
unsigned char iistof
Definition: isinternal.h:348
struct VBKEY * psnext
Definition: isinternal.h:324

Here is the call graph for this function:

Here is the caller graph for this function:

int ivbkeylocaterow ( const int  ihandle,
const int  ikeynumber,
off_t  trownumber 
)

Definition at line 435 of file vbkeysio.c.

References VBKEY::ckey, iserrno, ivbkeycompare(), ivbkeyload(), ivbkeysearch(), DICTINFO::ppcrowbuffer, VBKEY::pschild, VBTREE::pskeycurr, DICTINFO::pskeycurr, DICTINFO::pskeydesc, VBTREE::pskeyfirst, VBKEY::psnext, VBKEY::psparent, VBTREE::psparent, psvbfile, VBKEY::trownode, and vvbmakekey().

Referenced by irowdelete(), irowupdate(), and isread().

436 {
437  struct DICTINFO *psvbptr;
438  struct VBKEY *pskey;
439  struct VBTREE *pstree;
440  int iresult;
441  unsigned char ckeyvalue[VB_MAX_KEYLEN];
442 
443  /*
444  * Step 1:
445  * The easy way out...
446  * If it is already the current index pointer *AND*
447  * the index file has remained unchanged since then,
448  * we don't need to do anything
449  */
450  psvbptr = psvbfile[ihandle];
451  iresult = 1;
452  pskey = psvbptr->pskeycurr[ikeynumber];
453  if (pskey && pskey->trownode == trownumber) {
454  pskey->psparent->pskeycurr = pskey;
455  /* Position pskeycurr all the way up to the root to point at us */
456  pstree = pskey->psparent;
457  while (pstree->psparent) {
458  for (pstree->psparent->pskeycurr = pstree->psparent->pskeyfirst;
459  pstree->psparent->pskeycurr
460  && pstree->psparent->pskeycurr->pschild != pstree;
461  pstree->psparent->pskeycurr =
462  pstree->psparent->pskeycurr->psnext) ;
463  if (!pstree->psparent->pskeycurr) {
464  iresult = 0;
465  }
466  pstree = pstree->psparent;
467  }
468  if (iresult) {
469  return 0;
470  }
471  }
472 
473  /*
474  * Step 2:
475  * It's a valid and non-deleted row. Therefore, let's make a
476  * contiguous key from it to search by.
477  * Find the damn key!
478  */
479  vvbmakekey (psvbptr->pskeydesc[ikeynumber], psvbptr->ppcrowbuffer, ckeyvalue);
480  iresult = ivbkeysearch (ihandle, ISGTEQ, ikeynumber, 0, ckeyvalue, (off_t)0);
481  if (iresult < 0 || iresult > 1) {
482  iserrno = ENOREC;
483  return -1;
484  }
485  while (psvbptr->pskeycurr[ikeynumber]->trownode != trownumber) {
486  iserrno = ivbkeyload (ihandle, ikeynumber, ISNEXT, 1, &pskey);
487  if (iserrno) {
488  if (iserrno == EENDFILE) {
489  iserrno = ENOREC;
490  }
491  return -1;
492  }
493  if (ivbkeycompare (ihandle, ikeynumber, 0, ckeyvalue,
494  psvbptr->pskeycurr[ikeynumber]->ckey)) {
495  iserrno = ENOREC;
496  return -1;
497  }
498  }
499  return 0;
500 }
void vvbmakekey(const struct keydesc *pskeydesc, char *pcrow_buffer, unsigned char *pckeyvalue)
Definition: vbkeysio.c:212
int ivbkeyload(const int ihandle, const int ikeynumber, const int imode, const int isetcurr, struct VBKEY **ppskey)
Definition: vbkeysio.c:503
int ivbkeycompare(const int ihandle, const int ikeynumber, int ilength, unsigned char *pckey1, unsigned char *pckey2)
Definition: vbkeysio.c:230
struct VBTREE * pschild
Definition: isinternal.h:327
unsigned char ckey[1]
Definition: isinternal.h:334
int ivbkeysearch(const int ihandle, const int imode, const int ikeynumber, int ilength, unsigned char *pckeyvalue, off_t tdupnumber)
Definition: vbkeysio.c:372
struct VBTREE * psparent
Definition: isinternal.h:326
struct VBKEY * pskeycurr
Definition: isinternal.h:342
struct VBKEY * pskeycurr[32]
Definition: isinternal.h:448
off_t trownode
Definition: isinternal.h:328
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
struct VBKEY * pskeyfirst
Definition: isinternal.h:340
struct VBTREE * psparent
Definition: isinternal.h:339
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
struct VBKEY * psnext
Definition: isinternal.h:324
char * ppcrowbuffer
Definition: isinternal.h:423
int iserrno
Definition: vbmemio.c:27

Here is the call graph for this function:

Here is the caller graph for this function:

int ivbkeysearch ( const int  ihandle,
const int  imode,
const int  ikeynumber,
int  ilength,
unsigned char *  pckeyvalue,
off_t  tdupnumber 
)

Definition at line 372 of file vbkeysio.c.

References iserrno, itreeload(), ivbkeyload(), DICTINFO::pskeydesc, psvbfile, VB_MAX_OFF_T, and vvbkeyvalueset().

Referenced by imakekeysfromdata(), irowinsert(), irowupdate(), isdelete(), isread(), isrewrite(), isstart(), ivbkeylocaterow(), and vaddkeyforrow().

374 {
375  struct VBKEY *pskey;
376  struct keydesc *pskeydesc;
377  int iresult;
378  unsigned char ckeyvalue[VB_MAX_KEYLEN];
379 
380  pskeydesc = psvbfile[ihandle]->pskeydesc[ikeynumber];
381  if (ilength == 0) {
382  ilength = pskeydesc->k_len;
383  }
384  switch (imode) {
385  case ISFIRST:
386  vvbkeyvalueset (0, pskeydesc, ckeyvalue);
387  tdupnumber = -1;
388  return itreeload (ihandle, ikeynumber, ilength, ckeyvalue, tdupnumber);
389 
390  case ISLAST:
391  vvbkeyvalueset (1, pskeydesc, ckeyvalue);
392  tdupnumber = VB_MAX_OFF_T;
393  return itreeload (ihandle, ikeynumber, ilength, ckeyvalue, tdupnumber);
394 
395  case ISNEXT:
396  iresult = ivbkeyload (ihandle, ikeynumber, ISNEXT, 1, &pskey);
397  iserrno = iresult;
398  if (iresult == EENDFILE) {
399  iresult = 0;
400  }
401  if (iresult) {
402  return -1;
403  }
404  return 1; /* "NEXT" can NEVER be an exact match! */
405 
406  case ISPREV:
407  iresult = ivbkeyload (ihandle, ikeynumber, ISPREV, 1, &pskey);
408  iserrno = iresult;
409  if (iresult == EENDFILE) {
410  iresult = 0;
411  }
412  if (iresult) {
413  return -1;
414  }
415  return 1; /* "PREV" can NEVER be an exact match */
416 
417  case ISCURR:
418  return itreeload (ihandle, ikeynumber, ilength, pckeyvalue, tdupnumber);
419 
420  case ISEQUAL: /* Falls thru to ISGTEQ */
421  tdupnumber = 0;
422  case ISGTEQ:
423  return itreeload (ihandle, ikeynumber, ilength, pckeyvalue, tdupnumber);
424 
425  case ISGREAT:
426  tdupnumber = VB_MAX_OFF_T;
427  return itreeload (ihandle, ikeynumber, ilength, pckeyvalue, tdupnumber);
428 
429  }
430  /* From call sites, not possible */
431  return -1;
432 }
#define VB_MAX_OFF_T
Definition: vbkeysio.c:23
int ivbkeyload(const int ihandle, const int ikeynumber, const int imode, const int isetcurr, struct VBKEY **ppskey)
Definition: vbkeysio.c:503
static int itreeload(const int ihandle, const int ikeynumber, const int ilength, unsigned char *pckeyvalue, off_t tdupnumber)
Definition: vbkeysio.c:31
void vvbkeyvalueset(const int ihigh, struct keydesc *pskeydesc, unsigned char *pckeyvalue)
Definition: vbkeysio.c:659
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
int iserrno
Definition: vbmemio.c:27

Here is the call graph for this function:

Here is the caller graph for this function:

void vvbkeyvalueset ( const int  ihigh,
struct keydesc *  pskeydesc,
unsigned char *  pckeyvalue 
)

Definition at line 659 of file vbkeysio.c.

References inl_stint(), inl_stlong(), QUADSIZE, stdbl(), and stfloat().

Referenced by inewroot(), ivbkeysearch(), and ivbnodeload().

660 {
661  struct keypart *pskptr;
662  int ipart, iremainder;
663  char cbuffer[QUADSIZE];
664 
665  for (ipart = 0; ipart < pskeydesc->k_nparts; ipart++) {
666  pskptr = &pskeydesc->k_part[ipart];
667  switch (pskptr->kp_type & ~ISDESC) {
668  case CHARTYPE:
669  memset (pckeyvalue, ihigh ? 0xff : 0, (size_t)pskptr->kp_leng);
670  pckeyvalue += pskptr->kp_leng;
671  break;
672 
673  case INTTYPE:
674  iremainder = pskptr->kp_leng;
675  while (iremainder > 0) {
676  inl_stint (ihigh ? SHRT_MAX : SHRT_MIN, pckeyvalue);
677  pckeyvalue += INTSIZE;
678  iremainder -= INTSIZE;
679  }
680  break;
681 
682  case LONGTYPE:
683  iremainder = pskptr->kp_leng;
684  while (iremainder > 0) {
685  inl_stlong (ihigh ? LONG_MAX : LONG_MIN, pckeyvalue);
686  pckeyvalue += LONGSIZE;
687  iremainder -= LONGSIZE;
688  }
689  break;
690 
691  case QUADTYPE:
692  memset (cbuffer, ihigh ? 0xff : 0, QUADSIZE);
693  cbuffer[0] = ihigh ? 0x7f : 0x80;
694  iremainder = pskptr->kp_leng;
695  while (iremainder > 0) {
696  memcpy (pckeyvalue, cbuffer, QUADSIZE);
697  pckeyvalue += QUADSIZE;
698  iremainder -= QUADSIZE;
699  }
700  break;
701 
702  case FLOATTYPE:
703  iremainder = pskptr->kp_leng;
704  while (iremainder > 0) {
705  stfloat (ihigh ? FLT_MAX : FLT_MIN, pckeyvalue);
706  pckeyvalue += FLOATSIZE;
707  iremainder -= FLOATSIZE;
708  }
709  break;
710 
711  case DOUBLETYPE:
712  iremainder = pskptr->kp_leng;
713  while (iremainder > 0) {
714  stdbl (ihigh ? DBL_MAX : DBL_MIN, pckeyvalue);
715  pckeyvalue += DOUBLESIZE;
716  iremainder -= DOUBLESIZE;
717  }
718  break;
719 
720  default:
721  break;
722  }
723  }
724 }
void stdbl(double dsource, void *pcdestination)
Definition: ishelper.c:513
static void inl_stlong(int lvalue, void *pclocation)
Definition: isinternal.h:226
static void inl_stint(int ivalue, void *pclocation)
Definition: isinternal.h:190
void stfloat(double dsource, void *pcdestination)
Definition: ishelper.c:476
#define QUADSIZE
Definition: isinternal.h:108

Here is the call graph for this function:

Here is the caller graph for this function:

void vvbmakekey ( const struct keydesc *  pskeydesc,
char *  pcrow_buffer,
unsigned char *  pckeyvalue 
)

Definition at line 212 of file vbkeysio.c.

Referenced by imakekeysfromdata(), irowinsert(), irowupdate(), isdelete(), isread(), isrewrite(), isstart(), ivbkeylocaterow(), and vaddkeyforrow().

214 {
215  const struct keypart *pskptr;
216  char *pcsource;
217  int ipart;
218 
219  /* Wierdly enough, a single keypart *CAN* span multiple instances */
220  /* EG: Part number 1 might contain 4 long values */
221  for (ipart = 0; ipart < pskeydesc->k_nparts; ipart++) {
222  pskptr = &pskeydesc->k_part[ipart];
223  pcsource = pcrow_buffer + pskptr->kp_start;
224  memcpy (pckeyvalue, pcsource, (size_t)pskptr->kp_leng);
225  pckeyvalue += pskptr->kp_leng;
226  }
227 }

Here is the caller graph for this function: