void test_strnpbrk() { char str[] = "ahoj"; CU_ASSERT(strnpbrk(str, 4, "a") == (str + 0)); CU_ASSERT(strnpbrk(str, 4, "h") == (str + 1)); CU_ASSERT(strnpbrk(str, 4, "b") == NULL); CU_ASSERT(strnpbrk(str, 1, "h") == NULL); CU_ASSERT(strnpbrk(str, 4, "xo") == (str + 2)); }
/** * Find command termination character * @param cmd - input command * @param len - max search length * @return position of terminator or len */ size_t cmdTerminatorPos(const char * cmd, size_t len) { const char * terminator = strnpbrk(cmd, len, "; \r\n\t"); if (terminator == NULL) { return len; } else { return terminator - cmd; } }
/** * Find pattern separator position * @param pattern * @param len - max search length * @return position of separator or len */ size_t patternSeparatorPos(const char * pattern, size_t len) { char * separator = strnpbrk(pattern, len, "?:[]"); if (separator == NULL) { return len; } else { return separator - pattern; } }
/** * Find command separator position * @param cmd - input command * @param len - max search length * @return position of separator or len */ size_t cmdSeparatorPos(const char * cmd, size_t len) { char * separator = strnpbrk(cmd, len, ":?"); size_t result; if (separator == NULL) { result = len; } else { result = separator - cmd; } return result; }
/** * Write string withn " to the result * @param context * @param data * @return */ size_t SCPI_ResultText(scpi_t * context, const char * data) { size_t result = 0; size_t len = strlen(data); const char * quote; result += writeDelimiter(context); result += writeData(context, "\"", 1); while ((quote = strnpbrk(data, len, "\""))) { result += writeData(context, data, quote - data + 1); result += writeData(context, "\"", 1); len -= quote - data + 1; data = quote + 1; } result += writeData(context, data, len); result += writeData(context, "\"", 1); context->output_count++; return result; }
void UrlParser::parse() { // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] const char *urlEnd = m_url + m_urlLen; const char *currentPos = m_url; // hier-part = "//" authority path-abempty // / path-absolute // / path-rootless // / path-empty const char *authorityPos = static_cast<const char*>( memmem( currentPos, urlEnd - currentPos, "//", 2 ) ); if ( authorityPos != NULL ) { if ( authorityPos != currentPos ) { m_scheme = currentPos; m_schemeLen = authorityPos - currentPos - 1; } m_authority = authorityPos + 2; currentPos = m_authority; } else { m_authority = currentPos; } const char *pathPos = static_cast<const char*>( memchr( currentPos, '/', urlEnd - currentPos ) ); if ( pathPos != NULL ) { m_authorityLen = pathPos - m_authority; currentPos = pathPos + 1; } else { m_authorityLen = urlEnd - m_authority; // nothing else to process return; } // @todo similar logic in Url.cpp ( merge this ) // authority = [ userinfo "@" ] host [ ":" port ] const char *userInfoPos = static_cast<const char *>( memchr( m_authority, '@', m_authorityLen ) ); if ( userInfoPos != NULL ) { m_host = userInfoPos + 1; m_hostLen = m_authorityLen - ( userInfoPos - m_authority ) - 1; } else { m_host = m_authority; m_hostLen = m_authorityLen; } const char *portPos = static_cast<const char *>( memrchr( m_host, ':', m_hostLen ) ); if ( portPos != NULL ) { m_hostLen -= ( m_hostLen - ( portPos - m_host ) ); } // host = IP-literal / IPv4address / reg-name /// @todo ALC we should remove the const cast once we fix all the const issue int32_t ip = atoip( m_host, m_hostLen ); if ( ip ) { int32_t domainLen = 0; m_domain = getDomainOfIp ( const_cast<char *>( m_host ), m_hostLen , &domainLen ); m_domainLen = domainLen; } else { const char *tldPos = ::getTLD( const_cast<char *>( m_host ), m_hostLen ); if ( tldPos ) { size_t tldLen = m_host + m_hostLen - tldPos; if ( tldLen < m_hostLen ) { m_domain = static_cast<const char *>( memrchr( m_host, '.', m_hostLen - tldLen - 1 ) ); if ( m_domain ) { m_domain += 1; m_domainLen = m_hostLen - ( m_domain - m_host ); } else { m_domain = m_host; m_domainLen = m_hostLen; } } } } const char *queryPos = static_cast<const char*>( memchr( currentPos, '?', urlEnd - currentPos ) ); if ( queryPos != NULL ) { currentPos = queryPos + 1; } const char *anchorPos = static_cast<const char*>( memrchr( currentPos, '#', urlEnd - currentPos ) ); // if ( anchorPos != NULL ) { // currentPos = anchorPos + 1; // } const char *pathEnd = queryPos ? queryPos : (anchorPos ? anchorPos : urlEnd); m_pathEndChar = *( pathEnd - 1 ); const char *queryEnd = anchorPos ? anchorPos : urlEnd; // path const char *prevPos = pathPos + 1; while ( prevPos && ( prevPos <= pathEnd ) ) { size_t len = pathEnd - prevPos; currentPos = strnpbrk( prevPos, len, "/;&" ); if ( currentPos ) { len = currentPos - prevPos; } UrlComponent urlPart = UrlComponent( UrlComponent::TYPE_PATH, prevPos, len, *( prevPos - 1 ) ); m_paths.push_back( urlPart ); prevPos = currentPos ? currentPos + 1 : NULL; } // query if ( queryPos ) { prevPos = queryPos + 1; bool isPrevAmpersand = false; while ( prevPos && ( prevPos < queryEnd ) ) { size_t len = queryEnd - prevPos; currentPos = strnpbrk( prevPos, len, "&;" ); if ( currentPos ) { len = currentPos - prevPos; } UrlComponent urlPart = UrlComponent( UrlComponent::TYPE_QUERY, prevPos, len, *( prevPos - 1 ) ); std::string key = urlPart.getKey(); // check previous urlPart if ( isPrevAmpersand ) { urlPart.setSeparator( '&' ); } bool isAmpersand = ( !urlPart.hasValue() && urlPart.getKey() == "amp" ); if ( !key.empty() && !isAmpersand ) { // we don't cater for case sensitive query parameter (eg: parm, Parm, PARM is assumed to be the same) auto it = m_queriesMap.find( key ); if (it == m_queriesMap.end()) { m_queries.push_back( urlPart ); m_queriesMap[key] = m_queries.size() - 1; } else { m_queries[it->second] = urlPart; } } prevPos = currentPos ? currentPos + 1 : NULL; isPrevAmpersand = isAmpersand; } } }
int textfile_foreach(const char *pathname, textfile_cb func, void *data) { struct stat st; char *map, *off, *end, *key, *value; off_t size; size_t len; int fd, err = 0; fd = open(pathname, O_RDONLY); if (fd < 0) return -errno; if (flock(fd, LOCK_SH) < 0) { err = -errno; goto close; } if (fstat(fd, &st) < 0) { err = -errno; goto unlock; } size = st.st_size; map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (!map || map == MAP_FAILED) { err = -errno; goto unlock; } off = map; while (size - (off - map) > 0) { end = strnpbrk(off, size - (off - map), " "); if (!end) { err = -EILSEQ; break; } len = end - off; key = malloc(len + 1); if (!key) { err = -errno; break; } memset(key, 0, len + 1); memcpy(key, off, len); off = end + 1; if (size - (off - map) < 0) { err = -EILSEQ; free(key); break; } end = strnpbrk(off, size - (off - map), "\r\n"); if (!end) { err = -EILSEQ; free(key); break; } len = end - off; value = malloc(len + 1); if (!value) { err = -errno; free(key); break; } memset(value, 0, len + 1); memcpy(value, off, len); func(key, value, data); free(key); free(value); off = end + 1; } munmap(map, size); unlock: flock(fd, LOCK_UN); close: close(fd); errno = -err; return 0; }
static char *read_key(const char *pathname, const char *key, int icase) { struct stat st; char *map, *off, *end, *str = NULL; off_t size; size_t len; int fd, err = 0; fd = open(pathname, O_RDONLY); if (fd < 0) return NULL; if (flock(fd, LOCK_SH) < 0) { err = -errno; goto close; } if (fstat(fd, &st) < 0) { err = -errno; goto unlock; } size = st.st_size; map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (!map || map == MAP_FAILED) { err = -errno; goto unlock; } len = strlen(key); off = find_key(map, size, key, len, icase); if (!off) { err = -EILSEQ; goto unmap; } end = strnpbrk(off, size - (map - off), "\r\n"); if (!end) { err = -EILSEQ; goto unmap; } str = malloc(end - off - len); if (!str) { err = -EILSEQ; goto unmap; } memset(str, 0, end - off - len); strncpy(str, off + len + 1, end - off - len - 1); unmap: munmap(map, size); unlock: flock(fd, LOCK_UN); close: close(fd); errno = -err; return str; }
static int write_key(const char *pathname, const char *key, const char *value, int icase) { struct stat st; char *map, *off, *end, *str; off_t size; size_t base; int fd, len, err = 0; fd = open(pathname, O_RDWR); if (fd < 0) return -errno; if (flock(fd, LOCK_EX) < 0) { err = -errno; goto close; } if (fstat(fd, &st) < 0) { err = -errno; goto unlock; } size = st.st_size; if (!size) { if (value) { lseek(fd, size, SEEK_SET); err = write_key_value(fd, key, value); } goto unlock; } map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_LOCKED, fd, 0); if (!map || map == MAP_FAILED) { err = -errno; goto unlock; } len = strlen(key); off = find_key(map, size, key, len, icase); if (!off) { munmap(map, size); if (value) { lseek(fd, size, SEEK_SET); err = write_key_value(fd, key, value); } goto unlock; } base = off - map; end = strnpbrk(off, size, "\r\n"); if (!end) { err = -EILSEQ; goto unmap; } if (value && ((ssize_t) strlen(value) == end - off - len - 1) && !strncmp(off + len + 1, value, end - off - len - 1)) goto unmap; len = strspn(end, "\r\n"); end += len; len = size - (end - map); if (!len) { munmap(map, size); if (ftruncate(fd, base) < 0) { err = -errno; goto unlock; } lseek(fd, base, SEEK_SET); if (value) err = write_key_value(fd, key, value); goto unlock; } if (len < 0 || len > size) { err = -EILSEQ; goto unmap; } str = malloc(len); if (!str) { err = -errno; goto unmap; } memcpy(str, end, len); munmap(map, size); if (ftruncate(fd, base) < 0) { err = -errno; free(str); goto unlock; } lseek(fd, base, SEEK_SET); if (value) err = write_key_value(fd, key, value); if (write(fd, str, len) < 0) err = -errno; free(str); goto unlock; unmap: munmap(map, size); unlock: flock(fd, LOCK_UN); close: fdatasync(fd); close(fd); errno = -err; return err; }
static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { if (value == NULL) return ""; // Not sure how to handle unicode... if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && !containsControlCharacter0(value, length)) return JSONCPP_STRING("\"") + value + "\""; // We have to walk value and escape any special characters. // Appending to JSONCPP_STRING is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL JSONCPP_STRING result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; char const* end = value + length; for (const char* c = value; c != end; ++c) { switch (*c) { case '\"': result += "\\\""; break; case '\\': result += "\\\\"; break; case '\b': result += "\\b"; break; case '\f': result += "\\f"; break; case '\n': result += "\\n"; break; case '\r': result += "\\r"; break; case '\t': result += "\\t"; break; // case '/': // Even though \/ is considered a legal escape in JSON, a bare // slash is also legal, so I see no reason to escape it. // (I hope I am not misunderstanding something.) // blep notes: actually escaping \/ may be useful in javascript to avoid </ // sequence. // Should add a flag to allow this compatibility mode and prevent this // sequence from occurring. default: if ((isControlCharacter(*c)) || (*c == 0)) { JSONCPP_OSTRINGSTREAM oss; oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c); result += oss.str(); } else { result += *c; } break; } } result += "\""; return result; }
/** * Find command line separator * @param cmd - input command * @param len - max search length * @return pointer to line separator or NULL */ const char * cmdlineSeparator(const char * cmd, size_t len) { return strnpbrk(cmd, len, ";\r\n"); }
/** * Find command line terminator * @param cmd - input command * @param len - max search length * @return pointer to command line terminator or NULL */ const char * cmdlineTerminator(const char * cmd, size_t len) { return strnpbrk(cmd, len, "\r\n"); }