On Tue, Nov 06, 2007 at 02:33:53AM -0800, akpm@linux-foundation.org wrote:
[mmotm.git] / fs / reiser4 / coord.c
blobe37e2f9136ad2d6868a92b55726fa437e0538948
1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by
2 reiser4/README */
4 #include "forward.h"
5 #include "debug.h"
6 #include "dformat.h"
7 #include "tree.h"
8 #include "plugin/item/item.h"
9 #include "znode.h"
10 #include "coord.h"
12 /* Internal constructor. */
13 static inline void
14 coord_init_values(coord_t *coord, const znode * node, pos_in_node_t item_pos,
15 pos_in_node_t unit_pos, between_enum between)
17 coord->node = (znode *) node;
18 coord_set_item_pos(coord, item_pos);
19 coord->unit_pos = unit_pos;
20 coord->between = between;
21 ON_DEBUG(coord->plug_v = 0);
22 ON_DEBUG(coord->body_v = 0);
24 /*ON_TRACE (TRACE_COORDS, "init coord %p node %p: %u %u %s\n", coord,
25 node, item_pos, unit_pos, coord_tween_tostring (between)); */
28 /* after shifting of node content, coord previously set properly may become
29 invalid, try to "normalize" it. */
30 void coord_normalize(coord_t *coord)
32 znode *node;
34 node = coord->node;
35 assert("vs-683", node);
37 coord_clear_iplug(coord);
39 if (node_is_empty(node))
40 coord_init_first_unit(coord, node);
41 else if ((coord->between == AFTER_ITEM)
42 || (coord->between == AFTER_UNIT))
43 return;
44 else if (coord->item_pos == coord_num_items(coord)
45 && coord->between == BEFORE_ITEM) {
46 coord_dec_item_pos(coord);
47 coord->between = AFTER_ITEM;
48 } else if (coord->unit_pos == coord_num_units(coord)
49 && coord->between == BEFORE_UNIT) {
50 coord->unit_pos--;
51 coord->between = AFTER_UNIT;
52 } else if (coord->item_pos == coord_num_items(coord)
53 && coord->unit_pos == 0 && coord->between == BEFORE_UNIT) {
54 coord_dec_item_pos(coord);
55 coord->unit_pos = 0;
56 coord->between = AFTER_ITEM;
60 /* Copy a coordinate. */
61 void coord_dup(coord_t *coord, const coord_t *old_coord)
63 assert("jmacd-9800", coord_check(old_coord));
64 coord_dup_nocheck(coord, old_coord);
67 /* Copy a coordinate without check. Useful when old_coord->node is not
68 loaded. As in cbk_tree_lookup -> connect_znode -> connect_one_side */
69 void coord_dup_nocheck(coord_t *coord, const coord_t *old_coord)
71 coord->node = old_coord->node;
72 coord_set_item_pos(coord, old_coord->item_pos);
73 coord->unit_pos = old_coord->unit_pos;
74 coord->between = old_coord->between;
75 coord->iplugid = old_coord->iplugid;
76 ON_DEBUG(coord->plug_v = old_coord->plug_v);
77 ON_DEBUG(coord->body_v = old_coord->body_v);
80 /* Initialize an invalid coordinate. */
81 void coord_init_invalid(coord_t *coord, const znode * node)
83 coord_init_values(coord, node, 0, 0, INVALID_COORD);
86 void coord_init_first_unit_nocheck(coord_t *coord, const znode * node)
88 coord_init_values(coord, node, 0, 0, AT_UNIT);
91 /* Initialize a coordinate to point at the first unit of the first item. If the
92 node is empty, it is positioned at the EMPTY_NODE. */
93 void coord_init_first_unit(coord_t *coord, const znode * node)
95 int is_empty = node_is_empty(node);
97 coord_init_values(coord, node, 0, 0, (is_empty ? EMPTY_NODE : AT_UNIT));
99 assert("jmacd-9801", coord_check(coord));
102 /* Initialize a coordinate to point at the last unit of the last item. If the
103 node is empty, it is positioned at the EMPTY_NODE. */
104 void coord_init_last_unit(coord_t *coord, const znode * node)
106 int is_empty = node_is_empty(node);
108 coord_init_values(coord, node,
109 (is_empty ? 0 : node_num_items(node) - 1), 0,
110 (is_empty ? EMPTY_NODE : AT_UNIT));
111 if (!is_empty)
112 coord->unit_pos = coord_last_unit_pos(coord);
113 assert("jmacd-9802", coord_check(coord));
116 /* Initialize a coordinate to before the first item. If the node is empty, it is
117 positioned at the EMPTY_NODE. */
118 void coord_init_before_first_item(coord_t *coord, const znode * node)
120 int is_empty = node_is_empty(node);
122 coord_init_values(coord, node, 0, 0,
123 (is_empty ? EMPTY_NODE : BEFORE_UNIT));
125 assert("jmacd-9803", coord_check(coord));
128 /* Initialize a coordinate to after the last item. If the node is empty, it is
129 positioned at the EMPTY_NODE. */
130 void coord_init_after_last_item(coord_t *coord, const znode * node)
132 int is_empty = node_is_empty(node);
134 coord_init_values(coord, node,
135 (is_empty ? 0 : node_num_items(node) - 1), 0,
136 (is_empty ? EMPTY_NODE : AFTER_ITEM));
138 assert("jmacd-9804", coord_check(coord));
141 /* Initialize a coordinate to after last unit in the item. Coord must be set
142 already to existing item */
143 void coord_init_after_item_end(coord_t *coord)
145 coord->between = AFTER_UNIT;
146 coord->unit_pos = coord_last_unit_pos(coord);
149 /* Initialize a coordinate to before the item. Coord must be set already to
150 existing item */
151 void coord_init_before_item(coord_t *coord)
153 coord->unit_pos = 0;
154 coord->between = BEFORE_ITEM;
157 /* Initialize a coordinate to after the item. Coord must be set already to
158 existing item */
159 void coord_init_after_item(coord_t *coord)
161 coord->unit_pos = 0;
162 coord->between = AFTER_ITEM;
165 /* Initialize a coordinate by 0s. Used in places where init_coord was used and
166 it was not clear how actually */
167 void coord_init_zero(coord_t *coord)
169 memset(coord, 0, sizeof(*coord));
172 /* Return the number of units at the present item.
173 Asserts coord_is_existing_item(). */
174 unsigned coord_num_units(const coord_t *coord)
176 assert("jmacd-9806", coord_is_existing_item(coord));
178 return item_plugin_by_coord(coord)->b.nr_units(coord);
181 /* Returns true if the coord was initializewd by coord_init_invalid (). */
182 /* Audited by: green(2002.06.15) */
183 int coord_is_invalid(const coord_t *coord)
185 return coord->between == INVALID_COORD;
188 /* Returns true if the coordinate is positioned at an existing item, not before
189 or after an item. It may be placed at, before, or after any unit within the
190 item, whether existing or not. */
191 int coord_is_existing_item(const coord_t *coord)
193 switch (coord->between) {
194 case EMPTY_NODE:
195 case BEFORE_ITEM:
196 case AFTER_ITEM:
197 case INVALID_COORD:
198 return 0;
200 case BEFORE_UNIT:
201 case AT_UNIT:
202 case AFTER_UNIT:
203 return coord->item_pos < coord_num_items(coord);
206 impossible("jmacd-9900", "unreachable coord: %p", coord);
207 return 0;
210 /* Returns true if the coordinate is positioned at an existing unit, not before
211 or after a unit. */
212 /* Audited by: green(2002.06.15) */
213 int coord_is_existing_unit(const coord_t *coord)
215 switch (coord->between) {
216 case EMPTY_NODE:
217 case BEFORE_UNIT:
218 case AFTER_UNIT:
219 case BEFORE_ITEM:
220 case AFTER_ITEM:
221 case INVALID_COORD:
222 return 0;
224 case AT_UNIT:
225 return (coord->item_pos < coord_num_items(coord)
226 && coord->unit_pos < coord_num_units(coord));
229 impossible("jmacd-9902", "unreachable");
230 return 0;
233 /* Returns true if the coordinate is positioned at the first unit of the first
234 item. Not true for empty nodes nor coordinates positioned before the first
235 item. */
236 /* Audited by: green(2002.06.15) */
237 int coord_is_leftmost_unit(const coord_t *coord)
239 return (coord->between == AT_UNIT && coord->item_pos == 0
240 && coord->unit_pos == 0);
243 #if REISER4_DEBUG
244 /* For assertions only, checks for a valid coordinate. */
245 int coord_check(const coord_t *coord)
247 if (coord->node == NULL)
248 return 0;
249 if (znode_above_root(coord->node))
250 return 1;
252 switch (coord->between) {
253 default:
254 case INVALID_COORD:
255 return 0;
256 case EMPTY_NODE:
257 if (!node_is_empty(coord->node))
258 return 0;
259 return coord->item_pos == 0 && coord->unit_pos == 0;
261 case BEFORE_UNIT:
262 case AFTER_UNIT:
263 if (node_is_empty(coord->node) && (coord->item_pos == 0)
264 && (coord->unit_pos == 0))
265 return 1;
266 case AT_UNIT:
267 break;
268 case AFTER_ITEM:
269 case BEFORE_ITEM:
270 /* before/after item should not set unit_pos. */
271 if (coord->unit_pos != 0)
272 return 0;
273 break;
276 if (coord->item_pos >= node_num_items(coord->node))
277 return 0;
279 /* FIXME-VS: we are going to check unit_pos. This makes no sense when
280 between is set either AFTER_ITEM or BEFORE_ITEM */
281 if (coord->between == AFTER_ITEM || coord->between == BEFORE_ITEM)
282 return 1;
284 if (coord_is_iplug_set(coord) &&
285 coord->unit_pos >
286 item_plugin_by_coord(coord)->b.nr_units(coord) - 1)
287 return 0;
288 return 1;
290 #endif
292 /* Adjust coordinate boundaries based on the number of items prior to
293 coord_next/prev. Returns 1 if the new position is does not exist. */
294 static int coord_adjust_items(coord_t *coord, unsigned items, int is_next)
296 /* If the node is invalid, leave it. */
297 if (coord->between == INVALID_COORD)
298 return 1;
300 /* If the node is empty, set it appropriately. */
301 if (items == 0) {
302 coord->between = EMPTY_NODE;
303 coord_set_item_pos(coord, 0);
304 coord->unit_pos = 0;
305 return 1;
308 /* If it was empty and it no longer is, set to BEFORE/AFTER_ITEM. */
309 if (coord->between == EMPTY_NODE) {
310 coord->between = (is_next ? BEFORE_ITEM : AFTER_ITEM);
311 coord_set_item_pos(coord, 0);
312 coord->unit_pos = 0;
313 return 0;
316 /* If the item_pos is out-of-range, set it appropriatly. */
317 if (coord->item_pos >= items) {
318 coord->between = AFTER_ITEM;
319 coord_set_item_pos(coord, items - 1);
320 coord->unit_pos = 0;
321 /* If is_next, return 1 (can't go any further). */
322 return is_next;
325 return 0;
328 /* Advances the coordinate by one unit to the right. If empty, no change. If
329 coord_is_rightmost_unit, advances to AFTER THE LAST ITEM. Returns 0 if new
330 position is an existing unit. */
331 int coord_next_unit(coord_t *coord)
333 unsigned items = coord_num_items(coord);
335 if (coord_adjust_items(coord, items, 1) == 1)
336 return 1;
338 switch (coord->between) {
339 case BEFORE_UNIT:
340 /* Now it is positioned at the same unit. */
341 coord->between = AT_UNIT;
342 return 0;
344 case AFTER_UNIT:
345 case AT_UNIT:
346 /* If it was at or after a unit and there are more units in this
347 item, advance to the next one. */
348 if (coord->unit_pos < coord_last_unit_pos(coord)) {
349 coord->unit_pos += 1;
350 coord->between = AT_UNIT;
351 return 0;
354 /* Otherwise, it is crossing an item boundary and treated as if
355 it was after the current item. */
356 coord->between = AFTER_ITEM;
357 coord->unit_pos = 0;
358 /* FALLTHROUGH */
360 case AFTER_ITEM:
361 /* Check for end-of-node. */
362 if (coord->item_pos == items - 1)
363 return 1;
365 coord_inc_item_pos(coord);
366 coord->unit_pos = 0;
367 coord->between = AT_UNIT;
368 return 0;
370 case BEFORE_ITEM:
371 /* The adjust_items checks ensure that we are valid here. */
372 coord->unit_pos = 0;
373 coord->between = AT_UNIT;
374 return 0;
376 case INVALID_COORD:
377 case EMPTY_NODE:
378 /* Handled in coord_adjust_items(). */
379 break;
382 impossible("jmacd-9902", "unreachable");
383 return 0;
386 /* Advances the coordinate by one item to the right. If empty, no change. If
387 coord_is_rightmost_unit, advances to AFTER THE LAST ITEM. Returns 0 if new
388 position is an existing item. */
389 int coord_next_item(coord_t *coord)
391 unsigned items = coord_num_items(coord);
393 if (coord_adjust_items(coord, items, 1) == 1)
394 return 1;
396 switch (coord->between) {
397 case AFTER_UNIT:
398 case AT_UNIT:
399 case BEFORE_UNIT:
400 case AFTER_ITEM:
401 /* Check for end-of-node. */
402 if (coord->item_pos == items - 1) {
403 coord->between = AFTER_ITEM;
404 coord->unit_pos = 0;
405 coord_clear_iplug(coord);
406 return 1;
409 /* Anywhere in an item, go to the next one. */
410 coord->between = AT_UNIT;
411 coord_inc_item_pos(coord);
412 coord->unit_pos = 0;
413 return 0;
415 case BEFORE_ITEM:
416 /* The out-of-range check ensures that we are valid here. */
417 coord->unit_pos = 0;
418 coord->between = AT_UNIT;
419 return 0;
420 case INVALID_COORD:
421 case EMPTY_NODE:
422 /* Handled in coord_adjust_items(). */
423 break;
426 impossible("jmacd-9903", "unreachable");
427 return 0;
430 /* Advances the coordinate by one unit to the left. If empty, no change. If
431 coord_is_leftmost_unit, advances to BEFORE THE FIRST ITEM. Returns 0 if new
432 position is an existing unit. */
433 int coord_prev_unit(coord_t *coord)
435 unsigned items = coord_num_items(coord);
437 if (coord_adjust_items(coord, items, 0) == 1)
438 return 1;
440 switch (coord->between) {
441 case AT_UNIT:
442 case BEFORE_UNIT:
443 if (coord->unit_pos > 0) {
444 coord->unit_pos -= 1;
445 coord->between = AT_UNIT;
446 return 0;
449 if (coord->item_pos == 0) {
450 coord->between = BEFORE_ITEM;
451 return 1;
454 coord_dec_item_pos(coord);
455 coord->unit_pos = coord_last_unit_pos(coord);
456 coord->between = AT_UNIT;
457 return 0;
459 case AFTER_UNIT:
460 /* What if unit_pos is out-of-range? */
461 assert("jmacd-5442",
462 coord->unit_pos <= coord_last_unit_pos(coord));
463 coord->between = AT_UNIT;
464 return 0;
466 case BEFORE_ITEM:
467 if (coord->item_pos == 0)
468 return 1;
470 coord_dec_item_pos(coord);
471 /* FALLTHROUGH */
473 case AFTER_ITEM:
474 coord->between = AT_UNIT;
475 coord->unit_pos = coord_last_unit_pos(coord);
476 return 0;
478 case INVALID_COORD:
479 case EMPTY_NODE:
480 break;
483 impossible("jmacd-9904", "unreachable");
484 return 0;
487 /* Advances the coordinate by one item to the left. If empty, no change. If
488 coord_is_leftmost_unit, advances to BEFORE THE FIRST ITEM. Returns 0 if new
489 position is an existing item. */
490 int coord_prev_item(coord_t *coord)
492 unsigned items = coord_num_items(coord);
494 if (coord_adjust_items(coord, items, 0) == 1)
495 return 1;
497 switch (coord->between) {
498 case AT_UNIT:
499 case AFTER_UNIT:
500 case BEFORE_UNIT:
501 case BEFORE_ITEM:
503 if (coord->item_pos == 0) {
504 coord->between = BEFORE_ITEM;
505 coord->unit_pos = 0;
506 return 1;
509 coord_dec_item_pos(coord);
510 coord->unit_pos = 0;
511 coord->between = AT_UNIT;
512 return 0;
514 case AFTER_ITEM:
515 coord->between = AT_UNIT;
516 coord->unit_pos = 0;
517 return 0;
519 case INVALID_COORD:
520 case EMPTY_NODE:
521 break;
524 impossible("jmacd-9905", "unreachable");
525 return 0;
528 /* Calls either coord_init_first_unit or coord_init_last_unit depending on
529 sideof argument. */
530 void coord_init_sideof_unit(coord_t *coord, const znode * node, sideof dir)
532 assert("jmacd-9821", dir == LEFT_SIDE || dir == RIGHT_SIDE);
533 if (dir == LEFT_SIDE) {
534 coord_init_first_unit(coord, node);
535 } else {
536 coord_init_last_unit(coord, node);
540 /* Calls either coord_is_before_leftmost or coord_is_after_rightmost depending
541 on sideof argument. */
542 /* Audited by: green(2002.06.15) */
543 int coord_is_after_sideof_unit(coord_t *coord, sideof dir)
545 assert("jmacd-9822", dir == LEFT_SIDE || dir == RIGHT_SIDE);
546 if (dir == LEFT_SIDE) {
547 return coord_is_before_leftmost(coord);
548 } else {
549 return coord_is_after_rightmost(coord);
553 /* Calls either coord_next_unit or coord_prev_unit depending on sideof argument.
555 /* Audited by: green(2002.06.15) */
556 int coord_sideof_unit(coord_t *coord, sideof dir)
558 assert("jmacd-9823", dir == LEFT_SIDE || dir == RIGHT_SIDE);
559 if (dir == LEFT_SIDE) {
560 return coord_prev_unit(coord);
561 } else {
562 return coord_next_unit(coord);
566 #if REISER4_DEBUG
567 int coords_equal(const coord_t *c1, const coord_t *c2)
569 assert("nikita-2840", c1 != NULL);
570 assert("nikita-2841", c2 != NULL);
572 return
573 c1->node == c2->node &&
574 c1->item_pos == c2->item_pos &&
575 c1->unit_pos == c2->unit_pos && c1->between == c2->between;
577 #endif /* REISER4_DEBUG */
579 /* If coord_is_after_rightmost return NCOORD_ON_THE_RIGHT, if
580 coord_is_after_leftmost return NCOORD_ON_THE_LEFT, otherwise return
581 NCOORD_INSIDE. */
582 /* Audited by: green(2002.06.15) */
583 coord_wrt_node coord_wrt(const coord_t *coord)
585 if (coord_is_before_leftmost(coord))
586 return COORD_ON_THE_LEFT;
588 if (coord_is_after_rightmost(coord))
589 return COORD_ON_THE_RIGHT;
591 return COORD_INSIDE;
594 /* Returns true if the coordinate is positioned after the last item or after the
595 last unit of the last item or it is an empty node. */
596 /* Audited by: green(2002.06.15) */
597 int coord_is_after_rightmost(const coord_t *coord)
599 assert("jmacd-7313", coord_check(coord));
601 switch (coord->between) {
602 case INVALID_COORD:
603 case AT_UNIT:
604 case BEFORE_UNIT:
605 case BEFORE_ITEM:
606 return 0;
608 case EMPTY_NODE:
609 return 1;
611 case AFTER_ITEM:
612 return (coord->item_pos == node_num_items(coord->node) - 1);
614 case AFTER_UNIT:
615 return ((coord->item_pos == node_num_items(coord->node) - 1) &&
616 coord->unit_pos == coord_last_unit_pos(coord));
619 impossible("jmacd-9908", "unreachable");
620 return 0;
623 /* Returns true if the coordinate is positioned before the first item or it is
624 an empty node. */
625 int coord_is_before_leftmost(const coord_t *coord)
627 /* FIXME-VS: coord_check requires node to be loaded whereas it is not
628 necessary to check if coord is set before leftmost
629 assert ("jmacd-7313", coord_check (coord)); */
630 switch (coord->between) {
631 case INVALID_COORD:
632 case AT_UNIT:
633 case AFTER_ITEM:
634 case AFTER_UNIT:
635 return 0;
637 case EMPTY_NODE:
638 return 1;
640 case BEFORE_ITEM:
641 case BEFORE_UNIT:
642 return (coord->item_pos == 0) && (coord->unit_pos == 0);
645 impossible("jmacd-9908", "unreachable");
646 return 0;
649 /* Returns true if the coordinate is positioned after a item, before a item,
650 after the last unit of an item, before the first unit of an item, or at an
651 empty node. */
652 /* Audited by: green(2002.06.15) */
653 int coord_is_between_items(const coord_t *coord)
655 assert("jmacd-7313", coord_check(coord));
657 switch (coord->between) {
658 case INVALID_COORD:
659 case AT_UNIT:
660 return 0;
662 case AFTER_ITEM:
663 case BEFORE_ITEM:
664 case EMPTY_NODE:
665 return 1;
667 case BEFORE_UNIT:
668 return coord->unit_pos == 0;
670 case AFTER_UNIT:
671 return coord->unit_pos == coord_last_unit_pos(coord);
674 impossible("jmacd-9908", "unreachable");
675 return 0;
678 #if REISER4_DEBUG
679 /* Returns true if the coordinates are positioned at adjacent units, regardless
680 of before-after or item boundaries. */
681 int coord_are_neighbors(coord_t *c1, coord_t *c2)
683 coord_t *left;
684 coord_t *right;
686 assert("nikita-1241", c1 != NULL);
687 assert("nikita-1242", c2 != NULL);
688 assert("nikita-1243", c1->node == c2->node);
689 assert("nikita-1244", coord_is_existing_unit(c1));
690 assert("nikita-1245", coord_is_existing_unit(c2));
692 left = right = NULL;
693 switch (coord_compare(c1, c2)) {
694 case COORD_CMP_ON_LEFT:
695 left = c1;
696 right = c2;
697 break;
698 case COORD_CMP_ON_RIGHT:
699 left = c2;
700 right = c1;
701 break;
702 case COORD_CMP_SAME:
703 return 0;
704 default:
705 wrong_return_value("nikita-1246", "compare_coords()");
707 assert("vs-731", left && right);
708 if (left->item_pos == right->item_pos) {
709 return left->unit_pos + 1 == right->unit_pos;
710 } else if (left->item_pos + 1 == right->item_pos) {
711 return (left->unit_pos == coord_last_unit_pos(left))
712 && (right->unit_pos == 0);
713 } else {
714 return 0;
717 #endif /* REISER4_DEBUG */
719 /* Assuming two coordinates are positioned in the same node, return
720 COORD_CMP_ON_RIGHT, COORD_CMP_ON_LEFT, or COORD_CMP_SAME depending on c1's
721 position relative to c2. */
722 /* Audited by: green(2002.06.15) */
723 coord_cmp coord_compare(coord_t *c1, coord_t *c2)
725 assert("vs-209", c1->node == c2->node);
726 assert("vs-194", coord_is_existing_unit(c1)
727 && coord_is_existing_unit(c2));
729 if (c1->item_pos > c2->item_pos)
730 return COORD_CMP_ON_RIGHT;
731 if (c1->item_pos < c2->item_pos)
732 return COORD_CMP_ON_LEFT;
733 if (c1->unit_pos > c2->unit_pos)
734 return COORD_CMP_ON_RIGHT;
735 if (c1->unit_pos < c2->unit_pos)
736 return COORD_CMP_ON_LEFT;
737 return COORD_CMP_SAME;
740 /* If the coordinate is between items, shifts it to the right. Returns 0 on
741 success and non-zero if there is no position to the right. */
742 int coord_set_to_right(coord_t *coord)
744 unsigned items = coord_num_items(coord);
746 if (coord_adjust_items(coord, items, 1) == 1)
747 return 1;
749 switch (coord->between) {
750 case AT_UNIT:
751 return 0;
753 case BEFORE_ITEM:
754 case BEFORE_UNIT:
755 coord->between = AT_UNIT;
756 return 0;
758 case AFTER_UNIT:
759 if (coord->unit_pos < coord_last_unit_pos(coord)) {
760 coord->unit_pos += 1;
761 coord->between = AT_UNIT;
762 return 0;
763 } else {
765 coord->unit_pos = 0;
767 if (coord->item_pos == items - 1) {
768 coord->between = AFTER_ITEM;
769 return 1;
772 coord_inc_item_pos(coord);
773 coord->between = AT_UNIT;
774 return 0;
777 case AFTER_ITEM:
778 if (coord->item_pos == items - 1)
779 return 1;
781 coord_inc_item_pos(coord);
782 coord->unit_pos = 0;
783 coord->between = AT_UNIT;
784 return 0;
786 case EMPTY_NODE:
787 return 1;
789 case INVALID_COORD:
790 break;
793 impossible("jmacd-9920", "unreachable");
794 return 0;
797 /* If the coordinate is between items, shifts it to the left. Returns 0 on
798 success and non-zero if there is no position to the left. */
799 int coord_set_to_left(coord_t *coord)
801 unsigned items = coord_num_items(coord);
803 if (coord_adjust_items(coord, items, 0) == 1)
804 return 1;
806 switch (coord->between) {
807 case AT_UNIT:
808 return 0;
810 case AFTER_UNIT:
811 coord->between = AT_UNIT;
812 return 0;
814 case AFTER_ITEM:
815 coord->between = AT_UNIT;
816 coord->unit_pos = coord_last_unit_pos(coord);
817 return 0;
819 case BEFORE_UNIT:
820 if (coord->unit_pos > 0) {
821 coord->unit_pos -= 1;
822 coord->between = AT_UNIT;
823 return 0;
824 } else {
826 if (coord->item_pos == 0) {
827 coord->between = BEFORE_ITEM;
828 return 1;
831 coord->unit_pos = coord_last_unit_pos(coord);
832 coord_dec_item_pos(coord);
833 coord->between = AT_UNIT;
834 return 0;
837 case BEFORE_ITEM:
838 if (coord->item_pos == 0)
839 return 1;
841 coord_dec_item_pos(coord);
842 coord->unit_pos = coord_last_unit_pos(coord);
843 coord->between = AT_UNIT;
844 return 0;
846 case EMPTY_NODE:
847 return 1;
849 case INVALID_COORD:
850 break;
853 impossible("jmacd-9920", "unreachable");
854 return 0;
857 static const char *coord_tween_tostring(between_enum n)
859 switch (n) {
860 case BEFORE_UNIT:
861 return "before unit";
862 case BEFORE_ITEM:
863 return "before item";
864 case AT_UNIT:
865 return "at unit";
866 case AFTER_UNIT:
867 return "after unit";
868 case AFTER_ITEM:
869 return "after item";
870 case EMPTY_NODE:
871 return "empty node";
872 case INVALID_COORD:
873 return "invalid";
874 default:
876 static char buf[30];
878 sprintf(buf, "unknown: %i", n);
879 return buf;
884 void print_coord(const char *mes, const coord_t *coord, int node)
886 if (coord == NULL) {
887 printk("%s: null\n", mes);
888 return;
890 printk("%s: item_pos = %d, unit_pos %d, tween=%s, iplug=%d\n",
891 mes, coord->item_pos, coord->unit_pos,
892 coord_tween_tostring(coord->between), coord->iplugid);
896 item_utmost_child_real_block(const coord_t *coord, sideof side,
897 reiser4_block_nr * blk)
899 return item_plugin_by_coord(coord)->f.utmost_child_real_block(coord,
900 side,
901 blk);
904 int item_utmost_child(const coord_t *coord, sideof side, jnode ** child)
906 return item_plugin_by_coord(coord)->f.utmost_child(coord, side, child);
909 /* @count bytes of flow @f got written, update correspondingly f->length,
910 f->data and f->key */
911 void move_flow_forward(flow_t *f, unsigned count)
913 if (f->data)
914 f->data += count;
915 f->length -= count;
916 set_key_offset(&f->key, get_key_offset(&f->key) + count);
920 Local variables:
921 c-indentation-style: "K&R"
922 mode-name: "LC"
923 c-basic-offset: 8
924 tab-width: 8
925 fill-column: 120
926 scroll-step: 1
927 End: