Change CBC_OneDimWriter::Encode() to return DataVector.

Return a vector instead of having a raw pointer that is caller owned
plus a separate size out-parameter.

Bug: pdfium:1872
Change-Id: Ibf3bf8d28fba7519feedede419d4b9557cd6c997
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/100914
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fxbarcode/cbc_codabar.cpp b/fxbarcode/cbc_codabar.cpp
index 71061cb..cb4b875 100644
--- a/fxbarcode/cbc_codabar.cpp
+++ b/fxbarcode/cbc_codabar.cpp
@@ -24,7 +24,6 @@
 #include <memory>
 
 #include "core/fxcrt/fx_coordinates.h"
-#include "core/fxcrt/fx_memory_wrappers.h"
 #include "fxbarcode/oned/BC_OnedCodaBarWriter.h"
 
 CBC_Codabar::CBC_Codabar()
@@ -37,13 +36,10 @@
   if (!pWriter->CheckContentValidity(contents))
     return false;
 
-  int32_t outWidth = 0;
   m_renderContents = pWriter->FilterContents(contents);
   ByteString byteString = m_renderContents.ToUTF8();
-  std::unique_ptr<uint8_t, FxFreeDeleter> data(
-      pWriter->Encode(byteString, outWidth));
   return pWriter->RenderResult(m_renderContents.AsStringView(),
-                               pdfium::make_span(data.get(), outWidth));
+                               pWriter->Encode(byteString));
 }
 
 bool CBC_Codabar::RenderDevice(CFX_RenderDevice* device,
diff --git a/fxbarcode/cbc_code128.cpp b/fxbarcode/cbc_code128.cpp
index 4dfc232..8b2b65d 100644
--- a/fxbarcode/cbc_code128.cpp
+++ b/fxbarcode/cbc_code128.cpp
@@ -24,7 +24,6 @@
 #include <memory>
 
 #include "core/fxcrt/fx_coordinates.h"
-#include "core/fxcrt/fx_memory_wrappers.h"
 #include "fxbarcode/oned/BC_OnedCode128Writer.h"
 
 CBC_Code128::CBC_Code128(BC_TYPE type)
@@ -37,17 +36,14 @@
   if (!pWriter->CheckContentValidity(contents))
     return false;
 
-  int32_t outWidth = 0;
   WideString content(contents);
   if (contents.GetLength() % 2 && pWriter->GetType() == BC_TYPE::kCode128C)
     content += '0';
 
   m_renderContents = pWriter->FilterContents(content.AsStringView());
   ByteString byteString = m_renderContents.ToUTF8();
-  std::unique_ptr<uint8_t, FxFreeDeleter> data(
-      pWriter->Encode(byteString, outWidth));
   return pWriter->RenderResult(m_renderContents.AsStringView(),
-                               pdfium::make_span(data.get(), outWidth));
+                               pWriter->Encode(byteString));
 }
 
 bool CBC_Code128::RenderDevice(CFX_RenderDevice* device,
diff --git a/fxbarcode/cbc_code39.cpp b/fxbarcode/cbc_code39.cpp
index b3bbdc3..229048e 100644
--- a/fxbarcode/cbc_code39.cpp
+++ b/fxbarcode/cbc_code39.cpp
@@ -24,7 +24,6 @@
 #include <memory>
 
 #include "core/fxcrt/fx_coordinates.h"
-#include "core/fxcrt/fx_memory_wrappers.h"
 #include "fxbarcode/oned/BC_OnedCode39Writer.h"
 
 CBC_Code39::CBC_Code39()
@@ -37,14 +36,11 @@
   if (!pWriter->CheckContentValidity(contents))
     return false;
 
-  int32_t outWidth = 0;
   WideString filtercontents = pWriter->FilterContents(contents);
   m_renderContents = pWriter->RenderTextContents(contents);
   ByteString byteString = filtercontents.ToUTF8();
-  std::unique_ptr<uint8_t, FxFreeDeleter> data(
-      pWriter->Encode(byteString, outWidth));
   return pWriter->RenderResult(m_renderContents.AsStringView(),
-                               pdfium::make_span(data.get(), outWidth));
+                               pWriter->Encode(byteString));
 }
 
 bool CBC_Code39::RenderDevice(CFX_RenderDevice* device,
diff --git a/fxbarcode/cbc_eancode.cpp b/fxbarcode/cbc_eancode.cpp
index ba4ad01..261b753 100644
--- a/fxbarcode/cbc_eancode.cpp
+++ b/fxbarcode/cbc_eancode.cpp
@@ -8,7 +8,6 @@
 
 #include <utility>
 
-#include "core/fxcrt/fx_memory_wrappers.h"
 #include "fxbarcode/BC_Library.h"
 #include "fxbarcode/oned/BC_OnedEANWriter.h"
 
@@ -26,13 +25,11 @@
   if (!pWriter->CheckContentValidity(contents))
     return false;
 
-  int32_t out_width = 0;
   m_renderContents = Preprocess(contents);
   ByteString str = m_renderContents.ToUTF8();
   pWriter->InitEANWriter();
-  std::unique_ptr<uint8_t, FxFreeDeleter> data(pWriter->Encode(str, out_width));
   return pWriter->RenderResult(m_renderContents.AsStringView(),
-                               pdfium::make_span(data.get(), out_width));
+                               pWriter->Encode(str));
 }
 
 bool CBC_EANCode::RenderDevice(CFX_RenderDevice* device,
diff --git a/fxbarcode/oned/BC_OneDimWriter.h b/fxbarcode/oned/BC_OneDimWriter.h
index 1d9ed70..a990dd9 100644
--- a/fxbarcode/oned/BC_OneDimWriter.h
+++ b/fxbarcode/oned/BC_OneDimWriter.h
@@ -12,6 +12,7 @@
 
 #include <vector>
 
+#include "core/fxcrt/data_vector.h"
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/unowned_ptr.h"
 #include "core/fxge/cfx_textrenderoptions.h"
@@ -47,7 +48,7 @@
   void SetFontStyle(int32_t style);
   void SetFontColor(FX_ARGB color);
 
-  virtual uint8_t* Encode(const ByteString& contents, int32_t& outLength) = 0;
+  virtual DataVector<uint8_t> Encode(const ByteString& contents) = 0;
   bool RenderDeviceResult(CFX_RenderDevice* device,
                           const CFX_Matrix& matrix,
                           WideStringView contents);
diff --git a/fxbarcode/oned/BC_OnedCodaBarWriter.cpp b/fxbarcode/oned/BC_OnedCodaBarWriter.cpp
index 3294ae6..864e20a 100644
--- a/fxbarcode/oned/BC_OnedCodaBarWriter.cpp
+++ b/fxbarcode/oned/BC_OnedCodaBarWriter.cpp
@@ -120,11 +120,11 @@
   return filtercontents;
 }
 
