@@ -203,171 +203,206 @@ defmodule Base do
203203 @ swar_dash_x7 0x2D2D2D2D2D2D2D
204204 @ swar_under_x7 0x5F5F5F5F5F5F5F
205205
206- # Per-byte validity guards (used in both the SWAR clauses for the 8th byte
206+ # Per-byte validity checks (used in both the SWAR clauses for the 8th byte
207207 # of each stride and in the body of the sub-8-byte tail clauses).
208- defguardp valid_char16upper? ( c ) when c in ?0 .. ?9 or c in ?A .. ?F
209- defguardp valid_char16lower? ( c ) when c in ?0 .. ?9 or c in ?a .. ?f
210- defguardp valid_char16mixed? ( c ) when c in ?0 .. ?9 or c in ?A .. ?F or c in ?a .. ?f
211-
212- defguardp valid_char32upper? ( c ) when c in ?A .. ?Z or c in ?2 .. ?7
213- defguardp valid_char32lower? ( c ) when c in ?a .. ?z or c in ?2 .. ?7
214- defguardp valid_char32mixed? ( c ) when c in ?A .. ?Z or c in ?a .. ?z or c in ?2 .. ?7
208+ @ compile { :inline ,
209+ valid_char16upper?: 1 ,
210+ valid_char16lower?: 1 ,
211+ valid_char16mixed?: 1 ,
212+ valid_char32upper?: 1 ,
213+ valid_char32lower?: 1 ,
214+ valid_char32mixed?: 1 ,
215+ valid_char32hexupper?: 1 ,
216+ valid_char32hexlower?: 1 ,
217+ valid_char32hexmixed?: 1 ,
218+ valid_char64base?: 1 ,
219+ valid_char64url?: 1 ,
220+ valid_word16upper?: 1 ,
221+ valid_word16lower?: 1 ,
222+ valid_word16mixed?: 1 ,
223+ valid_word32upper?: 1 ,
224+ valid_word32lower?: 1 ,
225+ valid_word32mixed?: 1 ,
226+ valid_word32hexupper?: 1 ,
227+ valid_word32hexlower?: 1 ,
228+ valid_word32hexmixed?: 1 ,
229+ valid_word64base?: 1 ,
230+ valid_word64url?: 1 }
231+
232+ defp valid_char16upper? ( c ) , do: c in ?0 .. ?9 or c in ?A .. ?F
233+ defp valid_char16lower? ( c ) , do: c in ?0 .. ?9 or c in ?a .. ?f
234+ defp valid_char16mixed? ( c ) , do: c in ?0 .. ?9 or c in ?A .. ?F or c in ?a .. ?f
235+
236+ defp valid_char32upper? ( c ) , do: c in ?A .. ?Z or c in ?2 .. ?7
237+ defp valid_char32lower? ( c ) , do: c in ?a .. ?z or c in ?2 .. ?7
238+ defp valid_char32mixed? ( c ) , do: c in ?A .. ?Z or c in ?a .. ?z or c in ?2 .. ?7
215239
216240 # Most common range first — letters dominate (22/32) over digits (10/32)
217241 # in hex base32, so letters go first in the OR short-circuit.
218- defguardp valid_char32hexupper? ( c ) when c in ?A .. ?V or c in ?0 .. ?9
219- defguardp valid_char32hexlower? ( c ) when c in ?a .. ?v or c in ?0 .. ?9
220- defguardp valid_char32hexmixed? ( c ) when c in ?A .. ?V or c in ?a .. ?v or c in ?0 .. ?9
242+ defp valid_char32hexupper? ( c ) , do: c in ?A .. ?V or c in ?0 .. ?9
243+ defp valid_char32hexlower? ( c ) , do: c in ?a .. ?v or c in ?0 .. ?9
244+ defp valid_char32hexmixed? ( c ) , do: c in ?A .. ?V or c in ?a .. ?v or c in ?0 .. ?9
221245
222- defguardp valid_char64base? ( c )
223- when c in ?A .. ?Z or c in ?a .. ?z or c in ?0 .. ?9 or c == ?+ or c == ?/
246+ defp valid_char64base? ( c ) ,
247+ do: c in ?A .. ?Z or c in ?a .. ?z or c in ?0 .. ?9 or c == ?+ or c == ?/
224248
225- defguardp valid_char64url? ( c )
226- when c in ?A .. ?Z or c in ?a .. ?z or c in ?0 .. ?9 or c == ?- or c == ?_
249+ defp valid_char64url? ( c ) ,
250+ do: c in ?A .. ?Z or c in ?a .. ?z or c in ?0 .. ?9 or c == ?- or c == ?_
227251
228- # SWAR 7-byte word validity. Structure for each guard :
252+ # SWAR 7-byte word validity. Structure for each function :
229253 # 1. ASCII gate `band(w, MASK80) == 0` — every byte < 0x80 so the
230254 # additions below cannot carry across lanes.
231255 # 2. "Each byte is in range A OR range B (OR range C)" gate — OR per-
232256 # range XOR masks (high bit set in lane iff byte in that range), AND
233257 # with MASK80, demand all 7 high bits set.
234- defguardp valid_word16upper? ( w )
235- when band ( w , @ swar_mask80 ) == 0 and
236- band (
237- bor (
238- bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
239- bxor ( w + @ swar_ge_A , w + @ swar_gt_F )
240- ) ,
241- @ swar_mask80
242- ) == @ swar_mask80
243-
244- defguardp valid_word16lower? ( w )
245- when band ( w , @ swar_mask80 ) == 0 and
246- band (
247- bor (
248- bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
249- bxor ( w + @ swar_ge_a , w + @ swar_gt_f )
250- ) ,
251- @ swar_mask80
252- ) == @ swar_mask80
253-
254- defguardp valid_word16mixed? ( w )
255- when band ( w , @ swar_mask80 ) == 0 and
256- band (
257- bor (
258- bor (
259- bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
260- bxor ( w + @ swar_ge_A , w + @ swar_gt_F )
261- ) ,
262- bxor ( w + @ swar_ge_a , w + @ swar_gt_f )
263- ) ,
264- @ swar_mask80
265- ) == @ swar_mask80
266-
267- defguardp valid_word32upper? ( w )
268- when band ( w , @ swar_mask80 ) == 0 and
269- band (
270- bor (
271- bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
272- bxor ( w + @ swar_ge_2 , w + @ swar_gt_7 )
273- ) ,
274- @ swar_mask80
275- ) == @ swar_mask80
276-
277- defguardp valid_word32lower? ( w )
278- when band ( w , @ swar_mask80 ) == 0 and
279- band (
280- bor (
281- bxor ( w + @ swar_ge_a , w + @ swar_gt_z ) ,
282- bxor ( w + @ swar_ge_2 , w + @ swar_gt_7 )
283- ) ,
284- @ swar_mask80
285- ) == @ swar_mask80
286-
287- defguardp valid_word32mixed? ( w )
288- when band ( w , @ swar_mask80 ) == 0 and
289- band (
290- bor (
291- bor (
292- bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
293- bxor ( w + @ swar_ge_a , w + @ swar_gt_z )
294- ) ,
295- bxor ( w + @ swar_ge_2 , w + @ swar_gt_7 )
296- ) ,
297- @ swar_mask80
298- ) == @ swar_mask80
299-
300- defguardp valid_word32hexupper? ( w )
301- when band ( w , @ swar_mask80 ) == 0 and
302- band (
303- bor (
304- bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
305- bxor ( w + @ swar_ge_A , w + @ swar_gt_V )
306- ) ,
307- @ swar_mask80
308- ) == @ swar_mask80
309-
310- defguardp valid_word32hexlower? ( w )
311- when band ( w , @ swar_mask80 ) == 0 and
312- band (
313- bor (
314- bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
315- bxor ( w + @ swar_ge_a , w + @ swar_gt_v )
316- ) ,
317- @ swar_mask80
318- ) == @ swar_mask80
319-
320- defguardp valid_word32hexmixed? ( w )
321- when band ( w , @ swar_mask80 ) == 0 and
322- band (
323- bor (
324- bor (
325- bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
326- bxor ( w + @ swar_ge_A , w + @ swar_gt_V )
327- ) ,
328- bxor ( w + @ swar_ge_a , w + @ swar_gt_v )
329- ) ,
330- @ swar_mask80
331- ) == @ swar_mask80
258+ defp valid_word16upper? ( w ) do
259+ band ( w , @ swar_mask80 ) == 0 and
260+ band (
261+ bor (
262+ bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
263+ bxor ( w + @ swar_ge_A , w + @ swar_gt_F )
264+ ) ,
265+ @ swar_mask80
266+ ) == @ swar_mask80
267+ end
268+
269+ defp valid_word16lower? ( w ) do
270+ band ( w , @ swar_mask80 ) == 0 and
271+ band (
272+ bor (
273+ bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
274+ bxor ( w + @ swar_ge_a , w + @ swar_gt_f )
275+ ) ,
276+ @ swar_mask80
277+ ) == @ swar_mask80
278+ end
279+
280+ defp valid_word16mixed? ( w ) do
281+ band ( w , @ swar_mask80 ) == 0 and
282+ band (
283+ bor (
284+ bor (
285+ bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
286+ bxor ( w + @ swar_ge_A , w + @ swar_gt_F )
287+ ) ,
288+ bxor ( w + @ swar_ge_a , w + @ swar_gt_f )
289+ ) ,
290+ @ swar_mask80
291+ ) == @ swar_mask80
292+ end
293+
294+ defp valid_word32upper? ( w ) do
295+ band ( w , @ swar_mask80 ) == 0 and
296+ band (
297+ bor (
298+ bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
299+ bxor ( w + @ swar_ge_2 , w + @ swar_gt_7 )
300+ ) ,
301+ @ swar_mask80
302+ ) == @ swar_mask80
303+ end
304+
305+ defp valid_word32lower? ( w ) do
306+ band ( w , @ swar_mask80 ) == 0 and
307+ band (
308+ bor (
309+ bxor ( w + @ swar_ge_a , w + @ swar_gt_z ) ,
310+ bxor ( w + @ swar_ge_2 , w + @ swar_gt_7 )
311+ ) ,
312+ @ swar_mask80
313+ ) == @ swar_mask80
314+ end
315+
316+ defp valid_word32mixed? ( w ) do
317+ band ( w , @ swar_mask80 ) == 0 and
318+ band (
319+ bor (
320+ bor (
321+ bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
322+ bxor ( w + @ swar_ge_a , w + @ swar_gt_z )
323+ ) ,
324+ bxor ( w + @ swar_ge_2 , w + @ swar_gt_7 )
325+ ) ,
326+ @ swar_mask80
327+ ) == @ swar_mask80
328+ end
329+
330+ defp valid_word32hexupper? ( w ) do
331+ band ( w , @ swar_mask80 ) == 0 and
332+ band (
333+ bor (
334+ bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
335+ bxor ( w + @ swar_ge_A , w + @ swar_gt_V )
336+ ) ,
337+ @ swar_mask80
338+ ) == @ swar_mask80
339+ end
340+
341+ defp valid_word32hexlower? ( w ) do
342+ band ( w , @ swar_mask80 ) == 0 and
343+ band (
344+ bor (
345+ bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
346+ bxor ( w + @ swar_ge_a , w + @ swar_gt_v )
347+ ) ,
348+ @ swar_mask80
349+ ) == @ swar_mask80
350+ end
351+
352+ defp valid_word32hexmixed? ( w ) do
353+ band ( w , @ swar_mask80 ) == 0 and
354+ band (
355+ bor (
356+ bor (
357+ bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 ) ,
358+ bxor ( w + @ swar_ge_A , w + @ swar_gt_V )
359+ ) ,
360+ bxor ( w + @ swar_ge_a , w + @ swar_gt_v )
361+ ) ,
362+ @ swar_mask80
363+ ) == @ swar_mask80
364+ end
332365
333366 # base64 SWAR word validity: 3 ranges (A-Z, a-z, 0-9) OR'd with singletons.
334367 # For base, the digit range is extended to [0x2F, 0x39] to absorb '/' as
335368 # part of one range (Lemire merge), leaving only '+' as a Mycroft singleton.
336369 # For url, the singletons '-' and '_' are detected via two Mycroft terms.
337- defguardp valid_word64base? ( w )
338- when band ( w , @ swar_mask80 ) == 0 and
339- band (
340- bor (
341- bor (
342- bor (
343- bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
344- bxor ( w + @ swar_ge_a , w + @ swar_gt_z )
345- ) ,
346- bxor ( w + @ swar_ge_slash , w + @ swar_gt_9 )
347- ) ,
348- bxor ( w , @ swar_plus_x7 ) - @ swar_mask01
349- ) ,
350- @ swar_mask80
351- ) == @ swar_mask80
352-
353- defguardp valid_word64url? ( w )
354- when band ( w , @ swar_mask80 ) == 0 and
355- band (
356- bor (
357- bor (
358- bor (
359- bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
360- bxor ( w + @ swar_ge_a , w + @ swar_gt_z )
361- ) ,
362- bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 )
363- ) ,
364- bor (
365- bxor ( w , @ swar_dash_x7 ) - @ swar_mask01 ,
366- bxor ( w , @ swar_under_x7 ) - @ swar_mask01
367- )
368- ) ,
369- @ swar_mask80
370- ) == @ swar_mask80
370+ defp valid_word64base? ( w ) do
371+ band ( w , @ swar_mask80 ) == 0 and
372+ band (
373+ bor (
374+ bor (
375+ bor (
376+ bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
377+ bxor ( w + @ swar_ge_a , w + @ swar_gt_z )
378+ ) ,
379+ bxor ( w + @ swar_ge_slash , w + @ swar_gt_9 )
380+ ) ,
381+ bxor ( w , @ swar_plus_x7 ) - @ swar_mask01
382+ ) ,
383+ @ swar_mask80
384+ ) == @ swar_mask80
385+ end
386+
387+ defp valid_word64url? ( w ) do
388+ band ( w , @ swar_mask80 ) == 0 and
389+ band (
390+ bor (
391+ bor (
392+ bor (
393+ bxor ( w + @ swar_ge_A , w + @ swar_gt_Z ) ,
394+ bxor ( w + @ swar_ge_a , w + @ swar_gt_z )
395+ ) ,
396+ bxor ( w + @ swar_ge_0 , w + @ swar_gt_9 )
397+ ) ,
398+ bor (
399+ bxor ( w , @ swar_dash_x7 ) - @ swar_mask01 ,
400+ bxor ( w , @ swar_under_x7 ) - @ swar_mask01
401+ )
402+ ) ,
403+ @ swar_mask80
404+ ) == @ swar_mask80
405+ end
371406
372407 @ doc """
373408 Encodes a binary string into a base 16 encoded string.
0 commit comments