Add example/jsonfindptrs -query=STR flag
diff --git a/example/jsonfindptrs/jsonfindptrs.cc b/example/jsonfindptrs/jsonfindptrs.cc
index c26ff4e..4794279 100644
--- a/example/jsonfindptrs/jsonfindptrs.cc
+++ b/example/jsonfindptrs/jsonfindptrs.cc
@@ -106,6 +106,7 @@
     "\n"
     "Flags:\n"
     "    -d=NUM  -max-output-depth=NUM\n"
+    "    -q=STR  -query=STR\n"
     "            -input-allow-comments\n"
     "            -input-allow-extra-comma\n"
     "            -input-allow-inf-nan-numbers\n"
@@ -193,6 +194,7 @@
   char** remaining_argv;
 
   uint32_t max_output_depth;
+  char* query_c_string;
   bool strict_json_pointer_syntax;
 } g_flags = {0};
 
@@ -249,6 +251,12 @@
       g_quirks.push_back(WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS);
       continue;
     }
+    if (!strncmp(arg, "q=", 2) || !strncmp(arg, "query=", 6)) {
+      while (*arg++ != '=') {
+      }
+      g_flags.query_c_string = arg;
+      continue;
+    }
     if (!strcmp(arg, "strict-json-pointer-syntax")) {
       g_flags.strict_json_pointer_syntax = true;
       continue;
@@ -506,7 +514,8 @@
 
   return wuffs_aux::DecodeJson(
              Callbacks(), wuffs_aux::sync_io::FileInput(in),
-             wuffs_base__make_slice_u32(g_quirks.data(), g_quirks.size()))
+             wuffs_base__make_slice_u32(g_quirks.data(), g_quirks.size()),
+             (g_flags.query_c_string ? g_flags.query_c_string : ""))
       .error_message;
 }
 
diff --git a/internal/cgen/auxiliary/json.cc b/internal/cgen/auxiliary/json.cc
index 1613ff5..bcd3908 100644
--- a/internal/cgen/auxiliary/json.cc
+++ b/internal/cgen/auxiliary/json.cc
@@ -29,7 +29,7 @@
 
 std::string  //
 DecodeJsonCallbacks::AppendByteString(std::string&& val) {
-  return "wuffs_aux::JsonDecoder: unexpected JSON byte string";
+  return "wuffs_aux::DecodeJson: unexpected JSON byte string";
 }
 
 void  //
@@ -37,6 +37,10 @@
                           sync_io::Input& input,
                           IOBuffer& buffer) {}
 
