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

46.15% Statements 48/104
100% Branches 0/0
0% Functions 0/2
46.15% Lines 48/104

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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 1051x 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 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 { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js";
import { BUILDER_SECTION } from "./builder-section.js";
 
import List = KMXPlus.List;
import ListItem = KMXPlus.ListItem;
 
/* ------------------------------------------------------------------
 * list section
   ------------------------------------------------------------------ */
 
/** reference from build_list_index */
export type BUILDER_LIST_REF = number;
 
   /**
 * A list entry.
 */
interface BUILDER_LIST_LIST {
  index: number; // index into indices[] subtable
  count: number; // number of strings in this list
  _value: ListItem; // for locating the list during finalization
};
 
interface BUILDER_LIST_INDEX {
  str: BUILDER_STR_REF; // str for this string
  _value: string; // for locating this string during finalization
};
 
/**
 * Builder for the 'list' section
 */
export interface BUILDER_LIST extends BUILDER_SECTION {
  listCount: number; // Number of lists total in the subtable
  indexCount: number; // Total number of indices in the subtable
  lists: BUILDER_LIST_LIST[];
  indices: BUILDER_LIST_INDEX[];
};
 
export function build_list(source_list: List, sect_strs: BUILDER_STRS): BUILDER_LIST {
  if(!source_list?.lists?.length) {
    // there's always the null list
    return null;
  }

  const result: BUILDER_LIST = {
    ident: constants.hex_section_id(constants.section.list),
    size: 0,
    _offset: 0,
    listCount: source_list.lists.length,
    indexCount: 0,
    lists: [],
    indices: [],
  };

  result.lists = source_list.lists.map(array => {
    const list : BUILDER_LIST_LIST = {
      index: result.indices.length, // the next indexcount
      count: array.length,
      _value: array
    };
    array.forEach((i) => {
      const index : BUILDER_LIST_INDEX = {
        // Get the final string index
        str: build_strs_index(sect_strs, i.value),
        _value: i.value.value, // unwrap the actual string value
      };
      result.indices.push(index); // increment the indexCount
      result.indexCount++;
    });
    return list;
  });

  // Sort the lists.
  result.lists.sort((a,b) => a._value.compareTo(b._value));

  const offset = constants.length_list +
    (constants.length_list_item * result.listCount) +
    (constants.length_list_index * result.indexCount);
  result.size = offset;

  return result;
}
 
/**
 * Returns the index into the list, analagous to build_strs_index
 * @param sect_strs
 * @param value
 * @returns
 */
export function build_list_index(sect_list: BUILDER_LIST, value: ListItem) : BUILDER_LIST_REF {
  if (!value) {
    return 0; // empty list
  }
  if(!(value instanceof ListItem)) {
    throw new Error('unexpected value '+ value);
  }

  const result = sect_list.lists.findIndex(v => v._value === value);
  if(result < 0) {
    throw new Error('unexpectedly missing ListItem ' + value); // TODO-LDML: it's an array of strs
  }
  return <BUILDER_LIST_REF>result;
}