Skip to content

Commit

Permalink
Add Zephir/C PHP extension
Browse files Browse the repository at this point in the history
  • Loading branch information
danhunsaker committed Jul 15, 2018
1 parent 9ed2d25 commit 4944abb
Show file tree
Hide file tree
Showing 167 changed files with 7,580 additions and 38 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,16 @@

/calends
/coverage.htm

.temp/
compile.log
compile-errors.log
.libs/
autom4te.cache/
build/
.deps
*/Makefile
*/Makefile.*
core*
!core*.sh
*~
61 changes: 61 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,68 @@ go:
addons:
apt:
packages:
- valgrind
- gdb
- libpcre3-dev

matrix:
allow_failures:
- language: php
php: '7.0'
- language: php
php: 'nightly'
include:
- &phpDefaults
language: php
php: '7.2'
before_install:
- export ZEPHIR_VERSION="development"
- export ZEPHIR_PARSER_VERSION="v1.1.2"
- export RE2C_VERSION=1.0.3
- export PHP_MAJOR="$(`phpenv which php` -r 'echo phpversion();' | cut -d '.' -f 1)"
- export PHP_MINOR="$(`phpenv which php` -r 'echo phpversion();' | cut -d '.' -f 2)"
install:
- git clone --depth=1 -v https://github.com/phalcon/zephir -b ${ZEPHIR_VERSION}
- cd zephir
- bash ./unit-tests/ci/install-re2c $RE2C_VERSION
- bash ./unit-tests/ci/install_zephir_parser.sh
- ./install -c
- cd ..
before_script:
- |
GIMME_OUTPUT="$(gimme 1.10 | tee -a ${HOME}/.bashrc)" && eval "$GIMME_OUTPUT"
export GOPATH=${HOME}/gopath
export PATH=${GOPATH}/bin:$PATH
mkdir -p ${GOPATH}/src/github.com/danhunsaker/calends
rsync -az ${TRAVIS_BUILD_DIR}/ ${GOPATH}/src/github.com/danhunsaker/calends/
export TRAVIS_BUILD_DIR=${GOPATH}/src/github.com/danhunsaker/calends
- |
cd ${TRAVIS_BUILD_DIR}
go get -t -v ./...
- |
cd ${TRAVIS_BUILD_DIR}/libcalends
go build -o libcalends.so -buildmode=c-shared .
- |
cd ${TRAVIS_BUILD_DIR}/libcalends/php
zephir builddev -v
- echo "set auto-load safe-path /" > ~/.gdbinit
- ulimit -c unlimited || true
- echo '/tmp/core_%e.%p' | sudo tee /proc/sys/kernel/core_pattern &> /dev/null
- sudo chmod +s $(which gdb)
script:
- |
cd ${TRAVIS_BUILD_DIR}/libcalends/php/ext
TRAVIS='' NO_INTERACTION=true php run-tests.php -P -d "extension=calends.so"
- ${TRAVIS_BUILD_DIR}/tests/failed_test_info.sh

- << : *phpDefaults
php: '7.1'

- << : *phpDefaults
php: '7.0'

- << : *phpDefaults
php: 'nightly'

before_script:
- echo "set auto-load safe-path /" > ~/.gdbinit
Expand Down
40 changes: 40 additions & 0 deletions boxfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
run.config:
engine: php#option/no-default-cache-dirs
engine.config:
runtime: php-7.1
extensions:
- xml
- zephir_parser
extra_packages:
- go
- autoconf
- re2c
cache_dirs:
- .gopath
extra_path_dirs:
- .gopath/bin
cwd: /app/.gopath/src/github.com/danhunsaker/calends
extra_steps:
- |
# Set up Go stuff
export GOPATH=/app/.gopath
echo /app/.gopath > /data/etc/env.d/GOPATH
mkdir -p /app/.gopath/{bin,src/github.com/danhunsaker}
ln -sfT /app /app/.gopath/src/github.com/danhunsaker/calends
cd /app/.gopath/src/github.com/danhunsaker/calends
go get -t -v ./...
- |
# Install Zephir
cd /data
if [ ! -d zephir ]
then
git clone https://github.com/phalcon/zephir
cd zephir
else
cd zephir
git pull
fi
sed "s#%ZEPHIRDIR%#$(pwd)#g" bin/zephir > bin/zephir-cmd
chmod 755 bin/zephir-cmd
cp bin/zephir-cmd /data/bin/zephir
rm bin/zephir-cmd
22 changes: 22 additions & 0 deletions calendars/0calendars.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package calendars
import (
"errors"
// "fmt"
"sort"
"strings"
)

