2012-12-20 15 views
6

Piszę parser HTML w C, i staram się poprawnie podążać za the W3C guidelines on parser implementation. Jednym z kluczowych punktów jest to, że parser działa na strumieniu kodów Unicode zamiast na bajtach, co ma sens.Strumień kodów Unicode z bajtów w C?

Zasadniczo, następnie podano bufor znanego kodowania znaków (I albo będzie mieć kodowania wejściowego wyraźny lub użyje algorytmu skanowania wstępnego HTML5 zrobić dobre przypuszczenie), co jest najlepszym sposobem w C - idealnie między platformami, ale trzymanie się systemu UNIX jest w porządku - aby powtórzyć sekwencję kodów Unicode?

Czy przydzielasz kilka buforów o rozsądnej wielkości i używasz iconv do zrobienia? Czy powinienem patrzeć na ICU? Makra, takie jak U16_NEXT wydają się być dobrze dopasowane do mojego zadania, ale dokumentacja ICU jest niesamowicie długa i trudno jest dokładnie zobaczyć, jak sklejać elementy.

+0

'iconv' wydaje się być dobrym początkiem. Jest konceptualnie prosty i szeroko dostępny. –

+0

OK, dam 'iconv' spróbować. Czy uważasz, że najbardziej sensownym jest przejście na UTF-32? Mimo, że jest to prawdopodobnie prawie bezużyteczne kodowanie, oznaczałoby to, że co 4 bajty dokładnie reprezentują punkt kodu Unicode. –

+1

Tak, rzeczywiście. UTF-32 to doskonale dokładne kodowanie. –

Odpowiedz

2

ICU to dobry wybór. Użyłem go w C++ i bardzo go polubiłem. Jestem całkiem pewien, że dostajesz podobne przemyślane API również w C.

Nie zupełnie tak samo, ale nieco powiązany może być to tutorial, który wyjaśnia, jak wykonać streamingu/przyrostowe transliteracji (trudność w tym przypadku jest to, że „Kursor” może być wewnątrz punkt kod czasami).

2

Następujące zdekodują punkt kodowy i zwrócą wartość zwiększenia ciągu znaków o (ilość "przeżutego"). Zauważ, że xs_utf16 to niepodpisany skrót. Więcej informacji: http://sree.kotay.com/2006/12/unicode-is-pain-in.html

enum 
{ 
    xs_UTF_Max   = 0x0010FFFFUL, 
    xs_UTF_Replace  = 0x0000FFFDUL, 
    xs_UTF16_HalfBase = 0x00010000UL, 
    xs_UTF16_HighStart = 0x0000D800UL, 
    xs_UTF16_HighEnd = 0x0000DBFFUL, 
    xs_UTF16_LowStart = 0x0000DC00UL, 
    xs_UTF16_LowEnd  = 0x0000DFFFUL, 
    xs_UTF16_MaxUCS2 = 0x0000FFFFUL, 
    xs_UTF16_HalfMask = 0x000003FFUL, 
    xs_UTF16_HalfShift = 10 
}; 


int32 xs_UTF16Decode (uint32 &code, const xs_utf16* str, int32 len, bool strict) 
{ 
      if (str==0||len==0)   {code=0; return 0;} 

      uint32 c1 = str[0]; 

      //note: many implementations test from HighStart to HighEnd, 
      //     this may be a partial code point, and is incorrect(?) 
      //     trivial checking should exclude the WHOLE surrogate range 
      if (c1<xs_UTF16_HighStart || c1>xs_UTF16_LowEnd)   return 1; 
          //really an error if we're starting in the low range 

      //surrogate pair 
      if (len<=1 || str[1]==0)         {code=xs_UTF_Replace; return strict ? 0 : 1;} //error 
      uint32 c2 = str[1]; 
      code = ((c1-xs_UTF16_HighStart)<<xs_UTF16_HalfShift) + (c2-xs_UTF16_LowStart) + xs_UTF16_HalfBase; 

      if (strict==false)          return 2; 

      //check for errors 
      if (c1>=xs_UTF16_LowStart && c1<=xs_UTF16_LowEnd)   {code=xs_UTF_Replace; return 0;} //error 
      if (c2<xs_UTF16_LowStart || c2>xs_UTF16_LowEnd)   {code=xs_UTF_Replace; return 0;} //error 
      if (code>xs_UTF_Max)          {code=xs_UTF_Replace; return 0;} //error 

      //success 
      return 2; 
} 
Powiązane problemy