The .DS_Store file is automatically generated by the Mac OS filesystem to keep metainformation about that directory. This files is unnecessary to the project so should be excluded in the .gitignore
@privat
Pull-Request: #2060
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
# In Buffers, the internal sequence of character is mutable
# Thus, `chars` can be used to modify the buffer.
redef fun chars: Sequence[Char] is abstract
+
+ # Appends `length` chars from `s` starting at index `from`
+ #
+ # ~~~nit
+ # var b = new Buffer
+ # b.append_substring("abcde", 1, 2)
+ # assert b == "bc"
+ # b.append_substring("vwxyz", 2, 3)
+ # assert b == "bcxyz"
+ # b.append_substring("ABCDE", 4, 300)
+ # assert b == "bcxyzE"
+ # b.append_substring("VWXYZ", 400, 1)
+ # assert b == "bcxyzE"
+ # ~~~
+ fun append_substring(s: Text, from, length: Int) do
+ if from < 0 then
+ length += from
+ from = 0
+ end
+ var ln = s.length
+ if (length + from) > ln then length = ln - from
+ if length <= 0 then return
+ append_substring_impl(s, from, length)
+ end
+
+ # Unsafe version of `append_substring` for performance
+ #
+ # NOTE: Use only if sure about `from` and `length`, no checks
+ # or bound recalculation is done
+ fun append_substring_impl(s: Text, from, length: Int) do
+ var pos = from
+ for i in [0 .. length[ do
+ self.add s[pos]
+ pos += 1
+ end
+ end
end
# View for chars on Buffer objects, extends Sequence
return cp >= 0xD800 and cp <= 0xDFFF
end
+ # Is `self` a UTF-16 high surrogate ?
+ fun is_hi_surrogate: Bool do
+ var cp = code_point
+ return cp >= 0xD800 and cp <= 0xDBFF
+ end
+
+ # Is `self` a UTF-16 low surrogate ?
+ fun is_lo_surrogate: Bool do
+ var cp = code_point
+ return cp >= 0xDC00 and cp <= 0xDFFF
+ end
+
# Length of `self` in a UTF-8 String
fun u8char_len: Int do
var c = self.code_point
if from < 0 then
count += from
- if count < 0 then return ""
+ if count <= 0 then return ""
from = 0
end
is_dirty = true
_bytelen = 0
_length = 0
- if written then reset
+ if written then
+ _capacity = 16
+ reset
+ end
end
redef fun empty do return new Buffer
return new FlatBuffer.with_infos(r_items, byte_length, byte_length, count)
end
+ redef fun append_substring_impl(s, from, length) do
+ if length <= 0 then return
+ if not s isa FlatText then
+ super
+ return
+ end
+ var bytest = s.char_to_byte_index(from)
+ var bytend = s.char_to_byte_index(from + length - 1)
+ var btln = bytend - bytest + 1
+ enlarge(btln + _bytelen)
+ s._items.copy_to(_items, btln, bytest, _bytelen)
+ _bytelen += btln
+ _length += length
+ end
+
redef fun reverse
do
written = false
#
# Very unsafe, make sure to have room for this char prior to calling this function.
private fun set_char_at(pos: Int, c: Char) do
- if c.code_point < 128 then
- self[pos] = c.code_point.to_b
+ var cp = c.code_point
+ if cp < 128 then
+ self[pos] = cp.to_b
return
end
var ln = c.u8char_len
- native_set_char(pos, c, ln)
- end
-
- private fun native_set_char(pos: Int, c: Char, ln: Int) `{
- char* dst = self + pos;
- switch(ln){
- case 1:
- dst[0] = c;
- break;
- case 2:
- dst[0] = 0xC0 | ((c & 0x7C0) >> 6);
- dst[1] = 0x80 | (c & 0x3F);
- break;
- case 3:
- dst[0] = 0xE0 | ((c & 0xF000) >> 12);
- dst[1] = 0x80 | ((c & 0xFC0) >> 6);
- dst[2] = 0x80 | (c & 0x3F);
- break;
- case 4:
- dst[0] = 0xF0 | ((c & 0x1C0000) >> 18);
- dst[1] = 0x80 | ((c & 0x3F000) >> 12);
- dst[2] = 0x80 | ((c & 0xFC0) >> 6);
- dst[3] = 0x80 | (c & 0x3F);
- break;
- }
- `}
+ if ln == 2 then
+ self[pos] = (0xC0 | ((cp & 0x7C0) >> 6)).to_b
+ self[pos + 1] = (0x80 | (cp & 0x3F)).to_b
+ else if ln == 3 then
+ self[pos] = (0xE0 | ((cp & 0xF000) >> 12)).to_b
+ self[pos + 1] = (0x80 | ((cp & 0xFC0) >> 6)).to_b
+ self[pos + 2] = (0x80 | (cp & 0x3F)).to_b
+ else if ln == 4 then
+ self[pos] = (0xF0 | ((cp & 0x1C0000) >> 18)).to_b
+ self[pos + 1] = (0x80 | ((cp & 0x3F000) >> 12)).to_b
+ self[pos + 2] = (0x80 | ((cp & 0xFC0) >> 6)).to_b
+ self[pos + 3] = (0x80 | (cp & 0x3F)).to_b
+ end
+ end
end
redef class Int
"\"position\":{position.to_json}," +
"\"message\":{message.to_json}\}"
end
+
+ redef fun pretty_json_visit(buf, indents) do
+ buf.clear
+ buf.append(to_json)
+ end
end
redef class Position
return val
end
+ private var parse_str_buf = new FlatBuffer
+
# Parses and returns a Nit string from a JSON String
fun parse_json_string: Jsonable do
+ var src = src
var ln = src.length
var p = pos
p += 1
if p > ln then return make_parse_error("Malformed JSON String")
var c = src[p]
- var st = p
+ var ret = parse_str_buf
+ var chunk_st = p
while c != '"' do
- if c == '\\' then
- if p + 1 >= ln then return make_parse_error("Malformed Escape sequence in JSON string")
+ if c != '\\' then
p += 1
+ if p >= ln then return make_parse_error("Malformed JSON string")
c = src[p]
- if c == 'u' then
+ continue
+ end
+ ret.append_substring_impl(src, chunk_st, p - chunk_st)
+ p += 1
+ if p >= ln then return make_parse_error("Malformed Escape sequence in JSON string")
+ c = src[p]
+ if c == 'r' then
+ ret.add '\r'
+ p += 1
+ else if c == 'n' then
+ ret.add '\n'
+ p += 1
+ else if c == 't' then
+ ret.add '\t'
+ p += 1
+ else if c == 'u' then
+ var cp = 0
+ p += 1
+ for i in [0 .. 4[ do
+ cp <<= 4
+ if p >= ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string")
+ c = src[p]
+ if c >= '0' and c <= '9' then
+ cp += c.code_point - '0'.code_point
+ else if c >= 'a' and c <= 'f' then
+ cp += c.code_point - 'a'.code_point + 10
+ else if c >= 'A' and c <= 'F' then
+ cp += c.code_point - 'A'.code_point + 10
+ else
+ make_parse_error("Malformed \uXXXX Escape sequence in JSON string")
+ end
p += 1
- if p + 3 >= ln then return make_parse_error("Bad Unicode escape sequence in string")
- for i in [0 .. 4[ do if not src[p + i].is_hexdigit then return make_parse_error("Bad Unicode escape sequence in string")
- p += 3
end
+ c = cp.code_point
+ if cp >= 0xD800 and cp <= 0xDBFF then
+ if p >= ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string")
+ c = src[p]
+ if c != '\\' then make_parse_error("Malformed \uXXXX Escape sequence in JSON string")
+ p += 1
+ c = src[p]
+ if c != 'u' then make_parse_error("Malformed \uXXXX Escape sequence in JSON string")
+ var locp = 0
+ p += 1
+ for i in [0 .. 4[ do
+ locp <<= 4
+ if p > ln then make_parse_error("Malformed \uXXXX Escape sequence in JSON string")
+ c = src[p]
+ if c >= '0' and c <= '9' then
+ locp += c.code_point - '0'.code_point
+ else if c >= 'a' and c <= 'f' then
+ locp += c.code_point - 'a'.code_point + 10
+ else if c >= 'A' and c <= 'F' then
+ locp += c.code_point - 'A'.code_point + 10
+ else
+ make_parse_error("Malformed \uXXXX Escape sequence in JSON string")
+ end
+ p += 1
+ end
+ c = (((locp & 0x3FF) | ((cp & 0x3FF) << 10)) + 0x10000).code_point
+ end
+ ret.add c
+ else if c == 'b' then
+ ret.add 8.code_point
+ p += 1
+ else if c == 'f' then
+ ret.add '\f'
+ p += 1
+ else
+ p += 1
+ ret.add c
end
- p += 1
- if p >= ln then return make_parse_error("Malformed JSON String")
+ chunk_st = p
c = src[p]
end
pos = p + 1
- return src.substring(st, p - st).unescape_json
+ if ret.is_empty then return src.substring(chunk_st, p - chunk_st)
+ ret.append_substring_impl(src, chunk_st, p - chunk_st)
+ var rets = ret.to_s
+ ret.clear
+ return rets
end
# Ignores any character until a JSON separator is encountered
fun init_expr(v: AbstractCompilerVisitor, recv: RuntimeVariable)
do
- if has_value and not is_lazy and not n_expr isa ANullExpr then evaluate_expr(v, recv)
+ if has_value and not is_lazy and not is_optional and not n_expr isa ANullExpr then evaluate_expr(v, recv)
end
# Evaluate, store and return the default value of the attribute
# Evaluate and set the default value of the attribute in `recv`
private fun init_expr(v: NaiveInterpreter, recv: Instance)
do
- if is_lazy then return
+ if is_lazy or is_optional then return
if has_value then
var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
evaluate_expr(v, recv, f)
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import core::kernel
+
+fun foo(i: Int): Int
+do
+ 'f'.output
+ i.output
+ return i
+end
+
+class A
+ # needed on the new
+ var i: Int
+
+ # initialized by the allocation
+ var j: Int = foo(2)
+
+ # optional in the new, default value evaluated if `null` is given
+ var k: Int = foo(3) is optional
+
+ # the `init` will initialize it
+ var l: Int is noautoinit
+ init do l = foo(4)
+
+ # initialized if needed on the first `read`
+ var m: Int = foo(5) is lazy
+
+ fun set
+ do
+ i = 10
+ j = 20
+ k = 30
+ l = 40
+ m = 50
+ end
+
+ fun test
+ do
+ #alt1#set
+ i.output
+ j.output
+ k.output
+ l.output
+ m.output
+ '\n'.output
+ end
+end
+
+var a
+a = new A(foo(100))
+a.test
+a = new A(foo(100), null)
+a.test
+a = new A(foo(100), foo(300))
+a.test
--- /dev/null
+f2
+f100
+f3
+f4
+100
+2
+3
+4
+f5
+5
+
+f2
+f100
+f3
+f4
+100
+2
+3
+4
+f5
+5
+
+f2
+f100
+f300
+f4
+100
+2
+300
+4
+f5
+5
+
--- /dev/null
+f2
+f100
+f3
+f4
+10
+20
+30
+40
+50
+
+f2
+f100
+f3
+f4
+10
+20
+30
+40
+50
+
+f2
+f100
+f300
+f4
+10
+20
+30
+40
+50
+