Столкнулся с проблемой отсутствия простых операций со строками, содержащими символы юникода (например, русские буквы), в стандартной библиотеке Zig.
Конкретно, требовалось привести строку в нижний регистр. И оказалось, впрочем ожидаемо, что методы модуля std.ascii
не годятся для этого, прямо совсем. Ибо константа lowercase содержит только латинские символы.
А в модуле std.unicode
в принципе нет методов, для реализации приведения к нижнему/верхнему регистру символов. В итоге пришлось городить небольшой костыль:
// Кастомное преобразование строки в нижний регистр, с поддержкой
// обработки русских символов, латиницы и акцентированных знаков.
fn toLowerCustom(allocator: Allocator, str: []const u8) ![]const u8 {
var result = std.ArrayList(u8).init(allocator);
var iter = std.unicode.Utf8Iterator{ .bytes = str, .i = 0 };
while (iter.nextCodepoint()) |cp| {
const lower = blk: {
// Русские символы
if (cp >= 'А' and cp <= 'Я') break :blk cp + ('а' - 'А');
if (cp == 'Ё') break :blk 'ё';
// Базовые латинские символы
if (cp >= 'A' and cp <= 'Z') break :blk cp + 32;
// Обработка акцентированных символов
break :blk switch (cp) {
0xC0...0xD6 => cp + 32, // À-Ö → à-ö
0xD8...0xDE => cp + 32, // Ø-Þ → ø-þ
0x100...0x17F => handleLatinExtended(cp),
else => cp,
};
};
var buf: [4]u8 = undefined;
const len = std.unicode.utf8Encode(lower, &buf) catch unreachable;
try result.appendSlice(buf[0..len]);
}
return result.toOwnedSlice();
}
Знаю про существование библиотек для работы со строками на Zig, но ни одна не завелась, да и ради одного метода, тащить всю библиотеку, ИМХО, избыточно. Возможно, что я что-то пропустил и есть проверенные готовые решения?