@effekt-lang/effekt 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/effekt +0 -0
- package/libraries/common/bytearray.effekt +71 -0
- package/libraries/common/effekt.effekt +8 -8
- package/libraries/common/io/console.effekt +1 -2
- package/libraries/common/io/filesystem.effekt +46 -62
- package/libraries/common/io/network.effekt +9 -9
- package/libraries/common/io/time.effekt +1 -1
- package/libraries/common/io.effekt +5 -5
- package/libraries/common/ref.effekt +1 -1
- package/libraries/common/string.effekt +3 -14
- package/libraries/js/effekt_builtins.js +5 -1
- package/libraries/js/effekt_runtime.js +185 -352
- package/libraries/llvm/bytearray.c +209 -0
- package/libraries/llvm/forward-declare-c.ll +23 -23
- package/libraries/llvm/io.c +13 -15
- package/libraries/llvm/main.c +3 -3
- package/libraries/llvm/rts.ll +267 -159
- package/libraries/llvm/types.c +3 -2
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/package.json +1 -1
- package/libraries/common/bytes.effekt +0 -115
- package/libraries/js/unsafe/cont.effekt +0 -11
- package/libraries/llvm/buffer.c +0 -286
- package/licenses/mit license - mit-license.html +0 -1240
- package/licenses/the bsd license - bsd-license.html +0 -1236
- package/licenses/the mit license - mit.html +0 -1240
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!doctype html><html lang=en><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Eclipse Public License 2.0 (EPL) | The Eclipse Foundation</title><meta property="og:title" content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=twitter:title content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta property="og:description" content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=twitter:description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=author content="Wayne Beaton"><link href=/favicon.ico rel=icon type=image/x-icon><meta property="og:image" content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:image content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:card content="summary"><meta name=twitter:site content="@eclipsefdn"><meta name=twitter:creator content="@eclipsefdn"><meta property="og:url" content="https://www.eclipse.org/legal/epl-2.0/"><meta property="og:type" content="website"><meta property="og:site_name" content="Eclipse Foundation"><meta name=keywords content="epl,epl-2.0,legal,foundation,eclipse,eclipse public license,license,licenses"><meta name=generator content="Hugo 0.110.0"><link rel=canonical href=https://www.eclipse.org/legal/epl-2.0/><link rel=alternate href=/legal/epl-2.0/index.xml type=application/rss+xml title><link rel=stylesheet href="/public/css/styles.css?v=
|
|
1
|
+
<!doctype html><html lang=en><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Eclipse Public License 2.0 (EPL) | The Eclipse Foundation</title><meta property="og:title" content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=twitter:title content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta property="og:description" content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=twitter:description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=author content="Wayne Beaton"><link href=/favicon.ico rel=icon type=image/x-icon><meta property="og:image" content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:image content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:card content="summary"><meta name=twitter:site content="@eclipsefdn"><meta name=twitter:creator content="@eclipsefdn"><meta property="og:url" content="https://www.eclipse.org/legal/epl-2.0/"><meta property="og:type" content="website"><meta property="og:site_name" content="Eclipse Foundation"><meta name=keywords content="epl,epl-2.0,legal,foundation,eclipse,eclipse public license,license,licenses"><meta name=generator content="Hugo 0.110.0"><link rel=canonical href=https://www.eclipse.org/legal/epl-2.0/><link rel=alternate href=/legal/epl-2.0/index.xml type=application/rss+xml title><link rel=stylesheet href="/public/css/styles.css?v=1730052909"><script>(function(e,t,n,s,o){e[s]=e[s]||[],e[s].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var a=t.getElementsByTagName(n)[0],i=t.createElement(n),r=s!="dataLayer"?"&l="+s:"";i.async=!0,i.src="https://www.googletagmanager.com/gtm.js?id="+o+r,a.parentNode.insertBefore(i,a)})(window,document,"script","dataLayer","GTM-5WLCZXC")</script><script>var tableClasses="table"</script><link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet type=text/css></head><body><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5WLCZXC" height=0 width=0 style=display:none;visibility:hidden></iframe></noscript><a class=sr-only href=#content>Skip to main content</a><header class="header-wrapper header-wrapper" id=header><div class=header-toolbar><div class=container><div class=header-toolbar-row><div class="toolbar-btn toolbar-search-btn dropdown"><button class=dropdown-toggle id=toolbar-search type=button data-toggle=dropdown tabindex=0 aria-label=Search>
|
|
2
2
|
<i class="fa fa-search fa-lg" aria-role=none></i></button><div class="toolbar-search-bar-wrapper dropdown-menu dropdown-menu-right" aria-labelledby=toolbar-search><form action=https://www.eclipse.org/home/search method=get><div class=search-bar><input class=search-bar-input name=q placeholder=Search>
|
|
3
3
|
<button>
|
|
4
4
|
<i class="fa fa-search" type=submit></i></button></div></form></div></div><div class="toolbar-btn toolbar-user-menu-btn dropdown"><button class=dropdown-toggle id=toolbar-user-menu type=button data-toggle=dropdown tabindex=0 aria-label="User Menu">
|
|
@@ -57,5 +57,5 @@ open source software collaboration and innovation.</p></div><div class=mega-menu
|
|
|
57
57
|
<i class="fa fa-linkedin fa-stack-1x fa-inverse" aria-hidden=true></i>
|
|
58
58
|
<span class=sr-only>Linkedin account</span></span></a></li></ul></div></div><div class="footer-sections row equal-height-md font-bold"><div class=col-md-15><div class=row><section id=footer-eclipse-foundation class="footer-section col-sm-8"><div class=menu-heading>Eclipse Foundation</div><ul class=nav><li><a href=https://www.eclipse.org/org/>About</a></li><li><a href=https://projects.eclipse.org/>Projects</a></li><li><a href=https://www.eclipse.org/collaborations/>Collaborations</a></li><li><a href=https://www.eclipse.org/membership/>Membership</a></li><li><a href=https://www.eclipse.org/sponsor/>Sponsor</a></li></ul></section><section id=footer-legal class="footer-section col-sm-8"><div class=menu-heading>Legal</div><ul class=nav><li><a href=https://www.eclipse.org/legal/privacy/>Privacy Policy</a></li><li><a href=https://www.eclipse.org/legal/terms-of-use/>Terms of Use</a></li><li><a href=https://www.eclipse.org/legal/compliance/>Compliance</a></li><li><a href=https://www.eclipse.org/org/documents/Community_Code_of_Conduct.php>Code of Conduct</a></li><li><a href=https://www.eclipse.org/legal/>Legal Resources</a></li><li><a class=toolbar-manage-cookies href=# onclick=event.preventDefault()>Manage Cookies</a></li></ul></section><section id=footer-more class="footer-section col-sm-8"><div class=menu-heading>More</div><ul class=nav><li><a href=https://www.eclipse.org/security/>Report a Vulnerability</a></li><li><a href=https://status.eclipse.org/>Service Status</a></li><li><a href=https://www.eclipse.org/org/foundation/contact.php>Contact Us</a></li><li><a href=https://www.eclipse.org/projects/support/>Support</a></li></ul></section></div></div><div id=footer-end class="footer-section col-md-8 col-md-offset-1 col-sm-24"><div class=footer-end-newsletter><form id=mc-embedded-subscribe-form action=https://eclipsecon.us6.list-manage.com/subscribe/post method=post novalidate target=_blank><label class=footer-end-newsletter-label for=email>Subscribe to our Newsletter</label><div class=footer-end-newsletter-input-wrapper><input class=footer-end-newsletter-input type=email id=email name=EMAIL autocomplete=email placeholder="Enter your email address"><div><i class="fa fa-solid fa-envelope fa-lg" aria-hidden=true></i></div></div><input type=hidden name=u value=eaf9e1f06f194eadc66788a85>
|
|
59
59
|
<input type=hidden name=id value=46e57eacf1>
|
|
60
|
-
<input id=mc-embedded-subscribe type=submit name=subscribe hidden></form></div></div></div><div class="col-sm-24 margin-top-20"><div class=row><div id=copyright class=col-md-16><p id=copyright-text>Copyright © Eclipse Foundation AISBL. All Rights Reserved.</p></div></div></div><a href=# class=scrollup>Back to the top</a></div></footer><div id=footer-js><script src="/public/js/main.js?v1.0?v=
|
|
60
|
+
<input id=mc-embedded-subscribe type=submit name=subscribe hidden></form></div></div></div><div class="col-sm-24 margin-top-20"><div class=row><div id=copyright class=col-md-16><p id=copyright-text>Copyright © Eclipse Foundation AISBL. All Rights Reserved.</p></div></div></div><a href=# class=scrollup>Back to the top</a></div></footer><div id=footer-js><script src="/public/js/main.js?v1.0?v=1730052909"></script>
|
|
61
61
|
<script>(function(){})(jQuery,document)</script></div></body></html>
|
package/package.json
CHANGED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
module bytes
|
|
2
|
-
|
|
3
|
-
/// A memory managed, mutable, fixed-length buffer of bytes.
|
|
4
|
-
extern type Bytes
|
|
5
|
-
// = llvm "%Pos"
|
|
6
|
-
// = js "Uint8Array"
|
|
7
|
-
|
|
8
|
-
/// Allocates new bytes with the given `capacity`, setting its values to `0`.
|
|
9
|
-
extern io def bytes(capacity: Int): Bytes =
|
|
10
|
-
js "(new Uint8Array(${capacity}))"
|
|
11
|
-
llvm """
|
|
12
|
-
%buf = call %Pos @c_buffer_construct_uninitialized(i64 ${capacity})
|
|
13
|
-
ret %Pos %buf
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
def copy(b: Bytes): Bytes = {
|
|
17
|
-
val len = b.size
|
|
18
|
-
val clone = bytes(len)
|
|
19
|
-
copy(b, clone, 0, 0, len)
|
|
20
|
-
clone
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
extern io def copy(from: Bytes, to: Bytes, startFrom: Int, startTo: Int, length: Int): Unit =
|
|
24
|
-
js "bytes$copy(${from}, ${to}, ${startFrom}, ${startTo}, ${length})"
|
|
25
|
-
llvm """
|
|
26
|
-
call void @c_buffer_copy(%Pos ${from}, %Pos ${to}, i64 ${startFrom}, i64 ${startTo}, i64 ${length})
|
|
27
|
-
; return Unit
|
|
28
|
-
ret %Pos zeroinitializer
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
extern pure def size(b: Bytes): Int =
|
|
32
|
-
js "${b}.length"
|
|
33
|
-
llvm """
|
|
34
|
-
%size = call i64 @c_buffer_length(%Pos ${b})
|
|
35
|
-
ret i64 %size
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
extern io def read(b: Bytes, index: Int): Byte =
|
|
39
|
-
js "(${b})[${index}]"
|
|
40
|
-
llvm """
|
|
41
|
-
%byte = call i8 @c_buffer_index(%Pos ${b}, i64 ${index})
|
|
42
|
-
ret i8 %byte
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
// TODO should return the number of bytes written.
|
|
46
|
-
extern io def write(b: Bytes, index: Int, value: Byte): Unit =
|
|
47
|
-
js "bytes$set(${b}, ${index}, ${value})"
|
|
48
|
-
llvm """
|
|
49
|
-
call void @c_buffer_set(%Pos ${b}, i64 ${index}, i8 ${value})
|
|
50
|
-
; return Unit
|
|
51
|
-
ret %Pos zeroinitializer
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
/// Returns an *aliased* slice of b starting at offset with the given length
|
|
55
|
-
def slice(b: Bytes, offset: Int, length: Int): Bytes = {
|
|
56
|
-
def validOffset() = offset >= 0 && offset < b.size
|
|
57
|
-
def validLength() = length >= 0 && (offset + length) <= b.size
|
|
58
|
-
if (validOffset() && validLength()) unsafe::slice(b, offset, length)
|
|
59
|
-
else panic("Invalid slice of bytes (size: " ++ b.size.show ++ ", offset: " ++ offset.show ++ ", length: " ++ length.show ++ ")")
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
/// Returns a view into the buffer, with the length truncated to n
|
|
64
|
-
def truncated(b: Bytes, n: Int): Bytes =
|
|
65
|
-
b.slice(0, n)
|
|
66
|
-
|
|
67
|
-
extern pure def fromUTF8(s: String): Bytes =
|
|
68
|
-
js "(new TextEncoder().encode(${s}))"
|
|
69
|
-
llvm """
|
|
70
|
-
%copy = call %Pos @c_buffer_clone(%Pos ${s})
|
|
71
|
-
ret %Pos %copy
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
extern pure def toUTF8(b: Bytes): String =
|
|
75
|
-
js "(new TextDecoder('utf-8').decode(${b}))"
|
|
76
|
-
// assuming the buffer is already in UTF-8
|
|
77
|
-
llvm """
|
|
78
|
-
%copy = call %Pos @c_buffer_clone(%Pos ${b})
|
|
79
|
-
ret %Pos %copy
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
namespace unsafe {
|
|
83
|
-
/// Unsafe: offset and length are not checked.
|
|
84
|
-
extern io def slice(b: Bytes, offset: Int, length: Int): Bytes =
|
|
85
|
-
js "new Uint8Array(${b}.buffer, ${offset}, ${length})"
|
|
86
|
-
llvm """
|
|
87
|
-
%buf = call %Pos @c_buffer_slice(%Pos ${b}, i64 ${offset}, i64 ${length})
|
|
88
|
-
ret %Pos %buf
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
extern js """
|
|
95
|
-
function bytes$set(bytes, index, value) {
|
|
96
|
-
bytes[index] = value;
|
|
97
|
-
return $effekt.unit;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function bytes$clone(original) {
|
|
101
|
-
let copy = new Uint8Array(original.length);
|
|
102
|
-
copy.set(original);
|
|
103
|
-
return copy;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function bytes$copy(from, to, startFrom, startTo, length) {
|
|
107
|
-
// Check bounds
|
|
108
|
-
if (startFrom + length > from.length || startTo + length > to.length) {
|
|
109
|
-
throw new RangeError('Index out of bounds');
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Create a subarray of 'from' and set it into 'to'
|
|
113
|
-
to.set(from.subarray(startFrom, startFrom + length), startTo);
|
|
114
|
-
}
|
|
115
|
-
"""
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
module unsafe/cont
|
|
2
|
-
|
|
3
|
-
// The type of a captured continuation
|
|
4
|
-
extern type Cont[A, B]
|
|
5
|
-
|
|
6
|
-
// we mark this as {io} since pure functions should not take block parameters.
|
|
7
|
-
extern io def cont[A, B] { r: A => B / {} }: Cont[A, B] = js "${box r}"
|
|
8
|
-
|
|
9
|
-
// This is unsafe if the continuation left the scope of the
|
|
10
|
-
// capabilities it closed over
|
|
11
|
-
extern async def apply[A, B](k: Cont[A, B], a: A): B / {} = js "${k}(${a})"
|
package/libraries/llvm/buffer.c
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
#ifndef EFFEKT_BUFFER_C
|
|
2
|
-
#define EFFEKT_BUFFER_C
|
|
3
|
-
|
|
4
|
-
#include "stdlib.h"
|
|
5
|
-
#include <stdint.h>
|
|
6
|
-
#include <string.h> // For memcopy
|
|
7
|
-
|
|
8
|
-
/** We represent buffers like positive types.
|
|
9
|
-
*
|
|
10
|
-
* - The field `tag` contains offset (32bit) and length (32bit), which is equal to
|
|
11
|
-
* the tag (64bit) in Pos;
|
|
12
|
-
* - The field `obj` points to memory with the following layout:
|
|
13
|
-
*
|
|
14
|
-
* +--[ Header ]--+--------------+
|
|
15
|
-
* | Rc | Eraser | Contents ... |
|
|
16
|
-
* +--------------+--------------+
|
|
17
|
-
*
|
|
18
|
-
* The eraser is always a null pointer since it does not need to do anything.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
// TODO It may be performance-advantageous to implement this C file's semantics
|
|
22
|
-
// in LLVM, since the linker cannot realistically be asked to satisfactorily
|
|
23
|
-
// inline.
|
|
24
|
-
// Alternatively, one could drop gcc and combine Effekt-compiler-generated LLVM
|
|
25
|
-
// with clang-generated LLVM from this file's entire translation unit.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
struct Pos c_buffer(const uint32_t offset, const uint32_t length, void* obj) {
|
|
29
|
-
return (struct Pos) {
|
|
30
|
-
.tag = ((uint64_t)offset << 32) | (uint32_t)length,
|
|
31
|
-
.obj = obj,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
void c_buffer_erase_noop(void *envPtr) { (void)envPtr; }
|
|
36
|
-
|
|
37
|
-
uint64_t c_buffer_offset(const struct Pos buffer) {
|
|
38
|
-
return (uint32_t)(buffer.tag >> 32); // Extract offset from the upper 32 bits
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Function to get the length from Pos
|
|
42
|
-
// WARNING: This does not erase the Pos argument!
|
|
43
|
-
uint64_t c_buffer_length(const struct Pos buffer) {
|
|
44
|
-
return (uint32_t)(buffer.tag & 0xFFFFFFFF); // Extract length from the lower 32 bits
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
uint8_t *c_buffer_bytes(const struct Pos buffer) {
|
|
48
|
-
return (uint8_t *) (buffer.obj + sizeof(struct Header) + c_buffer_offset(buffer));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
struct Pos c_buffer_construct(const uint64_t n, const uint8_t *data) {
|
|
52
|
-
uint8_t *obj = (uint8_t *)malloc(sizeof(struct Header) + n * sizeof *obj);
|
|
53
|
-
ASSERT_NON_NULL(obj);
|
|
54
|
-
|
|
55
|
-
struct Header *header = (void*) obj;
|
|
56
|
-
*header = (struct Header) { .rc = 0, .eraser = c_buffer_erase_noop, };
|
|
57
|
-
|
|
58
|
-
// Copy data
|
|
59
|
-
memcpy(obj + sizeof(struct Header), data, n);
|
|
60
|
-
|
|
61
|
-
return c_buffer(0, n, obj);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
struct Pos c_buffer_construct_zeroed(const uint64_t n) {
|
|
65
|
-
uint8_t *zeroes = calloc(sizeof(struct Header) + n, sizeof *zeroes);
|
|
66
|
-
ASSERT_NON_NULL(zeroes)
|
|
67
|
-
|
|
68
|
-
struct Header *header = (void*) zeroes;
|
|
69
|
-
*header = (struct Header) { .rc = 0, .eraser = c_buffer_erase_noop, };
|
|
70
|
-
|
|
71
|
-
return c_buffer(0, n, zeroes);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
struct Pos c_buffer_construct_uninitialized(const uint64_t n) {
|
|
75
|
-
uint8_t *data = malloc(sizeof(struct Header) + n * sizeof *data);
|
|
76
|
-
ASSERT_NON_NULL(data)
|
|
77
|
-
|
|
78
|
-
struct Header *header = (void*) data;
|
|
79
|
-
*header = (struct Header) { .rc = 0, .eraser = c_buffer_erase_noop, };
|
|
80
|
-
|
|
81
|
-
return c_buffer(0, n, data);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
struct Pos c_buffer_slice(struct Pos buffer, const uint64_t offset, const uint64_t length) {
|
|
85
|
-
|
|
86
|
-
if ((c_buffer_offset(buffer) + offset + length) > c_buffer_length(buffer))
|
|
87
|
-
return buffer;
|
|
88
|
-
|
|
89
|
-
return c_buffer(c_buffer_offset(buffer) + offset, length, buffer.obj);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
struct Pos c_buffer_clone(const struct Pos buffer) {
|
|
93
|
-
return c_buffer_construct(c_buffer_length(buffer), c_buffer_bytes(buffer));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
void c_buffer_copy(const struct Pos from, struct Pos to, uint64_t startFrom, uint64_t startTo, uint64_t length) {
|
|
97
|
-
// Check bounds
|
|
98
|
-
if ((startFrom + length > c_buffer_length(from)) || (startTo + length > c_buffer_length(to))) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Get pointers to the source and destination slices
|
|
103
|
-
uint8_t *from_bytes = c_buffer_bytes(from) + startFrom;
|
|
104
|
-
uint8_t *to_bytes = c_buffer_bytes(to) + startTo;
|
|
105
|
-
|
|
106
|
-
// Copy bytes from `from` to `to`
|
|
107
|
-
memcpy(to_bytes, from_bytes, length);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Converts a buffer to a null-terminated string, handling zero bytes by encoding them as non-minimal UTF-8 sequences.
|
|
113
|
-
*
|
|
114
|
-
* Note: the returned pointer needs to be managed manually!
|
|
115
|
-
*
|
|
116
|
-
* @param buffer The buffer to convert.
|
|
117
|
-
* @return A null-terminated string representing the contents of the buffer.
|
|
118
|
-
*/
|
|
119
|
-
char* c_buffer_as_null_terminated_string(const struct Pos buffer) {
|
|
120
|
-
uint64_t length = c_buffer_length(buffer);
|
|
121
|
-
uint64_t zero_runes = 0;
|
|
122
|
-
uint8_t* bytes = c_buffer_bytes(buffer);
|
|
123
|
-
|
|
124
|
-
// Count zero runes
|
|
125
|
-
for (uint64_t j = 0; j < length; ++j) {
|
|
126
|
-
zero_runes += !bytes[j];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Allocate buffer for the null-terminated string
|
|
130
|
-
uint64_t n = length + zero_runes;
|
|
131
|
-
char *buf = (char *) malloc((n + 1) * sizeof(*buf));
|
|
132
|
-
ASSERT_NON_NULL(buf)
|
|
133
|
-
|
|
134
|
-
uint64_t i = 0;
|
|
135
|
-
for (uint64_t j = 0; j < length; ++j) {
|
|
136
|
-
buf[i++] = bytes[j];
|
|
137
|
-
if (buf[i-1] == 0) {
|
|
138
|
-
buf[i-1] = 0xc0; // 0b11000000
|
|
139
|
-
buf[i++] = 0x80; // 0b10000000
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Null-terminate the string
|
|
144
|
-
buf[n] = '\0';
|
|
145
|
-
|
|
146
|
-
return buf;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
struct Pos c_buffer_construct_from_null_terminated_string(const char *data_nt) {
|
|
150
|
-
uint64_t n = 0;
|
|
151
|
-
while (data_nt[++n]);
|
|
152
|
-
|
|
153
|
-
return c_buffer_construct(n, (uint8_t *) data_nt);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
struct Pos c_buffer_concatenate(const struct Pos left, const struct Pos right) {
|
|
158
|
-
const struct Pos concatenated = c_buffer_construct_zeroed(
|
|
159
|
-
c_buffer_length(left) + c_buffer_length(right));
|
|
160
|
-
for (uint64_t j = 0; j < c_buffer_length(concatenated); ++j)
|
|
161
|
-
c_buffer_bytes(concatenated)[j]
|
|
162
|
-
= j < c_buffer_length(left)
|
|
163
|
-
? c_buffer_bytes(left)[j]
|
|
164
|
-
: c_buffer_bytes(right)[j - c_buffer_length(left)];
|
|
165
|
-
|
|
166
|
-
erasePositive(left);
|
|
167
|
-
erasePositive(right);
|
|
168
|
-
return concatenated;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
struct Pos c_buffer_eq(const struct Pos left, const struct Pos right) {
|
|
172
|
-
uint64_t left_len = c_buffer_length(left);
|
|
173
|
-
uint64_t right_len = c_buffer_length(right);
|
|
174
|
-
if (left_len != right_len) {
|
|
175
|
-
erasePositive(left);
|
|
176
|
-
erasePositive(right);
|
|
177
|
-
return BooleanFalse;
|
|
178
|
-
}
|
|
179
|
-
for (uint64_t j = 0; j < left_len; ++j) {
|
|
180
|
-
if (c_buffer_bytes(left)[j] != c_buffer_bytes(right)[j]) {
|
|
181
|
-
erasePositive(left);
|
|
182
|
-
erasePositive(right);
|
|
183
|
-
return BooleanFalse;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
erasePositive(left);
|
|
187
|
-
erasePositive(right);
|
|
188
|
-
return BooleanTrue;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
struct Pos c_buffer_substring(const struct Pos str, uint64_t start, uint64_t end) {
|
|
192
|
-
const struct Pos substr = c_buffer_construct_zeroed(end - start);
|
|
193
|
-
for (uint64_t j = 0; j < c_buffer_length(substr); ++j) {
|
|
194
|
-
c_buffer_bytes(substr)[j] = c_buffer_bytes(str)[start+j];
|
|
195
|
-
}
|
|
196
|
-
erasePositive(str);
|
|
197
|
-
return substr;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
struct Pos c_buffer_show_Int(const Int n) {
|
|
201
|
-
char str[24];
|
|
202
|
-
sprintf(str, "%" PRId64, n);
|
|
203
|
-
return c_buffer_construct_from_null_terminated_string(str);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
struct Pos c_buffer_show_Byte(const uint8_t n) {
|
|
207
|
-
char str[4]; // Byte values range from 0 to 255, 3 characters + null terminator
|
|
208
|
-
sprintf(str, "%" PRIu8, n);
|
|
209
|
-
return c_buffer_construct_from_null_terminated_string(str);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
struct Pos c_buffer_show_Char(const uint64_t n) {
|
|
213
|
-
char str[5] = {0}; // Max 4 bytes for UTF-8 + 1 for null terminator
|
|
214
|
-
unsigned char *buf = (unsigned char *)str;
|
|
215
|
-
|
|
216
|
-
if (n < 0x80) { // 1-byte sequence
|
|
217
|
-
buf[0] = (unsigned char)n;
|
|
218
|
-
} else if (n < 0x800) { // 2-byte sequence
|
|
219
|
-
buf[0] = (unsigned char)(0xC0 | (n >> 6));
|
|
220
|
-
buf[1] = (unsigned char)(0x80 | (n & 0x3F));
|
|
221
|
-
} else if (n < 0x10000) { // 3-byte sequence
|
|
222
|
-
buf[0] = (unsigned char)(0xE0 | (n >> 12));
|
|
223
|
-
buf[1] = (unsigned char)(0x80 | ((n >> 6) & 0x3F));
|
|
224
|
-
buf[2] = (unsigned char)(0x80 | (n & 0x3F));
|
|
225
|
-
} else if (n < 0x110000) { // 4-byte sequence
|
|
226
|
-
buf[0] = (unsigned char)(0xF0 | (n >> 18));
|
|
227
|
-
buf[1] = (unsigned char)(0x80 | ((n >> 12) & 0x3F));
|
|
228
|
-
buf[2] = (unsigned char)(0x80 | ((n >> 6) & 0x3F));
|
|
229
|
-
buf[3] = (unsigned char)(0x80 | (n & 0x3F));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return c_buffer_construct_from_null_terminated_string(str);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
struct Pos c_buffer_show_Double(const Double x) {
|
|
236
|
-
char str[64]; // TODO is this large enough? Possibly use snprintf first
|
|
237
|
-
sprintf(str, "%g", x);
|
|
238
|
-
return c_buffer_construct_from_null_terminated_string(str);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
uint64_t c_buffer_index(const struct Pos buffer, const uint64_t index) {
|
|
242
|
-
return c_buffer_bytes(buffer)[index];
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
void c_buffer_set(struct Pos buffer, const uint64_t index, uint8_t value) {
|
|
246
|
-
c_buffer_bytes(buffer)[index] = value;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
uint32_t c_buffer_character_at(const struct Pos buffer, const uint64_t index) {
|
|
250
|
-
const uint8_t *bytes = c_buffer_bytes(buffer);
|
|
251
|
-
uint8_t first_byte = bytes[index];
|
|
252
|
-
uint32_t character = 0;
|
|
253
|
-
|
|
254
|
-
uint32_t length = c_buffer_length(buffer);
|
|
255
|
-
|
|
256
|
-
if (first_byte < 0x80) {
|
|
257
|
-
// Single-byte character (0xxxxxxx)
|
|
258
|
-
character = first_byte;
|
|
259
|
-
} else if ((first_byte & 0xE0) == 0xC0) {
|
|
260
|
-
// Two-byte character (110xxxxx 10xxxxxx)
|
|
261
|
-
if (index + 1 < length) {
|
|
262
|
-
character = ((first_byte & 0x1F) << 6) |
|
|
263
|
-
(bytes[index + 1] & 0x3F);
|
|
264
|
-
}
|
|
265
|
-
} else if ((first_byte & 0xF0) == 0xE0) {
|
|
266
|
-
// Three-byte character (1110xxxx 10xxxxxx 10xxxxxx)
|
|
267
|
-
if (index + 2 < length) {
|
|
268
|
-
character = ((first_byte & 0x0F) << 12) |
|
|
269
|
-
((bytes[index + 1] & 0x3F) << 6) |
|
|
270
|
-
(bytes[index + 2] & 0x3F);
|
|
271
|
-
}
|
|
272
|
-
} else if ((first_byte & 0xF8) == 0xF0) {
|
|
273
|
-
// Four-byte character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
|
274
|
-
if (index + 3 < length) {
|
|
275
|
-
character = ((first_byte & 0x07) << 18) |
|
|
276
|
-
((bytes[index + 1] & 0x3F) << 12) |
|
|
277
|
-
((bytes[index + 2] & 0x3F) << 6) |
|
|
278
|
-
(bytes[index + 3] & 0x3F);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
erasePositive(buffer);
|
|
283
|
-
return character;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
#endif
|