Jump to content
Developer Wiki and Function Reference Links ×

Function (or procedure) that returns dynarray[]of char


Paolo

Recommended Posts

I am trying to develop an SVG reader in Vectorscript, but I am at a stake because of the impossibility to manage functions or procedures that calculate and return strings that may have more than 255 chars.
Having to do with SVG commands like this…

<path fill="none" stroke="#000000" stroke-width="0.238" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-dasharray="1,1" d="
    M47.506,645.356c0.099,0,0.197-0.049,0.296-0.049c0.098,0,0.196-0.05,0.295-0.099s0.197-0.049,0.296-0.099
    c0.098-0.049,0.196-0.099,0.246-0.147c0.098-0.049,0.196-0.099,0.246-0.147c0.098-0.05,0.147-0.099,0.246-0.148
    c0.099-0.049,0.147-0.147,0.246-0.196c0.049-0.05,0.147-0.148,0.196-0.197c0.05-0.049,0.148-0.147,0.197-0.246
    s0.099-0.147,0.197-0.246c0.049-0.099,0.098-0.147,0.147-0.246c0.049-0.099,0.099-0.197,0.147-0.295
    c0.05-0.148,0.147-0.296,0.197-0.493c0.049-0.147,0.099-0.295,0.196-0.492c0.05-0.147,0.099-0.345,0.148-0.492
    c0.049-0.196,0.147-0.442,0.196-0.64c0-0.05,0.05-0.147,0.05-0.197c0-0.049,0.049-0.147,0.049-0.197
    c0-0.049,0.05-0.147,0.05-0.196c0-0.05,0.049-0.147,0.049-0.197c0-0.049,0-0.049,0-0.099c0-0.049,0-0.049,0-0.098
    c0-0.05,0-0.05,0-0.099c0-0.05,0-0.05-0.049-0.099c0-0.049-0.05-0.049-0.05-0.049l-0.049-0.05l-0.05-0.049
    c-0.049,0-0.049-0.05-0.099-0.05c-0.049,0-0.049,0-0.098,0c-0.05,0-0.05,0-0.099,0c-0.05,0-0.05,0-0.099,0s-0.049,0-0.099,0.05
    c-0.049,0-0.049,0.049-0.099,0.049l-0.049,0.05l-0.049,0.049c0,0-0.05,0.049-0.05,0.099c0,0.049-0.049,0.099-0.049,0.147
    s-0.05,0.099-0.05,0.147c0,0.05-0.049,0.099-0.049,0.148c0,0.049-0.049,0.098-0.049,0.147c-0.05,0.099-0.099,0.246-0.197,0.345
    c-0.05,0.099-0.099,0.246-0.197,0.345c-0.099,0.147-0.147,0.246-0.246,0.394s-0.147,0.246-0.246,0.394s-0.197,0.246-0.246,0.345
    s-0.147,0.147-0.197,0.246c-0.049,0.099-0.147,0.147-0.196,0.197c-0.05,0.049-0.147,0.147-0.197,0.196
    c-0.049,0.05-0.147,0.148-0.246,0.197s-0.147,0.099-0.246,0.147c-0.099,0.05-0.147,0.099-0.246,0.148
    c-0.099,0.049-0.197,0.098-0.246,0.147c-0.099,0.049-0.197,0.099-0.296,0.147c-0.147,0.049-0.295,0.099-0.442,0.147
    c-0.147,0.05-0.296,0.099-0.443,0.148c-0.147,0.049-0.295,0.098-0.443,0.147c-0.098,0.049-0.196,0.049-0.295,0.099
    c-0.099,0-0.197,0.049-0.296,0.049c-0.049,0-0.147,0.049-0.196,0.049c-0.05,0-0.147,0-0.197,0.05c-0.049,0-0.147,0-0.196,0.049
    c-0.05,0-0.148,0-0.197,0.05c-0.05,0-0.05,0-0.099,0s-0.049,0-0.099,0.049c-0.049,0-0.049,0.049-0.049,0.049l-0.05,0.05
    l-0.049,0.049c0,0.05-0.049,0.05-0.049,0.099s0,0.049,0,0.099c0,0.049,0,0.049,0,0.099c0,0.049,0,0.049,0,0.098
    c0,0.05,0,0.05,0.049,0.099c0,0.05,0.049,0.05,0.049,0.099l0.05,0.049l0.049,0.05c0,0,0.05,0.049,0.099,0.049s0.049,0,0.099,0.05
    c0.049,0,0.049,0,0.099,0c0.049,0,0.099,0,0.147,0s0.099,0,0.147,0c0.05,0,0.099,0,0.147,0c0.05,0,0.099,0,0.148,0
    c0.147,0,0.295,0,0.442,0c0.148,0,0.296,0,0.443,0s0.345,0,0.492-0.05c0.147,0,0.345-0.049,0.492-0.049
    C47.161,645.406,47.359,645.406,47.506,645.356z”/>

