add decoder static init

PiperOrigin-RevId: 802473490
diff --git a/c/dec/decode.c b/c/dec/decode.c
index 05f1d37..e03f7b3 100644
--- a/c/dec/decode.c
+++ b/c/dec/decode.c
@@ -17,6 +17,7 @@
 #include "huffman.h"
 #include "prefix.h"
 #include "state.h"
+#include "static_init.h"
 
 #if defined(BROTLI_TARGET_NEON)
 #include <arm_neon.h>
@@ -78,6 +79,10 @@
 BrotliDecoderState* BrotliDecoderCreateInstance(
     brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
   BrotliDecoderState* state = 0;
+  if (!BrotliDecoderEnsureStaticInit()) {
+    BROTLI_DUMP();
+    return 0;
+  }
   if (!alloc_func && !free_func) {
     state = (BrotliDecoderState*)malloc(sizeof(BrotliDecoderState));
   } else if (alloc_func && free_func) {
diff --git a/c/dec/prefix.c b/c/dec/prefix.c
index b31b505..ce3998f 100644
--- a/c/dec/prefix.c
+++ b/c/dec/prefix.c
@@ -7,13 +7,60 @@
 #include "prefix.h"
 
 #include "../common/platform.h"  /* IWYU pragma: keep */
+#include "../common/static_init.h"
+
+#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
+#include "../common/constants.h"
+#endif
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
 
+#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)
 /* Embed kCmdLut. */
 #include "prefix_inc.h"
+#else
+BROTLI_COLD BROTLI_BOOL BrotliDecoderInitCmdLut(CmdLutElement* items) {
+  static const uint8_t kInsertLengthExtraBits[24] = {
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
+      0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0E, 0x18};
+  static const uint8_t kCopyLengthExtraBits[24] = {
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
+      0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x18};
+  static const uint8_t kCellPos[11] = {0, 1, 0, 1, 8, 9, 2, 16, 10, 17, 18};
+
+  uint16_t insert_length_offsets[24];
+  uint16_t copy_length_offsets[24];
+  insert_length_offsets[0] = 0;
+  copy_length_offsets[0] = 2;
+  for (size_t i = 0; i < 23; ++i) {
+    insert_length_offsets[i + 1] =
+        insert_length_offsets[i] + (uint16_t)(1u << kInsertLengthExtraBits[i]);
+    copy_length_offsets[i + 1] =
+        copy_length_offsets[i] + (uint16_t)(1u << kCopyLengthExtraBits[i]);
+  }
+
+  for (size_t symbol = 0; symbol < BROTLI_NUM_COMMAND_SYMBOLS; ++symbol) {
+    CmdLutElement* item = items + symbol;
+    const size_t cell_idx = symbol >> 6;
+    const size_t cell_pos = kCellPos[cell_idx];
+    const size_t copy_code = ((cell_pos << 3) & 0x18) + (symbol & 0x7);
+    const uint16_t copy_len_offset = copy_length_offsets[copy_code];
+    const size_t insert_code = (cell_pos & 0x18) + ((symbol >> 3) & 0x7);
+    item->copy_len_extra_bits = kCopyLengthExtraBits[copy_code];
+    item->context = (copy_len_offset > 4) ? 3 : ((uint8_t)copy_len_offset - 2);
+    item->copy_len_offset = copy_len_offset;
+    item->distance_code = (cell_idx >= 2) ? -1 : 0;
+    item->insert_len_extra_bits = kInsertLengthExtraBits[insert_code];
+    item->insert_len_offset = insert_length_offsets[insert_code];
+  }
+  return BROTLI_TRUE;
+}
+
+BROTLI_MODEL("small")
+CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];
+#endif  /* BROTLI_STATIC_INIT */
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }  /* extern "C" */
diff --git a/c/dec/prefix.h b/c/dec/prefix.h
index 66aa52a..f45b8be 100644
--- a/c/dec/prefix.h
+++ b/c/dec/prefix.h
@@ -12,6 +12,11 @@
 
 #include "../common/constants.h"
 #include "../common/platform.h"  /* IWYU pragma: keep */
+#include "../common/static_init.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
 
 typedef struct CmdLutElement {
   uint8_t insert_len_extra_bits;
@@ -22,7 +27,17 @@
   uint16_t copy_len_offset;
 } CmdLutElement;
 
+#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)
 BROTLI_INTERNAL extern const BROTLI_MODEL("small")
     CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];
+#else
+BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderInitCmdLut(CmdLutElement* items);
+BROTLI_INTERNAL extern BROTLI_MODEL("small")
+    CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}  /* extern "C" */
+#endif
 
 #endif  /* BROTLI_DEC_PREFIX_H_ */
