0

I have a vector of unsigned char values. The data inside is keys and values in the format "key=value". Each pair is terminated by a '\0' character and the last pair is terminated by a double '/0'. A value can contain a "=" as well, so this delimiter shouldnt be a criteria for the pair, only the terminating '\0'

From this vector of single unsigned char I want to get a std::map<std::string, std::string> object. What would be an effective way to go through the vector and fill the map? Thanks in advance!

This code finds all pairs, but when printing them, my console seems to mess things up, so I suspect invalid characters... maybe it has to do with the fact that I'm using unsigned char?

unsigned char *env, *nxt;
std::string delimiter = "=";
std::string line;
std::map<string, string> myMap;

for (env = &myVector[0]; *env != '\0'; env = nxt + 1)
    {

        for (nxt = env; *nxt != '\0'; ++nxt)
        {

            if (nxt >= &myVector[myVector.size()])
            {
                printf("string not terminated\n");
                return -1;
            }
        }

        line = std::string(env, env + myVector.size());
        myMap.insert(std::pair<string, string>(
            line.substr(0, line.find(delimiter)),
            line.substr(line.find(delimiter) + 1, line.size())));

    }
1
  • Are you able to post some code instead of just describing it? Commented Jul 21, 2014 at 10:28

1 Answer 1

1

Since the key cannot contain the = sign, it's fairly easy:

  1. Split on (generate all positions of) zero characters.
  2. Split created entries on first =.
  3. Use the generated regions as key/value.

To make things clearer (than your double nested loops, ew), I'd use some reasonable data structure to mark the faux-strings in the buffer (if you want to avoid copying), such as pair<unsigned, unsigned>.

So, the signatures of the functions (which in this case tell more than their implementations, I suppose), could look like this:

using BufferRange = pair<unsigned, unsigned>;
using BufferEntry = pair<BufferRange, BufferRange>;

list<BufferRange> splitOnZeroes(Buffer const& b);
BufferEntry splitOnEquality(BufferRange const& br, Buffer const& b);
void addToMap(map<string, string>& m, BufferEntry const& p)

Those are fairly simplified; my code design OCD tells me that BufferRange could be a type carrying not only the numerical indices, but also the reference to the buffer itself. Changing that (if required) left as an exercise.

Sign up to request clarification or add additional context in comments.

1 Comment

Incidentally, this lends itself fairly naturally to functional programming. In a language with . composition, the final implementation could be written as map (addToMap . splitOnEquality . splitOnZeros) buffer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.