lpcset.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "lptypes.h"
  2. #include "lpcset.h"
  3. /*
  4. ** Add to 'c' the index of the (only) bit set in byte 'b'
  5. */
  6. static int onlybit (int c, int b) {
  7. if ((b & 0xF0) != 0) { c += 4; b >>= 4; }
  8. if ((b & 0x0C) != 0) { c += 2; b >>= 2; }
  9. if ((b & 0x02) != 0) { c += 1; }
  10. return c;
  11. }
  12. /*
  13. ** Check whether a charset is empty (returns IFail), singleton (IChar),
  14. ** full (IAny), or none of those (ISet). When singleton, 'info.offset'
  15. ** returns which character it is. When generic set, 'info' returns
  16. ** information about its range.
  17. */
  18. Opcode charsettype (const byte *cs, charsetinfo *info) {
  19. int low0, low1, high0, high1;
  20. for (low1 = 0; low1 < CHARSETSIZE && cs[low1] == 0; low1++)
  21. /* find lowest byte with a 1-bit */;
  22. if (low1 == CHARSETSIZE)
  23. return IFail; /* no characters in set */
  24. for (high1 = CHARSETSIZE - 1; cs[high1] == 0; high1--)
  25. /* find highest byte with a 1-bit; low1 is a sentinel */;
  26. if (low1 == high1) { /* only one byte with 1-bits? */
  27. int b = cs[low1];
  28. if ((b & (b - 1)) == 0) { /* does byte has only one 1-bit? */
  29. info->offset = onlybit(low1 * BITSPERCHAR, b); /* get that bit */
  30. return IChar; /* single character */
  31. }
  32. }
  33. for (low0 = 0; low0 < CHARSETSIZE && cs[low0] == 0xFF; low0++)
  34. /* find lowest byte with a 0-bit */;
  35. if (low0 == CHARSETSIZE)
  36. return IAny; /* set has all bits set */
  37. for (high0 = CHARSETSIZE - 1; cs[high0] == 0xFF; high0--)
  38. /* find highest byte with a 0-bit; low0 is a sentinel */;
  39. if (high1 - low1 <= high0 - low0) { /* range of 1s smaller than of 0s? */
  40. info->offset = low1;
  41. info->size = high1 - low1 + 1;
  42. info->deflt = 0; /* all discharged bits were 0 */
  43. }
  44. else {
  45. info->offset = low0;
  46. info->size = high0 - low0 + 1;
  47. info->deflt = 0xFF; /* all discharged bits were 1 */
  48. }
  49. info->cs = cs + info->offset;
  50. return ISet;
  51. }
  52. /*
  53. ** Get a byte from a compact charset. If index is inside the charset
  54. ** range, get the byte from the supporting charset (correcting it
  55. ** by the offset). Otherwise, return the default for the set.
  56. */
  57. byte getbytefromcharset (const charsetinfo *info, int index) {
  58. if (index < info->size)
  59. return info->cs[index];
  60. else return info->deflt;
  61. }
  62. /*
  63. ** If 'tree' is a 'char' pattern (TSet, TChar, TAny, TFalse), convert it
  64. ** into a charset and return 1; else return 0.
  65. */
  66. int tocharset (TTree *tree, Charset *cs) {
  67. switch (tree->tag) {
  68. case TChar: { /* only one char */
  69. assert(0 <= tree->u.n && tree->u.n <= UCHAR_MAX);
  70. clearset(cs->cs); /* erase all chars */
  71. setchar(cs->cs, tree->u.n); /* add that one */
  72. return 1;
  73. }
  74. case TAny: {
  75. fillset(cs->cs, 0xFF); /* add all characters to the set */
  76. return 1;
  77. }
  78. case TFalse: {
  79. clearset(cs->cs); /* empty set */
  80. return 1;
  81. }
  82. case TSet: { /* fill set */
  83. int i;
  84. fillset(cs->cs, tree->u.set.deflt);
  85. for (i = 0; i < tree->u.set.size; i++)
  86. cs->cs[tree->u.set.offset + i] = treebuffer(tree)[i];
  87. return 1;
  88. }
  89. default: return 0;
  90. }
  91. }
  92. void tree2cset (TTree *tree, charsetinfo *info) {
  93. assert(tree->tag == TSet);
  94. info->offset = tree->u.set.offset;
  95. info->size = tree->u.set.size;
  96. info->deflt = tree->u.set.deflt;
  97. info->cs = treebuffer(tree);
  98. }