Skip to content

Commit

Permalink
Make limit work.
Browse files Browse the repository at this point in the history
Extra functions on JS/Jackson object.
  • Loading branch information
jdunkerley committed Jan 23, 2024
1 parent 0bf25e8 commit f766ca7
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 28 deletions.
33 changes: 33 additions & 0 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Java_Json.enso
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import project.Any.Any
import project.Data.Array_Proxy.Array_Proxy
import project.Data.Json.Invalid_JSON
import project.Data.Json.JS_Object
import project.Data.Numbers.Integer
import project.Data.Numbers.Number
import project.Data.Text.Text
import project.Data.Vector.Vector
Expand All @@ -13,6 +14,7 @@ import project.Nothing.Nothing
import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True
from project.Data.Json.Extensions import all
from project.Data.Ordering import all
from project.Data.Text.Extensions import all
from project.Metadata.Choice import Option
from project.Metadata.Widget import Single_Choice
Expand Down Expand Up @@ -104,6 +106,14 @@ type Jackson_Object
field_names : Vector
field_names self = self.field_array

## GROUP Conversions
Maps ths object to a Vector of Pairs.
map : (Text->Any->Any) -> Vector
map self action=[_,_] =
self.field_names.map key->
value = self.get key
action key value

## GROUP Metadata
Gets the number of keys in the object.
length : Number
Expand Down Expand Up @@ -141,3 +151,26 @@ make_field_name_selector js_object display=Display.Always =
## Extension for Text to allow use.
Text.parse_fast_json : Nothing | Boolean | Number | Text | Vector | Jackson_Object
Text.parse_fast_json self = Java_Json.parse self

## PRIVATE
type Jackson_Object_Comparator
## PRIVATE
compare : Jackson_Object -> Jackson_Object -> (Ordering|Nothing)
compare obj1 obj2 =
obj1_keys = obj1.field_names
obj2_keys = obj2.field_names
same_values = obj1_keys.length == obj2_keys.length && obj1_keys.all key->
(obj1.get key == obj2.at key).catch No_Such_Key _->False
if same_values then Ordering.Equal else Nothing

## PRIVATE
hash : Jackson_Object -> Integer
hash obj =
values_hashes = obj.field_names.map field_name->
val = obj.get field_name
Comparable.from val . hash val
# Return sum, as we don't care about ordering of field names
values_hashes.fold 0 (+)

## PRIVATE
Comparable.from (_:Jackson_Object) = Jackson_Object_Comparator
8 changes: 8 additions & 0 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Json.enso
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ type JS_Object
field_names self =
Vector.from_polyglot_array (get_property_names self.js_object)

## GROUP Conversions
Maps ths object to a Vector of Pairs.
map : (Text->Any->Any) -> Vector
map self action=[_,_] =
self.field_names.map key->
value = self.get key
action key value

## GROUP Metadata
Gets the number of keys in the object.
length : Number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ type File_By_Line
- limit_lines: The number of lines to read (defaults to all lines).
- filter_func: The filter to apply to each line (defaults to no filter).
- row_map: The row map to use (defaults to a new row map).
Reader file:File encoding:Encoding limit_lines:(Integer|Nothing) filter_func row_map
- file_end: The end of the file in bytes.
Reader file:File encoding:Encoding limit_lines:(Integer|Nothing) filter_func row_map file_end=file.size

## Reads a specific line from the file.

Expand Down Expand Up @@ -77,7 +78,7 @@ type File_By_Line
to_vector : Vector Text
to_vector self = File_Error.handle_java_exceptions self.file <|
end_at = if self.limit_lines.is_nothing then Nothing else self.limit_lines-1
FileLineReader.readLines self.java_file self.row_map 0 end_at self.charset self.filter_func
FileLineReader.readLines self.java_file self.file_end self.row_map 0 end_at self.charset self.filter_func

## Performs an action on each line.

