IonicWind Software

IWBasic => General Questions => Topic started by: tbohon on June 20, 2007, 10:38:29 AM

Title: Strings vs IStrings
Post by: tbohon on June 20, 2007, 10:38:29 AM
Am using ISTRINGs for the first time and keep getting an error.  It was working just fine when I defined the variables as STRINGs but the strings I'm using are well beyond the 255 byte length.

I declare three working variables and make them global:
DEF wvar1, wvar2, wvar3:istring

GLOBAL wvar1
                GLOBAL wvar2
                GLOBAL wvar3


Next, I clear them to blank (which may be the issue?):

wvar1 = ""
                wvar2 = ""
                wvar3 = ""


Next, I copy a RT control's contents into one of the variables:

rv = CONTROLCMD w,8,@RTSAVE,wvar1,0


after which I start parsing the string, copying pieces of wvar1 to wvar2. 

I never get to the #DEBUGPRINT statements right before the parsing section of the code.  Instead, I get the following error in the DEBUG window:

Starting debug session...
Loading DLL: ntdll.dll
Loading DLL: C:\WINDOWS\system32\kernel32.dll
Loading DLL: C:\WINDOWS\system32\USER32.DLL
Loading DLL: C:\WINDOWS\system32\GDI32.dll
Loading DLL: C:\WINDOWS\system32\COMDLG32.DLL
Loading DLL: C:\WINDOWS\system32\SHLWAPI.dll
Loading DLL: C:\WINDOWS\system32\ADVAPI32.dll
Loading DLL: C:\WINDOWS\system32\RPCRT4.dll
Loading DLL: C:\WINDOWS\system32\msvcrt.dll
Loading DLL: C:\WINDOWS\system32\COMCTL32.dll
Loading DLL: C:\WINDOWS\system32\SHELL32.dll
Loading DLL: C:\WINDOWS\system32\OLE32.DLL
Loading DLL: C:\WINDOWS\system32\CRTDLL.DLL
Loading DLL: C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b641W
Loading DLL: C:\WINDOWS\system32\uxtheme.dll
Loading DLL: C:\WINDOWS\system32\riched32.dll
Loading DLL: C:\WINDOWS\system32\RICHED20.dll
First chance exception: Address 0x7C910466 Access Violation.
Final chance exception: Address 0x7C910466 Access Violation.
First chance exception: Address 0x7C910466 Access Violation.
The program 'C:\EBasicWork\parserv3.exe' exited with code: 1


Comments/thoughts/pointers appreciated - I've read the help files and can't see what I'm doing wrong.

Tnx in advance.

Tom
Title: Re: Strings vs IStrings
Post by: sapero on June 20, 2007, 11:01:00 AM
All your strings are ONE byte in size, that is, a ISTRING is an alias to CHAR (also one byte of memory), but with build-in 'string' functionality.
Check this out:
DEF wvar1, wvar2, wvar3:istring
print &wvar1 - &wvar2 /*subtract addresses of two variables*/
print &wvar2 - &wvar3

The above code is equal to
istring wvar1
and (from alias perspective) this is equal to
char wvar1
where wvar1 allocates only one byte of memory. Now, you need array of bytes for your strings, which can be done using [] operator
char wvar1[256] /*256 byte memory space*/
After replacing 'char' with 'istring' you are able to use this variable as standard string.

In your code you got an Access Violation exception.
Why? @RTSAVE command has overwriten all your local variables, the return address where current function should return,
and the (first pushed) pointer to 'rv' variable, where the @RTSAVE command should store the result. This was the real buffer overflow :)

If you use ISTRING's, always define the dimension:DEF wvar1[1024], wvar2[32], wvar3[2048]:istring

Using @RTSAVE to store text in a string is very unsafe, your unable to crop the text to destination buffer length.
Option 1:
POINTER lpStr : settype lpStr, string
lpStr = GetControlText(w, 8)
' do something: print *lpStr
FreeHeap(lpStr) /* free the string from memory */

Option 2:
const WM_GETTEXTLENGTH = 0xe
int required
required = SendMessage(w, WM_GETTEXTLENGTH, 0, 0, 8/*control id*/) + 1
POINTER lpStr
lpStr = new(char, required)
settype lpStr, string
CONTROLCMD w,8, @RTSAVE, *lpStr,0
' do something: print *lpStr
delete lpStr
Title: Re: Strings vs IStrings
Post by: tbohon on June 20, 2007, 02:52:13 PM
Arrrrrrrrghhhhhhhhhhhhhhhh!   :(  I hate it when I do 'stoopid' things ...  :) 

