Pascal to C string conversion algorithm needed

G

Guilbert STABILO

Hi everybody,

I am working on a C projet where I am receiving a Pascal string (the first
char contains the length of the string).
I need to convert this into a null terminated string (C string).
The conversion seems very simple to me but because the routine will be used
by hundred (and even more) of users, I do not want to badly reinvent
something which was already well done.

On Apple computers, there was a function called p2cstr() which was doing
this.
I searched but did not find the equivalent in the C runtime library.
Moreover, I did not find the source code of p2cstr() (which is what I am
looking for).

* Could anybody send me a link or give me the robust Pascal to C string
conversion algorithm ?

Thanks in advance for your help.
 
U

user923005

Hi everybody,

I am working on a C projet where I am receiving a Pascal string (the first
char contains the length of the string).
I need to convert this into a null terminated string (C string).
The conversion seems very simple to me but because the routine will be used
by hundred (and even more) of users, I do not want to badly reinvent
something which was already well done.

On Apple computers, there was a function called p2cstr() which was doing
this.
I searched but did not find the equivalent in the C runtime library.
Moreover, I did not find the source code of p2cstr() (which is what I am
looking for).

* Could anybody send me a link or give me the robust Pascal to C string
conversion algorithm ?

Untested, and off the top of my head in zero seconds, typed in without
even thinking it over carefully:

#include <string.h>
#include <stdlib.h>

char *cstring_from_pascal_string(unsigned char *pascal_string)
{
char *cstring = malloc((size_t)pascal_string[0] + 1);
if (cstring)
{
memcpy(cstring, pascal_string+1, (size_t)pascal_string[0]);
cstring[pascal_string[0]] = 0;
}
return cstring;
}

I guess with a little work, you can fashion this into something
worthwhile.

You could also do the conversion in place, but that will destroy the
original input.
 
N

Nate Eldredge

Guilbert STABILO said:
Hi everybody,

I am working on a C projet where I am receiving a Pascal string (the first
char contains the length of the string).
I need to convert this into a null terminated string (C string).
The conversion seems very simple to me but because the routine will be used
by hundred (and even more) of users, I do not want to badly reinvent
something which was already well done.

A Pascal string could legitimately contain a null byte. What do you
want to do in that case?
 
K

Kaz Kylheku

Hi everybody,

I am working on a C projet where I am receiving a Pascal string (the first
char contains the length of the string).
I need to convert this into a null terminated string (C string).
The conversion seems very simple to me but because the routine will be used
by hundred (and even more) of users, I do not want to badly reinvent
something which was already well done.

The expected wide use of this routine is an important non-functional
requirement, which influences the design. It means that you can't necessarily
just hack up something that works in the one situation you are faced with at
the moment. It's possible that no single function will fit everyone's needs,
due to the flexibilities in C memory management.

For instance, not everyone will want to use a conversion routine that
dynamically allocates the string and requires freeing.

And sometimes the user may even want to work with the Pascal string without the
overhead of converting it to a C string!

Also, what if a reverse conversion is required too, from a C string to a Pascal
string? If a Pascal string can come into your function, who is to say that
there won't be a requirement for a Pascal string to come out of a function.

It may be best to define a small library for manipulating these ``Pascal''
strings which gives the users some flexibilities:

/* length of Pacal string */
size_t pstrlen(const char *pstr);

/* compare Pascal string to C string, similarly to strcmp */
int pstrcmp(const char *pstr, const char *cstr);

/* duplicate Pascal string as C string; memory is allocated as if
by malloc */
char *pstrdup(const char *pstr);

/* copy Pascal string to buffer, ensuring null termination in
all cases; returns the length of the original: pstrlen(psrc) */
size_t pstrlcpy(char *cdst, const char *psrc, size_t size);

/* copy C string to buffer, truncating if necessary, ensuring the buffer is a
Pascal string. Returns strlen(csrc). */
size_t cstrlcpy(char *pdst, const char *csrc, size_t size);

You should circulate a proposed API among some representatives from the
intended user base. Designing the API is more important than the trivial
details of how it works. A bad API can give programmers headaches, and lead
them into making mistakes. Even if nothing else is wrong, maybe the above
names for the functions are poor.

As an example, if the pstrdup function is acceptable to the users, it can be
written like this:

#include <stdlib.h>

char *pstrdup(const char *pstr)
{
size_t len = pstr[0];
char *cstr = malloc(len + 1);
if (cstr != 0) {
memcpy(cstr, pstr + 1, len);
cstr[len] = 0;
}
return cstr;
}
 
B

Ben Bacarisse

As an example, if the pstrdup function is acceptable to the users, it can be
written like this:

#include <stdlib.h>

