Skip to content

Commit 75538a9

Browse files
MrHandsJBenda
andauthored
Correctly parse tags related to each line (#96)
My major goal with this pull request was to support retrieving the correct tags per line, and I've succeeded with that. Unfortunately, I also broke several existing tests in the process and haven't been able to get them working yet. I don’t think it’s very nice of me to leave your project in a worse state than I found it, so I’m providing you with as much documentation as possible about where I suspect the problems lie. I hope we can work together to integrate my changes into your main branch. # Changelog - choice class: Tags are stored as `snap_tag*` held by the `runner_impl` instead of `const char*`. - runner interface: Added virtual `num_global_tags()` and `get_global_tag()` methods. - runner interface: Added `line_type` for `std::string` or `FString` depending on compile settings. - runner interface: Simplified `getline()` method to return `line_type`. - basic_stream: Reimplemented `entries_since_marker()` as `find_first_of()` and `find_last_of()` methods. - basic_stream: Removed `saved_ends_with()` method in favor of an `offset` parameter to the `ends_with()` method. - basic_stream: Use `size_t` instead of `int` for offsets into the data. - basic_stream: Protect against buffer underflow in the `discard()` method. - basic_stream: Added `npos` constexpr for invalid positions in the buffer. - runner_impl: Added `add_tag()` and `clear_tags()` methods to manage tag info. - runner_impl: `advance_line()` clears line and choice tags while keeping the global ones. - runner_impl: `line_step()` reads steps from the execution buffer until the next new line. - runner_impl: `line_step()` copies global tags to the first line. - runner_impl: `line_step()` continues stepping execution until it's satisfied it doesn't affect the current line. - runner_impl: Added `set_debug_enabled()` to optionally write command info to a debug stream as the instance steps through the execution buffer. - runner_impl: `step()` writes debug info to the debug stream, if available. - runner_impl: Streamlined `getline()` implementation to work with either `std::string` or `FString`. - runner_impl: Streamlined `getall()` implementation to call `getline()` multiple times, reducing the need to test this method separately. - runner_impl: Simplified `detect_change()` to check for extending past the newline only. - command: Added `std::ostream` operator for streaming `Command` and `CommandFlag` enum values as strings. - snapshot_impl: Added `text()` method to retrieve stored string directly. - snapshot_impl: Store pointers to tags start and end instead of text pointers. - keep track of global tags and current knot/stitch tags - knot tags are tags in the current knot/stitch before the first line of ink code - tags from parent knots are not stored! - function to fetch current knot/stitch hash to detect knot/stitch changes - UE: new event: EnterKnot(GlobalTags, KnotTags) # Unit test changes - Replaced many `REQUIRE()` calls with `CHECK()` to ensure test execution isn’t halted immediately. - Tags.cpp: Added unit tests for adding and removing tags to a runner. - Tags.cpp: Made loaded story global to ensure that `WHEN()` and `THEN()` tests can be run in sequence correctly. - NoEarlyTags.cpp: Added checks for specific tags after each line. - NewLines.cpp: Cleaned up tests. - TagsStory.ink: Expanded tests for tags in different places. - LinesStory.ink: Added a condensed test case for ignoring functions when applying glue. --------- Co-authored-by: Julian Benda <Julian.m.benda@gmail.com>
1 parent c7d32d6 commit 75538a9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2725
-1343
lines changed

.clang-format

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,34 @@
22
AccessModifierOffset: -2
33
AlignAfterOpenBracket: BlockIndent
44
AlignArrayOfStructures: Right
5-
# readd padOperation if bumped from clang 14
6-
AlignConsecutiveAssignments: AcrossComments
7-
AlignConsecutiveBitFields: AcrossComments
8-
AlignConsecutiveDeclarations: AcrossComments
9-
AlignConsecutiveMacros: AcrossComments
5+
AlignConsecutiveAssignments:
6+
Enabled: true
7+
AcrossEmptyLines: false
8+
AcrossComments: true
9+
AlignCompound: false
10+
AlignFunctionPointers: false
11+
PadOperators: true
12+
AlignConsecutiveBitFields:
13+
Enabled: true
14+
AcrossEmptyLines: false
15+
AcrossComments: true
16+
AlignCompound: false
17+
AlignFunctionPointers: false
18+
PadOperators: true
19+
AlignConsecutiveDeclarations:
20+
Enabled: true
21+
AcrossEmptyLines: false
22+
AcrossComments: true
23+
AlignCompound: false
24+
AlignFunctionPointers: false
25+
PadOperators: true
26+
AlignConsecutiveMacros:
27+
Enabled: true
28+
AcrossEmptyLines: false
29+
AcrossComments: true
30+
AlignCompound: false
31+
AlignFunctionPointers: false
32+
PadOperators: true
1033
AlignEscapedNewlines: Left
1134
AlignOperands: AlignAfterOperator
1235
AlignTrailingComments: true
@@ -25,7 +48,6 @@ AlwaysBreakTemplateDeclarations: Yes
2548
BinPackArguments: true
2649
BinPackParameters: true
2750
BreakBeforeBraces: Linux
28-
# BreakAfterAttributes: Always
2951
BreakBeforeBinaryOperators: All
3052
UseTab: ForIndentation
3153
Standard: Latest
@@ -58,9 +80,6 @@ SortUsingDeclarations: false
5880
SortIncludes: Never
5981
ShortNamespaceLines: 0
6082
SeparateDefinitionBlocks: Always
61-
# RequiresExpressionIndentation: OuterScope
62-
# BreakBeforeConceptDeclarations: Always
63-
# BreakBeforeInlineASMColon: Always
6483
BreakBeforeTernaryOperators: true
6584
BreakConstructorInitializers: BeforeComma
6685
BreakInheritanceList: BeforeComma
@@ -77,23 +96,17 @@ IndentCaseLabels: true
7796
IndentExternBlock: Indent
7897
IndentGotoLabels: false
7998
IndentPPDirectives: AfterHash
80-
# IndentRequiresClause: true
8199
IndentWidth: 2
82100
TabWidth: 2
83101
IndentWrappedFunctionNames: true
84-
# InsertBraces: true
85-
# InsertNewlineAtEOF: true
86102
KeepEmptyLinesAtTheStartOfBlocks: true
87103
LambdaBodyIndentation: Signature
88104
Language: Cpp
89-
# LineEnding: LF
90105
MaxEmptyLinesToKeep: 2
91106
NamespaceIndentation: Inner
92107
QualifierAlignment: Left
93108
ReferenceAlignment: Left
94109
ReflowComments: true
95110
RemoveBracesLLVM: false
96-
# RemoveSemicolon: false
97-
# RequiresClausePosition: OwnLine
98111
UseCRLF: false
99112
DeriveLineEnding: false

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
guidelines = 100
5+
indent_style = tab
6+
indent_size = 4
7+
# Unix-style newlines
8+
end_of_line = lf
9+
insert_final_newline = true

.github/workflows/build.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ jobs:
117117
working-directory: ${{github.workspace}}/build
118118
shell: bash
119119
run: |
120-
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.5"
120+
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.5" -DINKCPP_UNREAL=ON
121121
cmake --install . --config $BUILD_TYPE --prefix comp_unreal_5_5 --component unreal
122-
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.4"
122+
cmake $GITHUB_WORKSPACE -DINKCPP_UNREAL_TARGET_VERSION="5.4" -DINKCPP_UNREAL=ON
123123
cmake --install . --config $BUILD_TYPE --prefix comp_unreal_5_4 --component unreal
124124
- name: Upload UE 5.5
125125
if: ${{ matrix.unreal }}
@@ -287,12 +287,12 @@ jobs:
287287
git fetch origin master
288288
- name: Check clang-format
289289
run: |
290+
git clang-format-18 --extensions c,cpp,h,hpp --style file -q --diff origin/master
290291
diff=$(git clang-format-18 --extensions c,cpp,h,hpp --style file -q --diff origin/master)
291-
echo $diff
292+
echo "::error Format diff >$diff<"
292293
if [ "$diff" != "" ]; then
293-
echo run git clang-format --extensions c,cpp,h,hpp --style file master
294+
echo run git clang-format-18 --extensions c,cpp,h,hpp --style file master
294295
echo or upstream/master depending on your setup
295-
clang
296296
fi
297297
298298
reporting:

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ Bin/
2222

2323
# Visual Studio
2424
/out/build/
25-
/.vs
25+
.vs

CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ include(FetchContent)
77
FetchContent_Declare(inklecate_mac
88
URL https://github.com/inkle/ink/releases/download/v1.1.1/inklecate_mac.zip
99
URL_HASH SHA256=c516402bca5fa249a7712e62591b048b137eba3098c53f9fb85a4253f9b9e2c0
10-
SOURCE_DIR "inklecate/mac"
10+
SOURCE_DIR "${CMAKE_BINARY_DIR}/inklecate/mac"
1111
)
1212
FetchContent_Declare(inklecate_windows
1313
URL https://github.com/inkle/ink/releases/download/v1.1.1/inklecate_windows.zip
1414
URL_HASH SHA256=6f317cb4c59bf1b31c6dd61e80c6a2287a1d8c241a703f0586f736ae00871aab
15-
SOURCE_DIR "inklecate/windows"
15+
SOURCE_DIR "${CMAKE_BINARY_DIR}/inklecate/windows"
1616
)
1717
FetchContent_Declare(inklecate_linux
1818
URL https://github.com/inkle/ink/releases/download/v1.1.1/inklecate_linux.zip
1919
URL_HASH SHA256=26f4e188e02536d6e99e73e71d9b13e2c2144187f1368a87e82fd5066176cff8
20-
SOURCE_DIR "inklecate/linux"
20+
SOURCE_DIR "${CMAKE_BINARY_DIR}/inklecate/linux"
2121
)
2222
set(FETCHCONTENT_QUIET OFF)
2323
mark_as_advanced(FETCHCONTENT_QUIET)
@@ -41,7 +41,7 @@ mark_as_advanced(PYBIND11_USE_CROSSCOMPILING)
4141
enable_testing()
4242

4343
# Project setup
44-
project(inkcpp VERSION 0.1.7)
44+
project(inkcpp VERSION 0.1.8)
4545
SET(CMAKE_CXX_STANDARD 20)
4646
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
4747
SET(CMAKE_INSTALL_LIBRARY_DIR lib)
18.9 KB
Binary file not shown.

inkcpp/array.h

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "system.h"
1111
#include "traits.h"
1212

13+
#include <limits>
14+
1315
namespace ink::runtime::internal
1416
{
1517
template<typename T, bool dynamic, size_t initialCapacity>
@@ -26,7 +28,7 @@ class managed_array : public snapshot_interface
2628
}
2729
}
2830

