cord_pos.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
  3. *
  4. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  5. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  6. *
  7. * Permission is hereby granted to use or copy this program
  8. * for any purpose, provided the above notices are retained on all copies.
  9. * Permission to modify the code and to distribute modified code is granted,
  10. * provided the above notices are retained, and a notice that the code was
  11. * modified is included with the above copyright notice.
  12. */
  13. /* This should never be included directly; included only from cord.h. */
  14. #if !defined(CORD_POSITION_H) && defined(CORD_H)
  15. #define CORD_POSITION_H
  16. /* The representation of CORD_position. This is private to the */
  17. /* implementation, but the size is known to clients. Also */
  18. /* the implementation of some exported macros relies on it. */
  19. /* Don't use anything defined here and not in cord.h. */
  20. # define MAX_DEPTH 48
  21. /* The maximum depth of a balanced cord + 1. */
  22. /* We don't let cords get deeper than MAX_DEPTH. */
  23. struct CORD_pe {
  24. CORD pe_cord;
  25. size_t pe_start_pos;
  26. };
  27. /* A structure describing an entry on the path from the root */
  28. /* to current position. */
  29. typedef struct CORD_Pos {
  30. size_t cur_pos;
  31. int path_len;
  32. # define CORD_POS_INVALID (0x55555555)
  33. /* path_len == INVALID <==> position invalid */
  34. const char *cur_leaf; /* Current leaf, if it is a string. */
  35. /* If the current leaf is a function, */
  36. /* then this may point to function_buf */
  37. /* containing the next few characters. */
  38. /* Always points to a valid string */
  39. /* containing the current character */
  40. /* unless cur_end is 0. */
  41. size_t cur_start; /* Start position of cur_leaf */
  42. size_t cur_end; /* Ending position of cur_leaf */
  43. /* 0 if cur_leaf is invalid. */
  44. struct CORD_pe path[MAX_DEPTH + 1];
  45. /* path[path_len] is the leaf corresponding to cur_pos */
  46. /* path[0].pe_cord is the cord we point to. */
  47. # define FUNCTION_BUF_SZ 8
  48. char function_buf[FUNCTION_BUF_SZ]; /* Space for next few chars */
  49. /* from function node. */
  50. } CORD_pos[1];
  51. /* Extract the cord from a position: */
  52. CORD_API CORD CORD_pos_to_cord(CORD_pos p);
  53. /* Extract the current index from a position: */
  54. CORD_API size_t CORD_pos_to_index(CORD_pos p);
  55. /* Fetch the character located at the given position: */
  56. CORD_API char CORD_pos_fetch(CORD_pos p);
  57. /* Initialize the position to refer to the give cord and index. */
  58. /* Note that this is the most expensive function on positions: */
  59. CORD_API void CORD_set_pos(CORD_pos p, CORD x, size_t i);
  60. /* Advance the position to the next character. */
  61. /* P must be initialized and valid. */
  62. /* Invalidates p if past end: */
  63. CORD_API void CORD_next(CORD_pos p);
  64. /* Move the position to the preceding character. */
  65. /* P must be initialized and valid. */
  66. /* Invalidates p if past beginning: */
  67. CORD_API void CORD_prev(CORD_pos p);
  68. /* Is the position valid, i.e. inside the cord? */
  69. CORD_API int CORD_pos_valid(CORD_pos p);
  70. CORD_API char CORD__pos_fetch(CORD_pos);
  71. CORD_API void CORD__next(CORD_pos);
  72. CORD_API void CORD__prev(CORD_pos);
  73. #define CORD_pos_fetch(p) \
  74. (((p)[0].cur_end != 0)? \
  75. (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \
  76. : CORD__pos_fetch(p))
  77. #define CORD_next(p) \
  78. (((p)[0].cur_pos + 1 < (p)[0].cur_end)? \
  79. (p)[0].cur_pos++ \
  80. : (CORD__next(p), 0))
  81. #define CORD_prev(p) \
  82. (((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start)? \
  83. (p)[0].cur_pos-- \
  84. : (CORD__prev(p), 0))
  85. #define CORD_pos_to_index(p) ((p)[0].cur_pos)
  86. #define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord)
  87. #define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID)
  88. /* Some grubby stuff for performance-critical friends: */
  89. #define CORD_pos_chars_left(p) ((long)((p)[0].cur_end) - (long)((p)[0].cur_pos))
  90. /* Number of characters in cache. <= 0 ==> none */
  91. #define CORD_pos_advance(p,n) ((p)[0].cur_pos += (n) - 1, CORD_next(p))
  92. /* Advance position by n characters */
  93. /* 0 < n < CORD_pos_chars_left(p) */
  94. #define CORD_pos_cur_char_addr(p) \
  95. (p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start)
  96. /* address of current character in cache. */
  97. #endif