MVMString * MVM_string_decodestream_get_chars(MVMThreadContext *tc, MVMDecodeStream *ds, MVMint32 chars, MVMint64 eof) { MVMint32 missing; /* If we request nothing, give empty string. */ if (chars == 0) return tc->instance->str_consts.empty; /* If we don't already have enough chars, try and decode more. */ missing = missing_chars(tc, ds, chars); ds->result_size_guess = missing; if (missing) run_decode(tc, ds, &missing, NULL, DECODE_NOT_EOF); /* If we've got enough, assemble a string. Otherwise, flag EOF and retry, * falling back to returning what's available. */ if (missing_chars(tc, ds, chars) == 0) { return take_chars(tc, ds, chars, 0); } else if (eof) { reached_eof(tc, ds); return missing_chars(tc, ds, chars) == 0 ? take_chars(tc, ds, chars, 0) : MVM_string_decodestream_get_all(tc, ds); } else { return NULL; } }
MVMString * MVM_string_decodestream_get_until_sep(MVMThreadContext *tc, MVMDecodeStream *ds, MVMDecodeStreamSeparators *sep_spec, MVMint32 chomp) { MVMint32 sep_loc, sep_length; /* Look for separator, trying more decoding if it fails. We get the place * just beyond the separator, so can use take_chars to get what's need. * Note that decoders are only responsible for finding the final char of * the separator, so we may need to loop a few times around this. */ sep_loc = find_separator(tc, ds, sep_spec, &sep_length, 0); while (!sep_loc) { MVMuint32 decode_outcome = run_decode(tc, ds, NULL, sep_spec, DECODE_NOT_EOF); if (decode_outcome == RUN_DECODE_NOTHING_DECODED) break; if (decode_outcome == RUN_DECODE_STOPPER_REACHED) sep_loc = find_separator(tc, ds, sep_spec, &sep_length, 0); } if (sep_loc) { /* Use this line length as a guesstimate of the next, unless it's tiny * in which case we treat it as an outlier (probably an empty line or * some such). Also round up and to a nice power of 2. */ if (sep_loc > 32) ds->result_size_guess = (sep_loc << 1) & ~0xF; return take_chars(tc, ds, sep_loc, chomp ? sep_length : 0); } else { return NULL; } }
MVMString * MVM_string_decodestream_get_until_sep(MVMThreadContext *tc, MVMDecodeStream *ds, MVMGrapheme32 sep) { MVMint32 sep_loc; /* Look for separator, trying more decoding if it fails. We get the place * just beyond the separator, so can use take_chars to get what's need. */ sep_loc = find_separator(tc, ds, sep); if (!sep_loc) { run_decode(tc, ds, NULL, &sep); sep_loc = find_separator(tc, ds, sep); } if (sep_loc) return take_chars(tc, ds, sep_loc); else return NULL; }
/* Variant of MVM_string_decodestream_get_until_sep that is called when we * reach EOF. Trims the final separator if there is one, or returns the last * line without the EOF marker. */ MVMString * MVM_string_decodestream_get_until_sep_eof(MVMThreadContext *tc, MVMDecodeStream *ds, MVMDecodeStreamSeparators *sep_spec, MVMint32 chomp) { MVMint32 sep_loc, sep_length; /* Decode anything remaining and flush normalization buffer. */ reached_eof(tc, ds); /* Look for separator, which should by now be at the end, and chomp it * off if needed. */ sep_loc = find_separator(tc, ds, sep_spec, &sep_length); if (sep_loc) return take_chars(tc, ds, sep_loc, chomp ? sep_length : 0); /* Otherwise, take all remaining chars. */ return MVM_string_decodestream_get_all(tc, ds); }
MVMString * MVM_string_decodestream_get_chars(MVMThreadContext *tc, MVMDecodeStream *ds, MVMint32 chars) { MVMint32 missing; /* If we request nothing, give empty string. */ if (chars == 0) return tc->instance->str_consts.empty; /* If we don't already have enough chars, try and decode more. */ missing = missing_chars(tc, ds, chars); if (missing) run_decode(tc, ds, &missing, NULL); /* If we've got enough, assemble a string. Otherwise, give up. */ if (missing_chars(tc, ds, chars) == 0) return take_chars(tc, ds, chars, 0); else return NULL; }
MVMString * MVM_string_decodestream_get_until_sep(MVMThreadContext *tc, MVMDecodeStream *ds, MVMDecodeStreamSeparators *sep_spec, MVMint32 chomp) { MVMint32 sep_loc, sep_length; /* Look for separator, trying more decoding if it fails. We get the place * just beyond the separator, so can use take_chars to get what's need. * Note that decoders are only responsible for finding the final char of * the separator, so we may need to loop a few times around this. */ sep_loc = find_separator(tc, ds, sep_spec, &sep_length); while (!sep_loc) { if (!run_decode(tc, ds, NULL, sep_spec)) break; sep_loc = find_separator(tc, ds, sep_spec, &sep_length); } if (sep_loc) return take_chars(tc, ds, sep_loc, chomp ? sep_length : 0); else return NULL; }