Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

String.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file String.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032 
00033         class MutableString(T) : String!(T)
00034         {
00035                 // reset the content 
00036                 MutableString set (T[] chars, bool mutable=true);
00037                 MutableString set (String other, bool mutable=true);
00038 
00039                 // get the index and length of the current selection
00040                 uint selection (inout int length);
00041 
00042                 // make a selection
00043                 MutableString select (int start=0, int length=int.max);
00044 
00045                 // move the selection around
00046                 bool select (T c);
00047                 bool select (T[] chars);
00048                 bool select (String other);
00049                 bool rselect (T c);
00050                 bool rselect (T[] chars);
00051                 bool rselect (String other);
00052 
00053                 // append behind current selection
00054                 MutableString append (String other);
00055                 MutableString append (char[] other);
00056                 MutableString append (wchar[] other);
00057                 MutableString append (dchar[] other);
00058                 MutableString append (T chr, int count=1);
00059                 MutableString append (int value, T[] format=null);
00060                 MutableString append (long value, T[] format=null);
00061                 MutableString append (double value, T[] format=null);
00062 
00063                 // format and layout behind current selection
00064                 MutableString format (T[] format, ...);
00065                 MutableString layout (T[] layout ...);
00066         
00067                 // insert before current selection
00068                 MutableString prepend (T[] other);
00069                 MutableString prepend (String other);
00070                 MutableString prepend (T chr, int count=1);
00071 
00072                 // replace current selection
00073                 MutableString replace (T chr);
00074                 MutableString replace (T[] other);
00075                 MutableString replace (String other);
00076 
00077                 // remove current selection
00078                 MutableString remove ();
00079 
00080                 // truncate at point, or current selection
00081                 MutableString truncate (int point = int.max);
00082 
00083                 // trim content
00084                 MutableString trim ();
00085 
00086                 // return content
00087                 T[] aliasOf ();
00088         }
00089 
00090         class String(T) : UniString
00091         {
00092                 // iterate across content
00093                 opApply (int delegate(inout T) dg);
00094 
00095                 // hash content
00096                 uint toHash ();
00097 
00098                 // return length of content
00099                 uint length ();
00100 
00101                 // compare content
00102                 bool equals  (T[] other);
00103                 bool equals  (String other);
00104                 bool ends    (T[] other);
00105                 bool ends    (String other);
00106                 bool starts  (T[] other);
00107                 bool starts  (String other);
00108                 int compare  (T[] other);
00109                 int compare  (String other);
00110                 int opEquals (Object other);
00111                 int opCmp    (Object other);
00112 
00113                 // copy content
00114                 T[] copy (T[] dst);
00115                 T[] copy ();
00116         }
00117 
00118         abstract class UniString
00119         {
00120                 // convert content
00121                 abstract char[]  utf8  (char[]  dst = null);
00122                 abstract wchar[] utf16 (wchar[] dst = null);
00123                 abstract dchar[] utf32 (dchar[] dst = null);
00124         }
00125 
00126 
00127                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00128 
00129 
00130         @version        Initial version, December 2005
00131               
00132         @author         Kris
00133 
00134 *******************************************************************************/
00135 
00136 module mango.text.String;
00137 
00138 private import  mango.text.Text;
00139 
00140 private import  mango.convert.Type,
00141                 mango.convert.Format,
00142                 mango.convert.Unicode;
00143 
00144 private import  mango.text.model.UniString;
00145 
00146 /*******************************************************************************
00147 
00148 *******************************************************************************/
00149 
00150 private extern (C) void memmove (void* dst, void* src, uint bytes);
00151 
00152 
00153 /*******************************************************************************
00154 
00155         MutableString is a string class that stores Unicode characters.
00156 
00157         Indexes and lengths of strings always count code units, not code 
00158         points. This is similar to traditional multi-byte string handling. 
00159         Operations on strings do not test for code point boundaries since
00160         the approach taken here is based upon pattern-matching rather than
00161         direct indexing.
00162 
00163         MutableString maintains a current "selection", controlled via the 
00164         select() and rselect() methods. Append(), prepend(), replace() and
00165         remove() each operate with respect to the selection. The select()
00166         methods themselves operate with respect to the current selection
00167         also, providing a means of iterating across matched patterns. To
00168         reset the selection to the entire string, use the select() method 
00169         with no arguments. 
00170        
00171 *******************************************************************************/
00172 
00173 class MutableStringTemplate(T) : StringTemplate!(T)
00174 {
00175         public  alias append                    opCat;
00176 
00177         private alias MutableStringTemplate     MutableString;
00178         private alias FormatStructTemplate!(T)  Format;
00179         private  alias Unicode.Into!(T)         Into;   
00180 
00181         public  Into                    into;           // unicode converter
00182         private T[]                     scratch;        // formatting scratchpad
00183         private T[]                     converts;       // unicode buffer
00184         private Format                  formatter;      // printf formatter
00185 
00186 
00187         /***********************************************************************
00188         
00189                 Create an empty MutableString with the specified available 
00190                 space
00191 
00192         ***********************************************************************/
00193 
00194         this (uint space = 0)
00195         {
00196                 content.length = space;
00197                 mutable = true;
00198                 setup ();
00199         }
00200 
00201         /***********************************************************************
00202         
00203                 Create a MutableString upon the provided content. If said 
00204                 content is immutable (read-only) then you might consider 
00205                 setting the 'mutable' parameter to false. Doing so will 
00206                 avoid allocating heap-space for the content until it is 
00207                 modified.
00208 
00209         ***********************************************************************/
00210 
00211         this (T[] content, bool mutable = true)
00212         {
00213                 set (content, mutable);
00214                 setup ();
00215         }
00216 
00217         /***********************************************************************
00218         
00219                 Create a MutableString via the content of a MutableString. 
00220                 If said content is immutable (read-only) then you might 
00221                 consider setting the 'mutable' parameter to false. Doing 
00222                 so will avoid allocating heap-space for the content until 
00223                 it is modified via MutableString methods.
00224 
00225         ***********************************************************************/
00226         
00227         this (MutableString other, bool mutable = true)
00228         {
00229                 this (other.get, mutable);
00230         }
00231 
00232         /***********************************************************************
00233         
00234                 Create a MutableString via the content of a String. Note 
00235                 that the default is to assume the content is immutable
00236                 
00237         ***********************************************************************/
00238         
00239         this (String other, bool mutable = false)
00240         {
00241                 this (other.get, mutable);
00242         }
00243 
00244         /***********************************************************************
00245    
00246                 Set the content to the provided array. Parameter 'mutable'
00247                 specifies whether the given array is likely to change. If 
00248                 not, the array is aliased until such time it is altered.
00249                      
00250         ***********************************************************************/
00251 
00252         MutableString set (T[] chars, bool mutable = true)
00253         {
00254                 contentLength = chars.length;
00255                 select (0, contentLength);
00256 
00257                 if ((this.mutable = mutable) == true)
00258                      content = chars.dup;
00259                 else
00260                    content = chars;
00261                 return this;
00262         }
00263 
00264         /***********************************************************************
00265         
00266                 Replace the content of this MutableString. If the new content
00267                 is immutable (read-only) then you might consider setting the
00268                 'mutable' parameter to false. Doing so will avoid allocating
00269                 heap-space for the content until it is modified via one of
00270                 these methods.
00271 
00272         ***********************************************************************/
00273 
00274         MutableString set (String other, bool mutable = true)
00275         {
00276                 return set (other.get, mutable);
00277         }
00278 
00279         /***********************************************************************
00280 
00281                 Return the index and length of the current selection
00282 
00283         ***********************************************************************/
00284 
00285         uint selection (inout int length)
00286         {
00287                 length = selectLength;
00288                 return selectPoint;
00289         }
00290 
00291         /***********************************************************************
00292 
00293                 Explicitly set the current selection
00294 
00295         ***********************************************************************/
00296 
00297         MutableString select (int start=0, int length=int.max)
00298         {
00299                 pinIndices (start, length);
00300                 selectPoint = start;
00301                 selectLength = length;                
00302                 return this;
00303         }
00304 
00305         /***********************************************************************
00306         
00307                 Find the first occurrence of a BMP code point in a string.
00308                 A surrogate code point is found only if its match in the 
00309                 text is not part of a surrogate pair.
00310 
00311         ***********************************************************************/
00312 
00313         bool select (T c)
00314         {
00315                 int x = utils.indexOf (get(), c, selectPoint);
00316                 if (x >= 0)
00317                    {
00318                    select (x, 1);
00319                    return true;
00320                    }
00321                 return false;
00322         }
00323 
00324         /***********************************************************************
00325         
00326                 Find the first occurrence of a substring in a string. 
00327 
00328                 The substring is found at code point boundaries. That means 
00329                 that if the substring begins with a trail surrogate or ends 
00330                 with a lead surrogate, then it is found only if these 
00331                 surrogates stand alone in the text. Otherwise, the substring 
00332                 edge units would be matched against halves of surrogate pairs.
00333 
00334         ***********************************************************************/
00335 
00336         bool select (String other)
00337         {
00338                 return select (other.get);
00339         }
00340 
00341         /***********************************************************************
00342         
00343                 Find the first occurrence of a substring in a string. 
00344 
00345                 The substring is found at code point boundaries. That means 
00346                 that if the substring begins with a trail surrogate or ends 
00347                 with a lead surrogate, then it is found only if these 
00348                 surrogates stand alone in the text. Otherwise, the substring 
00349                 edge units would be matched against halves of surrogate pairs.
00350 
00351         ***********************************************************************/
00352 
00353         bool select (T[] chars)
00354         {
00355                 int x = utils.indexOf (get(), chars, selectPoint);
00356                 if (x >= 0)
00357                    {
00358                    select (x, chars.length);
00359                    return true;
00360                    }
00361                 return false;
00362         }
00363 
00364         /***********************************************************************
00365         
00366                 Find the last occurrence of a BMP code point in a string.
00367                 A surrogate code point is found only if its match in the 
00368                 text is not part of a surrogate pair.
00369 
00370         ***********************************************************************/
00371 
00372         bool rselect (T c)
00373         {
00374                 int x = utils.rIndexOf (get(), c, selectPoint+selectLength);               
00375                 if (x >= 0)
00376                    {
00377                    select (x, 1);
00378                    return true;
00379                    }
00380                 return false;
00381         }
00382 
00383         /***********************************************************************
00384         
00385                 Find the last occurrence of a BMP code point in a string.
00386                 A surrogate code point is found only if its match in the 
00387                 text is not part of a surrogate pair.
00388 
00389         ***********************************************************************/
00390 
00391         bool rselect (String other)
00392         {
00393                 return rselect (other.get);
00394         }
00395 
00396         /***********************************************************************
00397         
00398                 Find the last occurrence of a substring in a string. 
00399 
00400                 The substring is found at code point boundaries. That means 
00401                 that if the substring begins with a trail surrogate or ends 
00402                 with a lead surrogate, then it is found only if these 
00403                 surrogates stand alone in the text. Otherwise, the substring 
00404                 edge units would be matched against halves of surrogate pairs.
00405 
00406         ***********************************************************************/
00407 
00408         bool rselect (T[] chars)
00409         {
00410                 int x = utils.rIndexOf (get(), chars, selectPoint+selectLength);
00411                 if (x >= 0)
00412                    {
00413                    select (x, chars.length);
00414                    return true;
00415                    }
00416                 return false;
00417         }
00418 
00419         /***********************************************************************
00420         
00421                 Append partial text to this MutableString
00422 
00423         ***********************************************************************/
00424 
00425         MutableString append (String other)
00426         {
00427                 return append (other.get);
00428         }
00429 
00430         /***********************************************************************
00431         
00432                 Append text to this MutableString
00433 
00434         ***********************************************************************/
00435 
00436         MutableString append (char[] chars)
00437         {
00438                 convert (chars, Type.Utf8);
00439                 return this;
00440         }
00441 
00442         /***********************************************************************
00443         
00444                 Append text to this MutableString
00445 
00446         ***********************************************************************/
00447 
00448         MutableString append (wchar[] chars)
00449         {
00450                 convert (chars, Type.Utf16);
00451                 return this;
00452         }
00453 
00454         /***********************************************************************
00455         
00456                 Append text to this MutableString
00457 
00458         ***********************************************************************/
00459 
00460         MutableString append (dchar[] chars)
00461         {
00462                 convert (chars, Type.Utf32);
00463                 return this;
00464         }
00465 
00466         /***********************************************************************
00467         
00468                 Append a count of characters to this MutableString
00469 
00470         ***********************************************************************/
00471 
00472         MutableString append (T chr, int count=1)
00473         {
00474                 uint point = selectPoint + selectLength;
00475                 expand (point, count);
00476                 return set (chr, point, count);
00477         }
00478 
00479         /***********************************************************************
00480         
00481                 Append an integer to this MutableString, using standard 
00482                 printf() notation
00483 
00484         ***********************************************************************/
00485 
00486         MutableString append (int v, T[] format=null)
00487         {
00488                 formatter (format, &v, v.sizeof, Type.Int);
00489                 return this;
00490         }
00491 
00492         /***********************************************************************
00493         
00494                 Append a long to this MutableString, using standard 
00495                 printf() notation
00496 
00497         ***********************************************************************/
00498 
00499         MutableString append (long v, T[] format=null)
00500         {
00501                 formatter (format, &v, v.sizeof, Type.Long);
00502                 return this;
00503         }
00504 
00505         /***********************************************************************
00506         
00507                 Append a double to this MutableString, using standard 
00508                 printf() notation
00509 
00510         ***********************************************************************/
00511 
00512         MutableString append (double v, T[] format=null)
00513         {
00514                 formatter (format, &v, v.sizeof, Type.Double);
00515                 return this;
00516         }
00517 
00518         /**********************************************************************
00519 
00520                 Format a set of arguments using the standard printf()
00521                 formatting notation
00522 
00523         **********************************************************************/
00524 
00525         MutableString format (T[] fmt, ...)
00526         {
00527                 formatter (fmt, _arguments, _argptr);
00528                 return this;
00529         }
00530 
00531         /***********************************************************************
00532         
00533                 Insert characters into this MutableString
00534 
00535         ***********************************************************************/
00536 
00537         MutableString prepend (T chr, uint count=1)
00538         {
00539                 expand (selectPoint, count);
00540                 return set (chr, selectPoint, count);
00541         }
00542 
00543         /***********************************************************************
00544         
00545                 Insert text into this MutableString
00546 
00547         ***********************************************************************/
00548 
00549         MutableString prepend (T[] other)
00550         {
00551                 expand (selectPoint, other.length);
00552                 content[selectPoint..selectPoint+other.length] = other;
00553                 return this;
00554         }
00555 
00556         /***********************************************************************
00557         
00558                 Insert another String into this MutableString
00559 
00560         ***********************************************************************/
00561 
00562         MutableString prepend (String other)
00563         {       
00564                 return prepend (other.get);
00565         }
00566 
00567         /***********************************************************************
00568                 
00569                 Replace a section of this MutableString with the specified 
00570                 character
00571 
00572         ***********************************************************************/
00573 
00574         MutableString replace (T chr)
00575         {
00576                 return set (chr, selectPoint, selectLength);
00577         }
00578 
00579         /***********************************************************************
00580                 
00581                 Replace a section of this MutableString with the specified 
00582                 array
00583 
00584         ***********************************************************************/
00585 
00586         MutableString replace (T[] chars)
00587         {
00588                 int chunk = chars.length - selectLength;
00589                 if (chunk >= 0)
00590                     expand (selectPoint, chunk);
00591                 else
00592                    remove (-chunk);
00593 
00594                 content [selectPoint .. selectPoint+chars.length] = chars;
00595                 select (selectPoint, chars.length);
00596                 return this;
00597         }
00598 
00599         /***********************************************************************
00600                 
00601                 Replace a section of this MutableString with the specified 
00602                 String
00603 
00604         ***********************************************************************/
00605 
00606         MutableString replace (String other)
00607         {
00608                 return replace (other.get);
00609         }
00610 
00611         /***********************************************************************
00612         
00613                 Remove the selection from this MutableString and reset the
00614                 selection to zero length
00615 
00616         ***********************************************************************/
00617 
00618         MutableString remove ()
00619         {
00620                 remove (selectLength);
00621                 select (selectPoint, 0);
00622                 return this;
00623         }
00624 
00625         /***********************************************************************
00626         
00627                 Remove the selection from this MutableString and reset the
00628                 selection to zero length
00629 
00630         ***********************************************************************/
00631 
00632         private int remove (int count)
00633         {
00634                 int start = selectPoint;
00635                 pinIndices (start, count);
00636                 if (count > 0)
00637                    {
00638                    if (! mutable)
00639                          realloc ();
00640 
00641                    uint i = start + count;
00642                    memmove (content.ptr+start, content.ptr+i, (contentLength-i) * T.sizeof);
00643                    contentLength -= count;
00644                    }
00645                 return count;
00646         }
00647 
00648         /***********************************************************************
00649         
00650                 Truncate this string. Default behaviour is to truncate at 
00651                 the current append point
00652 
00653         ***********************************************************************/
00654 
00655         MutableString truncate (int index = int.max)
00656         {
00657                 if (index is int.max)
00658                     index = selectPoint + selectLength;
00659 
00660                 pinIndex (index);
00661                 contentLength = index;
00662         }
00663 
00664         /**********************************************************************
00665 
00666                 Arranges text strings in order, using indices to specify 
00667                 where each particular argument should be positioned within 
00668                 the text. This is handy for collating I18N components.
00669 
00670                 @code
00671                 auto string = new MutableString;
00672 
00673                 string.layout ("%2 %1", "one", "two");
00674                 @endcode
00675 
00676                 The index numbers range from one through nine      
00677               
00678         **********************************************************************/
00679 
00680         MutableString layout (T[][] layout ...)
00681         {
00682                 int     args;
00683                 bool    state;
00684 
00685                 args = layout.length - 1;
00686                 foreach (T c; layout[0])
00687                         {
00688                         if (state)
00689                            {
00690                            state = false;
00691                            if (c >= '1' || c <= '9')
00692                               {
00693                               uint index = c - '0';
00694                               if (index <= args)
00695                                  {
00696                                  append (layout[index]);
00697                                  continue;
00698                                  }
00699                               else
00700                                  formatter.error ("TextLayout : invalid argument");
00701                               }
00702                            }
00703                         else
00704                            if (c == '%')
00705                               {
00706                               state = true;
00707                               continue;
00708                               }
00709                         append (c);
00710                         }
00711                 return this;
00712         }
00713 
00714         /***********************************************************************
00715         
00716                 Remove leading and trailing whitespace from this String,
00717                 and reset the selection to the trimmed content
00718 
00719         ***********************************************************************/
00720 
00721         MutableString trim ()
00722         {
00723                 content = utils.trim (get());
00724                 select (0, contentLength = content.length);
00725                 return this;
00726         }
00727 
00728         /***********************************************************************
00729         
00730                 Return an alias to the content of this MutableString
00731 
00732         ***********************************************************************/
00733 
00734         T[] aliasOf ()
00735         {
00736                 return get ();
00737         }
00738 
00739 
00740         /* ================================================================== */
00741 
00742 
00743         /***********************************************************************
00744         
00745                 make room available to insert or append something
00746 
00747         ***********************************************************************/
00748 
00749         private final void expand (uint index, uint count)
00750         {
00751                 if (!mutable || (contentLength + count) > content.length)
00752                      realloc (count);
00753 
00754                 memmove (content.ptr+index+count, content.ptr+index, (contentLength - index) * T.sizeof);
00755                 selectLength += count;
00756                 contentLength += count;                
00757         }
00758                 
00759         /***********************************************************************
00760                 
00761                 Replace a section of this MutableString with the specified 
00762                 character
00763 
00764         ***********************************************************************/
00765 
00766         private final MutableString set (T chr, uint start, uint count)
00767         {
00768                 content [start..start+count] = chr;
00769                 return this;
00770         }
00771 
00772         /***********************************************************************
00773         
00774                 Allocate memory due to a change in the content. We handle 
00775                 the distinction between mutable and immutable here.
00776 
00777         ***********************************************************************/
00778 
00779         private final void realloc (uint count = 0)
00780         {
00781                 uint size = (content.length + count + 127) & ~127;
00782                 
00783                 if (mutable)
00784                     content.length = size;
00785                 else
00786                    {
00787                    mutable = true;
00788                    T[] x = content;
00789                    content = new T[size];
00790                    if (contentLength)
00791                        content[0..contentLength] = x;
00792                    }
00793         }
00794 
00795         /***********************************************************************
00796         
00797                 Internal method to support MutableString appending
00798 
00799         ***********************************************************************/
00800 
00801         private final MutableString append (T* chars, uint count)
00802         {
00803                 uint point = selectPoint + selectLength;
00804                 expand (point, count);
00805                 content[point .. point+count] = chars[0 .. count];
00806                 return this;
00807         }
00808 
00809         /***********************************************************************
00810         
00811                 Initialize this MutableString. Allocate conversion buffers
00812                 and prime the formatter
00813 
00814         ***********************************************************************/
00815 
00816         private void setup (Format.DblFormat df = null)
00817         {
00818                 
00819                 scratch  = new T[64];
00820                 converts = new T[256];
00821                 formatter.ctor (&convert, null, scratch, df);                
00822         }
00823 
00824         /**********************************************************************
00825 
00826                 Support for the formatter, to convert from one encoding
00827                 to another
00828 
00829         **********************************************************************/
00830 
00831         private uint convert (void[] v, uint type)   
00832         {
00833                 // convert as required
00834                 auto s = cast(T[]) into.convert (v, type, converts);
00835                         
00836                 // hang onto conversion buffer when it grows
00837                 if (s.length > converts.length)
00838                     converts = s;
00839 
00840                 // append to string
00841                 append (s.ptr, s.length);
00842                 return s.length;
00843         }
00844 }
00845 
00846 
00847 
00848 /*******************************************************************************
00849 
00850         Immutable string
00851 
00852 *******************************************************************************/
00853 
00854 class StringTemplate(T) : UniString
00855 {
00856         public alias int delegate (T[] a, T[] b) Comparator;
00857         public alias get                opIndex;
00858 
00859         private alias StringTemplate    String;
00860 
00861         // unicode converter and utility functions
00862         public Unicode.From!(T)         from;
00863         public TextTemplate!(T)         utils;
00864 
00865         // the core of the String and MutableString attributes. The name 
00866         // 'contentLength' is used rather than the more obvious 'length' 
00867         // since there is a collision with the noxious array[length] sugar
00868         protected T[]                   content;
00869         protected uint                  selectPoint,
00870                                         selectLength,
00871                                         contentLength;
00872 
00873         // this should probably be in MutableString only, but there seems to 
00874         // be a compiler bug where it doesn't get initialised correctly,
00875         // and it's perhaps useful to have here for when a MutableString is
00876         // passed as a String argument.
00877         protected bool                  mutable;
00878         
00879         private Comparator              comparator;
00880 
00881         /***********************************************************************
00882         
00883                 Hidden constructor
00884 
00885         ***********************************************************************/
00886 
00887         private this ()
00888         {
00889                 this.comparator = &simpleComparator;
00890         }
00891 
00892         /***********************************************************************
00893         
00894                 Construct read-only wrapper around the given content
00895 
00896         ***********************************************************************/
00897 
00898         this (T[] content)
00899         {
00900                 this();
00901                 this.content = content;
00902                 this.selectPoint = 0;
00903                 this.selectLength = this.contentLength = content.length;
00904         }
00905 
00906         /***********************************************************************
00907         
00908                 Set the comparator delegate
00909 
00910         ***********************************************************************/
00911 
00912         void setComparator (Comparator comparator)
00913         {
00914                 this.comparator = comparator;
00915         }
00916 
00917         /***********************************************************************
00918         
00919                 Hash this String
00920 
00921         ***********************************************************************/
00922 
00923         override uint toHash ()
00924         {
00925                 return hash (content [0 .. contentLength]);
00926         }
00927 
00928         /***********************************************************************
00929         
00930                 Return the length of the valid content
00931 
00932         ***********************************************************************/
00933 
00934         uint length ()
00935         {
00936                 return contentLength;
00937         }
00938 
00939         /***********************************************************************
00940         
00941                 Is this String equal to another?
00942 
00943         ***********************************************************************/
00944 
00945         bool equals (String other)
00946         {
00947                 if (other is this)
00948                     return true;
00949                 return equals (other.get);
00950         }
00951 
00952         /***********************************************************************
00953         
00954                 Is this String equal to the the provided text?
00955 
00956         ***********************************************************************/
00957 
00958         bool equals (T[] other)
00959         {
00960                 if (other.length == contentLength)
00961                     return utils.equal (other.ptr, content.ptr, contentLength);
00962                 return false;
00963         }
00964 
00965         /***********************************************************************
00966         
00967                 Does this String end with another?
00968 
00969         ***********************************************************************/
00970 
00971         bool ends (String other)
00972         {
00973                 return ends (other.get);
00974         }
00975 
00976         /***********************************************************************
00977         
00978                 Does this String end with the specified string?
00979 
00980         ***********************************************************************/
00981 
00982         bool ends (T[] chars)
00983         {
00984                 if (chars.length <= contentLength)
00985                     return utils.equal (content.ptr+(contentLength-chars.length), chars.ptr, chars.length);
00986                 return false;
00987         }
00988 
00989         /***********************************************************************
00990         
00991                 Does this String start with another?
00992 
00993         ***********************************************************************/
00994 
00995         bool starts (String other)
00996         {
00997                 return starts (other.get);
00998         }
00999 
01000         /***********************************************************************
01001         
01002                 Does this String start with the specified string?
01003 
01004         ***********************************************************************/
01005 
01006         bool starts (T[] chars)
01007         {
01008                 if (chars.length <= contentLength)                
01009                     return utils.equal (content.ptr, chars.ptr, chars.length);
01010                 return false;
01011         }
01012 
01013         /***********************************************************************
01014         
01015                 Compare this String start with another. Returns 0 if the 
01016                 content matches, less than zero if this String is "less"
01017                 than the other, or greater than zero where this String 
01018                 is "bigger".
01019 
01020         ***********************************************************************/
01021 
01022         int compare (String other)
01023         {
01024                 if (other is this)
01025                     return 0;
01026 
01027                 return compare (other.get);
01028         }
01029 
01030         /***********************************************************************
01031         
01032                 Compare this String start with an array. Returns 0 if the 
01033                 content matches, less than zero if this String is "less"
01034                 than the other, or greater than zero where this String 
01035                 is "bigger".
01036 
01037         ***********************************************************************/
01038 
01039         int compare (T[] chars)
01040         {
01041                 return comparator (get(), chars);
01042         }
01043 
01044         /***********************************************************************
01045         
01046                 Return content from this String 
01047                 
01048                 A slice of dst is returned, representing a copy of the 
01049                 content. The slice is clipped to the minimum of either 
01050                 the length of the provided array, or the length of the 
01051                 content minus the stipulated start point
01052 
01053         ***********************************************************************/
01054 
01055         T[] copy (T[] dst)
01056         {
01057                 uint i = contentLength;
01058                 if (i > dst.length)
01059                     i = dst.length;
01060 
01061                 return dst [0 .. i] = content [0 .. i];
01062         }
01063 
01064         /***********************************************************************
01065         
01066                 Return dup'd content from this String 
01067 
01068         ***********************************************************************/
01069 
01070         T[] copy ()
01071         {
01072                 return content [0 .. contentLength].dup;
01073         }
01074 
01075         /***********************************************************************
01076 
01077                 Convert to the AbstractString types. The optional argument
01078                 dst will be resized as required to house the conversion. 
01079                 To minimize heap allocation, use the following pattern:
01080 
01081                         String  string;
01082 
01083                         wchar[] buffer;
01084                         wchar[] result = string.toUtf16 (buffer);
01085 
01086                         if (result.length > buffer.length)
01087                             buffer = result;
01088 
01089                You can also provide a buffer from the stack, but the output 
01090                will be moved to the heap if said buffer is not large enough
01091 
01092         ***********************************************************************/
01093 
01094         char[] utf8 (char[] dst = null)
01095         {
01096                 return cast(char[]) from.convert (get(), Type.Utf8, dst);
01097         }
01098 
01099         wchar[] utf16 (wchar[] dst = null)
01100         {
01101                 return cast(wchar[]) from.convert (get(), Type.Utf16, dst);
01102         }
01103 
01104         dchar[] utf32 (dchar[] dst = null)
01105         {
01106                 return cast(dchar[]) from.convert (get(), Type.Utf32, dst);
01107         }
01108 
01109         /**********************************************************************
01110 
01111                 Iterate over the characters in this string. Note that 
01112                 this is a read-only freachable ~ the worst a user can
01113                 do is alter the temporary 'c'
01114 
01115         **********************************************************************/
01116 
01117         int opApply (int delegate(inout T) dg)
01118         {
01119                 int result = 0;
01120 
01121                 foreach (T c; get())
01122                          if ((result = dg (c)) != 0)
01123                              break;
01124                 return result;
01125         }
01126 
01127         /***********************************************************************
01128         
01129                 Compare this String to another
01130 
01131         ***********************************************************************/
01132 
01133         final override int opCmp (Object o)
01134         {
01135                 auto other = cast (String) o;
01136 
01137                 if (other is null)
01138                     return -1;
01139 
01140                 return compare (other);
01141         }
01142 
01143         /***********************************************************************
01144         
01145                 Is this String equal to another?
01146 
01147         ***********************************************************************/
01148 
01149         final override int opEquals (Object o)
01150         {
01151                 auto other = cast (String) o;
01152 
01153                 if (other is null)
01154                     return 0;
01155 
01156                 return equals (other);
01157         }
01158 
01159         /**********************************************************************
01160 
01161             hash() -- hash a variable-length key into a 32-bit value
01162 
01163               k     : the key (the unaligned variable-length array of bytes)
01164               len   : the length of the key, counting by bytes
01165               level : can be any 4-byte value
01166 
01167             Returns a 32-bit value.  Every bit of the key affects every bit of
01168             the return value.  Every 1-bit and 2-bit delta achieves avalanche.
01169 
01170             About 4.3*len + 80 X86 instructions, with excellent pipelining
01171 
01172             The best hash table sizes are powers of 2.  There is no need to do
01173             mod a prime (mod is sooo slow!).  If you need less than 32 bits,
01174             use a bitmask.  For example, if you need only 10 bits, do
01175 
01176                         h = (h & hashmask(10));
01177 
01178             In which case, the hash table should have hashsize(10) elements.
01179             If you are hashing n strings (ub1 **)k, do it like this:
01180 
01181                         for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
01182 
01183             By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use 
01184             this code any way you wish, private, educational, or commercial.  
01185             It's free.
01186             
01187             See http://burlteburtle.net/bob/hash/evahash.html
01188             Use for hash table lookup, or anything where one collision in 2^32 
01189             is acceptable. Do NOT use for cryptographic purposes.
01190 
01191         **********************************************************************/
01192 
01193         static final uint hash (void[] x, uint c = 0)
01194         {
01195             uint    a,
01196                     b;
01197 
01198             a = b = 0x9e3779b9; 
01199 
01200             uint len = x.length;
01201             ubyte* k = cast(ubyte *) x.ptr;
01202 
01203             // handle most of the key 
01204             while (len >= 12) 
01205                   {
01206                   a += *cast(uint *)(k+0);
01207                   b += *cast(uint *)(k+4);
01208                   c += *cast(uint *)(k+8);
01209 
01210                   a -= b; a -= c; a ^= (c>>13); 
01211                   b -= c; b -= a; b ^= (a<<8); 
01212                   c -= a; c -= b; c ^= (b>>13); 
01213                   a -= b; a -= c; a ^= (c>>12);  
01214                   b -= c; b -= a; b ^= (a<<16); 
01215                   c -= a; c -= b; c ^= (b>>5); 
01216                   a -= b; a -= c; a ^= (c>>3);  
01217                   b -= c; b -= a; b ^= (a<<10); 
01218                   c -= a; c -= b; c ^= (b>>15); 
01219                   k += 12; len -= 12;
01220                   }
01221 
01222             // handle the last 11 bytes 
01223             c += x.length;
01224             switch (len)
01225                    {
01226                    case 11: c+=(cast(uint)k[10]<<24);
01227                    case 10: c+=(cast(uint)k[9]<<16);
01228                    case 9 : c+=(cast(uint)k[8]<<8);
01229                    case 8 : b+=(cast(uint)k[7]<<24);
01230                    case 7 : b+=(cast(uint)k[6]<<16);
01231                    case 6 : b+=(cast(uint)k[5]<<8);
01232                    case 5 : b+=k[4];
01233                    case 4 : a+=(cast(uint)k[3]<<24);
01234                    case 3 : a+=(cast(uint)k[2]<<16);
01235                    case 2 : a+=(cast(uint)k[1]<<8);
01236                    case 1 : a+=k[0];
01237                    default:
01238                    }
01239 
01240             a -= b; a -= c; a ^= (c>>13); 
01241             b -= c; b -= a; b ^= (a<<8); 
01242             c -= a; c -= b; c ^= (b>>13); 
01243             a -= b; a -= c; a ^= (c>>12);  
01244             b -= c; b -= a; b ^= (a<<16); 
01245             c -= a; c -= b; c ^= (b>>5); 
01246             a -= b; a -= c; a ^= (c>>3);  
01247             b -= c; b -= a; b ^= (a<<10); 
01248             c -= a; c -= b; c ^= (b>>15); 
01249 
01250             return c;
01251         }
01252 
01253         /***********************************************************************
01254         
01255                 Throw an exception
01256 
01257         ***********************************************************************/
01258 
01259         protected final void error (char[] msg)
01260         {
01261                 static class TextException : Exception
01262                 {
01263                         this (char[] msg)
01264                         {
01265                                 super (msg);
01266                         }
01267                 }
01268 
01269                 throw new TextException (msg);
01270         }
01271 
01272         /***********************************************************************
01273         
01274                 Return the valid content from this String
01275 
01276         ***********************************************************************/
01277 
01278         package final T[] get ()
01279         {
01280                     return content [0 .. contentLength];
01281         }
01282 
01283         /***********************************************************************
01284         
01285                 Pin the given index to a valid position.
01286 
01287         ***********************************************************************/
01288 
01289         protected final void pinIndex (inout int x)
01290         {
01291                 if (x > contentLength)
01292                     x = contentLength;
01293         }
01294 
01295         /***********************************************************************
01296         
01297                 Pin the given index and length to a valid position.
01298 
01299         ***********************************************************************/
01300 
01301         protected final void pinIndices (inout int start, inout int length)
01302         {
01303                 if (start > contentLength) 
01304                     start = contentLength;
01305 
01306                 if (length > (contentLength - start))
01307                     length = contentLength - start;
01308         }
01309 
01310         /***********************************************************************
01311         
01312                 Simple comparator
01313 
01314                 Compare two arrays. Returns 0 if the content matches, less 
01315                 than zero if A is "less" than B, or greater than zero where 
01316                 A is "bigger". Where the substrings match, the shorter is 
01317                 considered "less".
01318 
01319         ***********************************************************************/
01320 
01321         protected final int simpleComparator (T[] a, T[] b)
01322         {
01323                 uint i = a.length;
01324                 if (b.length < i)
01325                     i = b.length;
01326 
01327                 for (int j, k; j < i; ++j)
01328                      if ((k = a[j] - b[j]) != 0)
01329                           return k;
01330                 
01331                 return a.length - b.length;
01332         }
01333 }       
01334 
01335 
01336 // convenience alias
01337 alias StringTemplate!(char) String;
01338 
01339 // convenience alias
01340 alias MutableStringTemplate!(char) MutableString;
01341 

Generated on Sat Dec 24 17:28:33 2005 for Mango by  doxygen 1.4.0