Maximum length of a String and return value?

 
I have a function/subroutine that returns a string.

The string could range from a few bytes to almost 200Kbytes.

Initial testing shows that if the string is small (less than 200), the function works properly.
but when the sting is big (>4K ~ 170K), a simple
int size = StringLen(data);
Comment("Size : ", size);
Print("Size: ", size);


would print part of the string on the chart and on the Log.
And when th sting is long also, it does not return the full data.

 
See documentation "MQL4: String constants"

String constant is a sequence of ASCII-code characters enclosed in double quotes: "Character constant".

A string constant is an array of characters enclosed in quotes. It is of the string type. If there is a need to insert a double quote (") into the string, a reverse slash (\) must be put before it. Any special character constants can be inserted into the string if they have a reverse slash (\) before them. The length of a string constant lies between 0 and 255 characters. If the string constant is longer, the superfluous characters on the right will be rejected, and compiler will alert correspondingly.
 
The string is not a constant. It is part:

while (true) {
     str = stringconcentenate(str, abc);
.
.
.
}



String str could be anything from several bytes to ~200Kbytes.

When I tried Print("Size: ", StringLen(str)); I am getting garbage printouts.

 
Functions working with strings try to increase internal buffer for string processing. Initial buffer size is 4K. Maximal buffer size depends on free memory.
 
Functions working with strings try to increase internal buffer for string processing. Initial buffer size is 4K. Maximal buffer size depends on free memory.


aha! indeed when it hits more than 4K, its screwed.

Here is the actual code I am working on. It fetches webpages from the internet and stores them into the external string WebPage.


extern string URL = "";
start () {
	string Data= "";
	GrabWeb(URL,Data);
	int size = StringLen(Data);
	Comment("Size : ", size);
	Print(Data);
}

//====================================   GrabWeb Functions   ======================================

int hSession_IEType;
int hSession_Direct;
int Internet_Open_Type_Preconfig = 0;
int Internet_Open_Type_Direct = 1;
int Internet_Open_Type_Proxy = 3;
int Buffer_LEN = 16;

#import "wininet.dll"

#define INTERNET_FLAG_PRAGMA_NOCACHE    0x00000100 // Forces the request to be resolved by the origin server, even if a cached copy exists on the proxy.
#define INTERNET_FLAG_NO_CACHE_WRITE    0x04000000 // Does not add the returned entity to the cache. 
#define INTERNET_FLAG_RELOAD            0x80000000 // Forces a download of the requested file, object, or directory listing from the origin server, not from the cache.

int InternetOpenA(
	string	sAgent,
	int	lAccessType,
	string	sProxyName="",
	string	sProxyBypass="",
	int	lFlags=0
);

int InternetOpenUrlA(
	int	hInternetSession,
	string	sUrl, 
	string	sHeaders="",
	int	lHeadersLength=0,
	int	lFlags=0,
	int	lContext=0 
);

int InternetReadFile(
	int	hFile,
	string	sBuffer,
	int	lNumBytesToRead,
	int&	lNumberOfBytesRead[]
);

int InternetCloseHandle(
	int	hInet
);
#import


int hSession(bool Direct) {
	string InternetAgent;
	if (hSession_IEType == 0) {
		InternetAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)";
		hSession_IEType = InternetOpenA(InternetAgent, Internet_Open_Type_Preconfig, "0", "0", 0);
		hSession_Direct = InternetOpenA(InternetAgent, Internet_Open_Type_Direct, "0", "0", 0);
	}
	if (Direct) { 
		return(hSession_Direct); 
	} else {
		return(hSession_IEType); 
	}
}


bool GrabWeb(string strUrl, string& strWebPage) {
	int	iResult;
	int 	lReturn[]={1};
	string 	sBuffer="x";

	strWebPage = "";
	int hInternet = InternetOpenUrlA(hSession(FALSE), strUrl, "0", 0, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, 0);
	if (hInternet != 0) {
		while (InternetReadFile(hInternet, sBuffer, Buffer_LEN, lReturn) != 0) {
			if (lReturn[0] == 0) break;
			strWebPage = strWebPage + StringSubstr(sBuffer, 0, lReturn[0]);
		}
		iResult = InternetCloseHandle(hInternet);
		return(true);
	} else {
		return(false);
	}
}



Above, Buffer_LEN is 16; I find this number too small so I increased it to 256, 2048, 4096 all fails resulting in wrong StringLen count to total crash.

How do I increase this "Initial Buffer" such that it wont crash when the string grows big? A small Buffer_LEN is inefficient.




 
In your case You can use as sBuffer only constant strings. Parameters are passed by value, strings too. But there is one way to pass string by reference to dll-imported function - use constant string (side effect, accidental implementation). Use following code.
#import "wininet.dll"
bool InternetReadFile(int hInternet, string lpBuffer, int dwNumberOfBytesToRead, int& lpdwNumberOfBytesRead[]);
...
...
string sBuffer="                                                                                                                                        "; // not more than 255 spaces
int    nBufferLen=StringLen(sBuffer);
int    lReturn[1];
...
while (InternetReadFile(hInternet, sBuffer, nBufferLen, lReturn) != 0)
...



Two important things:
- long constant string
- String addition instead of StringConcatenate (I was wrong - string functions don't increase internal buffer, addition operation only)

 
So, what you meant is that:

string sBuffer="                                                                                                                                        "; // not more than 255 spaces

forces MT4 to allocate sBuffer with x spaces such that, when it is passed to the dll, dll can work with x bytes!

string1 = StringConcatenate( string1, string2) not ok on long strings
string1 = string1 + string2 OK for long strings
Is this correct about the string addition?

 
1. Yes
2. Yes
Reason: