Skip to content

Commit af0771e

Browse files
committed
Rework settings and apply to codecs.
1 parent d39ee92 commit af0771e

File tree

58 files changed

+2545
-1424
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2545
-1424
lines changed

src/Fs.Binary.Codecs/Common/CommonDecoder.cs renamed to src/Fs.Binary.Codecs/AffixMatcher.cs

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.Collections.Immutable;
44
using System.Text;
55

6-
namespace Fs.Binary.Codecs.Common
6+
namespace Fs.Binary.Codecs
77
{
88
internal static class AffixMatcher
99
{
@@ -61,65 +61,4 @@ public static int TryMatchAffix ( ReadOnlySpan<char> inputData, int inputIndex,
6161
return (partialMatchIndices == 0) ? matchLength : -1;
6262
}
6363
}
64-
65-
public abstract class CommonDecoder : BinaryDecoder
66-
{
67-
protected private CommonDecoder ()
68-
{
69-
}
70-
71-
protected int TryMatchAffix ( char[] inputData, int inputIndex, int inputEnd, bool flush, ImmutableArray<string> affixes )
72-
{
73-
// affixes must match exactly, we do not skip characters in the input. The incoming list of affixes is
74-
// sorted from shortest to longest and there are no duplicates. The sort order lets us mark matches as
75-
// we find them and know that we always select the longest (best) match.
76-
77-
int initialInputIndex = inputIndex;
78-
int affixesLength = affixes.Length;
79-
int matchOffset = 0;
80-
int matchLength = 0;
81-
int partialMatchIndices = (1 << affixesLength) - 1;
82-
83-
while (inputIndex < inputEnd)
84-
{
85-
char inputChar = inputData[inputIndex];
86-
if (inputChar >= 128)
87-
{
88-
// nothing else can match at this point...
89-
partialMatchIndices = 0;
90-
break;
91-
}
92-
93-
for (int affixIndex = 0; affixIndex < affixesLength; affixIndex++)
94-
{
95-
// ignore affixes that we've already determined don't match..
96-
if ((partialMatchIndices & (1 << affixIndex)) == 0)
97-
continue;
98-
99-
var affixString = affixes[affixIndex];
100-
if (affixString[matchOffset] == inputChar)
101-
{
102-
if (affixString.Length != matchOffset + 1)
103-
continue;
104-
105-
matchLength = affixString.Length;
106-
}
107-
108-
// complete match or non-match, either way remove from partials..
109-
if ((partialMatchIndices &= ~(1 << affixIndex)) == 0)
110-
break;
111-
}
112-
113-
// next input character..
114-
matchOffset++;
115-
inputIndex++;
116-
}
117-
118-
// if we're flushing, remaining possible matches aren't really possible..
119-
if (flush) partialMatchIndices = 0;
120-
121-
// if no more matching, whatever matched wins,.. otherwise not conclusive..
122-
return (partialMatchIndices == 0) ? matchLength : -1;
123-
}
124-
}
12564
}

src/Fs.Binary.Codecs/Base16/Base16Codec.Base16Decoder.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Collections.Generic;
33
using System.Collections.Immutable;
44
using System.Text;
5-
using Fs.Binary.Codecs.Common;
5+
using Fs.Binary.Codecs.Settings;
66

77
namespace Fs.Binary.Codecs.Base16
88
{
@@ -82,7 +82,7 @@ public ConvertStatus ConvertData ( ReadOnlySpan<char> inputData, int inputIndex,
8282
goto case State.BeginReadingPrefix;
8383

8484
case State.BeginReadingPrefix:
85-
if ((_flags & Base16Settings.FlagHasPrefixes) == 0) goto case State.BeginReading;
85+
if ((_flags & SettingsFlags.FlagHasPrefixes) == 0) goto case State.BeginReading;
8686
_currentState = State.ReadingPrefix;
8787
goto case State.ReadingPrefix;
8888

@@ -92,7 +92,7 @@ public ConvertStatus ConvertData ( ReadOnlySpan<char> inputData, int inputIndex,
9292
if (matchLength < 0) // need more data..
9393
return ConvertStatus.InputRequired;
9494

95-
if ((matchLength == 0) && ((_flags & Base16Settings.FlagRequirePrefix) != 0))
95+
if ((matchLength == 0) && ((_flags & SettingsFlags.FlagRequirePrefix) != 0))
9696
throw new FormatException(Resources.DecoderPrefixRequired);
9797

9898
inputIndex += matchLength;
@@ -111,7 +111,7 @@ public ConvertStatus ConvertData ( ReadOnlySpan<char> inputData, int inputIndex,
111111
char inputChar = inputData[inputIndex++];
112112
if (inputChar >= 128)
113113
{
114-
if ((_flags & Base16Settings.FlagIgnoreInvalidCharacters) == 0)
114+
if ((_flags & SettingsFlags.FlagIgnoreInvalidCharacters) == 0)
115115
throw new FormatException(Resources.DecoderInvalidCharacter);
116116

117117
// ignoring invalid characters..
@@ -152,15 +152,15 @@ public ConvertStatus ConvertData ( ReadOnlySpan<char> inputData, int inputIndex,
152152

153153
// inputChar is always 127 or less here (due to check above)
154154
byte decodedValue = _decodingTable[inputChar];
155-
if ((decodedValue & Base16Settings.CharTypeMask) == Base16Settings.CharAlphabet)
155+
if ((decodedValue & SettingsCharacterTypes.CharTypeMask) == SettingsCharacterTypes.CharAlphabet)
156156
{
157157
_decodedBits = (_decodedBits << 4) | (uint)(decodedValue & 0x0F);
158158
_decodedCount++;
159159
}
160-
else if (decodedValue != Base16Settings.CharSpecialIgnored)
160+
else if (decodedValue != SettingsCharacterTypes.CharSpecialIgnored)
161161
{
162162
// all non-ignored characters are treated as invalid..
163-
if ((_flags & Base16Settings.FlagIgnoreInvalidCharacters) == 0)
163+
if ((_flags & SettingsFlags.FlagIgnoreInvalidCharacters) == 0)
164164
throw new FormatException(Resources.DecoderInvalidCharacter);
165165
}
166166

@@ -191,7 +191,7 @@ public ConvertStatus ConvertData ( ReadOnlySpan<char> inputData, int inputIndex,
191191
if ((_decodedCount & 0x01) != 0)
192192
{
193193
// an odd number of input characters is invalid..
194-
if ((_flags & Base16Settings.FlagIgnoreInvalidFinalQuantum) == 0)
194+
if ((_flags & SettingsFlags.FlagIgnoreInvalidFinalQuantum) == 0)
195195
throw new FormatException(Resources.DecoderTruncatedQuantum);
196196

197197
_decodedBits >>= 4;
@@ -206,7 +206,7 @@ public ConvertStatus ConvertData ( ReadOnlySpan<char> inputData, int inputIndex,
206206
goto case State.BeginWriting;
207207

208208
case State.Finished:
209-
if (((_flags & Base16Settings.FlagRequirePostfix) != 0) && (!_postfixRead))
209+
if (((_flags & SettingsFlags.FlagRequirePostfix) != 0) && (!_postfixRead))
210210
throw new FormatException(Resources.DecoderPostfixRequired);
211211

212212
_currentState = State.Reset;

src/Fs.Binary.Codecs/Base16/Base16Codec.Base16Encoder.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Text;
4+
using Fs.Binary.Codecs.Settings;
45

56
namespace Fs.Binary.Codecs.Base16
67
{
@@ -68,13 +69,14 @@ public void Reset ()
6869
{
6970
_currentState = State.Reset;
7071
_previousState = State.ReturnToPreviousState;
72+
_currentLineLength = 0;
7173
}
7274

7375
public ConvertStatus ConvertData ( ReadOnlySpan<byte> inputData, int inputIndex, int inputCount, Span<char> outputData, int outputIndex, int outputCount, bool flush, out int inputUsed, out int outputUsed )
7476
{
7577
var inputEnd = inputIndex + inputCount;
7678
var outputEnd = outputIndex + outputCount;
77-
var hasSeparators = (_lineSeparator != null);
79+
var hasSeparators = (_lineSeparator != null) && (_lineSeparator.Length != 0);
7880
inputUsed = outputUsed = 0;
7981

8082
while (true)
@@ -181,7 +183,7 @@ public ConvertStatus ConvertData ( ReadOnlySpan<byte> inputData, int inputIndex,
181183
goto case State.BeginWriting;
182184

183185
case State.BeginFinalSeparator:
184-
if ((!hasSeparators) || ((_flags & Base16Settings.FlagIncludeTerminatingLineSeparator) == 0)) goto case State.Finished;
186+
if ((!hasSeparators) || ((_flags & SettingsFlags.ForceTerminatingLineSeparator) == 0)) goto case State.Finished;
185187

186188
SetPreviousState(State.Finished);
187189
goto case State.BeginSeparator;
@@ -208,6 +210,7 @@ public ConvertStatus ConvertData ( ReadOnlySpan<byte> inputData, int inputIndex,
208210
case State.ReturnToPreviousState:
209211
System.Diagnostics.Debug.Assert(_previousState != State.ReturnToPreviousState);
210212
_currentState = _previousState;
213+
_previousState = State.ReturnToPreviousState;
211214
continue;
212215

213216
default:

src/Fs.Binary.Codecs/Base16/Base16Codec.Decoder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Collections.Generic;
33
using System.Collections.Immutable;
44
using System.Text;
5-
using Fs.Binary.Codecs.Common;
5+
using Fs.Binary.Codecs.Settings;
66

77
namespace Fs.Binary.Codecs.Base16
88
{

src/Fs.Binary.Codecs/Base16/Base16Codec.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public override int GetMaxCharCount ( int byteCount )
177177
return (byteCount << 1) + Settings.EncodingAffixLength;
178178
}
179179

180-
public override int MinimumInputBuffer => Settings.GetMinimumInputBuffer();
180+
public override int MinimumInputBuffer => Settings.DecodingMinimumInputBuffer;
181181
public override int MinimumOutputBuffer => 1;
182182

183183
public Base16Settings Settings { get; }

src/Fs.Binary.Codecs/Base16/Base16Settings.cs

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
using System.Collections.Generic;
33
using System.Collections.Immutable;
44
using System.Text;
5-
using Fs.Binary.Codecs.Common;
5+
using Fs.Binary.Codecs.Settings;
6+
using Fs.Binary.Codecs.Settings.Providers;
67

78
namespace Fs.Binary.Codecs.Base16
89
{
9-
public class Base16Settings : ExposedAlphabetBuilder
10+
public class Base16Settings : SettingsBase, ISettingsAlphabet, ISettingsDecodingAffixes, ISettingsEncodingAffixes,
11+
ISettingsEncodingLines, ISettingsDecodingCheckFinalQuantum
1012
{
13+
private const int AlphabetSize = 16;
1114
private static readonly string[] DefaultAlphabet = new string[]
1215
{
1316
"0123456789ABCDEF",
@@ -16,17 +19,41 @@ public class Base16Settings : ExposedAlphabetBuilder
1619

1720
public static readonly Base16Settings Default = new Base16Settings()
1821
{
19-
IsReadOnly = true
22+
Alphabets = DefaultAlphabet,
23+
IsProtected = true
2024
};
2125

22-
public Base16Settings ()
23-
: base(16, DefaultAlphabet)
26+
private readonly SettingsFlagsProvider _flagsProvider;
27+
private readonly SettingsAlphabetProvider _alphabetProvider;
28+
private readonly SettingsDecodingAffixesProvider _decodingAffixes;
29+
private readonly SettingsEncodingAffixProvider _encodingAffixes;
30+
private readonly SettingsEncodingLinesProvider _encodingLines;
31+
private readonly SettingsDecodingCheckFinalQuantumProvider _decodingFinalQuantumProvider;
32+
33+
private Base16Settings ()
34+
: base()
2435
{
36+
_alphabetProvider = new SettingsAlphabetProvider(this, AlphabetSize);
37+
_decodingAffixes = new SettingsDecodingAffixesProvider(this);
38+
_encodingAffixes = new SettingsEncodingAffixProvider(this);
39+
_encodingLines = new SettingsEncodingLinesProvider(this);
40+
_decodingFinalQuantumProvider = new SettingsDecodingCheckFinalQuantumProvider(this);
41+
_flagsProvider = new SettingsFlagsProvider(this);
2542
}
2643

27-
public Base16Settings ( Base16Settings inheritedSettings, bool isProtected )
28-
: base(inheritedSettings, isProtected)
44+
public Base16Settings ( Base16Settings inheritedSettings )
45+
: this()
2946
{
47+
if (inheritedSettings == null)
48+
throw new ArgumentNullException(nameof(inheritedSettings));
49+
50+
InheritSettings(inheritedSettings);
51+
}
52+
53+
private Base16Settings ( Base16Settings inheritedSettings, bool isProtected )
54+
: this(inheritedSettings)
55+
{
56+
IsProtected = isProtected;
3057
}
3158

3259
internal void GetEncoderSettings ( out string alphabet,
@@ -36,12 +63,12 @@ internal void GetEncoderSettings ( out string alphabet,
3663
out string initialPrefix,
3764
out string finalPrefix )
3865
{
39-
alphabet = GetAlphabet();
40-
flags = GetFlags();
41-
lineSeparator = GetLineSeparator();
42-
maximumLineLength = GetMaximumLineLength();
43-
initialPrefix = GetEncodingPrefix();
44-
finalPrefix = GetEncodingPostfix();
66+
alphabet = _alphabetProvider.GetEncodingAlphabet();
67+
flags = _flagsProvider.GetFlags();
68+
lineSeparator = _encodingLines.GetEncodingLineSeparator();
69+
maximumLineLength = _encodingLines.GetEncodingMaximumLineLength();
70+
initialPrefix = _encodingAffixes.GetEncodingPrefix();
71+
finalPrefix = _encodingAffixes.GetEncodingPostfix();
4572
}
4673

4774
internal void GetDecoderSettings ( out ImmutableArray<byte> decodingTable,
@@ -50,13 +77,33 @@ internal void GetDecoderSettings ( out ImmutableArray<byte> decodingTable,
5077
out ImmutableArray<string> decodingPostfixes,
5178
out int flags )
5279
{
53-
decodingTable = GetDecodingTable();
54-
decodingAffixTable = GetDecodingAffixTable();
55-
decodingPrefixes = GetDecodingPrefixes();
56-
decodingPostfixes = GetDecodingPostfixes();
57-
flags = GetFlags();
80+
decodingTable = _alphabetProvider.GetDecodingTable();
81+
decodingAffixTable = _decodingAffixes.GetDecodingTable();
82+
decodingPrefixes = _decodingAffixes.GetDecodingPrefixes();
83+
decodingPostfixes = _decodingAffixes.GetDecodingPostfixes();
84+
flags = _flagsProvider.GetFlags();
5885
}
5986

60-
public Base16Settings ToReadOnly () => new Base16Settings(this, true);
87+
// GetHexEncoding / GetHexDecoding are used by other encodings to encode/decode hexadecimal values
88+
internal string GetHexEncoding () => _alphabetProvider.GetEncodingAlphabet();
89+
internal ImmutableArray<byte> GetHexDecoding () => _alphabetProvider.GetDecodingTable();
90+
91+
public Base16Settings ToReadOnly () => (IsProtected) ? this : new Base16Settings(this, true);
92+
93+
public string[] Alphabets { get => _alphabetProvider.Alphabets; set => _alphabetProvider.Alphabets = value; }
94+
public string DecodingIgnorableCharacters { get => _alphabetProvider.DecodingIgnorableCharacters; set => _alphabetProvider.DecodingIgnorableCharacters = value; }
95+
public bool DecodingIgnoreInvalidCharacters { get => _alphabetProvider.DecodingIgnoreInvalidCharacters; set => _alphabetProvider.DecodingIgnoreInvalidCharacters = value; }
96+
public string[] DecodingPrefixes { get => _decodingAffixes.DecodingPrefixes; set => _decodingAffixes.DecodingPrefixes = value; }
97+
public string[] DecodingPostfixes { get => _decodingAffixes.DecodingPostfixes; set => _decodingAffixes.DecodingPostfixes = value; }
98+
public bool DecodingPrefixRequired { get => _decodingAffixes.DecodingPrefixRequired; set => _decodingAffixes.DecodingPrefixRequired = value; }
99+
public bool DecodingPostfixRequired { get => _decodingAffixes.DecodingPostfixRequired; set => _decodingAffixes.DecodingPostfixRequired = value; }
100+
public int DecodingMinimumInputBuffer => _decodingAffixes.DecodingMinimumInputBuffer;
101+
public string EncodingPrefix { get => _encodingAffixes.EncodingPrefix; set => _encodingAffixes.EncodingPrefix = value; }
102+
public string EncodingPostfix { get => _encodingAffixes.EncodingPostfix; set => _encodingAffixes.EncodingPostfix = value; }
103+
public int EncodingAffixLength => _encodingAffixes.EncodingAffixLength;
104+
public string EncodingLineSeparator { get => _encodingLines.EncodingLineSeparator; set => _encodingLines.EncodingLineSeparator = value; }
105+
public int EncodingMaximumLineLength { get => _encodingLines.EncodingMaximumLineLength; set => _encodingLines.EncodingMaximumLineLength = value; }
106+
public bool EncodingRequireTerminalLineSeparator { get => _encodingLines.EncodingRequireTerminalLineSeparator; set => _encodingLines.EncodingRequireTerminalLineSeparator = value; }
107+
public bool DecodingIgnoreInvalidFinalQuantum { get => _decodingFinalQuantumProvider.DecodingIgnoreInvalidFinalQuantum; set => _decodingFinalQuantumProvider.DecodingIgnoreInvalidFinalQuantum = value; }
61108
}
62109
}

0 commit comments

Comments
 (0)