All files / src/types/kmx/kmx-plus-builder build-strs.ts

48% Statements 36/75
100% Branches 0/0
0% Functions 0/2
48% Lines 36/75

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 761x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                           1x 1x 1x 1x 1x                                      
import { constants } from "@keymanapp/ldml-keyboard-constants";
import { KMXPlus } from "@keymanapp/common-types";
import { BUILDER_SECTION } from "./builder-section.js";
 
import Strs = KMXPlus.Strs;
import StrsItem = KMXPlus.StrsItem;
 
/** reference from build_strs_index */
export type BUILDER_STR_REF = number;
 
/* ------------------------------------------------------------------
 * strs section
   ------------------------------------------------------------------ */
 
interface BUILDER_STRS_ITEM {
  // While we use length which is number of utf-16 code units excluding null terminator,
  // we always write a null terminator, so we can get restructure to do that for us here
  offset: number; //? new r.Pointer(r.uint32le, new r.String(null, 'utf16le')),
  length: number; // in UTF-16 code units
  _value: string; // in-memory: for finding and sorting
};
 
/**
 * Builder for the 'strs' section
 */
export interface BUILDER_STRS extends BUILDER_SECTION {
  count: number;
  items: BUILDER_STRS_ITEM[];
};
 
export function build_strs(source_strs: Strs): BUILDER_STRS {
  const result: BUILDER_STRS = {
    ident: constants.hex_section_id(constants.section.strs),
    size: 0,  // finalized later
    _offset: 0,
    count: source_strs.strings.length,
    items: [], // filled below
  };

  result.items = source_strs.strings.map(item => { return {_value: item.value, length: item.value.length, offset: 0}; });
  result.items.sort((a,b) => StrsItem.binaryStringCompare(a._value, b._value));

  let offset = constants.length_strs + constants.length_strs_item * result.count;
  // TODO: consider padding
  for(const item of result.items) {
    item.offset = offset;
    offset += item.length * 2 + 2; /* UTF-16 code units + sizeof null terminator */
  }
  result.size = offset;

  return result;
}
 
/**
 * @returns str index, or UTF-32 char if value.char is set (single char)
 */
export function build_strs_index(sect_strs: BUILDER_STRS, value: StrsItem) : BUILDER_STR_REF {
  if(!(value instanceof StrsItem)) {
    if (value === null) {
      throw new Error('unexpected null StrsItem, use an empty string instead');
    } else {
      throw new Error('unexpected StrsItem value '+ value);
    }
  }

  if(value.isOneChar) {
    return <BUILDER_STR_REF>value.char;
  }

  const result = sect_strs.items.findIndex(v => v._value === value.value);
  if(result < 0) {
    throw new Error('unexpectedly missing StrsItem '+value.value);
  }
  return <BUILDER_STR_REF>result;
}