diff --git a/c/dec/static_init.c b/c/dec/static_init.c
new file mode 100644
index 0000000..1345052
--- /dev/null
+++ b/c/dec/static_init.c
@@ -0,0 +1,53 @@
+/* Copyright 2025 Google Inc. All Rights Reserved.
+
+   Distributed under MIT license.
+   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+#include "static_init.h"
+
+#include "../common/platform.h"
+#include "../common/static_init.h"
+
+#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
+#include "../common/dictionary.h"
+#include "prefix.h"
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
+static BROTLI_BOOL DoBrotliDecoderStaticInit(void) {
+  BROTLI_BOOL ok = BrotliDecoderInitCmdLut(kCmdLut);
+  if (!ok) return BROTLI_FALSE;
+  return BROTLI_TRUE;
+}
+#endif  /* BROTLI_STATIC_INIT_NONE */
+
+#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)
+static BROTLI_BOOL kEarlyInitOk;
+static __attribute__((constructor)) void BrotliDecoderStaticInitEarly(void) {
+  kEarlyInitOk = DoBrotliDecoderStaticInit();
+}
+#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)
+static BROTLI_BOOL kLazyInitOk;
+void BrotliDecoderLazyStaticInitInner(void) {
+  kLazyInitOk = DoBrotliDecoderStaticInit();
+}
+#endif  /* BROTLI_STATIC_INIT_EARLY */
+
+BROTLI_BOOL BrotliDecoderEnsureStaticInit(void) {
+#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)
+  return BROTLI_TRUE;
+#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)
+  return kEarlyInitOk;
+#else
+  return kLazyInitOk;
+#endif
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}  /* extern "C" */
+#endif
diff --git a/c/dec/static_init.h b/c/dec/static_init.h
new file mode 100644
index 0000000..4ae063e
--- /dev/null
+++ b/c/dec/static_init.h
@@ -0,0 +1,30 @@
+/* Copyright 2025 Google Inc. All Rights Reserved.
+
+   Distributed under MIT license.
+   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Central point for static initialization. */
+
+#ifndef THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_
+#define THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_
+
+#include "../common/platform.h"
+#include "../common/static_init.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)
+BROTLI_INTERNAL void BrotliDecoderLazyStaticInitInner(void);
+BROTLI_INTERNAL void BrotliDecoderLazyStaticInit(void);
+#endif  /* BROTLI_STATIC_INIT */
+
+BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderEnsureStaticInit(void);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}  /* extern "C" */
+#endif
+
+#endif  // THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_
diff --git a/c/enc/dictionary_hash.c b/c/enc/dictionary_hash.c
index f367046..193f7a4 100644
--- a/c/enc/dictionary_hash.c
+++ b/c/enc/dictionary_hash.c
@@ -9,7 +9,7 @@
 #include "dictionary_hash.h"
 
 #include "../common/platform.h"  /* IWYU pragma: keep */
-#include "static_init.h"
+#include "../common/static_init.h"
 
 #if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
 #include "../common/dictionary.h"
diff --git a/c/enc/dictionary_hash.h b/c/enc/dictionary_hash.h
index 8d08f57..dfddc01 100644
--- a/c/enc/dictionary_hash.h
+++ b/c/enc/dictionary_hash.h
@@ -10,7 +10,7 @@
 #define BROTLI_ENC_DICTIONARY_HASH_H_
 
 #include "../common/platform.h"
-#include "static_init.h"
+#include "../common/static_init.h"
 
 #if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
 #include "../common/dictionary.h"
diff --git a/c/enc/static_dict_lut.c b/c/enc/static_dict_lut.c
index b7a8706..109366f 100644
--- a/c/enc/static_dict_lut.c
+++ b/c/enc/static_dict_lut.c
@@ -9,7 +9,7 @@
 #include "static_dict_lut.h"
 
 #include "../common/platform.h"  /* IWYU pragma: keep */
-#include "static_init.h"
+#include "../common/static_init.h"
 
 #if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)
 #include "../common/dictionary.h"
diff --git a/c/enc/static_dict_lut.h b/c/enc/static_dict_lut.h
index 6aa9613..078f554 100644
--- a/c/enc/static_dict_lut.h
+++ b/c/enc/static_dict_lut.h
@@ -11,7 +11,7 @@
 
 #include "../common/dictionary.h"
 #include "../common/platform.h"
-#include "static_init.h"
+#include "../common/static_init.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
diff --git a/c/enc/static_init_lazy.cc b/c/enc/static_init_lazy.cc
index 300357e..6e00cd3 100644
--- a/c/enc/static_init_lazy.cc
+++ b/c/enc/static_init_lazy.cc
@@ -1,10 +1,10 @@
-#include "third_party/brotli/common/platform.h"
+#include "../common/platform.h"
+#include "../common/static_init.h"
 #include "static_init.h"
 
 #if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_LAZY)
 #error "BROTLI_STATIC_INIT should be BROTLI_STATIC_INIT_LAZY"
-#endif
-
+#else
 void BrotliEncoderLazyStaticInit(void) {
   /* From https://en.cppreference.com/w/cpp/language/storage_duration.html:
      ### Static block variables ###
@@ -23,3 +23,4 @@
   }();
   if (!ok) BROTLI_CRASH();
 }
+#endif  /* BROTLI_STATIC_INIT_LAZY */
diff --git a/setup.py b/setup.py
index 5355ed8..d73d6dd 100644
--- a/setup.py
+++ b/setup.py
@@ -235,6 +235,7 @@
                 'c/dec/huffman.c',
                 'c/dec/prefix.c',
                 'c/dec/state.c',
+                'c/dec/static_init.c',
                 'c/enc/backward_references.c',
                 'c/enc/backward_references_hq.c',
                 'c/enc/bit_cost.c',
@@ -273,6 +274,7 @@
                 'c/dec/prefix.h',
                 'c/dec/prefix_inc.h',
                 'c/dec/state.h',
+                'c/dec/static_init.h',
                 'c/enc/backward_references.h',
                 'c/enc/backward_references_hq.h',
                 'c/enc/backward_references_inc.h',