/* * The routines _getbit() and _setbit() are the only * routines that actually understand the layout of bmp->maskp[]. * * On little endian architectures, this could simply be an array of * bytes. But the kernel layout of bitmasks _is_ visible to userspace * via the sched_(set/get)affinity calls in Linux 2.6, and on big * endian architectures, it is painfully obvious that this is an * array of unsigned longs.
*/
/* Return the value (0 or 1) of bit n in bitmask bmp */ staticunsignedint _getbit(conststruct bitmask *bmp, unsignedint n)
{ if (n < bmp->size) return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1; else return 0;
}
/* Set bit n in bitmask bmp to value v (0 or 1) */ staticvoid _setbit(struct bitmask *bmp, unsignedint n, unsignedint v)
{ if (n < bmp->size) { if (v)
bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong); else
bmp->maskp[n/bitsperlong] &=
~(1UL << (n % bitsperlong));
}
}
/* * When parsing bitmask lists, only allow numbers, separated by one * of the allowed next characters. * * The parameter 'sret' is the return from a sscanf "%u%c". It is * -1 if the sscanf input string was empty. It is 0 if the first * character in the sscanf input string was not a decimal number. * It is 1 if the unsigned number matching the "%u" was the end of the * input string. It is 2 if one or more additional characters followed * the matched unsigned number. If it is 2, then 'nextc' is the first * character following the number. The parameter 'ok_next_chars' * is the nul-terminated list of allowed next characters. * * The mask term just scanned was ok if and only if either the numbers * matching the %u were all of the input or if the next character in * the input past the numbers was one of the allowed next characters.
*/ staticint scan_was_ok(int sret, char nextc, constchar *ok_next_chars)
{ return sret == 1 ||
(sret == 2 && strchr(ok_next_chars, nextc) != NULL);
}
staticconstchar *nexttoken(constchar *q, int sep)
{ if (q)
q = strchr(q, sep); if (q)
q++; return q;
}
/* Set a single bit i in bitmask */ struct bitmask *bitmask_setbit(struct bitmask *bmp, unsignedint i)
{
_setbit(bmp, i, 1); return bmp;
}
/* Set all bits in bitmask: bmp = ~0 */ struct bitmask *bitmask_setall(struct bitmask *bmp)
{ unsignedint i; for (i = 0; i < bmp->size; i++)
_setbit(bmp, i, 1); return bmp;
}
/* Clear all bits in bitmask: bmp = 0 */ struct bitmask *bitmask_clearall(struct bitmask *bmp)
{ unsignedint i; for (i = 0; i < bmp->size; i++)
_setbit(bmp, i, 0); return bmp;
}
/* True if all bits are clear */ int bitmask_isallclear(conststruct bitmask *bmp)
{ unsignedint i; for (i = 0; i < bmp->size; i++) if (_getbit(bmp, i)) return 0; return 1;
}
/* True if specified bit i is set */ int bitmask_isbitset(conststruct bitmask *bmp, unsignedint i)
{ return _getbit(bmp, i);
}
/* Number of lowest set bit (min) */ unsignedint bitmask_first(conststruct bitmask *bmp)
{ return bitmask_next(bmp, 0);
}
/* Number of highest set bit (max) */ unsignedint bitmask_last(conststruct bitmask *bmp)
{ unsignedint i; unsignedint m = bmp->size; for (i = 0; i < bmp->size; i++) if (_getbit(bmp, i))
m = i; return m;
}
/* Number of next set bit at or above given bit i */ unsignedint bitmask_next(conststruct bitmask *bmp, unsignedint i)
{ unsignedint n; for (n = i; n < bmp->size; n++) if (_getbit(bmp, n)) break; return n;
}
/* * Parses a comma-separated list of numbers and ranges of numbers, * with optional ':%u' strides modifying ranges, into provided bitmask. * Some examples of input lists and their equivalent simple list: * Input Equivalent to * 0-3 0,1,2,3 * 0-7:2 0,2,4,6 * 1,3,5-7 1,3,5,6,7 * 0-3:2,8-15:4 0,2,8,12
*/ int bitmask_parselist(constchar *buf, struct bitmask *bmp)
{ constchar *p, *q;
bitmask_clearall(bmp);
q = buf; while (p = q, q = nexttoken(q, ','), p) { unsignedint a; /* begin of range */ unsignedint b; /* end of range */ unsignedint s; /* stride */ constchar *c1, *c2; /* next tokens after '-' or ',' */ char nextc; /* char after sscanf %u match */ int sret; /* sscanf return (number of matches) */
sret = sscanf(p, "%u%c", &a, &nextc); if (!scan_was_ok(sret, nextc, ",-")) goto err;
b = a;
s = 1;
c1 = nexttoken(p, '-');
c2 = nexttoken(p, ','); if (c1 != NULL && (c2 == NULL || c1 < c2)) {
sret = sscanf(c1, "%u%c", &b, &nextc); if (!scan_was_ok(sret, nextc, ",:")) goto err;
c1 = nexttoken(c1, ':'); if (c1 != NULL && (c2 == NULL || c1 < c2)) {
sret = sscanf(c1, "%u%c", &s, &nextc); if (!scan_was_ok(sret, nextc, ",")) goto err;
}
} if (!(a <= b)) goto err; if (b >= bmp->size) goto err; while (a <= b) {
_setbit(bmp, a, 1);
a += s;
}
} return 0;
err:
bitmask_clearall(bmp); return -1;
}
/* * emit(buf, buflen, rbot, rtop, len) * * Helper routine for bitmask_displaylist(). Write decimal number * or range to buf+len, suppressing output past buf+buflen, with optional * comma-prefix. Return len of what would be written to buf, if it * all fit.
*/
staticinlineint emit(char *buf, int buflen, int rbot, int rtop, int len)
{ if (len > 0)
len += snprintf(buf + len, max(buflen - len, 0), ","); if (rbot == rtop)
len += snprintf(buf + len, max(buflen - len, 0), "%d", rbot); else
len += snprintf(buf + len, max(buflen - len, 0), "%d-%d",
rbot, rtop); return len;
}
/* * Write decimal list representation of bmp to buf. * * Output format is a comma-separated list of decimal numbers and * ranges. Consecutively set bits are shown as two hyphen-separated * decimal numbers, the smallest and largest bit numbers set in * the range. Output format is compatible with the format * accepted as input by bitmap_parselist(). * * The return value is the number of characters which would be * generated for the given input, excluding the trailing '\0', as * per ISO C99.
*/
int bitmask_displaylist(char *buf, int buflen, conststruct bitmask *bmp)
{ int len = 0; /* current bit is 'cur', most recently seen range is [rbot, rtop] */ unsignedint cur, rbot, rtop;
if (buflen > 0)
*buf = 0;
rbot = cur = bitmask_first(bmp); while (cur < bmp->size) {
rtop = cur;
cur = bitmask_next(bmp, cur+1); if (cur >= bmp->size || cur > rtop + 1) {
len = emit(buf, buflen, rbot, rtop, len);
rbot = cur;
}
} return len;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.26 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.