mirror of https://github.com/tstack/lnav
[sqlite] Major improvements to the sqlite integration.
This is a checkpoint of the improvements to the sqlite integration. The data_parser stuff should be much better now and I've tried to improve other parts of the user experience as well.pull/69/head
parent
b04e6bfc78
commit
3128dc772c
@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Copyright (c) 2013, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file logfile_sub_source.hh
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
#include "strnatcmp.h"
|
||||
}
|
||||
|
||||
#define MAX_ADDR_LEN 128
|
||||
|
||||
static int strncmp2(int a_len, const char *a_str,
|
||||
int b_len, const char *b_str)
|
||||
{
|
||||
int retval = strncmp(a_str, b_str, std::min(a_len, b_len));
|
||||
|
||||
if (retval == 0) {
|
||||
if (a_len < b_len) {
|
||||
retval = -1;
|
||||
}
|
||||
else {
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int try_inet_pton(int p_len, const char *p, char *n)
|
||||
{
|
||||
static int family[] = { AF_INET6, AF_INET, AF_MAX };
|
||||
|
||||
char buf[MAX_ADDR_LEN];
|
||||
int retval = AF_MAX;
|
||||
|
||||
strncpy(buf, p, p_len);
|
||||
buf[p_len] = '\0';
|
||||
for (int lpc = 0; family[lpc] != AF_MAX; lpc++) {
|
||||
if (inet_pton(family[lpc], buf, n) == 1) {
|
||||
retval = family[lpc];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int convert_v6_to_v4(int family, char *n)
|
||||
{
|
||||
struct in6_addr *ia = (struct in6_addr *)n;
|
||||
|
||||
if (family == AF_INET6 &&
|
||||
(IN6_IS_ADDR_V4COMPAT(ia) ||
|
||||
IN6_IS_ADDR_V4MAPPED(ia))) {
|
||||
family = AF_INET;
|
||||
memmove(n, n + 12, sizeof(struct in_addr));
|
||||
}
|
||||
|
||||
return family;
|
||||
}
|
||||
|
||||
static
|
||||
int ipaddress(void *ptr,
|
||||
int a_len, const void *a_in,
|
||||
int b_len, const void *b_in)
|
||||
{
|
||||
char a_addr[sizeof(struct in6_addr)], b_addr[sizeof(struct in6_addr)];
|
||||
const char *a_str = (const char *)a_in, *b_str = (const char *)b_in;
|
||||
int a_family, b_family, retval;
|
||||
|
||||
if (a_len > MAX_ADDR_LEN || b_len > MAX_ADDR_LEN) {
|
||||
return strncmp2(a_len, a_str, b_len, b_str);
|
||||
}
|
||||
|
||||
a_family = try_inet_pton(a_len, a_str, a_addr);
|
||||
b_family = try_inet_pton(b_len, b_str, b_addr);
|
||||
|
||||
if (a_family == AF_MAX && b_family != AF_MAX) {
|
||||
retval = -1;
|
||||
}
|
||||
else if (a_family != AF_MAX && b_family == AF_MAX) {
|
||||
retval = 1;
|
||||
}
|
||||
else {
|
||||
a_family = convert_v6_to_v4(a_family, a_addr);
|
||||
b_family = convert_v6_to_v4(b_family, b_addr);
|
||||
if (a_family == b_family) {
|
||||
retval = memcmp(a_addr, b_addr,
|
||||
a_family == AF_INET ?
|
||||
sizeof(struct in_addr) :
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
else if (a_family == AF_INET) {
|
||||
retval = -1;
|
||||
}
|
||||
else {
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static
|
||||
int sql_strnatcmp(void *ptr,
|
||||
int a_len, const void *a_in,
|
||||
int b_len, const void *b_in)
|
||||
{
|
||||
return strnatcmp(a_len, (char *)a_in, b_len, (char *)b_in);
|
||||
}
|
||||
|
||||
static
|
||||
int sql_strnatcasecmp(void *ptr,
|
||||
int a_len, const void *a_in,
|
||||
int b_len, const void *b_in)
|
||||
{
|
||||
return strnatcasecmp(a_len, (char *)a_in, b_len, (char *)b_in);
|
||||
}
|
||||
|
||||
int register_collation_functions(sqlite3 *db)
|
||||
{
|
||||
sqlite3_create_collation(db, "ipaddress", SQLITE_UTF8, NULL, ipaddress);
|
||||
sqlite3_create_collation(db, "natural", SQLITE_UTF8, NULL, sql_strnatcmp);
|
||||
sqlite3_create_collation(db, "naturalnocase", SQLITE_UTF8, NULL, sql_strnatcasecmp);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2013, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file column_namer.hh
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
class column_namer {
|
||||
|
||||
public:
|
||||
column_namer() {
|
||||
this->cn_builtin_names.push_back("col");
|
||||
};
|
||||
|
||||
bool existing_name(const std::string &in_name) {
|
||||
if (find(this->cn_builtin_names.begin(),
|
||||
this->cn_builtin_names.end(),
|
||||
in_name) != this->cn_builtin_names.end()) {
|
||||
return true;
|
||||
}
|
||||
else if (find(this->cn_names.begin(),
|
||||
this->cn_names.end(),
|
||||
in_name) != this->cn_names.end()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
std::string add_column(const std::string &in_name) {
|
||||
std::string base_name = in_name, retval;
|
||||
size_t buf_size;
|
||||
char *buffer;
|
||||
int num = 0;
|
||||
|
||||
buf_size = in_name.length() + 64;
|
||||
buffer = (char *)alloca(buf_size);
|
||||
if (in_name == "") {
|
||||
base_name = "col";
|
||||
}
|
||||
|
||||
retval = base_name;
|
||||
while (this->existing_name(retval)) {
|
||||
snprintf(buffer, buf_size, "%s_%d", base_name.c_str(), num);
|
||||
retval = buffer;
|
||||
num += 1;
|
||||
}
|
||||
|
||||
this->cn_names.push_back(retval);
|
||||
|
||||
return retval;
|
||||
};
|
||||
|
||||
std::vector<std::string> cn_builtin_names;
|
||||
std::vector<std::string> cn_names;
|
||||
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright (c) 2013, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file nextwork-extension-functions.cc
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
static void sql_gethostbyname(sqlite3_context *context,
|
||||
int argc, sqlite3_value **argv)
|
||||
{
|
||||
char buffer[INET6_ADDRSTRLEN];
|
||||
const char *name_in;
|
||||
struct addrinfo *ai;
|
||||
void *addr_ptr;
|
||||
int rc;
|
||||
|
||||
assert(argc >= 1 && argc <= 2);
|
||||
|
||||
if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
|
||||
sqlite3_result_null(context);
|
||||
return;
|
||||
}
|
||||
|
||||
name_in = (const char *)sqlite3_value_text(argv[0]);
|
||||
while ((rc = getaddrinfo(name_in, NULL, NULL, &ai)) == EAI_AGAIN) {
|
||||
sqlite3_sleep(10);
|
||||
}
|
||||
if (rc != 0) {
|
||||
sqlite3_result_text(context, name_in, -1, SQLITE_TRANSIENT);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ai->ai_family) {
|
||||
case AF_INET:
|
||||
addr_ptr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr;
|
||||
break;
|
||||
case AF_INET6:
|
||||
addr_ptr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
|
||||
break;
|
||||
}
|
||||
|
||||
inet_ntop(ai->ai_family, addr_ptr, buffer, sizeof(buffer));
|
||||
|
||||
sqlite3_result_text(context, buffer, -1, SQLITE_TRANSIENT);
|
||||
|
||||
freeaddrinfo(ai);
|
||||
}
|
||||
|
||||
static void sql_gethostbyaddr(sqlite3_context *context,
|
||||
int argc, sqlite3_value **argv)
|
||||
{
|
||||
union {
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
} sa;
|
||||
const char *addr_str;
|
||||
char buffer[NI_MAXHOST];
|
||||
int family, socklen;
|
||||
char *addr_raw;
|
||||
int rc;
|
||||
|
||||
assert(argc == 1);
|
||||
|
||||
if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
|
||||
sqlite3_result_null(context);
|
||||
return;
|
||||
}
|
||||
|
||||
addr_str = (const char *)sqlite3_value_text(argv[0]);
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
if (strchr(addr_str, ':')) {
|
||||
family = AF_INET6;
|
||||
socklen = sizeof(struct sockaddr_in6);
|
||||
sa.sin6.sin6_family = family;
|
||||
addr_raw = (char *)&sa.sin6.sin6_addr;
|
||||
}
|
||||
else {
|
||||
family = AF_INET;
|
||||
socklen = sizeof(struct sockaddr_in);
|
||||
sa.sin.sin_family = family;
|
||||
addr_raw = (char *)&sa.sin.sin_addr;
|
||||
}
|
||||
|
||||
if (inet_pton(family, addr_str, addr_raw) != 1) {
|
||||
sqlite3_result_text(context, addr_str, -1, SQLITE_TRANSIENT);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((rc = getnameinfo((struct sockaddr *)&sa, socklen,
|
||||
buffer, sizeof(buffer), NULL, 0, 0)) == EAI_AGAIN) {
|
||||
sqlite3_sleep(10);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
sqlite3_result_text(context, addr_str, -1, SQLITE_TRANSIENT);
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_result_text(context, buffer, -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
int register_network_extension_functions(sqlite3 *db)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
char narg;
|
||||
uint8_t text_rep;
|
||||
void (*func)(sqlite3_context*,int,sqlite3_value**);
|
||||
} plain_funcs[] = {
|
||||
{ "gethostbyname", 1, SQLITE_UTF8, sql_gethostbyname },
|
||||
{ "gethostbyaddr", 1, SQLITE_UTF8, sql_gethostbyaddr },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int retval;
|
||||
|
||||
for (int lpc = 0; plain_funcs[lpc].name; lpc++) {
|
||||
retval = sqlite3_create_function(db,
|
||||
plain_funcs[lpc].name,
|
||||
plain_funcs[lpc].narg,
|
||||
plain_funcs[lpc].text_rep,
|
||||
NULL,
|
||||
plain_funcs[lpc].func,
|
||||
NULL,
|
||||
NULL);
|
||||
if (retval != SQLITE_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
/* -*- mode: c; c-file-style: "k&r" -*-
|
||||
|
||||
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
|
||||
Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
/* partial change history:
|
||||
*
|
||||
* 2004-10-10 mbp: Lift out character type dependencies into macros.
|
||||
*
|
||||
* Eric Sosman pointed out that ctype functions take a parameter whose
|
||||
* value must be that of an unsigned int, even on platforms that have
|
||||
* negative chars in their default char type.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "strnatcmp.h"
|
||||
|
||||
|
||||
/* These are defined as macros to make it easier to adapt this code to
|
||||
* different characters types or comparison functions. */
|
||||
static inline int
|
||||
nat_isdigit(nat_char a)
|
||||
{
|
||||
return isdigit((unsigned char) a);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
nat_isspace(nat_char a)
|
||||
{
|
||||
return isspace((unsigned char) a);
|
||||
}
|
||||
|
||||
|
||||
static inline nat_char
|
||||
nat_toupper(nat_char a)
|
||||
{
|
||||
return toupper((unsigned char) a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
compare_right(int a_len, nat_char const *a, int b_len, nat_char const *b)
|
||||
{
|
||||
int bias = 0;
|
||||
|
||||
/* The longest run of digits wins. That aside, the greatest
|
||||
value wins, but we can't know that it will until we've scanned
|
||||
both numbers to know that they have the same magnitude, so we
|
||||
remember it in BIAS. */
|
||||
for (;; a++, b++, a_len--, b_len--) {
|
||||
if (a_len == 0 && b_len == 0)
|
||||
return 0;
|
||||
if (a_len == 0)
|
||||
return -1;
|
||||
if (b_len == 0)
|
||||
return 1;
|
||||
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||
return bias;
|
||||
else if (!nat_isdigit(*a))
|
||||
return -1;
|
||||
else if (!nat_isdigit(*b))
|
||||
return +1;
|
||||
else if (*a < *b) {
|
||||
if (!bias)
|
||||
bias = -1;
|
||||
} else if (*a > *b) {
|
||||
if (!bias)
|
||||
bias = +1;
|
||||
} else if (!*a && !*b)
|
||||
return bias;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
compare_left(int a_len, nat_char const *a, int b_len, nat_char const *b)
|
||||
{
|
||||
/* Compare two left-aligned numbers: the first to have a
|
||||
different value wins. */
|
||||
for (;; a++, b++, a_len--, b_len--) {
|
||||
if (a_len == 0 && b_len == 0)
|
||||
return 0;
|
||||
if (a_len == 0)
|
||||
return -1;
|
||||
if (b_len == 0)
|
||||
return 1;
|
||||
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||
return 0;
|
||||
else if (!nat_isdigit(*a))
|
||||
return -1;
|
||||
else if (!nat_isdigit(*b))
|
||||
return +1;
|
||||
else if (*a < *b)
|
||||
return -1;
|
||||
else if (*a > *b)
|
||||
return +1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int strnatcmp0(int a_len, nat_char const *a,
|
||||
int b_len, nat_char const *b,
|
||||
int fold_case)
|
||||
{
|
||||
int ai, bi;
|
||||
nat_char ca, cb;
|
||||
int fractional, result;
|
||||
|
||||
assert(a && b);
|
||||
ai = bi = 0;
|
||||
while (1) {
|
||||
if (ai >= a_len)
|
||||
ca = 0;
|
||||
else
|
||||
ca = a[ai];
|
||||
if (bi >= b_len)
|
||||
cb = 0;
|
||||
else
|
||||
cb = b[bi];
|
||||
|
||||
/* skip over leading spaces or zeros */
|
||||
while (nat_isspace(ca)) {
|
||||
ai += 1;
|
||||
if (ai >= a_len)
|
||||
ca = 0;
|
||||
else
|
||||
ca = a[ai];
|
||||
}
|
||||
|
||||
while (nat_isspace(cb)) {
|
||||
bi += 1;
|
||||
if (bi >= b_len)
|
||||
cb = 0;
|
||||
else
|
||||
cb = b[bi];
|
||||
}
|
||||
|
||||
/* process run of digits */
|
||||
if (nat_isdigit(ca) && nat_isdigit(cb)) {
|
||||
fractional = (ca == '0' || cb == '0');
|
||||
|
||||
if (fractional) {
|
||||
if ((result = compare_left(a_len - ai, a+ai, b_len - bi, b+bi)) != 0)
|
||||
return result;
|
||||
} else {
|
||||
if ((result = compare_right(a_len - ai, a+ai, b_len - bi, b+bi)) != 0)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ca && !cb) {
|
||||
/* The strings compare the same. Perhaps the caller
|
||||
will want to call strcmp to break the tie. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fold_case) {
|
||||
ca = nat_toupper(ca);
|
||||
cb = nat_toupper(cb);
|
||||
}
|
||||
|
||||
if (ca < cb)
|
||||
return -1;
|
||||
else if (ca > cb)
|
||||
return +1;
|
||||
|
||||
++ai; ++bi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int strnatcmp(int a_len, nat_char const *a, int b_len, nat_char const *b) {
|
||||
return strnatcmp0(a_len, a, b_len, b, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Compare, recognizing numeric string and ignoring case. */
|
||||
int strnatcasecmp(int a_len, nat_char const *a, int b_len, nat_char const *b) {
|
||||
return strnatcmp0(a_len, a, b_len, b, 1);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/* -*- mode: c; c-file-style: "k&r" -*-
|
||||
|
||||
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
|
||||
Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
/* CUSTOMIZATION SECTION
|
||||
*
|
||||
* You can change this typedef, but must then also change the inline
|
||||
* functions in strnatcmp.c */
|
||||
typedef char nat_char;
|
||||
|
||||
int strnatcmp(int a_len, nat_char const *a, int b_len, nat_char const *b);
|
||||
int strnatcasecmp(int a_len, nat_char const *a, int b_len, nat_char const *b);
|
@ -1,17 +1,14 @@
|
||||
a=1 b=2 c=3,4
|
||||
key 8:9 ^
|
||||
sep 9:10 ^
|
||||
num 10:11 ^
|
||||
num 12:13 ^
|
||||
row 10:13 ^-^
|
||||
pair 8:13 ^---^
|
||||
key 4:5 ^
|
||||
sep 5:6 ^
|
||||
num 6:7 ^
|
||||
row 6:7 ^
|
||||
pair 4:7 ^-^
|
||||
key 0:1 ^
|
||||
sep 1:2 ^
|
||||
num 2:3 ^
|
||||
row 2:3 ^
|
||||
pair 0:3 ^-^
|
||||
key 0:1 ^ a
|
||||
num 2:3 ^ 1
|
||||
val 2:3 ^ 1
|
||||
pair 0:3 ^-^ a=1
|
||||
key 4:5 ^ b
|
||||
num 6:7 ^ 2
|
||||
val 6:7 ^ 2
|
||||
pair 4:7 ^-^ b=2
|
||||
key 8:9 ^ c
|
||||
num 10:11 ^ 3
|
||||
num 12:13 ^ 4
|
||||
val 10:13 ^-^ 3,4
|
||||
pair 8:13 ^---^ c=3,4
|
||||
|
@ -1,7 +1,7 @@
|
||||
current speed: 38 mph
|
||||
key 0:13 ^-----------^
|
||||
sep 13:14 ^
|
||||
num 15:17 ^^
|
||||
word 18:21 ^-^
|
||||
row 15:21 ^----^
|
||||
pair 0:17 ^---------------^
|
||||
key 0:0
|
||||
key 0:13 ^-----------^ current speed
|
||||
pair 0:13 ^-----------^ current speed
|
||||
key 15:15 ^
|
||||
num 15:17 ^^ 38
|
||||
pair 15:17 ^^ 38
|
||||
|
@ -1,9 +1,16 @@
|
||||
1,2,3,4,five,six,7
|
||||
num 0:1 ^
|
||||
num 2:3 ^
|
||||
num 4:5 ^
|
||||
num 6:7 ^
|
||||
word 8:12 ^--^
|
||||
word 13:16 ^-^
|
||||
num 17:18 ^
|
||||
row 0:18 ^----------------^
|
||||
key 0:0
|
||||
num 0:1 ^ 1
|
||||
pair 0:1 ^ 1
|
||||
key 2:2 ^
|
||||
num 2:3 ^ 2
|
||||
pair 2:3 ^ 2
|
||||
key 4:4 ^
|
||||
num 4:5 ^ 3
|
||||
pair 4:5 ^ 3
|
||||
key 6:6 ^
|
||||
num 6:7 ^ 4
|
||||
pair 6:7 ^ 4
|
||||
key 17:17 ^
|
||||
num 17:18 ^ 7
|
||||
pair 17:18 ^ 7
|
||||
|
@ -1,9 +1,16 @@
|
||||
1 2 3 4 five six 7
|
||||
num 0:1 ^
|
||||
num 2:3 ^
|
||||
num 4:5 ^
|
||||
num 6:7 ^
|
||||
word 8:12 ^--^
|
||||
word 13:16 ^-^
|
||||
num 17:18 ^
|
||||
row 0:18 ^----------------^
|
||||
key 0:0
|
||||
num 0:1 ^ 1
|
||||
pair 0:1 ^ 1
|
||||
key 2:2 ^
|
||||
num 2:3 ^ 2
|
||||
pair 2:3 ^ 2
|
||||
key 4:4 ^
|
||||
num 4:5 ^ 3
|
||||
pair 4:5 ^ 3
|
||||
key 6:6 ^
|
||||
num 6:7 ^ 4
|
||||
pair 6:7 ^ 4
|
||||
key 17:17 ^
|
||||
num 17:18 ^ 7
|
||||
pair 17:18 ^ 7
|
||||
|
@ -1,6 +1,5 @@
|
||||
the-value: "Hello, World!"
|
||||
key 0:9 ^-------^
|
||||
sep 9:10 ^
|
||||
quot 12:25 ^-----------^
|
||||
row 12:25 ^-----------^
|
||||
pair 0:25 ^-----------------------^
|
||||
key 0:9 ^-------^ the-value
|
||||
quot 12:25 ^-----------^ Hello, World!
|
||||
val 12:25 ^-----------^ Hello, World!
|
||||
pair 0:25 ^-----------------------^ the-value: "Hello, World!
|
||||
|
@ -1,6 +1,5 @@
|
||||
this is a url: http://www.example.com/foo-bar
|
||||
key 0:13 ^-----------^
|
||||
sep 13:14 ^
|
||||
url 15:45 ^----------------------------^
|
||||
row 15:45 ^----------------------------^
|
||||
pair 0:45 ^-------------------------------------------^
|
||||
key 0:13 ^-----------^ this is a url
|
||||
url 15:45 ^----------------------------^ http://www.example.com/foo-bar
|
||||
val 15:45 ^----------------------------^ http://www.example.com/foo-bar
|
||||
pair 0:45 ^-------------------------------------------^ this is a url: http://www.example.com/foo-bar
|
||||
|
@ -1,11 +1,9 @@
|
||||
qualified:name: foo=1 bar=2
|
||||
key 22:25 ^-^
|
||||
sep 25:26 ^
|
||||
num 26:27 ^
|
||||
row 26:27 ^
|
||||
pair 22:27 ^---^
|
||||
key 16:19 ^-^
|
||||
sep 19:20 ^
|
||||
num 20:21 ^
|
||||
row 20:21 ^
|
||||
pair 16:21 ^---^
|
||||
key 16:19 ^-^ foo
|
||||
num 20:21 ^ 1
|
||||
val 20:21 ^ 1
|
||||
pair 16:21 ^---^ foo=1
|
||||
key 22:25 ^-^ bar
|
||||
num 26:27 ^ 2
|
||||
val 26:27 ^ 2
|
||||
pair 22:27 ^---^ bar=2
|
||||
|
@ -0,0 +1,12 @@
|
||||
func(arg1="a", arg2="b")
|
||||
key 5:5 ^
|
||||
key 5:9 ^--^ arg1
|
||||
quot 11:12 ^ a
|
||||
val 11:12 ^ a
|
||||
pair 5:12 ^-----^ arg1="a
|
||||
key 15:19 ^--^ arg2
|
||||
quot 21:22 ^ b
|
||||
val 21:22 ^ b
|
||||
pair 15:22 ^-----^ arg2="b
|
||||
grp 5:22 ^---------------^ arg1="a", arg2="b
|
||||
pair 5:22 ^---------------^ arg1="a", arg2="b
|
@ -0,0 +1,31 @@
|
||||
Succeeded authorizing right 'system.privilege.taskport.debug' by client '/usr/libexec/taskgated' [76339] for authorization created by '/usr/libexec/taskgated' [77395] (100003,1)
|
||||
key 29:29 ^
|
||||
quot 29:60 ^-----------------------------^ system.privilege.taskport.debug
|
||||
pair 29:60 ^-----------------------------^ system.privilege.taskport.debug
|
||||
key 73:73 ^
|
||||
quot 73:95 ^--------------------^ /usr/libexec/taskgated
|
||||
pair 73:95 ^--------------------^ /usr/libexec/taskgated
|
||||
key 98:98 ^
|
||||
key 98:98 ^
|
||||
num 98:103 ^---^ 76339
|
||||
pair 98:103 ^---^ 76339
|
||||
grp 98:103 ^---^ 76339
|
||||
pair 98:103 ^---^ 76339
|
||||
key 135:135 ^
|
||||
quot 135:157 ^--------------------^ /usr/libexec/taskgated
|
||||
pair 135:157 ^--------------------^ /usr/libexec/taskgated
|
||||
key 160:160 ^
|
||||
key 160:160 ^
|
||||
num 160:165 ^---^ 77395
|
||||
pair 160:165 ^---^ 77395
|
||||
grp 160:165 ^---^ 77395
|
||||
pair 160:165 ^---^ 77395
|
||||
key 168:168 ^
|
||||
key 168:168 ^
|
||||
num 168:174 ^----^ 100003
|
||||
pair 168:174 ^----^ 100003
|
||||
key 175:175 ^
|
||||
num 175:176 ^ 1
|
||||
pair 175:176 ^ 1
|
||||
grp 168:176 ^------^ 100003,1
|
||||
pair 168:176 ^------^ 100003,1
|
@ -1,32 +1,20 @@
|
||||
Nov 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
|
||||
key 106:113 ^-----^
|
||||
sep 113:114 ^
|
||||
path 114:127 ^-----------^
|
||||
path 128:145 ^---------------^
|
||||
row 114:145 ^-----------------------------^
|
||||
pair 106:127 ^-------------------^
|
||||
key 94:98 ^--^
|
||||
sep 98:99 ^
|
||||
word 99:103 ^--^
|
||||
row 99:103 ^--^
|
||||
pair 94:103 ^-------^
|
||||
key 54:57 ^-^
|
||||
sep 57:58 ^
|
||||
path 58:91 ^-------------------------------^
|
||||
row 58:91 ^-------------------------------^
|
||||
pair 54:91 ^-----------------------------------^
|
||||
key 42:45 ^-^
|
||||
sep 45:46 ^
|
||||
word 46:49 ^-^
|
||||
path 49:51 ^^
|
||||
row 46:51 ^---^
|
||||
pair 42:51 ^-------^
|
||||
key 16:29 ^-----------^
|
||||
sep 29:30 ^
|
||||
word 31:39 ^------^
|
||||
row 31:39 ^------^
|
||||
pair 16:39 ^---------------------^
|
||||
word 0:3 ^-^
|
||||
num 5:6 ^
|
||||
time 7:15 ^------^
|
||||
date 0:15 ^-------------^
|
||||
timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages
|
||||
key 11:14 ^-^ TTY
|
||||
sym 15:18 ^-^ pts
|
||||
num 19:20 ^ 6
|
||||
val 15:20 ^---^ pts/6
|
||||
pair 11:20 ^-------^ TTY=pts/6
|
||||
key 23:26 ^-^ PWD
|
||||
path 27:60 ^-------------------------------^ /auto/wstimstack/rpms/lbuild/test
|
||||
val 27:60 ^-------------------------------^ /auto/wstimstack/rpms/lbuild/test
|
||||
pair 23:60 ^-----------------------------------^ PWD=/auto/wstimstack/rpms/lbuild/test
|
||||
key 63:67 ^--^ USER
|
||||
word 68:72 ^--^ root
|
||||
val 68:72 ^--^ root
|
||||
pair 63:72 ^-------^ USER=root
|
||||
key 75:82 ^-----^ COMMAND
|
||||
path 83:96 ^-----------^ /usr/bin/tail
|
||||
wspc 96:97 ^
|
||||
path 97:114 ^---------------^ /var/log/messages
|
||||
val 83:114 ^-----------------------------^ /usr/bin/tail /var/log/messages
|
||||
pair 75:114 ^-------------------------------------^ COMMAND=/usr/bin/tail /var/log/messages
|
||||
|
@ -1,33 +1,21 @@
|
||||
Jun 18 16:13:52 Tim-Stacks-iMac Safari[81045]: INSERT-HANG-DETECTED: Tx time:3.093364, # of Inserts: 89, # of bytes written: 465365, Did shrink: NO
|
||||
key 137:143 ^----^
|
||||
sep 143:144 ^
|
||||
word 145:147 ^^
|
||||
row 145:147 ^^
|
||||
pair 137:147 ^--------^
|
||||
key 107:123 ^--------------^
|
||||
sep 123:124 ^
|
||||
num 125:131 ^----^
|
||||
word 133:136 ^-^
|
||||
row 125:136 ^---------^
|
||||
pair 107:136 ^---------------------------^
|
||||
key 89:99 ^--------^
|
||||
sep 99:100 ^
|
||||
num 101:103 ^^
|
||||
word 105:106 ^
|
||||
row 101:106 ^---^
|
||||
pair 89:106 ^---------------^
|
||||
key 72:76 ^--^
|
||||
sep 76:77 ^
|
||||
num 77:85 ^------^
|
||||
word 87:88 ^
|
||||
row 77:88 ^---------^
|
||||
pair 72:88 ^--------------^
|
||||
key 47:67 ^------------------^
|
||||
sep 67:68 ^
|
||||
word 69:71 ^^
|
||||
row 69:71 ^^
|
||||
pair 47:71 ^----------------------^
|
||||
word 0:3 ^-^
|
||||
num 4:6 ^^
|
||||
time 7:15 ^------^
|
||||
date 0:15 ^-------------^
|
||||
INSERT-HANG-DETECTED: Tx time:3.093364, # of Inserts: 89, # of bytes written: 465365, Did shrink: NO
|
||||
key 0:20 ^------------------^ INSERT-HANG-DETECTED
|
||||
word 22:24 ^^ Tx
|
||||
val 22:24 ^^ Tx
|
||||
pair 0:24 ^----------------------^ INSERT-HANG-DETECTED: Tx
|
||||
key 25:29 ^--^ time
|
||||
num 30:38 ^------^ 3.093364
|
||||
val 30:38 ^------^ 3.093364
|
||||
pair 25:38 ^-----------^ time:3.093364
|
||||
key 40:52 ^----------^ # of Inserts
|
||||
num 54:56 ^^ 89
|
||||
val 54:56 ^^ 89
|
||||
pair 40:56 ^--------------^ # of Inserts: 89
|
||||
key 58:76 ^----------------^ # of bytes written
|
||||
num 78:84 ^----^ 465365
|
||||
val 78:84 ^----^ 465365
|
||||
pair 58:84 ^------------------------^ # of bytes written: 465365
|
||||
key 86:96 ^--------^ Did shrink
|
||||
sym 98:100 ^^ NO
|
||||
val 98:100 ^^ NO
|
||||
pair 86:100 ^------------^ Did shrink: NO
|
||||
|
Loading…
Reference in New Issue