+const char DecodeJson_BadJsonPointer[] =
+    "wuffs_aux::DecodeJson: bad JSON Pointer";
+const char DecodeJson_NoMatch[] = "wuffs_aux::DecodeJson: no match";
+
 #define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN                       \
   while (tok_buf.meta.ri >= tok_buf.meta.wi) {                           \
     if (tok_status.repr == nullptr) {                                    \
@@ -48,17 +52,17 @@
         goto done;                                                       \
       } else if (cursor_index != io_buf->meta.ri) {                      \
         ret_error_message =                                              \
-            "wuffs_aux::JsonDecoder: internal error: bad cursor_index";  \
+            "wuffs_aux::DecodeJson: internal error: bad cursor_index";   \
         goto done;                                                       \
       } else if (io_buf->meta.closed) {                                  \
         ret_error_message =                                              \
-            "wuffs_aux::JsonDecoder: internal error: io_buf is closed";  \
+            "wuffs_aux::DecodeJson: internal error: io_buf is closed";   \
         goto done;                                                       \
       }                                                                  \
       io_buf->compact();                                                 \
       if (io_buf->meta.wi >= io_buf->data.len) {                         \
         ret_error_message =                                              \
-            "wuffs_aux::JsonDecoder: internal error: io_buf is full";    \
+            "wuffs_aux::DecodeJson: internal error: io_buf is full";     \
         goto done;                                                       \
       }                                                                  \
       cursor_index = io_buf->meta.ri;                                    \
@@ -69,7 +73,7 @@
     }                                                                    \
     if (WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {      \
       ret_error_message =                                                \
-          "wuffs_aux::JsonDecoder: internal error: bad WORKBUF_LEN";     \
+          "wuffs_aux::DecodeJson: internal error: bad WORKBUF_LEN";      \
       goto done;                                                         \
     }                                                                    \
     wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();        \
@@ -80,16 +84,268 @@
   if ((io_buf->meta.ri < cursor_index) ||                                \
       ((io_buf->meta.ri - cursor_index) < token_len)) {                  \
     ret_error_message =                                                  \
-        "wuffs_aux::JsonDecoder: internal error: bad token indexes";     \
+        "wuffs_aux::DecodeJson: internal error: bad token indexes";      \
     goto done;                                                           \
   }                                                                      \
   uint8_t* token_ptr = io_buf->data.ptr + cursor_index;                  \
   cursor_index += token_len
 
+namespace {
+
+// DecodeJson_SplitJsonPointer returns ("bar", 8) for ("/foo/bar/baz/qux", 5).
+// It returns a 0 size_t when s has invalid JSON Pointer syntax.
+std::pair<std::string, size_t>  //
+DecodeJson_SplitJsonPointer(std::string& s, size_t i) {
+  std::string fragment;
+  while (i < s.size()) {
+    char c = s[i];
+    if (c == '/') {
+      break;
+    } else if (c != '~') {
+      fragment.push_back(c);
+      i++;
+      continue;
+    }
+    i++;
+    if (i >= s.size()) {
+      return std::make_pair(std::string(), 0);
+    }
+    c = s[i];
+    if (c == '0') {
+      fragment.push_back('~');
+      i++;
+      continue;
+    } else if (c == '1') {
+      fragment.push_back('/');
+      i++;
+      continue;
+    }
+    return std::make_pair(std::string(), 0);
+  }
+  return std::make_pair(std::move(fragment), i);
+}
+
+std::string  //
+DecodeJson_DecodeBackslashX(std::string& str,
+                            uint8_t* token_ptr,
+                            size_t token_len) {
+  wuffs_base__slice_u8 encoded =
+      wuffs_base__make_slice_u8(token_ptr, token_len);
+  while (encoded.len > 0) {
+    uint8_t decoded[64];
+    constexpr bool src_closed = true;
+    wuffs_base__transform__output o = wuffs_base__base_16__decode4(
+        wuffs_base__make_slice_u8(&decoded[0], sizeof decoded), encoded,
+        src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
+    if (o.status.is_error()) {
+      return o.status.message();
+    } else if ((o.num_dst > (sizeof decoded)) || (o.num_src > encoded.len)) {
+      return "wuffs_aux::DecodeJson: internal error: inconsistent base16 "
+             "decoding";
+    }
+    str.append(  // Convert from (uint8_t*).
+        static_cast<const char*>(static_cast<void*>(&decoded[0])), o.num_dst);
+    encoded.ptr += o.num_src;
+    encoded.len -= o.num_src;
+  }
+  return "";
+}
+
+std::string  //
+DecodeJson_WalkJsonPointerFragment(wuffs_base__token_buffer& tok_buf,
+                                   wuffs_base__status& tok_status,
+                                   wuffs_json__decoder::unique_ptr& dec,
+                                   wuffs_base__io_buffer* io_buf,
+                                   std::string& io_error_message,
+                                   size_t& cursor_index,
+                                   sync_io::Input& input,
+                                   std::string& json_pointer_fragment) {
+  std::string ret_error_message;
+  while (true) {
+    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+    int64_t vbc = token.value_base_category();
+    uint64_t vbd = token.value_base_detail();
+    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
+      continue;
+    } else if ((vbc != WUFFS_BASE__TOKEN__VBC__STRUCTURE) ||
+               !(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)) {
+      return DecodeJson_NoMatch;
+    } else if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST) {
+      goto do_list;
+    }
+    goto do_dict;
+  }
+
+do_dict:
+  // Alternate between these two things:
+  //  1. Decode the next dict key (a string). If it matches the fragment, we're
+  //    done (success). If we've reached the dict's end (VBD__STRUCTURE__POP)
+  //    so that there was no next dict key, we're done (failure).
+  //  2. Otherwise, skip the next dict value.
+  while (true) {
+    for (std::string str; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      switch (vbc) {
+        case WUFFS_BASE__TOKEN__VBC__FILLER:
+          continue;
+
+        case WUFFS_BASE__TOKEN__VBC__STRUCTURE:
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+            goto fail;
+          }
+          return DecodeJson_NoMatch;
+
+        case WUFFS_BASE__TOKEN__VBC__STRING: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
+            // No-op.
+          } else if (vbd &
+                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
+            const char* ptr =  // Convert from (uint8_t*).
+                static_cast<const char*>(static_cast<void*>(token_ptr));
+            str.append(ptr, token_len);
+          } else if (
+              vbd &
+              WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {
+            ret_error_message =
+                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);
+            if (!ret_error_message.empty()) {
+              goto done;
+            }
+          } else {
+            goto fail;
+          }
+          break;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
+          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
+          size_t n = wuffs_base__utf_8__encode(
+              wuffs_base__make_slice_u8(
+                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
+              static_cast<uint32_t>(vbd));
+          const char* ptr =  // Convert from (uint8_t*).
+              static_cast<const char*>(static_cast<void*>(&u[0]));
+          str.append(ptr, n);
+          break;
+        }
+
+        default:
+          goto fail;
+      }
+
+      if (token.continued()) {
+        continue;
+      }
+      if (str == json_pointer_fragment) {
+        return "";
+      }
+      goto skip_the_next_dict_value;
+    }
+
+  skip_the_next_dict_value:
+    for (uint32_t skip_depth = 0; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
+        continue;
+      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
+        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+          skip_depth++;
+          continue;
+        }
+        skip_depth--;
+      }
+
+      if (skip_depth == 0) {
+        break;
+      }
+    }  // skip_the_next_dict_value
+  }    // do_dict
+
+do_list:
+  do {
+    wuffs_base__result_u64 result_u64 = wuffs_base__parse_number_u64(
+        wuffs_base__make_slice_u8(
+            static_cast<uint8_t*>(static_cast<void*>(
+                const_cast<char*>(json_pointer_fragment.data()))),
+            json_pointer_fragment.size()),
+        WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
+    if (!result_u64.status.is_ok()) {
+      return DecodeJson_NoMatch;
+    }
+    uint64_t remaining = result_u64.value;
+    if (remaining == 0) {
+      goto check_that_a_value_follows;
+    }
+    for (uint32_t skip_depth = 0; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
+        continue;
+      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
+        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+          skip_depth++;
+          continue;
+        }
+        if (skip_depth == 0) {
+          return DecodeJson_NoMatch;
+        }
+        skip_depth--;
+      }
+
+      if (skip_depth > 0) {
+        continue;
+      }
+      remaining--;
+      if (remaining == 0) {
+        goto check_that_a_value_follows;
+      }
+    }
+  } while (false);  // do_list
+
+check_that_a_value_follows:
+  while (true) {
+    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+    int64_t vbc = token.value_base_category();
+    uint64_t vbd = token.value_base_detail();
+    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
+      continue;
+    }
+
+    // Undo the last part of WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN, so that
+    // we're only peeking at the next token.
+    tok_buf.meta.ri--;
+    cursor_index -= token_len;
+
+    if ((vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) &&
+        (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP)) {
+      return DecodeJson_NoMatch;
+    }
+    return "";
+  }  // check_that_a_value_follows
+
+fail:
+  return "wuffs_aux::DecodeJson: internal error: unexpected token";
+done:
+  return ret_error_message;
+}
+
+}  // namespace
+
 DecodeJsonResult  //
 DecodeJson(DecodeJsonCallbacks&& callbacks,
            sync_io::Input&& input,
-           wuffs_base__slice_u32 quirks) {
+           wuffs_base__slice_u32 quirks,
+           std::string json_pointer) {
   // Prepare the wuffs_base__io_buffer and the resultant error_message.
   wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
   wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
@@ -107,7 +363,7 @@
     // Prepare the low-level JSON decoder.
     wuffs_json__decoder::unique_ptr dec = wuffs_json__decoder::alloc();
     if (!dec) {
-      ret_error_message = "wuffs_aux::JsonDecoder: out of memory";
+      ret_error_message = "wuffs_aux::DecodeJson: out of memory";
       goto done;
     }
     for (size_t i = 0; i < quirks.len; i++) {
@@ -125,6 +381,27 @@
     uint32_t depth = 0;
     std::string str;
 
+    // Walk the (optional) JSON Pointer.
+    for (size_t i = 0; i < json_pointer.size();) {
+      if (json_pointer[i] != '/') {
+        ret_error_message = DecodeJson_BadJsonPointer;
+        goto done;
+      }
+      std::pair<std::string, size_t> split =
+          DecodeJson_SplitJsonPointer(json_pointer, i + 1);
+      i = std::move(split.second);
+      if (i == 0) {
+        ret_error_message = DecodeJson_BadJsonPointer;
+        goto done;
+      }
+      ret_error_message = DecodeJson_WalkJsonPointerFragment(
+          tok_buf, tok_status, dec, io_buf, io_error_message, cursor_index,
+          input, split.first);
+      if (!ret_error_message.empty()) {
+        goto done;
+      }
+    }
+
     // Loop, doing these two things:
     //  1. Get the next token.
     //  2. Process that token.
@@ -162,29 +439,10 @@
           } else if (
               vbd &
               WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {
-            wuffs_base__slice_u8 encoded =
-                wuffs_base__make_slice_u8(token_ptr, token_len);
-            while (encoded.len > 0) {
-              uint8_t decoded[64];
-              constexpr bool src_closed = true;
-              wuffs_base__transform__output o = wuffs_base__base_16__decode4(
-                  wuffs_base__make_slice_u8(&decoded[0], sizeof decoded),
-                  encoded, src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
-              if (o.status.is_error()) {
-                ret_error_message = o.status.message();
-                goto done;
-              } else if ((o.num_dst > (sizeof decoded)) ||
-                         (o.num_src > encoded.len)) {
-                ret_error_message =
-                    "wuffs_aux::JsonDecoder: internal error: inconsistent "
-                    "base16 decoding";
-                goto done;
-              }
-              str.append(  // Convert from (uint8_t*).
-                  static_cast<const char*>(static_cast<void*>(&decoded[0])),
-                  o.num_dst);
-              encoded.ptr += o.num_src;
-              encoded.len -= o.num_src;
+            ret_error_message =
+                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);
+            if (!ret_error_message.empty()) {
+              goto done;
             }
           } else {
             goto fail;
@@ -271,7 +529,7 @@
 
     fail:
       ret_error_message =
-          "wuffs_aux::JsonDecoder: internal error: unexpected token";
+          "wuffs_aux::DecodeJson: internal error: unexpected token";
       goto done;
 
     parsed_a_value:
diff --git a/internal/cgen/auxiliary/json.hh b/internal/cgen/auxiliary/json.hh
index 413c45d..89998d0 100644
--- a/internal/cgen/auxiliary/json.hh
+++ b/internal/cgen/auxiliary/json.hh
@@ -78,15 +78,27 @@
                     IOBuffer& buffer);
 };
 
+extern const char DecodeJson_BadJsonPointer[];
+extern const char DecodeJson_NoMatch[];
+
 // DecodeJson calls callbacks based on the JSON-formatted data in input.
 //
 // On success, the returned error_message is empty and cursor_position counts
 // the number of bytes consumed. On failure, error_message is non-empty and
 // cursor_position is the location of the error. That error may be a content
 // error (invalid JSON) or an input error (e.g. network failure).
+//
+// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks
+// run for the input's sub-node that matches the query. DecodeJson_NoMatch is
+// returned if no matching sub-node was found. The empty query matches the
+// input's root node, consistent with JSON Pointer semantics.
+//
+// The JSON Pointer implementation is greedy: duplicate keys are not rejected
+// but only the first match for each '/'-separated fragment is followed.
 DecodeJsonResult DecodeJson(
     DecodeJsonCallbacks&& callbacks,
     sync_io::Input&& input,
-    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32());
+    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32(),
+    std::string json_pointer = std::string());
 
 }  // namespace wuffs_aux
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index d0fbc0f..97a3686 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -648,26 +648,33 @@
 	""
 
 const AuxJsonCc = "" +
