public bool Read(char[] cache, bool toBeContinued) { SegmentMode prevMode = SegmentType; if (cache == null || cache.Length < 1) { SegmentType = SegmentMode.NotSpecified; return true; } else if (cache.Length < 2 || (cache[1] == 0 && !toBeContinued)) { builder.Append(cache[0]); SegmentType = JudgeMode(cache[0]); return true; } else if (cache[1] == 0 && toBeContinued) { builder.Append(cache[0]); SegmentType = JudgeMode(cache[0]); return false; } if (!JudgeCurrentMode(prevMode, cache)) { AppendBuilder(cache, false); return true; } if (SegmentType != SegmentMode.NotSpecified) { AppendBuilder(cache, true); } return false; }
public bool Read(char[] cache, bool toBeContinued) { SegmentMode prevMode = SegmentType; if (cache == null || cache.Length < 1) { SegmentType = SegmentMode.NotSpecified; return(true); } else if (cache.Length < 2 || (cache[1] == 0 && !toBeContinued)) { builder.Append(cache[0]); SegmentType = JudgeMode(cache[0]); return(true); } else if (cache[1] == 0 && toBeContinued) { builder.Append(cache[0]); SegmentType = JudgeMode(cache[0]); return(false); } if (!JudgeCurrentMode(prevMode, cache)) { AppendBuilder(cache, false); return(true); } if (SegmentType != SegmentMode.NotSpecified) { AppendBuilder(cache, true); } return(false); }
/// <summary> /// Calculates the amount of bits needed to encode <paramref name="count"/> characters /// in the specified segment mode /// </summary> /// <param name="mode">Segment mode</param> /// <param name="count">Amount of characters to encode</param> /// <returns></returns> private static int GetBitCount(SegmentMode mode, int count) { return(mode switch { SegmentMode.Numeric => (count / 3) * 10 + (count % 3) switch { 0 => 0, 1 => 4, 2 => 7, _ => throw new Exception("wtf") },
/// <summary> /// Log 到 txt 文件中 /// </summary> /// <param name="path">路径 默认为程序运行路径下的 Log 文件夹</param> /// <param name="logMode">选择 LogMode,默认为 Trace 模式</param> /// <param name="segmentMode">选择 Log 的记录分割模式。默认为按天分割</param> /// <param name="flushInterval">将缓存写入文件的周期,单位为毫秒。默认 10000ms</param> public Logger_ForFile(string path = "Log\\", LogMode logMode = LogMode.Trace, SegmentMode segmentMode = SegmentMode.Day, int flushInterval = 10000) { _TimeStampStart = DateTime.Now; loggerBase = Logger_Base.Create(logMode); newLine = _newLine; newSection = _newSection; // 校验 flushInterval 取值范围 // 不能为 0 以避免自旋消耗 CPU 性能 flushInterval = flushInterval > 0 ? flushInterval : 1; _QueueLog = new ConcurrentQueue <string>(); Path = path; switch (segmentMode) { case SegmentMode.Never: GetFileNameCheck = (DateTime dateTime) => { return(false); }; break; case SegmentMode.Month: GetFileNameCheck = (DateTime dateTime) => { return(dateTime.Month != _TimeStampStart.Month); }; break; case SegmentMode.Week: GetFileNameCheck = (DateTime dateTime) => { return(dateTime.GetWeek() != _TimeStampStart.GetWeek()); }; break; case SegmentMode.Day: GetFileNameCheck = (DateTime dateTime) => { return(dateTime.Day != _TimeStampStart.Day); }; break; case SegmentMode.Hour: GetFileNameCheck = (DateTime dateTime) => { return(dateTime.Hour != _TimeStampStart.Hour); }; break; case SegmentMode.Minute: GetFileNameCheck = (DateTime dateTime) => { return(dateTime.Minute != _TimeStampStart.Minute); }; break; default: break; } Task.Factory.StartNew(() => { while (true) { if (_QueueLog.Count != 0) { string logBuff; string header = "============" + DateTime.Now.ToString(_TimeFormat) + "============" + newLine; string log = ""; string fileName = _Path + "Log_" + GetFileName(DateTime.Now); while (_QueueLog.Count != 0) { if (_QueueLog.TryDequeue(out logBuff)) { log += logBuff; } } if (log != string.Empty) { try { Directory.CreateDirectory(_Path); File.AppendAllText(fileName, header + log, Encoding.UTF8); } catch (Exception e) { throw e; } } } System.Threading.Thread.Sleep(flushInterval); } }); }
protected bool JudgeCurrentMode(SegmentMode prevMode, char[] cache) { char ch = cache[1]; SegmentMode curtMode = JudgeMode(ch); // Mode Begin OpCode detected. (eg.:["][//][/*]) if (ch == '"' && prevMode != SegmentMode.String && prevMode != SegmentMode.Comment) { if (prevMode != SegmentMode.OpCode) { StartOpCode = "\""; SegmentType = SegmentMode.String; return true; } else { return false; } } else if (ch == '\\' && cache[0] == '\\' && prevMode == SegmentMode.String) { return true; } else if (ch == '/' && cache[0] == '/' && prevMode != SegmentMode.Comment && prevMode != SegmentMode.String) { if (prevMode != SegmentMode.OpCode) { StartOpCode = "//"; SegmentType = SegmentMode.Comment; return true; } else { return false; } } else if (ch == '*' && cache[0] == '/' && prevMode != SegmentMode.Comment && prevMode != SegmentMode.String) { StartOpCode = "/*"; SegmentType = SegmentMode.Comment; return true; } else if (ch == '(' && prevMode == SegmentMode.Variable) { if (prevSegment != null && !"function".Equals(prevSegment.Content)) { SegmentType = SegmentMode.FuncCall; } else { SegmentType = SegmentMode.FuncDef; } return false; } // Mode End OpCode detected. (eg.:["][\r][\n][*/]) if (curtMode == prevMode && curtMode != SegmentMode.String && curtMode != SegmentMode.Comment) { if (ch != '(' && ch != ')' && ch != '{' && ch != '}') { if (prevMode == SegmentMode.OpCode && curtMode == SegmentMode.OpCode) { if (cache[0] == '/' && ch == '/' || cache[0] == '/' && ch == '*') { SegmentType = SegmentMode.Comment; } } if (SegmentType == SegmentMode.NotSpecified && curtMode != SegmentMode.NotSpecified) { SegmentType = curtMode; } return true; } else { return false; } } else if (prevMode == SegmentMode.Variable && curtMode == SegmentMode.Number) { SegmentType = prevMode; return true; } else if (prevMode == SegmentMode.Number && ch == '.') { SegmentType = SegmentMode.Number; return true; } else if (prevMode == SegmentMode.String) { SegmentType = prevMode; if ("\"".Equals(StartOpCode) && (ch != '"' || cache[0] == '\\')) { return true; } else { return false; } } else if (prevMode == SegmentMode.Comment) { if (("//".Equals(StartOpCode) && ch != '\n') || ("/*".Equals(StartOpCode) && (cache[0] != '*' || cache[1] != '/'))) { SegmentType = prevMode; return true; } else { return false; } } else if ((prevMode == SegmentMode.String || prevMode == SegmentMode.Comment) && curtMode == SegmentMode.Space) { SegmentType = prevMode; return true; } else if (prevMode == SegmentMode.NotSpecified && curtMode != SegmentMode.NotSpecified) { SegmentType = curtMode; return true; } return false; }
protected bool JudgeCurrentMode(SegmentMode prevMode, char[] cache) { char ch = cache[1]; SegmentMode curtMode = JudgeMode(ch); // Mode Begin OpCode detected. (eg.:["][//][/*]) if (ch == '"' && prevMode != SegmentMode.String && prevMode != SegmentMode.Comment) { if (prevMode != SegmentMode.OpCode) { StartOpCode = "\""; SegmentType = SegmentMode.String; return(true); } else { return(false); } } else if (ch == '\\' && cache[0] == '\\' && prevMode == SegmentMode.String) { return(true); } else if (ch == '/' && cache[0] == '/' && prevMode != SegmentMode.Comment && prevMode != SegmentMode.String) { if (prevMode != SegmentMode.OpCode) { StartOpCode = "//"; SegmentType = SegmentMode.Comment; return(true); } else { return(false); } } else if (ch == '*' && cache[0] == '/' && prevMode != SegmentMode.Comment && prevMode != SegmentMode.String) { StartOpCode = "/*"; SegmentType = SegmentMode.Comment; return(true); } else if (ch == '(' && prevMode == SegmentMode.Variable) { if (prevSegment != null && !"function".Equals(prevSegment.Content)) { SegmentType = SegmentMode.FuncCall; } else { SegmentType = SegmentMode.FuncDef; } return(false); } // Mode End OpCode detected. (eg.:["][\r][\n][*/]) if (curtMode == prevMode && curtMode != SegmentMode.String && curtMode != SegmentMode.Comment) { if (ch != '(' && ch != ')' && ch != '{' && ch != '}') { if (prevMode == SegmentMode.OpCode && curtMode == SegmentMode.OpCode) { if (cache[0] == '/' && ch == '/' || cache[0] == '/' && ch == '*') { SegmentType = SegmentMode.Comment; } } if (SegmentType == SegmentMode.NotSpecified && curtMode != SegmentMode.NotSpecified) { SegmentType = curtMode; } return(true); } else { return(false); } } else if (prevMode == SegmentMode.Variable && curtMode == SegmentMode.Number) { SegmentType = prevMode; return(true); } else if (prevMode == SegmentMode.Number && ch == '.') { SegmentType = SegmentMode.Number; return(true); } else if (prevMode == SegmentMode.String) { SegmentType = prevMode; if ("\"".Equals(StartOpCode) && (ch != '"' || cache[0] == '\\')) { return(true); } else { return(false); } } else if (prevMode == SegmentMode.Comment) { if (("//".Equals(StartOpCode) && ch != '\n') || ("/*".Equals(StartOpCode) && (cache[0] != '*' || cache[1] != '/'))) { SegmentType = prevMode; return(true); } else { return(false); } } else if ((prevMode == SegmentMode.String || prevMode == SegmentMode.Comment) && curtMode == SegmentMode.Space) { SegmentType = prevMode; return(true); } else if (prevMode == SegmentMode.NotSpecified && curtMode != SegmentMode.NotSpecified) { SegmentType = curtMode; return(true); } return(false); }
/// <summary> /// Tries to decode the first segment in <paramref name="bitArray"/> /// </summary> /// <param name="bitArray">Span of bits to be decoded</param> /// <param name="codeVersion">QR Code version from 1 to 40</param> /// <param name="result">Decoded segment</param> /// <param name="bitsRead">Amount of used bits in <paramref name="bitArray"/></param> /// <returns>Inndicates if a segment was successfully decoded</returns> static bool TryDecodeFirstSegment(ReadOnlySpan <byte> bitArray, int codeVersion, out Segment result, out int bitsRead) { int modeIndicatorLength = Math.Min(4, bitArray.Length); SegmentMode mode = (SegmentMode)AssembleBits(bitArray.Slice(0, modeIndicatorLength), 0, modeIndicatorLength); switch (mode) { case SegmentMode.ECI: { try { (int eciDesignator, int bitCount) = (bitArray[modeIndicatorLength], bitArray[modeIndicatorLength + 1], bitArray[modeIndicatorLength + 2]) switch { (0, _, _) => (AssembleBits(bitArray, modeIndicatorLength + 1, 7), 8), (1, 0, _) => (AssembleBits(bitArray, modeIndicatorLength + 2, 14), 16), (1, 1, 0) => (AssembleBits(bitArray, modeIndicatorLength + 3, 21), 24), _ => throw new Exception($"Incorrect ECI designator prefix: {bitArray[modeIndicatorLength]}{bitArray[modeIndicatorLength + 1]}{bitArray[modeIndicatorLength + 2]}") }; result = new Segment { Mode = mode, CharacterCount = 0, Content = new byte[0] }; bitsRead = modeIndicatorLength + bitCount; return(true); } catch { result = new Segment(); bitsRead = 0; return(false); } } case SegmentMode.Numeric: case SegmentMode.Alphanumeric: case SegmentMode.Byte: case SegmentMode.Kanji: { try //TODO: replace this try/catch with something decent { ReadOnlySpan <byte> countIndicator = bitArray.Slice(modeIndicatorLength, GetCountIndicatorLength(codeVersion, mode)); int count = AssembleBits(countIndicator, 0, countIndicator.Length); int bitCount = GetBitCount(mode, count); ReadOnlySpan <byte> data = bitArray.Slice(modeIndicatorLength + countIndicator.Length, bitCount); result = new Segment { Mode = mode, CharacterCount = count, Content = mode switch { SegmentMode.Numeric => DecodeNumeric(data, count), SegmentMode.Alphanumeric => DecodeAlphanumeric(data, count), SegmentMode.Byte => DecodeByte(data, count), SegmentMode.Kanji => DecodeKanji(data, count), _ => throw new Exception("wtf") } }; bitsRead = modeIndicatorLength + countIndicator.Length + bitCount; return(true); } catch { result = new Segment(); bitsRead = 0; return(false); } } case SegmentMode.StructuredAppend: { try { byte sequenceIndicator = (byte)AssembleBits(bitArray, modeIndicatorLength, 8); byte parityData = (byte)AssembleBits(bitArray, modeIndicatorLength + 8, 8); result = new Segment { Mode = mode, CharacterCount = 0, Content = new byte[] { sequenceIndicator, parityData } }; bitsRead = modeIndicatorLength + 16; return(true); } catch { result = new Segment(); bitsRead = 0; return(false); } } case SegmentMode.FNC1FirstPosition: { try { result = new Segment { Mode = mode, CharacterCount = 0, Content = new byte[0] }; bitsRead = modeIndicatorLength; return(true); } catch { result = new Segment(); bitsRead = 0; return(false); } } case SegmentMode.FNC1SecondPosition: { try { byte applicationIndicator = (byte)AssembleBits(bitArray, modeIndicatorLength, 8); result = new Segment { Mode = mode, CharacterCount = 0, Content = new byte[] { applicationIndicator } }; bitsRead = modeIndicatorLength + 8; return(true); } catch { result = new Segment(); bitsRead = 0; return(false); } } case SegmentMode.Terminator: { result = new Segment { Mode = mode, CharacterCount = 0, Content = new byte[0] }; bitsRead = modeIndicatorLength; return(true); } default: { throw new Exception($"Unknown segment mode: {mode}"); } } }