void add_user(osmium::ChangesetComment& comment, const char* user, const size_t length) { if (length > osmium::max_osm_string_length) { throw std::length_error("OSM user name is too long"); } comment.set_user_size(osmium::string_size_type(length) + 1); add_size(append(user, osmium::memory::item_size_type(length)) + append_zero()); }
/** * Add role to buffer. * * @param member Relation member object where the length of the role * will be set. * @param role The role. * @param length Length of role (without \0 termination). * @throws std:length_error If role is longer than osmium::max_osm_string_length */ void add_role(osmium::RelationMember& member, const char* role, const size_t length) { if (length > osmium::max_osm_string_length) { throw std::length_error("OSM relation member role is too long"); } member.set_role_size(osmium::string_size_type(length) + 1); add_size(append(role, osmium::memory::item_size_type(length)) + append_zero()); add_padding(true); }
TEST_F(BufferTest, append_empty) { const char * data = "test_string"; EXPECT_EQ(strlen(data), append_string(data)); EXPECT_EQ((size_t)1, append_zero()); EXPECT_EQ(strlen(data) + 1, mem_buffer_size(&m_buffer)); EXPECT_STREQ(data, as_string()); }
TEST_F(BufferTest, append_multi_trunk) { EXPECT_TRUE(append_trunk("a")); EXPECT_TRUE(append_trunk("b")); EXPECT_TRUE(append_trunk("c")); append_zero(); EXPECT_EQ((size_t)4, mem_buffer_size(&m_buffer)); EXPECT_STREQ("abc", as_string()); }
TEST_F(BufferTest, pos_insert_in_empty) { struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 3); EXPECT_EQ(3, mem_pos_insert(&p, "abc", 3)); EXPECT_FALSE(mem_pos_valide(&p)); append_zero(); EXPECT_STREQ("abc", as_string()); }
TEST_F(BufferTest, pos_insert_zero) { append_trunk("def"); struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 0); EXPECT_EQ(0, mem_pos_insert(&p, "", 0)); EXPECT_EQ('d', mem_pos_data(&p)); append_zero(); EXPECT_STREQ("def", as_string()); }
TEST_F(BufferTest, pos_insert_at_trunk_last) { append_trunk("def"); struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 3); EXPECT_EQ(3, mem_pos_insert(&p, "abc", 3)); EXPECT_FALSE(mem_pos_valide(&p)); append_zero(); EXPECT_STREQ("defabc", as_string()); }
TEST_F(BufferTest, pos_insert_at_trunk_middle) { append_trunk("def"); struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 1); EXPECT_EQ(3, mem_pos_insert(&p, "abc", 3)); EXPECT_EQ('e', mem_pos_data(&p)); append_zero(); EXPECT_STREQ("dabcef", as_string()); }
void add_text(osmium::ChangesetComment& comment, const char* text, const size_t length) { // XXX There is no limit on the length of a comment text. We // limit it here to 2^16-2 characters, because that's all that // will fit into our internal data structure. This is not ideal, // and will have to be discussed and cleared up. if (length > std::numeric_limits<osmium::string_size_type>::max() - 1) { throw std::length_error("OSM changeset comment is too long"); } comment.set_text_size(osmium::string_size_type(length) + 1); add_size(append(text, osmium::memory::item_size_type(length)) + append_zero()); add_padding(true); }
TEST_F(BufferTest, pos_insert_at_trunk_first) { append_trunk("def"); struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 0); EXPECT_EQ(3, mem_pos_insert(&p, "abc", 3)); EXPECT_EQ((size_t)6, buffer_size()); EXPECT_EQ('d', mem_pos_data(&p)); append_zero(); EXPECT_STREQ("abcdef", as_string()); }
TEST_F(BufferTest, pos_insert_enouth_in_current_middle) { append_trunk("a"); append_trunk("bc"); append_trunk("d"); struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 2); EXPECT_EQ(1, mem_pos_insert(&p, "efg", 1)); EXPECT_EQ('c', mem_pos_data(&p)); append_zero(); EXPECT_STREQ("abecd", as_string()); }
TEST_F(BufferTest, pos_insert_multi_trunk_at_trunk_last) { append_trunk("a"); append_trunk("bc"); append_trunk("d"); struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 3); EXPECT_EQ(3, mem_pos_insert(&p, "efg", 3)); EXPECT_EQ('d', mem_pos_data(&p)); append_zero(); EXPECT_STREQ("abcefgd", as_string()); }
TEST_F(BufferTest, pos_insert_not_use_empty_trunk) { append_trunk("a"); append_trunk("bc"); append_trunk(NULL); append_trunk("d"); struct mem_buffer_pos p; mem_pos_at(&p, &m_buffer, 3); EXPECT_EQ(3, mem_pos_insert(&p, "efg", 3)); EXPECT_EQ((size_t)5, trunk_count()); EXPECT_EQ('d', mem_pos_data(&p)); append_zero(); EXPECT_STREQ("abcefgd", as_string()); }
/** * Add tag to buffer. * * @param key Pointer to tag key. * @param key_length Length of key (not including the \0 byte). * @param value Pointer to tag value. * @param value_length Length of value (not including the \0 byte). */ void add_tag(const char* key, const size_t key_length, const char* value, const size_t value_length) { if (key_length > osmium::max_osm_string_length) { throw std::length_error("OSM tag key is too long"); } if (value_length > osmium::max_osm_string_length) { throw std::length_error("OSM tag value is too long"); } add_size(append(key, osmium::memory::item_size_type(key_length)) + append_zero() + append(value, osmium::memory::item_size_type(value_length)) + append_zero()); }
//Reads a C string starting at s until quoteChar is found or e is reached // Returns the pointer to the terminating quote character or e if none was found char *read_cstring(array_char *out, const char *s, const char *e, char quoteChar, tok_message_queue *mq) { const char * const tokstart = s; const char *p; int has_endquote=0, has_newlines=0; //tok_msg_debug(called, s, "Called read_cstring on `%s`", s); #define append(startptr,endptr) array_append_items(*out, startptr, (endptr)-(startptr)) #define append_char(theChar) array_append(*out, theChar) #define append_zero() do {array_append(*out, 0); out->size--;} while(0) p = s; while (p<e) { char c = *p++; if (c == '\\') { append(s, p-1); s = p; if (p >= e) { append_char('\\'); tok_msg_error(ended_in_backslash, p-1, "read_cstring input ended in backslash"); break; } c = *p++; if (c>='0' && c<='9') { unsigned int octal = c-'0'; size_t digit_count = 0; while (p<e && *p>='0' && *p<='9') { octal <<= 3; octal += (*p++) - '0'; if (++digit_count >= 2) break; } if (p<e && *p>='0' && *p<='9') { tok_msg_info(ambiguous_octal, s-2, "Octal followed by digit"); } if (octal > 0xFF) { tok_msg_warn(octal_overflow, s-2, "Octal out of range"); } c = octal; } else { switch (c) { case 'x': { size_t digit_count = 0; size_t zero_count = 0; unsigned int hex = 0; while (p<e && *p=='0') p++, zero_count++; for (;p<e;digit_count++) { c = *p++; if (c>='0' && c<='9') c -= '0'; else if (c>='A' && c<='F') c -= 'A'-10; else if (c>='a' && c<='f') c -= 'a'-10; else { p--; break; } hex <<= 4; hex += c; } if (zero_count+digit_count > 2) { char *hex_string = strdup_rng(s-2, p); tok_msg_warn(ambiguous_hex, s-2, "Hex escape '%s' is ambiguous", hex_string); if (digit_count > 2) tok_msg_warn(hex_overflow, s-2, "Hex escape '%s' out of range", hex_string); free(hex_string); } c = hex & 0xFF; } break; case 'a': c=0x7; break; case 'b': c=0x8; break; case 'e': c=0x1B; break; case 'f': c=0xC; break; case 'n': c=0xA; break; case 'r': c=0xD; break; case 't': c=0x9; break; case 'v': c=0xB; break; case '\\': break; default: if (c == quoteChar) break; if (c=='\'' && quoteChar=='"') { /* tok_msg_info(escaped_single_quote, s-2, "Single quote characters need not be escaped within double quotes"); */ break; } if (c=='"' && quoteChar=='\'') { /* tok_msg_info(escaped_double_quote, s-2, "Double quote characters need not be escaped within single quotes"); */ break; } if (c=='?') // \? is needed in some situations to avoid building a trigraph break; tok_msg_warn(unknown_escape, s-2, "Unknown escape sequence '\\%c'", c); break; } } s = p; append_char(c); } else if (c == quoteChar) { p--; has_endquote = 1; break; } else if (creturn(c)) { has_newlines = 1; } } append(s, p); append_zero(); if (!has_endquote) { tok_msg_error(missing_endquote, tokstart, "Missing endquote on %s literal", quoteChar=='\'' ? "character" : "string"); } else if (has_newlines) { tok_msg_warn(quote_newlines, tokstart, "%s literal contains newline character(s)", quoteChar=='\'' ? "Character" : "String"); } return (char*)p; #undef append #undef append_char #undef append_zero }
/** * Add user name to buffer. * * @param user Pointer to user name. * @param length Length of user name (without \0 termination). */ void add_user(const char* user, const string_size_type length) { object().set_user_size(length + 1); add_size(append(user, length) + append_zero()); add_padding(true); }