29-
~managed_array()
31+
virtual ~managed_array()
3032
{
3133
if constexpr (dynamic) {
3234
delete[] _dynamic_data;
@@ -78,12 +80,37 @@ class managed_array : public snapshot_interface
7880
extend();
7981
}
8082
} else {
81-
inkAssert(_size <= _capacity, "Stack Overflow!");
82-
/// FIXME silent fail!!
83+
inkAssert(_size <= _capacity, "Try to append to a full array!");
84+
// TODO(JBenda): Silent fail?
8385
}
8486
return data()[_size++];
8587
}
8688

89+
virtual T& insert(size_t position)
90+
{
91+
inkAssert(
92+
position <= _size,
93+
"Array must be dense, cannot insert value at position larger then array.size."
94+
);
95+
push();
96+
if (_size >= 2) {
97+
for (size_t i = _size - 2; i >= position && i < std::numeric_limits<size_t>::max(); --i) {
98+
data()[i + 1] = data()[i];
99+
}
100+
}
101+
return data()[position];
102+
}
103+
104+
virtual void remove(size_t begin, size_t end)
105+
{
106+
inkAssert(end <= _size, "can not delete behind end of array.");
107+
inkAssert(begin <= end, "can not remove negative range.");
108+
for (size_t i = 0; i < (end - begin) && end + i < _size; ++i) {
109+
data()[begin + i] = data()[end + i];
110+
}
111+
_size -= end - begin;
112+
}
113+
87114
void clear() { _size = 0; }
88115

