This documentation describes the Prokee module interface.
Static Methods:
decode
int utf8::decode(int *utf32out,const char *utf8in)
encode
int utf8::encode(char *utf8out,int utf32in)
convert_utf8_to_utf32
int utf8::convert_utf8_to_utf32(int **utf32string,int *utf32string_length,const char *utf8string)
convert_utf32_to_utf8
int utf8::convert_utf32_to_utf8(char **utf8string,int *utf8string_length,const int *utf32string)
getBOM
int utf8::getBOM(char *utf8out)
Motivation
Das Modul bietet statische Methoden um Unicode Zeichen und Strings zwischen UTF-8 und UTF-32 zu konvertieren.
Annahmen
Der Datentyp int muss mindestens 4 Bytes groß sein um Unicode Codepoints (UTF-32 Zeichen) speichern zu können.
Static Methods
decode
Berechnet die Zeichennummer (den Unicode Codepoint) eines utf8-codierten Zeichens.
Signature:
int utf8::decode(int *utf32out,const char *utf8in)
Parameters:
| int * | utf32out | [OUT] | Speicherbereich in welchen die Zeichen-Nummer (der Unicode Codepoint) des Zeichens geschrieben wird. |
| const char * | utf8in | [IN] | Ein Zeichen in UTF-8 Codierung. (1 bis 4 Bytes) |
Return value:Gibt die Anzahl Bytes zurück, die das Zeichen in utf8-Codierung benötigt. Falls ein Fehler aufgetreten ist, wird 0 zurückgegeben und *utf32out wird auf 0 gesetzt.
Code: toggle
int utf8::decode(int *utf32out,const char *utf8in_)
{
*utf32out=0;
unsigned char *utf8in=(unsigned char *)utf8in_;
if(utf8in[0]==0xC0 || utf8in[0]==0xC1 || utf8in[0]>=0xF5)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte %d found.\n",utf8in[0]);
return 0;
}
if(!(utf8in[0] & 0b10000000))
{
// 7 bit
*utf32out=utf8in[0];
return 1;
}
else if((utf8in[0] & 0b11100000)==0b11000000)
{
// 11 bits
if((utf8in[1] & 0b11000000)!=0b10000000)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte %d found.\n",utf8in[0]);
return 0;
}
*utf32out |= (utf8in[0] & 0b00011111) << 6;
*utf32out |= (utf8in[1] & 0b00111111);
if(*utf32out<0x0080)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte sequence %d-%d found.\n",utf8in[0],utf8in[1]);
*utf32out=0;
return 0;
}
return 2;
}
else if((utf8in[0] & 0b11110000)==0b11100000)
{
// 16 bits
if((utf8in[1] & 0b11000000)!=0b10000000)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte %d found.\n",utf8in[0]);
return 0;
}
if((utf8in[2] & 0b11000000)!=0b10000000)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte %d found.\n",utf8in[0]);
return 0;
}
*utf32out |= (utf8in[0] & 0b00001111) << 12;
*utf32out |= (utf8in[1] & 0b00111111) << 6;
*utf32out |= (utf8in[2] & 0b00111111);
if(*utf32out<0x0800)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte sequence %d-%d-%d found.\n",utf8in[0],utf8in[1],utf8in[2]);
*utf32out=0;
return 0;
}
return 3;
}
else if((utf8in[0] & 0b11111000)==0b11110000)
{
// 21 bits
if((utf8in[1] & 0b11000000)!=0b10000000)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte %d found.\n",utf8in[0]);
return 0;
}
if((utf8in[2] & 0b11000000)!=0b10000000)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte %d found.\n",utf8in[0]);
return 0;
}
if((utf8in[3] & 0b11000000)!=0b10000000)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte %d found.\n",utf8in[0]);
return 0;
}
*utf32out |= (utf8in[0] & 0b00000111) << 18;
*utf32out |= (utf8in[1] & 0b00111111) << 12;
*utf32out |= (utf8in[2] & 0b00111111) << 6;
*utf32out |= (utf8in[3] & 0b00111111);
if(*utf32out<0x10000 || *utf32out>0x10FFFF)
{
fprintf(stderr,"[ERROR] utf8: while reading character. unexpected byte sequence %d-%d-%d-%d found.\n",utf8in[0],utf8in[1],utf8in[2],utf8in[3]);
*utf32out=0;
return 0;
}
return 4;
}
return 0;
}
encode
Berechnet die utf8-Codierung zu einer Zeichennummer (zu einem Unicode Codepoint) eines Zeichens.
Signature:
int utf8::encode(char *utf8out,int utf32in)
Parameters:
| char * | utf8out | [OUT] | Speicherbereich in welchen das Zeichen in UTF-8 Codierung geschrieben wird. Der Speicherbereich muss groß genug sein, um bis zu 4 Bytes aufzunehmen. |
| int | utf32in | [IN] | Die Zeichennummer (der Unicode Codepoint) eines Zeichens. |
Return value:Gibt die Anzahl Bytes zurück, die das Zeichen in utf8-Codierung benötigt. Falls ein Fehler aufgetreten ist, wird 0 zurückgegeben.
Code: toggle
int utf8::encode(char *utf8out,int utf32in)
{
if(utf32in<0)
{
fprintf(stderr,"[ERROR] utf8: while writing character %d. character value < 0x0.\n",utf32in);
return 0;
}
else if(utf32in<=0x0000007F)
{
// 7 bits
*utf8out=utf32in;
return 1;
}
else if(utf32in<=0x000007FF)
{
// 11 bits
utf8out[0]=0b11000000 | (utf32in >> 6);
utf8out[1]=0b10000000 | (utf32in & 0b00111111);
return 2;
}
else if(utf32in<=0x0000FFFF)
{
if(utf32in>=0xD800 && utf32in<=0xDFFF)
{
fprintf(stderr,"[ERROR] utf8: while writing character %d. illegal character.\n",utf32in);
return 0;
}
// 16 bits
utf8out[0]=0b11100000 | (utf32in >> 12);
utf8out[1]=0b10000000 | ((utf32in >>6) & 0b00111111);
utf8out[2]=0b10000000 | (utf32in & 0b00111111);
return 3;
}
else if(utf32in<=0x0010FFFF)
{
// 21 bits
utf8out[0]=0b11110000 | (utf32in >> 18);
utf8out[1]=0b10000000 | ((utf32in >>12) & 0b00111111);
utf8out[2]=0b10000000 | ((utf32in >>6) & 0b00111111);
utf8out[3]=0b10000000 | (utf32in & 0b00111111);
return 4;
}
else
{
fprintf(stderr,"[ERROR] utf8: while writing character %d. character value > 0x10FFFF.\n",utf32in);
return 0;
}
}
convert_utf8_to_utf32
Konvertiert einen String von UTF-8 zu UTF-32. (Die UTF-32 Werte werden in der Byte-Reigenfolge des Systems ausgegeben.)
Signature:
int utf8::convert_utf8_to_utf32(int **utf32string,int *utf32string_length,const char *utf8string)
Parameters:
| int ** | utf32string | [OUT] | Speicherbereich in den die Ausgabe geschrieben wird. Falls NULL angegeben wurde, oder falls *utf32string = 0 ist, wird der Speicherbereich neu alloziert. Die anfängliche Länge des Speicherbereichs wird durch *utf32string_length festgelegt. Falls *utf32string_length = 0 (oder utf32string_length = NULL) ist, so wird die anfängliche Länge (in sizeof(int)) auf die Anzahl Bytes in utf8string gesetzt. Ist der Speicherbereich für die Ausgabe zu klein, so wird die Länge so lange verdoppelt (und der Speicher neu alloziert) bis der Speicherbereich lang genug ist. Die Länge des resultierenden Speicherbereichs kann daher deutlich länger sein, als die Länge des Ausgabe-Strings. Bei wiederholtem Aufruf, sollte ein bereits allozierter Speicherbereich wiederverwendet werden, um die Anzahl der benötigten Speicher-Allozierungen gering zu halten. Wird der Speicherbereich neu alloziert (oder re-alloziert) und ist utf32string nicht NULL, so wird die neue Adresse des Speicherbereichs nach *utf32string zurück geschrieben. |
| int * | utf32string_length | [IN/OUT] | Länge des Speicherbereichs utf32string in den die Ausgabe geschrieben wird. Bei Angabe von NULL oder falls *utf32string_length = 0 ist, so wird falls utf32string = NULL oder *utf32string = 0 ist, ein neuer Speicherbereich alloziert bzw. falls *utf32string != 0 ist, der bestehende Speicherbereich re-alloziert. Ist der Speicherbereich zu klein für die Ausgabe, so wird ebenso ein längerer Speicherbereich alloziert. Sofern utf32string_length nicht NULL ist, wird die neue Länge des Speicherbereichs nach *utf32string_length geschrieben. |
| const char * | utf8string | [IN] | Ein null-terminierter und UTF-8 codierter String. |
Return value:Gibt die Anzahl Zeichen zurück, die nach utf32string geschrieben wurden.
Code: toggle
int utf8::convert_utf8_to_utf32(int **utf32string,int *utf32string_length,const char *utf8string)
{
int *out;
int outln;
if(!utf32string || *utf32string==0)
{
if(!utf32string_length || *utf32string_length==0)
{
outln=length(utf8string)+1;
}
else
{
outln=*utf32string_length;
}
out=(int *)malloc(outln*sizeof(int));
}
else
{
if(!utf32string_length || *utf32string_length==0)
{
outln=length(utf8string)+1;
out=(int *)realloc(*utf32string,outln*sizeof(int));
}
else
{
outln=*utf32string_length;
out=*utf32string;
}
}
int read_pos=0;
int write_pos=0;
int bcount=0;
do
{
if(write_pos>=outln)
{
outln*=2;
out=(int *)realloc(out,outln*sizeof(int));
}
bcount=decode(&out[write_pos],&utf8string[read_pos]);
read_pos+=bcount;
write_pos++;
}
while(out[write_pos-1] && bcount);
// -- VERSION A -- Speicherbereich nicht kürzen.
if(bcount==0)
{
if(write_pos>=outln)
{
outln+=1;
out=(int *)realloc(out,outln*sizeof(int));
}
out[write_pos]=0;
write_pos++;
}
/* -- VERSION B -- Speicherbereich kürzen.
if(bcount==0)
{
outln=write_pos+1;
out=(int *)realloc(out,outln*sizeof(int));
out[write_pos]=0;
write_pos++;
}
else
{
outln=write_pos;
out=(int *)realloc(out,outln*sizeof(int));
}
*/
if(utf32string)
{
*utf32string=out;
}
if(utf32string_length)
{
*utf32string_length=outln;
}
return write_pos-1;
}
convert_utf32_to_utf8
Konvertiert einen String von UTF-32 zu UTF-8. (Der UTF-32 String muss in der Byte-Reigenfolge des Systems vorliegen.)
Signature:
int utf8::convert_utf32_to_utf8(char **utf8string,int *utf8string_length,const int *utf32string)
Parameters:
| char ** | utf8string | [OUT] | Speicherbereich in den die Ausgabe geschrieben wird. Falls NULL angegeben wurde, oder falls *utf8string = 0 ist, wird der Speicherbereich neu alloziert. Die anfängliche Länge des Speicherbereichs wird durch *utf8string_length festgelegt. Falls *utf8string_length = 0 (oder utf8string_length = NULL) ist, so wird die anfängliche Länge (in Bytes) auf die vierfache Anzahl Zeichen in utf32string gesetzt. Ist der Speicherbereich für die Ausgabe zu klein, so wird die Länge so lange verdoppelt (und der Speicher neu alloziert) bis der Speicherbereich lang genug ist. Die Länge des resultierenden Speicherbereichs kann daher deutlich länger sein, als die Länge des Ausgabe-Strings. Bei wiederholtem Aufruf, sollte ein bereits allozierter Speicherbereich wiederverwendet werden, um die Anzahl der benötigten Speicher-Allozierungen gering zu halten. Wird der Speicherbereich neu alloziert (oder re-alloziert) und ist utf8string nicht NULL, so wird die neue Adresse des Speicherbereichs nach *utf8string zurück geschrieben. |
| int * | utf8string_length | [IN/OUT] | Länge des Speicherbereichs utf8string in den die Ausgabe geschrieben wird. Bei Angabe von NULL oder falls *utf8string_length = 0 ist, so wird falls utf32string = NULL oder *utf32string = 0 ist, ein neuer Speicherbereich alloziert bzw. falls *utf32string != 0 ist, der bestehende Speicherbereich re-alloziert. Ist der Speicherbereich zu klein für die Ausgabe, so wird ebenso ein längerer Speicherbereich alloziert. Sofern utf8string_length nicht NULL ist, wird die neue Länge des Speicherbereichs nach *utf8string_length geschrieben. |
| const int * | utf32string | [IN] | Ein null-terminierter und UTF-32 codierter String. |
Return value:Gibt die Anzahl Bytes zurück, die nach utf8string geschrieben wurden.
Code: toggle
int utf8::convert_utf32_to_utf8(char **utf8string,int *utf8string_length,const int *utf32string)
{
char *out;
int outln;
if(!utf8string || *utf8string==0)
{
if(!utf8string_length || *utf8string_length==0)
{
outln=length(utf32string)+1;
}
else
{
outln=*utf8string_length;
}
out=(char *)malloc(outln*sizeof(char));
}
else
{
if(!utf8string_length || *utf8string_length==0)
{
outln=length(utf32string)+1;
out=(char *)realloc(*utf8string,outln*sizeof(char));
}
else
{
outln=*utf8string_length;
out=*utf8string;
}
}
int read_pos=0;
int write_pos=0;
int bcount=1;
while(utf32string[read_pos] && bcount)
{
if(write_pos>=outln-4)
{
outln*=2+4;
out=(char *)realloc(out,outln*sizeof(char));
}
bcount=encode(&out[write_pos],utf32string[read_pos]);
write_pos+=bcount;
read_pos++;
}
// -- VERSION A -- Speicherbereich nicht kürzen.
if(write_pos>=outln)
{
outln+=1;
out=(char *)realloc(out,outln*sizeof(char));
}
out[write_pos]=0;
/* -- VERSION B -- Speicherbereich kürzen.
outln=write_pos+1;
out=(char *)realloc(out,outln*sizeof(char));
out[write_pos]=0;
*/
if(utf8string)
{
*utf8string=out;
}
if(utf8string_length)
{
*utf8string_length=outln;
}
return write_pos;
}
getBOM
Schreibt das BOM-Zeichen (Byte-Order-Mark) für die utf8-Codierung in den angegebenen Speicherbereich.
Signature:
int utf8::getBOM(char *utf8out)
Parameters:
| char * | utf8out | [OUT] | Speicherbereich in welchen das BOM-Zeichen in UTF-8 Codierung geschrieben wird. Der Speicherbereich muss groß genug sein, um 3 Bytes aufzunehmen. |
Return value:Gibt die Anzahl Bytes zurück, die das BOM-Zeichen in utf8-Codierung benötigt. (Das sind immer 3 Bytes.)
Code: toggle
int utf8::getBOM(char *utf8out)
{
utf8out[0]=0xEF;
utf8out[1]=0xBB;
utf8out[2]=0xBF;
return 3;
}