-	"// ---------------- Auxiliary - JSON\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__JSON)\n\n#include <utility>\n\nnamespace wuffs_aux {\n\nDecodeJsonResult::DecodeJsonResult(std::string&& error_message0,\n                                   uint64_t cursor_position0)\n    : error_message(std::move(error_message0)),\n      cursor_position(cursor_position0) {}\n\nstd::string  //\nDecodeJsonCallbacks::AppendByteString(std::string&& val) {\n  return \"wuffs_aux::JsonDecoder: unexpected JSON byte string\";\n}\n\nvoid  //\nDecodeJsonCallbacks::Done(DecodeJsonResult& result,\n                          sync_io::Input& input,\n                          IOBuffer& buffer) {}\n\n#define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN                       \\\n  while (tok_buf.meta.ri >= tok_buf.meta.wi) {                           \\\n    if (tok_status.repr == nullptr) {                                    \\\n    } else if (tok_status.repr == wuffs_base__suspension__short_write) { \\\n      tok_buf.compact();                   " +
-	"                              \\\n    } else if (tok_status.repr == wuffs_base__suspension__short_read) {  \\\n      if (!io_error_message.empty()) {                                   \\\n        ret_error_message = std::move(io_error_message);                 \\\n        goto done;                                                       \\\n      } else if (cursor_index != io_buf->meta.ri) {                      \\\n        ret_error_message =                                              \\\n            \"wuffs_aux::JsonDecoder: internal error: bad cursor_index\";  \\\n        goto done;                                                       \\\n      } else if (io_buf->meta.closed) {                                  \\\n        ret_error_message =                                              \\\n            \"wuffs_aux::JsonDecoder: internal error: io_buf is closed\";  \\\n        goto done;                                                       \\\n      }                                                                  \\\n      io_buf->com" +
-	"pact();                                                 \\\n      if (io_buf->meta.wi >= io_buf->data.len) {                         \\\n        ret_error_message =                                              \\\n            \"wuffs_aux::JsonDecoder: internal error: io_buf is full\";    \\\n        goto done;                                                       \\\n      }                                                                  \\\n      cursor_index = io_buf->meta.ri;                                    \\\n      io_error_message = input.CopyIn(io_buf);                           \\\n    } else {                                                             \\\n      ret_error_message = tok_status.message();                          \\\n      goto done;                                                         \\\n    }                                                                    \\\n    if (WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {      \\\n      ret_error_message =                                         " +
-	"       \\\n          \"wuffs_aux::JsonDecoder: internal error: bad WORKBUF_LEN\";     \\\n      goto done;                                                         \\\n    }                                                                    \\\n    wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();        \\\n    tok_status = dec->decode_tokens(&tok_buf, io_buf, work_buf);         \\\n  }                                                                      \\\n  wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++];         \\\n  uint64_t token_len = token.length();                                   \\\n  if ((io_buf->meta.ri < cursor_index) ||                                \\\n      ((io_buf->meta.ri - cursor_index) < token_len)) {                  \\\n    ret_error_message =                                                  \\\n        \"wuffs_aux::JsonDecoder: internal error: bad token indexes\";     \\\n    goto done;                                                           \\\n  }                                     " +
-	"                                 \\\n  uint8_t* token_ptr = io_buf->data.ptr + cursor_index;                  \\\n  cursor_index += token_len\n\nDecodeJsonResult  //\nDecodeJson(DecodeJsonCallbacks&& callbacks,\n           sync_io::Input&& input,\n           wuffs_base__slice_u32 quirks) {\n  // Prepare the wuffs_base__io_buffer and the resultant error_message.\n  wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();\n  wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();\n  std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);\n  if (!io_buf) {\n    fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);\n    fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);\n    io_buf = &fallback_io_buf;\n  }\n  size_t cursor_index = 0;\n  std::string ret_error_message;\n  std::string io_error_message;\n\n  do {\n    // Prepare the low-level JSON decoder.\n    wuffs_json__decoder::unique_ptr dec = wuffs_json__decoder::alloc();\n    if (!dec) {\n      ret_error_message = \"wuffs_aux::Jso" +
-	"nDecoder: out of memory\";\n      goto done;\n    }\n    for (size_t i = 0; i < quirks.len; i++) {\n      dec->set_quirk_enabled(quirks.ptr[i], true);\n    }\n\n    // Prepare the wuffs_base__tok_buffer.\n    wuffs_base__token tok_array[256];\n    wuffs_base__token_buffer tok_buf =\n        wuffs_base__slice_token__writer(wuffs_base__make_slice_token(\n            &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));\n    wuffs_base__status tok_status = wuffs_base__make_status(nullptr);\n\n    // Prepare other state.\n    uint32_t depth = 0;\n    std::string str;\n\n    // Loop, doing these two things:\n    //  1. Get the next token.\n    //  2. Process that token.\n    while (true) {\n      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;\n\n      int64_t vbc = token.value_base_category();\n      uint64_t vbd = token.value_base_detail();\n      switch (vbc) {\n        case WUFFS_BASE__TOKEN__VBC__FILLER:\n          continue;\n\n        case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {\n          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)" +
-	" {\n            ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));\n            if (!ret_error_message.empty()) {\n              goto done;\n            }\n            depth++;\n            continue;\n          }\n          ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));\n          depth--;\n          goto parsed_a_value;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__STRING: {\n          if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {\n            // No-op.\n          } else if (vbd &\n                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {\n            const char* ptr =  // Convert from (uint8_t*).\n                static_cast<const char*>(static_cast<void*>(token_ptr));\n            str.append(ptr, token_len);\n          } else if (\n              vbd &\n              WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {\n            wuffs_base__slice_u8 encoded =\n                wuffs_base__make_slice_u8(token_ptr, token_len);\n           " +
-	" while (encoded.len > 0) {\n              uint8_t decoded[64];\n              constexpr bool src_closed = true;\n              wuffs_base__transform__output o = wuffs_base__base_16__decode4(\n                  wuffs_base__make_slice_u8(&decoded[0], sizeof decoded),\n                  encoded, src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);\n              if (o.status.is_error()) {\n                ret_error_message = o.status.message();\n                goto done;\n              } else if ((o.num_dst > (sizeof decoded)) ||\n                         (o.num_src > encoded.len)) {\n                ret_error_message =\n                    \"wuffs_aux::JsonDecoder: internal error: inconsistent \"\n                    \"base16 decoding\";\n                goto done;\n              }\n              str.append(  // Convert from (uint8_t*).\n                  static_cast<const char*>(static_cast<void*>(&decoded[0])),\n                  o.num_dst);\n              encoded.ptr += o.num_src;\n              encoded.len -= o.num_src;\n           " +
-	" }\n          } else {\n            goto fail;\n          }\n          if (token.continued()) {\n            continue;\n          }\n          ret_error_message =\n              (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8)\n                  ? callbacks.AppendTextString(std::move(str))\n                  : callbacks.AppendByteString(std::move(str));\n          str.clear();\n          goto parsed_a_value;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {\n          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];\n          size_t n = wuffs_base__utf_8__encode(\n              wuffs_base__make_slice_u8(\n                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),\n              static_cast<uint32_t>(vbd));\n          const char* ptr =  // Convert from (uint8_t*).\n              static_cast<const char*>(static_cast<void*>(&u[0]));\n          str.append(ptr, n);\n          if (token.continued()) {\n            continue;\n          }\n          goto fail;\n        }\n\n        case WUFFS_BASE__" +
-	"TOKEN__VBC__LITERAL: {\n          ret_error_message =\n              (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL)\n                  ? callbacks.AppendNull()\n                  : callbacks.AppendBool(vbd &\n                                         WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);\n          goto parsed_a_value;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__NUMBER: {\n          if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {\n            if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED) {\n              wuffs_base__result_i64 r = wuffs_base__parse_number_i64(\n                  wuffs_base__make_slice_u8(token_ptr, token_len),\n                  WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);\n              if (r.status.is_ok()) {\n                ret_error_message = callbacks.AppendI64(r.value);\n                goto parsed_a_value;\n              }\n            }\n            if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT) {\n              wuffs_base__result_f64 r = wuffs_ba" +
-	"se__parse_number_f64(\n                  wuffs_base__make_slice_u8(token_ptr, token_len),\n                  WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);\n              if (r.status.is_ok()) {\n                ret_error_message = callbacks.AppendF64(r.value);\n                goto parsed_a_value;\n              }\n            }\n          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF) {\n            ret_error_message = callbacks.AppendF64(\n                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n                    0xFFF0000000000000ul));\n            goto parsed_a_value;\n          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF) {\n            ret_error_message = callbacks.AppendF64(\n                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n                    0x7FF0000000000000ul));\n            goto parsed_a_value;\n          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN) {\n            ret_error_message = callbacks.AppendF64(\n   " +
-	"             wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n                    0xFFFFFFFFFFFFFFFFul));\n            goto parsed_a_value;\n          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN) {\n            ret_error_message = callbacks.AppendF64(\n                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n                    0x7FFFFFFFFFFFFFFFul));\n            goto parsed_a_value;\n          }\n          goto fail;\n        }\n      }\n\n    fail:\n      ret_error_message =\n          \"wuffs_aux::JsonDecoder: internal error: unexpected token\";\n      goto done;\n\n    parsed_a_value:\n      if (!ret_error_message.empty() || (depth == 0)) {\n        goto done;\n      }\n    }\n  } while (false);\n\ndone:\n  DecodeJsonResult result(\n      std::move(ret_error_message),\n      wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));\n  callbacks.Done(result, input, *io_buf);\n  return result;\n}\n\n#undef WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN\n\n}  // namespace wuffs_aux\n\n#endif  // !def" +
-	"ined(WUFFS_CONFIG__MODULES) ||\n        // defined(WUFFS_CONFIG__MODULE__AUX__JSON)\n" +
+	"// ---------------- Auxiliary - JSON\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__JSON)\n\n#include <utility>\n\nnamespace wuffs_aux {\n\nDecodeJsonResult::DecodeJsonResult(std::string&& error_message0,\n                                   uint64_t cursor_position0)\n    : error_message(std::move(error_message0)),\n      cursor_position(cursor_position0) {}\n\nstd::string  //\nDecodeJsonCallbacks::AppendByteString(std::string&& val) {\n  return \"wuffs_aux::DecodeJson: unexpected JSON byte string\";\n}\n\nvoid  //\nDecodeJsonCallbacks::Done(DecodeJsonResult& result,\n                          sync_io::Input& input,\n                          IOBuffer& buffer) {}\n\nconst char DecodeJson_BadJsonPointer[] =\n    \"wuffs_aux::DecodeJson: bad JSON Pointer\";\nconst char DecodeJson_NoMatch[] = \"wuffs_aux::DecodeJson: no match\";\n\n#define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN                       \\\n  while (tok_buf.meta.ri >= tok_buf.meta.wi) {                           \\\n    if (tok_status.repr == nullptr) " +
+	"{                                    \\\n    } else if (tok_status.repr == wuffs_base__suspension__short_write) { \\\n      tok_buf.compact();                                                 \\\n    } else if (tok_status.repr == wuffs_base__suspension__short_read) {  \\\n      if (!io_error_message.empty()) {                                   \\\n        ret_error_message = std::move(io_error_message);                 \\\n        goto done;                                                       \\\n      } else if (cursor_index != io_buf->meta.ri) {                      \\\n        ret_error_message =                                              \\\n            \"wuffs_aux::DecodeJson: internal error: bad cursor_index\";   \\\n        goto done;                                                       \\\n      } else if (io_buf->meta.closed) {                                  \\\n        ret_error_message =                                              \\\n            \"wuffs_aux::DecodeJson: internal error: io_buf is closed\";   \\\n        go" +
+	"to done;                                                       \\\n      }                                                                  \\\n      io_buf->compact();                                                 \\\n      if (io_buf->meta.wi >= io_buf->data.len) {                         \\\n        ret_error_message =                                              \\\n            \"wuffs_aux::DecodeJson: internal error: io_buf is full\";     \\\n        goto done;                                                       \\\n      }                                                                  \\\n      cursor_index = io_buf->meta.ri;                                    \\\n      io_error_message = input.CopyIn(io_buf);                           \\\n    } else {                                                             \\\n      ret_error_message = tok_status.message();                          \\\n      goto done;                                                         \\\n    }                                                      " +
+	"              \\\n    if (WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {      \\\n      ret_error_message =                                                \\\n          \"wuffs_aux::DecodeJson: internal error: bad WORKBUF_LEN\";      \\\n      goto done;                                                         \\\n    }                                                                    \\\n    wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();        \\\n    tok_status = dec->decode_tokens(&tok_buf, io_buf, work_buf);         \\\n  }                                                                      \\\n  wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++];         \\\n  uint64_t token_len = token.length();                                   \\\n  if ((io_buf->meta.ri < cursor_index) ||                                \\\n      ((io_buf->meta.ri - cursor_index) < token_len)) {                  \\\n    ret_error_message =                                                  \\\n        \"wuffs_aux::DecodeJson: i" +
+	"nternal error: bad token indexes\";      \\\n    goto done;                                                           \\\n  }                                                                      \\\n  uint8_t* token_ptr = io_buf->data.ptr + cursor_index;                  \\\n  cursor_index += token_len\n\nnamespace {\n\n// DecodeJson_SplitJsonPointer returns (\"bar\", 8) for (\"/foo/bar/baz/qux\", 5).\n// It returns a 0 size_t when s has invalid JSON Pointer syntax.\nstd::pair<std::string, size_t>  //\nDecodeJson_SplitJsonPointer(std::string& s, size_t i) {\n  std::string fragment;\n  while (i < s.size()) {\n    char c = s[i];\n    if (c == '/') {\n      break;\n    } else if (c != '~') {\n      fragment.push_back(c);\n      i++;\n      continue;\n    }\n    i++;\n    if (i >= s.size()) {\n      return std::make_pair(std::string(), 0);\n    }\n    c = s[i];\n    if (c == '0') {\n      fragment.push_back('~');\n      i++;\n      continue;\n    } else if (c == '1') {\n      fragment.push_back('/');\n      i++;\n      continue;\n    }\n    return std::make" +
+	"_pair(std::string(), 0);\n  }\n  return std::make_pair(std::move(fragment), i);\n}\n\nstd::string  //\nDecodeJson_DecodeBackslashX(std::string& str,\n                            uint8_t* token_ptr,\n                            size_t token_len) {\n  wuffs_base__slice_u8 encoded =\n      wuffs_base__make_slice_u8(token_ptr, token_len);\n  while (encoded.len > 0) {\n    uint8_t decoded[64];\n    constexpr bool src_closed = true;\n    wuffs_base__transform__output o = wuffs_base__base_16__decode4(\n        wuffs_base__make_slice_u8(&decoded[0], sizeof decoded), encoded,\n        src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);\n    if (o.status.is_error()) {\n      return o.status.message();\n    } else if ((o.num_dst > (sizeof decoded)) || (o.num_src > encoded.len)) {\n      return \"wuffs_aux::DecodeJson: internal error: inconsistent base16 \"\n             \"decoding\";\n    }\n    str.append(  // Convert from (uint8_t*).\n        static_cast<const char*>(static_cast<void*>(&decoded[0])), o.num_dst);\n    encoded.ptr += o.num_src;\n    " +
+	"encoded.len -= o.num_src;\n  }\n  return \"\";\n}\n\nstd::string  //\nDecodeJson_WalkJsonPointerFragment(wuffs_base__token_buffer& tok_buf,\n                                   wuffs_base__status& tok_status,\n                                   wuffs_json__decoder::unique_ptr& dec,\n                                   wuffs_base__io_buffer* io_buf,\n                                   std::string& io_error_message,\n                                   size_t& cursor_index,\n                                   sync_io::Input& input,\n                                   std::string& json_pointer_fragment) {\n  std::string ret_error_message;\n  while (true) {\n    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;\n\n    int64_t vbc = token.value_base_category();\n    uint64_t vbd = token.value_base_detail();\n    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {\n      continue;\n    } else if ((vbc != WUFFS_BASE__TOKEN__VBC__STRUCTURE) ||\n               !(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)) {\n      return DecodeJson_NoMatch;\n    } else if " +
+	"(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST) {\n      goto do_list;\n    }\n    goto do_dict;\n  }\n\ndo_dict:\n  // Alternate between these two things:\n  //  1. Decode the next dict key (a string). If it matches the fragment, we're\n  //    done (success). If we've reached the dict's end (VBD__STRUCTURE__POP)\n  //    so that there was no next dict key, we're done (failure).\n  //  2. Otherwise, skip the next dict value.\n  while (true) {\n    for (std::string str; true;) {\n      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;\n\n      int64_t vbc = token.value_base_category();\n      uint64_t vbd = token.value_base_detail();\n      switch (vbc) {\n        case WUFFS_BASE__TOKEN__VBC__FILLER:\n          continue;\n\n        case WUFFS_BASE__TOKEN__VBC__STRUCTURE:\n          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {\n            goto fail;\n          }\n          return DecodeJson_NoMatch;\n\n        case WUFFS_BASE__TOKEN__VBC__STRING: {\n          if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {\n    " +
+	"        // No-op.\n          } else if (vbd &\n                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {\n            const char* ptr =  // Convert from (uint8_t*).\n                static_cast<const char*>(static_cast<void*>(token_ptr));\n            str.append(ptr, token_len);\n          } else if (\n              vbd &\n              WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {\n            ret_error_message =\n                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);\n            if (!ret_error_message.empty()) {\n              goto done;\n            }\n          } else {\n            goto fail;\n          }\n          break;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {\n          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];\n          size_t n = wuffs_base__utf_8__encode(\n              wuffs_base__make_slice_u8(\n                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),\n              static_cast<uint32_t>(vbd));\n          " +
+	"const char* ptr =  // Convert from (uint8_t*).\n              static_cast<const char*>(static_cast<void*>(&u[0]));\n          str.append(ptr, n);\n          break;\n        }\n\n        default:\n          goto fail;\n      }\n\n      if (token.continued()) {\n        continue;\n      }\n      if (str == json_pointer_fragment) {\n        return \"\";\n      }\n      goto skip_the_next_dict_value;\n    }\n\n  skip_the_next_dict_value:\n    for (uint32_t skip_depth = 0; true;) {\n      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;\n\n      int64_t vbc = token.value_base_category();\n      uint64_t vbd = token.value_base_detail();\n      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {\n        continue;\n      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {\n        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {\n          skip_depth++;\n          continue;\n        }\n        skip_depth--;\n      }\n\n      if (skip_depth == 0) {\n        break;\n      }\n    }  // skip_the_next_dict_value\n  }    // do_dict\n\ndo_list:\n  " +
+	"do {\n    wuffs_base__result_u64 result_u64 = wuffs_base__parse_number_u64(\n        wuffs_base__make_slice_u8(\n            static_cast<uint8_t*>(static_cast<void*>(\n                const_cast<char*>(json_pointer_fragment.data()))),\n            json_pointer_fragment.size()),\n        WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);\n    if (!result_u64.status.is_ok()) {\n      return DecodeJson_NoMatch;\n    }\n    uint64_t remaining = result_u64.value;\n    if (remaining == 0) {\n      goto check_that_a_value_follows;\n    }\n    for (uint32_t skip_depth = 0; true;) {\n      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;\n\n      int64_t vbc = token.value_base_category();\n      uint64_t vbd = token.value_base_detail();\n      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {\n        continue;\n      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {\n        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {\n          skip_depth++;\n          continue;\n        }\n        if (skip_depth == 0) {\n          ret" +
+	"urn DecodeJson_NoMatch;\n        }\n        skip_depth--;\n      }\n\n      if (skip_depth > 0) {\n        continue;\n      }\n      remaining--;\n      if (remaining == 0) {\n        goto check_that_a_value_follows;\n      }\n    }\n  } while (false);  // do_list\n\ncheck_that_a_value_follows:\n  while (true) {\n    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;\n\n    int64_t vbc = token.value_base_category();\n    uint64_t vbd = token.value_base_detail();\n    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {\n      continue;\n    }\n\n    // Undo the last part of WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN, so that\n    // we're only peeking at the next token.\n    tok_buf.meta.ri--;\n    cursor_index -= token_len;\n\n    if ((vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) &&\n        (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP)) {\n      return DecodeJson_NoMatch;\n    }\n    return \"\";\n  }  // check_that_a_value_follows\n\nfail:\n  return \"wuffs_aux::DecodeJson: internal error: unexpected token\";\ndone:\n  return ret_error_message;\n}\n\n}  // namespace\n\nD" +
+	"ecodeJsonResult  //\nDecodeJson(DecodeJsonCallbacks&& callbacks,\n           sync_io::Input&& input,\n           wuffs_base__slice_u32 quirks,\n           std::string json_pointer) {\n  // Prepare the wuffs_base__io_buffer and the resultant error_message.\n  wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();\n  wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();\n  std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);\n  if (!io_buf) {\n    fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);\n    fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);\n    io_buf = &fallback_io_buf;\n  }\n  size_t cursor_index = 0;\n  std::string ret_error_message;\n  std::string io_error_message;\n\n  do {\n    // Prepare the low-level JSON decoder.\n    wuffs_json__decoder::unique_ptr dec = wuffs_json__decoder::alloc();\n    if (!dec) {\n      ret_error_message = \"wuffs_aux::DecodeJson: out of memory\";\n      goto done;\n    }\n    for (size_t i = 0; i < quirks.len; i++) {\n      dec" +
+	"->set_quirk_enabled(quirks.ptr[i], true);\n    }\n\n    // Prepare the wuffs_base__tok_buffer.\n    wuffs_base__token tok_array[256];\n    wuffs_base__token_buffer tok_buf =\n        wuffs_base__slice_token__writer(wuffs_base__make_slice_token(\n            &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));\n    wuffs_base__status tok_status = wuffs_base__make_status(nullptr);\n\n    // Prepare other state.\n    uint32_t depth = 0;\n    std::string str;\n\n    // Walk the (optional) JSON Pointer.\n    for (size_t i = 0; i < json_pointer.size();) {\n      if (json_pointer[i] != '/') {\n        ret_error_message = DecodeJson_BadJsonPointer;\n        goto done;\n      }\n      std::pair<std::string, size_t> split =\n          DecodeJson_SplitJsonPointer(json_pointer, i + 1);\n      i = std::move(split.second);\n      if (i == 0) {\n        ret_error_message = DecodeJson_BadJsonPointer;\n        goto done;\n      }\n      ret_error_message = DecodeJson_WalkJsonPointerFragment(\n          tok_buf, tok_status, dec, io_buf, io_error_" +
+	"message, cursor_index,\n          input, split.first);\n      if (!ret_error_message.empty()) {\n        goto done;\n      }\n    }\n\n    // Loop, doing these two things:\n    //  1. Get the next token.\n    //  2. Process that token.\n    while (true) {\n      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;\n\n      int64_t vbc = token.value_base_category();\n      uint64_t vbd = token.value_base_detail();\n      switch (vbc) {\n        case WUFFS_BASE__TOKEN__VBC__FILLER:\n          continue;\n\n        case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {\n          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {\n            ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));\n            if (!ret_error_message.empty()) {\n              goto done;\n            }\n            depth++;\n            continue;\n          }\n          ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));\n          depth--;\n          goto parsed_a_value;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__STRING: {\n          if (vbd & WUFFS_BASE__T" +
+	"OKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {\n            // No-op.\n          } else if (vbd &\n                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {\n            const char* ptr =  // Convert from (uint8_t*).\n                static_cast<const char*>(static_cast<void*>(token_ptr));\n            str.append(ptr, token_len);\n          } else if (\n              vbd &\n              WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {\n            ret_error_message =\n                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);\n            if (!ret_error_message.empty()) {\n              goto done;\n            }\n          } else {\n            goto fail;\n          }\n          if (token.continued()) {\n            continue;\n          }\n          ret_error_message =\n              (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8)\n                  ? callbacks.AppendTextString(std::move(str))\n                  : callbacks.AppendByteString(std::move(str));\n         " +
+	" str.clear();\n          goto parsed_a_value;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {\n          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];\n          size_t n = wuffs_base__utf_8__encode(\n              wuffs_base__make_slice_u8(\n                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),\n              static_cast<uint32_t>(vbd));\n          const char* ptr =  // Convert from (uint8_t*).\n              static_cast<const char*>(static_cast<void*>(&u[0]));\n          str.append(ptr, n);\n          if (token.continued()) {\n            continue;\n          }\n          goto fail;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__LITERAL: {\n          ret_error_message =\n              (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL)\n                  ? callbacks.AppendNull()\n                  : callbacks.AppendBool(vbd &\n                                         WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);\n          goto parsed_a_value;\n        }\n\n        case WUFFS_BASE__TOKEN__VBC__NUM" +
+	"BER: {\n          if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {\n            if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED) {\n              wuffs_base__result_i64 r = wuffs_base__parse_number_i64(\n                  wuffs_base__make_slice_u8(token_ptr, token_len),\n                  WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);\n              if (r.status.is_ok()) {\n                ret_error_message = callbacks.AppendI64(r.value);\n                goto parsed_a_value;\n              }\n            }\n            if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT) {\n              wuffs_base__result_f64 r = wuffs_base__parse_number_f64(\n                  wuffs_base__make_slice_u8(token_ptr, token_len),\n                  WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);\n              if (r.status.is_ok()) {\n                ret_error_message = callbacks.AppendF64(r.value);\n                goto parsed_a_value;\n              }\n            }\n          } else if (vbd & WUFFS_BASE__T" +
+	"OKEN__VBD__NUMBER__CONTENT_NEG_INF) {\n            ret_error_message = callbacks.AppendF64(\n                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n                    0xFFF0000000000000ul));\n            goto parsed_a_value;\n          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF) {\n            ret_error_message = callbacks.AppendF64(\n                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n                    0x7FF0000000000000ul));\n            goto parsed_a_value;\n          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN) {\n            ret_error_message = callbacks.AppendF64(\n                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n                    0xFFFFFFFFFFFFFFFFul));\n            goto parsed_a_value;\n          } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN) {\n            ret_error_message = callbacks.AppendF64(\n                wuffs_base__ieee_754_bit_representation__from_u64_to_f64(\n             " +
+	"       0x7FFFFFFFFFFFFFFFul));\n            goto parsed_a_value;\n          }\n          goto fail;\n        }\n      }\n\n    fail:\n      ret_error_message =\n          \"wuffs_aux::DecodeJson: internal error: unexpected token\";\n      goto done;\n\n    parsed_a_value:\n      if (!ret_error_message.empty() || (depth == 0)) {\n        goto done;\n      }\n    }\n  } while (false);\n\ndone:\n  DecodeJsonResult result(\n      std::move(ret_error_message),\n      wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));\n  callbacks.Done(result, input, *io_buf);\n  return result;\n}\n\n#undef WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN\n\n}  // namespace wuffs_aux\n\n#endif  // !defined(WUFFS_CONFIG__MODULES) ||\n        // defined(WUFFS_CONFIG__MODULE__AUX__JSON)\n" +
 	""
 
 const AuxJsonHh = "" +
 	"// ---------------- Auxiliary - JSON\n\nnamespace wuffs_aux {\n\nstruct DecodeJsonResult {\n  DecodeJsonResult(std::string&& error_message0, uint64_t cursor_position0);\n\n  std::string error_message;\n  uint64_t cursor_position;\n};\n\nclass DecodeJsonCallbacks {\n public:\n  // AppendXxx are called for leaf nodes: literals, numbers and strings. For\n  // strings, the Callbacks implementation is responsible for tracking map keys\n  // versus other values.\n\n  // The JSON file format as specified deals only with (UTF-8) text strings,\n  // but an unofficial extension allows \"ijk\\x89m\" escapes within those\n  // strings. DecodeJsonCallbacks' AppendByteString will not be called unless\n  // WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_BYTES is passed to DecodeJson. If\n  // it is passed, AppendTextString will not be called and all byte strings are\n  // potentially invalid UTF-8. It is up to the AppendByteString implementation\n  // whether to test the std::string for UTF-8 validity.\n  //\n  // The default AppendByteString implementation r" +
 	"eturns an error message.\n\n  virtual std::string AppendNull() = 0;\n  virtual std::string AppendBool(bool val) = 0;\n  virtual std::string AppendF64(double val) = 0;\n  virtual std::string AppendI64(int64_t val) = 0;\n  virtual std::string AppendByteString(std::string&& val);\n  virtual std::string AppendTextString(std::string&& val) = 0;\n\n  // Push and Pop are called for container nodes: JSON arrays (lists) and JSON\n  // objects (dictionaries).\n  //\n  // The flags bits combine exactly one of:\n  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE\n  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST\n  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT\n  // and exactly one of:\n  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE\n  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST\n  //  - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT\n\n  virtual std::string Push(uint32_t flags) = 0;\n  virtual std::string Pop(uint32_t flags) = 0;\n\n  // Done is always the last Callback method called by DecodeJson, whether or\n  // not parsing th" +