Expand Down Expand Up @@ -126,23 +127,25 @@ type File_By_Line
skip : Integer -> File_By_Line
skip self lines:Integer =
## Read the line
position = if self.row_map.getSize > lines then self.row_map.get lines else
for_each_lines self 0 lines Nothing
self.row_map.get self.row_map.getSize-1
row_map = LongArrayList.new
row_map.add position
self.log "Created Skipped Parent"
create_row_map parent line =
position = if parent.row_map.getSize > line then parent.row_map.get line else
for_each_lines self 0 line Nothing
parent.row_map.get parent.row_map.getSize-1
row_map = LongArrayList.new
row_map.add position
parent.log "Created Skipped Row Map ("+line.to_text+")"
row_map

new_limit = if self.limit_lines.is_nothing then lines else lines.min self.limit_lines
File_By_Line.Reader self.file self.encoding new_limit self.filter_func row_map
File_By_Line.Reader self.file self.encoding new_limit self.filter_func (create_row_map self lines) self.file_end

## Limits a file to a specific number of lines.

Arguments
- lines: The number of lines to limit the file to.
limit : Integer -> File_By_Line
limit self lines:Integer =
File_By_Line.Reader self.file self.encoding lines self.filter_func self.row_map
File_By_Line.Reader self.file self.encoding lines self.filter_func self.row_map self.file_end

## Filters the file by a predicate.

Expand All @@ -156,17 +159,28 @@ type File_By_Line
_ -> FileLineReader.wrapBooleanFilter predicate self.charset

## Find the index of the first line matching the new index.
end_at = if self.limit_lines.is_nothing then -1 else self.limit_lines-1
first_index = FileLineReader.findFirstNewFilter self.java_file self.row_map end_at self.charset self.filter_func new_filter
new_row_map = LongArrayList.new
new_row_map.add first_index
make_filter_map parent new_filter =
end_at = if parent.limit_lines.is_nothing then -1 else parent.limit_lines-1
first_index = FileLineReader.findFirstNewFilter parent.java_file parent.file_end parent.row_map end_at parent.charset parent.filter_func new_filter
new_row_map = LongArrayList.new
new_row_map.add first_index
parent.log "Found Filter Start - "+first_index.to_text
new_row_map

## Merge the two predicates together.
new_predicate = if self.filter_func.is_nothing then new_filter else
FileLineReader.mergeTwoFilters self.filter_func new_filter

## Need to ensure the parent limit is obeyed - for now we just use it but should be applied on level above
File_By_Line.Reader self.file self.encoding self.limit_lines new_predicate new_row_map
## If the parent is limited need to limit the child by end position in file.
if self.limit_lines == Nothing then File_By_Line.Reader self.file self.encoding Nothing new_predicate (make_filter_map self new_filter) self.file_end else
## Find the index of the last line matching the new index.
index_of parent line =
file_len = if parent.row_map.getSize > line then parent.row_map.get line else
for_each_lines self 0 line Nothing
parent.row_map.get parent.row_map.getSize-1
parent.log "Created File End ("+line.to_text+") - "+file_len.to_text
file_len
File_By_Line.Reader self.file self.encoding Nothing new_predicate (make_filter_map self new_filter) (index_of self self.limit_lines)

## ADVANCED
Exports the row_map
Expand All @@ -188,19 +202,20 @@ type File_By_Line
Reads a specific line from the file.
read_line : File_By_Line->Integer->Any->Any
read_line file:File_By_Line line:Integer=0 ~default=Nothing = File_Error.handle_java_exceptions file.file <|
FileLineReader.readSingleLine file.java_file file.row_map line file.charset file.filter_func . if_nothing default
FileLineReader.readSingleLine file.java_file file.file_end file.row_map line file.charset file.filter_func . if_nothing default

## PRIVATE
Performs an action on each line in the file.
for_each_lines : File_By_Line->Integer->(Integer|Nothing)->Any->Any
for_each_lines file:File_By_Line start_at:Integer end_at:(Integer|Nothing) action = File_Error.handle_java_exceptions file.file <|
java_file = file.java_file
row_map = file.row_map
file_end = file.file_end
charset = file.charset

## First if we haven't read the found the start_at line we need to find that.
if start_at >= row_map.getSize then FileLineReader.readSingleLine java_file row_map start_at charset file.filter_func
if start_at >= row_map.getSize then FileLineReader.readSingleLine java_file file_end row_map start_at charset file.filter_func

