Recent

Author Topic: Substring from memory Stream?  (Read 2849 times)

daveinhull

  • Sr. Member
  • ****
  • Posts: 297
  • 1 divided by nothing must still be 1!
Substring from memory Stream?
« on: December 18, 2018, 04:28:58 pm »
Hi,

I have a memory stream and I'd like to extract a substring found between two other substrings. I can get into a String and usee Pos, but I need to find the second substring after and not from the start again which is what I think Pos does. A bit like VBA SubStr which has a start from parameter?

I could code this all up, but thought just to ask if there is anything already that will do this?

Thanks
Dave
Version #:1.8.4 Date 2019-01-08 FPC Version: 3.0.4 and SVN Revision 57972 for x86_64-win64-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Substring from memory Stream?
« Reply #1 on: December 18, 2018, 04:32:04 pm »
Yes. Examine the type helper for strings in sysutils.
Specialize a type, not a var.

silvioprog

  • Newbie
  • Posts: 6
Re: Substring from memory Stream?
« Reply #2 on: December 18, 2018, 04:56:48 pm »
Hi Dave,

I have a memory stream and I'd like to extract a substring found between two other substrings. I can get into a String and usee Pos, but I need to find the second substring after and not from the start again which is what I think Pos does.

A minimal example:

Code: Pascal  [Select][+][-]
  1. const
  2.   S = 'abc123abc456';
  3. begin
  4.   WriteLn(S.SubString(S.IndexOf('abc', 6))); // prints abc456
  5. end;

Cheers

daveinhull

  • Sr. Member
  • ****
  • Posts: 297
  • 1 divided by nothing must still be 1!
Re: Substring from memory Stream?
« Reply #3 on: December 18, 2018, 05:03:35 pm »
@silioprog, thanks for the suggestion, but the problem is that I don't know how many characters I need until I look for a second string after the first. I can't look again because the second string might occur before the first but I don't want that won.

@Thaddy, many thanks that did it  :)
Version #:1.8.4 Date 2019-01-08 FPC Version: 3.0.4 and SVN Revision 57972 for x86_64-win64-win32/win64

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Substring from memory Stream?
« Reply #4 on: December 18, 2018, 06:32:26 pm »
You could always use PosEx() which allows you to (re-)start the search from an index rather than the beginning. Or if you're looking for more power, look for SearchBuf().

Both are rather well documented in the RTL help file: look for unit StrUtils
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Substring from memory Stream?
« Reply #5 on: December 18, 2018, 11:40:11 pm »
StrPos and PosEx both will work..

StrPos uses Pointers where when you find your searched item it returns the pointer of the beginning of the found string.

you can move along to the next one by adding the length of the string to this pointer and reuse it to find the next string of said name
PosEx will also work but uses index value instead.

 It depends on how you are capturing the data, in bulk or in a serial method. The serial method would require you to build a string as you
read it.
The only true wisdom is knowing you know nothing

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Substring from memory Stream?
« Reply #6 on: December 19, 2018, 12:53:14 am »
Could this be made to work?

Code: Pascal  [Select][+][-]
  1. uses strutils;
  2.  
  3. {$R *.lfm}
  4.  
  5. // Returns string from s that is between s1 and s2
  6. function StrBetween(const s,s1,s2: string): string;
  7. var p1,p2: integer;
  8. begin
  9.   p1:=pos(s1,s); p2:=pos(s2,s);
  10.   if (p1>0) and (p2>0) then
  11.     StrBetween:=copy(s,p1+length(s1),p2-p1-length(s1))
  12.   else StrBetween:='';
  13. end;
  14.  
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Substring from memory Stream?
« Reply #7 on: December 19, 2018, 02:04:33 am »
I had some time so I made a little example. All you have to do is read the data from the stream to a String; then call something like:

Code: Pascal  [Select][+][-]
  1. (*
  2. uses
  3.   StrUtils;
  4. *)
  5.  
  6. { Returns substring between First and Last in AStr }
  7. function GetStrBetween(AStr, First, Last: String): String;
  8. var
  9.   FPos,
  10.   LPost,
  11.   Count: Integer
  12.  
  13.   { A quick sanity check }
  14.   function ChecksOK: Boolean;
  15.   begin
  16.     Result := (AStr <> '') and
  17.               (First <> '') and
  18.               (Last <> '');
  19.   end;
  20.  
  21. begin
  22.   Result := '';
  23.   if ChecksOK then begin
  24.     FPos := Pos(First, AStr);
  25.     if FPos >0 then begin
  26.       Inc(FPos, Length(First));
  27.       LPos := PosEx(Last, AStr, FPos);
  28.       if LPos > FPos then begin
  29.         Count := Lpos - FPos; {< This may be off by one }
  30.         Result := AnsiMidStr(AStr, FPos, Count);
  31.       end;
  32.     end;
  33.   end;
  34. end;

I only had a little time so it's untested, sorry!
« Last Edit: December 19, 2018, 02:07:02 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

daveinhull

  • Sr. Member
  • ****
  • Posts: 297
  • 1 divided by nothing must still be 1!
Re: Substring from memory Stream?
« Reply #8 on: December 19, 2018, 11:16:33 pm »
Hey guys,

Many thanks for all your ideas and code. I did solve it using type helper for strings and a simple string copy function . Also read the data from the web into a string rather than a stream, so ended up quite simple.

Thanks again
Dave
Version #:1.8.4 Date 2019-01-08 FPC Version: 3.0.4 and SVN Revision 57972 for x86_64-win64-win32/win64

 

TinyPortal © 2005-2018