let output_mo ?(endianess = LittleEndian) chn lst =
let null_terminated lst =
List.map ( fun str -> str^"\000" ) lst
in
let compute_table start_pos lst =
let compute_length lst =
List.map String.length lst
in
let compute_offset (current_pos,lst_pos) length =
( current_pos + length, (length - 1,current_pos) :: lst_pos )
in
let (final_pos, lst_rev) =
List.fold_left compute_offset (start_pos, []) (compute_length lst)
in
(final_pos, List.rev lst_rev)
in
let sorted_lst =
let compare_entry entry1 entry2 =
let value_of_entry entry =
match entry with
Singular (id, _) -> id
| Plural (id, _, _) -> id
in
String.compare ( value_of_entry entry1) (value_of_entry entry2)
in
List.sort compare_entry lst
in
let untranslated =
let to_string entry =
match entry with
Singular (id, _) -> id
| Plural (id, id_plural, _) -> id ^ "\000" ^ id_plural
in
null_terminated (List.map to_string sorted_lst)
in
let translated =
let to_string entry =
match entry with
Singular (_,str) -> str
| Plural (_, _, lst) -> String.concat "\000" lst
in
null_terminated (List.map to_string sorted_lst)
in
let gN = List.length lst
in
let gO = 28
in
let gT = gO + 8 * gN
in
let gS = 0
in
let gH = gT + 8 * gN
in
let (final_untranslated,untranslated_table) =
compute_table (gH + gS * 4) untranslated
in
let (_,translated_table) =
compute_table final_untranslated translated
in
let header = {
endianess = endianess;
file_format_revision = Int32.zero;
number_of_strings = Int32.of_int gN;
offset_table_strings = Int32.of_int gO;
offset_table_translation = Int32.of_int gT;
size_of_hashing_table = Int32.of_int gS;
offset_of_hashing_table = Int32.of_int gH;
}
in
output_mo_header chn header;
List.iter (
List.iter (
fun (a,b) ->
output_int32_pair chn endianess (Int32.of_int a,Int32.of_int b);
)
) [ untranslated_table ; translated_table ];
List.iter (output_string chn) untranslated;
List.iter (output_string chn) translated