Recent

Author Topic: Memory Layout of Dynamically sized Types?  (Read 1654 times)

MMarie

  • New Member
  • *
  • Posts: 49
  • Right, lets bodge this pisspot
    • Homepage
Memory Layout of Dynamically sized Types?
« on: May 02, 2025, 09:02:29 pm »
Hi,

Im currently working on a more low-level pascal project and I've been struggling in finding information about the memory layout of dynamic arrays.
I'm assuming that its the same as for Unicode Strings where, on x86_64 systems, there are 8 bytes for size and 8 bytes for the reference count before the actual data. Is this the same for, e.g. an array of Integer or an array of array of Integer? And does the size reflect the element count or the size in bytes? A link to the documentation that contains this information would be more than enough.

Thanks,
- Marie
i use arch btw

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12409
  • Debugger - SynEdit - and more
    • wiki
Re: Memory Layout of Dynamically sized Types?
« Reply #1 on: May 02, 2025, 09:13:20 pm »
As for the array "header" (where the size is stored) => there is no documentation, except for the compiler source.

And the format of that header (e.g. the count being 64 or 32bit) may differ per platform, or change between compiler versions (and if it hasn't yet, then it may in future).

You can search the source for
 fpc_dynarray_incr_ref

But be warned, it may change.


Nested array
Code: Pascal  [Select][+][-]
  1. T1 = array of array of word;

The outer is an array of other arrays => i.e. each entry is a variable of type "array [0..5] of word", essentially each entry in the outer array is a pointer to a separate inner array.

Each inner array can have a different length

PascalDragon

  • Hero Member
  • *****
  • Posts: 6396
  • Compiler Developer
Re: Memory Layout of Dynamically sized Types?
« Reply #2 on: May 02, 2025, 09:27:39 pm »
Im currently working on a more low-level pascal project and I've been struggling in finding information about the memory layout of dynamic arrays.

The only things relevant are that a dynamic array points to the first element of the array and that all elements are consecutive without any padding. Anything else is considered an implementation detail.

I'm assuming that its the same as for Unicode Strings where, on x86_64 systems, there are 8 bytes for size and 8 bytes for the reference count before the actual data. Is this the same for, e.g. an array of Integer or an array of array of Integer? And does the size reflect the element count or the size in bytes? A link to the documentation that contains this information would be more than enough.

The dynamic array header is the same for all types of dynamic arrays. And in multi-dimensional dynamic arrays the arrays are in fact arrays of pointers pointing to the other dynamic arrays.

MMarie

  • New Member
  • *
  • Posts: 49
  • Right, lets bodge this pisspot
    • Homepage
Re: Memory Layout of Dynamically sized Types?
« Reply #3 on: May 02, 2025, 10:31:04 pm »
Thanks for the responses!

Since I'm targeting x86_64 and pinning to a specific compiler version for this project isn't a bad idea anyways, this isn't too bad. The most important thing is that I can pass an address to a dynamic array (be that an array of Word or a dynamic string) starting at the first byte of the length specifier.

Another question popped up, although I could research this myself, I'll just ask it now: fixed size arrays, like an array [0..15] of Word or array [13..123] of Word don't store any information about their length in memory? (I wouldn't even care about the actual range, like that it starts at index 13 and ends at 123, but the amount of elements stored)..

Thanks again for your help!
« Last Edit: May 02, 2025, 10:33:51 pm by MMarie »
i use arch btw

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12409
  • Debugger - SynEdit - and more
    • wiki
Re: Memory Layout of Dynamically sized Types?
« Reply #4 on: May 03, 2025, 02:18:07 am »
Fixed size = "static arrays" indeed don't store any length info. It would be the same always.

Mind that you have
- static arrays
- dynamic arrays
- open arrays: procedure foo(openarray: array of word)
  (yes same syntax, different type)


And yes you can take pointer to any array element, and the address the next array element by incrementing the pointer.

With pointer math enabled
Code: Pascal  [Select][+][-]
  1. var p: pword;
  2. begin
  3.   p := @data[0];
  4.   inc(p); // next word in data / inc by the size of a word / because p is a typed pointer


Mind that "dynamic arrays" (sizeable arrays) are refcounted pointers, so passing them to a function only increases the refcount but does not copy them.

Static arrays are copied, and so are open arrays.
Except if you use "const" : procedure foo(const data: array of word);

"const" means that you can't edit the value.
"const" also means you must not change the variable that you passed in!

MMarie

  • New Member
  • *
  • Posts: 49
  • Right, lets bodge this pisspot
    • Homepage
Re: Memory Layout of Dynamically sized Types?
« Reply #5 on: May 04, 2025, 05:01:38 pm »
okay that clears it up, I guess the interface which I'm designing could just take in the pointer of a record type which could look something like this:

Code: Pascal  [Select][+][-]
  1. type TSysArrayArg = record
  2.     length: UInt64;
  3.     data: Pointer;
  4. end;
  5.  

And whenever an array is expected, you would (in any language that you wish to use the interface from), just initialise that record like this:

Code: Pascal  [Select][+][-]
  1. procedure Foo(arr: array of Integer);
  2. var
  3.     arg: TSysArrayArg;
  4. begin
  5.     arg.length := Length(arr) * sizeof(Integer);
  6.     arg.data := @arr[0];
  7.     SomeInterfaceCallWrapper(@arg);
  8. end;
  9.  
« Last Edit: May 04, 2025, 05:21:21 pm by MMarie »
i use arch btw

Thaddy

  • Hero Member
  • *****
  • Posts: 19268
  • Glad to be alive.
Re: Memory Layout of Dynamically sized Types?
« Reply #6 on: May 04, 2025, 05:27:57 pm »
I think you missed martin's point a bit:
Code: Pascal  [Select][+][-]
  1.  {$pointermath on}
  2. var p: TSomeBigOrSmallRecord;
  3. begin
  4.   p := @data[0];// data is an array of TSomeBigOrSmallRecord
  5.   inc(p); // next record in data / inc by the size of a word / because p is a typed pointer
See? It advances not per byte but by the size of that record.
objects are fine constructs. You can even initialize them with constructors.

MMarie

  • New Member
  • *
  • Posts: 49
  • Right, lets bodge this pisspot
    • Homepage
Re: Memory Layout of Dynamically sized Types?
« Reply #7 on: May 04, 2025, 05:40:50 pm »
Thaddy: I'm not sure what you are getting at, did I miss something that Martin said that would make my idea not work? I'm not really seeing the connection between the incrementation of a typed pointer and the memory layout of different array types. The whole context of my question is that I have an ABI where I want to pass an array-like data structure.
i use arch btw

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12409
  • Debugger - SynEdit - and more
    • wiki
Re: Memory Layout of Dynamically sized Types?
« Reply #8 on: May 04, 2025, 06:21:52 pm »
And whenever an array is expected,
Quote
Code: Pascal  [Select][+][-]
  1.     arg.length := Length(arr) * sizeof(Integer);
  2.     arg.data := @arr[0];
  3.     SomeInterfaceCallWrapper(@arg);

You can pass data to "SomeInterfaceCallWrapper" if that routine expects "TSysArrayArg"

But if "SomeInterfaceCallWrapper" expects any of open/static/dynamic array, then that will not work.

Your pointer points to the "length" in "TSysArrayArg" ....

- For dynamic array, the pointer must point to the first element. And in front of the first element there is the length and the ref-count (both in an undisclosed format).

- for open array, the pointer must also be the first element, but the length must be passed as a 2nd parameter (and that parameter is hidden from pascal code)

- for static arrays, there is no pointer. The address needs to be passed (and data will be copied). Well if you pass the pointer in the correct manner, it may be taken as the address. The length would not be passed as it is part of the declared type.


MMarie

  • New Member
  • *
  • Posts: 49
  • Right, lets bodge this pisspot
    • Homepage
Re: Memory Layout of Dynamically sized Types?
« Reply #9 on: May 04, 2025, 06:49:16 pm »
And whenever an array is expected,
Quote
Code: Pascal  [Select][+][-]
  1.     arg.length := Length(arr) * sizeof(Integer);
  2.     arg.data := @arr[0];
  3.     SomeInterfaceCallWrapper(@arg);

You can pass data to "SomeInterfaceCallWrapper" if that routine expects "TSysArrayArg"

But if "SomeInterfaceCallWrapper" expects any of open/static/dynamic array, then that will not work.


I should have written a definition of that function, yes in this context it expects a TSysArrayArg. And for the interface, the pointer must point to the "length" field.
i use arch btw

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12409
  • Debugger - SynEdit - and more
    • wiki
Re: Memory Layout of Dynamically sized Types?
« Reply #10 on: May 04, 2025, 10:33:56 pm »
I should have written a definition of that function, yes in this context it expects a TSysArrayArg. And for the interface, the pointer must point to the "length" field.

Then you are ok. 

Code: Pascal  [Select][+][-]
  1. @data[0]
gives a pointer to the first element. All other elements are continuous in memory.

For "array of record" the record usually aligns to a size dividable by 4 or 8. Use "sizeof" to find out. Or search for "packed records"


For multi-dim array, it depends on the type of array.

- dynamic array, the outer array is a list of pointer, then each pointer points to a stretch of memory with values.

- static arrays, the elements of all dimensions are flattened to one single stretch of memory.
  array [0..5, 1..10] has the 1st 10 elements, followed by the 2nd 10 element, followed by ...


d2010

  • Sr. Member
  • ****
  • Posts: 264
Re: Memory Layout of Dynamically sized Types?
« Reply #11 on: May 06, 2025, 09:49:45 am »
Hi,
Im currently working on a more low-level pascal project and I've been struggling in finding information about the memory layout of dynamic arrays.
- Marie
Why You  do no store all1838848words inside "AnsiString \" or Widestring?
The widestring/ansiString is top-portable with any Windows7Os.
If If AnsiString is leak of memory, then You can use WideChar, WideSTring?
Code: [Select]
Function MyWideNormalize(const S: Widestring): Widestring;
  {--------------------------------------------------------}
  Procedure InternalfoldNonDiacriticChar(Var aStr: WideString);
  Var i, j : integer;
  Begin
    for I := 1 to length(aStr) do begin
      j := ord(aStr[i]);
      case j of
        $0181: aStr[i] := widechar($0042);    // Æ_ -> B | LATIN CAPITAL LETTER B WITH HOOK -> LATIN CAPITAL LETTER B
        $0182: aStr[i] := widechar($0042);    // Æ, -> B | LATIN CAPITAL LETTER B WITH TOPBAR -> LATIN CAPITAL LETTER B
        $0187: aStr[i] := widechar($0043);    // Æ╪ -> C | LATIN CAPITAL LETTER C WITH HOOK -> LATIN CAPITAL LETTER C
        $0110: aStr[i] := widechar($0044);    // Ä_ -> D | LATIN CAPITAL LETTER D WITH STROKE -> LATIN CAPITAL LETTER D
        $018A: aStr[i] := widechar($0044);    // ÆS -> D | LATIN CAPITAL LETTER D WITH HOOK -> LATIN CAPITAL LETTER D
        $018B: aStr[i] := widechar($0044);    // Æ< -> D | LATIN CAPITAL LETTER D WITH TOPBAR -> LATIN CAPITAL LETTER D
        $0191: aStr[i] := widechar($0046);    // Æ` -> F | LATIN CAPITAL LETTER F WITH HOOK -> LATIN CAPITAL LETTER F
        $0193: aStr[i] := widechar($0047);    // Æ" -> G | LATIN CAPITAL LETTER G WITH HOOK -> LATIN CAPITAL LETTER G
        $01E4: aStr[i] := widechar($0047);    // Ç -> G | LATIN CAPITAL LETTER G WITH STROKE -> LATIN CAPITAL LETTER G
        $0126: aStr[i] := widechar($0048);    // Ä▌ -> H | LATIN CAPITAL LETTER H WITH STROKE -> LATIN CAPITAL LETTER H
        $0197: aStr[i] := widechar($0049);    // Æ- -> I | LATIN CAPITAL LETTER I WITH STROKE -> LATIN CAPITAL LETTER I
        $0198: aStr[i] := widechar($004B);    // Æ~ -> K | LATIN CAPITAL LETTER K WITH HOOK -> LATIN CAPITAL LETTER K
        $0141: aStr[i] := widechar($004C);    // Å_ -> L | LATIN CAPITAL LETTER L WITH STROKE -> LATIN CAPITAL LETTER L
        $019D: aStr[i] := widechar($004E);    // Æ_ -> N | LATIN CAPITAL LETTER N WITH LEFT HOOK -> LATIN CAPITAL LETTER N
        $0220: aStr[i] := widechar($004E);    // E  -> N | LATIN CAPITAL LETTER N WITH LONG RIGHT LEG -> LATIN CAPITAL LETTER N
        $00D8: aStr[i] := widechar($004F);    // A~ -> O | LATIN CAPITAL LETTER O WITH STROKE -> LATIN CAPITAL LETTER O
        $019F: aStr[i] := widechar($004F);    // ÆY -> O | LATIN CAPITAL LETTER O WITH MIDDLE TILDE -> LATIN CAPITAL LETTER O
        $01FE: aStr[i] := widechar($004F);    // Ç_ -> O | LATIN CAPITAL LETTER O WITH STROKE AND ACUTE -> LATIN CAPITAL LETTER O
        $01A4: aStr[i] := widechar($0050);    // Æ -> P | LATIN CAPITAL LETTER P WITH HOOK -> LATIN CAPITAL LETTER P
        $0166: aStr[i] := widechar($0054);    // Å▌ -> T | LATIN CAPITAL LETTER T WITH STROKE -> LATIN CAPITAL LETTER T
        $01AC: aStr[i] := widechar($0054);    // Ƭ -> T | LATIN CAPITAL LETTER T WITH HOOK -> LATIN CAPITAL LETTER T
        $01AE: aStr[i] := widechar($0054);    // Ær -> T | LATIN CAPITAL LETTER T WITH RETROFLEX HOOK -> LATIN CAPITAL LETTER T
        $01B2: aStr[i] := widechar($0056);    // Ʋ -> V | LATIN CAPITAL LETTER V WITH HOOK -> LATIN CAPITAL LETTER V
        $01B3: aStr[i] := widechar($0059);    // Æ3 -> Y | LATIN CAPITAL LETTER Y WITH HOOK -> LATIN CAPITAL LETTER Y
        $01B5: aStr[i] := widechar($005A);    // Ƶ -> Z | LATIN CAPITAL LETTER Z WITH STROKE -> LATIN CAPITAL LETTER Z
        $0224: aStr[i] := widechar($005A);    // E -> Z | LATIN CAPITAL LETTER Z WITH HOOK -> LATIN CAPITAL LETTER Z
        $0180: aStr[i] := widechar($0062);    // Æ_ -> b | LATIN SMALL LETTER B WITH STROKE -> LATIN SMALL LETTER B
        $0183: aStr[i] := widechar($0062);    // ƃ -> b | LATIN SMALL LETTER B WITH TOPBAR -> LATIN SMALL LETTER B
        $0253: aStr[i] := widechar($0062);    // É" -> b | LATIN SMALL LETTER B WITH HOOK -> LATIN SMALL LETTER B
        $0188: aStr[i] := widechar($0063);    // Æ^ -> c | LATIN SMALL LETTER C WITH HOOK -> LATIN SMALL LETTER C
        $0255: aStr[i] := widechar($0063);    // É -> c | LATIN SMALL LETTER C WITH CURL -> LATIN SMALL LETTER C
        $0111: aStr[i] := widechar($0064);    // Ä` -> d | LATIN SMALL LETTER D WITH STROKE -> LATIN SMALL LETTER D
        $018C: aStr[i] := widechar($0064);    // ÆO -> d | LATIN SMALL LETTER D WITH TOPBAR -> LATIN SMALL LETTER D
        $0221: aStr[i] := widechar($0064);    // E¡ -> d | LATIN SMALL LETTER D WITH CURL -> LATIN SMALL LETTER D
        $0256: aStr[i] := widechar($0064);    // É- -> d | LATIN SMALL LETTER D WITH TAIL -> LATIN SMALL LETTER D
        $0257: aStr[i] := widechar($0064);    // É- -> d | LATIN SMALL LETTER D WITH HOOK -> LATIN SMALL LETTER D
        $0192: aStr[i] := widechar($0066);    // Æ' -> f | LATIN SMALL LETTER F WITH HOOK -> LATIN SMALL LETTER F
        $01E5: aStr[i] := widechar($0067);    // Ç¥ -> g | LATIN SMALL LETTER G WITH STROKE -> LATIN SMALL LETTER G
        $0260: aStr[i] := widechar($0067);    // É  -> g | LATIN SMALL LETTER G WITH HOOK -> LATIN SMALL LETTER G
        $0127: aStr[i] := widechar($0068);    // Ä -> h | LATIN SMALL LETTER H WITH STROKE -> LATIN SMALL LETTER H
        $0266: aStr[i] := widechar($0068);    // É▌ -> h | LATIN SMALL LETTER H WITH HOOK -> LATIN SMALL LETTER H
        $0268: aStr[i] := widechar($0069);    // É" -> i | LATIN SMALL LETTER I WITH STROKE -> LATIN SMALL LETTER I
        $029D: aStr[i] := widechar($006A);    // E_ -> j | LATIN SMALL LETTER J WITH CROSSED-TAIL -> LATIN SMALL LETTER J
        $0199: aStr[i] := widechar($006B);    // ÆT -> k | LATIN SMALL LETTER K WITH HOOK -> LATIN SMALL LETTER K
        $0142: aStr[i] := widechar($006C);    // Å, -> l | LATIN SMALL LETTER L WITH STROKE -> LATIN SMALL LETTER L
        $019A: aStr[i] := widechar($006C);    // Æs -> l | LATIN SMALL LETTER L WITH BAR -> LATIN SMALL LETTER L
        $0234: aStr[i] := widechar($006C);    // E' -> l | LATIN SMALL LETTER L WITH CURL -> LATIN SMALL LETTER L
        $026B: aStr[i] := widechar($006C);    // É« -> l | LATIN SMALL LETTER L WITH MIDDLE TILDE -> LATIN SMALL LETTER L
        $026C: aStr[i] := widechar($006C);    // ɬ -> l | LATIN SMALL LETTER L WITH BELT -> LATIN SMALL LETTER L
        $026D: aStr[i] := widechar($006C);    // É- -> l | LATIN SMALL LETTER L WITH RETROFLEX HOOK -> LATIN SMALL LETTER L
        $0271: aStr[i] := widechar($006D);    // ɱ -> m | LATIN SMALL LETTER M WITH HOOK -> LATIN SMALL LETTER M
        $019E: aStr[i] := widechar($006E);    // Æz -> n | LATIN SMALL LETTER N WITH LONG RIGHT LEG -> LATIN SMALL LETTER N
        $0235: aStr[i] := widechar($006E);    // Eµ -> n | LATIN SMALL LETTER N WITH CURL -> LATIN SMALL LETTER N
        $0272: aStr[i] := widechar($006E);    // ɲ -> n | LATIN SMALL LETTER N WITH LEFT HOOK -> LATIN SMALL LETTER N
        $0273: aStr[i] := widechar($006E);    // É3 -> n | LATIN SMALL LETTER N WITH RETROFLEX HOOK -> LATIN SMALL LETTER N
        $00F8: aStr[i] := widechar($006F);    // A, -> o | LATIN SMALL LETTER O WITH STROKE -> LATIN SMALL LETTER O
        $01FF: aStr[i] := widechar($006F);    // Ç¿ -> o | LATIN SMALL LETTER O WITH STROKE AND ACUTE -> LATIN SMALL LETTER O
        $01A5: aStr[i] := widechar($0070);    // Æ¥ -> p | LATIN SMALL LETTER P WITH HOOK -> LATIN SMALL LETTER P
        $02A0: aStr[i] := widechar($0071);    // E  -> q | LATIN SMALL LETTER Q WITH HOOK -> LATIN SMALL LETTER Q
        $027C: aStr[i] := widechar($0072);    // ɼ -> r | LATIN SMALL LETTER R WITH LONG LEG -> LATIN SMALL LETTER R
        $027D: aStr[i] := widechar($0072);    // ɽ -> r | LATIN SMALL LETTER R WITH TAIL -> LATIN SMALL LETTER R
        $0282: aStr[i] := widechar($0073);    // E, -> s | LATIN SMALL LETTER S WITH HOOK -> LATIN SMALL LETTER S
        $0167: aStr[i] := widechar($0074);    // Å -> t | LATIN SMALL LETTER T WITH STROKE -> LATIN SMALL LETTER T
        $01AB: aStr[i] := widechar($0074);    // Æ« -> t | LATIN SMALL LETTER T WITH PALATAL HOOK -> LATIN SMALL LETTER T
        $01AD: aStr[i] := widechar($0074);    // Æ- -> t | LATIN SMALL LETTER T WITH HOOK -> LATIN SMALL LETTER T
        $0236: aStr[i] := widechar($0074);    // E -> t | LATIN SMALL LETTER T WITH CURL -> LATIN SMALL LETTER T
        $0288: aStr[i] := widechar($0074);    // E^ -> t | LATIN SMALL LETTER T WITH RETROFLEX HOOK -> LATIN SMALL LETTER T
        $028B: aStr[i] := widechar($0076);    // E< -> v | LATIN SMALL LETTER V WITH HOOK -> LATIN SMALL LETTER V
        $01B4: aStr[i] := widechar($0079);    // Æ' -> y | LATIN SMALL LETTER Y WITH HOOK -> LATIN SMALL LETTER Y
        $01B6: aStr[i] := widechar($007A);    // Æ -> z | LATIN SMALL LETTER Z WITH STROKE -> LATIN SMALL LETTER Z
        $0225: aStr[i] := widechar($007A);    // E¥ -> z | LATIN SMALL LETTER Z WITH HOOK -> LATIN SMALL LETTER Z
        $0290: aStr[i] := widechar($007A);    // E_ -> z | LATIN SMALL LETTER Z WITH RETROFLEX HOOK -> LATIN SMALL LETTER Z
        $0291: aStr[i] := widechar($007A);    // E` -> z | LATIN SMALL LETTER Z WITH CURL -> LATIN SMALL LETTER Z
        $025A: aStr[i] := widechar($0259);    // És -> ÉT | LATIN SMALL LETTER SCHWA WITH HOOK -> LATIN SMALL LETTER SCHWA
        $0286: aStr[i] := widechar($0283);    // E+ -> Eƒ | LATIN SMALL LETTER ESH WITH CURL -> LATIN SMALL LETTER ESH
        $01BA: aStr[i] := widechar($0292);    // ƺ -> E' | LATIN SMALL LETTER EZH WITH TAIL -> LATIN SMALL LETTER EZH
        $0293: aStr[i] := widechar($0292);    // E" -> E' | LATIN SMALL LETTER EZH WITH CURL -> LATIN SMALL LETTER EZH
        $0490: aStr[i] := widechar($0413);    // O_ -> D" | CYRILLIC CAPITAL LETTER GHE WITH UPTURN -> CYRILLIC CAPITAL LETTER GHE
        $0492: aStr[i] := widechar($0413);    // O' -> D" | CYRILLIC CAPITAL LETTER GHE WITH STROKE -> CYRILLIC CAPITAL LETTER GHE
        $0494: aStr[i] := widechar($0413);    // O" -> D" | CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK -> CYRILLIC CAPITAL LETTER GHE
        $0496: aStr[i] := widechar($0416);    // O- -> D- | CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER -> CYRILLIC CAPITAL LETTER ZHE
        $0498: aStr[i] := widechar($0417);    // O~ -> D- | CYRILLIC CAPITAL LETTER ZE WITH DESCENDER -> CYRILLIC CAPITAL LETTER ZE
        $048A: aStr[i] := widechar($0419);    // OS -> DT | CYRILLIC CAPITAL LETTER SHORT I WITH TAIL -> CYRILLIC CAPITAL LETTER SHORT I
        $049A: aStr[i] := widechar($041A);    // Os -> Ds | CYRILLIC CAPITAL LETTER KA WITH DESCENDER -> CYRILLIC CAPITAL LETTER KA
        $049C: aStr[i] := widechar($041A);    // Oo -> Ds | CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE -> CYRILLIC CAPITAL LETTER KA
        $049E: aStr[i] := widechar($041A);    // Oz -> Ds | CYRILLIC CAPITAL LETTER KA WITH STROKE -> CYRILLIC CAPITAL LETTER KA
        $04C3: aStr[i] := widechar($041A);    // Oƒ -> Ds | CYRILLIC CAPITAL LETTER KA WITH HOOK -> CYRILLIC CAPITAL LETTER KA
        $04C5: aStr[i] := widechar($041B);    // O. -> D> | CYRILLIC CAPITAL LETTER EL WITH TAIL -> CYRILLIC CAPITAL LETTER EL
        $04CD: aStr[i] := widechar($041C);    // O_ -> Do | CYRILLIC CAPITAL LETTER EM WITH TAIL -> CYRILLIC CAPITAL LETTER EM
        $04A2: aStr[i] := widechar($041D);    // O¢ -> D_ | CYRILLIC CAPITAL LETTER EN WITH DESCENDER -> CYRILLIC CAPITAL LETTER EN
        $04C7: aStr[i] := widechar($041D);    // O╪ -> D_ | CYRILLIC CAPITAL LETTER EN WITH HOOK -> CYRILLIC CAPITAL LETTER EN
        $04C9: aStr[i] := widechar($041D);    // O% -> D_ | CYRILLIC CAPITAL LETTER EN WITH TAIL -> CYRILLIC CAPITAL LETTER EN
        $04A6: aStr[i] := widechar($041F);    // O▌ -> DY | CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK -> CYRILLIC CAPITAL LETTER PE
        $048E: aStr[i] := widechar($0420);    // OZ -> D  | CYRILLIC CAPITAL LETTER ER WITH TICK -> CYRILLIC CAPITAL LETTER ER
        $04AA: aStr[i] := widechar($0421);    // Oª -> D¡ | CYRILLIC CAPITAL LETTER ES WITH DESCENDER -> CYRILLIC CAPITAL LETTER ES
        $04AC: aStr[i] := widechar($0422);    // O¬ -> D¢ | CYRILLIC CAPITAL LETTER TE WITH DESCENDER -> CYRILLIC CAPITAL LETTER TE
        $04B2: aStr[i] := widechar($0425);    // O² -> D¥ | CYRILLIC CAPITAL LETTER HA WITH DESCENDER -> CYRILLIC CAPITAL LETTER HA
        $04B3: aStr[i] := widechar($0425);    // O3 -> D¥ | CYRILLIC SMALL LETTER HA WITH DESCENDER -> CYRILLIC CAPITAL LETTER HA
        $0491: aStr[i] := widechar($0433);    // O` -> D3 | CYRILLIC SMALL LETTER GHE WITH UPTURN -> CYRILLIC SMALL LETTER GHE
        $0493: aStr[i] := widechar($0433);    // O" -> D3 | CYRILLIC SMALL LETTER GHE WITH STROKE -> CYRILLIC SMALL LETTER GHE
        $0495: aStr[i] := widechar($0433);    // O -> D3 | CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK -> CYRILLIC SMALL LETTER GHE
        $0497: aStr[i] := widechar($0436);    // O- -> D | CYRILLIC SMALL LETTER ZHE WITH DESCENDER -> CYRILLIC SMALL LETTER ZHE
        $0499: aStr[i] := widechar($0437);    // OT -> D· | CYRILLIC SMALL LETTER ZE WITH DESCENDER -> CYRILLIC SMALL LETTER ZE
        $048B: aStr[i] := widechar($0439);    // O< -> D1 | CYRILLIC SMALL LETTER SHORT I WITH TAIL -> CYRILLIC SMALL LETTER SHORT I
        $049B: aStr[i] := widechar($043A);    // O> -> Dº | CYRILLIC SMALL LETTER KA WITH DESCENDER -> CYRILLIC SMALL LETTER KA
        $049D: aStr[i] := widechar($043A);    // O_ -> Dº | CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE -> CYRILLIC SMALL LETTER KA
        $049F: aStr[i] := widechar($043A);    // OY -> Dº | CYRILLIC SMALL LETTER KA WITH STROKE -> CYRILLIC SMALL LETTER KA
        $04C4: aStr[i] := widechar($043A);    // O, -> Dº | CYRILLIC SMALL LETTER KA WITH HOOK -> CYRILLIC SMALL LETTER KA
        $04C6: aStr[i] := widechar($043B);    // O+ -> D» | CYRILLIC SMALL LETTER EL WITH TAIL -> CYRILLIC SMALL LETTER EL
        $04CE: aStr[i] := widechar($043C);    // OZ -> D¼ | CYRILLIC SMALL LETTER EM WITH TAIL -> CYRILLIC SMALL LETTER EM
        $04A3: aStr[i] := widechar($043D);    // O£ -> D½ | CYRILLIC SMALL LETTER EN WITH DESCENDER -> CYRILLIC SMALL LETTER EN
        $04C8: aStr[i] := widechar($043D);    // O^ -> D½ | CYRILLIC SMALL LETTER EN WITH HOOK -> CYRILLIC SMALL LETTER EN
        $04CA: aStr[i] := widechar($043D);    // OS -> D½ | CYRILLIC SMALL LETTER EN WITH TAIL -> CYRILLIC SMALL LETTER EN
        $04A7: aStr[i] := widechar($043F);    // O -> D¿ | CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK -> CYRILLIC SMALL LETTER PE
        $048F: aStr[i] := widechar($0440);    // O_ -> Ñ_ | CYRILLIC SMALL LETTER ER WITH TICK -> CYRILLIC SMALL LETTER ER
        $04AB: aStr[i] := widechar($0441);    // O« -> Ñ_ | CYRILLIC SMALL LETTER ES WITH DESCENDER -> CYRILLIC SMALL LETTER ES
        $04AD: aStr[i] := widechar($0442);    // O- -> Ñ, | CYRILLIC SMALL LETTER TE WITH DESCENDER -> CYRILLIC SMALL LETTER TE
        $04B9: aStr[i] := widechar($0447);    // O1 -> Ñ╪ | CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE -> CYRILLIC SMALL LETTER CHE
        $047C: aStr[i] := widechar($0460);    // Ѽ -> Ñ  | CYRILLIC CAPITAL LETTER OMEGA WITH TITLO -> CYRILLIC CAPITAL LETTER OMEGA
        $047D: aStr[i] := widechar($0461);    // ѽ -> Ñ¡ | CYRILLIC SMALL LETTER OMEGA WITH TITLO -> CYRILLIC SMALL LETTER OMEGA
        $04B0: aStr[i] := widechar($04AE);    // O° -> Or | CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE -> CYRILLIC CAPITAL LETTER STRAIGHT U
        $04B1: aStr[i] := widechar($04AF);    // O± -> O_ | CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE -> CYRILLIC SMALL LETTER STRAIGHT U
        $04B6: aStr[i] := widechar($04BC);    // O -> O¼ | CYRILLIC CAPITAL LETTER CHE WITH DESCENDER -> CYRILLIC CAPITAL LETTER ABKHASIAN CHE
        $04B7: aStr[i] := widechar($04BC);    // O· -> O¼ | CYRILLIC SMALL LETTER CHE WITH DESCENDER -> CYRILLIC CAPITAL LETTER ABKHASIAN CHE
        $04B8: aStr[i] := widechar($04BC);    // O, -> O¼ | CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE -> CYRILLIC CAPITAL LETTER ABKHASIAN CHE
        $04BE: aStr[i] := widechar($04BC);    // O_ -> O¼ | CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER -> CYRILLIC CAPITAL LETTER ABKHASIANCHE
        $04BF: aStr[i] := widechar($04BC);    // O¿ -> O¼ | CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER -> CYRILLIC CAPITAL LETTER ABKHASIAN CHE
        $04CB: aStr[i] := widechar($04BC);    // O< -> O¼ | CYRILLIC CAPITAL LETTER KHAKASSIAN CHE -> CYRILLIC CAPITAL LETTER ABKHASIAN CHE
        $04CC: aStr[i] := widechar($04BC);    // OO -> O¼ | CYRILLIC SMALL LETTER KHAKASSIAN CHE -> CYRILLIC CAPITAL LETTER ABKHASIAN CHE
      end;
    end;
  End;

Var i,j: integer;
    TmpWideStr: WideString;

Begin
  TmpWideStr := ALWideExpandLigatures(ALWideRemoveDiacritic(Widelowercase(s)));
  SetLength(Result,length(TmpWideStr));
  j := 0;
  For i := 1 to length(TmpWideStr) do begin
    if IsCharAlphaNumericW(TmpWideStr[i]) then begin
      inc(j);
      result[j] := TmpWideStr[i];
    end
    else if ((j >= 1) and
             (result[j] <> '-')) then begin
      inc(j);
      result[j] := '-';
    end;
  end;
  While (J > 0) and (result[j] = '-') do dec(j);
  setlength(result,j);
  InternalfoldNonDiacriticChar(result);
end;
 

« Last Edit: May 06, 2025, 09:52:10 am by d2010 »

cdbc

  • Hero Member
  • *****
  • Posts: 2814
    • http://www.cdbc.dk
Re: Memory Layout of Dynamically sized Types?
« Reply #12 on: May 06, 2025, 09:56:45 am »
Hi
@d2010: Wow - That's just plain USELESS!!!  == Stop trolling and wasting peoples time.
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

 

TinyPortal © 2005-2018