89116
void resize(size_t size)
@@ -154,7 +181,23 @@ class managed_restorable_array : public managed_array<T, dynamic, initialCapacit
154181
{
155182
}
156183

157-
void restore() { base::resize(_last_size); }
184+
virtual T& insert(size_t position) override
185+
{
186+
inkAssert(position >= _last_size, "Cannot insert data before last save point.");
187+
return base::insert(position);
188+
}
189+
190+
virtual void remove(size_t begin, size_t end) override
191+
{
192+
inkAssert(begin >= _last_size, "Cannot delete data before last save point.");
193+
base::remove(begin, end);
194+
}
195+
196+
void restore()
197+
{
198+
base::resize(_last_size);
199+
_last_size = 0;
200+
}
158201

159202
void save() { _last_size = this->size(); }
160203

@@ -287,7 +330,6 @@ class basic_restorable_array : public snapshot_interface
287330
const T _null;
288331
};
289332

290-
291333
template<typename T>
292334
inline void basic_restorable_array<T>::set(size_t index, const T& value)
293335
{

inkcpp/choice.cpp

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,48 +7,62 @@
77
#include "choice.h"
88

99
#include "output.h"
10+
#include "snapshot_impl.h"
1011
#include "string_table.h"
1112
#include "string_utils.h"
1213

13-
namespace ink {
14-
namespace runtime {
15-
choice& choice::setup( internal::basic_stream& in, internal::string_table& strings, internal::list_table& lists, int index, uint32_t path, thread_t thread, const char* const* tags )
14+
namespace ink
15+
{
16+
namespace runtime
17+
{
18+
19+
size_t choice::num_tags() const { return std::distance(_tags_start, _tags_end); }
20+
21+
const char* choice::get_tag(size_t index) const
22+
{
23+
return (index < num_tags()) ? _tags_start[index].text() : nullptr;
24+
}
25+
26+
choice& choice::setup(
27+
internal::basic_stream& in, internal::string_table& strings, internal::list_table& lists,
28+
int index, uint32_t path, thread_t thread, const internal::snap_tag* tags_start,
29+
const internal::snap_tag* tags_end
30+
)
1631
{
32+
// Index/path
33+
_index = index;
34+
_path = path;
35+
_thread = thread;
36+
_tags_start = tags_start;
37+
_tags_end = tags_end;
38+
1739
char* text = nullptr;
1840
// if we only have one item in our output stream
19-
if ( in.queued() == 2 )
20-
{
41+
if (in.queued() == 2) {
2142
// If it's a string, just grab it. Otherwise, use allocation
2243
const internal::value& data = in.peek();
23-
switch ( data.type() )
24-
{
25-
case internal::value_type::string:
26-
text = strings.duplicate( data.get<internal::value_type::string>() );
27-
in.discard( 2 );
28-
break;
29-
default:
30-
text = in.get_alloc( strings, lists );
44+
switch (data.type()) {
45+
case internal::value_type::string:
46+
text = strings.duplicate(data.get<internal::value_type::string>());
47+
in.discard(2);
48+
break;
49+
default: text = in.get_alloc(strings, lists);
3150
}
32-
}
33-
else
34-
{
51+
} else {
3552
// Non-string. Must allocate
36-
text = in.get_alloc( strings, lists );
53+
text = in.get_alloc(strings, lists);
3754
}
55+
3856
char* end = text;
39-
while ( *end )
40-
{
57+
while (*end != '\0') {
4158
++end;
4259
}
43-
end = ink::runtime::internal::clean_string<true, true>( text, end );
44-
*end = 0;
60+
end = ink::runtime::internal::clean_string<true, true>(text, end);
61+
*end = '\0';
62+
4563
_text = text;
46-
// Index/path
47-
_index = index;
48-
_path = path;
49-
_thread = thread;
50-
_tags = tags;
64+
5165
return *this;
5266
}
53-
}
54-
} // namespace ink::runtime
67+
} // namespace runtime
68+
} // namespace ink

0 commit comments

Comments
 (0)