-	"e input as JSON encountered an error. Even when successful,\n  // trailing data may remain in input and buffer. See \"Unintuitive JSON\n  // Parsing\" (https://nullprogram.com/blog/2019/12/28/) which discusses JSON\n  // parsing and when it stops.\n  //\n  // Do not keep a reference to buffer or buffer.data.ptr after Done returns,\n  // as DecodeJson may then de-allocate the backing array.\n  //\n  // The default Done implementation is a no-op.\n  virtual void Done(DecodeJsonResult& result,\n                    sync_io::Input& input,\n                    IOBuffer& buffer);\n};\n\n// DecodeJson calls callbacks based on the JSON-formatted data in input.\n//\n// On success, the returned error_message is empty and cursor_position counts\n// the number of bytes consumed. On failure, error_message is non-empty and\n// cursor_position is the location of the error. That error may be a content\n// error (invalid JSON) or an input error (e.g. network failure).\nDecodeJsonResult DecodeJson(\n    DecodeJsonCallbacks&& callbacks,\n    sync_io::I" +
-	"nput&& input,\n    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32());\n\n}  // namespace wuffs_aux\n" +
+	"e input as JSON encountered an error. Even when successful,\n  // trailing data may remain in input and buffer. See \"Unintuitive JSON\n  // Parsing\" (https://nullprogram.com/blog/2019/12/28/) which discusses JSON\n  // parsing and when it stops.\n  //\n  // Do not keep a reference to buffer or buffer.data.ptr after Done returns,\n  // as DecodeJson may then de-allocate the backing array.\n  //\n  // The default Done implementation is a no-op.\n  virtual void Done(DecodeJsonResult& result,\n                    sync_io::Input& input,\n                    IOBuffer& buffer);\n};\n\nextern const char DecodeJson_BadJsonPointer[];\nextern const char DecodeJson_NoMatch[];\n\n// DecodeJson calls callbacks based on the JSON-formatted data in input.\n//\n// On success, the returned error_message is empty and cursor_position counts\n// the number of bytes consumed. On failure, error_message is non-empty and\n// cursor_position is the location of the error. That error may be a content\n// error (invalid JSON) or an input error (e.g. network fa" +
+	"ilure).\n//\n// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks\n// run for the input's sub-node that matches the query. DecodeJson_NoMatch is\n// returned if no matching sub-node was found. The empty query matches the\n// input's root node, consistent with JSON Pointer semantics.\n//\n// The JSON Pointer implementation is greedy: duplicate keys are not rejected\n// but only the first match for each '/'-separated fragment is followed.\nDecodeJsonResult DecodeJson(\n    DecodeJsonCallbacks&& callbacks,\n    sync_io::Input&& input,\n    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32(),\n    std::string json_pointer = std::string());\n\n}  // namespace wuffs_aux\n" +
 	""
 
 var AuxNonBaseCcFiles = []string{
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 80f5875..6e58bbc 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -8604,16 +8604,28 @@
                     IOBuffer& buffer);
 };
 
