ascii-unicode improvements

This commit is contained in:
gazer 2016-01-26 23:59:30 +03:00
parent f4d26fa758
commit 3ba090d4cb
8 changed files with 51 additions and 110 deletions

View File

@ -5,10 +5,11 @@ import std.conv : to;
import std.string;
import std.array : empty;
import std.algorithm : equal;
import std.ascii : isAlpha;
import std.ascii : isAlpha, isWhite;
import dlangui.core.dom;
import dlangui.core.css;
import dlangui.core.types : parseHexDigit;
/// skip specified count of chars of string, returns next available character, or 0 if end of string reached
private char skip(ref string src, int count = 1) {
@ -33,7 +34,7 @@ private char skipSpaces(ref string str)
char ch = str.peek;
if (!ch)
return 0;
while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
while (isWhite(ch))
ch = str.skip;
if (str.peek == '/' && str.peek(1) == '*') {
// comment found
@ -44,7 +45,7 @@ private char skipSpaces(ref string str)
str.skip(2);
}
ch = str.peek;
while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
while (isWhite(ch))
ch = str.skip;
if (oldpos.ptr is str.ptr)
break;
@ -57,7 +58,7 @@ private char skipSpaces(ref string str)
private bool isIdentChar(char ch) {
return (ch >= 'A' && ch <='Z') || (ch >= 'a' && ch <='z') || (ch == '-') || (ch == '_');
return isAlpha(ch) || (ch == '-') || (ch == '_');
}
/// parse css identifier
@ -143,17 +144,6 @@ private bool nextProperty(ref string str) {
}
private int hexDigit( char c )
{
if ( c >= '0' && c <= '9' )
return c-'0';
if ( c >= 'A' && c <= 'F' )
return c - 'A' + 10;
if ( c >= 'a' && c <= 'f' )
return c - 'a' + 10;
return -1;
}
private int parseStandardColor(string ident) {
switch(ident) {
case "black": return 0x000000;
@ -205,23 +195,23 @@ private bool parseColor(ref string src, ref CssValue value)
// #rgb or #rrggbb colors
ch = src.skip;
int nDigits = 0;
for ( ; nDigits < src.length && hexDigit(src[nDigits])>=0; nDigits++ ) {
for ( ; nDigits < src.length && parseHexDigit(src[nDigits])>=0; nDigits++ ) {
}
if ( nDigits==3 ) {
int r = hexDigit( src[0] );
int g = hexDigit( src[1] );
int b = hexDigit( src[2] );
int r = parseHexDigit( src[0] );
int g = parseHexDigit( src[1] );
int b = parseHexDigit( src[2] );
value.type = CssValueType.color;
value.value = (((r + r*16) * 256) | (g + g*16)) * 256 | (b + b*16);
src.skip(3);
return true;
} else if ( nDigits==6 ) {
int r = hexDigit( src[0] ) * 16;
r += hexDigit( src[1] );
int g = hexDigit( src[2] ) * 16;
g += hexDigit( src[3] );
int b = hexDigit( src[4] ) * 16;
b += hexDigit( src[5] );
int r = parseHexDigit( src[0] ) * 16;
r += parseHexDigit( src[1] );
int g = parseHexDigit( src[2] ) * 16;
g += parseHexDigit( src[3] );
int b = parseHexDigit( src[4] ) * 16;
b += parseHexDigit( src[5] );
value.type = CssValueType.color;
value.value = ((r * 256) | g) * 256 | b;
src.skip(6);

View File

@ -626,9 +626,7 @@ class EditableContent {
performOperation(op, this);
}
static bool isAlphaForWordSelection(dchar ch) {
return ch == '_' || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}
static alias isAlphaForWordSelection = isAlNum;
/// get word bounds by position
TextRange wordBounds(TextPosition pos) {
@ -1133,21 +1131,18 @@ class EditableContent {
}
}
static bool isDigit(dchar ch) pure nothrow {
return ch >= '0' && ch <= '9';
}
static alias isDigit = std.uni.isNumber;
static bool isAlpha(dchar ch) pure nothrow {
return isLowerAlpha(ch) || isUpperAlpha(ch);
return std.uni.isAlpha(ch) || ch == '_';
}
static bool isAlNum(dchar ch) pure nothrow {
return isDigit(ch) || isAlpha(ch);
}
static bool isLowerAlpha(dchar ch) pure nothrow {
return (ch >= 'a' && ch <= 'z') || (ch == '_');
}
static bool isUpperAlpha(dchar ch) pure nothrow {
return (ch >= 'A' && ch <= 'Z');
return std.uni.isLower(ch) || ch == '_';
}
static alias isUpperAlpha = std.uni.isUpper;
static bool isPunct(dchar ch) pure nothrow {
switch(ch) {
case '.':

View File

@ -27,6 +27,7 @@ Authors: Vadim Lopatin, coolreader.org@gmail.com
module dlangui.core.settings;
import dlangui.core.logger;
import dlangui.core.types : parseHexDigit;
import std.range;
import std.algorithm : equal;
import std.conv : to;
@ -1623,42 +1624,28 @@ final class Setting {
context = "near `" ~ json[contextStart .. contextEnd] ~ "` ";
throw new Exception("JSON parsing error in (" ~ to!string(line) ~ ":" ~ to!string(col) ~ ") " ~ context ~ ": " ~ msg);
}
static bool isSpace(char ch) {
return ch== ' ' || ch == '\t' || ch == '\r' || ch == '\n';
}
static bool isAlpha(char ch) {
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
return std.ascii.isAlpha(ch) || ch == '_';
}
static bool isAlNum(char ch) {
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_';
}
static bool isDigit(char ch) {
return (ch >= '0' && ch <= '9');
return std.ascii.isAlphaNum(ch) || ch == '_';
}
@property char skipSpaces() {
for(;pos < json.length;pos++) {
char ch = json[pos];
if (!isSpace(ch))
if (!std.ascii.isWhite(ch))
break;
}
return peek;
}
static int parseHexDigit(char ch) {
if (ch >= '0' && ch <='9')
return ch - '0';
if (ch >= 'a' && ch <='f')
return ch - 'a' + 10;
if (ch >= 'A' && ch <='F')
return ch - 'A' + 10;
return -1;
}
string parseUnicodeChar() {
if (pos >= json.length - 3)
error("unexpected end of file while parsing unicode character entity inside string");
dchar ch = 0;
foreach(i; 0 .. 4) {
int d = parseHexDigit(nextChar);
if (d < 0)
uint d = parseHexDigit(nextChar);
if (d == uint.max)
error("error while parsing unicode character entity inside string");
ch = (ch << 4) | d;
}
@ -1756,6 +1743,7 @@ final class Setting {
// parse long, ulong or double
void parseNumber(Setting res) {
import std.ascii : isDigit;
char ch = peek;
int sign = 1;
if (ch == '-') {
@ -1886,7 +1874,7 @@ final class Setting {
this = true;
} else if (parser.parseKeyword("false")) {
this = false;
} else if (ch == '-' || JsonParser.isDigit(ch)) {
} else if (ch == '-' || std.ascii.isDigit(ch)) {
parser.parseNumber(this);
} else {
parser.error("cannot parse JSON value");

View File

@ -45,19 +45,13 @@ public import dlangui.core.config;
import std.algorithm;
/** 2D point */
/// 2D point
struct Point {
/// x coordinate
int x;
/// y coordinate
int y;
this(int x0, int y0) {
x = x0;
y = y0;
}
}
/** 2D rectangle */
/// 2D rectangle
struct Rect {
/// x coordinate of top left corner
int left;
@ -427,26 +421,6 @@ struct Ref(T) { // if (T is RefCountedObject)
//================================================================================
// some utility functions
/*
string fromStringz(const(char[]) s) {
if (s is null)
return null;
int i = 0;
while(s[i])
i++;
return cast(string)(s[0..i].dup);
}
string fromStringz(const(char*) s) {
if (s is null)
return null;
int i = 0;
while(s[i])
i++;
return cast(string)(s[0..i].dup);
}
*/
/** conversion from wchar z-string */
wstring fromWStringz(const(wchar[]) s) {
if (s is null)
@ -497,15 +471,20 @@ enum State : uint {
Parent = 0x10000, // use parent's state
}
/**
/** Deprecated: use std.uni.toUpper instead.
Uppercase unicode character.
TODO: support non-ascii.
*/
dchar dcharToUpper(dchar ch) {
// TODO: support non-ascii letters
if (ch >= 'a' && ch <= 'z')
return ch - 'a' + 'A';
return ch;
deprecated dchar dcharToUpper(dchar ch) {
return std.uni.toUpper(ch);
}
/// decodes hex digit (0..9, a..f, A..F), returns uint.max if invalid
uint parseHexDigit(T)(T ch) pure nothrow {
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
return uint.max;
}

View File

@ -347,13 +347,13 @@ class Tokenizer {
foreach(i; 0 .. prefixLen)
ch = skipChar();
uint n = decodeHexDigit(ch);
uint n = parseHexDigit(ch);
if (n == uint.max)
return parseError();
for(;;) {
ch = skipChar();
uint digit = decodeHexDigit(ch);
uint digit = parseHexDigit(ch);
if (digit == uint.max)
break;
n = (n << 4) + digit;

View File

@ -163,17 +163,6 @@ bool isFullyTransparentColor(uint color) pure nothrow {
return (color >> 24) == 0xFF;
}
/// decodes hex digit (0..9, a..f, A..F), returns uint.max if invalid
uint decodeHexDigit(T)(T ch) pure nothrow {
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
return uint.max;
}
/// decode color string supported formats: #RGB #ARGB #RRGGBB #AARRGGBB
uint decodeHexColor(string s, uint defValue = 0) pure {
s = strip(s);
@ -205,7 +194,7 @@ uint decodeHexColor(string s, uint defValue = 0) pure {
return defValue;
uint value = 0;
foreach(i; 1 .. s.length) {
uint digit = decodeHexDigit(s[i]);
uint digit = parseHexDigit(s[i]);
if (digit == uint.max)
return defValue;
value = (value << 4) | digit;

View File

@ -7,7 +7,7 @@ Layouts are similar to the same in Android.
LinearLayout - either VerticalLayout or HorizontalLayout.
VerticalLayout - just LinearLayout with orientation=Orientation.Vertical
HorizontalLayout - just LinearLayout with orientation=Orientation.Vertical
HorizontalLayout - just LinearLayout with orientation=Orientation.Horizontal
FrameLayout - children occupy the same place, usually one one is visible at a time
TableLayout - children aligned into rows and columns
ResizerWidget - widget to resize sibling widgets

View File

@ -155,14 +155,14 @@ class MenuItem {
break;
}
}
return dcharToUpper(ch);
return std.uni.toUpper(ch);
}
/// find subitem by hotkey character, returns subitem index, -1 if not found
int findSubitemByHotkey(dchar ch) {
if (!ch)
return -1;
ch = dcharToUpper(ch);
ch = std.uni.toUpper(ch);
for (int i = 0; i < _subitems.length; i++) {
if (_subitems[i].getHotkey() == ch)
return i;