Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-03-24 16:18:58 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-03-24 16:27:31 +0300
commit977a4e7f5d001e62a9e09dd3a02dc2cb2329f893 (patch)
tree09a3952a6651d8ff8e0206b9667a9811cec6ed41 /source
parent3f9d5ea0ecc2561ee51be977ffd5ef4cfa0c2b49 (diff)
Text: re-allocate exact lengths for undo
Undo sometimes reserved too much space in the buffer, now assert when this happens and allocate the exact size needed. Note prepares for moving text editor undo out of the text block (D3113) which will split the undo buffer into a list of undo steps.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/text.c138
1 files changed, 84 insertions, 54 deletions
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 5de325277ee..b8307031920 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -191,8 +191,8 @@ int txt_get_undostate(void)
static void init_undo_text(Text *text)
{
text->undo_pos = -1;
- text->undo_len = TXT_INIT_UNDO;
- text->undo_buf = MEM_mallocN(text->undo_len, "undo buf");
+ text->undo_len = 0;
+ text->undo_buf = NULL;
}
/**
@@ -1466,25 +1466,40 @@ void txt_insert_buf(Text *text, const char *in_buffer)
static bool max_undo_test(Text *text, int x)
{
- while (text->undo_pos + x >= text->undo_len) {
- if (text->undo_len * 2 > TXT_MAX_UNDO) {
- /* XXX error("Undo limit reached, buffer cleared\n"); */
- MEM_freeN(text->undo_buf);
- init_undo_text(text);
- return false;
- }
- else {
- void *tmp = text->undo_buf;
- text->undo_buf = MEM_callocN(text->undo_len * 2, "undo buf");
- memcpy(text->undo_buf, tmp, text->undo_len);
- text->undo_len *= 2;
- MEM_freeN(tmp);
- }
- }
+ /* Normally over-allocating is preferred,
+ * however in this case the buffer is small enough and re-allocation
+ * fast enough for each undo step that it's not a problem to allocate each time.
+ * This also saves on some memory when we have many text buffers
+ * that would have an empty undo memory allocated.
+ */
+ /* Add one for the null terminator. */
+ text->undo_len = text->undo_pos + x + 1;
+ if (text->undo_len > TXT_MAX_UNDO) {
+ /* XXX error("Undo limit reached, buffer cleared\n"); */
+ MEM_freeN(text->undo_buf);
+ init_undo_text(text);
+ return false;
+ }
+ else {
+ /* Small reallocations on each undo step is fine. */
+ text->undo_buf = MEM_recallocN(text->undo_buf, text->undo_len);
+ }
return true;
}
+static void txt_undo_end(Text *text)
+{
+ int undo_pos_end = text->undo_pos + 1;
+ BLI_assert(undo_pos_end + 1 == text->undo_len);
+ text->undo_buf[undo_pos_end] = '\0';
+}
+
+/* Call once undo is done. */
+#ifndef NDEBUG
+
+#endif
+
#if 0 /* UNUSED */
static void dump_buffer(Text *text)
{
@@ -1672,21 +1687,21 @@ static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int va
(*undo_pos)++;
}
-/* store the cur cursor to the undo buffer */
+/* store the cur cursor to the undo buffer (6 bytes)*/
static void txt_undo_store_cur(Text *text)
{
txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc);
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl));
}
-/* store the sel cursor to the undo buffer */
+/* store the sel cursor to the undo buffer (6 bytes) */
static void txt_undo_store_sel(Text *text)
{
txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc);
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell));
}
-/* store both cursors to the undo buffer */
+/* store both cursors to the undo buffer (12 bytes) */
static void txt_undo_store_cursors(Text *text)
{
txt_undo_store_cur(text);
@@ -1697,42 +1712,46 @@ static void txt_undo_store_cursors(Text *text)
static void txt_undo_add_blockop(Text *text, int op, const char *buf)
{
unsigned int length = strlen(buf);
-
- if (!max_undo_test(text, length + 11 + 12))
- return;
+ if (!max_undo_test(text, 2 + 12 + 4 + length + 4 + 1)) {
+ return;
+ }
+ /* 2 bytes */
text->undo_pos++;
text->undo_buf[text->undo_pos] = op;
text->undo_pos++;
-
+ /* 12 bytes */
txt_undo_store_cursors(text);
-
+ /* 4 bytes */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
-
+ /* 'length' bytes */
strncpy(text->undo_buf + text->undo_pos, buf, length);
text->undo_pos += length;
-
+ /* 4 bytes */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
+ /* 1 byte */
text->undo_buf[text->undo_pos] = op;
-
- text->undo_buf[text->undo_pos + 1] = 0;
+
+ txt_undo_end(text);
}
/* store a regular operator */
void txt_undo_add_op(Text *text, int op)
{
- if (!max_undo_test(text, 15))
+ if (!max_undo_test(text, 2 + 12 + 1)) {
return;
+ }
+ /* 2 bytes */
text->undo_pos++;
text->undo_buf[text->undo_pos] = op;
-
text->undo_pos++;
-
+ /* 12 bytes */
txt_undo_store_cursors(text);
-
+ /* 1 byte */
text->undo_buf[text->undo_pos] = op;
- text->undo_buf[text->undo_pos + 1] = 0;
+
+ txt_undo_end(text);
}
/* store an operator for a single character */
@@ -1741,35 +1760,41 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c)
char utf8[BLI_UTF8_MAX];
size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8);
- if (!max_undo_test(text, 3 + utf8_size + 12))
- return;
-
- text->undo_pos++;
-
- if (utf8_size < 4) {
+ if (utf8_size < 4 && 0) {
+ if (!max_undo_test(text, 2 + 6 + utf8_size + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ text->undo_pos++;
text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
text->undo_pos++;
-
+ /* 6 bytes */
txt_undo_store_cur(text);
-
+ /* 'utf8_size' bytes */
for (i = 0; i < utf8_size; i++) {
text->undo_buf[text->undo_pos] = utf8[i];
text->undo_pos++;
}
-
+ /* 1 byte */
text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
}
else {
+ if (!max_undo_test(text, 2 + 6 + 4 + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ text->undo_pos++;
text->undo_buf[text->undo_pos] = op_start + 3;
text->undo_pos++;
-
+ /* 6 bytes */
txt_undo_store_cur(text);
-
+ /* 4 bytes */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c);
+ /* 1 byte */
text->undo_buf[text->undo_pos] = op_start + 3;
}
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text);
}
/* extends Link */
@@ -1791,30 +1816,35 @@ static void txt_undo_add_unprefix_op(
BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
/* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */
- if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
+ if (!max_undo_test(text, 2 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
return;
}
- /* Opening buffer sequence with OP */
+ /* 2 bytes */
text->undo_pos++;
text->undo_buf[text->undo_pos] = undo_op;
text->undo_pos++;
- /* Adding number of line numbers to read */
+ /* Adding number of line numbers to read
+ * 4 bytes */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
- /* Adding linenumbers of lines that shall not be indented if undoing */
+ /* Adding linenumbers of lines that shall not be indented if undoing.
+ * 'line_index_mask_len * 4' bytes */
for (idata = line_index_mask->first; idata; idata = idata->next) {
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value);
}
- /* Adding number of line numbers to read again */
+ /* Adding number of line numbers to read again.
+ * 4 bytes */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
- /* Adding current selection */
+ /* Adding current selection.
+ * 12 bytes */
txt_undo_store_cursors(text);
- /* Closing with OP (same as above) */
+ /* Closing with OP (same as above).
+ * 1 byte */
text->undo_buf[text->undo_pos] = undo_op;
/* Marking as last undo operation */
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text);
}
static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)