Does anyone have an idea of a better (1) implementation of a "generic" (not these generics: stringjoin) StringJoin routine.
Does anyone have an idea of a better (1) implementation of a "generic" (not these generics: stringjoin) StringJoin routine.
The snippet below shows a rough skeleton with not all types supported but you should get the idea of what my intention was. I could use the new intrinsics and make the _DynArrayToString method a class or record method to give it a generic parameter and then let the compiler inline the different versions so it does not have to go through the case statement every time because that is getting resolved at compile time. Anyone with a better idea? (apart from "FPC has generic standalone routines! y u no have it?")
(1)
- No copy and paste for every supported type in every overload
- Reasonably fast - it does not have to be the fastest on earth with every CPU cycle squeezed out of it but it should not throw them out of the window either.
https://bitbucket.org/snippets/sglienke/r4Md8
The snippet below shows a rough skeleton with not all types supported but you should get the idea of what my intention was. I could use the new intrinsics and make the _DynArrayToString method a class or record method to give it a generic parameter and then let the compiler inline the different versions so it does not have to go through the case statement every time because that is getting resolved at compile time. Anyone with a better idea? (apart from "FPC has generic standalone routines! y u no have it?")
(1)
- No copy and paste for every supported type in every overload
- Reasonably fast - it does not have to be the fastest on earth with every CPU cycle squeezed out of it but it should not throw them out of the window either.
https://bitbucket.org/snippets/sglienke/r4Md8
Not really a better implementation, but a couple of possible tweaks...
ReplyDeleteYou have a double case inside the loop, so you could do a composite case variable before the loop and get away with only one case inside the loop.
You could always add the separator, and shave off the last one after the loop.
looks OK to me.
ReplyDeleteFor large arrays, and only if things are measured to be too slow, you might want to see if using a TStringBuilder as intermediate is faster than pure string concatenation.
I'm not sure if it's too much copy and paste for every case. It's just a few more methods: bitbucket.org - StringJoin Modified — Bitbucket
ReplyDeletePlease explain me how works this loop?
ReplyDeletefor i: = 0 to High (TBytes(p))
TBytes is array of byte, but p is unknown type array. Many times I needed this trick, but I passed length of array :-)
The length of the array is encoded in the first four(?) byte. So the array's type doesn't matter to get its length. Please correct me if I'm wrong.
ReplyDeleteChristopher Wosinski, kind of. An allocated dynamic array has room for a reference count and a length variable prior to the array itself. The size of the length variable varies with bitness of the platform. See docwiki.embarcadero.com - Internal Data Formats (Delphi) - RAD Studio
ReplyDeleteJacek Laskowski Christopher Wosinski Leif Uneus Yes, its a trick to get the compiler to generate the inlined code for System.__DynArrayLength without doing the pointer stuff yourself. The element type of the array is irrelevant for that.
ReplyDeleteJeroen Wiert Pluimers unless TStringBuilder was optimized in recent Delphis, for pure string concantenation it is slower than simply concatenating strings...
ReplyDeletedelphitools.info - Efficient String Building in Delphi - DelphiTools
TStringBuilder which could theoretically have great performance actually stumbles because of "implementation details".
Eric Grange wow, I didn't expect it to be that bad. Thanks!
ReplyDelete