-uint8_t* CBC_OnedCodaBarWriter::Encode(const ByteString& contents,
-                                       int32_t& outLength) {
+DataVector<uint8_t> CBC_OnedCodaBarWriter::Encode(const ByteString& contents) {
   ByteString data = m_chStart + contents + m_chEnd;
   m_iContentLen = data.GetLength();
-  uint8_t* result = FX_Alloc2D(uint8_t, m_iWideNarrRatio * 7, data.GetLength());
+  DataVector<uint8_t> result(
+      Fx2DSizeOrDie(m_iWideNarrRatio * 7, data.GetLength()));
   char ch;
   int32_t position = 0;
   for (size_t index = 0; index < data.GetLength(); index++) {
@@ -171,7 +171,7 @@
       position++;
     }
   }
-  outLength = position;
+  result.resize(position);
   return result;
 }
 
diff --git a/fxbarcode/oned/BC_OnedCodaBarWriter.h b/fxbarcode/oned/BC_OnedCodaBarWriter.h
index dd7658f..32d2f59 100644
--- a/fxbarcode/oned/BC_OnedCodaBarWriter.h
+++ b/fxbarcode/oned/BC_OnedCodaBarWriter.h
@@ -19,7 +19,7 @@
   ~CBC_OnedCodaBarWriter() override;
 
   // CBC_OneDimWriter:
-  uint8_t* Encode(const ByteString& contents, int32_t& outLength) override;
+  DataVector<uint8_t> Encode(const ByteString& contents) override;
   bool RenderResult(WideStringView contents,
                     pdfium::span<const uint8_t> code) override;
   bool CheckContentValidity(WideStringView contents) override;
diff --git a/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp b/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp
index add28cf..1f7744b 100644
--- a/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedCodaBarWriter_unittest.cpp
@@ -4,52 +4,36 @@
 
 #include "fxbarcode/oned/BC_OnedCodaBarWriter.h"
 
