Collection of VBScript string functions for classic ASP

By | November 20

I’ve just thought of extracting another class of my framework called StringOperations and publish it on here for free use because I think there are some useful things in it which you need for everyday work. Beside that it includes some functions which are also available in the .net framework. So whenever you have to deal with classic ASP again and you want to have a more powerful base for your work then this is a must.

Just download the class and have a quick look at the StringOperations documentation (Links at the bottom of the article). I recommend you to load this class somewhere that it will be always available and you don’t have to care about its presence. Also a name like “str” sounds good and makes your code more readable now. I’ve stapled together some short examples of the most important methods of the class, all others should be self explaining…

writeln(), wirte(), end(): I use them instead of response.write and response.end. It makes my code nicer and less to write. Furthermore I am on the safe side when I want to change the output method in the future (e.g. some StringBuilder)

format(): is the almost equivalent to the string.format() of .net. The idea of such a method is brilliant and I needed it somehow for classic ASP. As there is no way of optional parameters (e.g. params in C#) I decided to use an array for the simulation of optional params. Example of usage:

  1. str.write(str.format("my name is {0} and i am {1} years old.", array("Michal", "25")))

shorten(): hey I need this everywhere and in every project. I wonder why its not incorporated into any base framework such as .net. (or maybe I havent found it yet). This short functions helps me to shorten strings everywhere I dont want long ones. e.g. News summaries, long titles, etc. It expects the maximum length and the string which will be used to indicate the “overflow”. Example, which will shorten a string to 10 chars if necessary:

  1. longText = "i am a very long thing, like a banana"
  2. str.write(str.shorten(longText, 10, "..."))

endsWith(), startsWith(), clone(), trimStart(), trimEnd(), arrayToString(), toCharArray(), padLeft(), padRight: all just classic ASP equivalents to the .net bros.

trimComplete(): this is a nice trim function which removes all non-printable characters from the end and the beginning of the string. You know sometimes there are weird characters which we dont see and they are still here and cause problems when working with the strings.

defuseHTML(): hey guys I love this name. i have to patent it every string you pass into it will be defused of being HTML. this is usefull especially when you want to display some HTML within an application.

ensureSlash(): oh this one is very useful when you deal a lot with virtual paths (luckily within a web application you do) and want to be sure that there is a slash at the end. so lets say you have some config var which holds some path and you build the filename with this path then you could use this method to ensure that there is a slash even if the user havent entered one. Example:

  1. f = str.ensureSlash("/someParent/child", "image.gif")
  2. 'f will hold "/someParent/child/image.gif" after the call.

URL(): as an URL is some kind of a special string it fits in here to build an URL with this given function. It makes the code nicer and the parameters are automatically URLEncoded. Example use for a redirect:

  1. response.redirect(str.URL("letsgo.asp", array("id", 10), empty))

toInt(), toFloat(): those both take a string as a parameter and convert it into a numeric value (integer/float). If the conversion is not possible an alternative value is passed through. Very nice to use for e.g. Query string parameters or other user input fields. Example which tries to parse an ID parameter from the querystring as a number. If it cannot be parsed then 0 is passed through (with this youre always sure to deal with a number):

  1. ID = str.toInt(request.queryString("id"), 0)

captialize(): last but not least another useful function which is very common in a lot of apps out there. It converts the first char of each word found in a string to upper case. Useful for names of persons.

There are some more in the class which are very useful. This class has been used for years now and so there should not be any bugs (or at least not known yet ). Feel free to suggest some other useful stuff which could fit in here so I could expand it. Have fun. Here are the downloads:

Download: StringOperations

NOTE: StringOperations class is part of the ajaxed library now!
check ajaxed library for a newer version…

17 comments on “Collection of VBScript string functions for classic ASP

  1. i’m inspired by your approach to classic ASP. I’m forced to use it daily at work. I’d love to get my hands on your entire framework. I can only imagine how amazing it is!

  2. its really a bit hard to find any new and amazing resources of classic ASP since microsoft release .NET. but you save my time michal thanks.

  3. Wow what an excellent set of Functions!
    Helped me out drastically!
    I only code in classic asp so really finding this was 1 in a million!
    Thanks Michal!

  4. Where is the lib.iif function ? could not find it. All in all, great codes.


  5. is it used within the string functions? you can easily extract it from the ajaxed library which can be found at there is a library class which holds this method

  6. I do love the classics.

  7. glitch in stringOperations.asp
    public function JSEncode(byVal val)
    val = val & “”
    tmp = replace(val, chr(39), “’”) ‘it should be here
    tmp = replace(tmp, chr(92), “\”)
    ‘tmp = replace(val, chr(39), “’”) the order is not correct
    tmp = replace(tmp, chr(34), “””)
    tmp = replace(tmp, chr(13), “”)
    tmp = replace(tmp, chr(10), ” “)
    JSEncode = tmp
    end function

    better follow the XHTML way to use “hidden” instead of “Hidden” in
    public function getHiddenInput(name, value)

  8. Your Format method does not support the following: Format(“{0}{1}”, array(“{1}”, “{0}”)). Output should be “{1}{0}” but will be “{0}{0}”.

  9. craig thats right .. thx for pointing this out… do u have an idea how to solve this nicely? thx for any comments

  10. It’s not pretty, but I’ve come to terms with ASP code never looking pretty ;). I concat Left(…) with the Replace return because the Replace function truncates the string to the left of start.

    1. public function StringFormat(str, args())
    2.    if not IsArray(args) then
    3.       StringFormat = str
    4.       exit function
    5.    end if
    7.    if ubound(args) = -1 then
    8.       StringFormat = str
    9.       exit function
    10.    end if
    12.    dim regex : set regex = new RegExp
    13.    regex.Pattern = "{d+}"
    14.    regex.Global = true
    16.    dim match, i, shift
    17.    shift = 1
    19.    for each match in regex.Execute(str)
    20.       i = CInt(Mid(match.Value, 2, Len(match.Value) - 2))
    21.       str = Left(str, match.FirstIndex + shift - 1) & Replace(str, match.Value, args(i), match.FirstIndex + shift, 1, 0)
    22.       shift = shift + Len(args(i)) - Len(match.Value)
    23.    next
    24.    StringFormat = str
    25. end function
  11. thx craig … i am just a bit concerned about performance because this function is used very often in a lot of apps and the change compared to the previous one is dramatic.
    i am just doing some brainstorming if there would be maybe other solutions as well .. you know some function like this is called a lot.

    i was thinking of something like:
    1. looping through all given placeholders
    2. replacing its occurencies and surrounding it with some special char. the special char would prevent the repeated replacement (if regex is done correctly)
    3. remove all the special chars.

    havent tried yet if it would work .. what do you think? if yes, what char could we use?

  12. Ok, but it’s premature optimization without data, so here is some:

    It’s a csv, so you can download and import into Excel/Calc/whatever.

    I already identified the most expensive operation, creating the RegExp object. After moving the RegExp out of the method scope and into a global, the new method actually performs better in most cases, and the same in one case.

    Here’s the performance code:

    Both of the pastebins will last a month.

    I’m not sure if I understand the special character wrapping solution. Perhaps an example would help?

  13. Eh, forget about the previous data (lies, damn lies, and statistics). I had a bug in the performance code where the test string was modified making the tests run faster. Here is the new code:

    In hindsite, the tests only showed that the methods both perform linearly on the same length of args array and same number of replacements. I’ve varied the number of the replacements in the new code.

    I found that both methods performed linearly based on the number of replacements made. The average time (on my development box) per a replacement was 0.0015 ms for the original method and 0.0362 ms for the new method. Since this it was O(n) and the difference is a fraction of a millisecond, I’ve decided to run with it for our code base ;)

  14. thanks craig for your samples and your ideas … this made me playing around today for some time :)
    yeah the regex object creation takes the most time .. but i discovered that the main problem with your approach is that its execution lasts longer when the placeholders are used more than once in a string. example:

    1. format("{0}{1}{0}{0}", array(1, 2))

    first i have tried the approach i mentioned to you .. which resulted in this:

    1. public function format3(byVal str, byVal args)
    2.     if not isArray(args) then args = array(args)
    3.     set rx = new RegExp
    4.     for i = 0 to uBound(args)
    5.         rx.pattern = "([^_]|^){" & i & "}([^_]|$)"
    6. = true
    7.         str = rx.replace(str, "$1_" & args(i) & "_$2")
    8.     next
    9.     format3 = replace(str, "_", "")
    10. end function

    problem was that it looks shorter but takes even longer :))) however this approach led me to my final solution which seems the best i guess.. its also almost the same speed as the original one.

    1. function format(byVal str, byVal values)
    2.     escapeChar = asc(24) & asc(27)
    3.     if instr(str, escapeChar) > 0 then
    4.         response.write("unsupported char found in input string")
    5.         response.end()
    6.     end if
    7.     if not isArray(values) then values = array(values)
    8.     for i = 0 to ubound(values)
    9.         val = cStr(values(i))
    10.         if instr(val, escapeChar) > 0 then
    11.             response.write("unsupported char found in argument")
    12.             response.end()
    13.         end if
    14.         val = replace(val, "{", escapeChar)
    15.         str = replace(str, "{" & i & "}", val)
    16.     next
    17.     format = replace(str, escapeChar, "{")
    18. end function

    the only little odd on this is that in theory the string could contain a sequence of chars which is used internally for escaping. this results in an error then .. but the chance is very very low .. take a look at the code.
    Thanks for your inspiration craig and your time! the updated version can be found in the ajaxed SVN as this file here is not maintained.

    btw the code i ran for my benchmarks is the following:

    1. values = array( _
    2.         "{0}{1}{2}{3}{4}{5}{6}{7}{8}{0}{1}{2}{3}{4}{5}{6}{7}{8}", _
    3.         "asdasdasda{0}asdasd{1}asdasda{2}asdasda{3}adsad{4}adsad{5}adsad{6}asdad{7}asdad{8}asdasdda", _
    4.         "{0}{1}{2}{3}asdasd{4}{5}{7}{8}adasda{0}{1}{2}{3}asdasd{4}{5}{7}{8}" _
    5.     )
    6.     s = timer()
    7.     for each v in values
    8.         for i = 0 to 1000
    9.             x = str.format(v, array("a", "b", "c", "d", "e", "f", "g", "h", "j"))
    10.         next
    11.     next
    12.     str.write("new: " & timer() - s)

    last but not least: the new function also supports a non-array as argument as well. This is useful if you only need one argument to replace.

  15. Very neat, indeed. Both of my websites are in classic ASP so some of these may definitely come in handy.

  16. Pingback: cheap christian louboutin shoes

  17. Pingback: jordan retro 13