Agile Tortoise

Greg Pierce’s blog

« PyCon down the street      Ajaxload »

Dynamics AX (Axapta) String class

I’ve posted a utility String class I wrote years ago for Axapta. I’ve also compiled and used it in Dynamics AX v4. It extends the rather limited built-in string functions with a number of other common string manipulations and comparisons like “endsWith”, “replace”, “split”, etc.

Friday, January 12th, 2007 at 9:21 pm and is filed under Dynamics AX. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

5 Responses to “Dynamics AX (Axapta) String class”

  1. chrisroth Says:
    July 6th, 2007 at 10:14 am

    Hi Greg, love the String class and have subscribed to your RSS.

    It’s really helped with something I was doing.

    I reckon there’s a bug or 2 (depending on your understanding of strscan) in the replaceAll method:

    pos = strscan( s, findStr, pos + strlen( replStr ), strlen( s ) );
    - 3rd arg. Shouldn’t this be pos + strlen(findStr) otherwise if replStr is longer than findStr and findStr occurs close together we’ll skip over the 2nd quick occurrence.
    - 4th arg should be strlen(s) - (pos + strlen(replStr)) ?

    Anyhoo, I was using this on a mega string (150,000 char long result from an xsl transform) with lots of occurrences of the findStr in it and it was pretty darned slow. Caching the strlens in replaceAll saved about 10% but that was still quite slow.

    There’s probably all sorts of reasons why the following shouldn’t be used but according to the profiler it’s about 40% quicker:

    static str replaceAllTest2( str s, str findStr, str replStr)
    {
    int findStrLen = strlen(findStr);
    int sLen = strlen(s);
    int pos = strscan(s, findStr, 1, sLen);

    str opStr = “”;
    int lastPos = 1;
    ;

    while(pos > 0)
    {
    opStr += substr(s, lastPos, pos - lastPos);
    opStr += replStr;
    lastPos = pos + findStrLen;

    pos = strscan(s, findStr, lastPos, sLen - lastPos);
    }
    if (lastPos != sLen)
    {
    opStr += substr(s, lastPos, sLen - lastPos);
    }

    return opStr;
    }

    It’d be interesting to write a C# version and try that out for speed but deadlines threaten :(

    Cheers

    Chris Rothery

  2. greg Says:
    July 9th, 2007 at 9:09 pm

    Hey, Chris, thanks for the comments. I’d imagine any of these would be pretty slow on a large string. I made on efforts to optimize — and, frankly, X++ isn’t a real smoker.

    I’ll take a look at the bugs. I think I may have made some changes since the version that’s up here — I probably need to update. If you’re on AX v4, you should look at using .NET directly from X++. You’re manipulations will be a lot quicker.

    Of course, I also am wondering why you’re doing string manipulation on the results of an XSL transform — maybe you should look at tweaking your stylesheet to get the results you want?

    greg.

  3. chrisroth Says:
    July 10th, 2007 at 4:24 am

    Thanks for the reply Greg.

    I might be using a rocket launcher to kill a gnat but the reason I’ve ended up doing what I’m doing is to interface with a legacy system that has a fixed file format (feel free to skip to the bottom juicy bit now).

    I’m using AX 4.0 and have written some classes to extend AIF file system adapter so that once the xml file pops out, we can transform that xml into the specific format (AIF pipeline xsl transforms were causing trouble with needing to remain xml in format and match schemas etc).

    That’s all working but the specific format we’re generating has tags with in it. To get my xsl file to import into the repository we had to use < etc to stop it complaining that our xsl file was rubbish. That meant that those replacements came out in the final file rather than etc.

    In the cold light of day, I agreed with you that I should try and sort the xsl but try as I might I couldn’t so I went back to processing the string result of the transform before writing it.

    Long story short it’s now working beautifully (and ridiculously quickly!) using .Net directly (something I am only just getting into and was scared of but am going go persue now I’ve seen these results):

    /*
    replace the all occurances of “findStr” with “replStr” in “s”
    */
    static str replaceAllTest3( str s, str findStr, str replStr)
    {
    // BP Deviation Documented
    System.Text.StringBuilder sb = new System.Text.StringBuilder(s);
    ;

    sb.Replace(findStr, replStr);
    return sb.ToString();
    }

    According to the Dynamics profiler, the original replaceAll clocked about 3 million ‘ticks’. I got that down by about 40% but the Test3 above clocks in at a mere 33,000 ticks!!!

    Amazed, happy, you name it, I’m experiencing the emotion right now :)

    Thanks for your help and keep up the good work

    Chris

  4. chrisroth Says:
    July 10th, 2007 at 5:15 am

    Oh and…

    I’m 99% sure I was being a moron on my 1st comment re the 3rd arg to the strscan line and it should be ‘pos + strlen(replStr)’.

    :)

  5. webmotion Says:
    June 23rd, 2008 at 6:09 am

    Thanks a whole lot for the classes, Greg! :-) You’ve just spared me a bunch of time. Thanks again. Greets from Hungary :)

Leave a Reply