From e747de449518858ed7a5e5f9ecbd7fdabebf0bb1 Mon Sep 17 00:00:00 2001 From: Andrey Kotlarski Date: Mon, 20 Jan 2014 02:37:51 +0200 Subject: [PATCH] Unify and optimize deletion. --- vlf-base.el | 157 ++++++++++++++++++++++++++++------------------------ 1 file changed, 84 insertions(+), 73 deletions(-) diff --git a/vlf-base.el b/vlf-base.el index c6da794..761da5f 100644 --- a/vlf-base.el +++ b/vlf-base.el @@ -147,36 +147,28 @@ bytes added to the end." (let ((pos (+ (position-bytes (point)) vlf-start-pos)) (inhibit-read-only t)) (cond ((< end edit-end) - (let* ((del-pos (or (byte-to-position - (1+ (- end vlf-start-pos))) - (point-min))) - (del-len (length (encode-coding-region - del-pos (point-max) - buffer-file-coding-system - t)))) - (setq end (- (if (zerop vlf-end-pos) - vlf-file-size - vlf-end-pos) - del-len)) - (vlf-with-undo-disabled - (delete-region del-pos (point-max))))) + (setq end (car (vlf-delete-region + (point-min) vlf-start-pos edit-end + end (or (byte-to-position + (- end vlf-start-pos)) + (point-min)) + nil)))) ((< edit-end end) (vlf-with-undo-disabled (setq shift-end (cdr (vlf-insert-file-contents vlf-end-pos end (/= start vlf-end-pos) t (point-max))))))) + (setq vlf-end-pos (+ end shift-end)) (cond ((< vlf-start-pos start) - (let* ((del-pos (byte-to-position - (1+ (- start vlf-start-pos)))) - (del-len (length (encode-coding-region - (point-min) del-pos - buffer-file-coding-system - t)))) - (setq start (+ vlf-start-pos del-len)) - (vlf-with-undo-disabled - (delete-region (point-min) del-pos)) - (vlf-shift-undo-list (- (point-min) del-pos)))) + (let ((del-info (vlf-delete-region + (point-min) vlf-start-pos + vlf-end-pos start + (byte-to-position + (- start vlf-start-pos)) t))) + (setq start (car del-info)) + (vlf-shift-undo-list (- (point-min) + (cdr del-info))))) ((< start vlf-start-pos) (let ((edit-end-pos (point-max))) (vlf-with-undo-disabled @@ -187,13 +179,13 @@ bytes added to the end." (goto-char (point-min)) (insert (delete-and-extract-region edit-end-pos (point-max)))) - (vlf-shift-undo-list (- (point-max) edit-end-pos))))) + (vlf-shift-undo-list (- (point-max) + edit-end-pos))))) (setq start (- start shift-start)) (goto-char (or (byte-to-position (- pos start)) (byte-to-position (- pos vlf-start-pos)) (point-max))) - (setq vlf-start-pos start - vlf-end-pos (+ end shift-end))) + (setq vlf-start-pos start)) (set-buffer-modified-p modified) (set-visited-file-modtime) (cons shift-start shift-end)))))) @@ -241,11 +233,24 @@ bytes added to the end." (setq shift-start (vlf-adjust-start start safe-end position adjust-end) start (- start shift-start)) - (vlf-insert-file-contents-safe start safe-end position)) + (vlf-insert-file-contents-1 start safe-end position)) (if adjust-end - (setq shift-end (vlf-adjust-end start end position))) + (setq shift-end (- (car (vlf-delete-region position start + safe-end end + (point-max) + nil 'start)) + end))) (cons shift-start shift-end))) +(defun vlf-insert-file-contents-1 (start end position) + "Extract decoded file bytes START to END at POSITION." + (let ((coding buffer-file-coding-system)) + (insert-file-contents-literally buffer-file-name nil start end) + (let ((coding-system-for-read coding)) + (decode-coding-inserted-region position (point-max) + buffer-file-name nil start end))) + (setq buffer-file-coding-system last-coding-system-used)) + (defun vlf-adjust-start (start end position adjust-end) "Adjust chunk beginning at absolute START to END till content can\ be properly decoded. Use buffer POSITION as start. @@ -257,7 +262,7 @@ Return number of bytes moved back for proper decoding." (strict (or (= sample-end vlf-file-size) (and (not adjust-end) (= sample-end end)))) (shift 0)) - (while (and (progn (vlf-insert-file-contents-safe + (while (and (progn (vlf-insert-file-contents-1 safe-start sample-end position) (not (zerop safe-start))) (< shift 3) @@ -273,53 +278,59 @@ Return number of bytes moved back for proper decoding." safe-start (1- safe-start) chunk-size (1+ chunk-size)) (delete-region position (point-max))) - (let ((cut-pos position) - (cut-len 0)) - (while (< safe-start start) - (setq cut-len (length (encode-coding-region - cut-pos (1+ cut-pos) - buffer-file-coding-system t)) - cut-pos (1+ cut-pos) - safe-start (+ safe-start cut-len))) - (if (< start safe-start) - (setq safe-start (- safe-start cut-len) - cut-pos (1- cut-pos))) - (if (= sample-end end) - (delete-region position cut-pos) - (delete-region position (point-max)) - (vlf-insert-file-contents-safe safe-start end position))) + (setq safe-start (car (vlf-delete-region position safe-start + sample-end start + position t 'start))) + (unless (= sample-end end) + (delete-region position (point-max)) + (vlf-insert-file-contents-1 safe-start end position)) (- start safe-start))) -(defun vlf-adjust-end (start end position) - "Adjust chunk end at absolute START to END starting at POSITION. -Remove characters from the end until length is closest to expected. -Return number of bytes added over expected." - (let ((expected-size (- end start)) - (current-size (length (encode-coding-region - position (point-max) - buffer-file-coding-system t))) - (cut-point (point-max)) - (cut-len 0)) - (while (< expected-size current-size) - (setq cut-len (length (encode-coding-region - (1- cut-point) cut-point +(defun vlf-delete-region (position start end border cut-point from-start + &optional encode-direction) + "Delete from chunk starting at POSITION enclosing absolute file\ +positions START to END at absolute position BORDER. Start search for +best cut at CUT-POINT. Delete from buffer beginning if FROM-START is +non nil or up to buffer end otherwise. ENCODE-DIRECTION determines +which side of the region to use to calculate cut position's absolute +file position. Possible values are: `start' - from the beginning; +`end' - from end; nil - the shorter side. +Return actual absolute position of new border and buffer point at +which deletion was performed." + (let* ((encode-from-end (if encode-direction + (eq encode-direction 'end) + (< (- end border) (- border start)))) + (dist (if encode-from-end + (- end (length (encode-coding-region + cut-point (point-max) + buffer-file-coding-system t))) + (+ start (length (encode-coding-region + position cut-point + buffer-file-coding-system t))))) + (len 0)) + (if (< border dist) + (while (< border dist) + (setq len (length (encode-coding-region + cut-point (1- cut-point) buffer-file-coding-system t)) - cut-point (1- cut-point) - current-size (- current-size cut-len))) - (if (< current-size expected-size) - (setq cut-point (1+ cut-point) - current-size (+ current-size cut-len))) - (delete-region cut-point (point-max)) - (- current-size expected-size))) - -(defun vlf-insert-file-contents-safe (start end position) - "Extract decoded file bytes START to END at POSITION." - (let ((coding buffer-file-coding-system)) - (insert-file-contents-literally buffer-file-name nil start end) - (let ((coding-system-for-read coding)) - (decode-coding-inserted-region position (point-max) - buffer-file-name nil start end))) - (setq buffer-file-coding-system last-coding-system-used)) + cut-point (1- cut-point) + dist (- dist len))) + (while (< dist border) + (setq len (length (encode-coding-region + cut-point (1+ cut-point) + buffer-file-coding-system t)) + cut-point (1+ cut-point) + dist (+ dist len))) + (or (= dist border) + (setq cut-point (1- cut-point) + dist (- dist len)))) + (and (not from-start) (/= dist border) + (setq cut-point (1+ cut-point) + dist (+ dist len))) + (vlf-with-undo-disabled + (if from-start (delete-region position cut-point) + (delete-region cut-point (point-max)))) + (cons dist (1+ cut-point)))) (defun vlf-shift-undo-list (n) "Shift undo list element regions by N."