Rizin
unix-like reverse engineering framework and cli tools
get_changed_ranges.h File Reference
#include "./tree_cursor.h"
#include "./subtree.h"

Go to the source code of this file.

Functions

typedef Array (TSRange) TSRangeArray
 
void ts_range_array_get_changed_ranges (const TSRange *old_ranges, unsigned old_range_count, const TSRange *new_ranges, unsigned new_range_count, TSRangeArray *differences)
 
bool ts_range_array_intersects (const TSRangeArray *self, unsigned start_index, uint32_t start_byte, uint32_t end_byte)
 
unsigned ts_subtree_get_changed_ranges (const Subtree *old_tree, const Subtree *new_tree, TreeCursor *cursor1, TreeCursor *cursor2, const TSLanguage *language, const TSRangeArray *included_range_differences, TSRange **ranges)
 

Function Documentation

◆ Array()

typedef Array ( TSRange  )

◆ ts_range_array_get_changed_ranges()

void ts_range_array_get_changed_ranges ( const TSRange old_ranges,
unsigned  old_range_count,
const TSRange new_ranges,
unsigned  new_range_count,
TSRangeArray *  differences 
)

Definition at line 46 of file get_changed_ranges.c.

50  {
51  unsigned new_index = 0;
52  unsigned old_index = 0;
53  Length current_position = length_zero();
54  bool in_old_range = false;
55  bool in_new_range = false;
56 
57  while (old_index < old_range_count || new_index < new_range_count) {
58  const TSRange *old_range = &old_ranges[old_index];
59  const TSRange *new_range = &new_ranges[new_index];
60 
61  Length next_old_position;
62  if (in_old_range) {
63  next_old_position = (Length) {old_range->end_byte, old_range->end_point};
64  } else if (old_index < old_range_count) {
65  next_old_position = (Length) {old_range->start_byte, old_range->start_point};
66  } else {
67  next_old_position = LENGTH_MAX;
68  }
69 
70  Length next_new_position;
71  if (in_new_range) {
72  next_new_position = (Length) {new_range->end_byte, new_range->end_point};
73  } else if (new_index < new_range_count) {
74  next_new_position = (Length) {new_range->start_byte, new_range->start_point};
75  } else {
76  next_new_position = LENGTH_MAX;
77  }
78 
79  if (next_old_position.bytes < next_new_position.bytes) {
80  if (in_old_range != in_new_range) {
81  ts_range_array_add(differences, current_position, next_old_position);
82  }
83  if (in_old_range) old_index++;
84  current_position = next_old_position;
85  in_old_range = !in_old_range;
86  } else if (next_new_position.bytes < next_old_position.bytes) {
87  if (in_old_range != in_new_range) {
88  ts_range_array_add(differences, current_position, next_new_position);
89  }
90  if (in_new_range) new_index++;
91  current_position = next_new_position;
92  in_new_range = !in_new_range;
93  } else {
94  if (in_old_range != in_new_range) {
95  ts_range_array_add(differences, current_position, next_new_position);
96  }
97  if (in_old_range) old_index++;
98  if (in_new_range) new_index++;
99  in_old_range = !in_old_range;
100  in_new_range = !in_new_range;
101  current_position = next_new_position;
102  }
103  }
104 }
static void ts_range_array_add(TSRangeArray *self, Length start, Length end)
static Length length_zero(void)
Definition: length.h:39
static const Length LENGTH_MAX
Definition: length.h:15
Definition: length.h:9
uint32_t bytes
Definition: length.h:10
Definition: api.h:60
TSPoint end_point
Definition: api.h:62
uint32_t start_byte
Definition: api.h:63
TSPoint start_point
Definition: api.h:61
uint32_t end_byte
Definition: api.h:64

References Length::bytes, TSRange::end_byte, TSRange::end_point, LENGTH_MAX, length_zero(), TSRange::start_byte, TSRange::start_point, and ts_range_array_add().

Referenced by ts_parser_parse(), and ts_tree_get_changed_ranges().

◆ ts_range_array_intersects()

bool ts_range_array_intersects ( const TSRangeArray *  self,
unsigned  start_index,
uint32_t  start_byte,
uint32_t  end_byte 
)

Definition at line 30 of file get_changed_ranges.c.

35  {
36  for (unsigned i = start_index; i < self->size; i++) {
37  TSRange *range = &self->contents[i];
38  if (range->end_byte > start_byte) {
39  if (range->start_byte >= end_byte) break;
40  return true;
41  }
42  }
43  return false;
44 }
lzma_index ** i
Definition: index.h:629

References i, and capstone::range.

Referenced by ts_parser__has_included_range_difference(), and ts_subtree_get_changed_ranges().

◆ ts_subtree_get_changed_ranges()

unsigned ts_subtree_get_changed_ranges ( const Subtree old_tree,
const Subtree new_tree,
TreeCursor cursor1,
TreeCursor cursor2,
const TSLanguage language,
const TSRangeArray *  included_range_differences,
TSRange **  ranges 
)

Definition at line 357 of file get_changed_ranges.c.

363  {
364  TSRangeArray results = array_new();
365 
366  Iterator old_iter = iterator_new(cursor1, old_tree, language);
367  Iterator new_iter = iterator_new(cursor2, new_tree, language);
368 
369  unsigned included_range_difference_index = 0;
370 
371  Length position = iterator_start_position(&old_iter);
372  Length next_position = iterator_start_position(&new_iter);
373  if (position.bytes < next_position.bytes) {
374  ts_range_array_add(&results, position, next_position);
375  position = next_position;
376  } else if (position.bytes > next_position.bytes) {
377  ts_range_array_add(&results, next_position, position);
378  next_position = position;
379  }
380 
381  do {
382  #ifdef DEBUG_GET_CHANGED_RANGES
383  printf("At [%-2u, %-2u] Compare ", position.extent.row + 1, position.extent.column);
384  iterator_print_state(&old_iter);
385  printf("\tvs\t");
386  iterator_print_state(&new_iter);
387  puts("");
388  #endif
389 
390  // Compare the old and new subtrees.
391  IteratorComparison comparison = iterator_compare(&old_iter, &new_iter);
392 
393  // Even if the two subtrees appear to be identical, they could differ
394  // internally if they contain a range of text that was previously
395  // excluded from the parse, and is now included, or vice-versa.
396  if (comparison == IteratorMatches && ts_range_array_intersects(
397  included_range_differences,
398  included_range_difference_index,
399  position.bytes,
400  iterator_end_position(&old_iter).bytes
401  )) {
402  comparison = IteratorMayDiffer;
403  }
404 
405  bool is_changed = false;
406  switch (comparison) {
407  // If the subtrees are definitely identical, move to the end
408  // of both subtrees.
409  case IteratorMatches:
410  next_position = iterator_end_position(&old_iter);
411  break;
412 
413  // If the subtrees might differ internally, descend into both
414  // subtrees, finding the first child that spans the current position.
415  case IteratorMayDiffer:
416  if (iterator_descend(&old_iter, position.bytes)) {
417  if (!iterator_descend(&new_iter, position.bytes)) {
418  is_changed = true;
419  next_position = iterator_end_position(&old_iter);
420  }
421  } else if (iterator_descend(&new_iter, position.bytes)) {
422  is_changed = true;
423  next_position = iterator_end_position(&new_iter);
424  } else {
425  next_position = length_min(
426  iterator_end_position(&old_iter),
427  iterator_end_position(&new_iter)
428  );
429  }
430  break;
431 
432  // If the subtrees are different, record a change and then move
433  // to the end of both subtrees.
434  case IteratorDiffers:
435  is_changed = true;
436  next_position = length_min(
437  iterator_end_position(&old_iter),
438  iterator_end_position(&new_iter)
439  );
440  break;
441  }
442 
443  // Ensure that both iterators are caught up to the current position.
444  while (
445  !iterator_done(&old_iter) &&
446  iterator_end_position(&old_iter).bytes <= next_position.bytes
447  ) iterator_advance(&old_iter);
448  while (
449  !iterator_done(&new_iter) &&
450  iterator_end_position(&new_iter).bytes <= next_position.bytes
451  ) iterator_advance(&new_iter);
452 
453  // Ensure that both iterators are at the same depth in the tree.
454  while (old_iter.visible_depth > new_iter.visible_depth) {
455  iterator_ascend(&old_iter);
456  }
457  while (new_iter.visible_depth > old_iter.visible_depth) {
458  iterator_ascend(&new_iter);
459  }
460 
461  if (is_changed) {
462  #ifdef DEBUG_GET_CHANGED_RANGES
463  printf(
464  " change: [[%u, %u] - [%u, %u]]\n",
465  position.extent.row + 1, position.extent.column,
466  next_position.extent.row + 1, next_position.extent.column
467  );
468  #endif
469 
470  ts_range_array_add(&results, position, next_position);
471  }
472 
473  position = next_position;
474 
475  // Keep track of the current position in the included range differences
476  // array in order to avoid scanning the entire array on each iteration.
477  while (included_range_difference_index < included_range_differences->size) {
478  const TSRange *range = &included_range_differences->contents[
479  included_range_difference_index
480  ];
481  if (range->end_byte <= position.bytes) {
482  included_range_difference_index++;
483  } else {
484  break;
485  }
486  }
487  } while (!iterator_done(&old_iter) && !iterator_done(&new_iter));
488 
489  Length old_size = ts_subtree_total_size(*old_tree);
490  Length new_size = ts_subtree_total_size(*new_tree);
491  if (old_size.bytes < new_size.bytes) {
492  ts_range_array_add(&results, old_size, new_size);
493  } else if (new_size.bytes < old_size.bytes) {
494  ts_range_array_add(&results, new_size, old_size);
495  }
496 
497  *cursor1 = old_iter.cursor;
498  *cursor2 = new_iter.cursor;
499  *ranges = results.contents;
500  return results.size;
501 }
#define array_new()
Definition: array.h:25
static ut8 bytes[32]
Definition: asm_arc.c:23
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static void iterator_ascend(Iterator *self)
static IteratorComparison iterator_compare(const Iterator *old_iter, const Iterator *new_iter)
static bool iterator_done(Iterator *self)
static void iterator_advance(Iterator *self)
static bool iterator_descend(Iterator *self, uint32_t goal_position)
static Length iterator_end_position(Iterator *self)
static Iterator iterator_new(TreeCursor *cursor, const Subtree *tree, const TSLanguage *language)
static Length iterator_start_position(Iterator *self)
bool ts_range_array_intersects(const TSRangeArray *self, unsigned start_index, uint32_t start_byte, uint32_t end_byte)
IteratorComparison
@ IteratorDiffers
@ IteratorMatches
@ IteratorMayDiffer
voidpf void uLong size
Definition: ioapi.h:138
static Length length_min(Length len1, Length len2)
Definition: length.h:21
TreeCursor cursor
unsigned visible_depth
TSPoint extent
Definition: length.h:11
uint32_t row
Definition: api.h:56
uint32_t column
Definition: api.h:57
static Length ts_subtree_total_size(Subtree self)
Definition: subtree.h:274

References array_new, bytes, Length::bytes, TSPoint::column, Iterator::cursor, Length::extent, iterator_advance(), iterator_ascend(), iterator_compare(), iterator_descend(), iterator_done(), iterator_end_position(), iterator_new(), iterator_start_position(), IteratorDiffers, IteratorMatches, IteratorMayDiffer, length_min(), printf(), capstone::range, TSPoint::row, ts_range_array_add(), ts_range_array_intersects(), ts_subtree_total_size(), and Iterator::visible_depth.

Referenced by ts_tree_get_changed_ranges().