1 /*
2 * Copyright (c) 2003-2014 Tony Bybell.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23 #include <config.h>
24 #include "lxt2_read.h"
25
26 /****************************************************************************/
27
28 #ifdef _WAVE_BE32
29
30 /*
31 * reconstruct 8/16/24/32 bits out of the lxt's representation
32 * of a big-endian integer. this is for 32-bit PPC so no byte
33 * swizzling needs to be done at all. for 24-bit ints, we have no danger of
34 * running off the end of memory provided we do the "-1" trick
35 * since we'll never read a 24-bit int at the very start of a file which
36 * means that we'll have a 32-bit word that we can read.
37 */
38
39 #define lxt2_rd_get_byte(mm,offset) ((unsigned int)(*((unsigned char *)(mm)+(offset))))
40 #define lxt2_rd_get_16(mm,offset) ((unsigned int)(*((unsigned short *)(((unsigned char *)(mm))+(offset)))))
41 #define lxt2_rd_get_32(mm,offset) (*(unsigned int *)(((unsigned char *)(mm))+(offset)))
42 #define lxt2_rd_get_24(mm,offset) ((lxt2_rd_get_32((mm),(offset)-1)<<8)>>8)
43 #define lxt2_rd_get_64(mm,offset) ((((lxtint64_t)lxt2_rd_get_32((mm),(offset)))<<32)|((lxtint64_t)lxt2_rd_get_32((mm),(offset)+4)))
44
45 #else
46
47 /*
48 * reconstruct 8/16/24/32 bits out of the lxt's representation
49 * of a big-endian integer. this should work on all architectures.
50 */
51 #define lxt2_rd_get_byte(mm,offset) ((unsigned int)(*((unsigned char *)(mm)+(offset))))
52
lxt2_rd_get_16(void * mm,int offset)53 static unsigned int lxt2_rd_get_16(void *mm, int offset)
54 {
55 unsigned char *nn=(unsigned char *)mm+offset;
56 unsigned int m1=*((unsigned char *)(nn++));
57 unsigned int m2=*((unsigned char *)nn);
58 return((m1<<8)|m2);
59 }
60
lxt2_rd_get_24(void * mm,int offset)61 static unsigned int lxt2_rd_get_24(void *mm,int offset)
62 {
63 unsigned char *nn=(unsigned char *)mm+offset;
64 unsigned int m1=*((unsigned char *)(nn++));
65 unsigned int m2=*((unsigned char *)(nn++));
66 unsigned int m3=*((unsigned char *)nn);
67 return((m1<<16)|(m2<<8)|m3);
68 }
69
lxt2_rd_get_32(void * mm,int offset)70 static unsigned int lxt2_rd_get_32(void *mm, int offset)
71 {
72 unsigned char *nn=(unsigned char *)mm+offset;
73 unsigned int m1=*((unsigned char *)(nn++));
74 unsigned int m2=*((unsigned char *)(nn++));
75 unsigned int m3=*((unsigned char *)(nn++));
76 unsigned int m4=*((unsigned char *)nn);
77 return((m1<<24)|(m2<<16)|(m3<<8)|m4);
78 }
79
lxt2_rd_get_64(void * mm,int offset)80 static lxtint64_t lxt2_rd_get_64(void *mm, int offset)
81 {
82 return(
83 (((lxtint64_t)lxt2_rd_get_32(mm,offset))<<32)
84 |((lxtint64_t)lxt2_rd_get_32(mm,offset+4))
85 );
86 }
87
88 #endif
89
90 /****************************************************************************/
91
92 /*
93 * fast SWAR ones count for 32 and 64 bits
94 */
95 #if LXT2_RD_GRANULE_SIZE > 32
96
97 _LXT2_RD_INLINE granmsk_t
lxt2_rd_ones_cnt(granmsk_t x)98 lxt2_rd_ones_cnt(granmsk_t x)
99 {
100 x -= ((x >> 1) & LXT2_RD_ULLDESC(0x5555555555555555));
101 x = (((x >> 2) & LXT2_RD_ULLDESC(0x3333333333333333)) + (x & LXT2_RD_ULLDESC(0x3333333333333333)));
102 x = (((x >> 4) + x) & LXT2_RD_ULLDESC(0x0f0f0f0f0f0f0f0f));
103 return((x * LXT2_RD_ULLDESC(0x0101010101010101)) >> 56);
104 }
105
106 #else
107
108 _LXT2_RD_INLINE granmsk_t
lxt2_rd_ones_cnt(granmsk_t x)109 lxt2_rd_ones_cnt(granmsk_t x)
110 {
111 x -= ((x >> 1) & 0x55555555);
112 x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
113 x = (((x >> 4) + x) & 0x0f0f0f0f);
114 return((x * 0x01010101) >> 24);
115 }
116
117 #endif
118
119
120 /*
121 * total zero count to the right of the first rightmost one bit
122 * encountered. its intended use is to
123 * "return the bitposition of the least significant 1 in a granmsk_t"
124 * (use x &= ~(x&-x) to clear out that bit quickly)
125 */
126 _LXT2_RD_INLINE granmsk_t
lxt2_rd_tzc(granmsk_t x)127 lxt2_rd_tzc(granmsk_t x)
128 {
129 return (lxt2_rd_ones_cnt((x & -x) - LXT2_RD_GRAN_1VAL));
130 }
131
132 /****************************************************************************/
133
134 /*
135 * i2c and c2i utility functions
136 */
lxt2_rd_expand_integer_to_bits(int len,unsigned int value)137 static char *lxt2_rd_expand_integer_to_bits(int len, unsigned int value)
138 {
139 static char s[33];
140 char *p = s;
141 int i;
142 int len2 = len-1;
143
144 for(i=0;i<len;i++)
145 {
146 *(p++) = '0' | ((value & (1<<(len2-i)))!=0);
147 }
148 *p = 0;
149
150 return(s);
151 }
152
153
lxt2_rd_expand_bits_to_integer(int len,char * s)154 unsigned int lxt2_rd_expand_bits_to_integer(int len, char *s)
155 {
156 unsigned int v = 0;
157 int i;
158
159 for(i=0;i<len;i++)
160 {
161 v <<= 1;
162 v |= ((*s) & 1);
163 s++;
164 }
165
166 return(v);
167 }
168
169
170 /*
171 * called for all value changes except for the 1st one in a block
172 * (as they're all unique based on the timeslot scheme, no duplicate
173 * checking is necessary...)
174 */
lxt2_rd_iter_radix(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b)175 void lxt2_rd_iter_radix(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b)
176 {
177 unsigned int which_time;
178 int offset;
179 void **top_elem;
180 granmsk_t msk = ~LXT2_RD_GRAN_1VAL;
181 lxtint32_t x;
182
183 for(which_time = 0; which_time < lt->num_time_table_entries; which_time++, msk <<= 1)
184 while((top_elem = lt->radix_sort[which_time]))
185 {
186 lxtint32_t idx = top_elem - lt->next_radix;
187 unsigned int vch;
188 lxtint32_t i;
189
190 switch(lt->fac_curpos_width)
191 {
192 case 1: vch = lxt2_rd_get_byte(lt->fac_curpos[idx], 0); break;
193 case 2: vch = lxt2_rd_get_16(lt->fac_curpos[idx], 0); break;
194 case 3: vch = lxt2_rd_get_24(lt->fac_curpos[idx], 0); break;
195 case 4:
196 default:
197 vch = lxt2_rd_get_32(lt->fac_curpos[idx], 0); break;
198 }
199
200 lt->fac_curpos[idx] += lt->fac_curpos_width;
201
202 offset = lxt2_rd_tzc(lt->fac_map[idx] &= msk); /* offset = next "which time" for this fac */
203
204 lt->radix_sort[which_time] = lt->next_radix[idx]; /* get next list item for this "which time" bucket */
205
206 lt->next_radix[idx] = lt->radix_sort[offset]; /* promote fac to its next (higher) possible bucket (if any) */
207 lt->radix_sort[offset] = <->next_radix[idx]; /* ...and put it at the head of that list */
208
209 switch(vch)
210 {
211 case LXT2_RD_ENC_0:
212 case LXT2_RD_ENC_1: memset(lt->value[idx], '0'+(vch-LXT2_RD_ENC_0), lt->len[idx]); break;
213
214 case LXT2_RD_ENC_INV: for(i=0;i<lt->len[idx];i++) { lt->value[idx][i] ^= 1; } break;
215
216 case LXT2_RD_ENC_LSH0:
217 case LXT2_RD_ENC_LSH1: memmove(lt->value[idx], lt->value[idx]+1, lt->len[idx]-1);
218 lt->value[idx][lt->len[idx]-1] = '0'+(vch-LXT2_RD_ENC_LSH0);
219 break;
220
221 case LXT2_RD_ENC_RSH0:
222 case LXT2_RD_ENC_RSH1: memmove(lt->value[idx]+1, lt->value[idx], lt->len[idx]-1);
223 lt->value[idx][0] = '0'+(vch-LXT2_RD_ENC_RSH0);
224 break;
225
226 case LXT2_RD_ENC_ADD1:
227 case LXT2_RD_ENC_ADD2:
228 case LXT2_RD_ENC_ADD3:
229 case LXT2_RD_ENC_ADD4: x=lxt2_rd_expand_bits_to_integer(lt->len[idx], lt->value[idx]); x+= (vch-LXT2_RD_ENC_ADD1+1);
230 memcpy(lt->value[idx], lxt2_rd_expand_integer_to_bits(lt->len[idx], x), lt->len[idx]); break;
231
232 case LXT2_RD_ENC_SUB1:
233 case LXT2_RD_ENC_SUB2:
234 case LXT2_RD_ENC_SUB3:
235 case LXT2_RD_ENC_SUB4: x=lxt2_rd_expand_bits_to_integer(lt->len[idx], lt->value[idx]); x-= (vch-LXT2_RD_ENC_SUB1+1);
236 memcpy(lt->value[idx], lxt2_rd_expand_integer_to_bits(lt->len[idx], x), lt->len[idx]); break;
237
238 case LXT2_RD_ENC_X: memset(lt->value[idx], 'x', lt->len[idx]); break;
239 case LXT2_RD_ENC_Z: memset(lt->value[idx], 'z', lt->len[idx]); break;
240
241 case LXT2_RD_ENC_BLACKOUT:
242 lt->value[idx][0] = 0; break;
243
244 default: vch -= LXT2_RD_DICT_START;
245 if(vch >= b->num_dict_entries)
246 {
247 fprintf(stderr, LXT2_RDLOAD"Internal error: vch(%d) >= num_dict_entries("LXT2_RD_LD")\n", vch, b->num_dict_entries);
248 exit(255);
249 }
250
251 if(lt->flags[idx] & (LXT2_RD_SYM_F_DOUBLE|LXT2_RD_SYM_F_STRING))
252 {
253 /* fprintf(stderr, LXT2_RDLOAD"DOUBLE: %s\n", b->string_pointers[vch]); */
254 free(lt->value[idx]);
255 lt->value[idx] = strdup(b->string_pointers[vch]);
256 break;
257 }
258
259 if(lt->len[idx] == b->string_lens[vch])
260 {
261 memcpy(lt->value[idx], b->string_pointers[vch], lt->len[idx]);
262 }
263 else
264 if(lt->len[idx] > b->string_lens[vch])
265 {
266 int lendelta = lt->len[idx] - b->string_lens[vch];
267 memset(lt->value[idx], (b->string_pointers[vch][0]!='1') ? b->string_pointers[vch][0] : '0', lendelta);
268 strcpy(lt->value[idx]+lendelta, b->string_pointers[vch]);
269 }
270 else
271 {
272 fprintf(stderr, LXT2_RDLOAD"Internal error "LXT2_RD_LD" ('%s') vs %d ('%s')\n",
273 lt->len[idx], lt->value[idx],
274 b->string_lens[vch], b->string_pointers[vch]);
275 exit(255);
276 }
277
278 break;
279 }
280
281 /* this string is _always_ unique */
282 /* fprintf(stderr, LXT2_RDLOAD"%lld : [%d] '%s'\n", lt->time_table[which_time], idx, lt->value[idx]); */
283
284 if(lt->time_table[which_time] != lt->prev_time)
285 {
286 lt->prev_time = lt->time_table[which_time];
287 }
288
289 lt->value_change_callback(<, <->time_table[which_time], &idx, <->value[idx]);
290 }
291 }
292
293
294 /*
295 * called for only 1st vch in a block: blocks out emission of duplicate
296 * vch from preceeding block
297 */
lxt2_rd_iter_radix0(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b,lxtint32_t idx)298 void lxt2_rd_iter_radix0(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b, lxtint32_t idx)
299 {
300 unsigned int vch;
301 unsigned int which_time;
302 lxtint32_t i;
303 int uniq = 0;
304
305 switch(lt->fac_curpos_width)
306 {
307 case 1: vch = lxt2_rd_get_byte(lt->fac_curpos[idx], 0); break;
308 case 2: vch = lxt2_rd_get_16(lt->fac_curpos[idx], 0); break;
309 case 3: vch = lxt2_rd_get_24(lt->fac_curpos[idx], 0); break;
310 case 4:
311 default:
312 vch = lxt2_rd_get_32(lt->fac_curpos[idx], 0); break;
313 }
314
315 lt->fac_curpos[idx] += lt->fac_curpos_width;
316 which_time = 0;
317
318 switch(vch)
319 {
320 case LXT2_RD_ENC_0: for(i=0;i<lt->len[idx];i++)
321 {
322 if(lt->value[idx][i]!='0')
323 {
324 memset(lt->value[idx]+i, '0', lt->len[idx] - i);
325 uniq = 1;
326 break;
327 }
328 }
329 break;
330
331 case LXT2_RD_ENC_1: for(i=0;i<lt->len[idx];i++)
332 {
333 if(lt->value[idx][i]!='1')
334 {
335 memset(lt->value[idx]+i, '1', lt->len[idx] - i);
336 uniq = 1;
337 break;
338 }
339 }
340 break;
341
342 case LXT2_RD_ENC_INV:
343 case LXT2_RD_ENC_LSH0:
344 case LXT2_RD_ENC_LSH1:
345 case LXT2_RD_ENC_RSH0:
346 case LXT2_RD_ENC_RSH1:
347 case LXT2_RD_ENC_ADD1:
348 case LXT2_RD_ENC_ADD2:
349 case LXT2_RD_ENC_ADD3:
350 case LXT2_RD_ENC_ADD4:
351 case LXT2_RD_ENC_SUB1:
352 case LXT2_RD_ENC_SUB2:
353 case LXT2_RD_ENC_SUB3:
354 case LXT2_RD_ENC_SUB4: fprintf(stderr, LXT2_RDLOAD"Internal error in granule 0 position 0\n");
355 exit(255);
356
357 case LXT2_RD_ENC_X: for(i=0;i<lt->len[idx];i++)
358 {
359 if(lt->value[idx][i]!='x')
360 {
361 memset(lt->value[idx]+i, 'x', lt->len[idx] - i);
362 uniq = 1;
363 break;
364 }
365 }
366 break;
367
368 case LXT2_RD_ENC_Z: for(i=0;i<lt->len[idx];i++)
369 {
370 if(lt->value[idx][i]!='z')
371 {
372 memset(lt->value[idx]+i, 'z', lt->len[idx] - i);
373 uniq = 1;
374 break;
375 }
376 }
377 break;
378
379 case LXT2_RD_ENC_BLACKOUT:
380 if(lt->value[idx])
381 {
382 lt->value[idx][0] = 0;
383 uniq=1;
384 }
385 break;
386
387 default: vch -= LXT2_RD_DICT_START;
388 if(vch >= b->num_dict_entries)
389 {
390 fprintf(stderr, LXT2_RDLOAD"Internal error: vch(%d) >= num_dict_entries("LXT2_RD_LD")\n", vch, b->num_dict_entries);
391 exit(255);
392 }
393
394 if(lt->flags[idx] & (LXT2_RD_SYM_F_DOUBLE|LXT2_RD_SYM_F_STRING))
395 {
396 /* fprintf(stderr, LXT2_RDLOAD"DOUBLE: %s\n", b->string_pointers[vch]); */
397 if(strcmp(lt->value[idx], b->string_pointers[vch]))
398 {
399 free(lt->value[idx]);
400 lt->value[idx] = strdup(b->string_pointers[vch]);
401 uniq = 1;
402 }
403 break;
404 }
405
406 if(lt->len[idx] == b->string_lens[vch])
407 {
408 for(i=0;i<lt->len[idx];i++)
409 {
410 if(lt->value[idx][i] != b->string_pointers[vch][i])
411 {
412 memcpy(lt->value[idx]+i, b->string_pointers[vch]+i, lt->len[idx]-i);
413 uniq = 1;
414 }
415 }
416 }
417 else
418 if(lt->len[idx] > b->string_lens[vch])
419 {
420 lxtint32_t lendelta = lt->len[idx] - b->string_lens[vch];
421 int fill = (b->string_pointers[vch][0]!='1') ? b->string_pointers[vch][0] : '0';
422
423 for(i=0;i<lendelta;i++)
424 {
425 if (lt->value[idx][i] != fill)
426 {
427 memset(lt->value[idx] + i, fill, lendelta - i);
428 strcpy(lt->value[idx]+lendelta, b->string_pointers[vch]);
429 uniq = 1;
430 goto fini;
431 }
432 }
433
434 for(i=lendelta;i<lt->len[idx];i++)
435 {
436 if(lt->value[idx][i] != b->string_pointers[vch][i-lendelta])
437 {
438 memcpy(lt->value[idx]+i, b->string_pointers[vch]+i-lendelta, lt->len[idx]-i);
439 uniq = 1;
440 }
441 }
442 }
443 else
444 {
445 fprintf(stderr, LXT2_RDLOAD"Internal error "LXT2_RD_LD" ('%s') vs %d ('%s')\n",
446 lt->len[idx], lt->value[idx],
447 b->string_lens[vch], b->string_pointers[vch]);
448 exit(255);
449 }
450
451 break;
452 }
453
454
455 /* this string is unique if uniq != 0 */
456 /* fprintf(stderr, LXT2_RDLOAD"%lld : [%d] '%s'\n", lt->time_table[which_time], idx, lt->value[idx]); */
457 fini: if(uniq)
458 {
459 if(lt->time_table[which_time] != lt->prev_time)
460 {
461 lt->prev_time = lt->time_table[which_time];
462 }
463
464 lt->value_change_callback(<, <->time_table[which_time], &idx, <->value[idx]);
465 }
466 }
467
468
469 /*
470 * radix sort the fac entries based upon their first entry in the
471 * time change table. this runs in strict linear time: we can
472 * do this because of the limited domain of the dataset.
473 */
lxt2_rd_build_radix(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b,int granule,lxtint32_t strtfac,lxtint32_t endfac)474 static void lxt2_rd_build_radix(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b, int granule,
475 lxtint32_t strtfac, lxtint32_t endfac)
476 {
477 lxtint32_t i;
478 int offset;
479
480 for(i=0;i<LXT2_RD_GRANULE_SIZE+1;i++) /* +1 because tzc returns 33/65 when its arg == 0 */
481 {
482 lt->radix_sort[i] = NULL; /* each one is a linked list: we get fac number based on address of item from lt->next_radix */
483 }
484
485 for(i=strtfac;i<endfac;i++)
486 {
487 granmsk_t x;
488 int process_idx = i/8;
489 int process_bit = i&7;
490
491 if(lt->process_mask[process_idx]&(1<<process_bit))
492 {
493 if((x=lt->fac_map[i]))
494 {
495 if((!granule)&&(x&LXT2_RD_GRAN_1VAL))
496 {
497 lxt2_rd_iter_radix0(lt, b, i); /* emit vcd only if it's unique */
498 x&=(~LXT2_RD_GRAN_1VAL); /* clear out least sig bit */
499 lt->fac_map[i] = x;
500 if(!x) continue;
501 }
502
503 offset = lxt2_rd_tzc(x); /* get "which time" bucket number of new least sig one bit */
504 lt->next_radix[i] = lt->radix_sort[offset]; /* insert item into head of radix sorted "which time" buckets */
505 lt->radix_sort[offset] = <->next_radix[i];
506 }
507 }
508 }
509 }
510
511 /****************************************************************************/
512
513 /*
514 * build compressed process mask if necessary
515 */
lxt2_rd_regenerate_process_mask(struct lxt2_rd_trace * lt)516 static void lxt2_rd_regenerate_process_mask(struct lxt2_rd_trace *lt)
517 {
518 lxtint32_t i;
519 int j, lim, idx;
520
521 if((lt)&&(lt->process_mask_dirty))
522 {
523 lt->process_mask_dirty = 0;
524 idx=0;
525 for(i=0;i<lt->numrealfacs;i+=LXT2_RD_PARTIAL_SIZE)
526 {
527 if(i+LXT2_RD_PARTIAL_SIZE>lt->numrealfacs)
528 {
529 lim = lt->numrealfacs;
530 }
531 else
532 {
533 lim = i+LXT2_RD_PARTIAL_SIZE;
534 }
535
536 lt->process_mask_compressed[idx] = 0;
537 for(j=i;j<lim;j++)
538 {
539 int process_idx = j/8; /* no need to optimize this */
540 int process_bit = j&7;
541
542 if(lt->process_mask[process_idx]&(1<<process_bit))
543 {
544 lt->process_mask_compressed[idx] = 1;
545 break;
546 }
547 }
548
549 idx++;
550 }
551 }
552 }
553
554 /****************************************************************************/
555
556
557 /*
558 * process a single block and execute the vch callback as necessary
559 */
lxt2_rd_process_block(struct lxt2_rd_trace * lt,struct lxt2_rd_block * b)560 int lxt2_rd_process_block(struct lxt2_rd_trace *lt, struct lxt2_rd_block *b)
561 {
562 char vld;
563 char *pnt;
564 lxtint32_t i;
565 int granule = 0;
566 char sect_typ;
567 lxtint32_t strtfac_gran=0;
568 char granvld=0;
569
570 b->num_map_entries = lxt2_rd_get_32(b->mem, b->uncompressed_siz - 4);
571 b->num_dict_entries = lxt2_rd_get_32(b->mem, b->uncompressed_siz - 12);
572
573 #if LXT2_RD_GRANULE_SIZE > 32
574 if(lt->granule_size==LXT2_RD_GRANULE_SIZE)
575 {
576 b->map_start = (b->mem + b->uncompressed_siz - 12) - sizeof(granmsk_t) * b->num_map_entries;
577 }
578 else
579 {
580 b->map_start = (b->mem + b->uncompressed_siz - 12) - sizeof(granmsk_smaller_t) * b->num_map_entries;
581 }
582
583 #else
584 b->map_start = (b->mem + b->uncompressed_siz - 12) - sizeof(granmsk_t) * b->num_map_entries;
585 #endif
586
587 b->dict_start = b->map_start - lxt2_rd_get_32(b->mem, b->uncompressed_siz - 8);
588
589 /* fprintf(stderr, LXT2_RDLOAD"num_map_entries: %d, num_dict_entries: %d, map_start: %08x, dict_start: %08x, mem: %08x end: %08x\n",
590 b->num_map_entries, b->num_dict_entries, b->map_start, b->dict_start, b->mem, b->mem+b->uncompressed_siz); */
591
592 vld = lxt2_rd_get_byte(b->dict_start - 1, 0);
593 if(vld != LXT2_RD_GRAN_SECT_DICT)
594 {
595 fprintf(stderr, LXT2_RDLOAD"Malformed section\n");
596 exit(255);
597 }
598
599 if(b->num_dict_entries)
600 {
601 b->string_pointers = malloc(b->num_dict_entries * sizeof(char *));
602 b->string_lens = malloc(b->num_dict_entries * sizeof(unsigned int));
603 pnt = b->dict_start;
604 for(i=0;i<b->num_dict_entries;i++)
605 {
606 b->string_pointers[i] = pnt;
607 b->string_lens[i] = strlen(pnt);
608 pnt += (b->string_lens[i] + 1);
609 /* fprintf(stderr, LXT2_RDLOAD"%d '%s'\n", i, b->string_pointers[i]); */
610 }
611
612 if(pnt!=b->map_start)
613 {
614 fprintf(stderr, LXT2_RDLOAD"dictionary corrupt, exiting\n");
615 exit(255);
616 }
617 }
618
619 pnt = b->mem;
620 while(((sect_typ=*pnt) == LXT2_RD_GRAN_SECT_TIME)||(sect_typ == LXT2_RD_GRAN_SECT_TIME_PARTIAL))
621 {
622 lxtint32_t strtfac, endfac;
623
624 if(sect_typ == LXT2_RD_GRAN_SECT_TIME_PARTIAL)
625 {
626 lxtint32_t sublen;
627
628 lxt2_rd_regenerate_process_mask(lt);
629
630 strtfac = lxt2_rd_get_32(pnt, 1);
631 sublen = lxt2_rd_get_32(pnt, 5);
632
633 if(!granvld)
634 {
635 granvld=1;
636 strtfac_gran = strtfac;
637 }
638 else
639 {
640 granule += (strtfac==strtfac_gran);
641 }
642
643 if(!lt->process_mask_compressed[strtfac/LXT2_RD_PARTIAL_SIZE])
644 {
645 /* fprintf(stderr, "skipping group %d for %d bytes\n", strtfac, sublen); */
646 pnt += 9;
647 pnt += sublen;
648 continue;
649 }
650
651 /* fprintf(stderr, "processing group %d for %d bytes\n", strtfac, sublen); */
652 endfac=strtfac+LXT2_RD_PARTIAL_SIZE;
653 if(endfac>lt->numrealfacs) endfac=lt->numrealfacs;
654 pnt += 8;
655 }
656 else
657 {
658 strtfac=0;
659 endfac=lt->numrealfacs;
660 }
661
662 /* fprintf(stderr, LXT2_RDLOAD"processing granule %d\n", granule); */
663 pnt++;
664 lt->num_time_table_entries = lxt2_rd_get_byte(pnt, 0);
665 pnt++;
666 for(i=0;i<lt->num_time_table_entries;i++)
667 {
668 lt->time_table[i] = lxt2_rd_get_64(pnt, 0);
669 pnt+=8;
670 /* fprintf(stderr, LXT2_RDLOAD"\t%d) %lld\n", i, lt->time_table[i]); */
671 }
672
673 lt->fac_map_index_width = lxt2_rd_get_byte(pnt, 0);
674 if((!lt->fac_map_index_width)||(lt->fac_map_index_width > 4))
675 {
676 fprintf(stderr, LXT2_RDLOAD"Map index width of %d is illegal, exiting.\n", lt->fac_map_index_width);
677 exit(255);
678 }
679 pnt++;
680
681 for(i=strtfac;i<endfac;i++)
682 {
683 lxtint32_t mskindx;
684
685 switch(lt->fac_map_index_width)
686 {
687 case 1: mskindx = lxt2_rd_get_byte(pnt, 0); break;
688 case 2: mskindx = lxt2_rd_get_16(pnt, 0); break;
689 case 3: mskindx = lxt2_rd_get_24(pnt, 0); break;
690 case 4:
691 default:
692 mskindx = lxt2_rd_get_32(pnt, 0); break;
693 }
694
695 pnt += lt->fac_map_index_width;
696
697 #if LXT2_RD_GRANULE_SIZE > 32
698 if(lt->granule_size==LXT2_RD_GRANULE_SIZE)
699 {
700 lt->fac_map[i] = get_fac_msk(b->map_start, mskindx * sizeof(granmsk_t));
701 }
702 else
703 {
704 lt->fac_map[i] = get_fac_msk_smaller(b->map_start, mskindx * sizeof(granmsk_smaller_t));
705 }
706 #else
707 lt->fac_map[i] = get_fac_msk(b->map_start, mskindx * sizeof(granmsk_t));
708 #endif
709 }
710
711 lt->fac_curpos_width = lxt2_rd_get_byte(pnt, 0);
712 if((!lt->fac_curpos_width)||(lt->fac_curpos_width > 4))
713 {
714 fprintf(stderr, LXT2_RDLOAD"Curpos index width of %d is illegal, exiting.\n", lt->fac_curpos_width);
715 exit(255);
716 }
717 pnt++;
718
719 for(i=strtfac;i<endfac;i++)
720 {
721 lt->fac_curpos[i] = pnt;
722 if(lt->fac_map[i])
723 {
724 pnt += (lxt2_rd_ones_cnt(lt->fac_map[i]) * lt->fac_curpos_width);
725 }
726 }
727
728 lxt2_rd_build_radix(lt, b, granule, strtfac, endfac);
729 lxt2_rd_iter_radix(lt, b);
730
731 if(sect_typ != LXT2_RD_GRAN_SECT_TIME_PARTIAL)
732 {
733 granule++;
734 }
735 }
736
737 return(1);
738 }
739
740
741 /****************************************************************************/
742
743 /*
744 * null callback used when a user passes NULL as an argument to lxt2_rd_iter_blocks()
745 */
lxt2_rd_null_callback(struct lxt2_rd_trace ** lt,lxtint64_t * pnt_time,lxtint32_t * pnt_facidx,char ** pnt_value)746 void lxt2_rd_null_callback(struct lxt2_rd_trace **lt, lxtint64_t *pnt_time, lxtint32_t *pnt_facidx, char **pnt_value)
747 {
748 (void) lt;
749 (void) pnt_time;
750 (void) pnt_facidx;
751 (void) pnt_value;
752
753 /* fprintf(stderr, LXT2_RDLOAD"%lld %d %s\n", *pnt_time, *pnt_facidx, *pnt_value); */
754 }
755
756 /****************************************************************************/
757
758 /*
759 * initialize the trace, get compressed facnames, get geometries,
760 * and get block offset/size/timestart/timeend...
761 */
lxt2_rd_init(const char * name)762 struct lxt2_rd_trace *lxt2_rd_init(const char *name)
763 {
764 struct lxt2_rd_trace *lt=(struct lxt2_rd_trace *)calloc(1, sizeof(struct lxt2_rd_trace));
765 lxtint32_t i;
766
767 if(!(lt->handle=fopen(name, "rb")))
768 {
769 lxt2_rd_close(lt);
770 lt=NULL;
771 }
772 else
773 {
774 lxtint16_t id = 0, version = 0;
775
776 lt->block_mem_max = LXT2_RD_MAX_BLOCK_MEM_USAGE; /* cutoff after this number of bytes and force flush */
777
778 setvbuf(lt->handle, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
779
780 if(!fread(&id, 2, 1, lt->handle)) { id = 0; }
781 if(!fread(&version, 2, 1, lt->handle)) { id = 0; }
782 if(!fread(<->granule_size, 1, 1, lt->handle)) { id = 0; }
783
784 if(lxt2_rd_get_16(&id,0) != LXT2_RD_HDRID)
785 {
786 fprintf(stderr, LXT2_RDLOAD"*** Not an lxt file ***\n");
787 lxt2_rd_close(lt);
788 lt=NULL;
789 }
790 else
791 if((version=lxt2_rd_get_16(&version,0)) > LXT2_RD_VERSION)
792 {
793 fprintf(stderr, LXT2_RDLOAD"*** Version %d lxt not supported ***\n", version);
794 lxt2_rd_close(lt);
795 lt=NULL;
796 }
797 else
798 if(lt->granule_size > LXT2_RD_GRANULE_SIZE)
799 {
800 fprintf(stderr, LXT2_RDLOAD"*** Granule size of %d (>%d) not supported ***\n", lt->granule_size, LXT2_RD_GRANULE_SIZE);
801 lxt2_rd_close(lt);
802 lt=NULL;
803 }
804 else
805 {
806 size_t rcf;
807 int rc;
808 char *m;
809 off_t pos, fend;
810 int t;
811 struct lxt2_rd_block *b;
812
813 rcf=fread(<->numfacs, 4, 1, lt->handle); lt->numfacs = rcf ? lxt2_rd_get_32(<->numfacs,0) : 0;
814
815 if(!lt->numfacs)
816 {
817 lxtint32_t num_expansion_bytes;
818
819 rcf = fread(&num_expansion_bytes, 4, 1, lt->handle); num_expansion_bytes = rcf ? lxt2_rd_get_32(&num_expansion_bytes,0) : 0;
820 rcf = fread(<->numfacs, 4, 1, lt->handle); lt->numfacs = rcf ? lxt2_rd_get_32(<->numfacs,0) : 0;
821 if(num_expansion_bytes >= 8)
822 {
823 rcf = fread(<->timezero, 8, 1, lt->handle); lt->timezero = rcf ? lxt2_rd_get_64(<->timezero,0) : 0;
824 if(num_expansion_bytes > 8)
825 {
826 /* future version? */
827 fseeko(lt->handle, num_expansion_bytes - 8, SEEK_CUR);
828 }
829 }
830 else
831 {
832 /* malformed */
833 fseeko(lt->handle, num_expansion_bytes, SEEK_CUR);
834 }
835 }
836
837 rcf=fread(<->numfacbytes, 4, 1, lt->handle); lt->numfacbytes = rcf ? lxt2_rd_get_32(<->numfacbytes,0) : 0;
838 rcf=fread(<->longestname, 4, 1, lt->handle); lt->longestname = rcf ? lxt2_rd_get_32(<->longestname,0) : 0;
839 rcf=fread(<->zfacnamesize, 4, 1, lt->handle); lt->zfacnamesize = rcf ? lxt2_rd_get_32(<->zfacnamesize,0) : 0;
840 rcf=fread(<->zfacname_predec_size, 4, 1, lt->handle); lt->zfacname_predec_size = rcf ? lxt2_rd_get_32(<->zfacname_predec_size,0) : 0;
841 rcf=fread(<->zfacgeometrysize, 4, 1, lt->handle); lt->zfacgeometrysize = rcf ? lxt2_rd_get_32(<->zfacgeometrysize,0) : 0;
842 rcf=fread(<->timescale, 1, 1, lt->handle); if(!rcf) lt->timescale = 0; /* no swap necessary */
843
844 if(!lt->numfacs) /* scan-build for mallocs below */
845 {
846 fprintf(stderr, LXT2_RDLOAD"*** Nothing to do, zero facilities found.\n");
847 lxt2_rd_close(lt);
848 lt=NULL;
849 }
850 else
851 {
852 fprintf(stderr, LXT2_RDLOAD LXT2_RD_LD" facilities\n", lt->numfacs);
853
854 pos = ftello(lt->handle);
855 /* fprintf(stderr, LXT2_RDLOAD"gzip facnames start at pos %d (zsize=%d)\n", pos, lt->zfacnamesize); */
856
857 lt->process_mask = calloc(1, lt->numfacs/8+1);
858 lt->process_mask_compressed = calloc(1, lt->numfacs/LXT2_RD_PARTIAL_SIZE+1);
859
860 lt->zhandle = gzdopen(dup(fileno(lt->handle)), "rb");
861 m=(char *)malloc(lt->zfacname_predec_size);
862 rc=gzread(lt->zhandle, m, lt->zfacname_predec_size);
863 gzclose(lt->zhandle); lt->zhandle=NULL;
864
865 if(((lxtint32_t)rc)!=lt->zfacname_predec_size)
866 {
867 fprintf(stderr, LXT2_RDLOAD"*** name section mangled %d (act) vs "LXT2_RD_LD" (exp)\n", rc, lt->zfacname_predec_size);
868 free(m);
869
870 lxt2_rd_close(lt);
871 lt=NULL;
872 return(lt);
873 }
874
875 lt->zfacnames = m;
876
877 lt->faccache = calloc(1, sizeof(struct lxt2_rd_facname_cache));
878 lt->faccache->old_facidx = lt->numfacs; /* causes lxt2_rd_get_facname to initialize its unroll ptr as this is always invalid */
879 lt->faccache->bufcurr = malloc(lt->longestname+1);
880 lt->faccache->bufprev = malloc(lt->longestname+1);
881
882 fseeko(lt->handle, pos = pos+lt->zfacnamesize, SEEK_SET);
883 /* fprintf(stderr, LXT2_RDLOAD"seeking to geometry at %d (0x%08x)\n", pos, pos); */
884 lt->zhandle = gzdopen(dup(fileno(lt->handle)), "rb");
885
886 t = lt->numfacs * 4 * sizeof(lxtint32_t);
887 m=(char *)malloc(t);
888 rc=gzread(lt->zhandle, m, t);
889 gzclose(lt->zhandle); lt->zhandle=NULL;
890 if(rc!=t)
891 {
892 fprintf(stderr, LXT2_RDLOAD"*** geometry section mangled %d (act) vs %d (exp)\n", rc, t);
893 free(m);
894
895 lxt2_rd_close(lt);
896 lt=NULL;
897 return(lt);
898 }
899
900 pos = pos+lt->zfacgeometrysize;
901
902 lt->rows = malloc(lt->numfacs * sizeof(lxtint32_t));
903 lt->msb = malloc(lt->numfacs * sizeof(lxtsint32_t));
904 lt->lsb = malloc(lt->numfacs * sizeof(lxtsint32_t));
905 lt->flags = malloc(lt->numfacs * sizeof(lxtint32_t));
906 lt->len = malloc(lt->numfacs * sizeof(lxtint32_t));
907 lt->value = malloc(lt->numfacs * sizeof(char *));
908 lt->next_radix = malloc(lt->numfacs * sizeof(void *));
909
910 for(i=0;i<lt->numfacs;i++)
911 {
912 lt->rows[i] = lxt2_rd_get_32(m+i*16, 0);
913 lt->msb[i] = lxt2_rd_get_32(m+i*16, 4);
914 lt->lsb[i] = lxt2_rd_get_32(m+i*16, 8);
915 lt->flags[i] = lxt2_rd_get_32(m+i*16, 12);
916
917 if(!(lt->flags[i] & LXT2_RD_SYM_F_INTEGER))
918 {
919 lt->len[i] = (lt->msb[i] <= lt->lsb[i]) ? (lt->lsb[i] - lt->msb[i] + 1) : (lt->msb[i] - lt->lsb[i] + 1);
920 }
921 else
922 {
923 lt->len[i] = 32;
924 }
925 lt->value[i] = calloc(lt->len[i] + 1, sizeof(char));
926 }
927
928 for(lt->numrealfacs=0; lt->numrealfacs<lt->numfacs; lt->numrealfacs++)
929 {
930 if(lt->flags[lt->numrealfacs] & LXT2_RD_SYM_F_ALIAS)
931 {
932 break;
933 }
934 }
935 if(lt->numrealfacs > lt->numfacs) lt->numrealfacs = lt->numfacs;
936
937 lt->prev_time = ~(LXT2_RD_GRAN_0VAL);
938 free(m);
939
940 lt->fac_map = malloc(lt->numfacs * sizeof(granmsk_t));
941 lt->fac_curpos = malloc(lt->numfacs * sizeof(char *));
942
943 for(;;)
944 {
945 fseeko(lt->handle, 0L, SEEK_END);
946 fend=ftello(lt->handle);
947 if(pos>=fend) break;
948
949 fseeko(lt->handle, pos, SEEK_SET);
950 /* fprintf(stderr, LXT2_RDLOAD"seeking to block at %d (0x%08x)\n", pos, pos); */
951
952 b=calloc(1, sizeof(struct lxt2_rd_block));
953
954 rcf = fread(&b->uncompressed_siz, 4, 1, lt->handle); b->uncompressed_siz = rcf ? lxt2_rd_get_32(&b->uncompressed_siz,0) : 0;
955 rcf = fread(&b->compressed_siz, 4, 1, lt->handle); b->compressed_siz = rcf ? lxt2_rd_get_32(&b->compressed_siz,0) : 0;
956 rcf = fread(&b->start, 8, 1, lt->handle); b->start = rcf ? lxt2_rd_get_64(&b->start,0) : 0;
957 rcf = fread(&b->end, 8, 1, lt->handle); b->end = rcf ? lxt2_rd_get_64(&b->end,0) : 0;
958 pos = ftello(lt->handle);
959 fseeko(lt->handle, pos, SEEK_SET);
960 /* fprintf(stderr, LXT2_RDLOAD"block gzip start at pos %d (0x%08x)\n", pos, pos); */
961 if(pos>=fend)
962 {
963 free(b);
964 break;
965 }
966
967 b->filepos = pos; /* mark startpos for later in case we purge it from memory */
968 /* fprintf(stderr, LXT2_RDLOAD"un/compressed size: %d/%d\n", b->uncompressed_siz, b->compressed_siz); */
969
970 if((b->uncompressed_siz)&&(b->compressed_siz)&&(b->end))
971 {
972 /* fprintf(stderr, LXT2_RDLOAD"block [%d] %lld / %lld\n", lt->numblocks, b->start, b->end); */
973 fseeko(lt->handle, b->compressed_siz, SEEK_CUR);
974
975 lt->numblocks++;
976 if(lt->block_curr)
977 {
978 lt->block_curr->next = b;
979 lt->block_curr = b;
980 lt->end = b->end;
981 }
982 else
983 {
984 lt->block_head = lt->block_curr = b;
985 lt->start = b->start;
986 lt->end = b->end;
987 }
988 }
989 else
990 {
991 free(b);
992 break;
993 }
994
995 pos+=b->compressed_siz;
996 }
997
998 if(lt->numblocks)
999 {
1000 fprintf(stderr, LXT2_RDLOAD"Read %d block header%s OK\n", lt->numblocks, (lt->numblocks!=1) ? "s" : "");
1001
1002 fprintf(stderr, LXT2_RDLOAD"["LXT2_RD_LLD"] start time\n", lt->start);
1003 fprintf(stderr, LXT2_RDLOAD"["LXT2_RD_LLD"] end time\n", lt->end);
1004 fprintf(stderr, LXT2_RDLOAD"\n");
1005
1006 lt->value_change_callback = lxt2_rd_null_callback;
1007 }
1008 else
1009 {
1010 lxt2_rd_close(lt);
1011 lt=NULL;
1012 }
1013 }
1014 }
1015 }
1016
1017 return(lt);
1018 }
1019
1020
1021 /*
1022 * free up/deallocate any resources still left out there:
1023 * blindly do it based on NULL pointer comparisons (ok, since
1024 * calloc() is used to allocate all structs) as performance
1025 * isn't an issue for this set of cleanup code
1026 */
lxt2_rd_close(struct lxt2_rd_trace * lt)1027 void lxt2_rd_close(struct lxt2_rd_trace *lt)
1028 {
1029 if(lt)
1030 {
1031 struct lxt2_rd_block *b, *bt;
1032 lxtint32_t i;
1033
1034 if(lt->process_mask) { free(lt->process_mask); lt->process_mask=NULL; }
1035 if(lt->process_mask_compressed) { free(lt->process_mask_compressed); lt->process_mask_compressed=NULL; }
1036
1037 if(lt->rows) { free(lt->rows); lt->rows=NULL; }
1038 if(lt->msb) { free(lt->msb); lt->msb=NULL; }
1039 if(lt->lsb) { free(lt->lsb); lt->lsb=NULL; }
1040 if(lt->flags) { free(lt->flags); lt->flags=NULL; }
1041 if(lt->len) { free(lt->len); lt->len=NULL; }
1042 if(lt->next_radix) { free(lt->next_radix); lt->next_radix=NULL; }
1043
1044 for(i=0;i<lt->numfacs;i++)
1045 {
1046 if(lt->value[i])
1047 {
1048 free(lt->value[i]); lt->value[i]=NULL;
1049 }
1050 }
1051
1052 if(lt->value) { free(lt->value); lt->value=NULL; }
1053
1054 if(lt->zfacnames) { free(lt->zfacnames); lt->zfacnames=NULL; }
1055
1056 if(lt->faccache)
1057 {
1058 if(lt->faccache->bufprev) { free(lt->faccache->bufprev); lt->faccache->bufprev=NULL; }
1059 if(lt->faccache->bufcurr) { free(lt->faccache->bufcurr); lt->faccache->bufcurr=NULL; }
1060
1061 free(lt->faccache); lt->faccache=NULL;
1062 }
1063
1064 if(lt->fac_map) { free(lt->fac_map); lt->fac_map=NULL; }
1065 if(lt->fac_curpos) { free(lt->fac_curpos); lt->fac_curpos=NULL; }
1066
1067 b=lt->block_head;
1068 while(b)
1069 {
1070 bt=b->next;
1071
1072 if(b->mem) { free(b->mem); b->mem=NULL; }
1073
1074 if(b->string_pointers) { free(b->string_pointers); b->string_pointers=NULL; }
1075 if(b->string_lens) { free(b->string_lens); b->string_lens=NULL; }
1076
1077 free(b);
1078 b=bt;
1079 }
1080
1081 lt->block_head=lt->block_curr=NULL;
1082
1083 if(lt->zhandle) { gzclose(lt->zhandle); lt->zhandle=NULL; }
1084 if(lt->handle) { fclose(lt->handle); lt->handle=NULL; }
1085 free(lt);
1086 }
1087 }
1088
1089 /****************************************************************************/
1090
1091 /*
1092 * return number of facs in trace
1093 */
lxt2_rd_get_num_facs(struct lxt2_rd_trace * lt)1094 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_num_facs(struct lxt2_rd_trace *lt)
1095 {
1096 return(lt ? lt->numfacs : 0);
1097 }
1098
1099
1100 /*
1101 * return fac geometry for a given index
1102 */
lxt2_rd_get_fac_geometry(struct lxt2_rd_trace * lt,lxtint32_t facidx)1103 struct lxt2_rd_geometry *lxt2_rd_get_fac_geometry(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1104 {
1105 if((lt)&&(facidx<lt->numfacs))
1106 {
1107 lt->geometry.rows = lt->rows[facidx];
1108 lt->geometry.msb = lt->msb[facidx];
1109 lt->geometry.lsb = lt->lsb[facidx];
1110 lt->geometry.flags = lt->flags[facidx];
1111 lt->geometry.len = lt->len[facidx];
1112 return(<->geometry);
1113 }
1114 else
1115 {
1116 return(NULL);
1117 }
1118 }
1119
1120
1121 /*
1122 * return partial fac geometry for a given index
1123 */
lxt2_rd_get_fac_rows(struct lxt2_rd_trace * lt,lxtint32_t facidx)1124 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_fac_rows(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1125 {
1126 if((lt)&&(facidx<lt->numfacs))
1127 {
1128 return(lt->rows[facidx]);
1129 }
1130 else
1131 {
1132 return(0);
1133 }
1134 }
1135
1136
lxt2_rd_get_fac_msb(struct lxt2_rd_trace * lt,lxtint32_t facidx)1137 _LXT2_RD_INLINE lxtsint32_t lxt2_rd_get_fac_msb(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1138 {
1139 if((lt)&&(facidx<lt->numfacs))
1140 {
1141 return(lt->msb[facidx]);
1142 }
1143 else
1144 {
1145 return(0);
1146 }
1147 }
1148
1149
lxt2_rd_get_fac_lsb(struct lxt2_rd_trace * lt,lxtint32_t facidx)1150 _LXT2_RD_INLINE lxtsint32_t lxt2_rd_get_fac_lsb(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1151 {
1152 if((lt)&&(facidx<lt->numfacs))
1153 {
1154 return(lt->lsb[facidx]);
1155 }
1156 else
1157 {
1158 return(0);
1159 }
1160 }
1161
1162
lxt2_rd_get_fac_flags(struct lxt2_rd_trace * lt,lxtint32_t facidx)1163 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_fac_flags(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1164 {
1165 if((lt)&&(facidx<lt->numfacs))
1166 {
1167 return(lt->flags[facidx]);
1168 }
1169 else
1170 {
1171 return(0);
1172 }
1173 }
1174
1175
lxt2_rd_get_fac_len(struct lxt2_rd_trace * lt,lxtint32_t facidx)1176 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_fac_len(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1177 {
1178 if((lt)&&(facidx<lt->numfacs))
1179 {
1180 return(lt->len[facidx]);
1181 }
1182 else
1183 {
1184 return(0);
1185 }
1186 }
1187
1188
lxt2_rd_get_alias_root(struct lxt2_rd_trace * lt,lxtint32_t facidx)1189 _LXT2_RD_INLINE lxtint32_t lxt2_rd_get_alias_root(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1190 {
1191 if((lt)&&(facidx<lt->numfacs))
1192 {
1193 while(lt->flags[facidx] & LXT2_RD_SYM_F_ALIAS)
1194 {
1195 facidx = lt->rows[facidx]; /* iterate to next alias */
1196 }
1197 return(facidx);
1198 }
1199 else
1200 {
1201 return(~((lxtint32_t)0));
1202 }
1203 }
1204
1205
1206 /*
1207 * time queries
1208 */
lxt2_rd_get_start_time(struct lxt2_rd_trace * lt)1209 _LXT2_RD_INLINE lxtint64_t lxt2_rd_get_start_time(struct lxt2_rd_trace *lt)
1210 {
1211 return(lt ? lt->start : LXT2_RD_GRAN_0VAL);
1212 }
1213
1214
lxt2_rd_get_end_time(struct lxt2_rd_trace * lt)1215 _LXT2_RD_INLINE lxtint64_t lxt2_rd_get_end_time(struct lxt2_rd_trace *lt)
1216 {
1217 return(lt ? lt->end : LXT2_RD_GRAN_0VAL);
1218 }
1219
1220
lxt2_rd_get_timescale(struct lxt2_rd_trace * lt)1221 _LXT2_RD_INLINE char lxt2_rd_get_timescale(struct lxt2_rd_trace *lt)
1222 {
1223 return(lt ? lt->timescale : 0);
1224 }
1225
1226
lxt2_rd_get_timezero(struct lxt2_rd_trace * lt)1227 _LXT2_RD_INLINE lxtsint64_t lxt2_rd_get_timezero(struct lxt2_rd_trace *lt)
1228 {
1229 return(lt ? lt->timezero : 0);
1230 }
1231
1232
1233
1234 /*
1235 * extract facname from prefix-compressed table. this
1236 * performs best when extracting facs with monotonically
1237 * increasing indices...
1238 */
lxt2_rd_get_facname(struct lxt2_rd_trace * lt,lxtint32_t facidx)1239 char *lxt2_rd_get_facname(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1240 {
1241 char *pnt;
1242 lxtint32_t clone, j;
1243
1244 if(lt)
1245 {
1246 if((facidx==(lt->faccache->old_facidx+1))||(!facidx))
1247 {
1248 if(!facidx)
1249 {
1250 lt->faccache->n = lt->zfacnames;
1251 lt->faccache->bufcurr[0] = 0;
1252 lt->faccache->bufprev[0] = 0;
1253 }
1254
1255 if(facidx!=lt->numfacs)
1256 {
1257 pnt = lt->faccache->bufcurr;
1258 lt->faccache->bufcurr = lt->faccache->bufprev;
1259 lt->faccache->bufprev = pnt;
1260
1261 clone=lxt2_rd_get_16(lt->faccache->n, 0); lt->faccache->n+=2;
1262 pnt=lt->faccache->bufcurr;
1263
1264 for(j=0;j<clone;j++)
1265 {
1266 *(pnt++) = lt->faccache->bufprev[j];
1267 }
1268
1269 while((*(pnt++)=lxt2_rd_get_byte(lt->faccache->n++,0)));
1270 lt->faccache->old_facidx = facidx;
1271 return(lt->faccache->bufcurr);
1272 }
1273 else
1274 {
1275 return(NULL); /* no more left */
1276 }
1277 }
1278 else
1279 {
1280 if(facidx<lt->numfacs)
1281 {
1282 int strt;
1283
1284 if(facidx==lt->faccache->old_facidx)
1285 {
1286 return(lt->faccache->bufcurr);
1287 }
1288
1289 if(facidx>(lt->faccache->old_facidx+1))
1290 {
1291 strt = lt->faccache->old_facidx+1;
1292 }
1293 else
1294 {
1295 strt=0;
1296 }
1297
1298 for(j=strt;j<facidx;j++)
1299 {
1300 lxt2_rd_get_facname(lt, j);
1301 }
1302
1303 return(lxt2_rd_get_facname(lt, j));
1304 }
1305 }
1306 }
1307
1308 return(NULL);
1309 }
1310
1311
1312 /*
1313 * iter mask manipulation util functions
1314 */
lxt2_rd_get_fac_process_mask(struct lxt2_rd_trace * lt,lxtint32_t facidx)1315 _LXT2_RD_INLINE int lxt2_rd_get_fac_process_mask(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1316 {
1317 if(lt)
1318 {
1319 if(facidx<lt->numfacs)
1320 {
1321 int process_idx = facidx/8;
1322 int process_bit = facidx&7;
1323
1324 return( (lt->process_mask[process_idx]&(1<<process_bit)) != 0 );
1325 }
1326 }
1327 return(0);
1328 }
1329
1330
lxt2_rd_set_fac_process_mask(struct lxt2_rd_trace * lt,lxtint32_t facidx)1331 _LXT2_RD_INLINE int lxt2_rd_set_fac_process_mask(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1332 {
1333 int rc=0;
1334
1335 if(lt)
1336 {
1337 lt->process_mask_dirty = 1;
1338 if(facidx<lt->numfacs)
1339 {
1340 int idx = facidx/8;
1341 int bitpos = facidx&7;
1342
1343 lt->process_mask[idx] |= (1<<bitpos);
1344 }
1345 rc=1;
1346 }
1347
1348 return(rc);
1349 }
1350
1351
lxt2_rd_clr_fac_process_mask(struct lxt2_rd_trace * lt,lxtint32_t facidx)1352 _LXT2_RD_INLINE int lxt2_rd_clr_fac_process_mask(struct lxt2_rd_trace *lt, lxtint32_t facidx)
1353 {
1354 int rc=0;
1355
1356 if(lt)
1357 {
1358 lt->process_mask_dirty = 1;
1359 if(facidx<lt->numfacs)
1360 {
1361 int idx = facidx/8;
1362 int bitpos = facidx&7;
1363
1364 lt->process_mask[idx] &= (~(1<<bitpos));
1365 }
1366 rc=1;
1367 }
1368
1369 return(rc);
1370 }
1371
1372
lxt2_rd_set_fac_process_mask_all(struct lxt2_rd_trace * lt)1373 _LXT2_RD_INLINE int lxt2_rd_set_fac_process_mask_all(struct lxt2_rd_trace *lt)
1374 {
1375 int rc=0;
1376
1377 if(lt)
1378 {
1379 lt->process_mask_dirty = 1;
1380 memset(lt->process_mask, 0xff, (lt->numfacs+7)/8);
1381 rc=1;
1382 }
1383
1384 return(rc);
1385 }
1386
1387
lxt2_rd_clr_fac_process_mask_all(struct lxt2_rd_trace * lt)1388 _LXT2_RD_INLINE int lxt2_rd_clr_fac_process_mask_all(struct lxt2_rd_trace *lt)
1389 {
1390 int rc=0;
1391
1392 if(lt)
1393 {
1394 lt->process_mask_dirty = 1;
1395 memset(lt->process_mask, 0x00, (lt->numfacs+7)/8);
1396 rc=1;
1397 }
1398
1399 return(rc);
1400 }
1401
1402
1403 /*
1404 * block memory set/get used to control buffering
1405 */
lxt2_rd_set_max_block_mem_usage(struct lxt2_rd_trace * lt,lxtint64_t block_mem_max)1406 _LXT2_RD_INLINE lxtint64_t lxt2_rd_set_max_block_mem_usage(struct lxt2_rd_trace *lt, lxtint64_t block_mem_max)
1407 {
1408 lxtint64_t rc = lt->block_mem_max;
1409 lt->block_mem_max = block_mem_max;
1410 return(rc);
1411 }
1412
1413
lxt2_rd_get_block_mem_usage(struct lxt2_rd_trace * lt)1414 _LXT2_RD_INLINE lxtint64_t lxt2_rd_get_block_mem_usage(struct lxt2_rd_trace *lt)
1415 {
1416 return(lt->block_mem_consumed);
1417 }
1418
1419
1420 /*
1421 * return total number of blocks
1422 */
lxt2_rd_get_num_blocks(struct lxt2_rd_trace * lt)1423 _LXT2_RD_INLINE unsigned int lxt2_rd_get_num_blocks(struct lxt2_rd_trace *lt)
1424 {
1425 return(lt->numblocks);
1426 }
1427
1428 /*
1429 * return number of active blocks
1430 */
lxt2_rd_get_num_active_blocks(struct lxt2_rd_trace * lt)1431 unsigned int lxt2_rd_get_num_active_blocks(struct lxt2_rd_trace *lt)
1432 {
1433 int blk=0;
1434
1435 if(lt)
1436 {
1437 struct lxt2_rd_block *b = lt->block_head;
1438
1439 while(b)
1440 {
1441 if((!b->short_read_ignore)&&(!b->exclude_block))
1442 {
1443 blk++;
1444 }
1445
1446 b=b->next;
1447 }
1448 }
1449
1450 return(blk);
1451 }
1452
1453 /****************************************************************************/
1454
1455 /*
1456 * block iteration...purge/reload code here isn't sophisticated as it
1457 * merely caches the FIRST set of blocks which fit in lt->block_mem_max.
1458 * n.b., returns number of blocks processed
1459 */
lxt2_rd_iter_blocks(struct lxt2_rd_trace * lt,void (* value_change_callback)(struct lxt2_rd_trace ** lt,lxtint64_t * time,lxtint32_t * facidx,char ** value),void * user_callback_data_pointer)1460 int lxt2_rd_iter_blocks(struct lxt2_rd_trace *lt,
1461 void (*value_change_callback)(struct lxt2_rd_trace **lt, lxtint64_t *time, lxtint32_t *facidx, char **value),
1462 void *user_callback_data_pointer)
1463 {
1464 struct lxt2_rd_block *b;
1465 int blk=0, blkfinal=0;
1466 int processed = 0;
1467 struct lxt2_rd_block *bcutoff=NULL, *bfinal=NULL;
1468 int striped_kill = 0;
1469 unsigned int real_uncompressed_siz = 0;
1470 unsigned char gzid[2];
1471 lxtint32_t i;
1472
1473 if(lt)
1474 {
1475 lt->value_change_callback = value_change_callback ? value_change_callback : lxt2_rd_null_callback;
1476 lt->user_callback_data_pointer = user_callback_data_pointer;
1477
1478 b = lt->block_head;
1479 blk=0;
1480
1481 for(i=0;i<lt->numfacs;i++)
1482 {
1483 if(lt->value[i]) lt->value[i][0] = 0;
1484 }
1485
1486 while(b)
1487 {
1488 if((!b->mem)&&(!b->short_read_ignore)&&(!b->exclude_block))
1489 {
1490 if(processed<5)
1491 {
1492 int gate = (processed==4) && b->next;
1493 fprintf(stderr, LXT2_RDLOAD"block [%d] processing "LXT2_RD_LLD" / "LXT2_RD_LLD"%s\n", blk, b->start, b->end, gate ? " ..." : "");
1494 if(gate) { bcutoff = b; }
1495 }
1496
1497 processed++;
1498
1499 fseeko(lt->handle, b->filepos, SEEK_SET);
1500 gzid[0]=gzid[1]=0;
1501 if(!fread(&gzid, 2, 1, lt->handle)) { gzid[0] = gzid[1] = 0; }
1502 fseeko(lt->handle, b->filepos, SEEK_SET);
1503
1504 if((striped_kill = (gzid[0]!=0x1f)||(gzid[1]!=0x8b)))
1505 {
1506 lxtint32_t clen, unclen, iter=0;
1507 char *pnt;
1508 off_t fspos = b->filepos;
1509
1510 lxtint32_t zlen = 16;
1511 char *zbuff=malloc(zlen);
1512 struct z_stream_s strm;
1513
1514 real_uncompressed_siz = b->uncompressed_siz;
1515 pnt = b->mem = malloc(b->uncompressed_siz);
1516 b->uncompressed_siz = 0;
1517
1518 lxt2_rd_regenerate_process_mask(lt);
1519
1520 while(iter!=0xFFFFFFFF)
1521 {
1522 size_t rcf;
1523
1524 clen = unclen = iter = 0;
1525 rcf = fread(&clen, 4, 1, lt->handle); clen = rcf ? lxt2_rd_get_32(&clen,0) : 0;
1526 rcf = fread(&unclen, 4, 1, lt->handle); unclen = rcf ? lxt2_rd_get_32(&unclen,0) : 0;
1527 rcf = fread(&iter, 4, 1, lt->handle); iter = rcf ? lxt2_rd_get_32(&iter,0) : 0;
1528
1529 fspos += 12;
1530 if((iter==0xFFFFFFFF)||(lt->process_mask_compressed[iter/LXT2_RD_PARTIAL_SIZE]))
1531 {
1532 if(clen > zlen)
1533 {
1534 if(zbuff) free(zbuff);
1535 zlen = clen * 2;
1536 zbuff = malloc(zlen ? zlen : 1 /* scan-build */);
1537 }
1538
1539 if(!fread(zbuff, clen, 1, lt->handle)) { clen = 0; }
1540
1541 strm.avail_in = clen-10;
1542 strm.avail_out = unclen;
1543 strm.total_in = strm.total_out = 0;
1544 strm.zalloc = NULL; strm.zfree = NULL; strm.opaque = NULL;
1545 strm.next_in = (unsigned char *)(zbuff+10);
1546 strm.next_out = (unsigned char *)(pnt);
1547
1548 if((clen != 0)&&(unclen != 0))
1549 {
1550 inflateInit2(&strm, -MAX_WBITS);
1551 while (Z_OK == inflate(&strm, Z_NO_FLUSH));
1552 inflateEnd(&strm);
1553 }
1554
1555 if((strm.total_out!=unclen)||(clen == 0)||(unclen == 0))
1556 {
1557 fprintf(stderr, LXT2_RDLOAD"short read on subblock %ld vs "LXT2_RD_LD" (exp), ignoring\n", strm.total_out, unclen);
1558 free(b->mem); b->mem=NULL;
1559 b->short_read_ignore = 1;
1560 b->uncompressed_siz = real_uncompressed_siz;
1561 break;
1562 }
1563
1564 b->uncompressed_siz+=strm.total_out;
1565 pnt += strm.total_out;
1566 fspos += clen;
1567 }
1568 else
1569 {
1570 fspos += clen;
1571 fseeko(lt->handle, fspos, SEEK_SET);
1572 }
1573 }
1574
1575
1576 if(zbuff) free(zbuff);
1577 }
1578 else
1579 {
1580 int rc;
1581
1582 b->mem = malloc(b->uncompressed_siz);
1583 lt->zhandle = gzdopen(dup(fileno(lt->handle)), "rb");
1584 rc=gzread(lt->zhandle, b->mem, b->uncompressed_siz);
1585 gzclose(lt->zhandle); lt->zhandle=NULL;
1586 if(((lxtint32_t)rc)!=b->uncompressed_siz)
1587 {
1588 fprintf(stderr, LXT2_RDLOAD"short read on block %d vs "LXT2_RD_LD" (exp), ignoring\n", rc, b->uncompressed_siz);
1589 free(b->mem); b->mem=NULL;
1590 b->short_read_ignore = 1;
1591 }
1592 else
1593 {
1594 lt->block_mem_consumed += b->uncompressed_siz;
1595 }
1596 }
1597
1598 bfinal=b;
1599 blkfinal = blk;
1600 }
1601
1602 if(b->mem)
1603 {
1604 lxt2_rd_process_block(lt, b);
1605
1606 if(striped_kill)
1607 {
1608 free(b->mem); b->mem=NULL;
1609 b->uncompressed_siz = real_uncompressed_siz;
1610 }
1611 else
1612 if(lt->numblocks > 1) /* no sense freeing up the single block case */
1613 {
1614 if(lt->block_mem_consumed > lt->block_mem_max)
1615 {
1616 lt->block_mem_consumed -= b->uncompressed_siz;
1617 free(b->mem); b->mem=NULL;
1618 }
1619 }
1620 }
1621
1622 blk++;
1623 b=b->next;
1624 }
1625 }
1626
1627 if((bcutoff)&&(bfinal!=bcutoff))
1628 {
1629 fprintf(stderr, LXT2_RDLOAD"block [%d] processed "LXT2_RD_LLD" / "LXT2_RD_LLD"\n", blkfinal, bfinal->start, bfinal->end);
1630 }
1631
1632 return(blk);
1633 }
1634
1635
1636 /*
1637 * callback access to the user callback data pointer (if required)
1638 */
lxt2_rd_get_user_callback_data_pointer(struct lxt2_rd_trace * lt)1639 _LXT2_RD_INLINE void *lxt2_rd_get_user_callback_data_pointer(struct lxt2_rd_trace *lt)
1640 {
1641 if(lt)
1642 {
1643 return(lt->user_callback_data_pointer);
1644 }
1645 else
1646 {
1647 return(NULL);
1648 }
1649 }
1650
1651
1652 /*
1653 * limit access to certain timerange in file
1654 * and return number of active blocks
1655 */
lxt2_rd_limit_time_range(struct lxt2_rd_trace * lt,lxtint64_t strt_time,lxtint64_t end_time)1656 unsigned int lxt2_rd_limit_time_range(struct lxt2_rd_trace *lt, lxtint64_t strt_time, lxtint64_t end_time)
1657 {
1658 lxtint64_t tmp_time;
1659 int blk=0;
1660
1661 if(lt)
1662 {
1663 struct lxt2_rd_block *b = lt->block_head;
1664 struct lxt2_rd_block *bprev = NULL;
1665 int state = 0;
1666
1667 if(strt_time > end_time)
1668 {
1669 tmp_time = strt_time;
1670 strt_time = end_time;
1671 end_time = tmp_time;
1672 }
1673
1674 while(b)
1675 {
1676 switch(state)
1677 {
1678 case 0: if(b->end >= strt_time)
1679 {
1680 state = 1;
1681 if((b->start > strt_time) && (bprev))
1682 {
1683 bprev->exclude_block = 0;
1684 blk++;
1685 }
1686 }
1687 break;
1688
1689 case 1: if(b->start > end_time) state = 2;
1690 break;
1691
1692 default: break;
1693 }
1694
1695 if((state==1) && (!b->short_read_ignore))
1696 {
1697 b->exclude_block = 0;
1698 blk++;
1699 }
1700 else
1701 {
1702 b->exclude_block = 1;
1703 }
1704
1705 bprev = b;
1706 b = b->next;
1707 }
1708
1709 }
1710
1711 return(blk);
1712 }
1713
1714 /*
1715 * unrestrict access to the whole file
1716 * and return number of active blocks
1717 */
lxt2_rd_unlimit_time_range(struct lxt2_rd_trace * lt)1718 unsigned int lxt2_rd_unlimit_time_range(struct lxt2_rd_trace *lt)
1719 {
1720 int blk=0;
1721
1722 if(lt)
1723 {
1724 struct lxt2_rd_block *b = lt->block_head;
1725
1726 while(b)
1727 {
1728 b->exclude_block = 0;
1729
1730 if(!b->short_read_ignore)
1731 {
1732 blk++;
1733 }
1734
1735 b=b->next;
1736 }
1737 }
1738
1739 return(blk);
1740 }
1741
1742