## Now we can read the lines we need.
if row_map.getOrLast start_at >= java_file.length then Error.throw (Index_Out_Of_Bounds.Error start_at row_map.getSize) else
FileLineReader.forEachLine java_file row_map start_at (end_at.if_nothing -1) charset file.filter_func action
if row_map.getOrLast start_at >= file_end then Error.throw (Index_Out_Of_Bounds.Error start_at row_map.getSize) else
FileLineReader.forEachLine java_file file_end row_map start_at (end_at.if_nothing -1) charset file.filter_func action
19 changes: 11 additions & 8 deletions std-bits/base/src/main/java/org/enso/base/FileLineReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,12 @@ private static boolean scanLine(MappedByteBuffer buffer) {
}

// ** Reads a line from a file at the given index using the existing rowMap. */
private static String readLineByIndex(File file, LongArrayList rowMap, int index, Charset charset)
private static String readLineByIndex(File file, long length, LongArrayList rowMap, int index, Charset charset)
throws IOException {
if (index >= rowMap.getSize()) {
throw new IndexOutOfBoundsException(index);
}

long length = file.length();
long position = rowMap.get(index);
if (position >= length) {
return null;
Expand Down Expand Up @@ -150,30 +149,32 @@ private static String readLineByIndex(File file, LongArrayList rowMap, int index
// ** Scans forward in a file and returns the line at the given index. */
public static String readSingleLine(
File file,
long length,
LongArrayList rowMap,
int index,
Charset charset,
Function<ByteArrayOutputStreamWithContains, String> filter)
throws IOException {
int size = rowMap.getSize();
if (index != -1 && size > index) {
return readLineByIndex(file, rowMap, index, charset);
return readLineByIndex(file, length, rowMap, index, charset);
}

// Start at the last known line and scan forward.
return forEachLine(file, rowMap, size - 1, index, charset, filter, null);
return forEachLine(file, length, rowMap, size - 1, index, charset, filter, null);
}

public static List<String> readLines(
File file,
long length,
LongArrayList rowMap,
int startAt,
int endAt,
Charset charset,
Function<ByteArrayOutputStreamWithContains, String> filter)
throws IOException {
List<String> result = new ArrayList<>();
forEachLine(file, rowMap, startAt, endAt, charset, filter, (index, line) -> result.add(line));
forEachLine(file, length, rowMap, startAt, endAt, charset, filter, (index, line) -> result.add(line));
return result;
}

Expand All @@ -189,6 +190,7 @@ public static List<String> readLines(
// * *//
public static String forEachLine(
File file,
long length,
LongArrayList rowMap,
int startAt,
int endAt,
Expand All @@ -197,11 +199,12 @@ public static String forEachLine(
BiConsumer<Integer, String> action)
throws IOException {
return innerForEachLine(
file, rowMap, startAt, endAt, charset, filter, action, new CancellationToken());
file, length, rowMap, startAt, endAt, charset, filter, action, new CancellationToken());
}

private static String innerForEachLine(
File file,
long length,
LongArrayList rowMap,
int startAt,
int endAt,
Expand All @@ -215,7 +218,6 @@ private static String innerForEachLine(
}
int index = action == null ? rowMap.getSize() - 1 : startAt;

long length = file.length();
long position = rowMap.get(index);
if (position >= length) {
return null;
Expand Down Expand Up @@ -299,6 +301,7 @@ private static String innerForEachLine(
// filter. */
public static long findFirstNewFilter(
File file,
long length,
LongArrayList rowMap,
int endAt,
Charset charset,
Expand All @@ -316,7 +319,7 @@ public static long findFirstNewFilter(
token.cancel();
}
};
innerForEachLine(file, rowMap, 0, endAt, charset, filter, action, token);
innerForEachLine(file, length, rowMap, 0, endAt, charset, filter, action, token);
return result.isEmpty() ? rowMap.get(rowMap.getSize() - 1) : result.get(0);
}

Expand Down

0 comments on commit f766ca7

Please sign in to comment.