Skip to content

Commit

Permalink
Merge pull request #55 from esl/modernising
Browse files Browse the repository at this point in the history
Modernising the repo
  • Loading branch information
chrzaszcz committed May 7, 2021
2 parents 078499f + ffd0de2 commit e8c0cef
Show file tree
Hide file tree
Showing 13 changed files with 163 additions and 120 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: ci

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:

jobs:
test:
name: OTP ${{matrix.otp}}
strategy:
matrix:
otp: ['24.0-rc3', '23.3', '22.3', '21.3']
runs-on: 'ubuntu-20.04'
env:
OTPVER: ${{ matrix.otp }}
steps:
- uses: actions/checkout@v2
- uses: ErlGang/setup-erlang@v1.0.0
with:
otp-version: ${{ matrix.otp }}
- run: make rebar3
- run: make deps
- run: make test
- run: make dialyzer
if: ${{ matrix.otp == '23.3' }}
- run: make codecov
if: ${{ matrix.otp == '23.3' }}
- run: make gcov
if: ${{ matrix.otp == '23.3' }}
- run: pip install --user codecov
if: ${{ matrix.otp == '23.3' }}
- run: /home/runner/.local/bin/codecov
if: ${{ matrix.otp == '23.3' }}
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
_build/
/.eunit/
/.rebar/
/c_src/*o
/c_src/*d
/c_src/*gcda
/c_src/*gcno
/deps/
/ebin/
/logs/
/priv/*so
/test/*.beam

*.beam
*.lock
/rebar3
29 changes: 0 additions & 29 deletions .travis.yml

This file was deleted.

14 changes: 11 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
.PHONY: rel deps test

REBARVER = 3.13.2
ifeq ($(OTPVER),24.0-rc3)
REBARVER = 3.15.1
endif

all: deps compile

compile: rebar3
Expand All @@ -9,13 +14,13 @@ deps: rebar3
./rebar3 get-deps

clean: rebar3
./rebar3 clean
./rebar3 clean && rm -f c_src/exml.gc*

test-deps: rebar3
./rebar3 get-deps

test-compile: rebar3 test-deps
./rebar3 compile
./rebar3 as test compile

test: test-compile
./rebar3 eunit
Expand All @@ -26,8 +31,11 @@ coverage-report: _build/test/cover/eunit.coverdata
codecov: _build/test/cover/eunit.coverdata
./rebar3 as test codecov analyze

gcov: test-compile
gcov -o c_src exml

rebar3:
wget https://github.com/erlang/rebar3/releases/download/3.13.2/rebar3 &&\
wget https://github.com/erlang/rebar3/releases/download/${REBARVER}/rebar3 &&\
chmod u+x rebar3

dialyzer: rebar3
Expand Down
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
exml
====

[![Build Status](https://secure.travis-ci.org/esl/exml.png)](http://travis-ci.org/esl/exml) [![Coverage Status](https://coveralls.io/repos/github/esl/exml/badge.svg?branch=master)](https://coveralls.io/github/esl/exml?branch=master)
[![GitHub Actions](https://github.com/esl/exml/workflows/ci/badge.svg?branch=master)](https://github.com/esl/exml/actions?query=workflow%3Aci+branch%3Amaster)
[![Codecov](https://codecov.io/gh/esl/exml/branch/master/graph/badge.svg)](https://codecov.io/gh/esl/exml)

**exml** is an Erlang library helpful with parsing XML streams
and doing some basic XML structures manipulation.
**exml** is an Erlang library for parsing XML streams and doing complex XML structures manipulation.

Building
========

**exml** is a rebar3-compatible OTP application, run `make` or
`./rebar3 compile` in order to build it.
**exml** is a rebar3-compatible OTP application, run `make` or `./rebar3 compile` in order to build it. A C++11 compiler is required.

As a requirement, development headers for expat library are
required.

Using
=====

**exml** can parse both XML streams as well as single XML
documents at once.
**exml** can parse both XML streams as well as single XML documents at once.

To parse a whole XML document:

Expand All @@ -35,9 +31,7 @@ El = #xmlel{name = <<"foo">>,
children = [{xmlcdata, <<"Some Value">>}]},
exml:to_list(El).
```

or (pastable into `erl` shell):

```erlang
El = {xmlel, <<"foo">>,
[{<<"attr1">>, <<"bar">>}],
Expand All @@ -46,15 +40,13 @@ exml:to_list(El).
```

Which results in:

```xml
<foo attr1='bar'>Some Value</foo>
```

`exml:to_binary/1` works similarly.

There're also `exml:to_pretty_iolist/1,3` for a quick'n'dirty document
preview (pastable into `erl`):
There's also `exml:to_pretty_iolist/1,3` for a quick'n'dirty document preview (pastable into `erl`):

```erlang
rr("include/exml.hrl").
Expand All @@ -66,9 +58,7 @@ El = #xmlel{name = <<"outer">>,
children = [#xmlel{name = <<"a">>}]}]}.
io:format("~s", [exml:to_pretty_iolist(El)]).
```

which prints:

```xml
<outer attr2='val-two' attr1='val1'>
<inner-childless/>
Expand All @@ -79,3 +69,14 @@ which prints:
```

For an example of using the streaming API see `test/exml_stream_tests.erl`.

XML Tree navigation
=====

The `exml_query` module exposes powerful helper functions to navigate the tree, please refer to the documentation available.


Notes
=====

The implementation uses C++ thread-local memory pools of size 10MB by default (override `RAPIDXML_STATIC_POOL_SIZE` and/or `RAPIDXML_DYNAMIC_POOL_SIZE` at compilation time if desired differently), to maximise cache locality and memory allocation patterns. To also improve performance, the NIF calls are not checking input size, nor timeslicing themselves, nor running in dirty schedulers: that means that if called with too big inputs, the NIFs can starve the VM. It's up to the dev to throttle the input sizes and fine-tune the memory pool sizes.
4 changes: 4 additions & 0 deletions c_src/exml.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#ifndef RAPIDXML_STATIC_POOL_SIZE
#define RAPIDXML_STATIC_POOL_SIZE (10 * 1024 * 1024)
#endif
#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
#define RAPIDXML_DYNAMIC_POOL_SIZE (2 * 1024 * 1024)
#endif

#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
Expand Down
60 changes: 27 additions & 33 deletions rebar.config
Original file line number Diff line number Diff line change
@@ -1,49 +1,43 @@
{profiles,
[
{test,
[
{deps, [{proper, "1.3.0"}]},
{plugins,
[
pc,
coveralls,
{rebar3_codecov, {git, "https://github.com/esl/rebar3_codecov.git", {ref, "6bd31cc"}}}
]}
]}
]}.

{plugins, [pc]}.
{deps, []}.

{profiles, [
{test, [
{deps, [
{proper, "1.3.0"}
]},
{plugins, [
{rebar3_codecov, "0.2.0"}
]},
{port_env, [
{"CXXFLAGS", "$CXXFLAGS -O3 -std=c++11 -g -Wall -Wextra -fPIC --coverage"},
{"LDFLAGS", "$LDFLAGS --coverage"}
]},
{cover_enabled, true},
{cover_export_enabled, true}
]}
]}.

{plugins, [pc, rebar3_hex]}.

% Interrupt compilation, if the artifact is not found
{artifacts, ["priv/exml_nif.so"]}.

{port_specs,
[
{port_specs, [
{
% Any arch
".*",

% Create library
"priv/exml_nif.so",

% From files
["c_src/*.cpp"],

% Using options
[ {env, [{ "CXXFLAGS", "$CXXFLAGS -O3 -std=c++11" }]} ]
}
]}.
[{env, [{"CXXFLAGS", "$CXXFLAGS -O3 -std=c++11"}]}]
}
]}.

{provider_hooks,
[
{post,
[
{provider_hooks, [
{post, [
{compile, {pc, compile}},
{clean, {pc, clean}}
]}
]}.

{cover_enabled, true}.
{cover_export_enabled, true}.
{coveralls_coverdata, "_build/test/cover/eunit.coverdata"}.
{coveralls_service_name, "travis-ci"}.
]}.
11 changes: 0 additions & 11 deletions rebar.config.script

This file was deleted.

19 changes: 13 additions & 6 deletions src/exml.app.src
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
{application, exml,
[
{description, "XML parsing library"},
{vsn, git},
[{description, "Erlang fast XML parsing library"},
{vsn, "3.0.4"},
{registered, []},
{applications, [kernel,
stdlib]},
{env, []}
{applications,
[kernel,
stdlib
]},
{env, []},
{modules, []},
{maintainers, ["ESL"]},
{pkg_name, "hexml"},
{licenses, ["Apache 2.0", "Boost Software License 1.0 (C++ code)", "GPL (tests)"]},
{links, [{"GitHub", "https://github.com/esl/exml/"}]},
{exclude_files, ["c_src/exml.d"]}
]}.
18 changes: 6 additions & 12 deletions src/exml.erl
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
%%%-------------------------------------------------------------------
%%% @author Michal Ptaszek <michal.ptaszek@erlang-solutions.com>
%%% @copyright (C) 2011, Erlang Solutions Ltd.
%%% @copyright (C) 2011-2021, Erlang Solutions Ltd.
%%% @doc
%%%
%%% @end
%%% Created : 12 Jul 2011 by Michal Ptaszek <michal.ptaszek@erlang-solutions.com>
%%%
Expand All @@ -22,8 +20,6 @@
xml_sort/1,
to_pretty_iolist/1]).

-export([]).

-export_type([attr/0,
cdata/0,
element/0,
Expand Down Expand Up @@ -57,21 +53,20 @@ xml_size({Key, Value}) ->
+ 4 % ="" and whitespace before
+ byte_size(Value).

%% @doc Sort a (list of) `xmlel()`.
%% @doc Sort a (list of) `xmlel()'.
%%
%% Sorting is defined as calling `lists:sort/1` at:
%% Sorting is defined as calling `lists:sort/1' at:
%% * all the `xmlel's provided (if there is a list of them) AND
%% * all the `xmlel' elements' attributes recursively (the root and descendants) AND
%% * all the `xmlel' children recursively (the root and descendants).
%% The order is ascending.
%%
%% The implementation of this function is subtle modification of
%% The implementation of this function is a subtle modification of
%% https://github.com/erszcz/rxml/commit/e8483408663f0bc2af7896e786c1cdea2e86e43d
-spec xml_sort(item() | [item()]) -> item() | [item()].
xml_sort(#xmlcdata{} = Cdata) ->
Cdata;
xml_sort(#xmlel{} = El) ->
#xmlel{ attrs = Attrs, children = Children } = El,
xml_sort(#xmlel{ attrs = Attrs, children = Children } = El) ->
El#xmlel{
attrs = lists:sort(Attrs),
children = [ xml_sort(C) || C <- Children ]
Expand Down Expand Up @@ -108,8 +103,7 @@ to_iolist(#xmlel{} = Element, Pretty) ->
to_binary_nif(Element, Pretty);
to_iolist([Element], Pretty) ->
to_iolist(Element, Pretty);
to_iolist([_ | _] = Elements, Pretty) ->
Head = hd(Elements),
to_iolist([Head | _] = Elements, Pretty) ->
[Last | RevChildren] = lists:reverse(tl(Elements)),
case {Head, Last} of
{#xmlstreamstart{name = Name, attrs = Attrs},
Expand Down
4 changes: 2 additions & 2 deletions src/exml_nif.erl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%%%-------------------------------------------------------------------
%%% @author Konrad Zemek <konrad.zemek@erlang-solutions.com>
%%% @copyright (C) 2018, Erlang Solutions Ltd.
%%% @copyright (C) 2018-2021, Erlang Solutions Ltd.
%%% @private
%%%-------------------------------------------------------------------

-module(exml_nif).
Expand Down

0 comments on commit e8c0cef

Please sign in to comment.