tzippy
tzippy

Reputation: 6638

Parse char vector to std::map<string, string>

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())));

    }

Upvotes: 0

Views: 277

Answers (1)

Bartek Banachewicz
Bartek Banachewicz

Reputation: 39380

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.

Upvotes: 1

Related Questions