node.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #include "node.h"
  2. #include "leaf_skipper.h"
  3. #include "comptrie_impl.h"
  4. #include <util/system/yassert.h>
  5. #include <util/generic/yexception.h>
  6. namespace NCompactTrie {
  7. TNode::TNode()
  8. : Offset(0)
  9. , LeafLength(0)
  10. , CoreLength(0)
  11. , Label(0)
  12. {
  13. for (auto& offset : Offsets) {
  14. offset = 0;
  15. }
  16. }
  17. // We believe that epsilon links are found only on the forward-position and that afer jumping an epsilon link you come to an ordinary node.
  18. TNode::TNode(const char* data, size_t offset, const ILeafSkipper& skipFunction)
  19. : Offset(offset)
  20. , LeafLength(0)
  21. , CoreLength(0)
  22. , Label(0)
  23. {
  24. for (auto& anOffset : Offsets) {
  25. anOffset = 0;
  26. }
  27. if (!data)
  28. return; // empty constructor
  29. const char* datapos = data + offset;
  30. char flags = *(datapos++);
  31. Y_ASSERT(!IsEpsilonLink(flags));
  32. Label = *(datapos++);
  33. size_t leftsize = LeftOffsetLen(flags);
  34. size_t& leftOffset = Offsets[D_LEFT];
  35. leftOffset = UnpackOffset(datapos, leftsize);
  36. if (leftOffset) {
  37. leftOffset += Offset;
  38. }
  39. datapos += leftsize;
  40. size_t rightsize = RightOffsetLen(flags);
  41. size_t& rightOffset = Offsets[D_RIGHT];
  42. rightOffset = UnpackOffset(datapos, rightsize);
  43. if (rightOffset) {
  44. rightOffset += Offset;
  45. }
  46. datapos += rightsize;
  47. if (flags & MT_FINAL) {
  48. Offsets[D_FINAL] = datapos - data;
  49. LeafLength = skipFunction.SkipLeaf(datapos);
  50. }
  51. CoreLength = 2 + leftsize + rightsize + LeafLength;
  52. if (flags & MT_NEXT) {
  53. size_t& forwardOffset = Offsets[D_NEXT];
  54. forwardOffset = Offset + CoreLength;
  55. // There might be an epsilon link at the forward position.
  56. // If so, set the ForwardOffset to the value that points to the link's end.
  57. const char* forwardPos = data + forwardOffset;
  58. const char forwardFlags = *forwardPos;
  59. if (IsEpsilonLink(forwardFlags)) {
  60. // Jump through the epsilon link.
  61. size_t epsilonOffset = UnpackOffset(forwardPos + 1, forwardFlags & MT_SIZEMASK);
  62. if (!epsilonOffset) {
  63. ythrow yexception() << "Corrupted epsilon link";
  64. }
  65. forwardOffset += epsilonOffset;
  66. }
  67. }
  68. }
  69. }