I am trying to search the binary data of a file in dart, to find the index of a substring. I have working js code but I am unable to convert it to dart. This is the js snippet:
var rp = require('request-promise');
async function test(){
const uri = "https://file-examples-com.github.io/uploads/2017/04/file_example_MP4_480_1_5MG.mp4"
const result = await rp({ uri });
const position = Buffer.from(result).indexOf('dnlu');
console.log(position);
}
test() //outputs 2631582
What would be the dart equivalent of this function?
You'll typically fetch the bytes as a Uint8List.
The Dart Uint8List does not have an indexOf method which works on sublists, so you'll have to search the old fashioned way - by looking at it.
I assume that the bytes represent UTF-8 or Latin-1 characters, and since your string contains only ASCII, you can search for the code units directly.
Maybe you could add something like:
extension IndexOfListExtension<T> on List<T> {
int indexOfAll(List<T> needle, [int start = 0]) {
if (needle.length == 0) return start;
var first = needle[0];
var end = this.length - needle.length;
for (var i = start; i <= end; i++) {
match:
if (this[i] == first) {
for (var j = 1; j < needle.length; j++) {
if (this[i + j] != needle[j]) break match;
}
return i;
}
}
return -1;
}
}
Then you would be able to do:
var bytes = await fetch_the_bytes(uri); // However you want to do this.
var position = bytes.indexOfAll("dnlu".codeUnits);
...
Related
I'm trying to do something like this:
Future<String> getOutAndAnswer(testcase) async {
Process python = await Process.start('python', ['tasks/histogram/run.py']);
Process java = await Process.start('java', ['solutions/Histogram.java']);
String results = "";
for(int i = 0; i < testcase; i++){
final String out = await python.stdout.transform(utf8.decoder).first;
java.stdin.writeln(out);
final String answer = await java.stdout.transform(utf8.decoder).first;
python.stdin.writeln(answer);
results += "($out, $answer)";
}
return results;
}
Basically, the python program is responsible for generating the input of each test case, then the java program will take the input and return the answer, which is sent to the python program to check if it's correct or not, and so on for every test case.
But when I try to use the above code I get an error saying I've already listened to the stream once:
Exception has occurred.
StateError (Bad state: Stream has already been listened to.)
Python program:
import os
CASE_DIR = os.path.join(os.path.dirname(__file__), "cases")
test_cases = next(os.walk(CASE_DIR))[2]
print(len(test_cases))
for case in sorted(test_cases):
with open(os.path.join(CASE_DIR, case), 'r') as f:
print(f.readline(), end='', flush=True)
f.readline()
expected_output = f.readline()
user_output = input()
if expected_output != user_output:
raise ValueError("Wrong answer!")
print("EXIT", flush=True)
Java program:
public class Histogram {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
for (int i = 0; i < t; i++) {
String input = scanner.nextLine();
String answer = calculateAnswer(input);
System.out.println(answer);
}
}
}
Your issue is with .first which is going to listen to the stream, get the first element, and then immediately stop listening to the stream. See the documentation here: https://api.dart.dev/stable/2.17.3/dart-async/Stream/first.html
You should instead listen once and define an onData method to perform the steps. See the documentation for .listen() here: https://api.dart.dev/stable/2.17.3/dart-async/Stream/listen.html
You could try wrapping the stdout streams in StreamIterator<String>. You will have to give it a try to verify, but I think this is what you are looking for.
Future<String> getOutAndAnswer(int testcase) async {
Process python = await Process.start('python', ['tasks/histogram/run.py']);
Process java = await Process.start('java', ['solutions/Histogram.java']);
String results = "";
StreamIterator<String> pythonIterator = StreamIterator(
python.stdout.transform(utf8.decoder).transform(LineSplitter()));
StreamIterator<String> javaIterator = StreamIterator(
java.stdout.transform(utf8.decoder).transform(LineSplitter()));
for (int i = 0; i < testcase; i++) {
if (await pythonIterator.moveNext()) {
final String out = pythonIterator.current;
if (out == 'EXIT') {
break;
}
java.stdin.writeln(out);
if (await javaIterator.moveNext()) {
final String answer = javaIterator.current;
python.stdin.writeln(answer);
results += "($out, $answer)";
}
}
}
await pythonIterator.cancel();
await javaIterator.cancel();
return results;
}
You may need to add the following imports:
import 'dart:async';
import 'dart:convert';
Task: Modify the code for Countdown() method so it starts counting down at the start parameter, ends at the end parameter, and displays the message parameter when the countdown is done.
Current code: [Route("[action]/{start}/{end?}/{message?}")] public IActionResult Countdown(int start, int end = 0, string message = "") { string contentString = "Counting down:\n"; for(int i = start; i >= 0; i--) { contentString += i + "\n"; } return Content(contentString); }
enter image description here
I am not sure what's your expected result. The current code works but it just do a loop and then output a string:
[Route("[action]/{start}/{end?}/{message?}")]
public IActionResult Countdown(int start, int end = 0, string message = "")
{
string contentString = "Counting down:\n";
for (int i = start; i >= end; i--)
{
contentString += i + "\n";
}
return Content(contentString);
}
If you want to achieve a countdown timer, I think you should do it combined with your frontend, maybe you can provide us more information.
Let's say we have a name set to "Ben Bright". I want to output to the user "BB", with the first characters of each word. I tried with the split() method, but I failed to do it with dart.
String getInitials(bank_account_name) {
List<String> names = bank_account_name.split(" ");
String initials;
for (var i = 0; i < names.length; i++) {
initials = '${names[i]}';
}
return initials;
}
Allow me to give a shorter solution than the other mentioned:
void main() {
print(getInitials('')); //
print(getInitials('Ben')); // B
print(getInitials('Ben ')); // B
print(getInitials('Ben Bright')); // BB
print(getInitials('Ben Bright Big')); // BB
}
String getInitials(String bank_account_name) => bank_account_name.isNotEmpty
? bank_account_name.trim().split(' ').map((l) => l[0]).take(2).join()
: '';
The take(2) part ensures we only take up to two letters.
EDIT (7th October 2021):
Or if we must be able to handle multiple spaces between the words we can do (thanks #StackUnderflow for notice):
void main() {
print(getInitials('')); //
print(getInitials('Ben')); // B
print(getInitials('Ben ')); // B
print(getInitials('Ben Bright')); // BB
print(getInitials('Ben Bright Big')); // BB
print(getInitials('Ben Bright Big')); // BB
}
String getInitials(String bankAccountName) => bankAccountName.isNotEmpty
? bankAccountName.trim().split(RegExp(' +')).map((s) => s[0]).take(2).join()
: '';
Notice that split takes a RegExp(' +') compared to the original solution.
Just a slight modification since you only need the first letters
String getInitials(bank_account_name) {
List<String> names = bank_account_name.split(" ");
String initials = "";
int numWords = 2;
if(numWords < names.length) {
numWords = names.length;
}
for(var i = 0; i < numWords; i++){
initials += '${names[i][0]}';
}
return initials;
}
Edit:
You can set the value of num_words to print the intials of those many words.
If the bank_account_name is a 0 letter word, then return an empty string
If the bank_account_name contains lesser words than num_words, print the initials of all the words in bank_account_name.
var string = 'William Henry Gates';
var output = getInitials(string: string, limitTo: 1); // W
var output = getInitials(string: string, limitTo: 2); // WH
var output = getInitials(string: string); // WHG
String getInitials({String string, int limitTo}) {
var buffer = StringBuffer();
var split = string.split(' ');
for (var i = 0 ; i < (limitTo ?? split.length); i ++) {
buffer.write(split[i][0]);
}
return buffer.toString();
}
A more general solution can be found below. It takes care of empty strings, single word strings and situations where anticipated word count is less than actual word count:
static String getInitials(String string, {int limitTo}) {
var buffer = StringBuffer();
var wordList = string.trim().split(' ');
if (string.isEmpty)
return string;
// Take first character if string is a single word
if (wordList.length <= 1)
return string.characters.first;
/// Fallback to actual word count if
/// expected word count is greater
if (limitTo != null && limitTo > wordList.length) {
for (var i = 0; i < wordList.length; i++) {
buffer.write(wordList[i][0]);
}
return buffer.toString();
}
// Handle all other cases
for (var i = 0; i < (limitTo ?? wordList.length); i++) {
buffer.write(wordList[i][0]);
}
return buffer.toString();
}
Edit:
I actually use this for CircleAvatars with no images in my projects.
I used CopsOnRoad solution but I was getting the following error.
RangeError (index): Invalid value: Only valid value is 0: 1
So I modified it to
String getInitials(String string, [int limitTo = 2]) {
if (string == null || string.isEmpty) {
return '';
}
var buffer = StringBuffer();
var split = string.split(' ');
//For one word
if (split.length == 1) {
return string.substring(0, 1);
}
for (var i = 0; i < (limitTo ?? split.length); i++) {
buffer.write(split[i][0]);
}
return buffer.toString();
}
Here are some tests in case you are interested
void main() {
group('getInitials', () {
test('should process one later word name correctly', () {
final result = getInitials('J');
expect(result, 'J');
});
test('should process one word name correctly', () {
final result = getInitials('John');
expect(result, 'J');
});
test('should process two word name correctly', () {
final result = getInitials('John Mamba');
expect(result, 'JM');
});
test('should process more than two word name correctly', () {
final result = getInitials('John Mamba Kanzu');
expect(result, 'JM');
});
test('should return empty string when name is null', () {
final result = getInitials(null);
expect(result, '');
});
test('should return empty string when name is empty', () {
final result = getInitials('');
expect(result, '');
});
});
}
String getInitials(full_name) {
List<String> names = full_name.split(" ");
print("org::: $full_name");
print("list ::: $names");
print("Substring ::: ${names[0].substring(0,1)}");
String initials = "";
int numWords = 2;
numWords = names.length;
for(var i = 0; i < numWords; i++)
{
initials += '${names[i].substring(0,1)}';
print("the initials are $initials");
}
return initials;
}
On Nov, 2022
Working solution using Regex:
String getInitials(String string) => string.isNotEmpty
? string.trim().split(RegExp(' +')).map((s) => s[0]).join()
: '' ;
How can I get a function's signature (or at least the entire definition?) as a string using Clang/Libclang, assuming I have its CXCursor or so?
I think that the definition may be somehow obtainable by using the cursor's extents, but I don't really know how (what function to use).
You can use this simple code to get prototype of a function ( name, return type, count of arguments and arguments[name,data type]).
string Convert(const CXString& s)
{
string result = clang_getCString(s);
clang_disposeString(s);
return result;
}
void print_function_prototype(CXCursor cursor)
{
// TODO : Print data!
auto type = clang_getCursorType(cursor);
auto function_name = Convert(clang_getCursorSpelling(cursor));
auto return_type = Convert(clang_getTypeSpelling(clang_getResultType(type)));
int num_args = clang_Cursor_getNumArguments(cursor);
for (int i = 0; i < num_args; ++i)
{
auto arg_cursor = clang_Cursor_getArgument(cursor, i);
auto arg_name = Convert(clang_getCursorSpelling(arg_cursor));
if (arg_name.empty())
{
arg_name = "no name!";
}
auto arg_data_type = Convert(clang_getTypeSpelling(clang_getArgType(type, i)));
}
}
CXChildVisitResult functionVisitor(CXCursor cursor, CXCursor /* parent */, CXClientData /* clientData */)
{
if (clang_Location_isFromMainFile(clang_getCursorLocation(cursor)) == 0)
return CXChildVisit_Continue;
CXCursorKind kind = clang_getCursorKind(cursor);
if ((kind == CXCursorKind::CXCursor_FunctionDecl || kind == CXCursorKind::CXCursor_CXXMethod || kind == CXCursorKind::CXCursor_FunctionTemplate || \
kind == CXCursorKind::CXCursor_Constructor))
{
print_function_prototype(cursor);
}
return CXChildVisit_Continue;
}
You could try using clang_Cursor_getMangling() and demangle the result in order to get the complete definition.
I'm using the following for a project I am working on and it works great for the definition. TL&DR clang_getCursorPrettyPrinted with the policy TerseOutput set to true.
std::string getStdString(const CXString &s)
{
std::string rv = clang_getCString(s);
clang_disposeString(s);
return rv;
}
bool isFunctionImplementation(CXCursor &cursor,std::string &decl,std::string &filename,unsigned &lineno)
{
std::string cs = getStdString(clang_getCursorPrettyPrinted(cursor,nullptr));
if (cs.find('{') == std::string::npos) // Just a declaration, not the "meat" of the function, so we dont care
return false;
clang::LangOptions lo;
struct clang::PrintingPolicy pol(lo);
pol.adjustForCPlusPlus();
pol.TerseOutput = true;
pol.FullyQualifiedName = true;
decl = getStdString(clang_getCursorPrettyPrinted(cursor,&pol));
CXSourceLocation location = clang_getCursorLocation( cursor );
CXFile f;
lineno = 0;
filename = "(None)";
clang_getSpellingLocation(location,&f,&lineno,nullptr,nullptr);
if (lineno)
{
filename = getStdString(clang_File_tryGetRealPathName(f));
}
return isAllowedDirectory(filename);
}
This one checks if the function call is "meat" or just a definition. Obviously you can adjust as needed, including writing your own isAllowedDirectory function. Just pass the cursor, two strings and an unsigned into this as you walk your AST when you hit a declaration type.
I use the following, shorter way with clang 10 (though its using a matcher, not a cursor):
The 2 helper functions are general helpers to get the code snippet as a string.
// helper function 1: find position of end of token
SourceLocation
end_of_the_end(SourceLocation const & start_of_end, SourceManager & sm)
{
using namespace clang;
LangOptions lopt;
return Lexer::getLocForEndOfToken(start_of_end, 0, sm, lopt);
}
// helper function 2:
std::string getSymbolString(clang::SourceManager & sm,
const clang::SourceRange & range)
{
return std::string(sm.getCharacterData(range.getBegin()),
sm.getCharacterData(end_of_the_end(range.getEnd(), sm)));
}
The actual code snippet to get the function declaration string is:
// ... in run() of a matcher:
virtual void run(corct::result_t const & result) override
{
using namespace clang;
FunctionDecl * f_decl = const_cast<FunctionDecl *>(
result.Nodes.getNodeAs<FunctionDecl>(fd_bd_name_));
if(f_decl) {
SourceManager & sm(result.Context->getSourceManager());
FunctionDecl * f_decl = const_cast<FunctionDecl *>(
result.Nodes.getNodeAs<FunctionDecl>(fd_bd_name_));
auto full_decl_string =
getSymbolString(sm, f_decl->DeclaratorDecl::getSourceRange());
}
}
This will output inline bool test2(std::string const & str, std::vector<std::string> & sss) for the following function:
inline bool test2(std::string const & str, std::vector<std::string> & sss)
{
return true;
}
From the API page, I gather there's no function for what I'm trying to do. I want to read text from a file storing it as a list of strings, manipulate the text, and save the file. The first part is easy using the function:
abstract List<String> readAsLinesSync([Encoding encoding = Encoding.UTF_8])
However, there is no function that let's me write the contents of the list directly to the file e.g.
abstract void writeAsLinesSync(List<String> contents, [Encoding encoding = Encoding.UTF_8, FileMode mode = FileMode.WRITE])
Instead, I've been using:
abstract void writeAsStringSync(String contents, [Encoding encoding = Encoding.UTF_8, FileMode mode = FileMode.WRITE])
by reducing the list to a single string. I'm sure I could also use a for loop and feed to a stream line by line. I was wondering two things:
Is there a way to just hand the file a list of strings for writing?
Why is there a readAsLinesSync but no writeAsLinesSync? Is this an oversight or a design decision?
Thanks
I just made my own export class that handles writes to a file or for sending the data to a websocket.
Usage:
exportToWeb(mapOrList, 'local', 8080);
exportToFile(mapOrList, 'local/data/data.txt');
Class:
//Save data to a file.
void exportToFile(var data, String filename) =>
new _Export(data).toFile(filename);
//Send data to a websocket.
void exportToWeb(var data, String host, int port) =>
new _Export(data).toWeb(host, port);
class _Export {
HashMap mapData;
List listData;
bool isMap = false;
bool isComplex = false;
_Export(var data) {
// Check is input is List of Map data structure.
if (data.runtimeType == HashMap) {
isMap = true;
mapData = data;
} else if (data.runtimeType == List) {
listData = data;
if (data.every((element) => element is Complex)) {
isComplex = true;
}
} else {
throw new ArgumentError("input data is not valid.");
}
}
// Save to a file using an IOSink. Handles Map, List and List<Complex>.
void toFile(String filename) {
List<String> tokens = filename.split(new RegExp(r'\.(?=[^.]+$)'));
if (tokens.length == 1) tokens.add('txt');
if (isMap) {
mapData.forEach((k, v) {
File fileHandle = new File('${tokens[0]}_k$k.${tokens[1]}');
IOSink dataFile = fileHandle.openWrite();
for (var i = 0; i < mapData[k].length; i++) {
dataFile.write('${mapData[k][i].real}\t'
'${mapData[k][i].imag}\n');
}
dataFile.close();
});
} else {
File fileHandle = new File('${tokens[0]}_data.${tokens[1]}');
IOSink dataFile = fileHandle.openWrite();
if (isComplex) {
for (var i = 0; i < listData.length; i++) {
listData[i] = listData[i].cround2;
dataFile.write("${listData[i].real}\t${listData[i].imag}\n");
}
} else {
for (var i = 0; i < listData.length; i++) {
dataFile.write('${listData[i]}\n');
}
}
dataFile.close();
}
}
// Set up a websocket to send data to a client.
void toWeb(String host, int port) {
//connect with ws://localhost:8080/ws
//for echo - http://www.websocket.org/echo.html
if (host == 'local') host = '127.0.0.1';
HttpServer.bind(host, port).then((server) {
server.transform(new WebSocketTransformer()).listen((WebSocket webSocket) {
webSocket.listen((message) {
var msg = json.parse(message);
print("Received the following message: \n"
"${msg["request"]}\n${msg["date"]}");
if (isMap) {
webSocket.send(json.stringify(mapData));
} else {
if (isComplex) {
List real = new List(listData.length);
List imag = new List(listData.length);
for (var i = 0; i < listData.length; i++) {
listData[i] = listData[i].cround2;
real[i] = listData[i].real;
imag[i] = listData[i].imag;
}
webSocket.send(json.stringify({"real": real, "imag": imag}));
} else {
webSocket.send(json.stringify({"real": listData, "imag": null}));
}
}
},
onDone: () {
print('Connection closed by client: Status - ${webSocket.closeCode}'
' : Reason - ${webSocket.closeReason}');
server.close();
});
});
});
}
}
I asked Mads Agers about this. He works on the io module. He said that he decided not to add writeAsLines because he didn't find it useful. For one it is trivial to write the for loop and the other thing is that you have to parameterize it which the kind of line separator that you want to use. He said he can add it if there is a strong feeling that it would be valuable. He didn't immediately see a lot of value in it.