00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063 
00064 #include "GString.h"
00065 #if HAS_ICONV
00066 #include <iconv.h>
00067 #endif
00068 
00069 
00070 #ifdef HAVE_NAMESPACES
00071 namespace DJVU {
00072 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00073 }
00074 #endif
00075 #endif
00076 
00077 static unsigned char nill=0;
00078 
00079 static void const * 
00080 checkmarks(void const * const xbuf,
00081            unsigned int &bufsize,
00082            GStringRep::EncodeType &rep)
00083 {
00084   unsigned char const *buf=(unsigned char const *)xbuf;
00085   if(bufsize >= 2 || (xbuf && !bufsize && rep != GStringRep::XOTHER))
00086   {
00087     const unsigned int s=(((unsigned int)buf[0])<<8)+(unsigned int)buf[1];
00088     switch(s)
00089     {
00090       case 0:
00091         if((bufsize>=4)||(!bufsize && rep == GStringRep::XUCS4BE)
00092           ||(!bufsize && rep == GStringRep::XUCS4_2143))
00093         {
00094           const unsigned int s=(((unsigned int)buf[2])<<8)+(unsigned int)buf[3];
00095           if(s == 0xfeff)
00096           { 
00097             rep=GStringRep::XUCS4BE;
00098             buf+=4;
00099           }else if(s == 0xfffe)
00100           {
00101             rep=GStringRep::XUCS4_2143;
00102             buf+=4;
00103           }
00104         }
00105         break;
00106       case 0xfffe:
00107         if(((bufsize>=4)||(!bufsize && rep == GStringRep::XUCS4LE)) 
00108            && !((unsigned char *)buf)[2] && !((unsigned char *)buf)[3])
00109         {
00110           rep=GStringRep::XUCS4LE;
00111           buf+=4;
00112         }else
00113         {
00114           rep=GStringRep::XUTF16LE;
00115           buf+=2;
00116         }
00117         break;
00118       case 0xfeff:
00119         if(((bufsize>=4)||(!bufsize && rep == GStringRep::XUCS4_3412)) 
00120            && !((unsigned char *)buf)[2] && !((unsigned char *)buf)[3])
00121         {
00122           rep=GStringRep::XUCS4_3412;
00123           buf+=4;
00124         }else
00125         {
00126           rep=GStringRep::XUTF16LE;
00127           buf+=2;
00128         }
00129         break;
00130       case 0xefbb:
00131         if(((bufsize>=3)||(!bufsize && GStringRep::XUTF8 == rep))&&(buf[2] == 0xbf))
00132         {
00133           rep=GStringRep::XUTF8;
00134           buf+=3;
00135         }
00136         break;
00137       default:
00138         break;
00139     }
00140   }
00141   if(buf != xbuf)
00142   {
00143     if(bufsize)
00144     {
00145       const size_t s=(size_t)xbuf-(size_t)buf;
00146       if(bufsize> s)
00147       {
00148         bufsize-=s;
00149       }else
00150       {
00151         bufsize=0;
00152         buf=(const unsigned char *)&nill;
00153       }
00154     }
00155   }
00156   return buf;
00157 }
00158 
00159 class GStringRep::Unicode : public GStringRep::UTF8
00160 {
00161 public:
00162   GP<GStringRep> encoding;
00163   EncodeType encodetype;
00164   void *remainder;
00165   GPBufferBase gremainder;
00166 public:
00167   Unicode(void);
00169   virtual ~Unicode();
00170 
00171   static GP<GStringRep> create(const unsigned int sz);
00172   static GP<GStringRep> create(void const * const buf, unsigned int bufsize,
00173                                const EncodeType, const GP<GStringRep> &encoding);
00174   static GP<GStringRep> create( void const * const buf,
00175     unsigned int size, const EncodeType encodetype );
00176   static GP<GStringRep> create( void const * const buf,
00177     const unsigned int size, GP<GStringRep> encoding );
00178   static GP<GStringRep> create( void const * const buf,
00179     const unsigned int size, const GP<Unicode> &remainder );
00180 
00181 protected:
00182   virtual void set_remainder( void const * const buf, const unsigned int size,
00183     const EncodeType encodetype );
00184   virtual void set_remainder( void const * const buf, const unsigned int size,
00185     const GP<GStringRep> &encoding );
00186   virtual void set_remainder( const GP<Unicode> &remainder );
00187   virtual GP<Unicode> get_remainder(void) const;
00188 };
00189 
00190 static unsigned long xUTF16toUCS4(unsigned short const *&s,void const * const);
00191 static unsigned long UTF16BEtoUCS4(unsigned char const *&s,void const * const);
00192 static unsigned long UTF16LEtoUCS4(unsigned char const *&s,void const * const);
00193 static unsigned long UCS4BEtoUCS4(unsigned char const *&s,void const * const);
00194 static unsigned long UCS4LEtoUCS4(unsigned char const *&s,void const * const);
00195 static unsigned long UCS4_3412toUCS4(unsigned char const *&s,void const * const);
00196 static unsigned long UCS4_2143toUCS4(unsigned char const *&s,void const * const);
00197 
00198 GP<GStringRep>
00199 GStringRep::Unicode::create(const unsigned int sz)
00200 {
00201   GP<GStringRep> gaddr;
00202   if (sz > 0)
00203   {
00204     GStringRep *addr;
00205     gaddr=(addr=new GStringRep::Unicode);
00206     addr->data=(char *)(::operator new(sz+1));
00207     addr->size = sz;
00208     addr->data[sz] = 0;
00209   }
00210   return gaddr;
00211 }
00212 
00213 GStringRep::Unicode::Unicode(void)
00214 : encodetype(XUTF8), gremainder(remainder,0,1) {}
00215 
00216 GStringRep::Unicode::~Unicode() {}
00217 
00218 GP<GStringRep>
00219 GStringRep::Unicode::create(
00220   void const * const xbuf,
00221   unsigned int bufsize,
00222   const EncodeType t,
00223   const GP<GStringRep> &encoding)
00224 {
00225   return (encoding->size)
00226     ?create(xbuf,bufsize,encoding)
00227     :create(xbuf,bufsize,t);
00228 }
00229 
00230 GP<GStringRep>
00231 GStringRep::Unicode::create(
00232   void const * const xbuf,
00233   const unsigned int bufsize,
00234   const GP<Unicode> &xremainder )
00235 {
00236   Unicode *r=xremainder;
00237   GP<GStringRep> retval;
00238   if(r)
00239   {
00240     const int s=r->gremainder;
00241     if(xbuf && bufsize)
00242     {
00243       if(s)
00244       {
00245         void *buf;
00246         GPBufferBase gbuf(buf,s+bufsize,1);
00247         memcpy(buf,r->remainder,s);
00248         memcpy((void *)((size_t)buf+s),xbuf,bufsize);
00249         retval=((r->encoding)
00250           ?create(buf,s+bufsize,r->encoding)
00251           :create(buf,s+bufsize,r->encodetype));
00252       }else
00253       {
00254         retval=((r->encoding)
00255           ?create(xbuf,bufsize,r->encoding)
00256           :create(xbuf,bufsize,r->encodetype));
00257       }
00258     }else if(s)
00259     {
00260       void *buf;
00261       GPBufferBase gbuf(buf,s,1);
00262       memcpy(buf,r->remainder,s);
00263       retval=((r->encoding)
00264         ?create(buf,s,r->encoding)
00265         :create(buf,s,r->encodetype));
00266     }else
00267     {
00268       retval=((r->encoding)
00269         ?create(0,0,r->encoding)
00270         :create(0,0,r->encodetype));
00271     }
00272   }else
00273   {
00274     retval=create(xbuf,bufsize,XUTF8);
00275   }
00276   return retval;
00277 }
00278 
00279 #if HAS_ICONV
00280 
00281 template<typename _T> inline size_t 
00282 iconv_adaptor(size_t(*iconv_func)(iconv_t, _T, size_t *, char**, size_t*),
00283               iconv_t cd, char **inbuf, size_t *inbytesleft,
00284               char **outbuf, size_t *outbytesleft)
00285 {
00286   return iconv_func (cd, (_T)inbuf, inbytesleft, outbuf, outbytesleft);
00287 }
00288 #endif
00289 
00290 GP<GStringRep>
00291 GStringRep::Unicode::create(
00292   void const * const xbuf,
00293   unsigned int bufsize,
00294   GP<GStringRep> encoding)
00295 {
00296   GP<GStringRep> retval;
00297   GStringRep *e=encoding;
00298   if(e)
00299   {
00300     e=(encoding=e->upcase());
00301   }
00302   if(!e || !e->size)
00303   {
00304     retval=create(xbuf,bufsize,XOTHER);
00305   }else if(!e->cmp("UTF8") || !e->cmp("UTF-8"))
00306   {
00307     retval=create(xbuf,bufsize,XUTF8);
00308   }else if(!e->cmp("UTF16")|| !e->cmp("UTF-16")
00309     || !e->cmp("UCS2") || !e->cmp("UCS2"))
00310   {
00311     retval=create(xbuf,bufsize,XUTF16);
00312   }else if(!e->cmp("UCS4") || !e->cmp("UCS-4"))
00313   {
00314     retval=create(xbuf,bufsize,XUCS4);
00315   }else
00316   {
00317 #if HAS_ICONV
00318     EncodeType t=XOTHER;
00319     void const * const buf=checkmarks(xbuf,bufsize,t); 
00320     if(t != XOTHER)
00321     {
00322       retval=create(xbuf,bufsize,t);
00323     }else if(buf && bufsize)
00324     {
00325       unsigned char const *eptr=(unsigned char *)buf;
00326       unsigned int j=0;
00327       for(j=0;(j<bufsize)&&*eptr;j++,eptr++)
00328         EMPTY_LOOP;
00329       if (j)
00330       {
00331         unsigned char const *ptr=(unsigned char *)buf;
00332         if(e)
00333         {
00334           iconv_t cv=iconv_open("UTF-8",(const char *)e);
00335           if(cv == (iconv_t)(-1))
00336           { 
00337             const int i=e->search('-');
00338             if(i>=0)
00339             {
00340               cv=iconv_open("UTF-8",e->data+i+1);
00341             }
00342           }
00343           if(cv == (iconv_t)(-1))
00344           { 
00345             retval=create(0,0,XOTHER);
00346           }else
00347           {
00348             size_t ptrleft=(eptr-ptr); 
00349             char *utf8buf;
00350             size_t pleft=6*ptrleft+1;
00351             GPBuffer<char> gutf8buf(utf8buf,pleft);
00352             char *p=utf8buf;
00353             unsigned char const *last=ptr;
00354             for(;iconv_adaptor(iconv, cv, (char**)&ptr, &ptrleft, &p, &pleft);last=ptr) 
00355               EMPTY_LOOP;
00356             iconv_close(cv);
00357             retval=create(utf8buf,(size_t)last-(size_t)buf,t);
00358             retval->set_remainder(last,(size_t)eptr-(size_t)last,e);
00359           }
00360         }
00361       }else
00362       {
00363         retval=create(0,0,XOTHER);
00364         retval->set_remainder(0,0,e);
00365       }
00366     }
00367 #else
00368     retval=create(xbuf,bufsize,XOTHER);
00369 #endif
00370   }
00371   return retval;
00372 }
00373 
00374 GP<GStringRep>
00375 GStringRep::Unicode::create(
00376   void const * const xbuf,
00377   unsigned int bufsize,
00378   EncodeType t)
00379 {
00380   GP<GStringRep> gretval;
00381   GStringRep *retval=0;
00382   void const * const buf=checkmarks(xbuf,bufsize,t); 
00383   if(buf && bufsize)
00384   {
00385     unsigned char const *eptr=(unsigned char *)buf;
00386     unsigned int maxutf8size=0;
00387     void const* const xeptr=(void const *)((size_t)eptr+bufsize);
00388     switch(t)
00389     {
00390       case XUCS4:
00391       case XUCS4BE:
00392       case XUCS4LE:
00393       case XUCS4_2143:
00394       case XUCS4_3412:
00395       {
00396         for(unsigned long w;
00397           (eptr<xeptr)&&(w=*(unsigned long const *)eptr);
00398           eptr+=sizeof(unsigned long))
00399         {
00400           maxutf8size+=(w>0x7f)?6:1;
00401         }
00402         break;
00403       }
00404       case XUTF16:
00405       case XUTF16BE:
00406       case XUTF16LE:
00407       {
00408         for(unsigned short w;
00409           (eptr<xeptr)&&(w=*(unsigned short const *)eptr);
00410           eptr+=sizeof(unsigned short))
00411         {
00412           maxutf8size+=3;
00413         }
00414         break;
00415       }
00416       case XUTF8:
00417         for(;(eptr<xeptr)&&*eptr;maxutf8size++,eptr++)
00418           EMPTY_LOOP;
00419         break;
00420       case XEBCDIC:
00421         for(;(eptr<xeptr)&&*eptr;eptr++)
00422         {
00423           maxutf8size+=(*eptr>0x7f)?2:1;
00424         }
00425         break;
00426       default:
00427         break;
00428     }
00429     unsigned char *utf8buf=0;
00430     GPBuffer<unsigned char> gutf8buf(utf8buf,maxutf8size+1);
00431     utf8buf[0]=0;
00432     if (maxutf8size)
00433     {
00434       unsigned char *optr=utf8buf;
00435       int len=0;
00436       unsigned char const *iptr=(unsigned char *)buf;
00437       unsigned long w;
00438       switch(t)
00439       {
00440         case XUCS4:
00441           for(;
00442             (iptr<eptr)&&(w=*(unsigned long const *)iptr);
00443             len++,iptr+=sizeof(unsigned long const))
00444           {
00445             optr=UCS4toUTF8(w,optr);
00446           }
00447           break;
00448         case XUCS4BE:
00449           for(;(w=UCS4BEtoUCS4(iptr,eptr));len++)
00450           {
00451             optr=UCS4toUTF8(w,optr);
00452           }
00453           break;
00454         case XUCS4LE:
00455           for(;(w=UCS4LEtoUCS4(iptr,eptr));len++)
00456           {
00457             optr=UCS4toUTF8(w,optr);
00458           }
00459           break;
00460         case XUCS4_2143:
00461           for(;(w=UCS4_2143toUCS4(iptr,eptr));len++)
00462           {
00463             optr=UCS4toUTF8(w,optr);
00464           }
00465           break;
00466         case XUCS4_3412:
00467           for(;(w=UCS4_3412toUCS4(iptr,eptr));len++)
00468           {
00469             optr=UCS4toUTF8(w,optr);
00470           }
00471           break;
00472         case XUTF16:
00473           for(;
00474             (w=xUTF16toUCS4((unsigned short const*&)iptr,eptr));
00475             len++)
00476           {
00477             optr=UCS4toUTF8(w,optr);
00478           }
00479           break;
00480         case XUTF16BE:
00481           for(;(w=UTF16BEtoUCS4(iptr,eptr));len++)
00482           {
00483             optr=UCS4toUTF8(w,optr);
00484           }
00485           break;
00486         case XUTF16LE:
00487           for(;(w=UTF16LEtoUCS4(iptr,eptr));len++)
00488           {
00489             optr=UCS4toUTF8(w,optr);
00490           }
00491           break;
00492         case XUTF8:
00493           for(;(w=UTF8toUCS4(iptr,eptr));len++)
00494           {
00495             optr=UCS4toUTF8(w,optr);
00496           }
00497           break;
00498         case XEBCDIC:
00499           for(;(iptr<eptr)&&(w=*iptr++);len++)
00500           {
00501             optr=UCS4toUTF8(w,optr);
00502           }
00503           break;
00504         default:
00505           break;
00506       }
00507       const unsigned int size=(size_t)optr-(size_t)utf8buf;
00508       if(size)
00509       {
00510           retval=(gretval=GStringRep::Unicode::create(size));
00511         memcpy(retval->data,utf8buf,size);
00512       }else
00513       {
00514           retval=(gretval=GStringRep::Unicode::create(1));
00515         retval->size=size;
00516       }
00517       retval->data[size]=0;
00518       gutf8buf.resize(0);
00519       const size_t s=(size_t)eptr-(size_t)iptr;
00520       retval->set_remainder(iptr,s,t);
00521     }
00522   }
00523   if(!retval)
00524   {
00525     retval=(gretval=GStringRep::Unicode::create(1));
00526     retval->data[0]=0;
00527     retval->size=0;
00528     retval->set_remainder(0,0,t);
00529   }
00530   return gretval;
00531 }
00532 
00533 static unsigned long
00534 xUTF16toUCS4(unsigned short const *&s,void const * const eptr)
00535 {
00536   unsigned long U=0;
00537   unsigned short const * const r=s+1;
00538   if(r <= eptr)
00539   {
00540     unsigned long const W1=s[0];
00541     if((W1<0xD800)||(W1>0xDFFF))
00542     {
00543       if((U=W1))
00544       {
00545         s=r;
00546       }
00547     }else if(W1<=0xDBFF)
00548     {
00549       unsigned short const * const rr=r+1;
00550       if(rr <= eptr)
00551       {
00552         unsigned long const W2=s[1];
00553         if(((W2>=0xDC00)||(W2<=0xDFFF))&&((U=(0x1000+((W1&0x3ff)<<10))|(W2&0x3ff))))
00554         {
00555           s=rr;
00556         }else
00557         {
00558           U=(unsigned int)(-1)-W1;
00559           s=r;
00560         }
00561       }
00562     }
00563   }
00564   return U;
00565 }
00566 
00567 static unsigned long
00568 UTF16BEtoUCS4(unsigned char const *&s,void const * const eptr)
00569 {
00570   unsigned long U=0;
00571   unsigned char const * const r=s+2;
00572   if(r <= eptr)
00573   {
00574     unsigned long const C1MSB=s[0];
00575     if((C1MSB<0xD8)||(C1MSB>0xDF))
00576     {
00577       if((U=((C1MSB<<8)|((unsigned long)s[1]))))
00578       {
00579         s=r;
00580       }
00581     }else if(C1MSB<=0xDB)
00582     {
00583       unsigned char const * const rr=r+2;
00584       if(rr <= eptr)
00585       {
00586         unsigned long const C2MSB=s[2];
00587         if((C2MSB>=0xDC)||(C2MSB<=0xDF))
00588         {
00589           U=0x10000+((unsigned long)s[1]<<10)+(unsigned long)s[3]
00590             +(((C1MSB<<18)|(C2MSB<<8))&0xc0300);
00591           s=rr;
00592         }else
00593         {
00594           U=(unsigned int)(-1)-((C1MSB<<8)|((unsigned long)s[1]));
00595           s=r;
00596         }
00597       }
00598     }
00599   }
00600   return U;
00601 }
00602 
00603 static unsigned long
00604 UTF16LEtoUCS4(unsigned char const *&s,void const * const eptr)
00605 {
00606   unsigned long U=0;
00607   unsigned char const * const r=s+2;
00608   if(r <= eptr)
00609   {
00610     unsigned long const C1MSB=s[1];
00611     if((C1MSB<0xD8)||(C1MSB>0xDF))
00612     {
00613       if((U=((C1MSB<<8)|((unsigned long)s[0]))))
00614       {
00615         s=r;
00616       }
00617     }else if(C1MSB<=0xDB)
00618     {
00619       unsigned char const * const rr=r+2;
00620       if(rr <= eptr)
00621       {
00622         unsigned long const C2MSB=s[3];
00623         if((C2MSB>=0xDC)||(C2MSB<=0xDF))
00624         {
00625           U=0x10000+((unsigned long)s[0]<<10)+(unsigned long)s[2]
00626             +(((C1MSB<<18)|(C2MSB<<8))&0xc0300);
00627           s=rr;
00628         }else
00629         {
00630           U=(unsigned int)(-1)-((C1MSB<<8)|((unsigned long)s[1]));
00631           s=r;
00632         }
00633       }
00634     }
00635   }
00636   return U;
00637 }
00638 
00639 static unsigned long
00640 UCS4BEtoUCS4(unsigned char const *&s,void const * const eptr)
00641 {
00642   unsigned long U=0;
00643   unsigned char const * const r=s+4;
00644   if(r<=eptr)
00645   {
00646     U=(((((((unsigned long)s[0]<<8)|(unsigned long)s[1])<<8)|(unsigned long)s[2])<<8)|(unsigned long)s[3]);
00647     if(U)
00648     {
00649       s=r;
00650     } 
00651   }
00652   return U;
00653 }
00654 
00655 static unsigned long
00656 UCS4LEtoUCS4(unsigned char const *&s,void const * const eptr)
00657 {
00658   unsigned long U=0;
00659   unsigned char const * const r=s+4;
00660   if(r<=eptr)
00661   {
00662     U=(((((((unsigned long)s[3]<<8)|(unsigned long)s[2])<<8)|(unsigned long)s[1])<<8)|(unsigned long)s[0]);
00663     if(U)
00664     {
00665       s=r;
00666     }
00667   }
00668   return U;
00669 }
00670 
00671 static unsigned long
00672 UCS4_2143toUCS4(unsigned char const *&s,void const * const eptr)
00673 {
00674   unsigned long U=0;
00675   unsigned char const * const r=s+4;
00676   if(r<=eptr)
00677   {
00678     U=(((((((unsigned long)s[1]<<8)|(unsigned long)s[0])<<8)|(unsigned long)s[3])<<8)|(unsigned long)s[2]);
00679     if(U)
00680     {
00681       s=r;
00682     }
00683   }
00684   return U;
00685 }
00686 
00687 static unsigned long
00688 UCS4_3412toUCS4(unsigned char const *&s,void const * const eptr)
00689 {
00690   unsigned long U=0;
00691   unsigned char const * const r=s+4;
00692   if(r<=eptr)
00693   {
00694     U=(((((((unsigned long)s[2]<<8)|(unsigned long)s[3])<<8)|(unsigned long)s[0])<<8)|(unsigned long)s[1]);
00695     if(U)
00696     {
00697       s=r;
00698     }
00699   }
00700   return U;
00701 }
00702 
00703 void
00704 GStringRep::Unicode::set_remainder( void const * const buf,
00705    const unsigned int size, const EncodeType xencodetype )
00706 {
00707   gremainder.resize(size,1);
00708   if(size)
00709     memcpy(remainder,buf,size);
00710   encodetype=xencodetype;
00711   encoding=0;
00712 }
00713 
00714 void
00715 GStringRep::Unicode::set_remainder( void const * const buf,
00716    const unsigned int size, const GP<GStringRep> &xencoding )
00717 {
00718   gremainder.resize(size,1);
00719   if(size)
00720     memcpy(remainder,buf,size);
00721   encoding=xencoding;
00722   encodetype=XOTHER;
00723 }
00724 
00725 void
00726 GStringRep::Unicode::set_remainder( const GP<GStringRep::Unicode> &xremainder )
00727 {
00728   if(xremainder)
00729   {
00730     const int size=xremainder->gremainder;
00731     gremainder.resize(size,1);
00732     if(size)
00733       memcpy(remainder,xremainder->remainder,size);
00734     encodetype=xremainder->encodetype;
00735   }else
00736   {
00737     gremainder.resize(0,1);
00738     encodetype=XUTF8;
00739   }
00740 }
00741 
00742 GP<GStringRep::Unicode>
00743 GStringRep::Unicode::get_remainder( void ) const
00744 {
00745   return const_cast<GStringRep::Unicode *>(this);
00746 }
00747 
00748 GUTF8String 
00749 GUTF8String::create(void const * const buf,const unsigned int size,
00750     const EncodeType encodetype, const GUTF8String &encoding)
00751 {
00752   return encoding.length()
00753     ?create(buf,size,encodetype)
00754     :create(buf,size,encoding);
00755 }
00756 
00757 GUTF8String 
00758 GUTF8String::create( void const * const buf,
00759   unsigned int size, const EncodeType encodetype )
00760 {
00761   GUTF8String retval;
00762   retval.init(GStringRep::Unicode::create(buf,size,encodetype));
00763   return retval;
00764 }
00765 
00766 GUTF8String 
00767 GUTF8String::create( void const * const buf,
00768   const unsigned int size, const GP<GStringRep::Unicode> &remainder)
00769 {
00770   GUTF8String retval;
00771   retval.init(GStringRep::Unicode::create(buf,size,remainder));
00772   return retval;
00773 }
00774 
00775 GUTF8String 
00776 GUTF8String::create( void const * const buf,
00777   const unsigned int size, const GUTF8String &encoding )
00778 {
00779   GUTF8String retval;
00780   retval.init(GStringRep::Unicode::create(buf,size,encoding ));
00781   return retval;
00782 }
00783 
00784 
00785 #ifdef HAVE_NAMESPACES
00786 }
00787 # ifndef NOT_USING_DJVU_NAMESPACE
00788 using namespace DJVU;
00789 # endif
00790 #endif