/// <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); } } }