A bug or have I done something wrong

I'm trying to use the string.toNumberWithBase() function and I'm getting an interesting bug (?)

This is on a Garmin 630.

Easy to reproduce with a minimal program. Create the basic App (the one with the monkey on the face)

edit the View.mc file's onUpdate to look like this

// Update the view
function onUpdate(dc) {
// Call the parent onUpdate function to redraw the layout
var fff,ggg;
fff = "0X";
ggg = fff.toNumberWithBase(36);
View.onUpdate(dc);
}

Run it in the simulator. It works without crashing.

Run it on an actual Garmin 630 and it crashes the app.

I have tried cycling through a number of string sequences, and the only 2 character one I have found so far is 0X (Thats zero X). All before it work, and all after it work, but 0X crashes it and only on the actual watch.

I'm suspecting it's trying to interpret the string as a hex number (eg 0X1A) and cant find the rest of the string given I only supply 2 characters.

Can anyone see if I'm mistaken in my use of the toNumberWithBase.

From my understanding, with 36, it should use 0-9 and A-Z
  • Douglas,

    Read the original post carefully. It works just fine for all character sequences he tested except OX (and presumably Ox). If the call "11".toNumberWithBase(36) works (as he has indicated), then the function is available on the device.

    Andrew,

    I've done some testing on the simulator, and everything is working as I'd expect. This is consistent with what you reported. I'll try to test on a device tonight, and I'll let you know what I find.

    Travis
  • Read the original post carefully. It works just fine for all character sequences he tested except OX (and presumably Ox). If the call "11".toNumberWithBase(36) works (as he has indicated), then the function is available on the device.


    You're right. I misread his post as it "was crashing the device in all cases" -- a misread possibly due to a lack of sleep but more than likely due to frustration with the documentation of what should be in CIQ SDK 1.3 in terms of backporting from 2.1. When I see something documented as introduced in 2.1 then I assume it's not available in 1.3. Then my brain filled in the rest, albeit incorrectly. 😔

    Cheers,
    Douglas
  • Andrew,

    My trivial test case shows that the function is not available on the fr630, which is inconsistent with your original claim.

    using Toybox.Application as App;
    using Toybox.Graphics as Gfx;
    using Toybox.System as Sys;
    using Toybox.WatchUi as Ui;

    class MyView extends Ui.View
    {
    function initialize() {
    View.initialize();
    }
    }

    const _values = [
    "0",
    "1",
    "01",
    "02",
    "08",
    "09",
    "0a",
    "0A",
    "0w",
    "0W",
    "0x",
    "0X",
    "0y",
    "0Y",
    "0z",
    "0Z"
    ];

    class MyApp extends App.AppBase
    {
    function initialize() {
    AppBase.initialize();

    Sys.println(Lang.format("toNumberWithBase() $1$ available",
    [ Lang.String has :toNumberWithBase ? "is" : "is not" ]));

    for (var i = 0; i < _values.size(); ++i) {
    var n = _values.toNumberWithBase(36);
    Sys.println(Lang.format("$1$b36 => $2$", [ _values, n ]));
    }
    }

    function getInitialView() {
    return [ new MyView() ];
    }
    }
    [/code]

    The Apps/LOGS/CIQ_LOG.txt file that is produced on the device reads...

    ERROR: Symbol Not Found Error
    DETAILS:
    STORE_ID: 00000000000000000000000000000000
    CALLSTACK:
    C:\Users\Travis\workspace\Test\source\TestApp.mc (initialize:48)


    And Apps/LOGS/TEST.txt reads..

    toNumberWithBase() is not available


    I'm running good firmware on my fr630. Are you sure that you've tested this with other input strings?
  • In case you haven't already written it, the following code should convert from string to number and from number to string on ConnectIQ 1.2 platforms.

    const lower_digits = [
    "0", "1", "2", "3", "4",
    "5", "6", "7", "8", "9",
    "a", "b", "c", "d", "e",
    "f", "g", "h", "i", "j",
    "k", "l", "m", "n", "o",
    "p", "q", "r", "s", "t",
    "u", "v", "w", "x", "y",
    "z"
    ];

    const upper_digits = [
    "0", "1", "2", "3", "4",
    "5", "6", "7", "8", "9",
    "A", "B", "C", "D", "E",
    "F", "G", "H", "I", "J",
    "K", "L", "M", "N", "O",
    "P", "Q", "R", "D", "T",
    "U", "V", "W", "X", "Y",
    "Z"
    ];


    function _index_of_range(array, beg, end, object) {
    for (var i = beg; i < end; ++i) {
    if (object.equals(array)) {
    return i;
    }
    }
    return null;
    }

    using Toybox.Test;

    function _str_to_num(s, b) {
    Test.assert(b == 0 || 1 < b && b < 37);

    // detect the base given the string
    if (b == 0) {
    var x = s.substring(0, 1);
    if ("0".equals(x)) {
    x = s.substring(1, 2);
    if ("X".equals(x) || "x".equals(x)) {
    s = s.substring(2, s.length());
    b = 16;
    }
    else {
    s = s.substring(1, s.length());
    b = 8;
    }
    }
    }

    var n = 0;

    for (var i = 0, j = s.length(); i < j; ++i) {
    var x = s.substring(i, i + 1);

    var o = _index_of(upper_digits, 0, upper_digits.size(), x);
    if (o == null) {
    o = _index_of_range(lower_digits, 10, lower_digits.size(), x);
    }

    n = (n * b) + o;
    }

    return n;
    }

    function _num_to_str(n, b) {
    Test.assert(1 < b && b < 37);

    if (n == 0) {
    return lower_digits[0];
    }

    var s = "";

    while (n != 0) {
    s += lower_digits[n % b];
    n /= b;
    }

    var ss = "";
    for (var i = s.length(); 0 < i; --i) {
    ss += s.substring(i - 1, i);
    }
    s = ss;

    return s;
    }
    [/code]