I have long text content and I want to display it on screen with justify alignment using LabelField or something else. Currently, I can do right/left/center align but can't justify align.
Are there any custom controls that help me do this?
This is just a prototype, so there may be some things it doesn't handle. But, it should be a start, that you can use to do what you want. Most of the important logic is in the paint() method.
I'm not aware of any built-in (RIM libraries) way to do this.
public class JustifiedLabelField extends LabelField {
/** a cache of the label's words, to avoid having to recalculate every
time paint() is called */
private String[] _words;
/** the dynamic field height */
private int _height = 0;
public JustifiedLabelField(Object text, long style){
super(text, style);
setText(text);
}
public void setText(Object text) {
// update the words cache when text changes
_words = split((String)text, " "); // NOTE: this only supports String type!
super.setText(text);
}
public int getPreferredHeight() {
// I believe overriding this method is necessary because the
// justification might produce a different total number of lines,
// depending on the algorithm used
return (_height > 0) ? _height : super.getPreferredHeight();
}
protected void paint(Graphics g) {
Font font = g.getFont();
int space = font.getAdvance(' ');
int fontHeight = font.getHeight();
int fieldWidth = getWidth();
int word = 0;
int y = 0;
while (word < _words.length) {
// each iteration of this loop handles one line
int wordsInLine = 0;
int lineWordWidths = 0;
// first loop over all words that fit on this line, to measure
while (word < _words.length) {
int wordWidth = font.getAdvance(_words[word]);
if (lineWordWidths + wordWidth <= fieldWidth) {
lineWordWidths += (wordWidth + space);
word++;
wordsInLine++;
} else {
break;
}
}
// how much total space (gap) should be placed between every two words?
int gapSpacing = 0;
if (word == _words.length) {
// don't justify at all on last line
gapSpacing = space;
} else if (wordsInLine != 1) {
gapSpacing = (fieldWidth - (lineWordWidths - wordsInLine * space)) / (wordsInLine - 1);
}
int x = 0;
// now actually draw the words, with added spacing
for (int j = word - wordsInLine; j < word; j++) {
int span = g.drawText(_words[j], x, y);
x += span + gapSpacing;
}
y += fontHeight;
}
_height = y;
}
}
The above code makes use of a String split() method. You can find one possible implementation here.
Then, use the class like this:
public LabelScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
String loremIpsum = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam cursus. Morbi ut mi. Nullam enim leo, egestas id, condimentum at, laoreet mattis, massa. Sed eleifend nonummy diam. Praesent mauris ante, elementum et, bibendum at, posuere sit amet, nibh. Duis tincidunt lectus quis dui viverra vestibulum. Suspendisse vulputate aliquam dui. Nulla elementum dui ut augue. Aliquam vehicula mi at mauris. Maecenas placerat, nisl at consequat rhoncus, sem nunc gravida justo, quis eleifend arcu velit quis lacus. Morbi magna magna, tincidunt a, mattis non, imperdiet vitae, tellus. Sed odio est, auctor ac, sollicitudin in, consequat vitae, orci. Fusce id felis. Vivamus sollicitudin metus eget eros.";
JustifiedLabelField label = new JustifiedLabelField(loremIpsum, Field.NON_FOCUSABLE);
add(label);
}
producing this:
Limitations
I don't do anything to account for things like padding in this field
LabelField allows you to call setText() or the constructor, with other types, not just String. My class only supports String, but you could easily expand that.
My class splits the string on spaces (' ') only. You may want to support splitting on other characters, or even inserting dashes to break really long words. I'll leave that to you.
I didn't test any edge cases, like words that were longer than could fit in the field width. I only tested this with a full screen width field, with small to medium-sized words.
see Eugen's comments on the page I link to for the split() method used
Follow-Up
I refined the code posted above a bit, and posted it online here. The newer version should handle padding, which this version does not. It should also handle vertical size issues if you pick a string splitting algorithm that changes how many lines the LabelField superclass thinks the field should have. More comments, too.
Related
I have a question about the implementation of digital filters in CoreAudio. I'm in big trouble because it is a few weeks I'm trying to understand how to implement them. The basic idea is this: while I talk to the iPhone's microphone, my voice is filtered by a low-pass filter or high-pass or bandpass.
I Studied the books "Learning Core Audio" for the implementation of the CoreAudio (Although I had to work it a few weeks and do research, but now work very well) and the book "Digital Signal Processing" (very famous because i saw him indicated always in discussions dedicated to the filters).
Book of DSP I understand this: I must Create a filter, a sort of kernel filter that is a kind of "mask" to be applied to the signal itself. In this state the filter is said "Impulse Response" or also is said IIR. Now I apply the mask to signal by a function convolution becoming a FIR filter. What I have written is this correct?
I tried to implement what is written, taking even the AudioGraph application example as with the Documentation, but nothing. Does not work.
I also found a document which explained in a simple way what to do (the name is "Creating FIR Filters in C ++") where the algorithms of the filters were mentioned, but even here, once Implemented have not worked.
For this is coming to me the doubt: maybe something else I have to do with the signal that I get? The only thing that I understand is I have to convert the signal in Sint16. I did, but then what? What should I do to implement a digital filter?
For this I ask for help. I have no one to confront and so now I'm going blind. I leave you with my current code of CoreAudio, I works perfectly, even on devices, but, perhaps, may be some wrong setting?
AudioComponentDescription AudioCompDesc;
AudioCompDesc.componentType = kAudioUnitType_Output;
AudioCompDesc.componentSubType = kAudioUnitSubType_RemoteIO;
AudioCompDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioCompDesc.componentFlags = 0;
AudioCompDesc.componentFlagsMask = 0;
AudioComponent RIOComponente = AudioComponentFindNext(NULL, &AudioCompDesc);
CheckError(AudioComponentInstanceNew(RIOComponente, &strutturaAscolto.RIO), "Impossibile ottenre un'istanza dell'unità RIO");
UInt32 oneFlag = 1;
AudioUnitElement bus0 = 0;
CheckError(AudioUnitSetProperty (strutturaAscolto.RIO, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output,bus0, &oneFlag, sizeof(oneFlag)), "Impossibile abilitare l'uscita RIO");
AudioUnitElement bus1 = 1;
CheckError(AudioUnitSetProperty(strutturaAscolto.RIO, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, bus1, &oneFlag, sizeof(oneFlag)),"Imposibile abilitare l'ingresso RIO");
strutturaAscolto.AudioAscoltoASBD.mSampleRate = 44100;
strutturaAscolto.AudioAscoltoASBD.mFormatID = kAudioFormatLinearPCM;
strutturaAscolto.AudioAscoltoASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked;
strutturaAscolto.AudioAscoltoASBD.mBytesPerPacket = 4;
strutturaAscolto.AudioAscoltoASBD.mFramesPerPacket = 1;
strutturaAscolto.AudioAscoltoASBD.mBytesPerFrame = 4;
strutturaAscolto.AudioAscoltoASBD.mChannelsPerFrame = 2;
strutturaAscolto.AudioAscoltoASBD.mBitsPerChannel = 16;
CheckError(AudioUnitSetProperty (strutturaAscolto.RIO, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, bus0, &strutturaAscolto.AudioAscoltoASBD, sizeof (strutturaAscolto.AudioAscoltoASBD)), "Impossibile impostare la descrizione audio (ASBD) per RIO sull'applicazione di ingresso 0");
CheckError(AudioUnitSetProperty (strutturaAscolto.RIO, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, bus1, &strutturaAscolto.AudioAscoltoASBD, sizeof (strutturaAscolto.AudioAscoltoASBD)), "Impossibile impostare la descrizione audio (ASBD) per RIO sull'applicazione di uscita 1");
strutturaAscolto.SenoFrequenza = 30;
strutturaAscolto.SenoFase = 0;
AURenderCallbackStruct CallbackStruct;
CallbackStruct.inputProc = ModulazioneAudio;
CallbackStruct.inputProcRefCon = &strutturaAscolto;
CheckError(AudioUnitSetProperty(strutturaAscolto.RIO, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, bus0, &CallbackStruct, sizeof (CallbackStruct)), "Impossibile impostare il rendering di callback di RIO sul bus 0");
CheckError(AudioUnitInitialize(strutturaAscolto.RIO), "Non è stato possibile inizializzare l'unità RIO");
CheckError(AudioOutputUnitStart(strutturaAscolto.RIO), "Non è stato possibile avviare l'unità RIO");
While the function that should accommodate the filter is simply this.
static OSStatus ModulazioneAudio(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,AudioBufferList *ioData) {
StrutturaAscolto *strutturaAscolto = (StrutturaAscolto*) inRefCon;
UInt32 bus1 = 1;
CheckError(AudioUnitRender(strutturaAscolto->RIO, ioActionFlags, inTimeStamp, bus1, inNumberFrames, ioData), "Non è stato possibile fare il render dell'unità RIO");
return noErr;
}
I leave with some filters, what I tested (not all). Taking this algorithm for the high-pass filter of the document "Creating FIR Filters in C++":
int N = 1024;
float f_c = 5000/44100;
float ω_c = 2*M_PI*f_c;
int middle = N/2;
int i = -N/2;
float fltr[middle];
do {
if (i == 0) {
fltr[middle] = 1 - 2*f_c;
}
else {
fltr[i+middle] = -sin(ω_c*i)/(M_PI*i);
}
i++;
} while(i != N/2);
This i did by taking the book DPS (chapter 16) and is also referred to in the application AudioGraph.
void lowPassWindowedSincFilter( float *buf , float fc ) {
int i;
int m = 100;
float sum = 0;
for( i = 0; i < 101 ; i++ ) {
if((i - m / 2) == 0 ) {
buf[i] = 2 * M_PI * fc;
}
else {
buf[i] = sin(2 * M_PI * fc * (i - m / 2)) / (i - m / 2);
}
buf[i] = buf[i] * (.54 - .46 * cos(2 * M_PI * i / m ));
}
for ( i = 0 ; i < 101 ; i++ ) {
sum = sum + buf[i];
}
for ( i = 0 ; i < 101 ; i++ ) {
buf[i] = buf[i] / sum;
}
}
As for the convolution function, I used to Hamming, very simple that I found right here on StackOverflow.
for (int i = 0; i < 1024; i++) {
double multiplier = 0.5 * (1 - cos(2*M_PI*i/1023));
dataOut[i] = multiplier * dataIn[i];
}
Thank you for your attention.
Recently, I've stumbled upon an interview question where you need to write a code that's optimized for ARM, especially for iphone:
Write a function which takes an array of char (ASCII symbols) and find
the most frequent character.
char mostFrequentCharacter(char* str, int size)
The function should be optimized to run on dual-core ARM-based
processors, and an infinity amount of memory.
On the face of it, the problem itself looks pretty simple and here is the simple implementation of the function, that came out in my head:
#define RESULT_SIZE 127
inline int set_char(char c, int result[])
{
int count = result[c];
result[c] = ++count;
return count;
}
char mostFrequentChar(char str[], int size)
{
int result[RESULT_SIZE] = {0};
char current_char;
char frequent_char = '\0';
int current_char_frequency = 0;
int char_frequency = 0;
for(size_t i = 0; i<size; i++)
{
current_char = str[i];
current_char_frequency = set_char(current_char, result);
if(current_char_frequency >= char_frequency)
{
char_frequency = current_char_frequency;
frequent_char = current_char;
}
}
return frequent_char;
}
Firstly, I did some basic code optimization; I moved the code, that calculates the most frequent char every iteration, to an additional for loop and got a significant increase in speed, instead of evaluating the following block of code size times
if(current_char_frequency >= char_frequency)
{
char_frequency = current_char_frequency;
frequent_char = current_char;
}
we can find a most frequent char in O(RESULT_SIZE) where RESULT_SIZE == 127.
char mostFrequentCharOpt1(char str[], int size)
{
int result[RESULT_SIZE] = {0};
char frequent_char = '\0';
int current_char_frequency = 0;
int char_frequency = 0;
for(int i = 0; i<size; i++)
{
set_char(str[i], result);
}
for(int i = 0; i<RESULT_SIZE; i++)
{
current_char_frequency = result[i];
if(current_char_frequency >= char_frequency)
{
char_frequency = current_char_frequency;
frequent_char = i;
}
}
return frequent_char;
}
Benchmarks: iPhone 5s
size = 1000000
iterations = 500
// seconds = 7.842381
char mostFrequentChar(char str[], int size)
// seconds = 5.905090
char mostFrequentCharOpt1(char str[], int size)
In average, the mostFrequentCharOpt1 works in ~24% faster than basic implementation.
Type optimization
The ARM cores registers are 32-bits long. Therefore, changing all local variables that has a type char to type int prevents the processor from doing additional instructions to account for the size of the local variable after each assignment.
Note: The ARM64 provides 31 registers (x0-x30) where each register is 64 bits wide and also has a 32-bit form (w0-w30). Hence, there is no need to do something special to operate on int data type.
infocenter.arm.com - ARMv8 Registers
While comparing functions in assembly language version, I've noticed a difference between how the ARM works with int type and char type. The ARM uses LDRB instruction to load byte and STRB instruction to store byte into individual bytes in memory. Thereby, from my point of view, LDRB is a bit slower than LDR, because LDRB do zero-extending every time when accessing a memory and load to register. In other words, we can't just load a byte into the 32-bit registers, we should cast byte to word.
Benchmarks: iPhone 5s
size = 1000000
iterations = 500
// seconds = 5.905090
char mostFrequentCharOpt1(char str[], int size)
// seconds = 5.874684
int mostFrequentCharOpt2(char str[], int size)
Changing char type to int didn't give me a significant increase of speed on iPhone 5s, by way of contrast, running the same code on iPhone 4 gave a different result:
Benchmarks: iPhone 4
size = 1000000
iterations = 500
// seconds = 28.853877
char mostFrequentCharOpt1(char str[], int size)
// seconds = 27.328955
int mostFrequentCharOpt2(char str[], int size)
Loop optimization
Next, I did a loop optimization, where, instead of incrementing i value, I decremented it.
before
for(int i = 0; i<size; i++) { ... }
after
for(int i = size; i--) { ... }
Again, comparing assembly code, gave me a clear distinction between the two approaches.
mostFrequentCharOpt2 | mostFrequentCharOpt3
0x10001250c <+88>: ldr w8, [sp, #28] ; w8 = i | 0x100012694 <+92>: ldr w8, [sp, #28] ; w8 = i
0x100012510 <+92>: ldr w9, [sp, #44] ; w9 = size | 0x100012698 <+96>: sub w9, w8, #1 ; w9 = i - 1
0x100012514 <+96>: cmp w8, w9 ; if i<size | 0x10001269c <+100>: str w9, [sp, #28] ; save w9 to memmory
0x100012518 <+100>: b.ge 0x100012548 ; if true => end loop | 0x1000126a0 <+104>: cbz w8, 0x1000126c4 ; compare w8 with 0 and if w8 == 0 => go to 0x1000126c4
0x10001251c <+104>: ... set_char start routine | 0x1000126a4 <+108>: ... set_char start routine
... | ...
0x100012534 <+128>: ... set_char end routine | 0x1000126bc <+132>: ... set_char end routine
0x100012538 <+132>: ldr w8, [sp, #28] ; w8 = i | 0x1000126c0 <+136>: b 0x100012694 ; back to the first line
0x10001253c <+136>: add w8, w8, #1 ; i++ | 0x1000126c4 <+140>: ...
0x100012540 <+140>: str w8, [sp, #28] ; save i to $sp+28 |
0x100012544 <+144>: b 0x10001250c ; back to the first line |
0x100012548 <+148>: str ... |
Here, in place of accessing size from the memory and comparing it with the i variable, where the i variable, was incrementing, we just decremented i by 0x1 and compared the register, where the i is stored, with 0.
Benchmarks: iPhone 5s
size = 1000000
iterations = 500
// seconds = 5.874684
char mostFrequentCharOpt2(char str[], int size) //Type optimization
// seconds = 5.577797
char mostFrequentCharOpt3(char str[], int size) //Loop otimization
Threading optimization
Reading the question accurately gives us at least one more optimization. This line ..optimized to run on dual-core ARM-based processors ... especially, dropped a hint to optimize the code using pthread or gcd.
int mostFrequentCharThreadOpt(char str[], int size)
{
int s;
int tnum;
int num_threads = THREAD_COUNT; //by default 2
struct thread_info *tinfo;
tinfo = calloc(num_threads, sizeof(struct thread_info));
if (tinfo == NULL)
exit(EXIT_FAILURE);
int minCharCountPerThread = size/num_threads;
int startIndex = 0;
for (tnum = num_threads; tnum--;)
{
startIndex = minCharCountPerThread*tnum;
tinfo[tnum].thread_num = tnum + 1;
tinfo[tnum].startIndex = minCharCountPerThread*tnum;
tinfo[tnum].str_size = (size - minCharCountPerThread*tnum) >= minCharCountPerThread ? minCharCountPerThread : (size - minCharCountPerThread*(tnum-1));
tinfo[tnum].str = str;
s = pthread_create(&tinfo[tnum].thread_id, NULL,
(void *(*)(void *))_mostFrequentChar, &tinfo[tnum]);
if (s != 0)
exit(EXIT_FAILURE);
}
int frequent_char = 0;
int char_frequency = 0;
int current_char_frequency = 0;
for (tnum = num_threads; tnum--; )
{
s = pthread_join(tinfo[tnum].thread_id, NULL);
}
for(int i = RESULT_SIZE; i--; )
{
current_char_frequency = 0;
for (int z = num_threads; z--;)
{
current_char_frequency += tinfo[z].resultArray[i];
}
if(current_char_frequency >= char_frequency)
{
char_frequency = current_char_frequency;
frequent_char = i;
}
}
free(tinfo);
return frequent_char;
}
Benchmarks: iPhone 5s
size = 1000000
iterations = 500
// seconds = 5.874684
char mostFrequentCharOpt3(char str[], int size) //Loop optimization
// seconds = 3.758042
// THREAD_COUNT = 2
char mostFrequentCharThreadOpt(char str[], int size) //Thread otimization
Note: mostFrequentCharThreadOpt works slower than mostFrequentCharOpt2 on iPhone 4.
Benchmarks: iPhone 4
size = 1000000
iterations = 500
// seconds = 25.819347
char mostFrequentCharOpt3(char str[], int size) //Loop optimization
// seconds = 31.541066
char mostFrequentCharThreadOpt(char str[], int size) //Thread otimization
Question
How well optimized is the mostFrequentCharOpt3 and mostFrequentCharThreadOpt, in other words: are there any other methods to optimize both methods?
Source code
Alright, the following things you can try, I can't 100% say what will be effective in your situation, but from experience, if you put all possible optimizations off, and looking at the fact that even loop optimization worked for you: your compiler is pretty numb.
It slightly depends a bit on your THREAD_COUNT, you say its 2 at default, but you might be able to spare some time if you are 100% its 2. You know the platform you work on, don't make anything dynamic without a reason if speed is your priority.
If THREAD == 2, num_threads is a unnecessary variable and can be removed.
int minCharCountPerThread = size/num_threads;
And the olden way to many discussed topic about bit-shifting, try it:
int minCharCountPerThread = size >> 1; //divide by 2
The next thing you can try is unroll your loops: multiple loops are only used 2 times, if size isn't a problem, why not remove the loop aspect?
This is really something you should try, look what happens, and if it useful too you. I've seen cases loop unrolling works great, I've seen cases loop unrolling slows down my code.
Last thing: try using unsigned numbers instead if signed/int (unless you really need signed). It is known that some tricks/instruction are only available for unsigned variables.
There are quite a few things you could do, but the results will really depend on which specific ARM hardware the code is running on. For example, older iPhone hardware is completely different than the newer 64 bit devices. Totally different hardware arch and diff instruction set. Older 32 bit arm hardware contained some real "tricks" that could make things a lot faster like multiple register read/write operation. One example optimization, instead of loading bytes you load while 32 bit words and then operate on each byte in the register using bit shifts. If you are using 2 threads, then another approach can be to break up the memory access so that 1 memory page is processed by 1 thread and then the second thread operates on the 2nd memory page and so on. That way different registers in the different processors can do maximum crunching without reading or writing to the same memory page (and memory access is the slow part typically). I would also suggest that you start with a good timing framework, I built a timing framework for ARM+iOS that you might find useful for that purpose.
I tried this:
NSInteger numberFinal = 100000000000000000 + ((float)arc4random() / UINT32_MAX) * (999999999999999999 - 100000000000000000);
but it returns zero... I don't want to specify the range, but just want any number with 18 digits...
For your requirement, as #duDE mentioned you can't use a NSInteger to save 18 digit number, but there is a solution using NSString.
NSString *eighteenDigitNumberString = [[NSNumber numberWithInt:1 + arc4random_uniform(9)] stringValue];
for (int i = 0; i < 17; i++) {
eighteenDigitNumberString = [eighteenDigitNumberString stringByAppendingString:[[NSNumber numberWithInt:arc4random_uniform(10)] stringValue]];
}
NSLog(#"eighteenDigitNumberString : %#", eighteenDigitNumberString);
There we go, no need to explain everything is straightforward.
EDITED: if you really want a long long value you can do so:
long long eighteenDigitNumberLongLong = [eighteenDigitNumberString longLongValue];
EDITED: To avoid the leading 0 the initial string has been initiated with a non-zero number and the loop is running only 17 times.
As the maximum value of an NSInteger is NSIntegerMax, you cann't use NSInteger for your purpose:
enum {
NSNotFound = NSIntegerMax
};
Prior to OS X v10.5, NSNotFound was defined as 0x7fffffff.
This is 2147483647 (decimal).
If you need "any number" with 18 digits (as #A-Live assumes), you can take NSFloat for example.
A 18 digit integer will require a long long type.
Create two 9 digit random numbers, multiple one by 10^9 and add to the other.
const u_int32_t digits9 = 1000000000;
u_int32_t ms = arc4random_uniform(digits9);
u_int32_t ls = arc4random_uniform(digits9);
unsigned long long random18 = ((unsigned long long)ms * digits9) + ls;
NSLog(#"Example random18: %018llu", random18);
Output:
Example random18: 501895974656079554
If the number must have a leading non zero digit:
const u_int32_t digits81 = 100000000;
const u_int32_t digits89 = 900000000;
const u_int32_t digits9 = 1000000000;
u_int32_t ms = arc4random_uniform(digits89) + digits81;
u_int32_t ls = arc4random_uniform(digits9);
unsigned long long random18 = ((unsigned long long)ms * digits9) + ls;
If you need strictly 18 digits it would be better to use this code:
NSString *stringNumber = [NSString string];
for (int i = 0; i < 18; i++) {
if (i == 0) {
stringNumber = [stringNumber stringByAppendingString:[NSString stringWithFormat:#"%#", #(arc4random_uniform(9) + 1)]];
} else {
stringNumber = [stringNumber stringByAppendingString:[NSString stringWithFormat:#"%#", #(arc4random_uniform(10))]];
}
}
long long value = stringNumber.longLongValue;
You need the first condition because with the possibility of 0.1 you may receive 0 as the first digit, then your 18-digit integer would become 17-digit, with 0.01 possibility - 16-digit integer etc.
You're getting into unsigned long long territory...
#define ARC4RANDOM_MAX 0x100000000
float val = ((double)arc4random() / ARC4RANDOM_MAX);
unsigned long long numberToAdd = val * (900000000000000000-1);
unsigned long long numberFinal = 100000000000000000 + numberToAdd;
NSLog( #"value = %llu", numberFinal);
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I am working on a app which sends data to server with user location info. Server accept this data based on checksum calculation, which is written in java.
Here is the code written in Java:
private static final String CHECKSUM_CONS = "1217278743473774374";
private static String createChecksum(double lat, double lon) {
int latLon = (int) ((lat + lon) * 1E6);
String checkSumStr = CHECKSUM_CONS + latLon;
byte buffer[] = checkSumStr.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
CheckedInputStream cis = new CheckedInputStream(bais, new Adler32());
byte readBuffer[] = new byte[50];
long value = 0;
try {
while (cis.read(readBuffer) >= 0) {
value = cis.getChecksum().getValue();
}
} catch (Exception e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
return String.valueOf(value);
}
I tried looking for help to find out how to write objective c equivalent of this. Above function uses adler32 and I don't have any clue about that. Please help.
Thanks for your time.
The answers shown here by #achievelimitless and #user3275097 are incorrect.
First off, signed integers should not be used. The modulo operator on negative numbers is defined differently in different languages, and should be avoided when possible. Simply use unsigned integers instead.
Second, the loops will quickly overflow the 16-bit accumulators, which will give the wrong answer. The modulo operations can be deferred, but they must be done before overflow. You can calculate how many loops you can do safely by assuming that all of the input bytes are 255.
Third, because of the second point, you should not use 16-bit types. You should use at least 32-bit types to avoid having to do the modulo operation very often. You still need to limit the number of loops, but the number gets much bigger. For 32-bit unsigned types, the maximum number of loops is 5552. So the basic code looks like:
#define MOD 65521
#define MAX 5552
unsigned long adler32(unsigned char *buf, size_t len)
{
unsigned long a = 1, b = 0;
size_t n;
while (len) {
n = len > MAX ? MAX : len;
len -= n;
do {
a += *buf++;
b += a;
} while (--n);
a %= MOD;
b %= MOD;
}
return a | (b << 16);
}
As noted by #Sulthan, you should simply use the adler32() function provided in zlib, which is already there on Mac OS X and iOS.
On basis of definition of adler32 checksum as mentioned in wikipedia,
Objective C implementation would be like this:
static NSNumber * adlerChecksumof(NSString *str)
{
NSMutableData *data= [[NSMutableData alloc]init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
for (int i = 0; i < ([str length] / 2); i++)
{
byte_chars[0] = [str characterAtIndex:i*2];
byte_chars[1] = [str characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
int16_t a=1;
int16_t b=0;
Byte * dataBytes= (Byte *)[data bytes];
for (int i=0; i<[data length]; i++)
{
a+= dataBytes[i];
b+=a;
}
a%= 65521;
b%= 65521;
int32_t adlerChecksum= b*65536+a;
return #(adlerChecksum);
}
Here str would be your string as mentioned in your question..
So when you want to calculate checksum of some string just do this:
NSNumber * calculatedChkSm= adlerChecksumof(#"1217278743473774374");
Please Let me know if more info needed
I am working on an application that requires text larger than the viewable screen size in both a TreeField and a ListField. As you know, the TreeField and ListField callbacks support only
graphics.drawText() methods, so I cannot add an instance of a Field per row.
Does anyone have a method of Scrolling horizontally past the viewable text size?
Is there maybe a scrollable panel that would work? I know of the NullField(Field.Focusable) trick but this won't work on the list field.
Lastly, I am aware that the type of screen makes a different as FullScreen and MainScreen use VerticalFieldMangers. So am using a PopupScreen at the moment for my testing.
Thank you in advance for your time.
Maybe it's better to split text in two lines and set row height 2 x font height (+ margins)?
alt text http://img219.imageshack.us/img219/5802/listh.jpg
class Scr extends MainScreen implements ListFieldCallback {
int DISPLAY_WIDTH = Display.getWidth();
Vector mItems = new Vector();
ListField mListField = new ListField();
public Scr() {
mListField.setCallback(this);
add(mListField);
mItems.addElement("Lorem ipsum dolor sit amet, ");
mItems.addElement("Lorem ipsum dolor sit");
mItems.addElement("Lorem ipsum dolor sit amet, "+
"consectetuer adipiscing elit");
mItems.addElement("Lorem ipsum dolor sit amet, "+
"consectetuer adipiscing elit, sed diam "+
"nonummy nibh euismod");
mItems.addElement("Lorem ipsum dolor sit amet, "+
"consectetuer adipiscing elit");
mItems.addElement("Lorem ipsum dolor sit amet, ");
mListField.setSize(mItems.size());
mListField.setRowHeight(
mListField.getFont().getHeight()*2 + 4);
}
public void drawListRow(ListField field, Graphics g,
int i, int y, int w) {
// Draw the text.
String text = (String) get(field, i);
if(g.getFont().getAdvance(text) > w)
{
int index = 0;
while(g.getFont().getAdvance(text.substring(0, index)) < w)
{
index++;
}
g.drawText(text.substring(0, index), 0, y, 0, w);
g.drawText(text.substring(index, text.length()-1), 0,
y + g.getFont().getHeight()+ 4, DrawStyle.ELLIPSIS, w);
}
else
{
g.drawText(text, 0, y, 0, w);
}
}
public Object get(ListField listField, int index) {
return mItems.elementAt(index);
}
public int getPreferredWidth(ListField listField) {
return DISPLAY_WIDTH;
}
public int indexOfList(ListField listField,
String prefix, int start) {
return 0;
}
}