Merge branch 'wip/795906-turkish-locale'. Fixes Bug 795906.
This commit is contained in:
commit
ffb4befdd8
17 changed files with 190 additions and 97 deletions
|
|
@ -23,10 +23,10 @@ public enum Quoting {
|
||||||
private bool is_special_char(char ch, char[] ar, string? exceptions) {
|
private bool is_special_char(char ch, char[] ar, string? exceptions) {
|
||||||
if (ch > 0x7F || ch.iscntrl())
|
if (ch > 0x7F || ch.iscntrl())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (ch in ar)
|
if (ch in ar)
|
||||||
return (exceptions != null) ? exceptions.index_of_char(ch) < 0 : true;
|
return (exceptions != null) ? Ascii.index_of(exceptions, ch) < 0 : true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,15 +73,15 @@ public class Geary.Imap.FetchBodyDataSpecifier : BaseObject, Gee.Hashable<FetchB
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SectionPart deserialize(string value) throws ImapError {
|
public static SectionPart deserialize(string value) throws ImapError {
|
||||||
if (String.is_empty(value))
|
if (String.is_empty(value))
|
||||||
return NONE;
|
return NONE;
|
||||||
|
|
||||||
switch (value.down()) {
|
switch (Ascii.strdown(value)) {
|
||||||
case "header":
|
case "header":
|
||||||
return HEADER;
|
return HEADER;
|
||||||
|
|
||||||
case "header.fields":
|
case "header.fields":
|
||||||
return HEADER_FIELDS;
|
return HEADER_FIELDS;
|
||||||
|
|
||||||
|
|
@ -178,25 +178,23 @@ public class Geary.Imap.FetchBodyDataSpecifier : BaseObject, Gee.Hashable<FetchB
|
||||||
this.subset_start = subset_start;
|
this.subset_start = subset_start;
|
||||||
this.subset_count = subset_count;
|
this.subset_count = subset_count;
|
||||||
this.is_peek = is_peek;
|
this.is_peek = is_peek;
|
||||||
|
|
||||||
if (field_names != null && field_names.length > 0) {
|
if (field_names != null && field_names.length > 0) {
|
||||||
this.field_names = new Gee.TreeSet<string>((s1, s2) => {
|
this.field_names = new Gee.TreeSet<string>(Ascii.strcmp);
|
||||||
return GLib.strcmp(s1, s2);
|
|
||||||
});
|
|
||||||
foreach (string field_name in field_names) {
|
foreach (string field_name in field_names) {
|
||||||
string converted = field_name.strip().down();
|
string converted = Ascii.strdown(field_name.strip());
|
||||||
|
|
||||||
if (!String.is_empty(converted))
|
if (!String.is_empty(converted))
|
||||||
this.field_names.add(converted);
|
this.field_names.add(converted);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.field_names = null;
|
this.field_names = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see equal_to() for why the response version is used
|
// see equal_to() for why the response version is used
|
||||||
hashable = serialize_response();
|
hashable = serialize_response();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link FetchBodyDataSpecifier} in a string ready for a {@link Command}.
|
* Returns the {@link FetchBodyDataSpecifier} in a string ready for a {@link Command}.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -64,18 +64,18 @@ public class Geary.Imap.InternalDate : Geary.MessageData.AbstractMessageData, Ge
|
||||||
|| year < 1970) {
|
|| year < 1970) {
|
||||||
throw new ImapError.PARSE_ERROR("Invalid INTERNALDATE \"%s\": bad numerical range", internaldate);
|
throw new ImapError.PARSE_ERROR("Invalid INTERNALDATE \"%s\": bad numerical range", internaldate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check month (this catches localization problems)
|
// check month (this catches localization problems)
|
||||||
int month = -1;
|
int month = -1;
|
||||||
string mon_down = ((string) mon).down();
|
string mon_down = Ascii.strdown(((string) mon));
|
||||||
for (int ctr = 0; ctr < EN_US_MON_DOWN.length; ctr++) {
|
for (int ctr = 0; ctr < EN_US_MON_DOWN.length; ctr++) {
|
||||||
if (mon_down == EN_US_MON_DOWN[ctr]) {
|
if (mon_down == EN_US_MON_DOWN[ctr]) {
|
||||||
month = ctr;
|
month = ctr;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (month < 0)
|
if (month < 0)
|
||||||
throw new ImapError.PARSE_ERROR("Invalid INTERNALDATE \"%s\": bad month", internaldate);
|
throw new ImapError.PARSE_ERROR("Invalid INTERNALDATE \"%s\": bad month", internaldate);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ public class Geary.Imap.MailboxSpecifier : BaseObject, Gee.Hashable<MailboxSpeci
|
||||||
public static bool is_inbox_name(string name) {
|
public static bool is_inbox_name(string name) {
|
||||||
return Ascii.stri_equal(name, CANONICAL_INBOX_NAME);
|
return Ascii.stri_equal(name, CANONICAL_INBOX_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the string is the ''canonical'' name of the IMAP Inbox.
|
* Returns true if the string is the ''canonical'' name of the IMAP Inbox.
|
||||||
*
|
*
|
||||||
|
|
@ -90,9 +90,9 @@ public class Geary.Imap.MailboxSpecifier : BaseObject, Gee.Hashable<MailboxSpeci
|
||||||
* @see is_inbox_name
|
* @see is_inbox_name
|
||||||
*/
|
*/
|
||||||
public static bool is_canonical_inbox_name(string name) {
|
public static bool is_canonical_inbox_name(string name) {
|
||||||
return (name == CANONICAL_INBOX_NAME);
|
return Ascii.str_equal(name, CANONICAL_INBOX_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a generic {@link FolderPath} into an IMAP mailbox specifier.
|
* Converts a generic {@link FolderPath} into an IMAP mailbox specifier.
|
||||||
*/
|
*/
|
||||||
|
|
@ -195,27 +195,27 @@ public class Geary.Imap.MailboxSpecifier : BaseObject, Gee.Hashable<MailboxSpeci
|
||||||
public uint hash() {
|
public uint hash() {
|
||||||
return is_inbox ? Ascii.stri_hash(name) : Ascii.str_hash(name);
|
return is_inbox ? Ascii.stri_hash(name) : Ascii.str_hash(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool equal_to(MailboxSpecifier other) {
|
public bool equal_to(MailboxSpecifier other) {
|
||||||
if (this == other)
|
if (this == other)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (is_inbox)
|
if (is_inbox)
|
||||||
return Ascii.stri_equal(name, other.name);
|
return Ascii.stri_equal(name, other.name);
|
||||||
|
|
||||||
return (name == other.name);
|
return Ascii.str_equal(name, other.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compare_to(MailboxSpecifier other) {
|
public int compare_to(MailboxSpecifier other) {
|
||||||
if (this == other)
|
if (this == other)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (is_inbox && other.is_inbox)
|
if (is_inbox && other.is_inbox)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return GLib.strcmp(name, other.name);
|
return Ascii.strcmp(name, other.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string to_string() {
|
public string to_string() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,35 +134,35 @@ public abstract class Geary.Imap.StringParameter : Geary.Imap.Parameter {
|
||||||
public bool is_empty() {
|
public bool is_empty() {
|
||||||
return String.is_empty(ascii);
|
return String.is_empty(ascii);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Case-sensitive comparison.
|
* Case-sensitive comparison.
|
||||||
*/
|
*/
|
||||||
public bool equals_cs(string value) {
|
public bool equals_cs(string value) {
|
||||||
return (ascii == value);
|
return Ascii.str_equal(ascii, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Case-insensitive comparison.
|
* Case-insensitive comparison.
|
||||||
*/
|
*/
|
||||||
public bool equals_ci(string value) {
|
public bool equals_ci(string value) {
|
||||||
return Ascii.stri_equal(ascii, value);
|
return Ascii.stri_equal(ascii, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the string lowercased.
|
* Returns the string lowercased.
|
||||||
*/
|
*/
|
||||||
public string as_lower() {
|
public string as_lower() {
|
||||||
return ascii.down();
|
return Ascii.strdown(ascii);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the string uppercased.
|
* Returns the string uppercased.
|
||||||
*/
|
*/
|
||||||
public string as_upper() {
|
public string as_upper() {
|
||||||
return ascii.up();
|
return Ascii.strup(ascii);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the {@link ascii} to a signed 32-bit integer, clamped between clamp_min and
|
* Converts the {@link ascii} to a signed 32-bit integer, clamped between clamp_min and
|
||||||
* clamp_max.
|
* clamp_max.
|
||||||
|
|
|
||||||
|
|
@ -64,17 +64,17 @@ public class Geary.Imap.ResponseCodeType : BaseObject, Gee.Hashable<ResponseCode
|
||||||
public ResponseCodeType.from_parameter(StringParameter stringp) throws ImapError {
|
public ResponseCodeType.from_parameter(StringParameter stringp) throws ImapError {
|
||||||
init(stringp.ascii);
|
init(stringp.ascii);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init(string ascii) throws ImapError {
|
private void init(string ascii) throws ImapError {
|
||||||
// note that is_quoting_required() also catches empty strings (as they require quoting)
|
// note that is_quoting_required() also catches empty strings (as they require quoting)
|
||||||
if (DataFormat.is_quoting_required(ascii) != DataFormat.Quoting.OPTIONAL)
|
if (DataFormat.is_quoting_required(ascii) != DataFormat.Quoting.OPTIONAL)
|
||||||
throw new ImapError.INVALID("\"%s\" cannot be represented as a ResponseCodeType", ascii);
|
throw new ImapError.INVALID("\"%s\" cannot be represented as a ResponseCodeType", ascii);
|
||||||
|
|
||||||
// store lowercased so it's easily compared with const strings above
|
// store lowercased so it's easily compared with const strings above
|
||||||
original = ascii;
|
original = ascii;
|
||||||
value = ascii.down();
|
value = Ascii.strdown(ascii);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool is_value(string str) {
|
public bool is_value(string str) {
|
||||||
return Ascii.stri_equal(value, str);
|
return Ascii.stri_equal(value, str);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ public class Geary.Mime.ContentParameters : BaseObject {
|
||||||
|
|
||||||
return (stored != null) ? Ascii.stri_equal(stored, value) : false;
|
return (stored != null) ? Ascii.stri_equal(stored, value) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the attribute has the supplied value (case-sensitive comparison).
|
* Returns true if the attribute has the supplied value (case-sensitive comparison).
|
||||||
*
|
*
|
||||||
|
|
@ -86,10 +86,10 @@ public class Geary.Mime.ContentParameters : BaseObject {
|
||||||
*/
|
*/
|
||||||
public bool has_value_cs(string attribute, string value) {
|
public bool has_value_cs(string attribute, string value) {
|
||||||
string? stored = params.get(attribute);
|
string? stored = params.get(attribute);
|
||||||
|
|
||||||
return (stored != null) ? (stored == value) : false;
|
return (stored != null) ? Ascii.str_equal(stored, value) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add or replace the parameter.
|
* Add or replace the parameter.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -31,24 +31,24 @@ public enum Geary.Mime.DispositionType {
|
||||||
*/
|
*/
|
||||||
public static DispositionType deserialize(string? str, out bool is_unknown) {
|
public static DispositionType deserialize(string? str, out bool is_unknown) {
|
||||||
is_unknown = false;
|
is_unknown = false;
|
||||||
|
|
||||||
if (String.is_empty_or_whitespace(str))
|
if (String.is_empty_or_whitespace(str))
|
||||||
return UNSPECIFIED;
|
return UNSPECIFIED;
|
||||||
|
|
||||||
switch (str.down()) {
|
switch (Ascii.strdown(str)) {
|
||||||
case "inline":
|
case "inline":
|
||||||
return INLINE;
|
return INLINE;
|
||||||
|
|
||||||
case "attachment":
|
case "attachment":
|
||||||
return ATTACHMENT;
|
return ATTACHMENT;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
is_unknown = true;
|
is_unknown = true;
|
||||||
|
|
||||||
return ATTACHMENT;
|
return ATTACHMENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns null if value is {@link UNSPECIFIED}
|
* Returns null if value is {@link UNSPECIFIED}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -48,24 +48,24 @@ public enum Geary.Mime.MultipartSubtype {
|
||||||
public static MultipartSubtype from_content_type(ContentType? content_type, out bool is_unknown) {
|
public static MultipartSubtype from_content_type(ContentType? content_type, out bool is_unknown) {
|
||||||
if (content_type == null || !content_type.has_media_type("multipart")) {
|
if (content_type == null || !content_type.has_media_type("multipart")) {
|
||||||
is_unknown = true;
|
is_unknown = true;
|
||||||
|
|
||||||
return MIXED;
|
return MIXED;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_unknown = false;
|
is_unknown = false;
|
||||||
switch (content_type.media_subtype.down()) {
|
switch (Ascii.strdown(content_type.media_subtype)) {
|
||||||
case "mixed":
|
case "mixed":
|
||||||
return MIXED;
|
return MIXED;
|
||||||
|
|
||||||
case "alternative":
|
case "alternative":
|
||||||
return ALTERNATIVE;
|
return ALTERNATIVE;
|
||||||
|
|
||||||
case "related":
|
case "related":
|
||||||
return RELATED;
|
return RELATED;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
is_unknown = true;
|
is_unknown = true;
|
||||||
|
|
||||||
return MIXED;
|
return MIXED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ public class Geary.RFC822.MailboxAddress :
|
||||||
this.source_route = null;
|
this.source_route = null;
|
||||||
this.address = address;
|
this.address = address;
|
||||||
|
|
||||||
int atsign = address.last_index_of_char('@');
|
int atsign = Ascii.last_index_of(address, '@');
|
||||||
if (atsign > 0) {
|
if (atsign > 0) {
|
||||||
this.mailbox = address[0:atsign];
|
this.mailbox = address[0:atsign];
|
||||||
this.domain = address[atsign + 1:address.length];
|
this.domain = address[atsign + 1:address.length];
|
||||||
|
|
@ -173,12 +173,12 @@ public class Geary.RFC822.MailboxAddress :
|
||||||
}
|
}
|
||||||
|
|
||||||
string address = mailbox.get_addr();
|
string address = mailbox.get_addr();
|
||||||
int atsign = address.last_index_of_char('@');
|
int atsign = Ascii.last_index_of(address, '@');
|
||||||
if (atsign == -1) {
|
if (atsign == -1) {
|
||||||
// No @ detected, try decoding in case a mailer (wrongly)
|
// No @ detected, try decoding in case a mailer (wrongly)
|
||||||
// encoded the whole thing and re-try
|
// encoded the whole thing and re-try
|
||||||
address = decode_address_part(address);
|
address = decode_address_part(address);
|
||||||
atsign = address.last_index_of_char('@');
|
atsign = Ascii.last_index_of(address, '@');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atsign >= 0) {
|
if (atsign >= 0) {
|
||||||
|
|
|
||||||
|
|
@ -56,36 +56,36 @@ public enum Geary.Smtp.Command {
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Command deserialize(string str) throws SmtpError {
|
public static Command deserialize(string str) throws SmtpError {
|
||||||
switch (str.down()) {
|
switch (Ascii.strdown(str)) {
|
||||||
case "helo":
|
case "helo":
|
||||||
return HELO;
|
return HELO;
|
||||||
|
|
||||||
case "ehlo":
|
case "ehlo":
|
||||||
return EHLO;
|
return EHLO;
|
||||||
|
|
||||||
case "quit":
|
case "quit":
|
||||||
return QUIT;
|
return QUIT;
|
||||||
|
|
||||||
case "help":
|
case "help":
|
||||||
return HELP;
|
return HELP;
|
||||||
|
|
||||||
case "noop":
|
case "noop":
|
||||||
return NOOP;
|
return NOOP;
|
||||||
|
|
||||||
case "rset":
|
case "rset":
|
||||||
return RSET;
|
return RSET;
|
||||||
|
|
||||||
case "auth":
|
case "auth":
|
||||||
return AUTH;
|
return AUTH;
|
||||||
|
|
||||||
case "mail":
|
case "mail":
|
||||||
return MAIL;
|
return MAIL;
|
||||||
|
|
||||||
case "rcpt":
|
case "rcpt":
|
||||||
return RCPT;
|
return RCPT;
|
||||||
|
|
||||||
case "data":
|
case "data":
|
||||||
return DATA;
|
return DATA;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,21 +25,21 @@ public class Geary.Smtp.Greeting : Response {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ServerFlavor deserialize(string str) {
|
public static ServerFlavor deserialize(string str) {
|
||||||
switch (str.up()) {
|
switch (Ascii.strup(str)) {
|
||||||
case "SMTP":
|
case "SMTP":
|
||||||
return SMTP;
|
return SMTP;
|
||||||
|
|
||||||
case "ESMTP":
|
case "ESMTP":
|
||||||
return ESMTP;
|
return ESMTP;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return UNSPECIFIED;
|
return UNSPECIFIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? domain { get; private set; default = null; }
|
public string? domain { get; private set; default = null; }
|
||||||
public ServerFlavor flavor { get; private set; default = ServerFlavor.UNSPECIFIED; }
|
public ServerFlavor flavor { get; private set; default = ServerFlavor.UNSPECIFIED; }
|
||||||
public string? message { get; private set; default = null; }
|
public string? message { get; private set; default = null; }
|
||||||
|
|
|
||||||
|
|
@ -4,40 +4,80 @@
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* US-ASCII string utilities.
|
||||||
|
*
|
||||||
|
* Using ASCII-specific, non-localised functions is essential when
|
||||||
|
* dealing with protocol strings since any case-insensitive
|
||||||
|
* comparisons may be incorrect under certain locales — especially for
|
||||||
|
* Turkish, where translating between upper-case and lower-case `i` is
|
||||||
|
* not necessarily preserved.
|
||||||
|
*/
|
||||||
namespace Geary.Ascii {
|
namespace Geary.Ascii {
|
||||||
|
|
||||||
|
public int index_of(string str, char ch) {
|
||||||
|
// Use a pointer and explicit null check, since testing against
|
||||||
|
// the length of the string as in a traditional for loop will mean
|
||||||
|
// a call to strlen(), making the loop O(n^2)
|
||||||
|
int ret = -1;
|
||||||
|
char *strptr = str;
|
||||||
|
int i = 0;
|
||||||
|
while (*strptr != String.EOS) {
|
||||||
|
if (*strptr++ == ch) {
|
||||||
|
ret = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int last_index_of(string str, char ch) {
|
||||||
|
// Use a pointer and explicit null check, since testing against
|
||||||
|
// the length of the string as in a traditional for loop will mean
|
||||||
|
// a call to strlen(), making the loop O(n^2)
|
||||||
|
int ret = -1;
|
||||||
|
char *strptr = str;
|
||||||
|
int i = 0;
|
||||||
|
while (*strptr != String.EOS) {
|
||||||
|
if (*strptr++ == ch) {
|
||||||
|
ret = i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public bool get_next_char(string str, ref int index, out char ch) {
|
public bool get_next_char(string str, ref int index, out char ch) {
|
||||||
ch = str[index++];
|
ch = str[index++];
|
||||||
|
|
||||||
return ch != String.EOS;
|
return ch != String.EOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool stri_equal(string a, string b) {
|
public inline int strcmp(string a, string b) {
|
||||||
// XXX Is this marginally faster than a.down() == b.down() in the
|
return GLib.strcmp(a, b);
|
||||||
// best case, slower in the worse case, so not worth it?
|
}
|
||||||
char *aptr = a;
|
|
||||||
char *bptr = b;
|
|
||||||
for (;;) {
|
|
||||||
int diff = (int) (*aptr).tolower() - (int) (*bptr).tolower();
|
|
||||||
if (diff != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (*aptr == String.EOS)
|
public inline int stricmp(string a, string b) {
|
||||||
return true;
|
return a.ascii_casecmp(b);
|
||||||
|
}
|
||||||
|
|
||||||
aptr++;
|
public inline bool str_equal(string a, string b) {
|
||||||
bptr++;
|
return a == b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public inline bool stri_equal(string a, string b) {
|
||||||
|
return a.ascii_casecmp(b) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool nullable_stri_equal(string? a, string? b) {
|
public bool nullable_stri_equal(string? a, string? b) {
|
||||||
if (a == null)
|
if (a == null)
|
||||||
return (b == null);
|
return (b == null);
|
||||||
|
|
||||||
// a != null, so always false
|
// a != null, so always false
|
||||||
if (b == null)
|
if (b == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return stri_equal(a, b);
|
return stri_equal(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +95,14 @@ public uint nullable_stri_hash(string? str) {
|
||||||
return (str != null) ? stri_hash(str) : 0;
|
return (str != null) ? stri_hash(str) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public inline string strdown(string str) {
|
||||||
|
return str.ascii_down();
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline string strup(string str) {
|
||||||
|
return str.ascii_up();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the ASCII string contains only whitespace and at least one numeric character.
|
* Returns true if the ASCII string contains only whitespace and at least one numeric character.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ set(TEST_ENGINE_SRC
|
||||||
engine/rfc822-message-test.vala
|
engine/rfc822-message-test.vala
|
||||||
engine/rfc822-message-data-test.vala
|
engine/rfc822-message-data-test.vala
|
||||||
engine/rfc822-utils-test.vala
|
engine/rfc822-utils-test.vala
|
||||||
|
engine/util-ascii-test.vala
|
||||||
engine/util-html-test.vala
|
engine/util-html-test.vala
|
||||||
engine/util-idle-manager-test.vala
|
engine/util-idle-manager-test.vala
|
||||||
engine/util-inet-test.vala
|
engine/util-inet-test.vala
|
||||||
|
|
|
||||||
44
test/engine/util-ascii-test.vala
Normal file
44
test/engine/util-ascii-test.vala
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Michael Gratton <mike@vee.net>
|
||||||
|
*
|
||||||
|
* This software is licensed under the GNU Lesser General Public License
|
||||||
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Geary.Ascii.Test : TestCase {
|
||||||
|
|
||||||
|
public Test() {
|
||||||
|
base("Geary.Ascii.Test");
|
||||||
|
add_test("index_of", index_of);
|
||||||
|
add_test("last_index_of", last_index_of);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void index_of() throws Error {
|
||||||
|
assert_int(-1, Ascii.index_of("", 'a'));
|
||||||
|
assert_int(0, Ascii.index_of("a", 'a'));
|
||||||
|
assert_int(0, Ascii.index_of("aa", 'a'));
|
||||||
|
|
||||||
|
assert_int(0, Ascii.index_of("abcabc", 'a'));
|
||||||
|
assert_int(1, Ascii.index_of("abcabc", 'b'));
|
||||||
|
assert_int(2, Ascii.index_of("abcabc", 'c'));
|
||||||
|
|
||||||
|
assert_int(0, Ascii.index_of("@", '@'));
|
||||||
|
|
||||||
|
assert_int(-1, Ascii.index_of("abc", 'd'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void last_index_of() throws Error {
|
||||||
|
assert_int(-1, Ascii.last_index_of("", 'a'));
|
||||||
|
assert_int(0, Ascii.last_index_of("a", 'a'));
|
||||||
|
assert_int(1, Ascii.last_index_of("aa", 'a'));
|
||||||
|
|
||||||
|
assert_int(3, Ascii.last_index_of("abcabc", 'a'));
|
||||||
|
assert_int(4, Ascii.last_index_of("abcabc", 'b'));
|
||||||
|
assert_int(5, Ascii.last_index_of("abcabc", 'c'));
|
||||||
|
|
||||||
|
assert_int(0, Ascii.last_index_of("@", '@'));
|
||||||
|
|
||||||
|
assert_int(-1, Ascii.last_index_of("abc", 'd'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,7 @@ geary_test_engine_sources = [
|
||||||
'engine/rfc822-message-test.vala',
|
'engine/rfc822-message-test.vala',
|
||||||
'engine/rfc822-message-data-test.vala',
|
'engine/rfc822-message-data-test.vala',
|
||||||
'engine/rfc822-utils-test.vala',
|
'engine/rfc822-utils-test.vala',
|
||||||
|
'engine/util-ascii-test.vala',
|
||||||
'engine/util-html-test.vala',
|
'engine/util-html-test.vala',
|
||||||
'engine/util-idle-manager-test.vala',
|
'engine/util-idle-manager-test.vala',
|
||||||
'engine/util-inet-test.vala',
|
'engine/util-inet-test.vala',
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ int main(string[] args) {
|
||||||
engine.add_suite(new Geary.App.ConversationSetTest().get_suite());
|
engine.add_suite(new Geary.App.ConversationSetTest().get_suite());
|
||||||
// Depends on ConversationTest and ConversationSetTest passing
|
// Depends on ConversationTest and ConversationSetTest passing
|
||||||
engine.add_suite(new Geary.App.ConversationMonitorTest().get_suite());
|
engine.add_suite(new Geary.App.ConversationMonitorTest().get_suite());
|
||||||
|
engine.add_suite(new Geary.Ascii.Test().get_suite());
|
||||||
engine.add_suite(new Geary.HTML.UtilTest().get_suite());
|
engine.add_suite(new Geary.HTML.UtilTest().get_suite());
|
||||||
engine.add_suite(new Geary.Imap.DeserializerTest().get_suite());
|
engine.add_suite(new Geary.Imap.DeserializerTest().get_suite());
|
||||||
engine.add_suite(new Geary.Imap.CreateCommandTest().get_suite());
|
engine.add_suite(new Geary.Imap.CreateCommandTest().get_suite());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue