From 61728ab3fd4426623ca7727af566df174a0c1fe7 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Thu, 30 Mar 2017 16:23:16 +0300 Subject: [PATCH] CURL sample, copyright update --- cmd/interop | 14 ++++ cmd/konanc | 14 ++++ cmd/kotlinc | 2 +- cmd/kotlinc-native | 2 +- samples/libcurl/README.md | 10 +++ samples/libcurl/build.sh | 27 +++++++ samples/libcurl/callbacks.h | 8 +++ samples/libcurl/libcurl.def | 2 + samples/libcurl/libcurl.iml | 14 ++++ samples/libcurl/src/main.kt | 3 + samples/libcurl/src/org/konan/libcurl/CUrl.kt | 72 +++++++++++++++++++ .../libcurl/src/org/konan/libcurl/Event.kt | 29 ++++++++ .../libcurl/src/org/konan/libcurl/Program.kt | 23 ++++++ 13 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 samples/libcurl/README.md create mode 100755 samples/libcurl/build.sh create mode 100755 samples/libcurl/callbacks.h create mode 100755 samples/libcurl/libcurl.def create mode 100755 samples/libcurl/libcurl.iml create mode 100755 samples/libcurl/src/main.kt create mode 100755 samples/libcurl/src/org/konan/libcurl/CUrl.kt create mode 100755 samples/libcurl/src/org/konan/libcurl/Event.kt create mode 100755 samples/libcurl/src/org/konan/libcurl/Program.kt diff --git a/cmd/interop b/cmd/interop index 39e935a71a0..f1582f46381 100644 --- a/cmd/interop +++ b/cmd/interop @@ -1,4 +1,18 @@ #!/usr/bin/env bash +# +# Copyright 2010-2017 JetBrains s.r.o. +# +# 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. if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then JAVACMD="$JAVA_HOME/bin/java" diff --git a/cmd/konanc b/cmd/konanc index 1aa0faf4204..c2e82696ccb 100755 --- a/cmd/konanc +++ b/cmd/konanc @@ -1,4 +1,18 @@ #!/usr/bin/env bash +# +# Copyright 2010-2017 JetBrains s.r.o. +# +# 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. if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then JAVACMD="$JAVA_HOME/bin/java" diff --git a/cmd/kotlinc b/cmd/kotlinc index 84a6cd7dbdc..be05831054e 100755 --- a/cmd/kotlinc +++ b/cmd/kotlinc @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2010-2015 JetBrains s.r.o. +# Copyright 2010-2017 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/cmd/kotlinc-native b/cmd/kotlinc-native index 84a6cd7dbdc..be05831054e 100755 --- a/cmd/kotlinc-native +++ b/cmd/kotlinc-native @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2010-2015 JetBrains s.r.o. +# Copyright 2010-2017 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/samples/libcurl/README.md b/samples/libcurl/README.md new file mode 100644 index 00000000000..0df731f88ff --- /dev/null +++ b/samples/libcurl/README.md @@ -0,0 +1,10 @@ +# HTTP client + + This example shows how to communicate with libcurl, HTTP/HTTPS/FTP/etc client library. +To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling). + +To run use + + ./Curl.kexe https://jetbrains.com + +It will perform HTTP get and print out the data obtained. diff --git a/samples/libcurl/build.sh b/samples/libcurl/build.sh new file mode 100755 index 00000000000..6028463716a --- /dev/null +++ b/samples/libcurl/build.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +PATH=../../dist/bin:../../bin:$PATH +DIR=. + +CFLAGS_macbook=-I/opt/local/include +CFLAGS_linux=-I/usr/include +LINKER_ARGS_macbook="-L/opt/local/lib -lcurl" +LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lcurl" + +if [ x$TARGET == x ]; then +case "$OSTYPE" in + darwin*) TARGET=macbook ;; + linux*) TARGET=linux ;; + *) echo "unknown: $OSTYPE" && exit 1;; +esac +fi + +var=CFLAGS_${TARGET} +CFLAGS=${!var} +var=LINKER_ARGS_${TARGET} +LINKER_ARGS=${!var} +var=COMPILER_ARGS_${TARGET} +COMPILER_ARGS=${!var} # add -opt for an optimized build. + +interop -copt:"$CFLAGS" -copt:-I. -def:$DIR/libcurl.def -target:$TARGET || exit 1 +konanc -target $TARGET src libcurl -nativelibrary libcurlstubs.bc -linkerArgs "$LINKER_ARGS" -o Curl.kexe || exit 1 diff --git a/samples/libcurl/callbacks.h b/samples/libcurl/callbacks.h new file mode 100755 index 00000000000..14d1fbe6bee --- /dev/null +++ b/samples/libcurl/callbacks.h @@ -0,0 +1,8 @@ +#include + +// Those types are needed but not defined or used in libcurl headers. +typedef size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata); +typedef size_t write_data_callback(void *buffer, size_t size, size_t nmemb, void *userp); + +extern void something_using_callback1(header_callback*); +extern void something_using_callback2(write_data_callback*); diff --git a/samples/libcurl/libcurl.def b/samples/libcurl/libcurl.def new file mode 100755 index 00000000000..1305a1b5348 --- /dev/null +++ b/samples/libcurl/libcurl.def @@ -0,0 +1,2 @@ +headers = curl/curl.h callbacks.h +excludedFunctions = zopen pfctlinput diff --git a/samples/libcurl/libcurl.iml b/samples/libcurl/libcurl.iml new file mode 100755 index 00000000000..f7bc7ef6e74 --- /dev/null +++ b/samples/libcurl/libcurl.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/libcurl/src/main.kt b/samples/libcurl/src/main.kt new file mode 100755 index 00000000000..5c86e12e40b --- /dev/null +++ b/samples/libcurl/src/main.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + org.konan.libcurl.main(args) +} \ No newline at end of file diff --git a/samples/libcurl/src/org/konan/libcurl/CUrl.kt b/samples/libcurl/src/org/konan/libcurl/CUrl.kt new file mode 100755 index 00000000000..b75d2e69e47 --- /dev/null +++ b/samples/libcurl/src/org/konan/libcurl/CUrl.kt @@ -0,0 +1,72 @@ +package org.konan.libcurl + +import kotlinx.cinterop.* +import libcurl.* + +class CUrl(val url: String) { + val repositoryIndex = repository.run { + val index = size + add(this@CUrl) + index + } + + val curl = curl_easy_init(); + + init { + curl_easy_setopt(curl, CURLOPT_URL, url) + val header: CPointer = staticCFunction(::header_callback) + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header) + curl_easy_setopt(curl, CURLOPT_HEADERDATA, interpretCPointer(nativeNullPtr + 1 + repositoryIndex.toLong())) + } + + val header = Event() + val data = Event() + + fun fetch() { + val res = curl_easy_perform(curl) + if (res != CURLE_OK) + println("curl_easy_perform() failed: ${curl_easy_strerror(res)}") + } + + fun close() { + curl_easy_cleanup(curl) + // Cannot remove urls from repository because it would change other indices + // We could potentially remove it and update all indices in tails + repository[repositoryIndex] = null + } + + companion object { + val repository = ArrayList() + } +} + +fun CPointer.toKString(length: Int): String { + val bytes = ByteArray(length) + nativeMemUtils.getByteArray(pointed, bytes, length) + return kotlin.text.fromUtf8Array(bytes, 0, bytes.size) +} + +fun header_callback(buffer: CPointer?, size: size_t, nitems: size_t, userdata: COpaquePointer?): size_t { + if (buffer == null) return 0 + val header = buffer.toKString((size * nitems).toInt()).trim() + if (userdata != null) { + val id = userdata.rawValue.toLong() - 1 + val curl = CUrl.repository[id.toInt()] + if (curl != null) + curl.header(header) + } + return size * nitems +} + +/* +fun write_callback(buffer: COpaquePointer?, size: size_t, nitems: size_t, userdata: COpaquePointer?): size_t { + if (buffer == null) return 0 + if (userdata != null) { + val id = userdata.rawValue.toLong() - 1 + val curl = CUrl.repository[id.toInt()] + if (curl != null) + curl.data(buffer.) + } + return size * nitems +} +*/ diff --git a/samples/libcurl/src/org/konan/libcurl/Event.kt b/samples/libcurl/src/org/konan/libcurl/Event.kt new file mode 100755 index 00000000000..388a6e2c619 --- /dev/null +++ b/samples/libcurl/src/org/konan/libcurl/Event.kt @@ -0,0 +1,29 @@ +package org.konan.libcurl + +typealias EventHandler = (T) -> Unit +class Event { + private var handlers = emptyList>() + + fun subscribe(handler: EventHandler) { + handlers += handler + } + + fun unsubscribe(handler: EventHandler) { + handlers -= handler + } + + operator fun plusAssign(handler: EventHandler) = subscribe(handler) + operator fun minusAssign(handler: EventHandler) = unsubscribe(handler) + + operator fun invoke(value: T) { + var exception: Throwable? = null + for (handler in handlers) { + try { + handler(value) + } catch (e: Throwable) { + exception = e + } + } + exception?.let { throw it } + } +} \ No newline at end of file diff --git a/samples/libcurl/src/org/konan/libcurl/Program.kt b/samples/libcurl/src/org/konan/libcurl/Program.kt new file mode 100755 index 00000000000..9a4a00334ae --- /dev/null +++ b/samples/libcurl/src/org/konan/libcurl/Program.kt @@ -0,0 +1,23 @@ +package org.konan.libcurl + +fun main(args: Array) { + if (args.size == 0) + return help() + + val curl = CUrl(args[0]) + curl.header += { + println("[H] $it") + } + curl.fetch() + curl.close() + +/* + val write_data: CPointer = staticCFunction(::write_data) + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); +*/ +} + +fun help() { + println("ERROR: missing URL command line argument") +} +