zeh

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
hanibal
Beiträge: 369
Registriert: Sa 3. Mär 2007, 16:03
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Bramsche (Emsland)

Re: zeh

Beitrag von hanibal »

sollte eig auch stimmen, soweit ich das mit meinen C kentnissen beurteilen kann.

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: zeh

Beitrag von theo »

hanibal hat geschrieben:sollte eig auch stimmen, soweit ich das mit meinen C kentnissen beurteilen kann.
Ok, Merci :-)

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6877
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: zeh

Beitrag von af0815 »

theo hat geschrieben:Hat jemand nen Plan von C? ;-)

Wie wäre folgender Prozedur Parameter umzusetzen?

uint8_t **dstptr

Ist das ein var PByte resp. Pchar ?
** wird oft bei einem array of Zeigern verwendet. Beispiel ist ein Array auf Strings (Strings = Array of Char).

Vielleicht etwas für dich Pointer Tutorial oder hier Beispiel für Stringfeld
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: zeh

Beitrag von theo »

af0815 hat geschrieben: ** wird oft bei einem array of Zeigern verwendet. Beispiel ist ein Array auf Strings (Strings = Array of Char).
Danke. Ich hab jetzt den "eingebauten" Typen PPChar verwendet. Das trifft's wohl am besten.
Trotzdem wird mir aus meinem konkreten Zusammenhang der Sinn davon nicht ganz klar.
Die Variable soll nämlich afaics kein "Array" von PChar halten sondern nur einen.

_Bernd
Beiträge: 145
Registriert: Di 13. Feb 2007, 11:16

Re: zeh

Beitrag von _Bernd »

theo hat geschrieben:
af0815 hat geschrieben: ** wird oft bei einem array of Zeigern verwendet. Beispiel ist ein Array auf Strings (Strings = Array of Char).
Danke. Ich hab jetzt den "eingebauten" Typen PPChar verwendet. Das trifft's wohl am besten.
Trotzdem wird mir aus meinem konkreten Zusammenhang der Sinn davon nicht ganz klar.
Die Variable soll nämlich afaics kein "Array" von PChar halten sondern nur einen.
ssize_t utf8proc_map( const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options)

IMHO wird mit **dstptr die Adresse eines Zeigers übergeben. Das könnte auch darauf hindeuten, daß die Funktion utf8proc_map Speicher reserviert und über diesen Zeiger an den Aufrufer zurückliefert. Also z. B. so etwas wäre möglich:

Code: Alles auswählen

#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
 
uint8_t *x;
 
void AllokiereX(uint8_t **dstptr)
{
   *dstptr= malloc(100); 
 
   (*dstptr)[0]= 65;
   (*dstptr)[1]= 66;
   (*dstptr)[2]= 67;
   (*dstptr)[3]= 0;
}
 
int main(void)
{
   AllokiereX(&x);
   printf("%s\n", x); // gibt ABC aus.
}
Aber wenn Du den Source hast, dann kannst Du doch selber nachschauen, was die Funktion macht.

Gruß, Bernd.

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: zeh

Beitrag von theo »

_Bernd hat geschrieben: Aber wenn Du den Source hast, dann kannst Du doch selber nachschauen, was die Funktion macht.
Tja, wenn das nur so einfach wäre...

Also: Ich habe die Lib in zwei Varianten. Erstens als eingebundenes obj und zweitens als Versuch, das Ganze nach Pascal zu übersetzen.

Die Variante mit dem obj funktioniert.
Das ist so in Pascal geinterfaced:
function utf8proc_NFKC(str:Pchar):Pchar; cdecl; external;
Ich schicke einen PChar rein und bekomme einen PChar (String) zurück. Das Funktioniert.

Die C Seite dabei sieht so aus (hier nur die ersten Funktionen)

Code: Alles auswählen

uint8_t *utf8proc_NFKC(const uint8_t *str) {
  uint8_t *retval;
  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |  UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
  return retval;
}  
 
ssize_t utf8proc_map(
  const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options
) {
  int32_t *buffer;
  ssize_t result;
  *dstptr = NULL;
  result = utf8proc_decompose(str, strlen, NULL, 0, options);
  if (result < 0) return result;
  buffer = malloc(result * sizeof(int32_t) + 1);
  if (!buffer) return UTF8PROC_ERROR_NOMEM;
  result = utf8proc_decompose(str, strlen, buffer, result, options);
  if (result < 0) {
    free(buffer);
    return result;
  }
  result = utf8proc_reencode(buffer, result, options);
  if (result < 0) {
    free(buffer);
    return result;
  }
  {
    int32_t *newptr;
    newptr = realloc(buffer, result+1);
    if (newptr) buffer = newptr;
  }
  *dstptr = (uint8_t *)buffer;
  return result;
}
Natürlich könnte das Problem auch in den weiteren Funktionen utf8proc_decompose oder utf8proc_reencode liegen, aber ich will erstmal klären ob auf diesem Level alles richtig ist.

Nach Pascal übersetzt habe ich das so:

Code: Alles auswählen

