Преглед изворни кода

encoding/base32: Use consistent allocator and add proper cleanup

Fix memory handling throughout base32 package:
- Make padding map package-level constant (to avoid repeated allocs)
- Use passed allocator in encode's make() call
- Add defer delete for allocated memory in encode
- Add proper cleanup in test cases
- Fix memory cleanup of output buffers

The changes ensure consistent allocator usage and cleanup in both
implementation and tests.
Zoltán Kéri пре 10 месеци
родитељ
комит
93238db202
1 измењених фајлова са 43 додато и 22 уклоњено
  1. 43 22
      core/encoding/base32/base32.odin

+ 43 - 22
core/encoding/base32/base32.odin

@@ -45,11 +45,19 @@ DEC_TABLE := [?]u8 {
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 }
 }
 
 
+REQUIRED_PADDING := map[int]int{
+	2 = 6, // 2 chars need 6 padding chars
+	4 = 4, // 4 chars need 4 padding chars
+	5 = 3, // 5 chars need 3 padding chars
+	7 = 1, // 7 chars need 1 padding char
+}
+
 encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
 encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
 	out_length := (len(data) + 4) / 5 * 8
 	out_length := (len(data) + 4) / 5 * 8
-	out := make([]byte, out_length)
+	out := make([]byte, out_length, allocator)
+	defer delete(out)
 	_encode(out, data)
 	_encode(out, data)
-	return string(out)
+	return string(out[:])
 }
 }
 
 
 @private
 @private
@@ -143,22 +151,13 @@ decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocato
 			}
 			}
 		}
 		}
 
 
-		// Required padding for each content length mod 8
 		content_len := data_len - padding_count
 		content_len := data_len - padding_count
-		required_padding := map[int]int{
-			2 = 6, // 2 chars need 6 padding chars
-			4 = 4, // 4 chars need 4 padding chars
-			5 = 3, // 5 chars need 3 padding chars
-			7 = 1, // 7 chars need 1 padding char
-		}
-
 		mod8 := content_len % 8
 		mod8 := content_len % 8
-		if req_pad, ok := required_padding[mod8]; ok {
+		if req_pad, ok := REQUIRED_PADDING[mod8]; ok {
 			if padding_count != req_pad {
 			if padding_count != req_pad {
 				return nil, .Malformed_Input
 				return nil, .Malformed_Input
 			}
 			}
 		} else if mod8 != 0 {
 		} else if mod8 != 0 {
-			// If not in the map and not a multiple of 8, it's invalid
 			return nil, .Malformed_Input
 			return nil, .Malformed_Input
 		}
 		}
 	} else {
 	} else {
@@ -208,7 +207,7 @@ decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocato
 		outi += bytes_to_write
 		outi += bytes_to_write
 	}
 	}
 
 
-	return out, .None
+	return
 }
 }
 
 
 @(test)
 @(test)
@@ -226,12 +225,13 @@ test_base32_decode_valid :: proc(t: ^testing.T) {
 		{"MZXW6YTBOI======", "foobar"},
 		{"MZXW6YTBOI======", "foobar"},
 	}
 	}
 
 
-
 	for c in cases {
 	for c in cases {
 		output, err := decode(c.input)
 		output, err := decode(c.input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.None)
 		testing.expect_value(t, err, Error.None)
 		expected := transmute([]u8)c.expected
 		expected := transmute([]u8)c.expected
-
 		if output != nil {
 		if output != nil {
 			testing.expect(t, bytes.equal(output, expected))
 			testing.expect(t, bytes.equal(output, expected))
 		} else {
 		} else {
@@ -267,13 +267,19 @@ test_base32_decode_invalid :: proc(t: ^testing.T) {
 	{
 	{
 		// Characters outside alphabet
 		// Characters outside alphabet
 		input := "MZ1W6YTB" // '1' not in alphabet (A-Z, 2-7)
 		input := "MZ1W6YTB" // '1' not in alphabet (A-Z, 2-7)
-		_, err := decode(input)
+		output, err := decode(input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.Invalid_Character)
 		testing.expect_value(t, err, Error.Invalid_Character)
 	}
 	}
 	{
 	{
 		// Lowercase not allowed
 		// Lowercase not allowed
 		input := "mzxq===="
 		input := "mzxq===="
-		_, err := decode(input)
+		output, err := decode(input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.Invalid_Character)
 		testing.expect_value(t, err, Error.Invalid_Character)
 	}
 	}
 
 
@@ -281,25 +287,37 @@ test_base32_decode_invalid :: proc(t: ^testing.T) {
 	{
 	{
 		// Padding must only be at end
 		// Padding must only be at end
 		input := "MZ=Q===="
 		input := "MZ=Q===="
-		_, err := decode(input)
+		output, err := decode(input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.Malformed_Input)
 		testing.expect_value(t, err, Error.Malformed_Input)
 	}
 	}
 	{
 	{
 		// Missing padding
 		// Missing padding
 		input := "MZXQ" // Should be MZXQ====
 		input := "MZXQ" // Should be MZXQ====
-		_, err := decode(input)
+		output, err := decode(input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.Malformed_Input)
 		testing.expect_value(t, err, Error.Malformed_Input)
 	}
 	}
 	{
 	{
 		// Incorrect padding length
 		// Incorrect padding length
 		input := "MZXQ=" // Needs 4 padding chars
 		input := "MZXQ=" // Needs 4 padding chars
-		_, err := decode(input)
+		output, err := decode(input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.Malformed_Input)
 		testing.expect_value(t, err, Error.Malformed_Input)
 	}
 	}
 	{
 	{
 		// Too much padding
 		// Too much padding
 		input := "MY=========" // Extra padding chars
 		input := "MY=========" // Extra padding chars
-		_, err := decode(input)
+		output, err := decode(input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.Malformed_Input)
 		testing.expect_value(t, err, Error.Malformed_Input)
 	}
 	}
 
 
@@ -307,7 +325,10 @@ test_base32_decode_invalid :: proc(t: ^testing.T) {
 	{
 	{
 		// Single character (invalid block)
 		// Single character (invalid block)
 		input := "M"
 		input := "M"
-		_, err := decode(input)
+		output, err := decode(input)
+		if output != nil {
+			defer delete(output)
+		}
 		testing.expect_value(t, err, Error.Invalid_Length)
 		testing.expect_value(t, err, Error.Invalid_Length)
 	}
 	}
 }
 }