Shop OBEX P1 Docs P2 Docs Learn Events
Newbie question - string buffers — Parallax Forums

Newbie question - string buffers

ramman345ramman345 Posts: 24
edited 2008-06-01 21:28 in Propeller 1
Hey guys, I'm making a transition from the Javelin and I'm curious about the best way to do string buffers on the Propeller. The manual says to use the DAT block to define buffers but I'm just not sure on the exact syntax to declare a string buffer, then to append to the buffer. Also, anybody got a good "indexOf" string search?

Josh

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2008-05-29 04:33
    A string is just a byte array on the Propeller where the string normally has a zero termination byte (which you have to supply).

    To append to an existing string in the array "X", you'd first find the current length of the string using STRSIZE(@X), then copy the new string to the end of the existing one like:

    L := STRSIZE(@X) ' Get length of existing piece
    N := STRSIZE(@Y) ' Get length of new piece
    BYTEMOVE(@X+L,@Y,N+1) ' Copy new piece plus its terminator

    Note that I've included no checking for too long a result string.
  • ramman345ramman345 Posts: 24
    edited 2008-05-29 14:13
    Thanks a lot Mike, this clears things up.

    One more question, how do you append a constant string to that? Suppose you want to append "World" to string X.

    Josh
  • Mike GreenMike Green Posts: 23,101
    edited 2008-05-29 14:48
    Since you would know the length of the new piece, you could write

    BYTEMOVE(@X+STRSIZE(@X),STRING("World"),6)
  • ramman345ramman345 Posts: 24
    edited 2008-05-29 19:24
    Mike, thanks so much for your help so far. I've decided to implement these functions in a StringBuffer object in order to easily replicate them throughout my program. Can you tell me if the following code looks correct to you:

    VAR

    byte buffer[noparse][[/noparse]buffer_size]
    byte base_buffer[noparse][[/noparse]buffer_size]
    byte cmp_buffer[noparse][[/noparse]buffer_size]

    CON

    buffer_size = 32

    PUB clear | index
    repeat index from 0 to buffer_size-1
    buffer[noparse][[/noparse]index] := 0

    PUB append(strptr) : Success
    if strsize(strptr) > buffer_size 'Supplied string is too big for buffer
    return -1

    if strsize(strptr) > (buffer_size - strsize(@buffer)) 'Not enough room in the buffer for string
    return -1

    bytemove(@buffer+strsize(@buffer), @strptr, strsize(@strptr) + 1)

    return 1

    PUB toUpper(strptr) | index 'Convert each character to uppercase ASCII
    repeat index from 0 to strsize(@strptr) - 1
    if strptr[noparse][[/noparse]index] != 0
    strptr[noparse][[/noparse]index] -= 32

    PUB indexOf(strptr) : strindex | index
    bytemove(@base_buffer, @buffer, strsize(@buffer) + 1)
    bytemove(@cmp_buffer, @strptr, strsize(strptr) + 1)

    toUpper(base_buffer)
    toUpper(cmp_buffer)

    strindex := -1 'Init strindex to -1 for failed search

    repeat index from 0 to strsize(@base_buffer) 'Slide cmp_buffer through base_buffer
    if strcomp(@basebuffer + index, @cmp_buffer)
    strindex := index 'Store the current index
    return strindex

    return strindex

    Post Edited (ramman345) : 5/29/2008 7:48:27 PM GMT
  • Mike GreenMike Green Posts: 23,101
    edited 2008-05-29 19:39
    For the "clear" method, you only need to set the first byte to zero. You don't need to clear the whole array.

    For the "append" method, you don't need to test separately for the size of the string to be added. Just a test for the total length of the result is enough. Also, it would help to compute the current length of the buffer string only once and save it in a local variable. Similarly, compute the length of the new piece only once and save it in a local variable. It might be useful to return the total length of the result (or -1 if an error occurs). Note that strptr is already a pointer. You'd have:
    PUB clear
       buffer[noparse][[/noparse]0]~
    
    PUB append(strptr) | old, new
       old := strsize(@buffer)
       new := strsize(strptr)
       if (result := old + new) => buffer_size
          return -1
       bytemove(@buffer+old, strptr, new+1)
    
    PUB address
       result := @buffer
    

    Post Edited (Mike Green) : 5/29/2008 7:44:15 PM GMT
  • ramman345ramman345 Posts: 24
    edited 2008-05-29 19:49
    Thanks Mike, guess I was just covering my bases by clearing every element. Care to advise on these two (and too):

    PUB toUpper(strptr) | index 'Convert each character to uppercase ASCII
    repeat index from 0 to strsize(@strptr) - 1
    if strptr[noparse][[/noparse]index] != 0
    strptr[noparse][[/noparse]index] -= 32

    PUB indexOf(strptr) : strindex | index
    bytemove(@base_buffer, @buffer, strsize(@buffer) + 1)
    bytemove(@cmp_buffer, @strptr, strsize(strptr) + 1)

    toUpper(base_buffer)
    toUpper(cmp_buffer)

    strindex := -1 'Init strindex to -1 for failed search

    repeat index from 0 to strsize(@base_buffer) 'Slide cmp_buffer through base_buffer
    if strcomp(@basebuffer + index, @cmp_buffer)
    strindex := index 'Store the current index
    return strindex

    return strindex
  • Mike GreenMike Green Posts: 23,101
    edited 2008-05-29 20:19
    First of all, it looks like you're using C operators and this is Spin and they're different. Try
    PUB toUpper(strptr) | t
    repeat while t := byte[noparse][[/noparse]strptr++]
       if t =< "a" and t => "z"
          byte[noparse][[/noparse]strptr-1] -= 32
    


    For the "indexOf" method, you want to check first to see if a match is possible based on length.
  • ramman345ramman345 Posts: 24
    edited 2008-05-29 20:33
    Ok but I'm not sure which operators you are referring to as C, and I have a question about your function. Going through your version:

    PUB toUpper(strptr) | t
    repeat while t := byte[noparse][[/noparse]strptr++] <- cast whatever's at strptr++ as a byte and assign to t
    if t =< "a" and t => "z" <- make sure t is a character between a-z ** I was missing this condition
    byte[noparse][[/noparse]strptr-1] -= 32 <- strptr was already incremented above so we need the previous element

    How does it get out of the loop?
  • ramman345ramman345 Posts: 24
    edited 2008-05-29 21:48
    Ok, so I see that != is not equal in C and it should be <> in Spin. But I'm still not sure how the loop exits, wouldn't it keep going through memory?

    Josh
  • Jimmy W.Jimmy W. Posts: 112
    edited 2008-05-31 03:33
    ramman345 said...


    How does it get out of the loop?

    ramman345 said...

    repeat while t := byte[noparse][[/noparse]strptr++]
    as long as the condition evaluates to not zero it will be true so:
    strings end with a zero terminator so when it hits the end it stops
  • ramman345ramman345 Posts: 24
    edited 2008-06-01 21:28
    And the light slowly flickers on...

    Thanks so much Jimmy!

    Josh
Sign In or Register to comment.