Mercurial > projects > mde
changeset 164:c13bded1bed3
Some (somewhat pointless) memory optimisations for AStringContent.
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Sat, 23 May 2009 17:23:21 +0200 |
parents | 24d77c52243f |
children | bb2f1a76346d |
files | mde/content/AStringContent.d |
diffstat | 1 files changed, 59 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/mde/content/AStringContent.d Sat May 23 15:47:32 2009 +0200 +++ b/mde/content/AStringContent.d Sat May 23 17:23:21 2009 +0200 @@ -32,6 +32,14 @@ logger = Log.getLogger ("mde.content.AStringContent"); } +private { + // Returns the length of memory to allocate, when len is the min required. + // Returns at least 66, since formatting from int/float requires this. + size_t allocLength (size_t len) { + return len < 33 ? 66 : len * 2; + } +} + /** Union of all content types here - for dynamic cast checking against several * types. */ union UnionContent { @@ -55,6 +63,7 @@ { protected this (char[] symbol) { super (symbol); + svBuf.length = allocLength (0); } /// Get the text. @@ -75,10 +84,22 @@ return false; } - /** Acts on a keystroke and returns the new value. + /** Acts on a keystroke to edit the value as a string. + * + * After this has been used to edit the string, endEdit should be called + * to convert back to the native value type. * * Supports one-line editing: left/right, home/end, backspace/delete. */ char[] keyStroke (ushort sym, char[] i) { + // This routine relies on the folowing: svBuf[0..sv.length] == sv + if (sv.ptr !is svBuf.ptr) { + // sv may be within svBuf but not starting at its beginning + //NOTE: to further optimise, try to avoid a realloc on the heap + svBuf = new char[allocLength (sv.length)]; + svBuf[0..sv.length] = sv; + } + //NOTE (optimise): dup is used several times for temporary storage + //perhaps could be optimised by a dup func using thread-local buffer? debug assert (i.length, "StringContent.keyStroke: no value (??)"); // impossible? char k = *i; if (k >= 0x20) { @@ -87,14 +108,18 @@ if (p < sv.length) ++p; while (p < sv.length && (sv[p] & 0x80) && !(sv[p] & 0x40)) ++p; - sv = sv[0..pos] ~ sv[p..$]; + size_t l = sv.length - (p-pos); + sv[pos..l] = sv[p..$].dup; + sv = sv[0..l]; } else { // insert character char[] tail = sv[pos..$]; - //NOTE: reallocating each keypress isn't optimal - sv.length = sv.length + i.length; + size_t l = sv.length + i.length; + if (svBuf.length < l) + svBuf.length = allocLength (l); size_t npos = pos+i.length; - if (tail) sv[npos..$] = tail.dup; // cannot assign with overlapping ranges - sv[pos..npos] = i; + if (tail) svBuf[npos..l] = tail.dup; + svBuf[pos..npos] = i; + sv = svBuf[0..l]; pos = npos; } } else { // use sym; many keys output 0 @@ -102,10 +127,13 @@ } // all modifier keys and contect menu key; should be ignored else if (sym == SDLK_BACKSPACE) { // backspace; k == 0x8 char[] tail = sv[pos..$]; + size_t l = pos; if (pos) --pos; while (pos && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) --pos; - sv = sv[0..pos] ~ tail; + l = sv.length - (l - pos); + sv[pos..l] = tail.dup; + sv = sv[0..l]; } else if (sym == SDLK_LEFT) { if (pos) --pos; while (pos && (sv[pos] & 0x80) && !(sv[pos] & 0x40)) @@ -155,10 +183,10 @@ protected: /* String version of value (for toString(0) and editing). - * WARNING: This must point to mutable memory! - * (Actually this isn't usually required now, but after optimising will be.) - * TODO: provide a buffer, for use when editing sv. */ + * WARNING: This must point to mutable memory (for endEdit), and + * when keyStroke can be called we must have svBuf[0..sv.length] == sv. */ char[] sv; + char[] svBuf; // buffer to reduce reallocs size_t pos; // editing position; used by keyStroke } @@ -169,14 +197,14 @@ auto valp = symbol in changed.boolData; if (valp) v = *valp; - sv = (v ? "true" : "false").dup; + sv = v ? "true" : "false"; super (symbol); } // Assign without adding change to save changeset void assignNoCng (bool val) { v = val; - sv = (v ? "true" : "false").dup; + sv = v ? "true" : "false"; if (pos > sv.length) pos = sv.length; endEvent; } @@ -200,10 +228,10 @@ v = (Int.toLong (sv) != 0); } catch (Exception e) { logger.error (e.msg); - sv = (v ? "true" : "false").dup; + sv = v ? "true" : "false"; return false; } - sv = (v ? "true" : "false").dup; + sv = v ? "true" : "false"; endEvent; endCng; return true; @@ -261,11 +289,11 @@ { /** Create a content with _symbol name symbol. */ this (char[] symbol) { - auto valp = symbol in changed.intData; + super (symbol); + auto valp = symbol in changed.intData; if (valp) v = *valp; - sv = Int.toString (v); - super (symbol); + sv = Int.format (svBuf, v); } override bool set (IContent c) { @@ -290,7 +318,7 @@ void assignNoCng (int val) { v = val; - sv = Int.toString (v); + sv = Int.format (svBuf, v); if (pos > sv.length) pos = sv.length; endEvent; } @@ -305,13 +333,14 @@ override bool endEdit () { try { - v = Int.toInt (sv); + // use toFloat to allow decimal points and exponents + v = Math.rndint (Float.toFloat (sv)); } catch (Exception e) { logger.error (e.msg); - sv = Int.toString (v); + sv = Int.format (svBuf, v); return false; } - sv = Int.toString (v); + sv = Int.format (svBuf, v); endEvent; endCng; return true; @@ -330,11 +359,11 @@ { /** Create a content with _symbol name symbol. */ this (char[] symbol) { - auto valp = symbol in changed.doubleData; + super (symbol); + auto valp = symbol in changed.doubleData; if (valp) v = *valp; - sv = Float.toString (v, 8, 4); - super (symbol); + sv = Float.format (svBuf, v, 8, 4); } override bool set (IContent c) { @@ -359,7 +388,7 @@ void assignNoCng (double val) { v = val; - sv = Float.toString (v, 8, 4); + sv = Float.format (svBuf, v, 8, 4); if (pos > sv.length) pos = sv.length; endEvent; } @@ -377,10 +406,10 @@ v = Float.toFloat (sv); } catch (Exception e) { logger.error (e.msg); - sv = Float.toString (v, 8, 4); + sv = Float.format (svBuf, v, 8, 4); return false; } - sv = Float.toString (v, 8, 4); + sv = Float.format (svBuf, v, 8, 4); endEvent; endCng; return true; @@ -412,7 +441,7 @@ e = new EnumValueContent (this, i, symPeriod~enumSymbols[i]); } enums[v].assignFromParent (true); - sv = enums[v].name_.dup; + sv = enums[v].name_; // Re-set the value if a saved value is found: auto valp = symbol in changed.enumValData; if (valp) @@ -446,7 +475,7 @@ enums[v] .assignFromParent (false); enums[val].assignFromParent (true); v = val; - sv = enums[v].name_.dup; + sv = enums[v].name_; if (pos > sv.length) pos = sv.length; endEvent; } @@ -458,7 +487,7 @@ goto break1; } - sv = enums[v].name_.dup; // sv was edited; revert + sv = enums[v].name_; // sv was edited; revert logger.error ("EnumContent "~name_~" assigned invalid value; keeping value: "~sv); if (pos > sv.length) pos = sv.length; return false;