char *pstrdup(const char *pstr)
{
size_t len = pstr[0];
char *cstr = malloc(len + 1);

Watch out for signed char. This will go boom.
if (cstr != 0) {
memcpy(cstr, pstr + 1, len);
cstr[len] = 0;
}
return cstr;
}
 
K

Kaz Kylheku

As an example, if the pstrdup function is acceptable to the users, it can be
written like this:

#include <stdlib.h>

char *pstrdup(const char *pstr)
{
size_t len = pstr[0];
char *cstr = malloc(len + 1);

Watch out for signed char. This will go boom.

Excellent point; we need something like:

size_t len = *(unsigned char *) pstr;

Even such a simple thing can be screwed up.
 
C

CBFalconer

Guilbert said:
I am working on a C projet where I am receiving a Pascal string
(the first char contains the length of the string). I need to
convert this into a null terminated string (C string). The
conversion seems very simple to me but because the routine will
be used by hundred (and even more) of users, I do not want to
badly reinvent something which was already well done.

On Apple computers, there was a function called p2cstr() which
was doing this. I searched but did not find the equivalent in
the C runtime library. Moreover, I did not find the source code
of p2cstr() (which is what I am looking for).

Pascal does not define strings, except as fixed length arrays of
char. What you are converting is an extension, provided by your
Pascal system. Such an extension may include lengths of the
string, max string length handled, and the string itself. The
lengths may be bytes, shorts, integers, longs. So you have to look
the format up.

If the string has room to simply add a '\0' char, conversion is
simple. Do so, and take the address of the first string char as
the address of the C string. Add that '\0' after the final string
char, not after the max string length. A fundamental Pascal string
(the fixed length array I mentioned above) has unused characters on
the end of string replaced by blanks.

Otherwise copy the char array into a C char array, add the '\0',
and you are done. Takes more room that way.

If the string includes a '\0' char in its data, it is not
compatible.
 
Q

qarnos

Guilbert said:
* Could anybody send me a link or give me the robust Pascal to C string
conversion algorithm ?

Thanks in advance for your help.

I'm not sure what your definition of "robust" is but if I were to do
it, I'd probably try something like this:

Note: code written quickly, not tested. If it contains any bugs,
consider them features.

----- BEGIN CODE -----

#include <assert.h> /* for assert */
#include <stddef.h> /* for size_t */

/**
* converts a pascal string to a c-style string. any NULL characters
* encountered in the pascal string will be replaced with <nullchar>.
*
* if the buffer is not large enough to copy the whole string, only
* the first portion of the string is copied. the terminating NULL
* will still be inserted, unless the buffer size was zero.
*
* if <buffer> is not NULL, returns the number of characters copied,
* including the terminating NULL.
*
* if <buffer> is NULL, returns the required size of the buffer,
* including the terminating NULL.
*/
size_t pstr_to_cstr(
unsigned char * pstr, /*!< pointer to pascal-style string */
int nullchar, /*!< character to substitute for NULLs */
char * buffer, /*!< buffer to receive c-style string */
size_t count /*!< size of the buffer, in characters */
)
{
int i;

/* pstr and nullchar must not be NULL */
assert(pstr && nullchar);

/* if no buffer, return chars required including NULL */
if (!buffer) return (size_t)pstr[0] + 1;

/* if count is zero, we cant copy anything */
if (!count) return 0;

/* get number of chars to copy, not including NULL */
if (--count > (size_t)pstr[0]) count = pstr[0];

/* copy the string */
for (i = count; i--; ) *buffer++ = (*++pstr) ? (char)*pstr :
nullchar;

/* add terminating NULL */
*buffer = 0;

/* return (count + 1) for size including terminating NULL */
return count + 1;
}

----- END CODE -----
 
P

Phil Carmody

Guilbert STABILO said:
Hi everybody,

I am working on a C projet where I am receiving a Pascal string (the first
char contains the length of the string).

There's no way in C to receive a Pascal string. You can receive a
reference to the string, via a pointer to either its first element
or a suitably-defined variable-length struct, but you cannot receive
the Pascal string itself.
I need to convert this into a null terminated string (C string).
The conversion seems very simple to me but because the routine will be used
by hundred (and even more) of users, I do not want to badly reinvent
something which was already well done.

On Apple computers, there was a function called p2cstr() which was doing
this.
I searched but did not find the equivalent in the C runtime library.
Moreover, I did not find the source code of p2cstr() (which is what I am
looking for).

* Could anybody send me a link or give me the robust Pascal to C string
conversion algorithm ?

Not until you tell us the actual interface requirements, rather than
just something fluffy. I can think of at least two completely different
implementations which could each be considered completely right or
completely wrong, depending on your view of memory management.

Phil
 
G

Guilbert STABILO

I'm not sure what your definition of "robust" is but if I were to do
it, I'd probably try something like this:

Thanks to all for your posts.
I did a mix with all the information you gave and I have now a working
algorithm.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top