---
title: sto_subfield
description: >-
  Index into a xahaud serialized object and return the location and length of a
  subfield
---
import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components';

### Concepts

<LinkButton href="/docs/hooks/concepts/serialized-objects">Serialized Objects</LinkButton>

### Behaviour

<Tabs>
<TabItem label="C">
* Parse a STObject pointed to by `read_ptr`
* Find the field specified by `field_id`
* If the field is found, and:
*
  1. It is an array, then return the start and length of the array including the leadin/leadout bytes, or
*
  2. It is **not** an array, then return the start and length of the PAYLOAD of the field (excluding the leadin bytes).

<Aside type="caution" title="Field ID encoding">
The `sto_` apis accept a `field_id` parameter encoded as follows: `(type << 16U) + field`
Thus type 1 field 2 would be `0x10002U`.
</Aside>
</TabItem>

<TabItem label="JavaScript">
* Parse a STObject into `sto` variable
* Find the field specified by `field_id`
</TabItem>
</Tabs>



### Definition

<Tabs>
<TabItem label="C">
```c
int64_t sto_subfield (
    uint32_t read_ptr,
    uint32_t read_len,
    uint32_t field_id
);
```


</TabItem>

<TabItem label="JavaScript">
```javascript
function sto_subfield(
    sto: ByteArray | HexString,
    field_id: number
  ): ErrorCode | bigint
```
</TabItem>
</Tabs>



### Example

<Tabs>
<TabItem label="C">
```c
#define SUB_OFFSET(x) ((int32_t)(x >> 32))
#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL))
int64_t memos_lookup =
    sto_subfield(txn_ptr, txn_len, sfMemos);
if (memos_lookup < 0)
{
    // sfMemos was not found in the STObject pointed at by memo_ptr
}
else
{
    // sfMemos was found and its location is as follows:
    uint8_t* memos_ptr = SUB_OFFSET(memos_lookup) + memos_ptr;
    int64_t  memos_len = SUB_LENGTH(memos_lookup);
}
```

<Aside type="tip">
hookmacro.h already contains the `SUB_OFFSET` and `SUB_LENGTH` macros.
</Aside>
</TabItem>

<TabItem label="JavaScript">
```javascript
const SUB_OFFSET = (x) => Number(x >> 32n)
const SUB_LENGTH = (x) => Number(x & 0xFFFFFFFFn)
const memos_lookup = sto_subfield(txn, sfMemos);
if (typeof memos_lookup === 'number')
{
    // sfMemos was not found in the STObject pointed at by memo_ptr
}
else
{
    // sfMemos was found and its location is as follows:
    const memo_start = SUB_OFFSET(memos_lookup)
    const memo_len = SUB_LENGTH(memos_lookup)
    const memo = txn.slice(memo_start, memo_len)
}
```
</TabItem>
</Tabs>



### Parameters

<Tabs>
<TabItem label="C">
| Name      | Type      | Description                                                                                                                                                                                                                                                                                                                                                                                                |
| --------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| read_ptr | uint32_t | Pointer to the buffer containing the STObject                                                                                                                                                                                                                                                                                                                                                              |
| read_len | uint32_t | Length of STObject                                                                                                                                                                                                                                                                                                                                                                                         |
| field_id | uint32_t | <p>The <code>sf</code> code of the field you are searching for.<br /><br />To compute this manually take the serialized <code>type</code> and shift it into the 16 highest bits of uint32_t, then take the <code>field</code> and place it in the 16 lowest bits.<br /><br />For example:<br /><code>sfEmitNonce</code> has <code>type</code> 5 and <code>field</code> 11 thus its value is <code>0x050BU</code></p> |


</TabItem>

<TabItem label="JavaScript">


| Name      | Type                   | Description                                                                     |
| --------- | ---------------------- | ------------------------------------------------------------------------------- |
| sto       | ByteArray or HexString | The STO object (binary encoded ledger data) from which to extract the subfield. |
| field_id | number                 | The ID of the field to be extracted.                                            |
</TabItem>
</Tabs>



### Return Code

<Tabs>
<TabItem label="C">
| Type     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| -------- |   |
| int64_t | <p>The location of the field within the specified buffer:<br />- The high 32 bits are the offset location.<br />- The low 32 bits are the length.<br /><br />If negative, an error:<br /><code>OUT_OF_BOUNDS</code><br />- pointers/lengths specified outside of hook memory.<br /><br /><code>TOO_SMALL</code><br />- Input buffer isn't large enough to possibly contain a valid STObject.<br /><br /><code>DOESNT_EXIST</code><br />- The searched for field isn't present in the supplied STObject.<br /><br /><code>PARSE_ERROR</code><br />- The supplied STObject is malformed or not an STObject.</p> |


</TabItem>

<TabItem label="JavaScript">


| Type               | Description                                                                                                                                                                                              |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| bigint / ErrorCode | <p>The location of the field within the specified buffer:<br />- The high 32 bits are the offset location.<br />- The low 32 bits are the length.</p><p></p><p>or an error code if the extraction fails.</p> |
</TabItem>
</Tabs>