-#include "core/fxcrt/fx_memory.h"
+#include <string.h>
+
+#include "core/fxcrt/data_vector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-// 3 wide and 4 narrow modules per delimiter. One space between them.
-constexpr int kModulesForDelimiters = (3 * 2 + 4) * 2 + 1;
-
-// 2 wide and 5 narrow modules per number, '_' or '$'. 1 space between chars.
-constexpr int kModulesPerNumber = 2 * 2 + 5 + 1;
-
-// 3 wide and 4 narrow modules per number, '_' or '$'. 1 space between chars.
-constexpr int kModulesPerPunctuation = 3 * 2 + 4 + 1;
-
 TEST(OnedCodaBarWriterTest, Encode) {
   CBC_OnedCodaBarWriter writer;
-  int32_t width;
 
-  uint8_t* encoded = writer.Encode("", width);
-  EXPECT_EQ(kModulesForDelimiters, width);
-  const char* expected =
+  static const char kExpected1[] =
       "# ##  #  # "  // A Start
       "#  #  # ##";  // B End
-  for (size_t i = 0; i < strlen(expected); i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("");
+  ASSERT_EQ(strlen(kExpected1), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected1); i++)
+    EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("123", width);
-  EXPECT_EQ(kModulesForDelimiters + 3 * kModulesPerNumber, width);
-  expected =
+  static const char kExpected2[] =
       "# ##  #  # "  // A Start
       "# # ##  # "   // 1
       "# #  # ## "   // 2
       "##  # # # "   // 3
       "#  #  # ##";  // B End
-  for (size_t i = 0; i < strlen(expected); i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  encoded = writer.Encode("123");
+  ASSERT_EQ(strlen(kExpected2), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected2); i++)
+    EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("-$./:+", width);
-  EXPECT_EQ(kModulesForDelimiters + 2 * kModulesPerNumber +
-                4 * kModulesPerPunctuation,
-            width);
-  expected =
+  static const char kExpected3[] =
       "# ##  #  # "  // A Start
       "# #  ## # "   // -
       "# ##  # # "   // $
@@ -58,16 +42,12 @@
       "## # ## ## "  // :
       "# ## ## ## "  // +
       "#  #  # ##";  // B End
-  for (size_t i = 0; i < strlen(expected); i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  encoded = writer.Encode("-$./:+");
+  ASSERT_EQ(strlen(kExpected3), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected3); i++)
+    EXPECT_EQ(kExpected3[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("456.987987987/001", width);
-  EXPECT_EQ(kModulesForDelimiters + 15 * kModulesPerNumber +
-                2 * kModulesPerPunctuation,
-            width);
-  expected =
+  static const char kExpected4[] =
       "# ##  #  # "  // A Start
       "# ## #  # "   // 4
       "## # #  # "   // 5
@@ -87,15 +67,14 @@
       "# # #  ## "   // 0
       "# # ##  # "   // 1
       "#  #  # ##";  // B End
-  for (size_t i = 0; i < strlen(expected); i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  encoded = writer.Encode("456.987987987/001");
+  ASSERT_EQ(strlen(kExpected4), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected4); i++)
+    EXPECT_EQ(kExpected4[i] != ' ', !!encoded[i]) << i;
 }
 
 TEST(OnedCodaBarWriterTest, SetDelimiters) {
   CBC_OnedCodaBarWriter writer;
-  int32_t width;
 
   EXPECT_TRUE(writer.SetStartChar('A'));
   EXPECT_TRUE(writer.SetStartChar('B'));
@@ -126,18 +105,16 @@
   writer.SetStartChar('N');
   writer.SetEndChar('*');
 
-  uint8_t* encoded = writer.Encode("987", width);
-  EXPECT_EQ(kModulesForDelimiters + 3 * kModulesPerNumber, width);
-  const char* expected =
+  static const char kExpected[] =
       "#  #  # ## "  // N (same as B) Start
       "## #  # # "   // 9
       "#  ## # # "   // 8
       "#  # ## # "   // 7
       "# #  #  ##";  // * (same as C) End
-  for (size_t i = 0; i < strlen(expected); i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("987");
+  ASSERT_EQ(strlen(kExpected), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected); i++)
+    EXPECT_EQ(kExpected[i] != ' ', !!encoded[i]) << i;
 }
 
 }  // namespace
diff --git a/fxbarcode/oned/BC_OnedCode128Writer.cpp b/fxbarcode/oned/BC_OnedCode128Writer.cpp
index 5c2a7b8..8d9d96e 100644
--- a/fxbarcode/oned/BC_OnedCode128Writer.cpp
+++ b/fxbarcode/oned/BC_OnedCode128Writer.cpp
@@ -118,10 +118,9 @@
   m_locTextLoc = location;
 }
 
-uint8_t* CBC_OnedCode128Writer::Encode(const ByteString& contents,
-                                       int32_t& outLength) {
+DataVector<uint8_t> CBC_OnedCode128Writer::Encode(const ByteString& contents) {
   if (contents.GetLength() < 1 || contents.GetLength() > 80)
-    return nullptr;
+    return DataVector<uint8_t>();
 
   std::vector<int32_t> patterns;
   int32_t checkSum = 0;
@@ -140,14 +139,13 @@
     for (size_t i = 0; i < kPatternSize; ++i)
       codeWidth += pattern[i];
   }
-  outLength = codeWidth;
-  std::unique_ptr<uint8_t, FxFreeDeleter> result(FX_Alloc(uint8_t, outLength));
+  DataVector<uint8_t> result(codeWidth);
   int32_t pos = 0;
   for (size_t i = 0; i < patterns.size(); ++i) {
     const int8_t* pattern = CODE_PATTERNS[patterns[i]];
-    pos += AppendPattern(result.get(), pos, pattern, kPatternSize, true);
+    pos += AppendPattern(result.data(), pos, pattern, kPatternSize, true);
   }
-  return result.release();
+  return result;
 }
 
 // static
diff --git a/fxbarcode/oned/BC_OnedCode128Writer.h b/fxbarcode/oned/BC_OnedCode128Writer.h
index 62e2ad6..121c02b 100644
--- a/fxbarcode/oned/BC_OnedCode128Writer.h
+++ b/fxbarcode/oned/BC_OnedCode128Writer.h
@@ -27,7 +27,7 @@
                             std::vector<int32_t>* patterns);
 
   // CBC_OneDimWriter
-  uint8_t* Encode(const ByteString& contents, int32_t& outLength) override;
+  DataVector<uint8_t> Encode(const ByteString& contents) override;
   bool CheckContentValidity(WideStringView contents) override;
   WideString FilterContents(WideStringView contents) override;
   void SetTextLocation(BC_TEXT_LOC location) override;