Expand Down Expand Up @@ -45,6 +46,8 @@ var (
ErrInvalidFormat = errors.New("Invalid Format")
)

// ErrUnknownCalendar generates a "calendar not registered" error including the
// calendar's actual name in the error message
func ErrUnknownCalendar(calendar string) error {
return errors.New("Unknown Calendar: " + calendar)
}
Expand Down Expand Up @@ -84,12 +87,31 @@ func RegisterElements(
}
}

// Unregister removes a calendar system from the callback list.
func Unregister(name string) {
if Registered(name) {
delete(registeredCalendars, canonCalendarName(name))
}
}

// Registered returns whether or not a calendar system has been registered, yet.
func Registered(calendar string) bool {
_, set := registeredCalendars[canonCalendarName(calendar)]
return set
}

// ListRegistered returns the list of calendar systems currently registered.
func ListRegistered() []string {
var out []string

for name := range registeredCalendars {
out = append(out, name)
}
sort.Strings(out)

return out
}

// DefaultFormat returns the associated value from a registered calendar system.
func DefaultFormat(calendar string) string {
if !Registered(calendar) {
Expand Down
39 changes: 39 additions & 0 deletions calendars/0calendars_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package calendars

import (
"errors"
"strings"
"testing"
)

Expand Down Expand Up @@ -56,6 +57,21 @@ func TestRegisterElements(t *testing.T) {
}
}

func TestUnregister(t *testing.T) {
instance := testCalendarClass{}
RegisterClass("testCalendarClass", instance, instance.DefaultFormat)

if !Registered("testCalendarClass") {
t.Errorf("RegisterClass(%#v, %#v) failed", "testCalendarClass", instance)
}

Unregister("testCalendarClass")

if Registered("testCalendarClass") {
t.Errorf("Unregister(%#v) failed", "testCalendarClass")
}
}

func TestRegistered(t *testing.T) {
if Registered("testCalendar") {
t.Errorf("Registered(testCalendar) failed - the calendar should not be registered before the test starts")
Expand All @@ -69,6 +85,29 @@ func TestRegistered(t *testing.T) {
}
}

func TestListRegistered(t *testing.T) {
Unregister("testCalendar")
Unregister("testCalendarClass")
Unregister("testCalendarElements")

got := ListRegistered()
want := []string{"Gregorian", "Jdc", "Stardate", "Tai64", "Unix"}
if strings.Join(got, ":") != strings.Join(want, ":") {
t.Errorf("ListRegistered() failed - the calendar list was incorrect:\n\twant: %v\n\t got: %v", want, got)
}

instance := testCalendarClass{"test"}
RegisterClass("teSt CaLenDar", instance, instance.DefaultFormat)

got = ListRegistered()
want = []string{"Gregorian", "Jdc", "Stardate", "Tai64", "TestCalendar", "Unix"}
if strings.Join(got, ":") != strings.Join(want, ":") {
t.Errorf("ListRegistered() failed - the calendar list was incorrect:\n\twant: %v\n\t got: %v", want, got)
}

Unregister("test calendar")
}

func TestDefaultFormat(t *testing.T) {
if !Registered("testCalendar") {
TestRegistered(t)
Expand Down
8 changes: 4 additions & 4 deletions calendars/0leapseconds.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,16 @@ func init() {
// UTCtoTAI removes the UTC leap second offset from a TAI64NAXURTime value.
func UTCtoTAI(utc TAI64NAXURTime) (tai TAI64NAXURTime) {
// Calculate year, month, day
oldYear, oldMonth, oldDay := time.Unix(utc.Seconds, int64(utc.Nano)).Date()
oldYear, oldMonth, oldDay := time.Unix(utc.Seconds, int64(utc.Nano)).UTC().Date()
// Remove the leap second offset
tai = utc.Sub(getTAIOffset(oldYear, oldMonth, oldDay))

// Ensure we used the correct offset
newYear, newMonth, newDay := time.Unix(tai.Seconds, int64(tai.Nano)).Date()
newYear, newMonth, newDay := time.Unix(tai.Seconds, int64(tai.Nano)).UTC().Date()
for newYear != oldYear || newMonth != oldMonth || newDay != oldDay {
tai = utc.Sub(getTAIOffset(newYear, newMonth, newDay))
oldYear, oldMonth, oldDay = newYear, newMonth, newDay
newYear, newMonth, newDay = time.Unix(tai.Seconds, int64(tai.Nano)).Date()
newYear, newMonth, newDay = time.Unix(tai.Seconds, int64(tai.Nano)).UTC().Date()
}

return
Expand All @@ -148,7 +148,7 @@ func UTCtoTAI(utc TAI64NAXURTime) (tai TAI64NAXURTime) {
// TAItoUTC adds the UTC leap second offset to a TAI64NAXURTime value.
func TAItoUTC(tai TAI64NAXURTime) (utc TAI64NAXURTime) {
// Calculate year, month, day
year, month, day := time.Unix(tai.Seconds, int64(tai.Nano)).Date()
year, month, day := time.Unix(tai.Seconds, int64(tai.Nano)).UTC().Date()
// Add the leap second offset
utc = tai.Add(getTAIOffset(year, month, day))

Expand Down
6 changes: 3 additions & 3 deletions calendars/gregorian.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func init() {
},
// fromInternal
func(stamp TAI64NAXURTime, format string) (date string, err error) {
tmp := time.Unix(stamp.Seconds, int64(stamp.Nano))
tmp := time.Unix(stamp.Seconds, int64(stamp.Nano)).UTC()
if strings.ContainsRune(format, '%') {
date, err = datefmt.Strftime(format, tmp)
} else {
Expand All @@ -82,7 +82,7 @@ func init() {
switch offset.(type) {
case time.Duration:
dur := offset.(time.Duration)
r := time.Unix(in.Seconds, int64(in.Nano)).Add(dur)
r := time.Unix(in.Seconds, int64(in.Nano)).UTC().Add(dur)
out.Seconds = r.Unix()
out.Nano = uint32(r.Nanosecond())
return
Expand All @@ -101,7 +101,7 @@ func init() {
w.Add(when_en.All...)
w.Add(when_common.All...)

r, err := w.Parse(str, time.Unix(in.Seconds, int64(in.Nano)))
r, err := w.Parse(str, time.Unix(in.Seconds, int64(in.Nano)).UTC())
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion calendars/gregorian_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestGregorianToInternal(t *testing.T) {
{"in": []interface{}{"1970-01-01 00:00:01 UTC", "2006-01-02 15:04:05 MST"}, "want": []interface{}{TAI64NAXURTimeFromDecimalString("-6.997489999999999987778664944926276803016662598"), nil}},
{"in": []interface{}{"1970-01-01 00:00:01 UTC", "%Y-%m-%d %H:%M:%S %Z"}, "want": []interface{}{TAI64NAXURTimeFromDecimalString("-6.997489999999999987778664944926276803016662598"), nil}},
{"in": []interface{}{[]byte("Thu, 01 Jan 1970 00:00:01 UTC"), ""}, "want": []interface{}{TAI64NAXURTimeFromDecimalString("-6.997489999999999987778664944926276803016662598"), nil}},
{"in": []interface{}{time.Unix(1, 0), ""}, "want": []interface{}{TAI64NAXURTimeFromDecimalString("-6.997489999999999987778664944926276803016662598"), nil}},
{"in": []interface{}{time.Unix(1, 0).UTC(), ""}, "want": []interface{}{TAI64NAXURTimeFromDecimalString("-6.997489999999999987778664944926276803016662598"), nil}},

{"in": []interface{}{1, ""}, "want": []interface{}{TAI64NAXURTime{}, ErrUnsupportedInput}},
{"in": []interface{}{1., ""}, "want": []interface{}{TAI64NAXURTime{}, ErrUnsupportedInput}},
Expand Down
9 changes: 4 additions & 5 deletions calendars/stardate.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,8 @@ func stardateOffset(in TAI64NAXURTime, offset interface{}) (out TAI64NAXURTime,
_, err = fmt.Sscanf(mod, "%s %s", &date, &format)
if err != nil && err.Error() != "EOF" {
return
} else {
err = nil
}
err = nil

adjust, err = stardateToInternal(date, format)
if err != nil {
Expand Down Expand Up @@ -399,7 +398,7 @@ func stardateJDCToMain(jdc big.Float) string {
issue, _ = tmp.Quo(stardate, big.NewFloat(10000.0)).Int64()
stardate.Sub(stardate, big.NewFloat(float64(10000*issue)))
if stardate.Cmp(big.NewFloat(0)) < 0 {
issue -= 1
issue--
stardate.Add(stardate, big.NewFloat(10000))
}
format = "[%d]%04.6g"
Expand Down Expand Up @@ -479,9 +478,9 @@ func stardatePughToJDC(stardate string, fixed bool) big.Float {

if fixed {
return *new(big.Float).Add(stardatePughEpoch, new(big.Float).Mul(new(big.Float).Add(new(big.Float).SetInt64(prefix), new(big.Float).Quo(suffix, big.NewFloat(1000.0))), big.NewFloat(365.2425)))
} else {
return yearfToJDC(*new(big.Float).Add(new(big.Float).Add(new(big.Float).SetInt64(prefix), big.NewFloat(2323.0)), new(big.Float).Quo(suffix, big.NewFloat(1000.0))))
}

return yearfToJDC(*new(big.Float).Add(new(big.Float).Add(new(big.Float).SetInt64(prefix), big.NewFloat(2323.0)), new(big.Float).Quo(suffix, big.NewFloat(1000.0))))
}

func stardateJDCToPugh(jdc big.Float, fixed bool) string {
Expand Down
2 changes: 1 addition & 1 deletion calends.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type Calends struct {
}

// Version of the library
var Version string = "0.0.3"
var Version = "0.0.3"

// Create is the mechanism for constructing new Calends objects.
/*
Expand Down
11 changes: 11 additions & 0 deletions libcalends/calendars.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import "C"

import (
"math/big"
"strings"
"unsafe"

"github.com/danhunsaker/calends/calendars"
Expand Down Expand Up @@ -84,11 +85,21 @@ func Calends_calendar_register(
)
}

//export Calends_calendar_unregister
func Calends_calendar_unregister(name *C.char) {
calendars.Unregister(C.GoString(name))
}

//export Calends_calendar_registered
func Calends_calendar_registered(calendar *C.char) bool {
return calendars.Registered(C.GoString(calendar))
}

//export Calends_calendar_list_registered
func Calends_calendar_list_registered() *C.char {
return C.CString(strings.Join(calendars.ListRegistered(), "\n"))
}

//export TAI64Time_add
func TAI64Time_add(t C.TAI64Time, z C.TAI64Time) C.TAI64Time {
base := taiCToGo(t)
Expand Down
Loading

1 comment on commit 4944abb

@danhunsaker
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.