static G_GNUC_HOT int iprange_net6_cmp(const void *p, const void *q) { const struct iprange_net6 *a = p, *b = q; return bitcmp(a->ip, b->ip, MIN(a->bits, b->bits)); }
/* --- entry point --- */ int rasterizechar ( FILE *fp, raster *image ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ char *readaline(), *line; /* read next scan line for char from fp */ unsigned char bitvec[1024][128]; /* scan lines parsed up to 1024x1024 bits */ int bitcmp(); /* compare bit strings */ int height = 0, /* #scan lines in fp comprising char */ width = 0; /* #chars on longest scan line */ int iscan, /* bitvec[] index */ ibit; /* bit along scan (i.e., 0...width-1) */ int isokay = 0; /* returned status, init for failure */ /* --- bitmap and .gf-formatted image info (we'll choose smallest) --- */ int iformat = gformat; /*0=best, 1=bitmap, 2=8-bit.gf, 3=4-bit.gf*/ unsigned char gfpixcount[2][65536]; /* .gf black/white flips (max=64K) */ int npixcounts[2] = {9999999,9999999}; /* #counts for 8-bit,4-bit .gf */ int nbytes1=9999999,nbytes2=9999999,nbytes3=9999999;/*#bytes for format*/ /* -------------------------------------------------------------------------- read lines till ".<--" terminator, and construct one vector[] int per line -------------------------------------------------------------------------- */ memset(bitvec,0,128*1024); /* zero-fill bitvec[] */ while ( (line=readaline(fp)) != NULL ) /* read lines until eof */ { /* --- allocations and declarations --- */ int icol, ncols=strlen(line); /* line[] column index, #cols in line[] */ /* --- check for end-of-char (when we encounter corner line) --- */ if ( memcmp(line,CORNER_STUB,strlen(CORNER_STUB)) == 0 ) /* corner line */ break; /* so done with loop */ /* --- parse line (encode asterisks comprising character image) --- */ memset(bitvec[height],0,128); /* first zero out all bits */ for ( icol=0; icol<ncols; icol++ ) /* now check line[] for asterisks */ if ( line[icol] == '*' ) /* we want to set this bit */ { setlongbit(bitvec[height],icol); /* set bit */ if ( icol >= width ) width=icol+1; } /* and check for new width */ height++; /* bump character height */ } /* --- end-of-while(line!=NULL) --- */ if ( height<1 || width<1 ) /* some problem parsing character */ goto end_of_job; /* so quit */ /* -------------------------------------------------------------------------- init image values -------------------------------------------------------------------------- */ if ( image->pixmap != NULL ) /* hmm, somebody already allocated memory */ free((void *)image->pixmap); /* so just free it */ image->width = width; /* set image width within raster struct */ image->height = height; /* and height */ image->format = gformat; /* set format (will be reset below) */ image->pixsz = 1; /* #bits per pixel (or #counts in .gf fmt) */ if ( gformat==0 || gformat==1 ) /* bitmap representation allowed */ { nbytes1 = pixmapsz(image); /* #bytes needed for bitmap */ iformat = 1; } /* default to bitmap format */ /* -------------------------------------------------------------------------- perform .gf-like compression on image in bitvec -------------------------------------------------------------------------- */ if ( gformat == 0 /* choose optimal/smallest respresentation */ || gformat==2 || gformat==3 ) /* .gf-like compressed representation */ { /* --- try both 8-bits/count and 4-bits/count for best compression --- */ int maxbitcount[2] = {254,14}; /* don't count too much in one byte */ int repeatcmds[2] = {255,15}; /* opcode for repeat/duplicate count */ int minbytes = 0; /* #bytes needed for smallest format */ for ( iformat=2; iformat<=3; iformat++ ) { /* 2=8-bit packing, 3=4-bit */ int gfbitcount = 0, /* count of consecutive gfbitval's */ gfbitval = 0, /* begin with count of leading 0's */ pixcount = 0; /* #packed bytes (#black/white flips) */ unsigned char *gfcount = gfpixcount[iformat-2]; /*counts for this format*/ if ( gformat!=0 && gformat!=iformat ) /* this format not allowed */ continue; /* so just skip it */ for ( iscan=0; iscan<height; iscan++ ) /* for each integer in bitvec[] */ { int bitval = 0; /* current actual pixel value */ int nrepeats=0, nextreps=0; /* #duplicate lines below current,next line*/ /* --- check for repeated/duplicate scan lines --- */ if ( isrepeat /* we're storing scan line repeat counts */ && iscan < height-1 ) { /* current scan line isn't the last line */ /* --- count repeats --- */ int jscan = iscan; /* compare current scan with lines below it*/ while ( ++jscan < height ) { /* until last scan line */ if (nrepeats == jscan-iscan-1) /*no intervening non-identical lines*/ if ( bitcmp(bitvec[iscan],bitvec[jscan],width) == 0 ) /* identical */ nrepeats++; /* so bump repeat count */ if ( jscan > iscan+1 ) /* we're below next line */ if (nextreps == jscan-iscan-2) /*no intervening non-identical lines*/ if ( bitcmp(bitvec[iscan+1],bitvec[jscan],width) == 0 )/*identical*/ nextreps++; } /* so bump next lline repeat count */ /* --- set repeat command and count --- */ if ( nrepeats > 0 ) { /* found repeated lines below current */ int maxrepeats = maxbitcount[iformat-2]; /*max count/repeats per byte*/ if ( nrepeats > maxrepeats ) nrepeats=maxrepeats; /* don't exceed max */ {setbyfmt(iformat,gfcount,pixcount,repeatcmds[iformat-2]);} /*set cmd*/ {setbyfmt(iformat,gfcount,pixcount+1,nrepeats);} /* set #repeats */ pixcount += 2; } /* don't bump pixcount within macros */ } /* --- end-of-if(isrepeat) --- */ /* --- set bit counts for current scan line --- */ for ( ibit=0; ibit<width; ibit++ ) /* for all bits in this scanline */ { bitval = getlongbit(bitvec[iscan],ibit); /* check actual pixel value */ if ( bitval != gfbitval ) { /* black-to-white edge (or vice versa) */ {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/ pixcount++; /* don't bump pixcount within macro */ gfbitcount = 0; /* reset consecutive bit count */ gfbitval = 1-gfbitval; } /* flip bit to be counted */ else /* check count if continuing with same val */ if ( gfbitcount >= maxbitcount[iformat-2] ) { /* max count per byte */ {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/ clearbyfmt(iformat,gfcount,pixcount+1); /*followed by dummy 0 count*/ pixcount += 2; /* don't bump pixcount within macros */ gfbitcount = 0; } /* reset consecutive bit count */ if ( bitval == gfbitval ) /* same bit val as preceding, or first new */ gfbitcount++; /* so just count another pixel */ } /* --- end-of-for(ibit) --- */ /* --- adjust for repeated scan lines --- */ iscan += nrepeats; /* skip repeated/duplicate scan lines */ if ( nrepeats>0 || nextreps>0 ) /* emit count to align on full scan */ if ( iscan < height-1 ) /* have another scan line below this one */ if ( gfbitcount > 0 ) { /* should always have some final count */ {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/ pixcount++; /* don't bump pixcount within macro */ gfbitcount = 0; /* reset consecutive bit count */ if ( bitval == getlongbit(bitvec[iscan+1],0) ) { /* same bit value */ clearbyfmt(iformat,gfcount,pixcount); /*so we need a dummy 0 count*/ pixcount++; } /* don't bump pixcount within macros */ else /* bitval flips at start of next line */ gfbitval = 1-gfbitval; /* so flip bit to be counted */ } /* --- end-of-if(nrepeats...gfbitcount>0) --- */ } /* --- end-of-for(iscan) --- */ /* --- store final count --- */ if ( gfbitcount > 0 ) { /* have a final count */ {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/ pixcount++; } /* don't bump pixcount within macro */ else /* ended exactly after maxbitcount? */ if ( getbyfmt(iformat,gfcount,pixcount-1) == 0 )/*have dummy 0 trailer?*/ pixcount--; /* remove unneeded dummy trailer */ /* --- save count to choose smallest --- */ npixcounts[iformat-2] = pixcount; /* save count */ } /* --- end-of-for(iformat) --- */ /* --- check for optimal/smallest format --- */ nbytes2=npixcounts[0]; nbytes3=(1+npixcounts[1])/2; /* #bytes for count */ iformat = (nbytes2<nbytes3? 2:3); /* choose smallest format */ minbytes = (iformat==2?nbytes2:nbytes3); /* #bytes for smallest format */ if ( gformat == 0 ) /* bitmap representation also permitted */ if ( nbytes1 <= minbytes ) /* and it's the optimal/smallest format */ iformat = 1; /* so flip format */ /* --- move results to returned image --- */ if ( iformat != 1 ) { /* using a .gf format */ if ( (image->pixmap = (unsigned char *)malloc(minbytes)) /* alloc pixmap */ == NULL ) goto end_of_job; /* quit if failed to allocate pixmap */ memcpy(image->pixmap,gfpixcount[iformat-2],minbytes); /*copy local counts*/ image->format = iformat; /* signal byte counts or nibble counts */ image->pixsz = npixcounts[iformat-2]; /*#counts in pixmap for gformat=2,3*/ } /* --- end-of-if(iformat!=1) --- */ } /* --- end-of-if(gformat==2) --- */ /* -------------------------------------------------------------------------- copy each integer in bitvec[] to raster pixmap, bit by bit -------------------------------------------------------------------------- */ if ( iformat == 1 ) /* bit-by-bit representation of image */ { int ipixel = 0; /* pixmap index */ /* --- first allocate image raster pixmap for character --- */ if ( (image->pixmap = (unsigned char *)malloc(pixmapsz(image))) == NULL ) goto end_of_job; /* quit if failed to allocate pixmap */ image->format = iformat; /* reset format */ /* --- now store bit image in allocated raster --- */ for ( iscan=0; iscan<height; iscan++ ) /* for each integer in bitvec[] */ for ( ibit=0; ibit<width; ibit++ ) /* for all bits in this scanline */ { if ( getlongbit(bitvec[iscan],ibit) != 0 ) /* check current scan pixel */ { setlongbit(image->pixmap,ipixel); } else /*turn off corresponding raster bit*/ { unsetlongbit(image->pixmap,ipixel); } ipixel++; /* bump image raster pixel */ } /* --- end-of-for(iscan,ibit) --- */ } /* --- end-of-if(gformat==1) --- */ /* -------------------------------------------------------------------------- done -------------------------------------------------------------------------- */ isokay = 1; /* reset flag for success */ end_of_job: return ( isokay ); /* back with 1=success, 0=failure */ } /* --- end-of-function rasterizechar() --- */
/** * See if the n first bits of two KUID prefixes match. */ bool kuid_match_nth(const kuid_t *k1, const kuid_t *k2, int bits) { return 0 == bitcmp(k1->v, k2->v, bits); }