/// <summary>
 ///     写文件错误
 /// </summary>
 /// <param name="error">错误异常</param>
 private void error(Exception error)
 {
     if (isLog) TmphLog.Default.Add(error, null, false);
     LastException = error;
     TmphInterlocked.NoCheckCompareSetSleep0(ref bufferLock);
     var isDisposed = this.isDisposed;
     currentIndex = startIndex;
     isWritting = 0;
     fileBufferLength = fileLength = 0;
     this.isDisposed = 1;
     bufferLock = 0;
     dispose();
     TmphPub.Dispose(ref fileStream);
     TmphList<TmphMemoryPool.TmphPushSubArray> buffers = null;
     Interlocked.Exchange(ref buffers, this.buffers);
     try
     {
         if (buffers != null && buffers.Count != 0)
         {
             var dataArray = buffers.array;
             for (var index = buffers.Count; index != 0; dataArray[--index].Push()) ;
         }
     }
     finally
     {
         currentBuffers = null;
         memoryPool.Push(ref TmphBuffer);
         if (isDisposed == 0)
         {
             flushWait.Set();
             flushWait.Close();
         }
     }
 }
 /// <summary>
 ///     清除表单数据
 /// </summary>
 /// <param name="values">表单数据集合</param>
 private static void clear(TmphList<TmphValue> values)
 {
     var count = values.Count;
     if (count != 0)
     {
         var formArray = values.array;
         for (var index = 0; index != count; ++index) formArray[index].Clear();
         values.Empty();
     }
 }
 /// <summary>
 ///     写入文件数据
 /// </summary>
 private void writeFile()
 {
     try
     {
         do
         {
             TmphInterlocked.NoCheckCompareSetSleep0(ref bufferLock);
             var bufferCount = buffers.Count;
             if (bufferCount == 0)
             {
                 if ((flushCount | isFlush) == 0)
                 {
                     checkFlushTime = TmphDate.NowSecond.AddTicks(checkFlushTicks);
                     isWritting = 0;
                     if (currentIndex == startIndex) bufferLock = 0;
                     else
                     {
                         bufferLock = 0;
                         setCheckFlush();
                     }
                     break;
                 }
                 isFlush = 0;
                 var writeSize = currentIndex - startIndex;
                 if (writeSize == 0)
                 {
                     bufferLock = 0;
                     if (buffers.Count == 0)
                     {
                         fileStream.Flush();
                         if (buffers.Count == 0) flushWait.Set();
                     }
                     continue;
                 }
                 bufferLock = 0;
                 fileStream.Write(TmphBuffer, startIndex, writeSize);
                 TmphInterlocked.NoCheckCompareSetSleep0(ref bufferLock);
                 fileLength += writeSize;
                 bufferLock = 0;
                 startIndex = currentIndex;
                 if (buffers.Count == 0)
                 {
                     fileStream.Flush();
                     if (buffers.Count == 0) flushWait.Set();
                 }
                 continue;
             }
             var datas = buffers;
             isCopyBuffer = 0;
             buffers = currentBuffers;
             bufferIndex = fileBufferLength;
             currentBuffers = datas;
             bufferLock = 0;
             foreach (var data in datas.array)
             {
                 int dataSize = data.Value.Count, writeSize = writeFile(data.Value);
                 TmphInterlocked.NoCheckCompareSetSleep0(ref bufferLock);
                 fileLength += writeSize;
                 bufferSize -= dataSize;
                 bufferLock = 0;
                 data.Push();
                 if (--bufferCount == 0) break;
             }
             Array.Clear(datas.array, 0, datas.Count);
             datas.Empty();
             if (isCopyBuffer != 0 && buffers.Count == 0) Thread.Sleep(0);
         } while (true);
     }
     catch (Exception error)
     {
         this.error(error);
     }
 }
 /// <summary>
 ///     合并同域cookie(用于处理跨域BUG)
 /// </summary>
 /// <param name="address">URI地址</param>
 /// <param name="responseHeaderCookie">HTTP头cookie信息</param>
 /// <param name="replaceCookie">需要替换的cookie</param>
 public void MergeDomainCookie(Uri address, string responseHeaderCookie, string replaceCookie)
 {
     if (address != null)
     {
         int index;
         string name;
         Cookie newCookie;
         var cookies = new CookieCollection();
         Dictionary<TmphHashString, Cookie> replaceCookies = null;
         if (responseHeaderCookie != null && responseHeaderCookie.Length != 0)
         {
             replaceCookies = TmphDictionary.CreateHashString<Cookie>();
             DateTime expires;
             string value, domain, path, expiresString;
             string lastCookie = null;
             TmphList<string> newCookies = new TmphList<string>();
             foreach (var cookie in responseHeaderCookie.Split(','))
             {
                 if (lastCookie == null)
                 {
                     var lowerCookie = cookie.ToLower();
                     index = lowerCookie.IndexOf("; expires=", StringComparison.Ordinal);
                     if (index == -1) index = lowerCookie.IndexOf(";expires=", StringComparison.Ordinal);
                     if (index == -1 || cookie.IndexOf(';', index + 10) != -1) newCookies.Add(cookie);
                     else lastCookie = cookie;
                 }
                 else
                 {
                     newCookies.Add(lastCookie + "," + cookie);
                     lastCookie = null;
                 }
             }
             Dictionary<TmphHashString, string> cookieInfo = TmphDictionary.CreateHashString<string>();
             foreach (string cookie in newCookies)
             {
                 newCookie = null;
                 foreach (TmphSubString values in cookie.Split(';'))
                 {
                     if ((index = values.IndexOf('=')) != 0)
                     {
                         if ((index = values.IndexOf('=')) == -1)
                         {
                             name = values.Trim();
                             value = string.Empty;
                         }
                         else
                         {
                             name = values.Substring(0, index).Trim();
                             value = values.Substring(index + 1);
                         }
                         if (newCookie == null)
                             newCookie = new Cookie(Web.TmphCookie.FormatCookieName(name),
                                 Web.TmphCookie.FormatCookieValue(value));
                         else cookieInfo[name.ToLower()] = value;
                     }
                 }
                 if (cookieInfo.TryGetValue(expiresHash, out expiresString)
                     && DateTime.TryParse(expiresString, out expires))
                 {
                     newCookie.Expires = expires;
                 }
                 if (cookieInfo.TryGetValue(pathHash, out path)) newCookie.Path = path;
                 replaceCookies[newCookie.Name] = newCookie;
                 newCookie = new Cookie(newCookie.Name, newCookie.Value, newCookie.Path);
                 if (cookieInfo.TryGetValue(domainHash, out domain)) newCookie.Domain = domain;
                 Cookies.Add(address, newCookie);
                 cookieInfo.Clear();
             }
         }
         if (replaceCookie != null && replaceCookie.Length != 0)
         {
             if (replaceCookies == null) replaceCookies = TmphDictionary.CreateHashString<Cookie>();
             foreach (TmphSubString cookie in replaceCookie.Split(';'))
             {
                 if ((index = cookie.IndexOf('=')) != 0)
                 {
                     if (index == -1)
                     {
                         name = Web.TmphCookie.FormatCookieName(cookie.Trim());
                         newCookie = new Cookie(name, string.Empty);
                     }
                     else
                     {
                         name = Web.TmphCookie.FormatCookieName(cookie.Substring(0, index).Trim());
                         newCookie = new Cookie(name, Web.TmphCookie.FormatCookieValue(cookie.Substring(index + 1)));
                     }
                     TmphHashString nameKey = name;
                     if (replaceCookies.ContainsKey(nameKey)) replaceCookies[nameKey].Value = newCookie.Value;
                     else replaceCookies.Add(nameKey, newCookie);
                 }
             }
         }
         bool isCookie;
         foreach (Cookie cookie in Cookies.GetCookies(address))
         {
             if (isCookie = replaceCookies != null && replaceCookies.ContainsKey(cookie.Name))
             {
                 newCookie = replaceCookies[cookie.Name];
             }
             else newCookie = new Cookie(cookie.Name, cookie.Value, HttpUtility.UrlDecode((cookie.Path)));
             cookies.Add(newCookie);
             if (isCookie) replaceCookies.Remove(cookie.Name);
             newCookie.Expires = cookie.Expires;
             cookie.Expired = true;
         }
         if (replaceCookies != null)
         {
             foreach (var cookie in replaceCookies.Values) cookies.Add(cookie);
         }
         if (cookies.Count != 0)
         {
             try
             {
                 Cookies.Add(address, cookies);
             }
             catch (Exception error)
             {
                 TmphLog.Default.Add(error, "合并同域cookie失败", true);
             }
         }
     }
 }
 /// <summary>
 ///     合并同域cookie(用于处理跨域BUG)
 /// </summary>
 /// <param name="address">URI地址</param>
 /// <param name="cookies">默认cookie集合信息</param>
 /// <param name="documentCookie">登录后的cookie信息</param>
 /// <param name="httpOnlyCookie">登录后的httpOnly相关cookie信息</param>
 public void MergeDomainCookie(Uri address, TmphList<Cookie> cookies, string documentCookie, string httpOnlyCookie)
 {
     if (cookies != null)
     {
         foreach (Cookie cookie in cookies) Cookies.Add(address, cookie);
     }
     if (address != null)
     {
         TmphList<Cookie> newCookies = new TmphList<Cookie>();
         Dictionary<TmphHashString, int> nameCounts = null;
         TmphList<string> documentCookies = new TmphList<string>(2);
         if (documentCookie.Length != 0) documentCookies.Unsafer.Add(documentCookie);
         if (httpOnlyCookie.Length != 0) documentCookies.Unsafer.Add(httpOnlyCookie);
         if (documentCookies.Count != 0)
         {
             int index, nextCount, count;
             string name;
             Cookie newCookie;
             Dictionary<TmphHashString, int> nextNameCounts = TmphDictionary.CreateHashString<int>();
             nameCounts = TmphDictionary.CreateHashString<int>();
             foreach (string nextCookie in documentCookies)
             {
                 nextNameCounts.Clear();
                 foreach (TmphSubString cookie in nextCookie.Split(';'))
                 {
                     if (cookie.Length != 0 && (index = cookie.IndexOf('=')) != 0)
                     {
                         if (index == -1)
                         {
                             name = Web.TmphCookie.FormatCookieName(cookie.Trim());
                         }
                         else name = Web.TmphCookie.FormatCookieName(cookie.Substring(0, index).Trim());
                         TmphHashString nameKey = name;
                         if (nextNameCounts.TryGetValue(nameKey, out nextCount))
                             nextNameCounts[nameKey] = ++nextCount;
                         else nextNameCounts.Add(nameKey, nextCount = 1);
                         if (!nameCounts.TryGetValue(nameKey, out count)) count = 0;
                         if (nextCount > count)
                         {
                             if (index == -1) newCookie = new Cookie(name, string.Empty);
                             else
                                 newCookie = new Cookie(name,
                                     Web.TmphCookie.FormatCookieValue(cookie.Substring(index + 1)));
                             newCookies.Add(newCookie);
                             if (count != 0) newCookie.HttpOnly = true;
                             if (count == 0) nameCounts.Add(nameKey, nextCount);
                             else nameCounts[nameKey] = nextCount;
                         }
                     }
                 }
             }
         }
         foreach (Cookie cookie in Cookies.GetCookies(address))
         {
             if (nameCounts != null && nameCounts.ContainsKey(cookie.Name)) cookie.Expired = true;
         }
         if (newCookies.Count != 0)
         {
             try
             {
                 foreach (Cookie cookie in newCookies) Cookies.Add(address, cookie);
             }
             catch (Exception error)
             {
                 TmphLog.Default.Add(error, "合并同域cookie失败", true);
             }
         }
     }
 }
 /// <summary>
 /// 数据文本分词
 /// </summary>
 /// <param name="text">文本</param>
 /// <returns>分词结果</returns>
 protected unsafe Dictionary<TmphHashString, TmphList<int>> getAllWords(string text)
 {
     if (text != null)
     {
         int length = text.Length;
         if (length != 0)
         {
             TmphList<TmphSubString> words = getWords(text + " ", length);
             if (words != null)
             {
                 Dictionary<TmphHashString, TmphList<int>> dictionary = TmphTypePool<Dictionary<TmphHashString, TmphList<int>>>.Pop();
                 if (dictionary == null) dictionary = Laurent.Lee.CLB.TmphDictionary.CreateHashString<TmphList<int>>();
                 else if (dictionary.Count != 0) dictionary.Clear();
                 TmphList<int> indexs;
                 int count = words.Count;
                 foreach (TmphSubString word in words.Unsafer.Array)
                 {
                     TmphHashString wordKey = word;
                     if (!dictionary.TryGetValue(wordKey, out indexs))
                     {
                         indexs = TmphTypePool<TmphList<int>>.Pop();
                         if (indexs == null) indexs = new TmphList<int>();
                         else indexs.Empty();
                         dictionary.Add(wordKey, indexs);
                     }
                     indexs.Add(word.StartIndex);
                     if (--count == 0) break;
                 }
                 words.Clear();
                 TmphTypePool<TmphList<TmphSubString>>.Push(ref words);
                 return dictionary;
             }
         }
     }
     return null;
 }
 /// <summary>
 /// 文本分词
 /// </summary>
 /// <param name="text">文本</param>
 /// <param name="length">文本长度</param>
 /// <returns>分词结果</returns>
 private unsafe TmphList<TmphSubString> getWords(string text, int length)
 {
     fixed (char* textFixed = text)
     {
         TmphSimplified.Format(textFixed, length);
         int count = (length + 7) >> 3;
         byte* match = stackalloc byte[count];
         TmphFixedMap matchMap = new TmphFixedMap(match, count, 0);
         TmphList<TmphSubString> words = TmphTypePool<TmphList<TmphSubString>>.Pop();
         if (words == null) words = new TmphList<TmphSubString>();
         else if (words.Count != 0) words.Clear();
         TmphList<TmphKeyValue<int, int>> matchs = TmphTypePool<TmphList<TmphKeyValue<int, int>>>.Pop() ?? new TmphList<TmphKeyValue<int, int>>();
         byte* charTypes = charTypePointer.Byte;
         for (char* start = textFixed, end = textFixed + length; start != end;)
         {
             if (*start == ' ')
             {
                 *end = '?';
                 while (*++start == ' ') ;
             }
             else
             {
                 *end = ' ';
                 char* segment = start;
                 if ((uint)(*start - 0x4E00) <= 0X9FA5 - 0x4E00)
                 {
                     while ((uint)(*++start - 0x4E00) <= 0X9FA5 - 0x4E00) ;
                     if ((length = (int)(start - segment)) == 1)
                     {
                         words.Add(TmphSubString.Unsafe(text, (int)(segment - textFixed), 1));
                     }
                     else
                     {
                         int startIndex = (int)(segment - textFixed);
                         matchs.Empty();
                         wordTrieGraph.LeftRightMatchs(TmphSubString.Unsafe(text, startIndex, length), matchs);
                         if ((count = matchs.Count) != 0)
                         {
                             foreach (TmphKeyValue<int, int> value in matchs.Unsafer.Array)
                             {
                                 words.Add(TmphSubString.Unsafe(text, value.Key, value.Value));
                                 matchMap.Set(value.Key, value.Value);
                                 if (--count == 0) break;
                             }
                         }
                         int index = startIndex;
                         for (int endIndex = startIndex + length; index != endIndex; ++index)
                         {
                             if (matchMap.Get(index))
                             {
                                 if ((count = index - startIndex) != 1)
                                 {
                                     words.Add(TmphSubString.Unsafe(text, startIndex, count));
                                 }
                                 startIndex = index;
                             }
                             else words.Add(TmphSubString.Unsafe(text, index, 1));
                         }
                         if ((index -= startIndex) > 1) words.Add(TmphSubString.Unsafe(text, startIndex, index));
                     }
                 }
                 else
                 {
                     byte type = charTypes[*start];
                     if (type == (byte)TmphCharType.OtherLetter)
                     {
                         while (charTypes[*++start] == (byte)TmphCharType.OtherLetter) ;
                     }
                     else
                     {
                         char* word = start;
                         for (byte newType = charTypes[*++start]; newType >= (byte)TmphCharType.Letter; newType = charTypes[*++start])
                         {
                             if (type != newType)
                             {
                                 if (type != (byte)TmphCharType.Keep)
                                 {
                                     words.Add(TmphSubString.Unsafe(text, (int)(word - textFixed), (int)(start - word)));
                                 }
                                 type = newType;
                                 word = start;
                             }
                         }
                     }
                     words.Add(TmphSubString.Unsafe(text, (int)(segment - textFixed), (int)(start - segment)));
                 }
             }
         }
         TmphTypePool<TmphList<TmphKeyValue<int, int>>>.Push(ref matchs);
         if ((count = words.Count) == 0)
         {
             TmphTypePool<TmphList<TmphSubString>>.Push(ref words);
             return null;
         }
         return words;
     }
 }
 /// <summary>
 ///     状态数据创建器
 /// </summary>
 /// <param name="names">名称集合</param>
 public TmphBuilder(TmphKeyValue<string, int>[] names)
 {
     this.names = names;
     prefixSize = tableCount = stateCount = tableType = 0;
     state = charsAscii = charStart = charEnd = prefix = table = null;
     if (names.Length > 1)
     {
         chars = new TmphList<char>();
         Data = new TmphPointer();
         count(0, names.Length, 0);
         var charArray = chars.array;
         int charCount, asciiCount;
         Array.Sort(charArray, 0, chars.Count);
         fixed (char* charFixed = charArray)
         {
             char* start = charFixed + 1, end = charFixed + chars.Count, write = start;
             var value = *charFixed;
             if (*(end - 1) < 128)
             {
                 while (start != end)
                 {
                     if (*start != value) *write++ = value = *start;
                     ++start;
                 }
                 asciiCount = (int)(write - charFixed);
                 charCount = 0;
             }
             else
             {
                 while (value < 128)
                 {
                     while (*start == value) ++start;
                     *write++ = value = *start++;
                 }
                 asciiCount = (int)(write - charFixed) - 1;
                 while (start != end)
                 {
                     if (*start != value) *write++ = value = *start;
                     ++start;
                 }
                 charCount = (int)(write - charFixed) - asciiCount;
             }
             chars.Unsafer.AddLength(asciiCount + charCount - chars.Count);
             var size = (1 + (stateCount += tableCount) * 3) * sizeof(int) +
                        (128 + 2 + charCount + prefixSize) * sizeof(ushort);
             if (stateCount < 256) size += tableCount * (chars.Count + 1);
             else if (stateCount < 65536)
             {
                 size += tableCount * (chars.Count + 1) * sizeof(ushort);
                 tableType = 1;
             }
             else
             {
                 size += tableCount * (chars.Count + 1) * sizeof(int);
                 tableType = 2;
             }
             Data = TmphUnmanaged.Get(size, true);
             *Data.Int = stateCount; //状态数量[int]
             state = Data.Byte + sizeof(int); //状态集合[stateCount*(前缀位置[int]+状态位置[int]+名称索引[int])]
             charsAscii = state + (stateCount * 3) * sizeof(int); //ascii字符查找表[128*ushort]
             charStart = charsAscii + 128 * sizeof(ushort);
             *(ushort*)charStart = (ushort)(asciiCount + 1); //特殊字符起始值[ushort]
             *(ushort*)(charStart + sizeof(ushort)) = (ushort)charCount; //特殊字符数量[ushort]
             charStart += sizeof(ushort) * 2;
             ushort charIndex = 0;
             for (start = charFixed, end = charFixed + asciiCount; start != end; ++start)
             {
                 *(ushort*)(charsAscii + (*start << 1)) = ++charIndex;
             }
             charEnd = charStart;
             if (charCount != 0)
             {
                 //特殊字符二分查找表[charCount*char]
                 Unsafe.TmphMemory.Copy((byte*)start, charStart, charCount << 1);
                 charEnd += charCount << 1;
             }
             prefix = charStart + charCount * sizeof(ushort); //前缀集合
             table = prefix + prefixSize * sizeof(ushort);
             //状态矩阵[tableCount*(chars.Count+1)*[byte/ushort/int]]
         }
         stateCount = 0;
         create(0, names.Length, 0);
     }
     else
     {
         chars = null;
         if (names.Length == 0) Data = new TmphPointer();
         else if (names[0].Key.Length <= 128)
         {
             Data =
                 TmphUnmanaged.Get(
                     sizeof(int) + sizeof(int) * 3 + 128 * sizeof(ushort) + 2 * sizeof(ushort), false);
             *Data.Int = 1; //状态数量
             state = Data.Byte + sizeof(int);
             *(int*)state = sizeof(int) * 3; //前缀位置
             *(int*)(state + sizeof(int)) = 0; //状态位置
             *(int*)(state + sizeof(int) * 2) = names[0].Value; //名称索引
             prefix = Data.Byte + sizeof(int) * 4;
             Unsafe.TmphString.Copy(names[0].Key, prefix);
             *(char*)(prefix + (names[0].Key.Length << 1)) = (char)0;
             *(int*)(Data.Byte + sizeof(int) * 4 + 128 * sizeof(ushort)) = 0;
         }
         else
         {
             Data =
                 TmphUnmanaged.Get(
                     sizeof(int) + sizeof(int) * 3 + 128 * sizeof(ushort) + 2 * sizeof(ushort) +
                     names[0].Key.Length * sizeof(char) + sizeof(char), true);
             *Data.Int = 1; //状态数量
             state = Data.Byte + sizeof(int);
             *(int*)state = sizeof(int) * 3 + 128 * sizeof(ushort) + 2 * sizeof(ushort); //前缀位置
             *(int*)(state + sizeof(int)) = 0; //状态位置
             *(int*)(state + sizeof(int) * 2) = names[0].Value; //名称索引
             Unsafe.TmphString.Copy(names[0].Key, state + *(int*)state);
         }
     }
 }