| 5135 | } |
| 5136 | |
| 5137 | static ssize_t |
| 5138 | xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip, |
| 5139 | const char *value, ssize_t vlen) |
| 5140 | { |
| 5141 | const char *fmt = xfip->xfi_format; |
| 5142 | ssize_t flen = xfip->xfi_flen; |
| 5143 | |
| 5144 | long width = 0; |
| 5145 | char *bp; |
| 5146 | char *cp; |
| 5147 | |
| 5148 | if (vlen) { |
| 5149 | bp = alloca(vlen + 1); /* Make local NUL-terminated copy of value */ |
| 5150 | memcpy(bp, value, vlen); |
| 5151 | bp[vlen] = '\0'; |
| 5152 | |
| 5153 | width = strtol(bp, &cp, 0); |
| 5154 | if (width == LONG_MIN || width == LONG_MAX || bp == cp || *cp != '\0') { |
| 5155 | width = 0; |
| 5156 | xo_failure(xop, "invalid width for anchor: '%s'", bp); |
| 5157 | } |
| 5158 | } else if (flen) { |
| 5159 | /* |
| 5160 | * We really expect the format for width to be "{:/%d}" or |
| 5161 | * "{:/%u}", so if that's the case, we just grab our width off |
| 5162 | * the argument list. But we need to avoid optimized logic if |
| 5163 | * there's a custom formatter. |
| 5164 | */ |
| 5165 | if (xop->xo_formatter == NULL && flen == 2 |
| 5166 | && strncmp("%d", fmt, flen) == 0) { |
| 5167 | if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) |
| 5168 | width = va_arg(xop->xo_vap, int); |
| 5169 | } else if (xop->xo_formatter == NULL && flen == 2 |
| 5170 | && strncmp("%u", fmt, flen) == 0) { |
| 5171 | if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) |
| 5172 | width = va_arg(xop->xo_vap, unsigned); |
| 5173 | } else { |
| 5174 | /* |
| 5175 | * So we have a format and it's not a simple one like |
| 5176 | * "{:/%d}". That means we need to format the field, |
| 5177 | * extract the value from the formatted output, and then |
| 5178 | * discard that output. |
| 5179 | */ |
| 5180 | int anchor_was_set = FALSE; |
| 5181 | xo_buffer_t *xbp = &xop->xo_data; |
| 5182 | ssize_t start_offset = xo_buf_offset(xbp); |
| 5183 | bp = xo_buf_cur(xbp); /* Save start of the string */ |
| 5184 | cp = NULL; |
| 5185 | |
| 5186 | if (XOIF_ISSET(xop, XOIF_ANCHOR)) { |
| 5187 | XOIF_CLEAR(xop, XOIF_ANCHOR); |
| 5188 | anchor_was_set = TRUE; |
| 5189 | } |
| 5190 | |
| 5191 | ssize_t rc = xo_do_format_field(xop, xbp, fmt, flen, 0); |
| 5192 | if (rc >= 0) { |
| 5193 | xo_buf_append(xbp, "", 1); /* Append a NUL */ |
| 5194 |
no test coverage detected