1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
12 #include "sjme/stdTypes.h"
13 #include "sjme/util.h"
14 #include "sjme/debug.h"
16 sjme_jint
sjme_compare_null(
17 sjme_attrInNullable sjme_cpointer a
,
18 sjme_attrInNullable sjme_cpointer b
)
20 /* Nulls before non-null. */
33 * Initializes the random number generator.
35 * @param outRandom The random state to initialize.
36 * @param seedHi The high seed value.
37 * @param seedLo The low seed value.
38 * @return Returns @c SJME_JNI_TRUE on success.
41 sjme_errorCode
sjme_randomInit(
42 sjme_attrInOutNotNull sjme_random
* outRandom
,
43 sjme_attrInValue sjme_jint seedHi
,
44 sjme_attrInValue sjme_jint seedLo
)
46 sjme_todo("Implement this?");
47 return SJME_ERROR_NOT_IMPLEMENTED
;
50 sjme_errorCode
sjme_randomInitL(
51 sjme_attrInOutNotNull sjme_random
* outRandom
,
52 sjme_attrInValue sjme_jlong seed
)
54 sjme_todo("Implement this?");
55 return SJME_ERROR_NOT_IMPLEMENTED
;
58 sjme_errorCode
sjme_randomNextInt(
59 sjme_attrInOutNotNull sjme_random
* random
,
60 sjme_attrOutNotNull sjme_jint
* outValue
)
62 sjme_todo("Implement this?");
63 return SJME_ERROR_NOT_IMPLEMENTED
;
66 sjme_errorCode
sjme_randomNextIntMax(
67 sjme_attrInOutNotNull sjme_random
* random
,
68 sjme_attrOutNotNull sjme_jint
* outValue
,
69 sjme_attrInPositiveNonZero sjme_jint maxValue
)
71 sjme_todo("Implement this?");
72 return SJME_ERROR_NOT_IMPLEMENTED
;
75 sjme_jint
sjme_string_charAt(sjme_lpcstr string
, sjme_jint index
)
85 /* Read until end of string. */
87 for (p
= string
; *p
!= 0;)
89 /* Decode character. */
90 c
= sjme_string_decodeChar(p
, &p
);
96 /* If this is the desired character then return it. */
101 /* Could not find character. */
105 sjme_jint
sjme_string_compareN(sjme_lpcstr aString
, sjme_jint aLen
,
106 sjme_lpcstr bString
, sjme_jint bLen
)
108 sjme_jint result
, limit
;
111 if (aString
== NULL
|| bString
== NULL
)
112 return sjme_compare_null(aString
, bString
);
114 /* Determine the max number of characters to compare. */
120 /* Compare strings up to the limit. */
121 result
= strncmp(aString
, bString
, limit
);
125 /* If the lengths differ, smaller is first. */
129 /* Equal otherwise. */
133 sjme_jint
sjme_string_decodeChar(sjme_lpcstr at
, sjme_lpcstr
* stringP
)
141 /* Read first character. */
142 c
= (*(at
++)) & 0xFF;
144 /* Invalid, cannot be this. */
148 /* Single byte character? */
152 /* Double byte character? */
153 else if ((c
& 0xE0) == 0xC0)
156 result
= (c
& 0x1F) << 6;
159 c
= (*(at
++)) & 0xFF;
161 /* Invalid continuation? */
162 if ((c
& 0xC0) != 0x80)
166 result
|= (c
& 0x3F);
168 /* Too low of a character? */
169 if (result
< 0x80 && result
!= 0)
173 /* Triple byte character. */
174 else if ((c
& 0xF0) == 0xE0)
177 result
= (c
& 0x0F) << 12;
180 c
= (*(at
++)) & 0xFF;
182 /* Invalid continuation? */
183 if ((c
& 0xC0) != 0x80)
187 result
|= (c
& 0x3F) << 6;
190 c
= (*(at
++)) & 0xFF;
192 /* Invalid continuation? */
193 if ((c
& 0xC0) != 0x80)
197 result
|= (c
& 0x3F);
199 /* Too low of a character? */
204 /* Invalid sequence. */
208 /* Return the result. */
214 sjme_jint
sjme_string_hash(sjme_lpcstr string
)
223 /* Initial result. */
226 /* Read until end of string. */
227 for (p
= string
; *p
!= 0;)
229 /* Decode character. */
230 c
= sjme_string_decodeChar(p
, &p
);
236 /* Calculate the hashCode(), the JavaDoc gives the following formula:
237 * == s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] .... yikes! */
238 result
= ((result
<< 5) - result
) + (sjme_jint
)c
;
241 /* Return calculated result. */
245 sjme_jint
sjme_string_hashN(sjme_lpcstr string
, sjme_jint limit
)
251 if (string
== NULL
|| limit
<= 0)
254 /* Initial result. */
257 /* Read until end of string. */
258 for (p
= string
, end
= p
+ limit
; *p
!= 0 && p
< end
;)
260 /* Decode character. */
261 c
= sjme_string_decodeChar(p
, &p
);
267 /* Calculate the hashCode(), the JavaDoc gives the following formula:
268 * == s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] .... yikes! */
269 result
= ((result
<< 5) - result
) + (sjme_jint
)c
;
272 /* Return calculated result. */
276 sjme_jint
sjme_string_length(sjme_lpcstr string
)
285 /* Read until end of string. */
287 for (p
= string
; *p
!= 0;)
289 /* Decode character. */
290 c
= sjme_string_decodeChar(p
, &p
);
296 /* Counts as a single character. */
300 /* Use whatever length we found. */
304 sjme_jint
sjme_string_lengthN(sjme_lpcstr string
, sjme_jint limit
)
310 if (string
== NULL
|| limit
< 0)
313 /* Read until end of string. */
315 for (p
= string
; *p
!= 0 && result
< limit
;)
317 /* Decode character. */
318 c
= sjme_string_decodeChar(p
, &p
);
324 /* Counts as a single character. */
328 /* Use whatever length we found. */
332 sjme_errorCode
sjme_swap_shu8_uint_memmove(
333 sjme_attrInNotNull sjme_pointer dest
,
334 sjme_attrInNotNull sjme_pointer src
,
335 sjme_attrInPositiveNonZero sjme_jint n
)
340 if (dest
== NULL
|| src
== NULL
)
341 return SJME_ERROR_NULL_ARGUMENTS
;
344 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
348 return SJME_ERROR_NONE
;
350 /* Perform initial move. */
351 memmove(dest
, src
, n
);
353 /* Then perform swapping. */
355 count
= n
/ sizeof(sjme_juint
);
356 for (i
= 0; i
< count
; i
++)
357 iDest
[i
] = sjme_swap_uint(iDest
[i
] << 8);
360 return SJME_ERROR_NONE
;
363 sjme_errorCode
sjme_swap_uint_memmove(
364 sjme_attrInNotNull sjme_pointer dest
,
365 sjme_attrInNotNull sjme_pointer src
,
366 sjme_attrInPositiveNonZero sjme_jint n
)
371 if (dest
== NULL
|| src
== NULL
)
372 return SJME_ERROR_NULL_ARGUMENTS
;
375 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
379 return SJME_ERROR_NONE
;
381 /* Perform initial move. */
382 memmove(dest
, src
, n
);
384 /* Then perform swapping. */
386 count
= n
/ sizeof(sjme_juint
);
387 for (i
= 0; i
< count
; i
++)
388 iDest
[i
] = sjme_swap_uint(iDest
[i
]);
391 return SJME_ERROR_NONE
;
394 sjme_juint
sjme_util_intBitCountU(
395 sjme_attrInValue sjme_juint v
)
397 v
= v
- ((v
>> 1) & UINT32_C(0x55555555));
398 v
= (v
& UINT32_C(0x33333333)) + ((v
>> 2) & UINT32_C(0x33333333));
399 return ((v
+ (v
>> 4) & UINT32_C(0xF0F0F0F)) * UINT32_C(0x1010101)) >> 24;
402 sjme_juint
sjme_util_intHighestOneBit(
403 sjme_attrInValue sjme_juint v
)
414 sjme_juint
sjme_util_intLeadingZeroesU(
415 sjme_attrInValue sjme_juint v
)
423 return sjme_util_intBitCountU(~v
);
426 sjme_juint
sjme_util_intOverShiftU(
427 sjme_attrInValue sjme_juint v
,
428 sjme_attrInRange(-32, 32) sjme_jint sh
)
430 /* Shifting more than this always results in zero. */
431 if (sh
<= -32 || sh
>= 32)
434 /* Shift by zero does nothing. */
438 /* Otherwise the shifted amount. */
440 return v
>> (sjme_juint
)(-sh
);
441 return v
<< (sjme_juint
)sh
;
444 sjme_jint
sjme_util_intReverse(sjme_jint v
)
446 return (sjme_jint
)sjme_util_intReverseU((sjme_juint
)v
);
449 sjme_juint
sjme_util_intReverseU(sjme_juint v
)
451 v
= (((v
& UINT32_C(0xAAAAAAAA)) >> 1) |
452 ((v
& UINT32_C(0x55555555)) << 1));
453 v
= (((v
& UINT32_C(0xCCCCCCCC)) >> 2) |
454 ((v
& UINT32_C(0x33333333)) << 2));
455 v
= (((v
& UINT32_C(0xF0F0F0F0)) >> 4) |
456 ((v
& UINT32_C(0x0F0F0F0F)) << 4));
457 v
= (((v
& UINT32_C(0xFF00FF00)) >> 8) |
458 ((v
& UINT32_C(0x00FF00FF)) << 8));
460 return ((v
>> 16) | (v
<< 16));
463 sjme_errorCode
sjme_util_intToBinary(
464 sjme_attrInNotNullBuf(destLen
) sjme_lpstr destBuf
,
465 sjme_attrInPositiveNonZero sjme_jint destLen
,
466 sjme_attrInValue sjme_juint inVal
,
467 sjme_attrInPositiveNonZero sjme_juint bitCount
)
473 return SJME_ERROR_NULL_ARGUMENTS
;
475 /* Correct bit count. */
476 if (bitCount
<= 0 || bitCount
> 32)
480 if (destLen
<= (3 + bitCount
))
481 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
483 /* Start with the prefix. */
488 /* Start from the top and go down. */
489 for (sh
= (1 << (bitCount
- 1)); sh
> 0; sh
>>= 1)
490 *(wp
++) = ((inVal
& sh
) != 0 ? '1' : '0');
494 return SJME_ERROR_NONE
;
497 sjme_errorCode
sjme_util_lpstrTrimEnd(
498 sjme_attrInNotNullBuf(length
) sjme_lpstr buf
,
499 sjme_attrInPositiveNonZero sjme_jint length
)
505 return SJME_ERROR_NULL_ARGUMENTS
;
508 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
510 /* Find end of string first. */
511 for (at
= 0; at
< length
;)
527 /* Remove any whitespace. */
532 /* NUL out whitespace. */
533 if (c
== ' ' || c
== '\r' || c
== '\n' || c
== '\t')
536 /* Nothing here anymore. */
542 return SJME_ERROR_NONE
;