From 8323333c448ea892fc903f3fe75ae344cee7c14a Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Mon, 7 Aug 2023 17:16:04 +0200 Subject: [PATCH 1/2] Fix SuggestionIterator hasNext. --- lib/src/main/cpp/libzim/suggestion_iterator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/main/cpp/libzim/suggestion_iterator.cpp b/lib/src/main/cpp/libzim/suggestion_iterator.cpp index 9fe6cd8..8211fc2 100644 --- a/lib/src/main/cpp/libzim/suggestion_iterator.cpp +++ b/lib/src/main/cpp/libzim/suggestion_iterator.cpp @@ -42,13 +42,13 @@ METHOD0(void, dispose) } CATCH_EXCEPTION() METHOD0(jboolean, hasNext) { - NATIVE_TYPE next(*THIS); - next++; + // THIS is the next item to return. So we have to check it with end auto end = getPtr(env, thisObj, "nativeHandleEnd"); - return next == *end; + return *THIS != *end; } CATCH_EXCEPTION(false) METHOD0(jobject, next) { + zim::SuggestionItem item = **THIS; (*THIS)++; return BUILD_WRAPPER("org/kiwix/libzim/SuggestionItem", item); From c94a04bbdcc8f95e792a84bb9dd5306763dd2524 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Mon, 7 Aug 2023 17:16:40 +0200 Subject: [PATCH 2/2] Make `next()` throws NoSuchElementException if hasNext is false. --- lib/src/main/cpp/libzim/entry_iterator.cpp | 18 +++++++ lib/src/main/cpp/libzim/search_iterator.cpp | 8 +++ .../main/cpp/libzim/suggestion_iterator.cpp | 6 +++ lib/src/test/test.java | 50 ++++++++++++++++++- 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/lib/src/main/cpp/libzim/entry_iterator.cpp b/lib/src/main/cpp/libzim/entry_iterator.cpp index 4834d74..63b952a 100644 --- a/lib/src/main/cpp/libzim/entry_iterator.cpp +++ b/lib/src/main/cpp/libzim/entry_iterator.cpp @@ -89,16 +89,34 @@ METHOD0(jboolean, hasNext) { METHOD0(jobject, next) { switch (get_order(env, thisObj)) { case 0: { + auto end = getPtr(env, thisObj, "nativeHandleEnd"); + if ((*GET_PTR(PATH_NATIVE_TYPE)) == *end) { + throwException(env, "java/util/NoSuchElementException", ""); + return nullptr; + } + zim::Entry entry = **GET_PTR(PATH_NATIVE_TYPE); (*GET_PTR(PATH_NATIVE_TYPE))++; return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); } case 1: { + auto end = getPtr(env, thisObj, "nativeHandleEnd"); + if ((*GET_PTR(TITLE_NATIVE_TYPE)) == *end) { + throwException(env, "java/util/NoSuchElementException", ""); + return nullptr; + } + zim::Entry entry = **GET_PTR(TITLE_NATIVE_TYPE); (*GET_PTR(TITLE_NATIVE_TYPE))++; return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); } case 2: { + auto end = getPtr(env, thisObj, "nativeHandleEnd"); + if ((*GET_PTR(EFFICIENT_NATIVE_TYPE)) == *end) { + throwException(env, "java/util/NoSuchElementException", ""); + return nullptr; + } + zim::Entry entry = **GET_PTR(EFFICIENT_NATIVE_TYPE); (*GET_PTR(EFFICIENT_NATIVE_TYPE))++; return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); diff --git a/lib/src/main/cpp/libzim/search_iterator.cpp b/lib/src/main/cpp/libzim/search_iterator.cpp index f2746f5..60c559e 100644 --- a/lib/src/main/cpp/libzim/search_iterator.cpp +++ b/lib/src/main/cpp/libzim/search_iterator.cpp @@ -57,11 +57,19 @@ METHOD0(jstring, getZimId) { } CATCH_EXCEPTION(0) METHOD0(jboolean, hasNext) { + // THIS is the next item to return. So we have to check it with end auto end = getPtr(env, thisObj, "nativeHandleEnd"); return *THIS != *end; } CATCH_EXCEPTION(false) METHOD0(jobject, next) { + // THIS is the next item to return. So we have to return it and advance for next round + auto end = getPtr(env, thisObj, "nativeHandleEnd"); + if (*THIS == *end) { + throwException(env, "java/util/NoSuchElementException", ""); + return nullptr; + } + zim::Entry entry = **THIS; (*THIS)++; return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); diff --git a/lib/src/main/cpp/libzim/suggestion_iterator.cpp b/lib/src/main/cpp/libzim/suggestion_iterator.cpp index 8211fc2..85c0e1d 100644 --- a/lib/src/main/cpp/libzim/suggestion_iterator.cpp +++ b/lib/src/main/cpp/libzim/suggestion_iterator.cpp @@ -48,6 +48,12 @@ METHOD0(jboolean, hasNext) { } CATCH_EXCEPTION(false) METHOD0(jobject, next) { + // THIS is the next item to return. So we have to return it and advance for next round + auto end = getPtr(env, thisObj, "nativeHandleEnd"); + if (*THIS == *end) { + throwException(env, "java/util/NoSuchElementException", ""); + return nullptr; + } zim::SuggestionItem item = **THIS; (*THIS)++; diff --git a/lib/src/test/test.java b/lib/src/test/test.java index 77f4ce6..ba419b0 100644 --- a/lib/src/test/test.java +++ b/lib/src/test/test.java @@ -123,6 +123,14 @@ private void testArchive(TestArchive archive) assertEquals("favicon.png", iter.next().getPath()); assertEquals("main.html", iter.next().getPath()); assertFalse(iter.hasNext()); + try { + iter.next(); + fail("ERROR: next() should raise a NoSuchElementException."); + } catch (NoSuchElementException e) { + // We are good + } catch(Exception e) { + fail("ERROR: Must be a NoSuchElementException."); + } } { @@ -131,6 +139,14 @@ private void testArchive(TestArchive archive) assertEquals("main.html", iter.next().getPath()); // No favicon, because favicon is not a main article (no title) assertFalse(iter.hasNext()); + try { + iter.next(); + fail("ERROR: next() should raise a NoSuchElementException."); + } catch (NoSuchElementException e) { + // We are good + } catch(Exception e) { + fail("ERROR: Must be a NoSuchElementException."); + } } { @@ -139,6 +155,14 @@ private void testArchive(TestArchive archive) assertEquals("main.html", iter.next().getPath()); assertEquals("favicon.png", iter.next().getPath()); assertFalse(iter.hasNext()); + try { + iter.next(); + fail("ERROR: next() should raise a NoSuchElementException."); + } catch (NoSuchElementException e) { + // We are good + } catch(Exception e) { + fail("ERROR: Must be a NoSuchElementException."); + } } { @@ -146,6 +170,14 @@ private void testArchive(TestArchive archive) assertTrue(iter.hasNext()); assertEquals("main.html", iter.next().getPath()); assertFalse(iter.hasNext()); + try { + iter.next(); + fail("ERROR: next() should raise a NoSuchElementException."); + } catch (NoSuchElementException e) { + // We are good + } catch(Exception e) { + fail("ERROR: Must be a NoSuchElementException."); + } } { @@ -153,6 +185,14 @@ private void testArchive(TestArchive archive) assertTrue(iter.hasNext()); assertEquals("main.html", iter.next().getPath()); assertFalse(iter.hasNext()); + try { + iter.next(); + fail("ERROR: next() should raise a NoSuchElementException."); + } catch (NoSuchElementException e) { + // We are good + } catch(Exception e) { + fail("ERROR: Must be a NoSuchElementException."); + } } // Test invalid path @@ -210,7 +250,7 @@ public void testNotValid() { } catch (ZimFileFormatException e) { assertEquals("Invalid magic number", e.getMessage()); } catch(Exception e) { - fail("ERROR: Must be a ZimFileFormatException."); + fail("ERROR: Must be a ZimFileFormatException."); } } @@ -459,6 +499,14 @@ public void testSearcher() throws Exception, ZimFileFormatException, JNIKiwixExc assertTrue(results.hasNext()); TestSuggestionItem suggestionItem = results.next(); assertFalse(results.hasNext()); + try { + results.next(); + fail("ERROR: next() should raise a NoSuchElementException."); + } catch (NoSuchElementException e) { + // We are good + } catch(Exception e) { + fail("ERROR: Must be a NoSuchElementException."); + } assertEquals("Test ZIM file", suggestionItem.getTitle()); assertEquals("main.html", suggestionItem.getPath()); assertTrue(suggestionItem.hasSnippet());