Read input from a cocoa/foundation tool console? - cocoa

I wonder if Objective-C/Foundation has any special commands for reading user input from the console. Since it has NSLog for output maybe there is something else I could use instead of the scanf command.
I need to read some numbers (user input) into my tool. What is the best way to get these input in types like double or int? And how do I get user input into an NSString?

I was bored earlier and came across this issue of 'use scanf'. since I wanted to see if I could do it without dropping into c, the following came up:
NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput];
while (1)
{
NSData* data = [input availableData];
if(data != nil)
{
NSString* aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
I'm sure somebody could optimize this and make it nicer (this was used for a really simple PoC CLI tool)

The only real Cocoa support for input is NSFileHandle's fileHandleWithStandardInput. It isn't really more useful than scanf() if you ask me. But for getting input into specific types, well, that's pretty much NSFormatter's thing. There are already a lot of predefined formatter types for standard things, and you can make a custom formatter if you have more specialized needs. So if you need something a little more than scanf(), just read in the data (either as bytes with scanf() or data with NSFileHandle) and make an NSString from it and you can format it to your heart's content.

Nothing like scanf (which is a good thing). You can slurp data from stdin using NSFileHandle; for interactive input, fgets is better. You'll then want to use either strtol/strtoul/strtod, NSScanner, or NSNumberFormatter to convert the input to numeric types.

Related

About protobuf repeating varint decoding

I use charles and got a protobuf http message from other iOS applications. Now I want to genereate the same http packet but the output is not the same.
My protobuf file:
message TTCreateConversationBody
{
repeated uint32 imUid1 = 2;
}
I'm using objective-c:
TTCreateConversationBody *body = [TTCreateConversationBody new];
GPBUInt32Array *arr = [[GPBUInt32Array alloc] initWithCapacity:2];
[arr addValue:123123];
[arr addValue:9999999];
body.imUid1Array = arr;
and my output, charles decode it as a length-delimited string:
it's raw data and mine:
8A-26-10-08-01-10-AE-F7-81-80-9F-03-10-D4-E4-82-F0-D2-01
8A-26-10-08-01-12-0C-F9-F6-C3-9D-FA-02-AE-F7-81-80-9F-03
What's the correct protobuf file format?
They're actually both valid... ish.
This comes down to "packed" fields; without "packed", your two integers are encoded as
[header, varint][value][header, varint][value]
[10][AE-F7-81-80-9F-03][10][D4-E4-82-F0-D2-01]
where-as with "packed", it becomes
[header, string][length][value][value]
[12][0C][F9-F6-C3-9D-FA-02][AE-F7-81-80-9F-03]
note: the actual values look very different in the two runs... I'm assuming that is accidental.
To quote from the specification:
Protocol buffer parsers must be able to parse repeated fields that were compiled as packed as if they were not packed, and vice versa. This permits adding [packed=true] to existing fields in a forward- and backward-compatible way.
So: serializers should write the layout that is defined by whether your data is "packed" or not, but decoders must be able to handle it either way. Some libraries, when encountering data that should be "packed": determine which layout will actually be shorter, and make the final decision based on that. In reality, this can be approximated to "use packed encoding whenever there's at least two items".

Changing results in the debugger

I am trying to fix a bug in an iPhone app, and find myself in front of this situation.
The instance variable myView is of type MYTextView, and MYTextView is a subclass of UITextView.
At the debugger I enter a few times in a row: p myView.text
the strange thing, as one can see below, is that I get different results:
(lldb) p myView.text
(NSString *) $34 = 0x095da870 #"พี(the-date-in-Thai-Language)
05"
(lldb) p myView.text
(NSString *) $35 = 0x0a2c5620 #"พี(the-date-in-Thai-Language)
"
(lldb) p myView.text
(NSString *) $36 = 0x09515f60 #"พี(the-date-in-Thai-Language)
щ"
(lldb) p myView.text
(NSString *) $37 = 0x09515f80 #"พี(the-date-in-Thai-Language)
㏀ड़ख़筀ज़툠ज़梐
⨈Ⴊ"
(lldb) p myView.text
(NSString *) $38 = 0x0a2c3800 #"พี(the-date-in-Thai-Language)
妜샷फ़"
(lldb) p myView.text
(NSString *) $39 = 0x095e7010 #"พี(the-date-in-Thai-Language)
"
Above the results $35 and $39 contain what I expect, the other lines contain garbage at the end of the expect string.
I don't understand how this changing garbage can be here, when I am supposed to be inside the debugger an pausing.
One more thing is that I am having this kind of problem only with the Thai language.
Does anyone have an idea of what could be going on?
This looks like a bug in the data formatter for NSString.
Are you on Xcode 4.6? If so I would love it if you filed a bug against Xcode with as much context as possible.
My guess is that there is some buffer that is not being managed properly.
When you use the p command, there are several different things lldb can do.
For simple concrete types (int, int *) it may only print the value in the variable (10, 0xffffffff83021600). It may have a formatter preference set (e.g. display the int in hexadecimal). It may have a more sophisticated python formatter (which can read different parts of memory and present a high-level view of the object to you). Finally, it may actually run code in your program to come up with a high level view of that variable.
In this case, with Xcode 4.6, this looks like a simple NSString ivar and so the expectation is that lldb can use its built-in python formatter for NSString objects. This built-in formatter looks at the object memory and knows how to reconstruct the actual string for display without running any code in your program. In which case, the content of the string should not be modified.
Earlier versions (and gdb) may run code in your program to format the string, and it is possible that the program could change a little in the process. There is a lot of work done to ensure that doesn't happen, but the possibility exists.
Enrico is suspecting that the built-in python formatter function for NSString may be misbehaving somehow in your program and providing string summaries that change as you re-call the formatter. Please do file a bug report at http://bugreport.apple.com/ with the details for how to reproduce this behavior.

How do I capture a list of all running processes for OSX and save them as a file in Xcode / Cocoa?

I am wanting to capture a list of all running processes for OSX and save them as a file in Xcode / Cocoa. I googled this and all I found was:
[myWorkspace runningApplications];
And I am not sure how to do this. Please Help! Thank you!
As explained in QA1123, "process" means multiple different things on a Mac (and that changes over time).
A "process" at the level of Cocoa (or Carbon, or once upon a time Classic) is basically what an end-user thinks of as a process: an app, fba, launchitem, etc. A "process" at the level of BSD is what a Unix-trained sysadmin thinks of as a process: something that shows up in ps. A high-level process can have multiple BSD processes; the other way around used to be possible too (under Classic); you can also have BSD processes that have no high-level process; etc.
If you want the high-level definition, forget that QA, the method -[NSWorkspace runningApplications] that you mentioned returns exactly what you want: an array with an object for each such app, and those objects have all the info you want. How you save them in a file depends on what information you want about each one, what format you want to save that information in, etc. Here's a complete sample app that will save the URL of each app, one per line, to a file called "./appslist":
#include <Cocoa/Cocoa.h>
int main(int argc, char *argv[]) {
NSString *output = [NSString string];
for (NSRunningApplication *app in
[[NSWorkspace sharedWorkspace] runningApplications]) {
output = [output stringByAppendingFormat:#"%#\n",
[[app bundleURL] absoluteString]];
}
[output writeToFile:#"./appslist"
atomically:YES
encoding:NSUTF8StringEncoding
error:NULL];
return 0;
}
If you want the low-level definition, the code in that QA is still accurate. Or you could just exec (or system or NSTask) ps.
Anyway, here's a sample that (with the code from that QA) prints the pid of each running process to a local file called "./bsdlist":
int main(int argc, char *argv[]) {
kinfo_proc *procs;
size_t count;
int err = GetBSDProcessList(&procs, &count);
if (err) return err;
FILE *f = fopen("./bsdlist", "w");
for (size_t i=0; i!=count; ++i) {
fprintf(f, "%d\n", procs[i].kp_proc.p_pid);
}
fclose(f);
free(procs);
}
If you like the idea of scripting ps, as mentioned above, there are a number of ways to do this.
The DDTask library mentioned in Dominik's answer looks like the easiest way to do this. If you want to use NSTask directly, it takes a bit more code to set up an NSPipe for stdout, etc. There's a good general CocoaDev (it's scripting ls rather than ps, but the ideas are all the same.)
Or you could drop down to a lower level. You could explicitly fork/exec and pass the results through stdout, but the popen function is designed to wrap all of that up, and it's a lot easier to use. The GNU C Programming Tutorial shows how to popen ps -A and pipe it to grep init; the first half of this is all you need.
Whichever way you go, the problem is that you're going to get back a mess of strings you have to parse. The best thing to do is pass different flags to ps to only get what you actually want. If all you want is the command lines, ps -ax -ocommand= will give you nothing but that, one command line per line—no header line to skip, no columns to parse apart, etc.
If you're worried about efficiency: The QA says "exec'ing ps will require parsing the tool's output and will not use system resources as efficiently as Listing 1." And this is true; formatting the sysctl output into strings just to pass them over a pipe and parse them again is extra work that has to take some CPU time. But unless you're doing this millions of times, I doubt it uses enough to make a difference. The best approach (to this, and most cases) is to write the simpler code first and test whether it's fast enough; if it is, you're done.
yip to get high-level query the workspace as shown by abarnet
to get 'all' processes go lower-level and execute ps via an NSTask and read the response via a NSPipe.
there's sample code by apple ..
or use DDTask (a wrapper I wrote) github repository
NSString *exe = #"/bin/ps";
NSArray *args = #[#"-ax"];
NSString *res = [DDTask runTaskWithToolPath:exe andArguments:args andErrorHandler:nil];
[res writeToFile:#"./appslist"
atomically:YES
encoding:NSUTF8StringEncoding
error:NULL];

In Cocoa, how to explicitly use UTF-7 for encoding string to use in CC_MD5?

Hello dearest community,
I run into problem of creating an exact MD5 of a string. It must match with MD5 in the PHP and C# counterpart. Reading this : PHP MD5 not the same as .NET MD5, I guess that I must convert first the string using UTF-7 Encoding. But currently I only know that NSString only support UTF-8. This is my code of creating MD5 from a string :
-(NSString *) md5:(NSString *) str
{
const char *cStr = [str UTF8String];
unsigned char result[16];
CC_MD5( cStr, strlen(cStr), result );
return [NSString stringWithFormat:
#"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}
So, if I am not that mistaken, in the line that read [str UTF8String], I must change this into something that read [str UTF7String]. Am I correct? If it's is Cocoa have that functionality? Currently my googling didn't give good result for this.
Thanks
The post you linked to is absolutely incorrect. The MD5 algorithm works on blocks of bytes, it doesn't know anything about what those bytes represent.
All you need to do is ensure that the strings are encoded the same way in PHP, C# and Cocoa. Just use UTF-8. If you do, the MD5 hashes of the bytes representing the strings will be the same.
If you are using UTF-8 on all platforms and the hashes are different then there is likely a problem either with how you're feeding the data to the MD5 algorithm or in the implementation of the algorithm itself. The CC_MD5 function on Mac OS X should be considered correct.

Is the NSData a substring of the another NSData?

I have two NSData objects
NSData *toScan = /* initialized somehow with "Hello, this world." */;
NSData *toMatch = /* initialized somehow with "this" */;
What is the best way to know the toMatch bytes are the subset of toScan bytes?
I use C-functions for this purposes at this point: something like this
strstr([[toScan identifier] bytes], [[toMatch identifier] bytes]);
// returned bytes are null-terminated
but I think there is not the best way to use C-functions in object-oriented environment...
As of Snow Leopard and iOS 4.0, NSData has -rangeOfData:options:range: which should do what you want.
It's also pretty darn fast.
In a different question, I wrote an answer containing an NSData category with a rangeOfData: method:
Elegant Algorithm for Parsing Data Stream Into Record
That'll do what you're looking for.

Resources