Skip to content
This repository has been archived by the owner on Oct 8, 2020. It is now read-only.

Commit

Permalink
Deprecate RawParseUtils.parse_base_10/1 in favor of ParseDecimal.from…
Browse files Browse the repository at this point in the history
…_decimal_charlist/1. (#195)
  • Loading branch information
scouten committed Oct 12, 2019
1 parent a450c68 commit 32ecea6
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 7 deletions.
7 changes: 5 additions & 2 deletions lib/xgit/core/object.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ defmodule Xgit.Core.Object do
alias Xgit.Core.FileMode
alias Xgit.Core.FilePath
alias Xgit.Core.ObjectId
alias Xgit.Util.ParseDecimal
alias Xgit.Util.RawParseUtils

import Xgit.Util.ForceCoverage
Expand Down Expand Up @@ -407,8 +408,10 @@ defmodule Xgit.Core.Object do
{:missing_email, RawParseUtils.next_lf(data, ?<)},
{:bad_email, [?> | after_email]} <- {:bad_email, RawParseUtils.next_lf(email_start, ?>)},
{:missing_space_before_date, [?\s | date]} <- {:missing_space_before_date, after_email},
{:bad_date, {_date, [?\s | tz]}} <- {:bad_date, RawParseUtils.parse_base_10(date)},
{:bad_timezone, {_tz, [?\n | next]}} <- {:bad_timezone, RawParseUtils.parse_base_10(tz)} do
{:bad_date, {_date, [?\s | tz]}} <-
{:bad_date, ParseDecimal.from_decimal_charlist(date)},
{:bad_timezone, {_tz, [?\n | next]}} <-
{:bad_timezone, ParseDecimal.from_decimal_charlist(tz)} do
next
else
{:missing_email, _} -> cover :missing_email
Expand Down
7 changes: 4 additions & 3 deletions lib/xgit/core/person_ident.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ defmodule Xgit.Core.PersonIdent do
A combination of a person identity and time in git.
"""

import Xgit.Util.ForceCoverage

alias Xgit.Util.ParseDecimal
alias Xgit.Util.RawParseUtils

import Xgit.Util.ForceCoverage

@typedoc "Time zone offset in minutes +/- from GMT."
@type tz_offset :: -720..840

Expand Down Expand Up @@ -144,7 +145,7 @@ defmodule Xgit.Core.PersonIdent do

case {time, tz} do
{[_ | _], [_ | _]} ->
{time |> RawParseUtils.parse_base_10() |> elem(0),
{time |> ParseDecimal.from_decimal_charlist() |> elem(0),
tz |> RawParseUtils.parse_timezone_offset() |> elem(0)}

_ ->
Expand Down
4 changes: 2 additions & 2 deletions lib/xgit/repository/on_disk/get_object.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule Xgit.Repository.OnDisk.GetObject do

alias Xgit.Core.Object
alias Xgit.Core.ObjectId
alias Xgit.Util.RawParseUtils
alias Xgit.Util.ParseDecimal
alias Xgit.Util.UnzipStream

defmodule LooseObjectContentSource do
Expand Down Expand Up @@ -93,7 +93,7 @@ defmodule Xgit.Repository.OnDisk.GetObject do
defp parse_length(_type, ' '), do: cover(:invalid_header)

defp parse_length(type, [?\s | length]) do
case RawParseUtils.parse_base_10(length) do
case ParseDecimal.from_decimal_charlist(length) do
{length, []} when is_integer(length) and length >= 0 -> {:header, type, length}
_ -> cover :invalid_header
end
Expand Down
39 changes: 39 additions & 0 deletions lib/xgit/util/parse_decimal.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule Xgit.Util.ParseDecimal do
@moduledoc false
# Internal utility for parsing decimal values from charlist.

import Xgit.Util.ForceCoverage

@doc ~S"""
Parse a base-10 numeric value from a charlist of ASCII digits into a number.
Similar to `Integer.parse/2` but uses charlist instead.
Digit sequences can begin with an optional run of spaces before the
sequence, and may start with a `+` or a `-` to indicate sign position.
Any other characters will cause the method to stop and return the current
result to the caller.
Returns `{number, new_buffer}` where `number` is the integer that was
found (or 0 if no number found there) and `new_buffer` is the charlist
following the number that was parsed.
"""
@spec from_decimal_charlist(b :: charlist) :: {integer, charlist}
def from_decimal_charlist(b) when is_list(b) do
b = skip_white_space(b)
{sign, b} = parse_sign(b)
{n, b} = parse_digits(0, b)

cover {sign * n, b}
end

defp skip_white_space([?\s | b]), do: skip_white_space(b)
defp skip_white_space(b), do: b

defp parse_sign([?- | b]), do: cover({-1, b})
defp parse_sign([?+ | b]), do: cover({1, b})
defp parse_sign(b), do: cover({1, b})

defp parse_digits(n, [d | b]) when d >= ?0 and d <= ?9, do: parse_digits(n * 10 + (d - ?0), b)
defp parse_digits(n, b), do: cover({n, b})
end
14 changes: 14 additions & 0 deletions test/xgit/util/parse_decimal_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule Xgit.Util.ParseDecimalTest do
use ExUnit.Case, async: true

import Xgit.Util.ParseDecimal

test "from_decimal_charlist/1" do
assert from_decimal_charlist('abc') == {0, 'abc'}
assert from_decimal_charlist('0abc') == {0, 'abc'}
assert from_decimal_charlist('99') == {99, ''}
assert from_decimal_charlist('+99x') == {99, 'x'}
assert from_decimal_charlist(' -42 ') == {-42, ' '}
assert from_decimal_charlist(' xyz') == {0, 'xyz'}
end
end

0 comments on commit 32ecea6

Please sign in to comment.