… that goes very beyond the 255 chars strings limit, I had necessarily to substitute functions returning strings into functions returning dynarray[]of char, but this is FORBIDDEN.
So I tried with procedures returning dynarray[]of char as VAR (this is allowed) but I found strange behaviors.

 

For example, the following script takes the constant string (this is a short string, just for instance).
The first procedure extracts the substring starting from 'points="' and the subsequent '"'.
The second procedure replaces the commas with spaces.
Both procedure uses the same VAR s:string declared.

procedure test;
const
polygon = '<polygon  points="35.938,135.145 36.233,140.511     36.971,140.511 36.971,135.145     "/>’; 
{this is just an example of SVG line, this is < 256 chars, but this is a special case}
    
var
s: dynarray[]of char; {declare the VAR I'll use later as value returned from procedures}
    
{*********************** scanPolyPoints **********************}
{return the substring between 'points="' and '"', I'll split these points later}
procedure scanPolyPoints(parameter: string; line: DYNARRAY[] OF CHAR; var r:DYNARRAY[] OF CHAR);
var
index1, index2: integer;
temp: DYNARRAY[] OF CHAR;
begin
{search the position of 'parameter='}
index1 := Pos(parameter, line)+1+len(parameter);
temp := copy(line, index1, len(line)-index1); {remaining string} 
{search the position of '"' in the remaining string}
index2 := Pos('"', temp);
temp := copy(temp, 1, index2-1); {here I have only the string composed by points} 
r := temp; {set the answer r}
end;

{*********************** replaceCommas **********************}
{substitute each comma with a space and each minus signs with ' -'}
{in the SVG (generated by Adobe Illustrator), the path numbers are separated by a ',' or by '-' or by a space}
{whenever you find a '-', the ',' is omitted!}
procedure replaceCommas(source:dynarray[]of char; var dest: dynarray[]of char);
var
i:integer;
temp: string;
begin
temp := '';
for i:=1 to len(source) do
begin
if source[i] = ',' then temp:=Concat(temp,' ')
    else if source[i] = '-' then temp:=Concat(temp,' -')
    else temp:=Concat(temp,source[i])
end;
dest := temp;
end;
begin
s := ''; {init}
writeln(polygon); {write the input string to the standard output}
scanPolyPoints(' points=', polygon, s); {first procedure}
writeln(s); {write the resulting "s" string to the standard output}
{Now I use the variable s both as parameter and resulting var}
replaceCommas(s, s); {second procedure, commas should be replaced by spaces}
writeln(s); {but NO! It's unchanged}
{test it with a constant string as parameter…}
replaceCommas('.,.,.,.,.,.,.,', s);
writeln(s); {…it works!}
end;
run(test);    

The resulting output is the following:

<polygon  points="35.938,135.145 36.233,140.511             36.971,140.511 36.971,135.145         "/>
35.938,135.145 36.233,140.511             36.971,140.511 36.971,135.145         
35.938,135.145 36.233,140.511             36.971,140.511 36.971,135.145         
. . . . . . . 

As you can see, the first procedure works (line 2), the second no (line 3 has still commas in place!). While the constant string has the commas removed (line 4).

Where is the problem and, most of all, is there a solution?

 

Thank you for any help.

Paolo Marcuccetti

 


 

Link to comment

 replaceCommas( s, s ) is a bit irregular. You are essentially passing both a copy of and a reference to the same variable, which is unnecessary, as the VAR (reference) syntax gives you both read and write access. 

 

Your code can be much simpler if the arguement is a single VAR dynarray of char:

 

For i := 1 to len(inStr) do begin

     if inStr = ‘,’ then

          inStr := ‘ ‘

end;

 

Sometimes dynarrays of chr need a sort of reset if the length changes. Str := Concat(str) will work. 

 

All that said, I highly recommend looking into python for this script. If you’re new to VS, python is going to be much easier to learn. If not, most of the vs functions you’re familiar with still work in python — just double check the syntax. 

 

Python is is designed for parsing data, so you won’t have to reinvent the wheel for iterating, extracting, and replacing. I also believe there are existing svg modules for python that you can take advantage of. 

  • Like 1
Link to comment

I only took a really quick look, but I don't see where you are storing the Temp back into the original string/array.

 

I think you need to DELETE the original command and INSERT the temp at the same location.

 

Python is certainly better at string manipulation, but this is well within the capability of VS.

Link to comment

Here's the script with the var passed as reference.

It works only when you apply the trick

s:=concat('', s);

The result is a list of valid real numbers delimited by spaces, to be splitter later:

35.938 135.145 36.233 140.511 36.971 140.511 36.971 135.145 145

 

I'll try to port these in python. I do not know python, while I am an old Vectorscript developer.

I hope python has a better array management (count, split etc.) as any modern language should.

procedure trim;
const
testString = '<polygon  points="35.938,135.145 36.233,140.511     36.971,140.511 36.971,135.145     "/>';
var
r: dynarray[]of char;
procedure trimNotInList(list: DYNARRAY[] OF CHAR; VAR s: dynarray[]of char);
VAR
    i : INTEGER;
    t : dynarray[]of char;
BEGIN
    t := s;
    i := 1;
    WHILE i <= Len(t) DO
        IF (Pos(Copy(t, i, 1), list) = 0) THEN
            Delete(t, i, 1)
        ELSE
            i := i + 1;
    s := t;
END;
procedure runOfSpacesIntoOne(var s:dynarray[]of char);
var
i:integer;
temp: dynarray[] of char;
begin
s := Concat('',s); {pseudo reset}
temp := '';
for i:=1 to len(s) do
begin
temp:=concat(temp, s[i]);
if (i>1) then
    if (s[i]=' ') and (s[i-1]=' ') then 
        temp := copy(temp, 1, len(temp)-1);
end;
s := temp;
end;
procedure trimSpaces(var s:dynarray[] of char);
var
i, ti, te:integer;
begin
s := Concat('',s); {pseudo reset}
    for i:=1 to len(s) do
    begin
        ti :=i;
        if s[i] <> ' ' then i := len(s); {esco dal for}
    end;
    for i:=len(s) downto 1 do
    begin
        te := i;
        if s[i] <> ' ' then i := 1; {esco dal for}
    end;
s := copy(s, ti, te-ti+1);
end;
procedure replaceCommas(var s: dynarray[]of char);
var
i:integer;
temp: string;
begin
s := Concat('',s); {pseudo reset}
temp := '';
for i:=1 to len(s) do
begin
if s[i] = ',' then temp:=Concat(temp,' ')
    else if s[i] = '-' then temp:=Concat(temp,' -')
    else temp:=Concat(temp,s[i])
end;
s := temp;
end;
{*********************** scanPolyPoints **********************}
{return the substring between 'points="' and '"', I'll split these points later}
procedure scanPolyPoints(parameter: string; line: DYNARRAY[] OF CHAR; var r:DYNARRAY[] OF CHAR);
var
index1, index2: integer;
temp: DYNARRAY[] OF CHAR;
begin
index1 := Pos(parameter, line)+1+len(parameter);
temp := copy(line, index1, len(line)-index1);
index2 := Pos('"', temp);
temp := copy(temp, 1, index2-1);
temp := concat('', temp);
trimNotInList('0123456789+-,. ',temp);
replaceCommas(temp);
runOfSpacesIntoOne(temp);
r := temp; 
trimSpaces(r);
end;

begin
r:=teststring;
scanPolyPoints(' points=', teststring, r);
writeln(r);
end;
run(trim);

 

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...