diff --git a/fxbarcode/oned/BC_OnedCode39Writer.cpp b/fxbarcode/oned/BC_OnedCode39Writer.cpp
index b674e0c..fee37ba 100644
--- a/fxbarcode/oned/BC_OnedCode39Writer.cpp
+++ b/fxbarcode/oned/BC_OnedCode39Writer.cpp
@@ -145,11 +145,10 @@
   return kOnedCode39Checksum[checksum % std::size(kOnedCode39Checksum)];
 }
 
-uint8_t* CBC_OnedCode39Writer::Encode(const ByteString& contents,
-                                      int32_t& outlength) {
+DataVector<uint8_t> CBC_OnedCode39Writer::Encode(const ByteString& contents) {
   char checksum = CalcCheckSum(contents);
   if (checksum == '*')
-    return nullptr;
+    return DataVector<uint8_t>();
 
   int8_t widths[9] = {0};
   int32_t wideStrideNum = 3;
@@ -170,13 +169,12 @@
         codeWidth += widths[k];
     }
   }
-  outlength = codeWidth;
-  std::unique_ptr<uint8_t, FxFreeDeleter> result(FX_Alloc(uint8_t, codeWidth));
+  DataVector<uint8_t> result(codeWidth);
   ToIntArray(kOnedCode39CharacterEncoding[39], widths);
-  int32_t pos = AppendPattern(result.get(), 0, widths, 9, true);
+  int32_t pos = AppendPattern(result.data(), 0, widths, 9, true);
 
   int8_t narrowWhite[] = {1};
-  pos += AppendPattern(result.get(), pos, narrowWhite, 1, false);
+  pos += AppendPattern(result.data(), pos, narrowWhite, 1, false);
 
   for (int32_t l = m_iContentLen - 1; l >= 0; l--) {
     for (size_t i = 0; i < kOnedCode39AlphabetLen; i++) {
@@ -184,20 +182,19 @@
         continue;
 
       ToIntArray(kOnedCode39CharacterEncoding[i], widths);
-      pos += AppendPattern(result.get(), pos, widths, 9, true);
+      pos += AppendPattern(result.data(), pos, widths, 9, true);
     }
-    pos += AppendPattern(result.get(), pos, narrowWhite, 1, false);
+    pos += AppendPattern(result.data(), pos, narrowWhite, 1, false);
   }
   ToIntArray(kOnedCode39CharacterEncoding[39], widths);
-  pos += AppendPattern(result.get(), pos, widths, 9, true);
+  pos += AppendPattern(result.data(), pos, widths, 9, true);
 
-  auto* result_ptr = result.get();
   for (int32_t i = 0; i < codeWidth / 2; i++) {
-    result_ptr[i] ^= result_ptr[codeWidth - 1 - i];
-    result_ptr[codeWidth - 1 - i] ^= result_ptr[i];
-    result_ptr[i] ^= result_ptr[codeWidth - 1 - i];
+    result[i] ^= result[codeWidth - 1 - i];
+    result[codeWidth - 1 - i] ^= result[i];
+    result[i] ^= result[codeWidth - 1 - i];
   }
-  return result.release();
+  return result;
 }
 
 bool CBC_OnedCode39Writer::encodedContents(WideStringView contents,
diff --git a/fxbarcode/oned/BC_OnedCode39Writer.h b/fxbarcode/oned/BC_OnedCode39Writer.h
index 0dd99aa..98055c7 100644
--- a/fxbarcode/oned/BC_OnedCode39Writer.h
+++ b/fxbarcode/oned/BC_OnedCode39Writer.h
@@ -16,7 +16,7 @@
   ~CBC_OnedCode39Writer() override;
 
   // CBC_OneDimWriter
-  uint8_t* Encode(const ByteString& contents, int32_t& outLength) override;
+  DataVector<uint8_t> Encode(const ByteString& contents) override;
   bool RenderResult(WideStringView contents,
                     pdfium::span<const uint8_t> code) override;
   bool CheckContentValidity(WideStringView contents) override;
diff --git a/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp b/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp
index 6f1efbb..b0645f4 100644
--- a/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedCode39Writer_unittest.cpp
@@ -6,20 +6,11 @@
 
 #include <string.h>
 
-#include "core/fxcrt/fx_memory.h"
+#include "core/fxcrt/data_vector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-// 3 wide and 6 narrow modules per char. 1 space between chars.
-constexpr int MODULES_PER_CHAR = 3 * 3 + 6 + 1;
-
-// '*' is added as the first and last char.
-const int DELIMITER_CHARS = 2;
-
-// Last char may serve as checksum.
-const int CHECKSUM_CHARS = 1;
-
 TEST(OnedCode39WriterTest, SetWideNarrowRatio) {
   // Code 39 barcodes encode strings of any size into modules in a
   // unidimensional disposition.
@@ -36,12 +27,7 @@
 
   writer.SetWideNarrowRatio(3);
 
-  int32_t width;
-  uint8_t* encoded;
-  const char* expected;
-
-  encoded = writer.Encode("PDFIUM", width);
-  expected =
+  static const char kExpected1[] =
       "#   # ### ### # "  // * Start
       "# ### ### #   # "  // P
       "# # ###   # ### "  // D
@@ -50,14 +36,14 @@
       "###   # # # ### "  // U
       "### ### # #   # "  // M
       "#   # ### ### #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("PDFIUM");
+  ASSERT_EQ(strlen(kExpected1), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected1); i++)
+    EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i]) << i;
 
   writer.SetWideNarrowRatio(2);
 
