forked from git-for-windows/git
-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prepare `scalar` to use the GVFS protocol instead of partial clone (required to support Azure Repos). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
- Loading branch information
Showing
10 changed files
with
888 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
#include "cache.h" | ||
#include "json-parser.h" | ||
|
||
static int reset_iterator(struct json_iterator *it) | ||
{ | ||
it->p = it->begin = it->json; | ||
strbuf_release(&it->key); | ||
strbuf_release(&it->string_value); | ||
it->type = JSON_NULL; | ||
return -1; | ||
} | ||
|
||
static int parse_json_string(struct json_iterator *it, struct strbuf *out) | ||
{ | ||
const char *begin = it->p; | ||
|
||
if (*(it->p)++ != '"') | ||
return error("expected double quote: '%.*s'", 5, begin), | ||
reset_iterator(it); | ||
|
||
strbuf_reset(&it->string_value); | ||
#define APPEND(c) strbuf_addch(out, c) | ||
while (*it->p != '"') { | ||
switch (*it->p) { | ||
case '\0': | ||
return error("incomplete string: '%s'", begin), | ||
reset_iterator(it); | ||
case '\\': | ||
it->p++; | ||
if (*it->p == '\\' || *it->p == '"') | ||
APPEND(*it->p); | ||
else if (*it->p == 'b') | ||
APPEND(8); | ||
else if (*it->p == 't') | ||
APPEND(9); | ||
else if (*it->p == 'n') | ||
APPEND(10); | ||
else if (*it->p == 'f') | ||
APPEND(12); | ||
else if (*it->p == 'r') | ||
APPEND(13); | ||
else if (*it->p == 'u') { | ||
unsigned char binary[2]; | ||
int i; | ||
|
||
if (hex_to_bytes(binary, it->p + 1, 2) < 0) | ||
return error("invalid: '%.*s'", | ||
6, it->p - 1), | ||
reset_iterator(it); | ||
it->p += 4; | ||
|
||
i = (binary[0] << 8) | binary[1]; | ||
if (i < 0x80) | ||
APPEND(i); | ||
else if (i < 0x0800) { | ||
APPEND(0xc0 | ((i >> 6) & 0x1f)); | ||
APPEND(0x80 | (i & 0x3f)); | ||
} else if (i < 0x10000) { | ||
APPEND(0xe0 | ((i >> 12) & 0x0f)); | ||
APPEND(0x80 | ((i >> 6) & 0x3f)); | ||
APPEND(0x80 | (i & 0x3f)); | ||
} else { | ||
APPEND(0xf0 | ((i >> 18) & 0x07)); | ||
APPEND(0x80 | ((i >> 12) & 0x3f)); | ||
APPEND(0x80 | ((i >> 6) & 0x3f)); | ||
APPEND(0x80 | (i & 0x3f)); | ||
} | ||
} | ||
break; | ||
default: | ||
APPEND(*it->p); | ||
} | ||
it->p++; | ||
} | ||
|
||
it->end = it->p++; | ||
return 0; | ||
} | ||
|
||
static void skip_whitespace(struct json_iterator *it) | ||
{ | ||
while (isspace(*it->p)) | ||
it->p++; | ||
} | ||
|
||
int iterate_json(struct json_iterator *it) | ||
{ | ||
skip_whitespace(it); | ||
it->begin = it->p; | ||
|
||
switch (*it->p) { | ||
case '\0': | ||
return reset_iterator(it), 0; | ||
case 'n': | ||
if (!starts_with(it->p, "null")) | ||
return error("unexpected value: %.*s", 4, it->p), | ||
reset_iterator(it); | ||
it->type = JSON_NULL; | ||
it->end = it->p = it->begin + 4; | ||
break; | ||
case 't': | ||
if (!starts_with(it->p, "true")) | ||
return error("unexpected value: %.*s", 4, it->p), | ||
reset_iterator(it); | ||
it->type = JSON_TRUE; | ||
it->end = it->p = it->begin + 4; | ||
break; | ||
case 'f': | ||
if (!starts_with(it->p, "false")) | ||
return error("unexpected value: %.*s", 5, it->p), | ||
reset_iterator(it); | ||
it->type = JSON_FALSE; | ||
it->end = it->p = it->begin + 5; | ||
break; | ||
case '-': case '.': | ||
case '0': case '1': case '2': case '3': case '4': | ||
case '5': case '6': case '7': case '8': case '9': | ||
it->type = JSON_NUMBER; | ||
it->end = it->p = it->begin + strspn(it->p, "-.0123456789"); | ||
break; | ||
case '"': | ||
it->type = JSON_STRING; | ||
if (parse_json_string(it, &it->string_value) < 0) | ||
return -1; | ||
break; | ||
case '[': { | ||
const char *save = it->begin; | ||
size_t key_offset = it->key.len; | ||
int i = 0, res; | ||
|
||
for (it->p++, skip_whitespace(it); *it->p != ']'; i++) { | ||
strbuf_addf(&it->key, "[%d]", i); | ||
|
||
if ((res = iterate_json(it))) | ||
return reset_iterator(it), res; | ||
strbuf_setlen(&it->key, key_offset); | ||
|
||
skip_whitespace(it); | ||
if (*it->p == ',') | ||
it->p++; | ||
} | ||
|
||
it->type = JSON_ARRAY; | ||
it->begin = save; | ||
it->end = it->p; | ||
it->p++; | ||
break; | ||
} | ||
case '{': { | ||
const char *save = it->begin; | ||
size_t key_offset = it->key.len; | ||
int res; | ||
|
||
strbuf_addch(&it->key, '.'); | ||
for (it->p++, skip_whitespace(it); *it->p != '}'; ) { | ||
strbuf_setlen(&it->key, key_offset + 1); | ||
if (parse_json_string(it, &it->key) < 0) | ||
return -1; | ||
skip_whitespace(it); | ||
if (*(it->p)++ != ':') | ||
return error("expected colon: %.*s", 5, it->p), | ||
reset_iterator(it); | ||
|
||
if ((res = iterate_json(it))) | ||
return res; | ||
|
||
skip_whitespace(it); | ||
if (*it->p == ',') | ||
it->p++; | ||
} | ||
strbuf_setlen(&it->key, key_offset); | ||
|
||
it->type = JSON_OBJECT; | ||
it->begin = save; | ||
it->end = it->p; | ||
it->p++; | ||
break; | ||
} | ||
} | ||
|
||
return it->fn(it); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#ifndef JSON_PARSER_H | ||
#define JSON_PARSER_H | ||
|
||
#include "strbuf.h" | ||
|
||
struct json_iterator { | ||
const char *json, *p, *begin, *end; | ||
struct strbuf key, string_value; | ||
enum { | ||
JSON_NULL = 0, | ||
JSON_FALSE, | ||
JSON_TRUE, | ||
JSON_NUMBER, | ||
JSON_STRING, | ||
JSON_ARRAY, | ||
JSON_OBJECT | ||
} type; | ||
int (*fn)(struct json_iterator *it); | ||
void *fn_data; | ||
}; | ||
#define JSON_ITERATOR_INIT(json_, fn_, fn_data_) { \ | ||
.json = json_, .p = json_, \ | ||
.key = STRBUF_INIT, .string_value = STRBUF_INIT, \ | ||
.fn = fn_, .fn_data = fn_data_ \ | ||
} | ||
|
||
int iterate_json(struct json_iterator *it); | ||
|
||
#endif |
Oops, something went wrong.