Browse Source

Merge branch 'master' into update-benchmark

Takeru Ohta 4 years ago
parent
commit
53e509193f
5 changed files with 115 additions and 34 deletions
  1. 33 0
      .github/workflows/ci.yml
  2. 0 23
      .travis.yml
  3. 1 1
      README.md
  4. 1 1
      src/jsone.app.src
  5. 80 9
      src/jsone_encode.erl

+ 33 - 0
.github/workflows/ci.yml

@@ -0,0 +1,33 @@
+---
+name: build
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+jobs:
+  ci:
+    name: Run checks and tests over ${{matrix.otp_vsn}} and ${{matrix.os}}
+    runs-on: ${{matrix.os}}
+    strategy:
+      matrix:
+        otp_vsn: [19.3, 20.0, 21.0, 22.0, 23.0, 24.0]
+        os: [ubuntu-latest]
+    steps:
+      - uses: actions/checkout@v2
+      - run: rebar3 compile
+      - run: rebar3 xref
+      - run: rebar3 eunit
+      - run: rebar3 dialyzer
+      - run: rebar3 edoc
+      - run: rebar3 cover
+      - run: rebar3 as test covertool generate
+      - run: cp _build/test/covertool/jsone.covertool.xml ./cobertura.xml
+  cov:
+    needs: ci
+    runs-on: ubuntu-latest
+    steps:
+      - run: sudo pip install codecov
+      - run: codecov

+ 0 - 23
.travis.yml

@@ -1,23 +0,0 @@
-language: erlang
-
-os: linux
-otp_release:
-  - 22.0
-  - 21.0
-  - 20.0
-  - 19.3
-
-install:
-  - sudo pip install codecov
-script:
-  - rebar3 compile
-  - rebar3 xref
-  - rebar3 eunit
-  - rebar3 dialyzer
-  - rebar3 edoc
-  - rebar3 cover
-  - rebar3 as test covertool generate
-  - cp _build/test/covertool/jsone.covertool.xml ./cobertura.xml
-
-after_success:
-  - codecov

+ 1 - 1
README.md

@@ -2,7 +2,7 @@ jsone
 =====
 
 [![hex.pm version](https://img.shields.io/hexpm/v/jsone.svg)](https://hex.pm/packages/jsone)
-[![Build Status](https://travis-ci.org/sile/jsone.svg?branch=master)](https://travis-ci.org/sile/jsone)
+[![Build Status](https://github.com/sile/jsone/workflows/build/badge.svg)](https://github.com/sile/jsone)
 [![Code Coverage](https://codecov.io/gh/sile/jsone/branch/master/graph/badge.svg)](https://codecov.io/gh/sile/jsone/branch/master)
 [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
 

+ 1 - 1
src/jsone.app.src

@@ -1,6 +1,6 @@
 {application,jsone,
              [{description,"Erlang JSON Library"},
-              {vsn,"1.5.7"},
+              {vsn,"1.6.0"},
               {registered,[]},
               {applications,[kernel,stdlib]},
               {licenses,["MIT"]},

+ 80 - 9
src/jsone_encode.erl

@@ -156,7 +156,9 @@ value(Value, Nexts, Buf, Opt)                        ->
 
 -spec string(jsone:json_string(), [next()], binary(), opt()) -> encode_result().
 string(<<Str/binary>>, Nexts, Buf, Opt) ->
-    escape_string(Str, Nexts, <<Buf/binary, $">>, Opt);
+    Len = unescaped_string_length(Str, Opt),
+    <<Unescaped:Len/binary, Rest/binary>> = Str,
+    escape_string(Rest, Nexts, <<Buf/binary, $", Unescaped/binary>>, Opt);
 string(Str, Nexts, Buf, Opt) ->
     string(atom_to_binary(Str, utf8), Nexts, Buf, Opt).
 
@@ -259,20 +261,89 @@ escape_string(<<$\/, Str/binary>>,      Nexts, Buf, Opt) when not Opt?OPT.native
 escape_string(<<0:1, C:7, Str/binary>>, Nexts, Buf, Opt) ->
     case C < 16#20 of
         true  -> escape_string(Str, Nexts, <<Buf/binary, "\\u00", ?H8(C)>>, Opt);
-        false -> escape_string(Str, Nexts, <<Buf/binary, C>>, Opt)
+        false ->
+            Len = unescaped_string_length(Str, Opt),
+            <<Unescaped:Len/binary, Rest/binary>> = Str,
+            escape_string(Rest, Nexts, <<Buf/binary, C, Unescaped/binary>>, Opt)
+
     end;
 escape_string(<<Ch/utf8, Str/binary>>,  Nexts, Buf, Opt = ?OPT{native_utf8 = false}) ->
-    NewBuf = if
-                 Ch =< 16#FFFF -> <<Buf/binary, $\\, $u, ?H16(Ch)>>;
-                 true ->
-                     <<H1, H2, L1, L2>> = <<Ch/utf16>>,
-                     <<Buf/binary, $\\, $u, ?H8(H1), ?H8(H2), $\\, $u, ?H8(L1), ?H8(L2)>>
-             end,
-    escape_string(Str, Nexts, NewBuf, Opt);
+     if
+         Ch =< 16#FFFF ->
+             escape_string(Str, Nexts,<<Buf/binary, $\\, $u, ?H16(Ch)>>, Opt);
+         true ->
+             <<H1, H2, L1, L2>> = <<Ch/utf16>>,
+             escape_string(Str, Nexts, <<Buf/binary, $\\, $u, ?H8(H1), ?H8(H2), $\\, $u, ?H8(L1), ?H8(L2)>>, Opt)
+     end;
 ?COPY_UTF8;
 escape_string(Str, Nexts, Buf, Opt) ->
     ?ERROR(escape_string, [Str, Nexts, Buf, Opt]).
 
+-define(UNESCAPED_CHARS_WITH_SLASH,
+        {false,false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,true,true,false,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,false,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false}).
+
+-define(UNESCAPED_CHARS_WITHOUT_SLASH,
+        {false,false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,true,true,false,
+         true,true,true,true,true,true,true,true,true,true,true,true,false,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,false,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,true,true,true,true,true,true,
+         true,true,true,true,true,true,true,true,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false,false,false,false,false,false,false,false,false,
+         false,false,false}).
+
+
+-compile({inline, [unescaped_string_length/2]}).
+-spec unescaped_string_length(binary(), opt()) -> non_neg_integer().
+unescaped_string_length(Str, ?OPT{native_forward_slash = true}) ->
+    unescaped_string_length(Str, 0, ?UNESCAPED_CHARS_WITH_SLASH);
+unescaped_string_length(Str, _) ->
+    unescaped_string_length(Str, 0, ?UNESCAPED_CHARS_WITHOUT_SLASH).
+
+-spec unescaped_string_length(binary(), non_neg_integer(), tuple()) -> non_neg_integer().
+unescaped_string_length(<<C, Str/binary>>, N, Table) ->
+    case element(C + 1, Table) of
+        true  -> unescaped_string_length(Str, N + 1, Table);
+        false -> N
+    end;
+unescaped_string_length(_, N, _) ->
+    N.
+
 -compile({inline, [hex/1]}).
 -spec hex(byte()) -> 0..16#FFFF.
 hex(X) ->