Skip to content

feat: add base64 support - #1171

Open
RatanKokal wants to merge 10 commits into
fortran-lang:masterfrom
RatanKokal:wip_base64
Open

feat: add base64 support#1171
RatanKokal wants to merge 10 commits into
fortran-lang:masterfrom
RatanKokal:wip_base64

Conversation

@RatanKokal

@RatanKokal RatanKokal commented Mar 31, 2026

Copy link
Copy Markdown

Adds support for base64

Solves issue: #916

This PR provides a portable, branchless scalar implementation. A follow-up PR is in development to add an AVX2-accelerated backend for supported x86_64 architectures.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces Base64 encoding/decoding support to stdlib, integrating it into the strings component and adding a dedicated test suite (per issue #916).

Changes:

  • Added new stdlib_base64 module implementing base64_encode (generic over numeric/logical types) and base64_decode.
  • Re-exported base64_encode/base64_decode via stdlib_strings.
  • Added Base64 unit tests and wired them into the string test CMake configuration.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/strings/stdlib_base64.fypp New Base64 implementation (encode/decode).
src/strings/stdlib_strings.fypp Re-exports Base64 APIs from stdlib_base64.
src/strings/CMakeLists.txt Adds stdlib_base64.fypp to strings build sources.
test/string/test_base64.f90 Adds unit tests for known vectors, whitespace handling, invalid input, and roundtrips.
test/string/CMakeLists.txt Registers the new base64 test target.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/strings/stdlib_base64.fypp Outdated
Comment thread src/strings/stdlib_base64.fypp Outdated
Comment thread src/strings/stdlib_base64.fypp

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/strings/stdlib_base64_encode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread test/string/test_base64.f90 Outdated
Comment thread test/string/test_base64.f90
@RatanKokal

Copy link
Copy Markdown
Author

@jvdp1 Could you please have a look? I have tackled all possible issues.

Working on a performance improvement using avx2 specific instructions which was the ultimate goal of the resources shared in the issue. Upon completion, would increase speeds drastically.

Since fortran is depndent on autovectorizers, it may not always lead to the optimall register management as can be controlled using C intrinsics.

Will still have a architecture fallback. Architecture specific kernels can be added to increase performance in future.

@jvdp1 jvdp1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you @RatanKokal for this PR. Overall it looks already very good to me.

Maybe some general comments:

  • I suggest to use state_type (provided by stdlib_error to handle errors
  • I think that some procedures could be declared pure
  • Is there any reason to prefer module instead of using submodule?

Comment thread src/strings/stdlib_base64.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated
@codecov

codecov Bot commented Apr 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.20%. Comparing base (72698fd) to head (7000f3a).
⚠️ Report is 71 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1171      +/-   ##
==========================================
- Coverage   68.66%   68.20%   -0.46%     
==========================================
  Files         408       19     -389     
  Lines       13619     2378   -11241     
  Branches     1537        0    -1537     
==========================================
- Hits         9351     1622    -7729     
+ Misses       4268      756    -3512     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: RatanKokal <ratanskokal@gmail.com>
…ulator

Replaced O(N) string searches with an instant Look-Up Table and implemented a 32-bit accumulator to process data in a single pass. Eliminated multi-pass string packing, removed helper function overhead (dead code elimination), and pre-allocated memory to prevent expensive reallocations.

Signed-off-by: RatanKokal <ratanskokal@gmail.com>
This commit addresses reviewer feedback regarding memory safety, type portability, and documentation for the pure Fortran implementation.

Key changes:
- API Alignment: Updated base64_encode_into to mirror the decoder API by returning encoded_len and error_flag.
- Memory Safety: Added explicit blank-filling and strict bounds checking to the encoder to prevent silent buffer overflows.
- Branchless Bounds Checking: Implemented an iand(..., 255_int32) mask in the decoder to safely handle non-ASCII codepoints.
- Strict Portability: Enforced int32 type consistency across all bitwise intrinsics and literal masks.
- Documentation: Added FORD headers to the umbrella module.

Signed-off-by: RatanKokal <ratanskokal@gmail.com>
This commit hardens the base64 implementation by addressing standard compliance issues and optimizing the hot paths for the zero-copy API.

Key changes:
* Compliance: Replaced non-conforming 'c_loc' and 'c_f_pointer' usage with 'transfer' and 'select rank' blocks to ensure compatibility with non-C-interoperable types.
* Correctness: Fixed a Unicode aliasing bug in the decoder by implementing a bitwise-OR 'unicode_accum' check to reject non-ASCII characters (>255).
* Performance: Optimized 'base64_encode_into' by moving string blank-filling ('str = ""') off the hot path, preventing unnecessary memory operations during high-throughput encoding.
* API Refinement: Restricted the 'base64_encode_into' power-user API to accept only 'integer(int8)' arrays to guarantee zero-copy performance while remaining standard-compliant.
* Ergonomics: Added an optional 'error_flag' to 'base64_decode' to improve error handling for the allocating API.
* Testing: Expanded unit tests to include coverage for the new subroutine signatures and error states.

Signed-off-by: RatanKokal <ratanskokal@gmail.com>
This commit addresses the architectural and stylistic feedback for the Base64 implementation:

* Architecture: Consolidated interfaces into a single stdlib_base64 parent module and moved the high-performance logic into encode and decode submodules to prevent compilation cascades.
* Standards: Replaced the logical error flag with type(state_type) from stdlib_error for consistent library-wide error handling.
* Optimization: Marked the core _into subroutines as pure to guarantee no side effects and allow for aggressive compiler optimizations.
* Dependency: Imported base64_alphabet directly from stdlib_ascii to reduce redundancy.
* Documentation: Added explanatory comments for the branchless DT and IS_VAL lookup tables.
* Formatting: Expanded semicolon-separated multi-statement lines into single lines to improve debuggability and prevent CI truncation errors.

Signed-off-by: RatanKokal <ratanskokal@gmail.com>
@RatanKokal

Copy link
Copy Markdown
Author

Hey @jvdp1, could you please have a look. I have encorporated all the feedback.

@jvdp1 jvdp1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @RatanKokal . this PR is taking a good shape. Below are a few comments. Could you also add the specs, please?

Comment thread src/core/stdlib_ascii.fypp Outdated
Comment thread src/strings/stdlib_base64.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp
Comment thread src/strings/stdlib_base64_decode.fypp
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated

#:for k1, t1, _, _ in REAL_KINDS_TYPES
module function base64_encode_real_${k1}$(data) result(str)
${t1}$, intent(in), target, contiguous :: data(..)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is target mentioned?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, target is not needed here, please remove.
The target attribute in fortran has a very specific use and it is to signal that a variable will be pointed to.

Comment thread src/strings/stdlib_base64_encode.fypp Outdated

#:for k1, t1, _ in CMPLX_KINDS_TYPES
module function base64_encode_cmplx_${k1}$(data) result(str)
${t1}$, intent(in), target, contiguous :: data(..)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
${t1}$, intent(in), target, contiguous :: data(..)
${t1}$, intent(in), contiguous :: data(..)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

target is a compiler hint, ennsuring maximum memory efficiency by forcing pass-by-reference.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where in the fortran standard does it specify such conclusion?
target has a very specific purpose: signaling the compiler that a variable can be "pointed to" by a pointer variable. Telling the compiler that a variable is pontetially a target, can prevent agressive optimization.

Also, in Fortran, arguments are passed by reference.

Please remove this attribute.

Comment thread src/strings/stdlib_base64_encode.fypp Outdated
module function base64_encode_bytes(bytes) result(str)
integer(int8), intent(in), target, contiguous :: bytes(:)
character(len=:), allocatable, target :: str
integer(c_size_t) :: nbytes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment to explain why nbytes must be of type c_size_t?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this simply requires integer(int64), there is no need to invoke iso_c_binding here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @jalvesz : use integer(int64) instead of c_size_t

Comment thread test/string/test_base64.f90 Outdated
Comment thread test/string/test_base64.f90 Outdated
- use MAXRANK-based rank generation (including rank-0 scalar support)
- align c_bool import with stdlib_kinds and keep iso_c_binding for c_size_t
- derive base64 alphabet from letters and digits constants
- simplify decode despace loop by skipping filtered-out bytes directly
- tidy roundtrip tests: parameterized constants and 132-char-safe line split

Signed-off-by: RatanKokal <ratanskokal@gmail.com>
@RatanKokal
RatanKokal requested a review from jvdp1 April 13, 2026 08:58
Signed-off-by: RatanKokal <ratanskokal@gmail.com>
@RatanKokal

Copy link
Copy Markdown
Author

Hi @jvdp1,
I have implemented most of the changes as per the comments.
Also updated the specs.

Comment thread src/strings/stdlib_base64.fypp Outdated
Comment thread src/strings/stdlib_base64.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated

#:for k1, t1, _ in CMPLX_KINDS_TYPES
module function base64_encode_cmplx_${k1}$(data) result(str)
${t1}$, intent(in), target, contiguous :: data(..)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where in the fortran standard does it specify such conclusion?
target has a very specific purpose: signaling the compiler that a variable can be "pointed to" by a pointer variable. Telling the compiler that a variable is pontetially a target, can prevent agressive optimization.

Also, in Fortran, arguments are passed by reference.

Please remove this attribute.

Comment thread src/strings/stdlib_base64_encode.fypp Outdated
module function base64_encode_bytes(bytes) result(str)
integer(int8), intent(in), target, contiguous :: bytes(:)
character(len=:), allocatable, target :: str
integer(c_size_t) :: nbytes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this simply requires integer(int64), there is no need to invoke iso_c_binding here.

Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated
Comment thread src/strings/stdlib_base64_encode.fypp Outdated
Comment thread src/strings/stdlib_base64.fypp Outdated
Comment thread doc/specs/stdlib_base64.md
Comment thread src/strings/stdlib_base64_encode.fypp Outdated
@14NGiestas 14NGiestas added the topic: strings String processing label May 7, 2026
@14NGiestas 14NGiestas linked an issue May 7, 2026 that may be closed by this pull request
- Aligned `fypp` preprocessor macros to match their respective inner scopes.
- Removed redundant `target` attributes from dummy arguments.
- Vectorized decoding routines using a `chunk_size` parameter and array constructors.
- Simplified `iachar` intrinsic calls by utilizing the `kind` argument.
- Replaced `c_size_t` with `int64` for byte tracking and added explanatory documentation.
- Renamed `base64_alphabet` to `base64_dictionary` for improved clarity.
- Converted documentation snippets into executable examples and integrated them into the CMake build system.
@RatanKokal
RatanKokal requested review from jalvesz and jvdp1 July 13, 2026 05:31
@RatanKokal

Copy link
Copy Markdown
Author

@jvdp1 @jalvesz I have incorporated the feedback/changes requested. Requesting you to please have a look

Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
slen = len(str)
if (mod(slen, 4) /= 0) then
err_state = state_type("base64_decode_into", STDLIB_VALUE_ERROR, &
"Input length must be a multiple of 4")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Input length must be a multiple of 4")
"Input length must be a multiple of "//to_string(chunk_size))

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, to_string cannot be used here because base64_decode_into must remain a pure subroutine, and calling an impure function results in a compilation error. To remove the hardcoded number while preserving the procedure's purity, I defined an FYPP macro (#:set ENC_CHUNK = 4) and injected it directly into the string at compile time.

Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
Comment thread src/strings/stdlib_base64_decode.fypp Outdated
@RatanKokal

Copy link
Copy Markdown
Author

@jalvesz I have used enc_chunk = 4 and raw_chunk = 3 now, 3 bytes of original data gets encoded as 4 bytes. This would give a even more clear picture in my opinion. Requesting you to please have a look.

@RatanKokal

Copy link
Copy Markdown
Author

@jalvesz I have introduced two variables for chunk size, raw chunk and enc chunk which is 3 and 4 respectively since base64 converts 3 bytes of normal text in 4 bytes of encoded text

@jalvesz

jalvesz commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

@RatanKokal is there a reason for converting the size parameters to fypp parameters? This looks like an overkill complexity.

@RatanKokal

Copy link
Copy Markdown
Author

@RatanKokal is there a reason for converting the size parameters to fypp parameters? This looks like an overkill complexity.

I get error in "Input length must be a multiple of "//to_string(chunk_size)) if not done this way. to_string cannot be used here because base64_decode_into must remain a pure subroutine, and calling an impure function results in a compilation error.

@jalvesz

jalvesz commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

pure module function to_string_${t1[0]}$_${k1}$(value, format) result(string)

The procedure to_string is pure. I think the error you got was simply that the module containing it was not used

@RatanKokal

Copy link
Copy Markdown
Author

@jalvesz Thanks for the correction. Made the changes and it does work now.

@jvdp1 jvdp1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you @RatanKokal . Overall it looks good to me. Here are some suggestions

Comment thread doc/specs/stdlib_base64.md Outdated
Comment on lines +39 to +40
`data`: shall be a contiguous array of an intrinsic type (`real`, `integer`,
`complex`, `logical`, or `integer(int8)`). It is an `intent(in)` argument.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

integer is mentioned twice. Does it mean that all kinds of integer are supported? (and what about other types?)
Maybe:

Suggested change
`data`: shall be a contiguous array of an intrinsic type (`real`, `integer`,
`complex`, `logical`, or `integer(int8)`). It is an `intent(in)` argument.
`data`: shall be a contiguous array of an intrinsic type (`real`, `integer`,
`complex`, `logical`) of any kind. It is an `intent(in)` argument.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the docs to make it clear. Yeah everything is supported.

Comment thread doc/specs/stdlib_base64.md Outdated
Encodes bytes into a caller-provided output buffer.

This is the preallocated API for throughput-sensitive workflows. It does not
allocate and reports status through `err_state`. On success,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence is unclear. Does it or not report status?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it clear, it reports status

Comment thread doc/specs/stdlib_base64.md Outdated
`bytes`: shall be a contiguous array of type `integer(int8)`. It is an
`intent(in)` argument.

`str`: shall be an intrinsic character type. It is an `intent(out)` argument.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it allocatable?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No

Comment thread src/strings/stdlib_base64.fypp Outdated

module stdlib_base64
use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64, lk, c_bool
use stdlib_ascii, only: base64_dictionary => base64_alphabet

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you rename it? For readability, I suggest to avoid renaming variables, unless it improves readability, or it avoids issues likes name conflicts.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was requested to have a more explicit name like dictionary, and I wanted to have some resemblance with the original RFQ. I have updated this in my latest commit to use base64_dictionary everywhere.

!> Encodes bytes into a caller-provided output buffer.
!>
!> This is the preallocated API for throughput-sensitive workflows.
!> It does not allocate and reports status through `err_state`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
!> It does not allocate and reports status through `err_state`.
!> It does not allocate `str` and reports status through `err_state`.

or

Suggested change
!> It does not allocate and reports status through `err_state`.
!> `str` must be of a defined length. It reports status through `err_state`.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made these lines more clear

Comment on lines +57 to +67
allocate(filtered(len(str)))
j = 0
do i = 1, len(str)
raw_c = iachar(str(i:i), kind=int32)
unicode_accum = ior(unicode_accum, raw_c)
c = iand(raw_c, 255_int32)
if (IS_VAL(c) == 0) cycle
j = j + 1
filtered(j) = int(c, int8)
end do
slen = j

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some entries of filtered might be undefined due to cycle. I suggest to mention it in the specs.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added comment in the code, since filtered is dev facing

Comment on lines +97 to +99
v = int(DT(iand(raw_c4, 255_int32)), int32)
else
v = int(DT(iand(int(filtered(i:i+enc_chunk-1), int32), 255_int32)), int32)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DT (declared as integer(int8)) seems to be always converted to int32. For readability and efficiency, I suggest to declared DT as integer(int32)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

Comment thread src/strings/stdlib_base64_encode.fypp Outdated
Comment on lines +7 to +8
integer, parameter :: enc_chunk = 4
integer, parameter :: raw_chunk = 3

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these variables are declared in both modules, I suggest to define them only once in the parent module.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, done

Comment thread test/string/test_base64.f90 Outdated
Comment on lines +31 to +42
call check(error, base64_encode([int(77, int8), int(97, int8), int(110, int8)]) == "TWFu")
if (allocated(error)) return
call check(error, base64_encode([int(77, int8), int(97, int8)]) == "TWE=")
if (allocated(error)) return
call check(error, base64_encode([int(77, int8)]) == "TQ==")
if (allocated(error)) return

call check(error, base64_decode("TWFu") == "Man")
if (allocated(error)) return
call check(error, base64_decode("TWE=") == "Ma")
if (allocated(error)) return
call check(error, base64_decode("TQ==") == "M")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add some message in check. It will be helpful to identify which check is failing, in case one of them will fail. Currenty, the developer won't be able to identify it without additional work.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

Comment thread test/string/test_base64.f90 Outdated
integer(int32) :: vals(4), got(4)
character(len=:), allocatable :: enc, dec

vals = [1_int32, -2_int32, 1024_int32, -4096_int32]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could it be declared asparameter?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes done

- Rename base64_alphabet to base64_dictionary
- Move chunk parameters to parent module
- Optimize DT lookup table to int32
- Improve test error messages and docstrings
@RatanKokal

Copy link
Copy Markdown
Author

@jvdp1 Thanks for the feedback. I have incorporated all of that in my latest commit. Requesting you to have a look.
Thanks.

@RatanKokal
RatanKokal requested a review from jvdp1 July 20, 2026 14:01
@RatanKokal

Copy link
Copy Markdown
Author

@jalvesz Are there any more suggestions, or are we good to go with this one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic: strings String processing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

base64

5 participants