+extern const char DecodeJson_BadJsonPointer[];
+extern const char DecodeJson_NoMatch[];
+
 // DecodeJson calls callbacks based on the JSON-formatted data in input.
 //
 // On success, the returned error_message is empty and cursor_position counts
 // the number of bytes consumed. On failure, error_message is non-empty and
 // cursor_position is the location of the error. That error may be a content
 // error (invalid JSON) or an input error (e.g. network failure).
+//
+// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks
+// run for the input's sub-node that matches the query. DecodeJson_NoMatch is
+// returned if no matching sub-node was found. The empty query matches the
+// input's root node, consistent with JSON Pointer semantics.
+//
+// The JSON Pointer implementation is greedy: duplicate keys are not rejected
+// but only the first match for each '/'-separated fragment is followed.
 DecodeJsonResult DecodeJson(
     DecodeJsonCallbacks&& callbacks,
     sync_io::Input&& input,
-    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32());
+    wuffs_base__slice_u32 quirks = wuffs_base__empty_slice_u32(),
+    std::string json_pointer = std::string());
 
 }  // namespace wuffs_aux
 
@@ -29355,7 +29367,7 @@
 
 std::string  //
 DecodeJsonCallbacks::AppendByteString(std::string&& val) {
-  return "wuffs_aux::JsonDecoder: unexpected JSON byte string";
+  return "wuffs_aux::DecodeJson: unexpected JSON byte string";
 }
 
 void  //