I'll rewrite the routine - not that much work - and press on.

Thanks, Sapero!!!!!

Tom
Title: Re: Strings vs IStrings
Post by: tbohon on June 22, 2007, 07:46:58 PM
OK, recoded the routine and it works in test.  However, when I use this program 'for real', I'm not going to have any idea how long the input string is going to be ... it's HL7 message traffic from our hospital network and it could be 30-40 characters or several thousand - some of the transcribed documents go on forever and ever.

One thought was to dimension the strings as large as I can (and I'm not sure how large that is ... ???) and then trim it once I've loaded the string.  As it currently stands, I'm pasting the string from the clipboard, cleaning up the Unix line endings by going through it and eliminating all chr(10) and chr(13) ... which means that I'm also removing the end-of-string cr/lf as well so don't know how I'll know when I've reached the end of the string if I dimension it as big as possible.

Another idea I had was to grow the string dynamically ... but that seems to be a bit complicated and probably difficult to implement.

Any suggestions here ... ?
Title: Re: Strings vs IStrings
Post by: LarryMc on June 22, 2007, 09:00:33 PM
My answer will only make sense if I'm understanding your problem correctly:

You have a richedit control that you want to read what it contains; store in a variable; and strip out the CRLF characters.

I have no idea how you are capturing the information that you are wanting to paste in the RE but maybe the following will help you.

By default a RE control will only hold 32767 bytes.  You can increase that by using:
CONTROLCMD  window | dialog, ID, @RTSETLIMITTEXT, length

You can determine how much text is currently in a RE control by using:
length  = CONTROLCMD (window | dialog, ID, @RTGETTEXTLENGTH)


you can create a static istring variable to some max size or, based upon the RTGETTEXTLENGTH command you can
create a ptr to a NEW(char,length+1)

you can then read the contents of the RE into that memory location

then you can created a 2nd ptr to another NEW(char,length+1)

then, in while end while loop you can read each char of the 1st ptrs memory and if it is a keeper then write it to the 2nd ptrs location.

the data in the 2nd ptr location shorter the created length(because you stripped out characters)

Then you can do whatever you need to with the data.

Another way is to write the RE contents to a file instead of a variable; open the file and use the LEN(file) command to create a ptr to a NEW(char,len(file)+1) and read the file a char at a time and keep only those characters you want in the ptr location.

Hope this makes sense and that it helps you.

Larry
Title: Re: Strings vs IStrings
Post by: Ionic Wind Support Team on June 22, 2007, 09:07:46 PM
(larry was faster typing than I)

Don't be afraid to use more than one memory buffer to get the job done. Dynamic strings are easy once you get the hang of it.

pointer mystring
mystring = new(char, length+1)
rv = CONTROLCMD w,8,@RTSAVE,#<STRING>mystring,0
...
delete mystring


If you are using a rich edit control and pasting the text into try

1.  Allocate memory large enough to hold the pasted text.  Use @RTGETTEXTLENGTH.  Save the text into that buffer as I did above.
2. use INSTR to find each end of line, keeping track of the position.  INSTR has an optional starting position that you can use to advance through the primary buffer, remember to add 2 to this pos after each iteration to skip the found end of line.
3. Use MID$ to copy the substring to a new allocated buffer using the previous and current postions.
4. repeat until done.

I can code it for you, or you can give it a shot first ;)

Paul.
Title: Re: Strings vs IStrings
Post by: tbohon on June 24, 2007, 06:57:34 PM
Thanks, guys - and thank you, Paul, for the coding offer.  However, I won't learn a darned thing if I don't muddle through this myself so I'm going to do just that - muddle  ;)

FYI, I have the remainder of the routine working and can pick out the segments - the 255 character length of the string in which I'm storing the RE contents (which come from the clipboard, BTW) is what was slowing me down.  I'm going to work on it a bit more tomorrow (Monday) - I'm a 'ham' (amateur radio operator) and just finished a 30+ hour stint during our annual Field Day and I know better than to make any major decisions or even look at code as tired as I am.

Appreciate it!

Tom