-  encoded = writer.Encode("PDFIUM", width);
-  expected =
+  static const char kExpected2[] =
       "#  # ## ## # "  // * Start
       "# ## ## #  # "  // P
       "# # ##  # ## "  // D
@@ -66,41 +52,35 @@
       "##  # # # ## "  // U
       "## ## # #  # "  // M
       "#  # ## ## #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  encoded = writer.Encode("PDFIUM");
+  ASSERT_EQ(strlen(kExpected2), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected2); i++)
+    EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i]) << i;
 }
 
 TEST(OnedCode39WriterTest, Encode) {
   CBC_OnedCode39Writer writer;
-  int32_t width;
-  uint8_t* encoded;
-  const char* expected;
 
-  encoded = writer.Encode("", width);
-  EXPECT_EQ((0 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width);
-  expected =
+  static const char kExpected1[] =
       "#   # ### ### # "  // * Start
       "#   # ### ### #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("");
+  ASSERT_EQ(strlen(kExpected1), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected1); i++)
+    EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("123", width);
-  EXPECT_EQ((3 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width);
-  expected =
+  static const char kExpected2[] =
       "#   # ### ### # "  // * Start
       "### #   # # ### "  // 1
       "# ###   # # ### "  // 2
       "### ###   # # # "  // 3
       "#   # ### ### #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  encoded = writer.Encode("123");
+  ASSERT_EQ(strlen(kExpected2), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected2); i++)
+    EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("PDFIUM", width);
-  EXPECT_EQ((6 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width);
-  expected =
+  static const char kExpected3[] =
       "#   # ### ### # "  // * Start
       "# ### ### #   # "  // P
       "# # ###   # ### "  // D
@@ -109,13 +89,12 @@
       "###   # # # ### "  // U
       "### ### # #   # "  // M
       "#   # ### ### #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  encoded = writer.Encode("PDFIUM");
+  ASSERT_EQ(strlen(kExpected3), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected3); i++)
+    EXPECT_EQ(kExpected3[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("A -$%./+Z", width);
-  EXPECT_EQ((9 + DELIMITER_CHARS) * MODULES_PER_CHAR - 1, width);
-  expected =
+  static const char kExpected4[] =
       "#   # ### ### # "  // * Start
       "### # #   # ### "  // A
       "#   ### # ### # "  // Space
@@ -127,37 +106,29 @@
       "#   # #   #   # "  // +
       "#   ### ### # # "  // Z
       "#   # ### ### #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  encoded = writer.Encode("A -$%./+Z");
+  ASSERT_EQ(strlen(kExpected4), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected4); i++)
+    EXPECT_EQ(kExpected4[i] != ' ', !!encoded[i]) << i;
 }
 
 TEST(OnedCode39WriterTest, Checksum) {
   CBC_OnedCode39Writer writer;
-  int32_t width;
-  uint8_t* encoded;
-  const char* expected;
-
   writer.SetCalcChecksum(true);
 
-  encoded = writer.Encode("123", width);
-  EXPECT_EQ((3 + CHECKSUM_CHARS + DELIMITER_CHARS) * MODULES_PER_CHAR - 1,
-            width);
-  expected =
+  static const char kExpected1[] =
       "#   # ### ### # "  // * Start
       "### #   # # ### "  // 1 (1)
       "# ###   # # ### "  // 2 (2)
       "### ###   # # # "  // 3 (3)
       "# ###   ### # # "  // 6 (6 = (1 + 2 + 3) % 43)
       "#   # ### ### #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("123");
+  ASSERT_EQ(strlen(kExpected1), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected1); i++)
+    EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("PDFIUM", width);
-  EXPECT_EQ((6 + CHECKSUM_CHARS + DELIMITER_CHARS) * MODULES_PER_CHAR - 1,
-            width);
-  expected =
+  static const char kExpected2[] =
       "#   # ### ### # "  // * Start
       "# ### ### #   # "  // P (25)
       "# # ###   # ### "  // D (13)
@@ -167,9 +138,10 @@
       "### ### # #   # "  // M (22)
       "###   # # ### # "  // . (37 = (25 + 13 + 15 + 18 + 30 + 22) % 43)
       "#   # ### ### #";  // * End
-  for (size_t i = 0; i < strlen(expected); i++)
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  FX_Free(encoded);
+  encoded = writer.Encode("PDFIUM");
+  ASSERT_EQ(strlen(kExpected2), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected2); i++)
+    EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i]) << i;
 }
 
 }  // namespace
diff --git a/fxbarcode/oned/BC_OnedEAN13Writer.cpp b/fxbarcode/oned/BC_OnedEAN13Writer.cpp
index e2433d9..0b3aa28 100644
--- a/fxbarcode/oned/BC_OnedEAN13Writer.cpp
+++ b/fxbarcode/oned/BC_OnedEAN13Writer.cpp
@@ -85,19 +85,16 @@
   return EANCalcChecksum(contents);
 }
 