function utf8proc_NFKC(str: puint8_t): Pchar;//puint8_t;
var
  retval: Pchar;//puint8_t;
begin
  utf8proc_map(str, 0, @retval, UTF8PROC_NULLTERM or UTF8PROC_STABLE or UTF8PROC_COMPOSE or UTF8PROC_COMPAT);
  result := retval;
end; 
 
function utf8proc_map(str: puint8_t; strlen: ssize_t; dstptr: ppuint8_t; options: integer): ssize_t;
 
var
  buffer: pint32_t;
  aresult: ssize_t;
  newptr: pint32_t;
begin
  dstptr^ := nil;
  aresult := utf8proc_decomposer(str, strlen, nil, 0, options);
  if aresult < 0 then
  begin
    result := aresult;
    exit;
  end;
  buffer := GetMem(aresult * sizeof(int32_t) + 1);
  if buffer = nil then
  begin
    result := UTF8PROC_ERROR_NOMEM;
    exit;
  end;
  aresult := utf8proc_decomposer(str, strlen, buffer, aresult, options);
  if aresult < 0 then
  begin
    freemem(buffer);
    result := aresult;
    exit;
  end;
  aresult := utf8proc_reencode(buffer, aresult, options);
  if aresult < 0 then
  begin
    freemem(buffer);
    result := aresult;
    exit;
  end;
  begin
    newptr := reallocmem(buffer, aresult + 1);
    if newptr <> nil  then buffer := newptr;
  end;
  dstptr^ := puint8_t(buffer);
  result := aresult;
end;
Wobei
int32_t = longint;
puint8_t = PByte;
pint32_t = plongint;
ppuint8_t=^puint8_t;

Kompilieren tut's, aber ich kriege nur den ersten Buchstaben zurück, nicht den ganzen String.
Siehst du den Denkfehler?

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: zeh

Beitrag von theo »

Was ich z.B. nicht verstehe:

Was passiert hier:
*dstptr = (uint8_t *)buffer;

Wie kann man einen Plongint buffer auf PChar casten ??
Wenn ich mir bei der C Variante den buffer mit "Überwachte Ausdrücke" anschaue, also Pchar(buffer) dann steht da der ganze String drin, während bei Pascal nur das erste Zeichen steht, sofern es in ein Byte passt. (Umlaute sind falsch angezeigt).
Ich würde eigenlich auch das letztere erwarten. Was macht C da?

_Bernd
Beiträge: 145
Registriert: Di 13. Feb 2007, 11:16

Re: zeh

Beitrag von _Bernd »

Was C da macht, weiß ich auch nicht ganz genau. Mann könnte jetzt nachforschen. Ist mir aber zu aufwendig und raten möchte ich auch nicht ;-)
Aber ich denke, Du hast da möglicherweise eine wunde Stelle gefunden. Vielleicht kannst Du mal auf die Schnelle den buffer und auch den newptr auf PByte setzen.

Gruß, Bernd.

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: zeh

Beitrag von theo »

Der Longint wird aber gebraucht.
In diesem stehen die (maximal) vier Byte die einen UTF8Char ausmachen.

Ich kann die Daten schon abholen mit einem zweiten Puffer, auf den ich die Zeichen verteile z.B. (hier nur angetestet auf max 2 Byte).

Code: Alles auswählen

var  buf2:puint8_t;
...
  buf2:=GetMem(aresult * 8 + 1);
  count:=0;
  for i:=0 to aresult do
  begin
   if Buffer[i]>$FF then
   begin
     buf2[count]:=Chr(Buffer[i]);
     inc(count);
     buf2[count]:=Chr(Buffer[i] shr 8);
   end else
   buf2[count]:=Chr(Buffer[i]);
   inc(count);
  end;     
 dstptr^ := puint8_t(buf2);
So geht's schon, aber mir ist das ganze doch extremst Suspekt. Ich möchte wissen, wie C das macht.
Viellicht hat's im restlichen Code auch noch solche Schmankerl.
Danke für deinen Beistand. ;-)

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: zeh

Beitrag von theo »

Heureka!
Zwei Nächte und jetzt klappt's. Wollt ich nur melden.... ;-)

_Bernd
Beiträge: 145
Registriert: Di 13. Feb 2007, 11:16

Re: zeh

Beitrag von _Bernd »

prima. Aber worin lag denn nun das Hauptproblem?

Gruß, Bernd.

Benutzeravatar
theo
Beiträge: 10949
Registriert: Mo 11. Sep 2006, 19:01

Re: zeh

Beitrag von theo »

Es lag in einer anderen Funktion. Zwei kleinere Fehler die ich nicht gesehen hatte.
Aber nichts, was ich jetzt als grosse Erkenntnis weitergeben könnte.
Es ist halt schnell mal was verbockt mit Pchar, Pointer-Offsets und Type-Casting etc.
Der Hauptfehler lag in diesen Zeilen (korrigiert):

uc := buffer[rpos];
wpos := wpos + utf8proc_encode_char(uc, PByte(buffer) + wpos);

Danke für die Unterstützung.

Antworten