EAString.html 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
  2. <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  3. <Title>EAString</title>
  4. <link type="text/css" rel="stylesheet" href="UTFDoc.css">
  5. <meta name="author" content="Paul Pedriana">
  6. </head>
  7. <body bgcolor="#FFFFFF">
  8. <h1>EAString</h1>
  9. <h2>Introduction</h2>
  10. <p>EAString implements an extensive suite of C string functionality from &lt;string.h&gt; in a portable way. Much of this functionality is the same as what
  11. is present in the C standard and in common (but non-portable) extensions to the C standard. EAString presents a consistent portable interface to its functionality
  12. in both 8 bit and 16 bit string form.</p>
  13. <p>The C language provides various functions which work with non-portable data types, such as long. EAString defines all significant data types in terms of portable
  14. types such as int32_t and int64_t. Additionally, the EAString versions of functions are usually faster than the C runtime library versions, usually because the EAString versions minimize cache misses
  15. and branching, whereas typical C runtime libraries optimize for the smallest memory footprint with little or no regard to other performance characteristics. Also, the EAString functions do not implement locale-specific functionality and thus save time and space as a result. Other packages within EA implement localization functionality in a way that is better suited to high performance game development.</p>
  16. <p>C-style printf functionality is separate from EAString and is found in <a href="EASprintf.html">EASprintf</a>. Memcpy functionality (which comes from the &lt;string.h&gt;
  17. header file) is present in <a href="EAMemory.html">EAMemory</a>. </p>
  18. <h2>Extension functions</h2>
  19. <p> EAString provides extended functionality that isn't found in conventional C libraries, but it useful nevertheless.</p>
  20. <table width="100%" border="1" cellpadding="3">
  21. <tr>
  22. <td><b>Function</b></td>
  23. <td><b>Description</b></td>
  24. <td><b>Signature</b></td>
  25. </tr>
  26. <tr>
  27. <td>Strlcat</td>
  28. <td>Safe variation of strncat</td>
  29. <td><font size="-1">char_t* Strlcat(char_t* pDestination, const char_t* pSource, size_t n); </font></td>
  30. </tr>
  31. <tr>
  32. <td>Strlcpy</td>
  33. <td>Safe variation of strcpy</td>
  34. <td><p><font size="-1">char_t* Strlcpy(char_t* pDestination, const char_t* pSource, size_t n); <br>
  35. int Strlcpy(char16_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  36. int Strlcpy(char32_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  37. int Strlcpy(char8_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  38. int Strlcpy(char32_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  39. int Strlcpy(char8_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  40. int Strlcpy(char16_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0); <br>
  41. int Strlcpy(char8_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  42. int Strlcpy(char16_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0); <br>
  43. int Strlcpy(char32_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  44. int Strlcpy(wchar_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  45. int Strlcpy(wchar_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0); <br>
  46. int Strlcpy(wchar_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);<br>
  47. bool Strlcpy(char16_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  48. bool Strlcpy(char32_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  49. bool Strlcpy(char8_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  50. bool Strlcpy(char32_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  51. bool Strlcpy(char8_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  52. bool Strlcpy(char16_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  53. bool Strlcpy(char8_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  54. bool Strlcpy(char16_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  55. bool Strlcpy(char32_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  56. bool Strlcpy(wchar_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  57. bool Strlcpy(wchar_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);<br>
  58. bool Strlcpy(wchar_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  59. </font></p>
  60. </td>
  61. </tr>
  62. <tr>
  63. <td>Stristr</td>
  64. <td>Case insensitive version of strstr (find string within string)</td>
  65. <td><font size="-1">char_t* Stristr(const char_t* pString, const char_t* pSubString);</font></td>
  66. </tr>
  67. <tr>
  68. <td>FtoaEnglish</td>
  69. <td>
  70. <p>Float to ascii; always use English numeric format, regardless of the current locale.</p>
  71. </td>
  72. <td><font size="-1">char_t* FtoaEnglish(double dValue, char_t* pResult, int nInputLength, int nPrecision, bool bExponentEnabled); </font></td>
  73. </tr>
  74. <tr>
  75. <td>AtofEnglish</td>
  76. <td>Ascii to float; always use English numeric format, regardless of the current locale.</td>
  77. <td><font size="-1">double AtofEnglish(const char_t* pString); </font></td>
  78. </tr>
  79. <tr>
  80. <td> StrtodEnglish</td>
  81. <td>Same as strtod, but always use English numeric format, regardless of the current locale.</td>
  82. <td><font size="-1">double StrtodEnglish(const char_t* pString, char_t** ppStringEnd);</font></td>
  83. </tr>
  84. <tr>
  85. <td>Memset16</td>
  86. <td>Sets 16 bit values in memory (as opposed to memset's 8 bit values)</td>
  87. <td><font size="-1">uint16_t* Memset16(void* pDestination, uint16_t c, size_t count); </font></td>
  88. </tr>
  89. <tr>
  90. <td>Memset32</td>
  91. <td>Sets 32 bit values in memory (as opposed to memset's 8 bit values)</td>
  92. <td><font size="-1"> uint32_t* Memset32(void* pDestination, uint32_t c, size_t count);</font></td>
  93. </tr>
  94. <tr>
  95. <td>Memset64</td>
  96. <td>Sets 64 bit values in memory (as opposed to memset's 8 bit values)</td>
  97. <td><font size="-1">uint64_t* Memset64(void* pDestination, uint64_t c, size_t count);</font></td>
  98. </tr>
  99. <tr>
  100. <td>MemsetN</td>
  101. <td>Sets arbitrarily sized values in memory.</td>
  102. <td><font size="-1">void* MemsetN (void* pDestination, const void* pSource, size_t sourceBytes, size_t count); </font></td>
  103. </tr>
  104. <tr>
  105. <td>EcvtBuf</td>
  106. <td>Base function for converting a float to a %e string.</td>
  107. <td>
  108. <p><font size="-1">char_t* EcvtBuf(double dValue, int nDigitCount, int* decimalPos, int* sign, char_t* buffer); </font></p>
  109. </td>
  110. </tr>
  111. <tr>
  112. <td>FcvtBuf</td>
  113. <td>Base function for converting a float to a %f string.</td>
  114. <td><font size="-1">char_t* FcvtBuf(double dValue, int nDigitCountAfterDecimal, int* decimalPos, int* sign, char_t* buffer); </font></td>
  115. </tr>
  116. </table>
  117. <h2>Example usage </h2>
  118. <p>We provide a random smattering of example code here.</p>
  119. <pre class="code-example">char16_t buffer[32] = L"hello ";
  120. Strcat(buffer, L"world");
  121. </pre>
  122. <p>Strlcpy, Strlcat:</p>
  123. <pre class="code-example">char8_t buffer[32];
  124. Strlcpy(buffer, "Hello ", sizeof(buffer));<br>Strlcat(buffer, "world", sizeof(buffer));
  125. </pre>
  126. <p>Strlcpy, used to translate UTF8 to UTF16: </p>
  127. <pre class="code-example">char8_t buffer8[64];
  128. char16_t buffer16[64];
  129. int length16 = Strlcpy(buffer16, buffer8, 64);</pre>
  130. <p>U64toa:</p>
  131. <pre class="code-example">char buffer[32];
  132. U64toa(UINT64_C(12345678901234567890), buffer, 16);
  133. </pre>
  134. <p>AtoI32:</p>
  135. <pre class="code-example">int32_t x = AtoI32(&quot;1234567890&quot;);
  136. </pre>
  137. <p>Strtod:</p>
  138. <pre class="code-example">const char16_t* pString = L"12345.678 123.456 1.23456";
  139. while(*pString)
  140. {
  141. double value = Strtod(pString, &pString);
  142. printf("Field = %f\n, value);
  143. }
  144. </pre>
  145. <h2>Interface</h2>
  146. <p>In each of the functions below, there is an char8_t and char16_t version. So for Strcat there are the following:</p>
  147. <blockquote>
  148. <p><span class="code-example-span">char8_t* &nbsp;Strcat(char8_t* &nbsp;pDestination, const char8_t* &nbsp;pSource)<br>
  149. </span><span class="code-example-span">char16_t* Strcat(char16_t* pDestination, const char16_t* pSource)</span></p>
  150. </blockquote>
  151. <p>The list below may be out of date as you read this, so see EAString.h for a definitive list of supported functionality.</p>
  152. <pre class="code-example">char_t* Strcat(char_t* pDestination, const char_t* pSource);
  153. char_t* Strncat(char_t* pDestination, const char_t* pSource, size_t n);
  154. char_t* Strlcat(char_t* pDestination, const char_t* pSource, size_t n);
  155. char_t* Strcpy(char_t* pDestination, const char_t* pSource);
  156. char_t* Strncpy(char_t* pDestination, const char_t* pSource, size_t n);
  157. char_t* Strlcpy(char_t* pDestination, const char_t* pSource, size_t n);
  158. int Strlcpy(char16_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  159. int Strlcpy(char32_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  160. int Strlcpy(char8_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  161. int Strlcpy(char32_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  162. int Strlcpy(char8_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  163. int Strlcpy(char16_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  164. int Strlcpy(char8_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  165. int Strlcpy(char16_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  166. int Strlcpy(char32_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  167. int Strlcpy(wchar_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  168. int Strlcpy(wchar_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  169. int Strlcpy(wchar_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength = (size_t)~0);
  170. bool Strlcpy(char16_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  171. bool Strlcpy(char32_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  172. bool Strlcpy(char8_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  173. bool Strlcpy(char32_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  174. bool Strlcpy(char8_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  175. bool Strlcpy(char16_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  176. bool Strlcpy(char8_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  177. bool Strlcpy(char16_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  178. bool Strlcpy(char32_t* pDestination, const wchar_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  179. bool Strlcpy(wchar_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  180. bool Strlcpy(wchar_t* pDestination, const char16_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  181. bool Strlcpy(wchar_t* pDestination, const char32_t* pSource, size_t nDestCapacity, size_t nSourceLength, size_t&amp; nDestUsed, size_t&amp; nSourceUsed);
  182. size_t Strlen(const char_t* pString);
  183. size_t Strxfrm(char_t* pDest, const char_t* pSource, size_t n);
  184. char_t* Strdup(const char_t* pString);
  185. char_t* Strlwr(char_t* pString);
  186. char_t* Strupr(char_t* pString);
  187. char_t* Strchr(const char_t* pString, char_t c);
  188. size_t Strcspn(const char_t* pString1, const char_t* pString2);
  189. char_t* Strpbrk(const char_t* pString1, const char_t* pString2);
  190. char_t* Strrchr(const char_t* pString, char_t c);
  191. size_t Strspn(const char_t* pString, const char_t* pSubString);
  192. char_t* Strstr(const char_t* pString, const char_t* pSubString);
  193. char_t* Stristr(const char_t* pString, const char_t* pSubString);
  194. char_t* Strtok(char_t* pString, const char_t* pTokens, char_t** pContext);
  195. char_t* Strset(char_t* pString, char_t c);
  196. char_t* Strnset(char_t* pString, char_t c, size_t n);
  197. char_t* Strrev(char_t* pString);
  198. int Strcmp(const char_t* pString1, const char_t* pString2);
  199. int Strncmp(const char_t* pString1, const char_t* pString2, size_t n);
  200. int Stricmp(const char_t* pString1, const char_t* pString2);
  201. int Strnicmp(const char_t* pString1, const char_t* pString2, size_t n);
  202. int Strcoll(const char_t* pString1, const char_t* pString2);
  203. int Strncoll(const char_t* pString1, const char_t* pString2, size_t n);
  204. int Stricoll(const char_t* pString1, const char_t* pString2);
  205. int Strnicoll(const char_t* pString1, const char_t* pString1, size_t n);
  206. char_t* EcvtBuf(double dValue, int nDigitCount, int* decimalPos, int* sign, char_t* buffer);
  207. char_t* FcvtBuf(double dValue, int nDigitCountAfterDecimal, int* decimalPos, int* sign, char_t* buffer);
  208. char_t* I32toa(int32_t nValue, char_t* pResult, int nBase);
  209. char_t* U32toa(uint32_t nValue, char_t* pResult, int nBase);
  210. char_t* I64toa(int64_t nValue, char_t* pBuffer, int nBase);
  211. char_t* U64toa(uint64_t nValue, char_t* pBuffer, int nBase);
  212. double Strtod(const char_t* pString, char_t** ppStringEnd);
  213. double StrtodEnglish(const char_t* pString, char_t** ppStringEnd);
  214. int64_t StrtoI64(const char_t* pString, char_t** ppStringEnd, int nBase);
  215. uint64_t StrtoU64(const char_t* pString, char_t** ppStringEnd, int nBase);
  216. int32_t StrtoI32(const char_t* pString, char_t** ppStringEnd, int nBase);
  217. uint32_t StrtoU32(const char_t* pString, char_t** ppStringEnd, int nBase);
  218. int32_t AtoI32(const char_t* pString);
  219. uint32_t AtoU32(const char_t* pString);
  220. int64_t AtoI64(const char_t* pString);
  221. uint64_t AtoU64(const char_t* pString);
  222. double Atof(const char_t* pString);
  223. double AtofEnglish(const char_t* pString);
  224. char_t* Ftoa(double dValue, char_t* pResult, int nInputLength, int nPrecision, bool bExponentEnabled);
  225. char_t* FtoaEnglish(double dValue, char_t* pResult, int nInputLength, int nPrecision, bool bExponentEnabled);
  226. </pre>
  227. <h2>Encoded Strlcpy Issue </h2>
  228. <p>The Strlcpy function <span class="code-example-comment"> size_t Strlcpy(char16_t* pDestination, const char8_t* pSource, size_t nDestCapacity, size_t nSourceLength)</span> converts UTF8 text (char8_t) to UCS2 (char16_t). It doesn't work if your pSource string isn't truly UTF8-encoded. Typically this would happen because the source string is using Windows code page 1252 or HTML's ISO 8859-1. All 8 bit strings in EAStdC are assumed to be UTF8 unless specifically documented otherwise. </p>
  229. <p>Any 8 bit text that's not UTF8 has to be defined within the context of a code page; otherwise any chars above 127 have an arbitrary meaning, and may include multi-byte characters for some code pages. If you need to convert code page 1252 to UCS2, you need to implement a function which uses a table that maps the high byte values into their proper Unicode values. It's not so simple to just cast the byte value to char16_t, as some of the code page 1252 characters don't map directly to their numerical values in Unicode, though ISO 8859-1 characters to completely map to their equivalent Unicode values. </p>
  230. <p>The following is an implementation of Strcpy and Strlcpy for ISO 8859-1 char8_t text which isn't currently part of EAStdC: </p>
  231. <p class="code-example">char16_t* StrcpyISO8859_1(char16_t* pDestination, const char8_t* pSource)<br>
  232. {<br>
  233. &nbsp;&nbsp;&nbsp;&nbsp;char16_t* pDestSaved = pDestination;<br>
  234. <br>
  235. &nbsp;&nbsp;&nbsp;&nbsp;while(*pSource)<br>
  236. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(pDestination++) = (uint8_t)*pSource++;<br>
  237. <br>
  238. &nbsp;&nbsp;&nbsp;&nbsp;*pDestination = 0;<br>
  239. <br>
  240. &nbsp;&nbsp;&nbsp;&nbsp;return pDestSaved;<br>
  241. }</p>
  242. <p> </p>
  243. <p class="code-example">size_t StrlcpyISO8859_1(char16_t* pDestination, const char8_t* pSource, size_t nDestCapacity)<br>
  244. {<br>
  245. &nbsp;&nbsp;&nbsp;&nbsp;const char8_t* s = pSource;<br>
  246. &nbsp;&nbsp;&nbsp;&nbsp;size_t n = nDestCapacity;<br>
  247. <br>
  248. &nbsp;&nbsp;&nbsp;&nbsp;if(n &amp;&amp; --n)<br>
  249. &nbsp;&nbsp;&nbsp;&nbsp;{<br>
  250. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do{<br>
  251. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((*pDestination++ = (uint8_t)*s++) == 0)<br>
  252. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>
  253. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} while(--n);<br>
  254. &nbsp;&nbsp;&nbsp;&nbsp;}<br>
  255. <br>
  256. &nbsp;&nbsp;&nbsp;&nbsp;if(!n)<br>
  257. &nbsp;&nbsp;&nbsp;&nbsp;{<br>
  258. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(nDestCapacity)<br>
  259. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*pDestination = 0;<br>
  260. <br>
  261. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(*s)<br>
  262. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++s;<br>
  263. &nbsp;&nbsp;&nbsp;&nbsp;}<br>
  264. <br>
  265. &nbsp;&nbsp;&nbsp;&nbsp;return (s - pSource - 1);<br>
  266. }</p>
  267. <hr>
  268. <p>&nbsp;</p>
  269. <p>&nbsp;</p>
  270. <p>&nbsp;</p>
  271. <p>&nbsp;</p>
  272. <p>&nbsp;</p>
  273. <p>&nbsp;</p>
  274. <p>&nbsp;</p>
  275. <p>&nbsp;</p>
  276. <p>&nbsp;</p>
  277. <p>&nbsp;</p>
  278. <p>&nbsp;</p>
  279. <p>&nbsp;</p>
  280. <p>&nbsp;</p>
  281. <p> </p>
  282. </body>
  283. </html>