-uint8_t* CBC_OnedEAN13Writer::Encode(const ByteString& contents,
-                                     int32_t& outLength) {
+DataVector<uint8_t> CBC_OnedEAN13Writer::Encode(const ByteString& contents) {
   if (contents.GetLength() != 13)
-    return nullptr;
+    return DataVector<uint8_t>();
 
   m_iDataLenth = 13;
   int32_t firstDigit = FXSYS_DecimalCharToInt(contents.Front());
   int32_t parities = kFirstDigitEncodings[firstDigit];
-  outLength = m_codeWidth;
-  std::unique_ptr<uint8_t, FxFreeDeleter> result(
-      FX_Alloc(uint8_t, m_codeWidth));
+  DataVector<uint8_t> result(m_codeWidth);
   int32_t pos = 0;
-  pos += AppendPattern(result.get(), pos, kOnedEAN13StartPattern, 3, true);
+  pos += AppendPattern(result.data(), pos, kOnedEAN13StartPattern, 3, true);
 
   int32_t i = 0;
   for (i = 1; i <= 6; i++) {
@@ -105,16 +102,17 @@
     if ((parities >> (6 - i) & 1) == 1) {
       digit += 10;
     }
-    pos += AppendPattern(result.get(), pos, L_AND_G_PATTERNS[digit], 4, false);
+    pos += AppendPattern(result.data(), pos, L_AND_G_PATTERNS[digit], 4, false);
   }
-  pos += AppendPattern(result.get(), pos, kOnedEAN13MiddlePattern, 5, false);
+  pos += AppendPattern(result.data(), pos, kOnedEAN13MiddlePattern, 5, false);
 
   for (i = 7; i <= 12; i++) {
     int32_t digit = FXSYS_DecimalCharToInt(contents[i]);
-    pos += AppendPattern(result.get(), pos, kOnedEAN13LPattern[digit], 4, true);
+    pos +=
+        AppendPattern(result.data(), pos, kOnedEAN13LPattern[digit], 4, true);
   }
-  pos += AppendPattern(result.get(), pos, kOnedEAN13StartPattern, 3, true);
-  return result.release();
+  pos += AppendPattern(result.data(), pos, kOnedEAN13StartPattern, 3, true);
+  return result;
 }
 
 bool CBC_OnedEAN13Writer::ShowChars(WideStringView contents,
diff --git a/fxbarcode/oned/BC_OnedEAN13Writer.h b/fxbarcode/oned/BC_OnedEAN13Writer.h
index 6975fa5..8c7ff1c 100644
--- a/fxbarcode/oned/BC_OnedEAN13Writer.h
+++ b/fxbarcode/oned/BC_OnedEAN13Writer.h
@@ -21,7 +21,7 @@
   ~CBC_OnedEAN13Writer() override;
 
   // CBC_OneDimEANWriter:
-  uint8_t* Encode(const ByteString& contents, int32_t& outLength) override;
+  DataVector<uint8_t> Encode(const ByteString& contents) override;
   bool CheckContentValidity(WideStringView contents) override;
   WideString FilterContents(WideStringView contents) override;
   int32_t CalcChecksum(const ByteString& contents) override;
diff --git a/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp b/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp
index d0bb4b6..e4119e5 100644
--- a/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedEAN13Writer_unittest.cpp
@@ -4,7 +4,9 @@
 
 #include "fxbarcode/oned/BC_OnedEAN13Writer.h"
 
-#include "core/fxcrt/fx_memory.h"
+#include <string.h>
+
+#include "core/fxcrt/data_vector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -12,33 +14,15 @@
 TEST(OnedEAN13WriterTest, Encode) {
   CBC_OnedEAN13Writer writer;
   writer.InitEANWriter();
-  int32_t width;
-  uint8_t* encoded;
-  const char* expected;
 
   // EAN-13 barcodes encode 13-digit numbers into 95 modules in a unidimensional
   // disposition.
-  encoded = writer.Encode("", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
+  EXPECT_TRUE(writer.Encode("").empty());
+  EXPECT_TRUE(writer.Encode("123").empty());
+  EXPECT_TRUE(writer.Encode("123456789012").empty());
+  EXPECT_TRUE(writer.Encode("12345678901234").empty());
 
-  encoded = writer.Encode("123", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("123456789012", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("12345678901234", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("1234567890128", width);
-  EXPECT_TRUE(encoded);
-  EXPECT_EQ(95, width);
-
-  expected =
+  static const char kExpected1[] =
       "# #"  // Start
       // 1 implicit by LLGLGG in next 6 digits
       "  #  ##"  // 2 L
@@ -55,16 +39,11 @@
       "## ##  "  // 2 R
       "#  #   "  // 8 R
       "# #";     // End
-  for (int i = 0; i < 95; i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("1234567890128");
+  for (size_t i = 0; i < strlen(kExpected1); i++)
+    EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("7776665554440", width);
-  EXPECT_TRUE(encoded);
-  EXPECT_EQ(95, width);
-
-  expected =
+  static const char kExpected2[] =
       "# #"  // Start
       // 7 implicit by LGLGLG in next 6 digits
       " ### ##"  // 7 L
@@ -81,10 +60,10 @@
       "# ###  "  // 4 R
       "###  # "  // 0 R
       "# #";     // End
-  for (int i = 0; i < 95; i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  encoded = writer.Encode("7776665554440");
+  ASSERT_EQ(strlen(kExpected2), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected2); i++)
+    EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i]) << i;
 }
 
 TEST(OnedEAN13WriterTest, Checksum) {
diff --git a/fxbarcode/oned/BC_OnedEAN8Writer.cpp b/fxbarcode/oned/BC_OnedEAN8Writer.cpp
index 1d3e07e..101e5e8 100644
--- a/fxbarcode/oned/BC_OnedEAN8Writer.cpp
+++ b/fxbarcode/oned/BC_OnedEAN8Writer.cpp
@@ -88,30 +88,28 @@
   return EANCalcChecksum(contents);
 }
 
-uint8_t* CBC_OnedEAN8Writer::Encode(const ByteString& contents,
-                                    int32_t& outLength) {
+DataVector<uint8_t> CBC_OnedEAN8Writer::Encode(const ByteString& contents) {
   if (contents.GetLength() != 8)
-    return nullptr;
+    return {};
 
-  outLength = m_codeWidth;
-  std::unique_ptr<uint8_t, FxFreeDeleter> result(
-      FX_Alloc(uint8_t, m_codeWidth));
+  DataVector<uint8_t> result(m_codeWidth);
   int32_t pos = 0;
-  pos += AppendPattern(result.get(), pos, kOnedEAN8StartPattern, 3, true);
+  pos += AppendPattern(result.data(), pos, kOnedEAN8StartPattern, 3, true);
 
   int32_t i = 0;
   for (i = 0; i <= 3; i++) {
     int32_t digit = FXSYS_DecimalCharToInt(contents[i]);
-    pos += AppendPattern(result.get(), pos, kOnedEAN8LPattern[digit], 4, false);
+    pos +=
+        AppendPattern(result.data(), pos, kOnedEAN8LPattern[digit], 4, false);
   }
-  pos += AppendPattern(result.get(), pos, kOnedEAN8MiddlePattern, 5, false);
+  pos += AppendPattern(result.data(), pos, kOnedEAN8MiddlePattern, 5, false);
 
   for (i = 4; i <= 7; i++) {
     int32_t digit = FXSYS_DecimalCharToInt(contents[i]);
-    pos += AppendPattern(result.get(), pos, kOnedEAN8LPattern[digit], 4, true);
+    pos += AppendPattern(result.data(), pos, kOnedEAN8LPattern[digit], 4, true);
   }
-  pos += AppendPattern(result.get(), pos, kOnedEAN8StartPattern, 3, true);
-  return result.release();
+  pos += AppendPattern(result.data(), pos, kOnedEAN8StartPattern, 3, true);
+  return result;
 }
 
 bool CBC_OnedEAN8Writer::ShowChars(WideStringView contents,
diff --git a/fxbarcode/oned/BC_OnedEAN8Writer.h b/fxbarcode/oned/BC_OnedEAN8Writer.h
index 252db9f..3f633e6 100644
--- a/fxbarcode/oned/BC_OnedEAN8Writer.h
+++ b/fxbarcode/oned/BC_OnedEAN8Writer.h
@@ -22,7 +22,7 @@
   ~CBC_OnedEAN8Writer() override;
 
   // CBC_OneDimEANWriter:
-  uint8_t* Encode(const ByteString& contents, int32_t& outLength) override;
+  DataVector<uint8_t> Encode(const ByteString& contents) override;
   bool CheckContentValidity(WideStringView contents) override;
   WideString FilterContents(WideStringView contents) override;
   void SetDataLength(int32_t length) override;
diff --git a/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp b/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp
index 513c666..36d961d 100644
--- a/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedEAN8Writer_unittest.cpp
@@ -4,7 +4,9 @@
 
 #include "fxbarcode/oned/BC_OnedEAN8Writer.h"
 
-#include "core/fxcrt/fx_memory.h"
+#include <string.h>
+
+#include "core/fxcrt/data_vector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -12,33 +14,15 @@
 TEST(OnedEAN8WriterTest, Encode) {
   CBC_OnedEAN8Writer writer;
   writer.InitEANWriter();
-  int32_t width;
-  uint8_t* encoded;
-  const char* expected;
 
   // EAN-8 barcodes encode 8-digit numbers into 67 modules in a unidimensional
   // disposition.
-  encoded = writer.Encode("", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
+  EXPECT_TRUE(writer.Encode("").empty());
+  EXPECT_TRUE(writer.Encode("123").empty());
+  EXPECT_TRUE(writer.Encode("1234567").empty());
+  EXPECT_TRUE(writer.Encode("123456789").empty());
 
-  encoded = writer.Encode("123", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("1234567", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("123456789", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("12345670", width);
-  EXPECT_TRUE(encoded);
-  EXPECT_EQ(67, width);
-
-  expected =
+  static const char kExpected1[] =
       "# #"      // Start
       "  ##  #"  // 1 L
       "  #  ##"  // 2 L
@@ -50,16 +34,12 @@
       "#   #  "  // 7 R
       "###  # "  // 0 R
       "# #";     // End
-  for (int i = 0; i < 67; i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("12345670");
+  ASSERT_EQ(strlen(kExpected1), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected1); i++)
+    EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("99441104", width);
-  EXPECT_TRUE(encoded);
-  EXPECT_EQ(67, width);
-
-  expected =
+  static const char kExpected2[] =
       "# #"      // Start
       "   # ##"  // 9 L
       "   # ##"  // 9 L
@@ -71,10 +51,10 @@
       "###  # "  // 0 R
       "# ###  "  // 4 R
       "# #";     // End
-  for (int i = 0; i < 67; i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  encoded = writer.Encode("99441104");
+  ASSERT_EQ(strlen(kExpected2), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected2); i++)
+    EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i]) << i;
 }
 
 TEST(OnedEAN8WriterTest, Checksum) {
diff --git a/fxbarcode/oned/BC_OnedUPCAWriter.cpp b/fxbarcode/oned/BC_OnedUPCAWriter.cpp
index 3534a76..55a6a02 100644
--- a/fxbarcode/oned/BC_OnedUPCAWriter.cpp
+++ b/fxbarcode/oned/BC_OnedUPCAWriter.cpp
@@ -84,11 +84,10 @@
   return checksum;
 }
 
-uint8_t* CBC_OnedUPCAWriter::Encode(const ByteString& contents,
-                                    int32_t& outLength) {
+DataVector<uint8_t> CBC_OnedUPCAWriter::Encode(const ByteString& contents) {
   ByteString toEAN13String = '0' + contents;
   m_iDataLenth = 13;
-  return m_subWriter->Encode(toEAN13String, outLength);
+  return m_subWriter->Encode(toEAN13String);
 }
 
 bool CBC_OnedUPCAWriter::ShowChars(WideStringView contents,
diff --git a/fxbarcode/oned/BC_OnedUPCAWriter.h b/fxbarcode/oned/BC_OnedUPCAWriter.h
index 60c1536..7d8beff 100644
--- a/fxbarcode/oned/BC_OnedUPCAWriter.h
+++ b/fxbarcode/oned/BC_OnedUPCAWriter.h
@@ -23,7 +23,7 @@
   ~CBC_OnedUPCAWriter() override;
 
   // CBC_OneDimEANWriter:
-  uint8_t* Encode(const ByteString& contents, int32_t& outLength) override;
+  DataVector<uint8_t> Encode(const ByteString& contents) override;
   bool CheckContentValidity(WideStringView contents) override;
   WideString FilterContents(WideStringView contents) override;
   void InitEANWriter() override;
diff --git a/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp b/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp
index 19330b5..71d10e1 100644
--- a/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp
+++ b/fxbarcode/oned/BC_OnedUPCAWriter_unittest.cpp
@@ -4,7 +4,9 @@
 
 #include "fxbarcode/oned/BC_OnedUPCAWriter.h"
 
-#include "core/fxcrt/fx_memory.h"
+#include <string.h>
+
+#include "core/fxcrt/data_vector.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -12,28 +14,15 @@
 TEST(OnedUPCAWriterTest, Encode) {
   CBC_OnedUPCAWriter writer;
   writer.InitEANWriter();
-  int32_t width;
 
   // UPCA barcodes encode 12-digit numbers into 95 modules in a unidimensional
   // disposition.
-  uint8_t* encoded = writer.Encode("", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
+  EXPECT_TRUE(writer.Encode("").empty());
+  EXPECT_TRUE(writer.Encode("123").empty());
+  EXPECT_TRUE(writer.Encode("12345678901").empty());
+  EXPECT_TRUE(writer.Encode("1234567890123").empty());
 
-  encoded = writer.Encode("123", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("12345678901", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("1234567890123", width);
-  EXPECT_FALSE(encoded);
-  FX_Free(encoded);
-
-  encoded = writer.Encode("123456789012", width);
-  const char* expected =
+  static const char kExpected1[] =
       "# #"      // Start
       "  ##  #"  // 1 L
       "  #  ##"  // 2 L
@@ -49,15 +38,13 @@
       "##  ## "  // 1 R
       "## ##  "  // 2 R
       "# #";     // End
-  EXPECT_TRUE(encoded);
-  EXPECT_EQ(static_cast<int32_t>(strlen(expected)), width);
-  for (size_t i = 0; i < strlen(expected); i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  DataVector<uint8_t> encoded = writer.Encode("123456789012");
+  ASSERT_EQ(strlen(kExpected1), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected1); i++)
+    EXPECT_EQ(kExpected1[i] != ' ', !!encoded[i]) << i;
 
-  encoded = writer.Encode("777666555440", width);
-  expected =
+  encoded = writer.Encode("777666555440");
+  static const char kExpected2[] =
       "# #"      // Start
       " ### ##"  // 7 L
       " ### ##"  // 7 L
@@ -73,12 +60,9 @@
       "# ###  "  // 4 R
       "###  # "  // 0 R
       "# #";     // End
-  EXPECT_TRUE(encoded);
-  EXPECT_EQ(static_cast<int32_t>(strlen(expected)), width);
-  for (size_t i = 0; i < strlen(expected); i++) {
-    EXPECT_EQ(expected[i] != ' ', !!encoded[i]) << i;
-  }
-  FX_Free(encoded);
+  ASSERT_EQ(strlen(kExpected2), encoded.size());
+  for (size_t i = 0; i < strlen(kExpected2); i++)
+    EXPECT_EQ(kExpected2[i] != ' ', !!encoded[i]) << i;
 }
 
 TEST(OnedUPCAWriterTest, Checksum) {