{
  "__type": "IngestedDoc",
  "__tag": 4010,
  "_content": {},
  "_ordered_sections": [],
  "item_file": null,
  "item_line": null,
  "item_type": null,
  "aliases": [],
  "example_section_data": {
    "__type": "Section",
    "__tag": 4015,
    "children": [],
    "title": [],
    "level": 0,
    "target": null
  },
  "see_also": [],
  "signature": null,
  "references": null,
  "qa": "reference:c-api:strings",
  "arbitrary": [
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "versionadded",
          "base_type": "neutral",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "versionadded 2.0"
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This API allows access to the UTF-8 string data stored in NumPy StringDType arrays. See "
            },
            {
              "__type": "InlineRole",
              "__tag": 4003,
              "value": "NEP-55 <NEP55>",
              "domain": null,
              "role": "ref",
              "inventory": null
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " for more in-depth details into the design of StringDType."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "NpyString API"
        }
      ],
      "level": 0,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Examples"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Say we are writing a ufunc implementation for "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "StringDType"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ". If we are given "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "const char *buf"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " pointer to the beginning of a "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "StringDType"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " array entry, and a "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "PyArray_Descr *"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " pointer to the array descriptor, one can access the underlying string data like so:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "npy_string_allocator *allocator = NpyString_acquire_allocator(\n        (PyArray_StringDTypeObject *)descr);\n\nnpy_static_string sdata = {0, NULL};\nnpy_packed_static_string *packed_string = (npy_packed_static_string *)buf;\nint is_null = 0;\n\nis_null = NpyString_load(allocator, packed_string, &sdata);\n\nif (is_null == -1) {\n    // failed to load string, set error\n    return -1;\n}\nelse if (is_null) {\n    // handle missing string\n    // sdata->buf is NULL\n    // sdata->size is 0\n}\nelse {\n    // sdata->buf is a pointer to the beginning of a string\n    // sdata->size is the size of the string\n}\nNpyString_release_allocator(allocator);",
          "execution_status": null
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Loading a String"
        }
      ],
      "level": 2,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "This example shows how to pack a new string entry into an array:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "char *str = \"Hello world\";\nsize_t size = 11;\nnpy_packed_static_string *packed_string = (npy_packed_static_string *)buf;\n\nnpy_string_allocator *allocator = NpyString_acquire_allocator(\n        (PyArray_StringDTypeObject *)descr);\n\n// copy contents of str into packed_string\nif (NpyString_pack(allocator, packed_string, str, size) == -1) {\n    // string packing failed, set error\n    return -1;\n}\n\n// packed_string contains a copy of \"Hello world\"\n\nNpyString_release_allocator(allocator);",
          "execution_status": null
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Packing a String"
        }
      ],
      "level": 2,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Types"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Blockquote",
          "__tag": 4059,
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Acquire the mutex locking the allocator attached to      "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "descr"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": ". "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "NpyString_release_allocator"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " must be called on the allocator      returned by this function exactly once. Note that functions requiring the      GIL should not be called while the allocator mutex is held, as doing so may      cause deadlocks."
                }
              ]
            }
          ]
        },
        {
          "__type": "Blockquote",
          "__tag": 4059,
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Simultaneously acquire the mutexes locking the allocators attached to      multiple descriptors. Writes a pointer to the associated allocator in the      allocators array for each StringDType descriptor in the array. If any of      the descriptors are not StringDType instances, write NULL to the allocators      array for that entry."
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "n_descriptors"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " is the number of descriptors in the descrs array that      should be examined. Any descriptor after "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "n_descriptors"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " elements is      ignored. A buffer overflow will happen if the "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "descrs"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " array does not      contain n_descriptors elements."
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "If pointers to the same descriptor are passed multiple times, only acquires      the allocator mutex once but sets identical allocator pointers appropriately.      The allocator mutexes must be released after this function returns, see      "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "NpyString_release_allocators"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "."
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Note that functions requiring the GIL should not be called while the      allocator mutex is held, as doing so may cause deadlocks."
                }
              ]
            }
          ]
        },
        {
          "__type": "Blockquote",
          "__tag": 4059,
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Release the mutex locking an allocator. This must be called exactly once      after acquiring the allocator mutex and all operations requiring the      allocator are done."
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "If you need to release multiple allocators, see      NpyString_release_allocators, which can correctly handle releasing the      allocator once when given several references to the same allocator."
                }
              ]
            }
          ]
        },
        {
          "__type": "Blockquote",
          "__tag": 4059,
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Release the mutexes locking N allocators. "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "length"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " is the length of the      allocators array. NULL entries are ignored."
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "If pointers to the same allocator are passed multiple times, only releases      the allocator mutex once."
                }
              ]
            }
          ]
        },
        {
          "__type": "Blockquote",
          "__tag": 4059,
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Extract the packed contents of "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "packed_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " into "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "unpacked_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "."
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "The "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "unpacked_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " is a read-only view onto the "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "packed_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " data      and should not be used to modify the string data. If "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "packed_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " is      the null string, sets "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "unpacked_string.buf"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " to the NULL      pointer. Returns -1 if unpacking the string fails, returns 1 if      "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "packed_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " is the null string, and returns 0 otherwise."
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "A useful pattern is to define a stack-allocated npy_static_string instance      initialized to "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "{0, NULL}"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " and pass a pointer to the stack-allocated      unpacked string to this function.  This function can be used to      simultaneously unpack a string and determine if it is a null string."
                }
              ]
            }
          ]
        },
        {
          "__type": "Blockquote",
          "__tag": 4059,
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Pack the null string into "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "packed_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": ". Returns 0 on success and -1 on    failure."
                }
              ]
            }
          ]
        },
        {
          "__type": "Blockquote",
          "__tag": 4059,
          "children": [
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "Copy and pack the first "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "size"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " entries of the buffer pointed to by "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "buf"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "    into the "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "packed_string"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": ". Returns 0 on success and -1 on failure."
                }
              ]
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Functions"
        }
      ],
      "level": 1,
      "target": null
    }
  ],
  "local_refs": []
}