Jump to content
chkaufmann

String Helper for NormalizeString

Recommended Posts

I created the following helper method to normalize Unicode strings with different representations of ä, ö, ü:

function TBSStringHelper.Length: Integer;
begin
  Result := TBSStringHelperCaller.Length(Self);
end;

function TBSStringHelper.NormalizeNFC: String;
var
  bufLen : Integer;
  buffer : PWideChar;
begin
  Result := Self;
  bufLen := NormalizeString(NormalizationC, PWideChar(Self), Length, nil, 0);
  if bufLen > 0 then begin
    GetMem(buffer, bufLen);
    try
      bufLen := NormalizeString(NormalizationC, PWideChar(Self), Length, buffer, bufLen);
      if bufLen > 0 then begin
        Result := buffer;
        SetLength(Result, bufLen);
      end;
    finally
      FreeMem(buffer);
    end;
  end;
end;

But when I use this function many times, I get a memory corruption error and at some point an access violation. What is wrong here? I'm on Delphi 11, Update 1.

 

Christian

Share this post


Link to post

What do you get if you do GetLastError?

If you look at the example given on Microsoft's document page for NormalizeString you will see:

 

const int maxIterations = 10;
LPWSTR strResult = NULL;
HANDLE hHeap = GetProcessHeap();

int iSizeEstimated = NormalizeString(form, strInput, -1, NULL, 0);
for (int i = 0; i < maxIterations; i++)
{
    if (strResult)
        HeapFree(hHeap, 0, strResult);
    strResult = (LPWSTR)HeapAlloc(hHeap, 0, iSizeEstimated * sizeof (WCHAR));
    iSizeEstimated = NormalizeString(form, strInput, -1, strResult, iSizeEstimated);
 
    if (iSizeEstimated > 0)
        break; // success 
 
    if (iSizeEstimated <= 0)
    {
        DWORD dwError = GetLastError();
        if (dwError != ERROR_INSUFFICIENT_BUFFER) break; // Real error, not buffer error 
 
        // New guess is negative of the return value. 
        iSizeEstimated = -iSizeEstimated;
    }
}

It seems the "buffer length required" returned from the first call to NormalizeString is in character length and not byte length because in the example it seems that the buffer is set to a length of the RequiredLength * SizeOf(WChar)

 

You will also see that the parameters are described as " Length, in characters "

 

Edited by PeaShooter_OMO

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×