-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCommonU.pas
137 lines (115 loc) · 2.96 KB
/
CommonU.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
unit CommonU;
interface
uses
Math,
System.Classes,
System.NetEncoding.Sqids;
const
ALPHABET_DEFAULT = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
ALPHABET_NUMBERS = '0123456789';
ALPHABET_LETTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
ALPHABET_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';
ALPHABET_UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
ALPHABETS: TArray<string> = [ALPHABET_DEFAULT,
ALPHABET_NUMBERS,
ALPHABET_LETTERS,
ALPHABET_LOWERCASE,
ALPHABET_UPPERCASE];
type
TMySqids = class(TObject)
private
FSqids: TSqidsEncoding;
FAlphabet: string;
FLength: integer;
function GetAlphabet: string;
procedure SetAlphabet(const Value: string);
function GetLength: integer;
procedure SetLength(const Value: integer);
public
constructor Create;
destructor Destroy; override;
function Encode(const ANumbers: string): string;
function Decode(const AHash: string): string;
property Alphabet: string read GetAlphabet write SetAlphabet;
property Length: integer read GetLength write SetLength;
end;
var
MySqids: TMySqids;
function ShuffleString(const AString: string): string;
implementation
uses System.SysUtils;
function ShuffleString(const AString: string): string;
var
j: integer;
t: char;
begin
randomize;
var a := AString;
for var i := Length(a) downto 1 do
begin
j := randomrange(1, i);
t := a[i];
a[i] := a[j];
a[j] := t;
end;
Result := a;
end;
{ TMySqids }
constructor TMySqids.Create;
begin
FSqids := TSqidsEncoding.Create;
end;
destructor TMySqids.Destroy;
begin
inherited;
FSqids.Free;
end;
function TMySqids.GetLength: integer;
begin
Result := FLength;
end;
procedure TMySqids.SetLength(const Value: integer);
begin
FLength := Value;
FSqids.Free;
FSqids := TSqidsEncoding.Create(Alphabet, Length);
end;
procedure TMySqids.SetAlphabet(const Value: string);
begin
FAlphabet := Value;
FSqids.Free;
FSqids := TSqidsEncoding.Create(Alphabet, Length);
end;
function TMySqids.GetAlphabet: string;
begin
Result := FAlphabet;
end;
function TMySqids.Decode(const AHash: string): string;
begin
Result := FSqids.DecodeToStr(AHash.Trim);
// Decoding IDs will usually produce some kind of numeric output,
// but that doesn't necessarily mean that the ID is canonical.
// To check that the ID is valid, you can re-encode decoded numbers and check that the ID matches.
if AHash <> Encode(Result) then
Result := 'Invalid ID';
end;
function TMySqids.Encode(const ANumbers: string): string;
begin
var lNumbers := ANumbers.Replace(' ', '');
if lNumbers.EndsWith(',') then
lNumbers := lNumbers.TrimRight([',']);
try
Result := FSqids.Encode(lNumbers);
except
Result := 'invalid numbers';
end;
end;
initialization
begin
MySqids := TMySqids.Create;
end;
finalization
begin
MySqids.Free;
end;
end.