@@ -29363,6 +29375,10 @@
                           sync_io::Input& input,
                           IOBuffer& buffer) {}
 
+const char DecodeJson_BadJsonPointer[] =
+    "wuffs_aux::DecodeJson: bad JSON Pointer";
+const char DecodeJson_NoMatch[] = "wuffs_aux::DecodeJson: no match";
+
 #define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN                       \
   while (tok_buf.meta.ri >= tok_buf.meta.wi) {                           \
     if (tok_status.repr == nullptr) {                                    \
@@ -29374,17 +29390,17 @@
         goto done;                                                       \
       } else if (cursor_index != io_buf->meta.ri) {                      \
         ret_error_message =                                              \
-            "wuffs_aux::JsonDecoder: internal error: bad cursor_index";  \
+            "wuffs_aux::DecodeJson: internal error: bad cursor_index";   \
         goto done;                                                       \
       } else if (io_buf->meta.closed) {                                  \
         ret_error_message =                                              \
-            "wuffs_aux::JsonDecoder: internal error: io_buf is closed";  \
+            "wuffs_aux::DecodeJson: internal error: io_buf is closed";   \
         goto done;                                                       \
       }                                                                  \
       io_buf->compact();                                                 \
       if (io_buf->meta.wi >= io_buf->data.len) {                         \
         ret_error_message =                                              \
-            "wuffs_aux::JsonDecoder: internal error: io_buf is full";    \
+            "wuffs_aux::DecodeJson: internal error: io_buf is full";     \
         goto done;                                                       \
       }                                                                  \
       cursor_index = io_buf->meta.ri;                                    \
@@ -29395,7 +29411,7 @@
     }                                                                    \
     if (WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {      \
       ret_error_message =                                                \
-          "wuffs_aux::JsonDecoder: internal error: bad WORKBUF_LEN";     \
+          "wuffs_aux::DecodeJson: internal error: bad WORKBUF_LEN";      \
       goto done;                                                         \
     }                                                                    \
     wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();        \
@@ -29406,16 +29422,268 @@
   if ((io_buf->meta.ri < cursor_index) ||                                \
       ((io_buf->meta.ri - cursor_index) < token_len)) {                  \
     ret_error_message =                                                  \
-        "wuffs_aux::JsonDecoder: internal error: bad token indexes";     \
+        "wuffs_aux::DecodeJson: internal error: bad token indexes";      \
     goto done;                                                           \
   }                                                                      \
   uint8_t* token_ptr = io_buf->data.ptr + cursor_index;                  \
   cursor_index += token_len
 
+namespace {
+
+// DecodeJson_SplitJsonPointer returns ("bar", 8) for ("/foo/bar/baz/qux", 5).
+// It returns a 0 size_t when s has invalid JSON Pointer syntax.
+std::pair<std::string, size_t>  //
+DecodeJson_SplitJsonPointer(std::string& s, size_t i) {
+  std::string fragment;
+  while (i < s.size()) {
+    char c = s[i];
+    if (c == '/') {
+      break;
+    } else if (c != '~') {
+      fragment.push_back(c);
+      i++;
+      continue;
+    }
+    i++;
+    if (i >= s.size()) {
+      return std::make_pair(std::string(), 0);
+    }
+    c = s[i];
+    if (c == '0') {
+      fragment.push_back('~');
+      i++;
+      continue;
+    } else if (c == '1') {
+      fragment.push_back('/');
+      i++;
+      continue;
+    }
+    return std::make_pair(std::string(), 0);
+  }
+  return std::make_pair(std::move(fragment), i);
+}
+
+std::string  //
+DecodeJson_DecodeBackslashX(std::string& str,
+                            uint8_t* token_ptr,
+                            size_t token_len) {
+  wuffs_base__slice_u8 encoded =
+      wuffs_base__make_slice_u8(token_ptr, token_len);
+  while (encoded.len > 0) {
+    uint8_t decoded[64];
+    constexpr bool src_closed = true;
+    wuffs_base__transform__output o = wuffs_base__base_16__decode4(
+        wuffs_base__make_slice_u8(&decoded[0], sizeof decoded), encoded,
+        src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
+    if (o.status.is_error()) {
+      return o.status.message();
+    } else if ((o.num_dst > (sizeof decoded)) || (o.num_src > encoded.len)) {
+      return "wuffs_aux::DecodeJson: internal error: inconsistent base16 "
+             "decoding";
+    }
+    str.append(  // Convert from (uint8_t*).
+        static_cast<const char*>(static_cast<void*>(&decoded[0])), o.num_dst);
+    encoded.ptr += o.num_src;
+    encoded.len -= o.num_src;
+  }
+  return "";
+}
+
+std::string  //
+DecodeJson_WalkJsonPointerFragment(wuffs_base__token_buffer& tok_buf,
+                                   wuffs_base__status& tok_status,
+                                   wuffs_json__decoder::unique_ptr& dec,
+                                   wuffs_base__io_buffer* io_buf,
+                                   std::string& io_error_message,
+                                   size_t& cursor_index,
+                                   sync_io::Input& input,
+                                   std::string& json_pointer_fragment) {
+  std::string ret_error_message;
+  while (true) {
+    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+    int64_t vbc = token.value_base_category();
+    uint64_t vbd = token.value_base_detail();
+    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
+      continue;
+    } else if ((vbc != WUFFS_BASE__TOKEN__VBC__STRUCTURE) ||
+               !(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)) {
+      return DecodeJson_NoMatch;
+    } else if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST) {
+      goto do_list;
+    }
+    goto do_dict;
+  }
+
+do_dict:
+  // Alternate between these two things:
+  //  1. Decode the next dict key (a string). If it matches the fragment, we're
+  //    done (success). If we've reached the dict's end (VBD__STRUCTURE__POP)
+  //    so that there was no next dict key, we're done (failure).
+  //  2. Otherwise, skip the next dict value.
+  while (true) {
+    for (std::string str; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      switch (vbc) {
+        case WUFFS_BASE__TOKEN__VBC__FILLER:
+          continue;
+
+        case WUFFS_BASE__TOKEN__VBC__STRUCTURE:
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+            goto fail;
+          }
+          return DecodeJson_NoMatch;
+
+        case WUFFS_BASE__TOKEN__VBC__STRING: {
+          if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
+            // No-op.
+          } else if (vbd &
+                     WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
+            const char* ptr =  // Convert from (uint8_t*).
+                static_cast<const char*>(static_cast<void*>(token_ptr));
+            str.append(ptr, token_len);
+          } else if (
+              vbd &
+              WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {
+            ret_error_message =
+                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);
+            if (!ret_error_message.empty()) {
+              goto done;
+            }
+          } else {
+            goto fail;
+          }
+          break;
+        }
+
+        case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
+          uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
+          size_t n = wuffs_base__utf_8__encode(
+              wuffs_base__make_slice_u8(
+                  &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
+              static_cast<uint32_t>(vbd));
+          const char* ptr =  // Convert from (uint8_t*).
+              static_cast<const char*>(static_cast<void*>(&u[0]));
+          str.append(ptr, n);
+          break;
+        }
+
+        default:
+          goto fail;
+      }
+
+      if (token.continued()) {
+        continue;
+      }
+      if (str == json_pointer_fragment) {
+        return "";
+      }
+      goto skip_the_next_dict_value;
+    }
+
+  skip_the_next_dict_value:
+    for (uint32_t skip_depth = 0; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
+        continue;
+      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
+        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+          skip_depth++;
+          continue;
+        }
+        skip_depth--;
+      }
+
+      if (skip_depth == 0) {
+        break;
+      }
+    }  // skip_the_next_dict_value
+  }    // do_dict
+
+do_list:
+  do {
+    wuffs_base__result_u64 result_u64 = wuffs_base__parse_number_u64(
+        wuffs_base__make_slice_u8(
+            static_cast<uint8_t*>(static_cast<void*>(
+                const_cast<char*>(json_pointer_fragment.data()))),
+            json_pointer_fragment.size()),
+        WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
+    if (!result_u64.status.is_ok()) {
+      return DecodeJson_NoMatch;
+    }
+    uint64_t remaining = result_u64.value;
+    if (remaining == 0) {
+      goto check_that_a_value_follows;
+    }
+    for (uint32_t skip_depth = 0; true;) {
+      WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+      int64_t vbc = token.value_base_category();
+      uint64_t vbd = token.value_base_detail();
+      if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
+        continue;
+      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
+        if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
+          skip_depth++;
+          continue;
+        }
+        if (skip_depth == 0) {
+          return DecodeJson_NoMatch;
+        }
+        skip_depth--;
+      }
+
+      if (skip_depth > 0) {
+        continue;
+      }
+      remaining--;
+      if (remaining == 0) {
+        goto check_that_a_value_follows;
+      }
+    }
+  } while (false);  // do_list
+
+check_that_a_value_follows:
+  while (true) {
+    WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
+
+    int64_t vbc = token.value_base_category();
+    uint64_t vbd = token.value_base_detail();
+    if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
+      continue;
+    }
+
+    // Undo the last part of WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN, so that
+    // we're only peeking at the next token.
+    tok_buf.meta.ri--;
+    cursor_index -= token_len;
+
+    if ((vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) &&
+        (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP)) {
+      return DecodeJson_NoMatch;
+    }
+    return "";
+  }  // check_that_a_value_follows
+
+fail:
+  return "wuffs_aux::DecodeJson: internal error: unexpected token";
+done:
+  return ret_error_message;
+}
+
+}  // namespace
+
 DecodeJsonResult  //
 DecodeJson(DecodeJsonCallbacks&& callbacks,
            sync_io::Input&& input,
-           wuffs_base__slice_u32 quirks) {
+           wuffs_base__slice_u32 quirks,
+           std::string json_pointer) {
   // Prepare the wuffs_base__io_buffer and the resultant error_message.
   wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
   wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
@@ -29433,7 +29701,7 @@
     // Prepare the low-level JSON decoder.
     wuffs_json__decoder::unique_ptr dec = wuffs_json__decoder::alloc();
     if (!dec) {
-      ret_error_message = "wuffs_aux::JsonDecoder: out of memory";
+      ret_error_message = "wuffs_aux::DecodeJson: out of memory";
       goto done;
     }
     for (size_t i = 0; i < quirks.len; i++) {
@@ -29451,6 +29719,27 @@
     uint32_t depth = 0;
     std::string str;
 
+    // Walk the (optional) JSON Pointer.
+    for (size_t i = 0; i < json_pointer.size();) {
+      if (json_pointer[i] != '/') {
+        ret_error_message = DecodeJson_BadJsonPointer;
+        goto done;
+      }
+      std::pair<std::string, size_t> split =
+          DecodeJson_SplitJsonPointer(json_pointer, i + 1);
+      i = std::move(split.second);
+      if (i == 0) {
+        ret_error_message = DecodeJson_BadJsonPointer;
+        goto done;
+      }
+      ret_error_message = DecodeJson_WalkJsonPointerFragment(
+          tok_buf, tok_status, dec, io_buf, io_error_message, cursor_index,
+          input, split.first);
+      if (!ret_error_message.empty()) {
+        goto done;
+      }
+    }
+
     // Loop, doing these two things:
     //  1. Get the next token.
     //  2. Process that token.
@@ -29488,29 +29777,10 @@
           } else if (
               vbd &
               WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {
-            wuffs_base__slice_u8 encoded =
-                wuffs_base__make_slice_u8(token_ptr, token_len);
-            while (encoded.len > 0) {
-              uint8_t decoded[64];
-              constexpr bool src_closed = true;
-              wuffs_base__transform__output o = wuffs_base__base_16__decode4(
-                  wuffs_base__make_slice_u8(&decoded[0], sizeof decoded),
-                  encoded, src_closed, WUFFS_BASE__BASE_16__DEFAULT_OPTIONS);
-              if (o.status.is_error()) {
-                ret_error_message = o.status.message();
-                goto done;
-              } else if ((o.num_dst > (sizeof decoded)) ||
-                         (o.num_src > encoded.len)) {
-                ret_error_message =
-                    "wuffs_aux::JsonDecoder: internal error: inconsistent "
-                    "base16 decoding";
-                goto done;
-              }
-              str.append(  // Convert from (uint8_t*).
-                  static_cast<const char*>(static_cast<void*>(&decoded[0])),
-                  o.num_dst);
-              encoded.ptr += o.num_src;
-              encoded.len -= o.num_src;
+            ret_error_message =
+                DecodeJson_DecodeBackslashX(str, token_ptr, token_len);
+            if (!ret_error_message.empty()) {
+              goto done;
             }
           } else {
             goto fail;
@@ -29597,7 +29867,7 @@
 
     fail:
       ret_error_message =
-          "wuffs_aux::JsonDecoder: internal error: unexpected token";
+          "wuffs_aux::DecodeJson: internal error: unexpected token";
       goto done;
 
     parsed_a_value: