Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
c8ac5cfb
Commit
c8ac5cfb
authored
May 21, 2017
by
Arnim Läuger
Committed by
GitHub
May 21, 2017
Browse files
Merge pull request #1980 from nodemcu/dev
2.1.0 master drop
parents
22e1adc4
787379f0
Changes
153
Show whitespace changes
Inline
Side-by-side
app/cjson/rfc4627.txt
deleted
100644 → 0
View file @
22e1adc4
Network Working Group D. Crockford
Request for Comments: 4627 JSON.org
Category: Informational July 2006
The application/json Media Type for JavaScript Object Notation (JSON)
Status of This Memo
This memo provides information for the Internet community. It does
not specify an Internet standard of any kind. Distribution of this
memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (2006).
Abstract
JavaScript Object Notation (JSON) is a lightweight, text-based,
language-independent data interchange format. It was derived from
the ECMAScript Programming Language Standard. JSON defines a small
set of formatting rules for the portable representation of structured
data.
1. Introduction
JavaScript Object Notation (JSON) is a text format for the
serialization of structured data. It is derived from the object
literals of JavaScript, as defined in the ECMAScript Programming
Language Standard, Third Edition [ECMA].
JSON can represent four primitive types (strings, numbers, booleans,
and null) and two structured types (objects and arrays).
A string is a sequence of zero or more Unicode characters [UNICODE].
An object is an unordered collection of zero or more name/value
pairs, where a name is a string and a value is a string, number,
boolean, null, object, or array.
An array is an ordered sequence of zero or more values.
The terms "object" and "array" come from the conventions of
JavaScript.
JSON's design goals were for it to be minimal, portable, textual, and
a subset of JavaScript.
Crockford Informational [Page 1]
RFC 4627 JSON July 2006
1.1. Conventions Used in This Document
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC2119].
The grammatical rules in this document are to be interpreted as
described in [RFC4234].
2. JSON Grammar
A JSON text is a sequence of tokens. The set of tokens includes six
structural characters, strings, numbers, and three literal names.
A JSON text is a serialized object or array.
JSON-text = object / array
These are the six structural characters:
begin-array = ws %x5B ws ; [ left square bracket
begin-object = ws %x7B ws ; { left curly bracket
end-array = ws %x5D ws ; ] right square bracket
end-object = ws %x7D ws ; } right curly bracket
name-separator = ws %x3A ws ; : colon
value-separator = ws %x2C ws ; , comma
Insignificant whitespace is allowed before or after any of the six
structural characters.
ws = *(
%x20 / ; Space
%x09 / ; Horizontal tab
%x0A / ; Line feed or New line
%x0D ; Carriage return
)
2.1. Values
A JSON value MUST be an object, array, number, or string, or one of
the following three literal names:
false null true
Crockford Informational [Page 2]
RFC 4627 JSON July 2006
The literal names MUST be lowercase. No other literal names are
allowed.
value = false / null / true / object / array / number / string
false = %x66.61.6c.73.65 ; false
null = %x6e.75.6c.6c ; null
true = %x74.72.75.65 ; true
2.2. Objects
An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members). A name is a
string. A single colon comes after each name, separating the name
from the value. A single comma separates a value from a following
name. The names within an object SHOULD be unique.
object = begin-object [ member *( value-separator member ) ]
end-object
member = string name-separator value
2.3. Arrays
An array structure is represented as square brackets surrounding zero
or more values (or elements). Elements are separated by commas.
array = begin-array [ value *( value-separator value ) ] end-array
2.4. Numbers
The representation of numbers is similar to that used in most
programming languages. A number contains an integer component that
may be prefixed with an optional minus sign, which may be followed by
a fraction part and/or an exponent part.
Octal and hex forms are not allowed. Leading zeros are not allowed.
A fraction part is a decimal point followed by one or more digits.
An exponent part begins with the letter E in upper or lowercase,
which may be followed by a plus or minus sign. The E and optional
sign are followed by one or more digits.
Numeric values that cannot be represented as sequences of digits
(such as Infinity and NaN) are not permitted.
Crockford Informational [Page 3]
RFC 4627 JSON July 2006
number = [ minus ] int [ frac ] [ exp ]
decimal-point = %x2E ; .
digit1-9 = %x31-39 ; 1-9
e = %x65 / %x45 ; e E
exp = e [ minus / plus ] 1*DIGIT
frac = decimal-point 1*DIGIT
int = zero / ( digit1-9 *DIGIT )
minus = %x2D ; -
plus = %x2B ; +
zero = %x30 ; 0
2.5. Strings
The representation of strings is similar to conventions used in the C
family of programming languages. A string begins and ends with
quotation marks. All Unicode characters may be placed within the
quotation marks except for the characters that must be escaped:
quotation mark, reverse solidus, and the control characters (U+0000
through U+001F).
Any character may be escaped. If the character is in the Basic
Multilingual Plane (U+0000 through U+FFFF), then it may be
represented as a six-character sequence: a reverse solidus, followed
by the lowercase letter u, followed by four hexadecimal digits that
encode the character's code point. The hexadecimal letters A though
F can be upper or lowercase. So, for example, a string containing
only a single reverse solidus character may be represented as
"\u005C".
Alternatively, there are two-character sequence escape
representations of some popular characters. So, for example, a
string containing only a single reverse solidus character may be
represented more compactly as "\\".
To escape an extended character that is not in the Basic Multilingual
Plane, the character is represented as a twelve-character sequence,
encoding the UTF-16 surrogate pair. So, for example, a string
containing only the G clef character (U+1D11E) may be represented as
"\uD834\uDD1E".
Crockford Informational [Page 4]
RFC 4627 JSON July 2006
string = quotation-mark *char quotation-mark
char = unescaped /
escape (
%x22 / ; " quotation mark U+0022
%x5C / ; \ reverse solidus U+005C
%x2F / ; / solidus U+002F
%x62 / ; b backspace U+0008
%x66 / ; f form feed U+000C
%x6E / ; n line feed U+000A
%x72 / ; r carriage return U+000D
%x74 / ; t tab U+0009
%x75 4HEXDIG ) ; uXXXX U+XXXX
escape = %x5C ; \
quotation-mark = %x22 ; "
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
3. Encoding
JSON text SHALL be encoded in Unicode. The default encoding is
UTF-8.
Since the first two characters of a JSON text will always be ASCII
characters [RFC0020], it is possible to determine whether an octet
stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
at the pattern of nulls in the first four octets.
00 00 00 xx UTF-32BE
00 xx 00 xx UTF-16BE
xx 00 00 00 UTF-32LE
xx 00 xx 00 UTF-16LE
xx xx xx xx UTF-8
4. Parsers
A JSON parser transforms a JSON text into another representation. A
JSON parser MUST accept all texts that conform to the JSON grammar.
A JSON parser MAY accept non-JSON forms or extensions.
An implementation may set limits on the size of texts that it
accepts. An implementation may set limits on the maximum depth of
nesting. An implementation may set limits on the range of numbers.
An implementation may set limits on the length and character contents
of strings.
Crockford Informational [Page 5]
RFC 4627 JSON July 2006
5. Generators
A JSON generator produces JSON text. The resulting text MUST
strictly conform to the JSON grammar.
6. IANA Considerations
The MIME media type for JSON text is application/json.
Type name: application
Subtype name: json
Required parameters: n/a
Optional parameters: n/a
Encoding considerations: 8bit if UTF-8; binary if UTF-16 or UTF-32
JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON
is written in UTF-8, JSON is 8bit compatible. When JSON is
written in UTF-16 or UTF-32, the binary content-transfer-encoding
must be used.
Security considerations:
Generally there are security issues with scripting languages. JSON
is a subset of JavaScript, but it is a safe subset that excludes
assignment and invocation.
A JSON text can be safely passed into JavaScript's eval() function
(which compiles and executes a string) if all the characters not
enclosed in strings are in the set of characters that form JSON
tokens. This can be quickly determined in JavaScript with two
regular expressions and calls to the test and replace methods.
var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
eval('(' + text + ')');
Interoperability considerations: n/a
Published specification: RFC 4627
Crockford Informational [Page 6]
RFC 4627 JSON July 2006
Applications that use this media type:
JSON has been used to exchange data between applications written
in all of these programming languages: ActionScript, C, C#,
ColdFusion, Common Lisp, E, Erlang, Java, JavaScript, Lua,
Objective CAML, Perl, PHP, Python, Rebol, Ruby, and Scheme.
Additional information:
Magic number(s): n/a
File extension(s): .json
Macintosh file type code(s): TEXT
Person & email address to contact for further information:
Douglas Crockford
douglas@crockford.com
Intended usage: COMMON
Restrictions on usage: none
Author:
Douglas Crockford
douglas@crockford.com
Change controller:
Douglas Crockford
douglas@crockford.com
7. Security Considerations
See Security Considerations in Section 6.
8. Examples
This is a JSON object:
{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": "100"
},
"IDs": [116, 943, 234, 38793]
Crockford Informational [Page 7]
RFC 4627 JSON July 2006
}
}
Its Image member is an object whose Thumbnail member is an object
and whose IDs member is an array of numbers.
This is a JSON array containing two objects:
[
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},
{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]
9. References
9.1. Normative References
[ECMA] European Computer Manufacturers Association, "ECMAScript
Language Specification 3rd Edition", December 1999,
<http://www.ecma-international.org/publications/files/
ecma-st/ECMA-262.pdf>.
[RFC0020] Cerf, V., "ASCII format for network interchange", RFC 20,
October 1969.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC4234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", RFC 4234, October 2005.
Crockford Informational [Page 8]
RFC 4627 JSON July 2006
[UNICODE] The Unicode Consortium, "The Unicode Standard Version 4.0",
2003, <http://www.unicode.org/versions/Unicode4.1.0/>.
Author's Address
Douglas Crockford
JSON.org
EMail: douglas@crockford.com
Crockford Informational [Page 9]
RFC 4627 JSON July 2006
Full Copyright Statement
Copyright (C) The Internet Society (2006).
This document is subject to the rights, licenses and restrictions
contained in BCP 78, and except as set forth therein, the authors
retain all their rights.
This document and the information contained herein are provided on an
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property
The IETF takes no position regarding the validity or scope of any
Intellectual Property Rights or other rights that might be claimed to
pertain to the implementation or use of the technology described in
this document or the extent to which any license under such rights
might or might not be available; nor does it represent that it has
made any independent effort to identify any such rights. Information
on the procedures with respect to rights in RFC documents can be
found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any
assurances of licenses to be made available, or the result of an
attempt made to obtain a general license or permission for the use of
such proprietary rights by implementers or users of this
specification can be obtained from the IETF on-line IPR repository at
http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any
copyrights, patents or patent applications, or other proprietary
rights that may cover technology that may be required to implement
this standard. Please address the information to the IETF at
ietf-ipr@ietf.org.
Acknowledgement
Funding for the RFC Editor function is provided by the IETF
Administrative Support Activity (IASA).
Crockford Informational [Page 10]
app/cjson/strbuf.c
deleted
100644 → 0
View file @
22e1adc4
/* strbuf - String buffer routines
*
* Copyright (c) 2010-2012 Mark Pulford <mark@kyne.com.au>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_stdarg.h"
#include "c_string.h"
#include "strbuf.h"
#include "cjson_mem.h"
int
strbuf_init
(
strbuf_t
*
s
,
int
len
)
{
int
size
;
if
(
len
<=
0
)
size
=
STRBUF_DEFAULT_SIZE
;
else
size
=
len
+
1
;
/* \0 terminator */
s
->
buf
=
NULL
;
s
->
size
=
size
;
s
->
length
=
0
;
s
->
increment
=
STRBUF_DEFAULT_INCREMENT
;
s
->
dynamic
=
0
;
s
->
reallocs
=
0
;
s
->
debug
=
0
;
s
->
buf
=
(
char
*
)
cjson_mem_malloc
(
size
);
if
(
!
s
->
buf
){
NODE_ERR
(
"not enough memory
\n
"
);
return
-
1
;
}
strbuf_ensure_null
(
s
);
return
0
;
}
strbuf_t
*
strbuf_new
(
int
len
)
{
strbuf_t
*
s
;
s
=
(
strbuf_t
*
)
cjson_mem_malloc
(
sizeof
(
strbuf_t
));
if
(
!
s
){
NODE_ERR
(
"not enough memory
\n
"
);
return
NULL
;
}
strbuf_init
(
s
,
len
);
/* Dynamic strbuf allocation / deallocation */
s
->
dynamic
=
1
;
return
s
;
}
int
strbuf_set_increment
(
strbuf_t
*
s
,
int
increment
)
{
/* Increment > 0: Linear buffer growth rate
* Increment < -1: Exponential buffer growth rate */
if
(
increment
==
0
||
increment
==
-
1
){
NODE_ERR
(
"BUG: Invalid string increment"
);
return
-
1
;
}
s
->
increment
=
increment
;
return
0
;
}
static
inline
void
debug_stats
(
strbuf_t
*
s
)
{
if
(
s
->
debug
)
{
NODE_ERR
(
"strbuf(%lx) reallocs: %d, length: %d, size: %d
\n
"
,
(
long
)
s
,
s
->
reallocs
,
s
->
length
,
s
->
size
);
}
}
/* If strbuf_t has not been dynamically allocated, strbuf_free() can
* be called any number of times strbuf_init() */
void
strbuf_free
(
strbuf_t
*
s
)
{
debug_stats
(
s
);
if
(
s
->
buf
)
{
c_free
(
s
->
buf
);
s
->
buf
=
NULL
;
}
if
(
s
->
dynamic
)
c_free
(
s
);
}
char
*
strbuf_free_to_string
(
strbuf_t
*
s
,
int
*
len
)
{
char
*
buf
;
debug_stats
(
s
);
strbuf_ensure_null
(
s
);
buf
=
s
->
buf
;
if
(
len
)
*
len
=
s
->
length
;
if
(
s
->
dynamic
)
c_free
(
s
);
return
buf
;
}
static
int
calculate_new_size
(
strbuf_t
*
s
,
int
len
)
{
int
reqsize
,
newsize
;
if
(
len
<=
0
){
NODE_ERR
(
"BUG: Invalid strbuf length requested"
);
return
0
;
}
/* Ensure there is room for optional NULL termination */
reqsize
=
len
+
1
;
/* If the user has requested to shrink the buffer, do it exactly */
if
(
s
->
size
>
reqsize
)
return
reqsize
;
newsize
=
s
->
size
;
if
(
s
->
increment
<
0
)
{
/* Exponential sizing */
while
(
newsize
<
reqsize
)
newsize
*=
-
s
->
increment
;
}
else
{
/* Linear sizing */
newsize
=
(((
reqsize
-
1
)
/
s
->
increment
)
+
1
)
*
s
->
increment
;
}
return
newsize
;
}
/* Ensure strbuf can handle a string length bytes long (ignoring NULL
* optional termination). */
int
strbuf_resize
(
strbuf_t
*
s
,
int
len
)
{
int
newsize
;
newsize
=
calculate_new_size
(
s
,
len
);
if
(
s
->
debug
>
1
)
{
NODE_ERR
(
"strbuf(%lx) resize: %d => %d
\n
"
,
(
long
)
s
,
s
->
size
,
newsize
);
}
s
->
buf
=
(
char
*
)
cjson_mem_realloc
(
s
->
buf
,
newsize
);
if
(
!
s
->
buf
){
NODE_ERR
(
"not enough memory"
);
return
-
1
;
}
s
->
size
=
newsize
;
s
->
reallocs
++
;
return
0
;
}
void
strbuf_append_string
(
strbuf_t
*
s
,
const
char
*
str
)
{
int
space
,
i
;
space
=
strbuf_empty_length
(
s
);
for
(
i
=
0
;
str
[
i
];
i
++
)
{
if
(
space
<
1
)
{
strbuf_resize
(
s
,
s
->
length
+
1
);
space
=
strbuf_empty_length
(
s
);
}
s
->
buf
[
s
->
length
]
=
str
[
i
];
s
->
length
++
;
space
--
;
}
}
#if 0
/* strbuf_append_fmt() should only be used when an upper bound
* is known for the output string. */
void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
{
va_list arg;
int fmt_len;
strbuf_ensure_empty_length(s, len);
va_start(arg, fmt);
fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);
va_end(arg);
if (fmt_len < 0)
die("BUG: Unable to convert number"); /* This should never happen.. */
s->length += fmt_len;
}
/* strbuf_append_fmt_retry() can be used when the there is no known
* upper bound for the output string. */
void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
{
va_list arg;
int fmt_len, try;
int empty_len;
/* If the first attempt to append fails, resize the buffer appropriately
* and try again */
for (try = 0; ; try++) {
va_start(arg, fmt);
/* Append the new formatted string */
/* fmt_len is the length of the string required, excluding the
* trailing NULL */
empty_len = strbuf_empty_length(s);
/* Add 1 since there is also space to store the terminating NULL. */
fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);
va_end(arg);
if (fmt_len <= empty_len)
break; /* SUCCESS */
if (try > 0)
die("BUG: length of formatted string changed");
strbuf_resize(s, s->length + fmt_len);
}
s->length += fmt_len;
}
#endif
/* vi:ai et sw=4 ts=4:
*/
app/cjson/strbuf.h
deleted
100644 → 0
View file @
22e1adc4
/* strbuf - String buffer routines
*
* Copyright (c) 2010-2012 Mark Pulford <mark@kyne.com.au>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "c_stdlib.h"
#include "c_stdarg.h"
#include "user_config.h"
/* Size: Total bytes allocated to *buf
* Length: String length, excluding optional NULL terminator.
* Increment: Allocation increments when resizing the string buffer.
* Dynamic: True if created via strbuf_new()
*/
typedef
struct
{
char
*
buf
;
int
size
;
int
length
;
int
increment
;
int
dynamic
;
int
reallocs
;
int
debug
;
}
strbuf_t
;
#ifndef STRBUF_DEFAULT_SIZE
#define STRBUF_DEFAULT_SIZE 1023
#endif
#ifndef STRBUF_DEFAULT_INCREMENT
#define STRBUF_DEFAULT_INCREMENT -2
#endif
/* Initialise */
extern
strbuf_t
*
strbuf_new
(
int
len
);
extern
int
strbuf_init
(
strbuf_t
*
s
,
int
len
);
extern
int
strbuf_set_increment
(
strbuf_t
*
s
,
int
increment
);
/* Release */
extern
void
strbuf_free
(
strbuf_t
*
s
);
extern
char
*
strbuf_free_to_string
(
strbuf_t
*
s
,
int
*
len
);
/* Management */
extern
int
strbuf_resize
(
strbuf_t
*
s
,
int
len
);
static
int
strbuf_empty_length
(
strbuf_t
*
s
);
static
int
strbuf_length
(
strbuf_t
*
s
);
static
char
*
strbuf_string
(
strbuf_t
*
s
,
int
*
len
);
static
void
strbuf_ensure_empty_length
(
strbuf_t
*
s
,
int
len
);
static
char
*
strbuf_empty_ptr
(
strbuf_t
*
s
);
static
void
strbuf_extend_length
(
strbuf_t
*
s
,
int
len
);
/* Update */
extern
void
strbuf_append_fmt
(
strbuf_t
*
s
,
int
len
,
const
char
*
fmt
,
...);
extern
void
strbuf_append_fmt_retry
(
strbuf_t
*
s
,
const
char
*
format
,
...);
static
void
strbuf_append_mem
(
strbuf_t
*
s
,
const
char
*
c
,
int
len
);
extern
void
strbuf_append_string
(
strbuf_t
*
s
,
const
char
*
str
);
static
void
strbuf_append_char
(
strbuf_t
*
s
,
const
char
c
);
static
void
strbuf_ensure_null
(
strbuf_t
*
s
);
/* Reset string for before use */
static
inline
void
strbuf_reset
(
strbuf_t
*
s
)
{
s
->
length
=
0
;
}
static
inline
int
strbuf_allocated
(
strbuf_t
*
s
)
{
return
s
->
buf
!=
NULL
;
}
/* Return bytes remaining in the string buffer
* Ensure there is space for a NULL terminator. */
static
inline
int
strbuf_empty_length
(
strbuf_t
*
s
)
{
return
s
->
size
-
s
->
length
-
1
;
}
static
inline
void
strbuf_ensure_empty_length
(
strbuf_t
*
s
,
int
len
)
{
if
(
len
>
strbuf_empty_length
(
s
))
strbuf_resize
(
s
,
s
->
length
+
len
);
}
static
inline
char
*
strbuf_empty_ptr
(
strbuf_t
*
s
)
{
return
s
->
buf
+
s
->
length
;
}
static
inline
void
strbuf_extend_length
(
strbuf_t
*
s
,
int
len
)
{
s
->
length
+=
len
;
}
static
inline
int
strbuf_length
(
strbuf_t
*
s
)
{
return
s
->
length
;
}
static
inline
void
strbuf_append_char
(
strbuf_t
*
s
,
const
char
c
)
{
strbuf_ensure_empty_length
(
s
,
1
);
s
->
buf
[
s
->
length
++
]
=
c
;
}
static
inline
void
strbuf_append_char_unsafe
(
strbuf_t
*
s
,
const
char
c
)
{
s
->
buf
[
s
->
length
++
]
=
c
;
}
static
inline
void
strbuf_append_mem
(
strbuf_t
*
s
,
const
char
*
c
,
int
len
)
{
strbuf_ensure_empty_length
(
s
,
len
);
c_memcpy
(
s
->
buf
+
s
->
length
,
c
,
len
);
s
->
length
+=
len
;
}
static
inline
void
strbuf_append_mem_unsafe
(
strbuf_t
*
s
,
const
char
*
c
,
int
len
)
{
c_memcpy
(
s
->
buf
+
s
->
length
,
c
,
len
);
s
->
length
+=
len
;
}
static
inline
void
strbuf_ensure_null
(
strbuf_t
*
s
)
{
s
->
buf
[
s
->
length
]
=
0
;
}
static
inline
char
*
strbuf_string
(
strbuf_t
*
s
,
int
*
len
)
{
if
(
len
)
*
len
=
s
->
length
;
return
s
->
buf
;
}
/* vi:ai et sw=4 ts=4:
*/
app/cjson/tests/README
deleted
100644 → 0
View file @
22e1adc4
These JSON examples were taken from the JSON website
(http://json.org/example.html) and RFC 4627.
Used with permission.
app/cjson/tests/bench.lua
deleted
100644 → 0
View file @
22e1adc4
#!/usr/bin/env lua
-- This benchmark script measures wall clock time and should be
-- run on an unloaded system.
--
-- Your Mileage May Vary.
--
-- Mark Pulford <mark@kyne.com.au>
local
json_module
=
os.getenv
(
"JSON_MODULE"
)
or
"cjson"
require
"socket"
local
json
=
require
(
json_module
)
local
util
=
require
"cjson.util"
local
function
find_func
(
mod
,
funcnames
)
for
_
,
v
in
ipairs
(
funcnames
)
do
if
mod
[
v
]
then
return
mod
[
v
]
end
end
return
nil
end
local
json_encode
=
find_func
(
json
,
{
"encode"
,
"Encode"
,
"to_string"
,
"stringify"
,
"json"
})
local
json_decode
=
find_func
(
json
,
{
"decode"
,
"Decode"
,
"to_value"
,
"parse"
})
local
function
average
(
t
)
local
total
=
0
for
_
,
v
in
ipairs
(
t
)
do
total
=
total
+
v
end
return
total
/
#
t
end
function
benchmark
(
tests
,
seconds
,
rep
)
local
function
bench
(
func
,
iter
)
-- Use socket.gettime() to measure microsecond resolution
-- wall clock time.
local
t
=
socket
.
gettime
()
for
i
=
1
,
iter
do
func
(
i
)
end
t
=
socket
.
gettime
()
-
t
-- Don't trust any results when the run lasted for less than a
-- millisecond - return nil.
if
t
<
0
.
001
then
return
nil
end
return
(
iter
/
t
)
end
-- Roughly calculate the number of interations required
-- to obtain a particular time period.
local
function
calc_iter
(
func
,
seconds
)
local
iter
=
1
local
rate
-- Warm up the bench function first.
func
()
while
not
rate
do
rate
=
bench
(
func
,
iter
)
iter
=
iter
*
10
end
return
math.ceil
(
seconds
*
rate
)
end
local
test_results
=
{}
for
name
,
func
in
pairs
(
tests
)
do
-- k(number), v(string)
-- k(string), v(function)
-- k(number), v(function)
if
type
(
func
)
==
"string"
then
name
=
func
func
=
_G
[
name
]
end
local
iter
=
calc_iter
(
func
,
seconds
)
local
result
=
{}
for
i
=
1
,
rep
do
result
[
i
]
=
bench
(
func
,
iter
)
end
-- Remove the slowest half (round down) of the result set
table.sort
(
result
)
for
i
=
1
,
math.floor
(
#
result
/
2
)
do
table.remove
(
result
,
1
)
end
test_results
[
name
]
=
average
(
result
)
end
return
test_results
end
function
bench_file
(
filename
)
local
data_json
=
util
.
file_load
(
filename
)
local
data_obj
=
json_decode
(
data_json
)
local
function
test_encode
()
json_encode
(
data_obj
)
end
local
function
test_decode
()
json_decode
(
data_json
)
end
local
tests
=
{}
if
json_encode
then
tests
.
encode
=
test_encode
end
if
json_decode
then
tests
.
decode
=
test_decode
end
return
benchmark
(
tests
,
0
.
1
,
5
)
end
-- Optionally load any custom configuration required for this module
local
success
,
data
=
pcall
(
util
.
file_load
,
(
"bench-%s.lua"
):
format
(
json_module
))
if
success
then
util
.
run_script
(
data
,
_G
)
configure
(
json
)
end
for
i
=
1
,
#
arg
do
local
results
=
bench_file
(
arg
[
i
])
for
k
,
v
in
pairs
(
results
)
do
print
((
"%s\t%s\t%d"
):
format
(
arg
[
i
],
k
,
v
))
end
end
-- vi:ai et sw=4 ts=4:
app/cjson/tests/example1.json
deleted
100644 → 0
View file @
22e1adc4
{
"glossary"
:
{
"title"
:
"example glossary"
,
"GlossDiv"
:
{
"title"
:
"S"
,
"GlossList"
:
{
"GlossEntry"
:
{
"ID"
:
"SGML"
,
"SortAs"
:
"SGML"
,
"GlossTerm"
:
"Standard Generalized Mark up Language"
,
"Acronym"
:
"SGML"
,
"Abbrev"
:
"ISO 8879:1986"
,
"GlossDef"
:
{
"para"
:
"A meta-markup language, used to create markup languages such as DocBook."
,
"GlossSeeAlso"
:
[
"GML"
,
"XML"
]
},
"GlossSee"
:
"markup"
}
}
}
}
}
app/cjson/tests/example2.json
deleted
100644 → 0
View file @
22e1adc4
{
"menu"
:
{
"id"
:
"file"
,
"value"
:
"File"
,
"popup"
:
{
"menuitem"
:
[
{
"value"
:
"New"
,
"onclick"
:
"CreateNewDoc()"
},
{
"value"
:
"Open"
,
"onclick"
:
"OpenDoc()"
},
{
"value"
:
"Close"
,
"onclick"
:
"CloseDoc()"
}
]
}
}}
app/cjson/tests/example3.json
deleted
100644 → 0
View file @
22e1adc4
{
"widget"
:
{
"debug"
:
"on"
,
"window"
:
{
"title"
:
"Sample Konfabulator Widget"
,
"name"
:
"main_window"
,
"width"
:
500
,
"height"
:
500
},
"image"
:
{
"src"
:
"Images/Sun.png"
,
"name"
:
"sun1"
,
"hOffset"
:
250
,
"vOffset"
:
250
,
"alignment"
:
"center"
},
"text"
:
{
"data"
:
"Click Here"
,
"size"
:
36
,
"style"
:
"bold"
,
"name"
:
"text1"
,
"hOffset"
:
250
,
"vOffset"
:
100
,
"alignment"
:
"center"
,
"onMouseUp"
:
"sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
app/cjson/tests/example4.json
deleted
100644 → 0
View file @
22e1adc4
{
"web-app"
:
{
"servlet"
:
[
{
"servlet-name"
:
"cofaxCDS"
,
"servlet-class"
:
"org.cofax.cds.CDSServlet"
,
"init-param"
:
{
"configGlossary:installationAt"
:
"Philadelphia, PA"
,
"configGlossary:adminEmail"
:
"ksm@pobox.com"
,
"configGlossary:poweredBy"
:
"Cofax"
,
"configGlossary:poweredByIcon"
:
"/images/cofax.gif"
,
"configGlossary:staticPath"
:
"/content/static"
,
"templateProcessorClass"
:
"org.cofax.WysiwygTemplate"
,
"templateLoaderClass"
:
"org.cofax.FilesTemplateLoader"
,
"templatePath"
:
"templates"
,
"templateOverridePath"
:
""
,
"defaultListTemplate"
:
"listTemplate.htm"
,
"defaultFileTemplate"
:
"articleTemplate.htm"
,
"useJSP"
:
false
,
"jspListTemplate"
:
"listTemplate.jsp"
,
"jspFileTemplate"
:
"articleTemplate.jsp"
,
"cachePackageTagsTrack"
:
200
,
"cachePackageTagsStore"
:
200
,
"cachePackageTagsRefresh"
:
60
,
"cacheTemplatesTrack"
:
100
,
"cacheTemplatesStore"
:
50
,
"cacheTemplatesRefresh"
:
15
,
"cachePagesTrack"
:
200
,
"cachePagesStore"
:
100
,
"cachePagesRefresh"
:
10
,
"cachePagesDirtyRead"
:
10
,
"searchEngineListTemplate"
:
"forSearchEnginesList.htm"
,
"searchEngineFileTemplate"
:
"forSearchEngines.htm"
,
"searchEngineRobotsDb"
:
"WEB-INF/robots.db"
,
"useDataStore"
:
true
,
"dataStoreClass"
:
"org.cofax.SqlDataStore"
,
"redirectionClass"
:
"org.cofax.SqlRedirection"
,
"dataStoreName"
:
"cofax"
,
"dataStoreDriver"
:
"com.microsoft.jdbc.sqlserver.SQLServerDriver"
,
"dataStoreUrl"
:
"jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon"
,
"dataStoreUser"
:
"sa"
,
"dataStorePassword"
:
"dataStoreTestQuery"
,
"dataStoreTestQuery"
:
"SET NOCOUNT ON;select test='test';"
,
"dataStoreLogFile"
:
"/usr/local/tomcat/logs/datastore.log"
,
"dataStoreInitConns"
:
10
,
"dataStoreMaxConns"
:
100
,
"dataStoreConnUsageLimit"
:
100
,
"dataStoreLogLevel"
:
"debug"
,
"maxUrlLength"
:
500
}},
{
"servlet-name"
:
"cofaxEmail"
,
"servlet-class"
:
"org.cofax.cds.EmailServlet"
,
"init-param"
:
{
"mailHost"
:
"mail1"
,
"mailHostOverride"
:
"mail2"
}},
{
"servlet-name"
:
"cofaxAdmin"
,
"servlet-class"
:
"org.cofax.cds.AdminServlet"
},
{
"servlet-name"
:
"fileServlet"
,
"servlet-class"
:
"org.cofax.cds.FileServlet"
},
{
"servlet-name"
:
"cofaxTools"
,
"servlet-class"
:
"org.cofax.cms.CofaxToolsServlet"
,
"init-param"
:
{
"templatePath"
:
"toolstemplates/"
,
"log"
:
1
,
"logLocation"
:
"/usr/local/tomcat/logs/CofaxTools.log"
,
"logMaxSize"
:
""
,
"dataLog"
:
1
,
"dataLogLocation"
:
"/usr/local/tomcat/logs/dataLog.log"
,
"dataLogMaxSize"
:
""
,
"removePageCache"
:
"/content/admin/remove?cache=pages&id="
,
"removeTemplateCache"
:
"/content/admin/remove?cache=templates&id="
,
"fileTransferFolder"
:
"/usr/local/tomcat/webapps/content/fileTransferFolder"
,
"lookInContext"
:
1
,
"adminGroupID"
:
4
,
"betaServer"
:
true
}}],
"servlet-mapping"
:
{
"cofaxCDS"
:
"/"
,
"cofaxEmail"
:
"/cofaxutil/aemail/*"
,
"cofaxAdmin"
:
"/admin/*"
,
"fileServlet"
:
"/static/*"
,
"cofaxTools"
:
"/tools/*"
},
"taglib"
:
{
"taglib-uri"
:
"cofax.tld"
,
"taglib-location"
:
"/WEB-INF/tlds/cofax.tld"
}}}
app/cjson/tests/example5.json
deleted
100644 → 0
View file @
22e1adc4
{
"menu"
:
{
"header"
:
"SVG Viewer"
,
"items"
:
[
{
"id"
:
"Open"
},
{
"id"
:
"OpenNew"
,
"label"
:
"Open New"
},
null
,
{
"id"
:
"ZoomIn"
,
"label"
:
"Zoom In"
},
{
"id"
:
"ZoomOut"
,
"label"
:
"Zoom Out"
},
{
"id"
:
"OriginalView"
,
"label"
:
"Original View"
},
null
,
{
"id"
:
"Quality"
},
{
"id"
:
"Pause"
},
{
"id"
:
"Mute"
},
null
,
{
"id"
:
"Find"
,
"label"
:
"Find..."
},
{
"id"
:
"FindAgain"
,
"label"
:
"Find Again"
},
{
"id"
:
"Copy"
},
{
"id"
:
"CopyAgain"
,
"label"
:
"Copy Again"
},
{
"id"
:
"CopySVG"
,
"label"
:
"Copy SVG"
},
{
"id"
:
"ViewSVG"
,
"label"
:
"View SVG"
},
{
"id"
:
"ViewSource"
,
"label"
:
"View Source"
},
{
"id"
:
"SaveAs"
,
"label"
:
"Save As"
},
null
,
{
"id"
:
"Help"
},
{
"id"
:
"About"
,
"label"
:
"About Adobe CVG Viewer..."
}
]
}}
app/cjson/tests/genutf8.pl
deleted
100644 → 0
View file @
22e1adc4
#!/usr/bin/env perl
# Create test comparison data using a different UTF-8 implementation.
# The generated utf8.dat file must have the following MD5 sum:
# cff03b039d850f370a7362f3313e5268
use
strict
;
# 0xD800 - 0xDFFF are used to encode supplementary codepoints
# 0x10000 - 0x10FFFF are supplementary codepoints
my
(
@codepoints
)
=
(
0
..
0xD7FF
,
0xE000
..
0x10FFFF
);
my
$utf8
=
pack
("
U*
",
@codepoints
);
defined
(
$utf8
)
or
die
"
Unable create UTF-8 string
\n
";
open
(
FH
,
"
>:utf8
",
"
utf8.dat
")
or
die
"
Unable to open utf8.dat: $!
\n
";
print
FH
$utf8
or
die
"
Unable to write utf8.dat
\n
";
close
(
FH
);
# vi:ai et sw=4 ts=4:
app/cjson/tests/numbers.json
deleted
100644 → 0
View file @
22e1adc4
[
0.110001
,
0.12345678910111
,
0.412454033640
,
2.6651441426902
,
2.718281828459
,
3.1415926535898
,
2.1406926327793
]
app/cjson/tests/octets-escaped.dat
deleted
100644 → 0
View file @
22e1adc4
"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
\ No newline at end of file
app/cjson/tests/rfc-example1.json
deleted
100644 → 0
View file @
22e1adc4
{
"Image"
:
{
"Width"
:
800
,
"Height"
:
600
,
"Title"
:
"View from 15th Floor"
,
"Thumbnail"
:
{
"Url"
:
"http://www.example.com/image/481989943"
,
"Height"
:
125
,
"Width"
:
"100"
},
"IDs"
:
[
116
,
943
,
234
,
38793
]
}
}
app/cjson/tests/rfc-example2.json
deleted
100644 → 0
View file @
22e1adc4
[
{
"precision"
:
"zip"
,
"Latitude"
:
37.7668
,
"Longitude"
:
-122.3959
,
"Address"
:
""
,
"City"
:
"SAN FRANCISCO"
,
"State"
:
"CA"
,
"Zip"
:
"94107"
,
"Country"
:
"US"
},
{
"precision"
:
"zip"
,
"Latitude"
:
37.371991
,
"Longitude"
:
-122.026020
,
"Address"
:
""
,
"City"
:
"SUNNYVALE"
,
"State"
:
"CA"
,
"Zip"
:
"94085"
,
"Country"
:
"US"
}
]
app/cjson/tests/test.lua
deleted
100644 → 0
View file @
22e1adc4
#!/usr/bin/env lua
-- Lua CJSON tests
--
-- Mark Pulford <mark@kyne.com.au>
--
-- Note: The output of this script is easier to read with "less -S"
local
json
=
require
"cjson"
local
json_safe
=
require
"cjson.safe"
local
util
=
require
"cjson.util"
local
function
gen_raw_octets
()
local
chars
=
{}
for
i
=
0
,
255
do
chars
[
i
+
1
]
=
string.char
(
i
)
end
return
table.concat
(
chars
)
end
-- Generate every UTF-16 codepoint, including supplementary codes
local
function
gen_utf16_escaped
()
-- Create raw table escapes
local
utf16_escaped
=
{}
local
count
=
0
local
function
append_escape
(
code
)
local
esc
=
(
'
\\
u%04X'
):
format
(
code
)
table.insert
(
utf16_escaped
,
esc
)
end
table.insert
(
utf16_escaped
,
'"'
)
for
i
=
0
,
0xD7FF
do
append_escape
(
i
)
end
-- Skip 0xD800 - 0xDFFF since they are used to encode supplementary
-- codepoints
for
i
=
0xE000
,
0xFFFF
do
append_escape
(
i
)
end
-- Append surrogate pair for each supplementary codepoint
for
high
=
0xD800
,
0xDBFF
do
for
low
=
0xDC00
,
0xDFFF
do
append_escape
(
high
)
append_escape
(
low
)
end
end
table.insert
(
utf16_escaped
,
'"'
)
return
table.concat
(
utf16_escaped
)
end
function
load_testdata
()
local
data
=
{}
-- Data for 8bit raw <-> escaped octets tests
data
.
octets_raw
=
gen_raw_octets
()
data
.
octets_escaped
=
util
.
file_load
(
"octets-escaped.dat"
)
-- Data for \uXXXX -> UTF-8 test
data
.
utf16_escaped
=
gen_utf16_escaped
()
-- Load matching data for utf16_escaped
local
utf8_loaded
utf8_loaded
,
data
.
utf8_raw
=
pcall
(
util
.
file_load
,
"utf8.dat"
)
if
not
utf8_loaded
then
data
.
utf8_raw
=
"Failed to load utf8.dat - please run genutf8.pl"
end
data
.
table_cycle
=
{}
data
.
table_cycle
[
1
]
=
data
.
table_cycle
local
big
=
{}
for
i
=
1
,
1100
do
big
=
{
{
10
,
false
,
true
,
json
.
null
},
"string"
,
a
=
big
}
end
data
.
deeply_nested_data
=
big
return
data
end
function
test_decode_cycle
(
filename
)
local
obj1
=
json
.
decode
(
util
.
file_load
(
filename
))
local
obj2
=
json
.
decode
(
json
.
encode
(
obj1
))
return
util
.
compare_values
(
obj1
,
obj2
)
end
-- Set up data used in tests
local
Inf
=
math.huge
;
local
NaN
=
math.huge
*
0
;
local
testdata
=
load_testdata
()
local
cjson_tests
=
{
-- Test API variables
{
"Check module name, version"
,
function
()
return
json
.
_NAME
,
json
.
_VERSION
end
,
{
},
true
,
{
"cjson"
,
"2.1devel"
}
},
-- Test decoding simple types
{
"Decode string"
,
json
.
decode
,
{
'"test string"'
},
true
,
{
"test string"
}
},
{
"Decode numbers"
,
json
.
decode
,
{
'[ 0.0, -5e3, -1, 0.3e-3, 1023.2, 0e10 ]'
},
true
,
{
{
0
.
0
,
-
5000
,
-
1
,
0
.
0003
,
1023
.
2
,
0
}
}
},
{
"Decode null"
,
json
.
decode
,
{
'null'
},
true
,
{
json
.
null
}
},
{
"Decode true"
,
json
.
decode
,
{
'true'
},
true
,
{
true
}
},
{
"Decode false"
,
json
.
decode
,
{
'false'
},
true
,
{
false
}
},
{
"Decode object with numeric keys"
,
json
.
decode
,
{
'{ "1": "one", "3": "three" }'
},
true
,
{
{
[
"1"
]
=
"one"
,
[
"3"
]
=
"three"
}
}
},
{
"Decode object with string keys"
,
json
.
decode
,
{
'{ "a": "a", "b": "b" }'
},
true
,
{
{
a
=
"a"
,
b
=
"b"
}
}
},
{
"Decode array"
,
json
.
decode
,
{
'[ "one", null, "three" ]'
},
true
,
{
{
"one"
,
json
.
null
,
"three"
}
}
},
-- Test decoding errors
{
"Decode UTF-16BE [throw error]"
,
json
.
decode
,
{
'
\0
"\0"'
},
false
,
{
"JSON parser does not support UTF-16 or UTF-32"
}
},
{
"Decode UTF-16LE [throw error]"
,
json
.
decode
,
{
'"\0"\0'
},
false
,
{
"JSON parser does not support UTF-16 or UTF-32"
}
},
{
"Decode UTF-32BE [throw error]"
,
json
.
decode
,
{
'
\0\0\0
"'
},
false
,
{
"JSON parser does not support UTF-16 or UTF-32"
}
},
{
"Decode UTF-32LE [throw error]"
,
json
.
decode
,
{
'"\0\0\0'
},
false
,
{
"JSON parser does not support UTF-16 or UTF-32"
}
},
{
"Decode partial JSON [throw error]"
,
json
.
decode
,
{
'{ "unexpected eof": '
},
false
,
{
"Expected value but found T_END at character 21"
}
},
{
"Decode with extra comma [throw error]"
,
json
.
decode
,
{
'{ "extra data": true }, false'
},
false
,
{
"Expected the end but found T_COMMA at character 23"
}
},
{
"Decode invalid escape code [throw error]"
,
json
.
decode
,
{
[[ { "bad escape \q code" } ]]
},
false
,
{
"Expected object key string but found invalid escape code at character 16"
}
},
{
"Decode invalid unicode escape [throw error]"
,
json
.
decode
,
{
[[ { "bad unicode \u0f6 escape" } ]]
},
false
,
{
"Expected object key string but found invalid unicode escape code at character 17"
}
},
{
"Decode invalid keyword [throw error]"
,
json
.
decode
,
{
' [ "bad barewood", test ] '
},
false
,
{
"Expected value but found invalid token at character 20"
}
},
{
"Decode invalid number #1 [throw error]"
,
json
.
decode
,
{
'[ -+12 ]'
},
false
,
{
"Expected value but found invalid number at character 3"
}
},
{
"Decode invalid number #2 [throw error]"
,
json
.
decode
,
{
'-v'
},
false
,
{
"Expected value but found invalid number at character 1"
}
},
{
"Decode invalid number exponent [throw error]"
,
json
.
decode
,
{
'[ 0.4eg10 ]'
},
false
,
{
"Expected comma or array end but found invalid token at character 6"
}
},
-- Test decoding nested arrays / objects
{
"Set decode_max_depth(5)"
,
json
.
decode_max_depth
,
{
5
},
true
,
{
5
}
},
{
"Decode array at nested limit"
,
json
.
decode
,
{
'[[[[[ "nested" ]]]]]'
},
true
,
{
{{{{{
"nested"
}}}}}
}
},
{
"Decode array over nested limit [throw error]"
,
json
.
decode
,
{
'[[[[[[ "nested" ]]]]]]'
},
false
,
{
"Found too many nested data structures (6) at character 6"
}
},
{
"Decode object at nested limit"
,
json
.
decode
,
{
'{"a":{"b":{"c":{"d":{"e":"nested"}}}}}'
},
true
,
{
{
a
=
{
b
=
{
c
=
{
d
=
{
e
=
"nested"
}}}}}
}
},
{
"Decode object over nested limit [throw error]"
,
json
.
decode
,
{
'{"a":{"b":{"c":{"d":{"e":{"f":"nested"}}}}}}'
},
false
,
{
"Found too many nested data structures (6) at character 26"
}
},
{
"Set decode_max_depth(1000)"
,
json
.
decode_max_depth
,
{
1000
},
true
,
{
1000
}
},
{
"Decode deeply nested array [throw error]"
,
json
.
decode
,
{
string.rep
(
"["
,
1100
)
..
'1100'
..
string.rep
(
"]"
,
1100
)},
false
,
{
"Found too many nested data structures (1001) at character 1001"
}
},
-- Test encoding nested tables
{
"Set encode_max_depth(5)"
,
json
.
encode_max_depth
,
{
5
},
true
,
{
5
}
},
{
"Encode nested table as array at nested limit"
,
json
.
encode
,
{
{{{{{
"nested"
}}}}}
},
true
,
{
'[[[[["nested"]]]]]'
}
},
{
"Encode nested table as array after nested limit [throw error]"
,
json
.
encode
,
{
{
{{{{{
"nested"
}}}}}
}
},
false
,
{
"Cannot serialise, excessive nesting (6)"
}
},
{
"Encode nested table as object at nested limit"
,
json
.
encode
,
{
{
a
=
{
b
=
{
c
=
{
d
=
{
e
=
"nested"
}}}}}
},
true
,
{
'{"a":{"b":{"c":{"d":{"e":"nested"}}}}}'
}
},
{
"Encode nested table as object over nested limit [throw error]"
,
json
.
encode
,
{
{
a
=
{
b
=
{
c
=
{
d
=
{
e
=
{
f
=
"nested"
}}}}}}
},
false
,
{
"Cannot serialise, excessive nesting (6)"
}
},
{
"Encode table with cycle [throw error]"
,
json
.
encode
,
{
testdata
.
table_cycle
},
false
,
{
"Cannot serialise, excessive nesting (6)"
}
},
{
"Set encode_max_depth(1000)"
,
json
.
encode_max_depth
,
{
1000
},
true
,
{
1000
}
},
{
"Encode deeply nested data [throw error]"
,
json
.
encode
,
{
testdata
.
deeply_nested_data
},
false
,
{
"Cannot serialise, excessive nesting (1001)"
}
},
-- Test encoding simple types
{
"Encode null"
,
json
.
encode
,
{
json
.
null
},
true
,
{
'null'
}
},
{
"Encode true"
,
json
.
encode
,
{
true
},
true
,
{
'true'
}
},
{
"Encode false"
,
json
.
encode
,
{
false
},
true
,
{
'false'
}
},
{
"Encode empty object"
,
json
.
encode
,
{
{
}
},
true
,
{
'{}'
}
},
{
"Encode integer"
,
json
.
encode
,
{
10
},
true
,
{
'10'
}
},
{
"Encode string"
,
json
.
encode
,
{
"hello"
},
true
,
{
'"hello"'
}
},
{
"Encode Lua function [throw error]"
,
json
.
encode
,
{
function
()
end
},
false
,
{
"Cannot serialise function: type not supported"
}
},
-- Test decoding invalid numbers
{
"Set decode_invalid_numbers(true)"
,
json
.
decode_invalid_numbers
,
{
true
},
true
,
{
true
}
},
{
"Decode hexadecimal"
,
json
.
decode
,
{
'0x6.ffp1'
},
true
,
{
13
.
9921875
}
},
{
"Decode numbers with leading zero"
,
json
.
decode
,
{
'[ 0123, 00.33 ]'
},
true
,
{
{
123
,
0
.
33
}
}
},
{
"Decode +-Inf"
,
json
.
decode
,
{
'[ +Inf, Inf, -Inf ]'
},
true
,
{
{
Inf
,
Inf
,
-
Inf
}
}
},
{
"Decode +-Infinity"
,
json
.
decode
,
{
'[ +Infinity, Infinity, -Infinity ]'
},
true
,
{
{
Inf
,
Inf
,
-
Inf
}
}
},
{
"Decode +-NaN"
,
json
.
decode
,
{
'[ +NaN, NaN, -NaN ]'
},
true
,
{
{
NaN
,
NaN
,
NaN
}
}
},
{
"Decode Infrared (not infinity) [throw error]"
,
json
.
decode
,
{
'Infrared'
},
false
,
{
"Expected the end but found invalid token at character 4"
}
},
{
"Decode Noodle (not NaN) [throw error]"
,
json
.
decode
,
{
'Noodle'
},
false
,
{
"Expected value but found invalid token at character 1"
}
},
{
"Set decode_invalid_numbers(false)"
,
json
.
decode_invalid_numbers
,
{
false
},
true
,
{
false
}
},
{
"Decode hexadecimal [throw error]"
,
json
.
decode
,
{
'0x6'
},
false
,
{
"Expected value but found invalid number at character 1"
}
},
{
"Decode numbers with leading zero [throw error]"
,
json
.
decode
,
{
'[ 0123, 00.33 ]'
},
false
,
{
"Expected value but found invalid number at character 3"
}
},
{
"Decode +-Inf [throw error]"
,
json
.
decode
,
{
'[ +Inf, Inf, -Inf ]'
},
false
,
{
"Expected value but found invalid token at character 3"
}
},
{
"Decode +-Infinity [throw error]"
,
json
.
decode
,
{
'[ +Infinity, Infinity, -Infinity ]'
},
false
,
{
"Expected value but found invalid token at character 3"
}
},
{
"Decode +-NaN [throw error]"
,
json
.
decode
,
{
'[ +NaN, NaN, -NaN ]'
},
false
,
{
"Expected value but found invalid token at character 3"
}
},
{
'Set decode_invalid_numbers("on")'
,
json
.
decode_invalid_numbers
,
{
"on"
},
true
,
{
true
}
},
-- Test encoding invalid numbers
{
"Set encode_invalid_numbers(false)"
,
json
.
encode_invalid_numbers
,
{
false
},
true
,
{
false
}
},
{
"Encode NaN [throw error]"
,
json
.
encode
,
{
NaN
},
false
,
{
"Cannot serialise number: must not be NaN or Infinity"
}
},
{
"Encode Infinity [throw error]"
,
json
.
encode
,
{
Inf
},
false
,
{
"Cannot serialise number: must not be NaN or Infinity"
}
},
{
"Set encode_invalid_numbers(\"
null
\
")"
,
json
.
encode_invalid_numbers
,
{
"null"
},
true
,
{
"null"
}
},
{
"Encode NaN as null"
,
json
.
encode
,
{
NaN
},
true
,
{
"null"
}
},
{
"Encode Infinity as null"
,
json
.
encode
,
{
Inf
},
true
,
{
"null"
}
},
{
"Set encode_invalid_numbers(true)"
,
json
.
encode_invalid_numbers
,
{
true
},
true
,
{
true
}
},
{
"Encode NaN"
,
json
.
encode
,
{
NaN
},
true
,
{
"NaN"
}
},
{
"Encode +Infinity"
,
json
.
encode
,
{
Inf
},
true
,
{
"Infinity"
}
},
{
"Encode -Infinity"
,
json
.
encode
,
{
-
Inf
},
true
,
{
"-Infinity"
}
},
{
'Set encode_invalid_numbers("off")'
,
json
.
encode_invalid_numbers
,
{
"off"
},
true
,
{
false
}
},
-- Test encoding tables
{
"Set encode_sparse_array(true, 2, 3)"
,
json
.
encode_sparse_array
,
{
true
,
2
,
3
},
true
,
{
true
,
2
,
3
}
},
{
"Encode sparse table as array #1"
,
json
.
encode
,
{
{
[
3
]
=
"sparse test"
}
},
true
,
{
'[null,null,"sparse test"]'
}
},
{
"Encode sparse table as array #2"
,
json
.
encode
,
{
{
[
1
]
=
"one"
,
[
4
]
=
"sparse test"
}
},
true
,
{
'["one",null,null,"sparse test"]'
}
},
{
"Encode sparse array as object"
,
json
.
encode
,
{
{
[
1
]
=
"one"
,
[
5
]
=
"sparse test"
}
},
true
,
{
'{"1":"one","5":"sparse test"}'
}
},
{
"Encode table with numeric string key as object"
,
json
.
encode
,
{
{
[
"2"
]
=
"numeric string key test"
}
},
true
,
{
'{"2":"numeric string key test"}'
}
},
{
"Set encode_sparse_array(false)"
,
json
.
encode_sparse_array
,
{
false
},
true
,
{
false
,
2
,
3
}
},
{
"Encode table with incompatible key [throw error]"
,
json
.
encode
,
{
{
[
false
]
=
"wrong"
}
},
false
,
{
"Cannot serialise boolean: table key must be a number or string"
}
},
-- Test escaping
{
"Encode all octets (8-bit clean)"
,
json
.
encode
,
{
testdata
.
octets_raw
},
true
,
{
testdata
.
octets_escaped
}
},
{
"Decode all escaped octets"
,
json
.
decode
,
{
testdata
.
octets_escaped
},
true
,
{
testdata
.
octets_raw
}
},
{
"Decode single UTF-16 escape"
,
json
.
decode
,
{
[["\uF800"]]
},
true
,
{
"
\239\160\128
"
}
},
{
"Decode all UTF-16 escapes (including surrogate combinations)"
,
json
.
decode
,
{
testdata
.
utf16_escaped
},
true
,
{
testdata
.
utf8_raw
}
},
{
"Decode swapped surrogate pair [throw error]"
,
json
.
decode
,
{
[["\uDC00\uD800"]]
},
false
,
{
"Expected value but found invalid unicode escape code at character 2"
}
},
{
"Decode duplicate high surrogate [throw error]"
,
json
.
decode
,
{
[["\uDB00\uDB00"]]
},
false
,
{
"Expected value but found invalid unicode escape code at character 2"
}
},
{
"Decode duplicate low surrogate [throw error]"
,
json
.
decode
,
{
[["\uDB00\uDB00"]]
},
false
,
{
"Expected value but found invalid unicode escape code at character 2"
}
},
{
"Decode missing low surrogate [throw error]"
,
json
.
decode
,
{
[["\uDB00"]]
},
false
,
{
"Expected value but found invalid unicode escape code at character 2"
}
},
{
"Decode invalid low surrogate [throw error]"
,
json
.
decode
,
{
[["\uDB00\uD"]]
},
false
,
{
"Expected value but found invalid unicode escape code at character 2"
}
},
-- Test locale support
--
-- The standard Lua interpreter is ANSI C online doesn't support locales
-- by default. Force a known problematic locale to test strtod()/sprintf().
{
"Set locale to cs_CZ (comma separator)"
,
function
()
os.setlocale
(
"cs_CZ"
)
json
.
new
()
end
},
{
"Encode number under comma locale"
,
json
.
encode
,
{
1
.
5
},
true
,
{
'1.5'
}
},
{
"Decode number in array under comma locale"
,
json
.
decode
,
{
'[ 10, "test" ]'
},
true
,
{
{
10
,
"test"
}
}
},
{
"Revert locale to POSIX"
,
function
()
os.setlocale
(
"C"
)
json
.
new
()
end
},
-- Test encode_keep_buffer() and enable_number_precision()
{
"Set encode_keep_buffer(false)"
,
json
.
encode_keep_buffer
,
{
false
},
true
,
{
false
}
},
{
"Set encode_number_precision(3)"
,
json
.
encode_number_precision
,
{
3
},
true
,
{
3
}
},
{
"Encode number with precision 3"
,
json
.
encode
,
{
1
/
3
},
true
,
{
"0.333"
}
},
{
"Set encode_number_precision(14)"
,
json
.
encode_number_precision
,
{
14
},
true
,
{
14
}
},
{
"Set encode_keep_buffer(true)"
,
json
.
encode_keep_buffer
,
{
true
},
true
,
{
true
}
},
-- Test config API errors
-- Function is listed as '?' due to pcall
{
"Set encode_number_precision(0) [throw error]"
,
json
.
encode_number_precision
,
{
0
},
false
,
{
"bad argument #1 to '?' (expected integer between 1 and 14)"
}
},
{
"Set encode_number_precision(\"
five
\
") [throw error]"
,
json
.
encode_number_precision
,
{
"five"
},
false
,
{
"bad argument #1 to '?' (number expected, got string)"
}
},
{
"Set encode_keep_buffer(nil, true) [throw error]"
,
json
.
encode_keep_buffer
,
{
nil
,
true
},
false
,
{
"bad argument #2 to '?' (found too many arguments)"
}
},
{
"Set encode_max_depth(\"
wrong
\
") [throw error]"
,
json
.
encode_max_depth
,
{
"wrong"
},
false
,
{
"bad argument #1 to '?' (number expected, got string)"
}
},
{
"Set decode_max_depth(0) [throw error]"
,
json
.
decode_max_depth
,
{
"0"
},
false
,
{
"bad argument #1 to '?' (expected integer between 1 and 2147483647)"
}
},
{
"Set encode_invalid_numbers(-2) [throw error]"
,
json
.
encode_invalid_numbers
,
{
-
2
},
false
,
{
"bad argument #1 to '?' (invalid option '-2')"
}
},
{
"Set decode_invalid_numbers(true, false) [throw error]"
,
json
.
decode_invalid_numbers
,
{
true
,
false
},
false
,
{
"bad argument #2 to '?' (found too many arguments)"
}
},
{
"Set encode_sparse_array(\"
not
quite
on
\
") [throw error]"
,
json
.
encode_sparse_array
,
{
"not quite on"
},
false
,
{
"bad argument #1 to '?' (invalid option 'not quite on')"
}
},
{
"Reset Lua CJSON configuration"
,
function
()
json
=
json
.
new
()
end
},
-- Wrap in a function to ensure the table returned by json.new() is used
{
"Check encode_sparse_array()"
,
function
(
...
)
return
json
.
encode_sparse_array
(
...
)
end
,
{
},
true
,
{
false
,
2
,
10
}
},
{
"Encode (safe) simple value"
,
json_safe
.
encode
,
{
true
},
true
,
{
"true"
}
},
{
"Encode (safe) argument validation [throw error]"
,
json_safe
.
encode
,
{
"arg1"
,
"arg2"
},
false
,
{
"bad argument #1 to '?' (expected 1 argument)"
}
},
{
"Decode (safe) error generation"
,
json_safe
.
decode
,
{
"Oops"
},
true
,
{
nil
,
"Expected value but found invalid token at character 1"
}
},
{
"Decode (safe) error generation after new()"
,
function
(
...
)
return
json_safe
.
new
().
decode
(
...
)
end
,
{
"Oops"
},
true
,
{
nil
,
"Expected value but found invalid token at character 1"
}
},
}
print
((
"==> Testing Lua CJSON version %s\n"
):
format
(
json
.
_VERSION
))
util
.
run_test_group
(
cjson_tests
)
for
_
,
filename
in
ipairs
(
arg
)
do
util
.
run_test
(
"Decode cycle "
..
filename
,
test_decode_cycle
,
{
filename
},
true
,
{
true
})
end
local
pass
,
total
=
util
.
run_test_summary
()
if
pass
==
total
then
print
(
"==> Summary: all tests succeeded"
)
else
print
((
"==> Summary: %d/%d tests failed"
):
format
(
total
-
pass
,
total
))
os.exit
(
1
)
end
-- vi:ai et sw=4 ts=4:
app/cjson/tests/types.json
deleted
100644 → 0
View file @
22e1adc4
{
"array"
:
[
10
,
true
,
null
]
}
app/driver/onewire.c
View file @
c8ac5cfb
...
...
@@ -122,15 +122,29 @@ uint8_t onewire_reset(uint8_t pin)
// Write a bit. Port and bit is used to cut lookup time and provide
// more certain timing.
//
static
void
onewire_write_bit
(
uint8_t
pin
,
uint8_t
v
)
static
void
onewire_write_bit
(
uint8_t
pin
,
uint8_t
v
,
uint8_t
power
)
{
if
(
v
&
1
)
{
onewire_read_bit
(
pin
);
noInterrupts
();
DIRECT_WRITE_LOW
(
pin
);
delayMicroseconds
(
5
);
if
(
power
)
{
DIRECT_WRITE_HIGH
(
pin
);
}
else
{
DIRECT_MODE_INPUT
(
pin
);
// drive output high by the pull-up
}
delayMicroseconds
(
8
);
interrupts
();
delayMicroseconds
(
52
);
}
else
{
noInterrupts
();
DIRECT_WRITE_LOW
(
pin
);
delayMicroseconds
(
65
);
if
(
power
)
{
DIRECT_WRITE_HIGH
(
pin
);
}
else
{
DIRECT_MODE_INPUT
(
pin
);
// drive output high by the pull-up
}
interrupts
();
delayMicroseconds
(
5
);
}
...
...
@@ -157,9 +171,10 @@ static uint8_t onewire_read_bit(uint8_t pin)
}
//
// Write a byte. The writing code uses the
active drivers
to raise the
// Write a byte. The writing code uses the
external pull-up
to raise the
// pin high, if you need power after the write (e.g. DS18S20 in
// parasite power mode) then set 'power' to 1, otherwise the pin will
// parasite power mode) then set 'power' to 1 and the output driver will
// be activated at the end of the write. Otherwise the pin will
// go tri-state at the end of the write to avoid heating in a short or
// other mishap.
//
...
...
@@ -167,26 +182,15 @@ void onewire_write(uint8_t pin, uint8_t v, uint8_t power /* = 0 */) {
uint8_t
bitMask
;
for
(
bitMask
=
0x01
;
bitMask
;
bitMask
<<=
1
)
{
onewire_write_bit
(
pin
,
(
bitMask
&
v
)
?
1
:
0
);
}
if
(
power
)
{
noInterrupts
();
DIRECT_WRITE_HIGH
(
pin
);
interrupts
();
// send last bit with requested power mode
onewire_write_bit
(
pin
,
(
bitMask
&
v
)
?
1
:
0
,
bitMask
&
0x80
?
power
:
0
);
}
}
void
onewire_write_bytes
(
uint8_t
pin
,
const
uint8_t
*
buf
,
uint16_t
count
,
bool
power
/* = 0 */
)
{
uint16_t
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
onewire_write
(
pin
,
buf
[
i
],
owDefaultPower
);
if
(
power
)
{
noInterrupts
();
DIRECT_WRITE_HIGH
(
pin
);
interrupts
();
}
onewire_write
(
pin
,
buf
[
i
],
i
<
count
-
1
?
owDefaultPower
:
power
);
}
//
...
...
@@ -360,7 +364,7 @@ uint8_t onewire_search(uint8_t pin, uint8_t *newAddr)
ROM_NO
[
pin
][
rom_byte_number
]
&=
~
rom_byte_mask
;
// serial number search direction write bit
onewire_write_bit
(
pin
,
search_direction
);
onewire_write_bit
(
pin
,
search_direction
,
0
);
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
...
...
app/driver/spi.c
View file @
c8ac5cfb
...
...
@@ -19,13 +19,13 @@ void spi_lcd_mode_init(uint8 spi_no)
if
(
spi_no
>
1
)
return
;
//handle invalid input number
//bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock
//bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock
if
(
spi_no
==
SPI
){
if
(
spi_no
==
SPI
_SPI
){
WRITE_PERI_REG
(
PERIPHS_IO_MUX
,
0x005
);
//clear bit9,and bit8
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_CLK_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_CMD_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_DATA0_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_DATA1_U
,
1
);
//configure io to spi mode
}
else
if
(
spi_no
==
HSPI
){
}
else
if
(
spi_no
==
SPI_
HSPI
){
WRITE_PERI_REG
(
PERIPHS_IO_MUX
,
0x105
);
//clear bit9
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTDI_U
,
2
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTCK_U
,
2
);
//configure io to spi mode
...
...
@@ -93,10 +93,10 @@ uint32_t spi_set_clkdiv(uint8 spi_no, uint32_t clock_div)
WRITE_PERI_REG
(
SPI_CLOCK
(
spi_no
),
SPI_CLK_EQU_SYSCLK
);
// 80Mhz speed
}
if
(
spi_no
==
SPI
){
if
(
spi_no
==
SPI
_SPI
){
WRITE_PERI_REG
(
PERIPHS_IO_MUX
,
0x005
|
(
clock_div
<=
1
?
0x100
:
0
));
}
else
if
(
spi_no
==
HSPI
){
else
if
(
spi_no
==
SPI_
HSPI
){
WRITE_PERI_REG
(
PERIPHS_IO_MUX
,
0x105
|
(
clock_div
<=
1
?
0x200
:
0
));
}
...
...
@@ -144,13 +144,13 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_
spi_set_clkdiv
(
spi_no
,
clock_div
);
if
(
spi_no
==
SPI
){
if
(
spi_no
==
SPI
_SPI
){
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_CLK_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_CMD_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_DATA0_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_DATA1_U
,
1
);
//configure io to spi mode
}
else
if
(
spi_no
==
HSPI
){
else
if
(
spi_no
==
SPI_
HSPI
){
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTDI_U
,
2
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTCK_U
,
2
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTMS_U
,
2
);
//configure io to spi mode
...
...
@@ -179,8 +179,16 @@ void spi_mast_byte_order(uint8 spi_no, uint8 order)
*******************************************************************************/
void
spi_mast_blkset
(
uint8
spi_no
,
size_t
bitlen
,
const
uint8
*
data
)
{
size_t
aligned_len
=
bitlen
>>
3
;
while
(
READ_PERI_REG
(
SPI_CMD
(
spi_no
))
&
SPI_USR
);
os_memcpy
((
void
*
)
SPI_W0
(
spi_no
),
(
const
void
*
)
data
,
bitlen
>>
3
);
if
(
aligned_len
%
4
)
{
// length for memcpy needs to be aligned to uint32 bounday
// otherwise single byte writes are issued to the register and corrupt data
aligned_len
+=
4
-
(
aligned_len
%
4
);
}
os_memcpy
((
void
*
)
SPI_W0
(
spi_no
),
(
const
void
*
)
data
,
aligned_len
);
}
/******************************************************************************
...
...
@@ -188,12 +196,29 @@ void spi_mast_blkset(uint8 spi_no, size_t bitlen, const uint8 *data)
* Description : Copy a block of data from the MISO FIFO
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* size_t bitlen - number of bits to copy, multiple of 8
* uint8 *data - pointer to data buffer
* uint8 *data - pointer to data buffer, the buffer must be able to
* accept a multiple of 4*8 bits
*******************************************************************************/
void
spi_mast_blkget
(
uint8
spi_no
,
size_t
bitlen
,
uint8
*
data
)
{
size_t
aligned_len
=
bitlen
>>
3
;
while
(
READ_PERI_REG
(
SPI_CMD
(
spi_no
))
&
SPI_USR
);
os_memcpy
((
void
*
)
data
,
(
void
*
)
SPI_W0
(
spi_no
),
bitlen
>>
3
);
if
(
aligned_len
%
4
)
{
// length for memcpy needs to be aligned to uint32 bounday
// otherwise single byte reads are issued to the register and corrupt data
aligned_len
+=
4
-
(
aligned_len
%
4
);
}
os_memcpy
((
void
*
)
data
,
(
void
*
)
SPI_W0
(
spi_no
),
aligned_len
);
}
static
uint32
swap_endianess
(
uint32
n
)
{
return
((
n
&
0xff
)
<<
24
)
|
((
n
&
0xff00
)
<<
8
)
|
((
n
&
0xff0000UL
)
>>
8
)
|
((
n
&
0xff000000UL
)
>>
24
);
}
/******************************************************************************
...
...
@@ -208,8 +233,8 @@ void spi_mast_blkget(uint8 spi_no, size_t bitlen, uint8 *data)
*******************************************************************************/
void
spi_mast_set_mosi
(
uint8
spi_no
,
uint16
offset
,
uint8
bitlen
,
uint32
data
)
{
uint8
wn
,
shift
;
spi_buf_t
spi_buf
;
uint8
wn
,
shift
;
if
(
spi_no
>
1
)
return
;
// handle invalid input number
...
...
@@ -226,8 +251,10 @@ void spi_mast_set_mosi(uint8 spi_no, uint16 offset, uint8 bitlen, uint32 data)
// transfer Wn to buf
spi_buf
.
word
[
1
]
=
READ_PERI_REG
(
SPI_W0
(
spi_no
)
+
wn
*
4
);
spi_buf
.
word
[
1
]
=
swap_endianess
(
spi_buf
.
word
[
1
]);
if
(
wn
<
15
)
{
spi_buf
.
word
[
0
]
=
READ_PERI_REG
(
SPI_W0
(
spi_no
)
+
(
wn
+
1
)
*
4
);
spi_buf
.
word
[
0
]
=
swap_endianess
(
spi_buf
.
word
[
0
]);
}
shift
=
64
-
(
offset
&
0x1f
)
-
bitlen
;
...
...
@@ -235,9 +262,9 @@ void spi_mast_set_mosi(uint8 spi_no, uint16 offset, uint8 bitlen, uint32 data)
spi_buf
.
dword
|=
(
uint64
)
data
<<
shift
;
if
(
wn
<
15
)
{
WRITE_PERI_REG
(
SPI_W0
(
spi_no
)
+
(
wn
+
1
)
*
4
,
spi_buf
.
word
[
0
]);
WRITE_PERI_REG
(
SPI_W0
(
spi_no
)
+
(
wn
+
1
)
*
4
,
swap_endianess
(
spi_buf
.
word
[
0
])
)
;
}
WRITE_PERI_REG
(
SPI_W0
(
spi_no
)
+
wn
*
4
,
spi_buf
.
word
[
1
]);
WRITE_PERI_REG
(
SPI_W0
(
spi_no
)
+
wn
*
4
,
swap_endianess
(
spi_buf
.
word
[
1
])
)
;
return
;
}
...
...
@@ -269,8 +296,10 @@ uint32 spi_mast_get_miso(uint8 spi_no, uint16 offset, uint8 bitlen)
// transfer Wn to buf
spi_buf
.
word
[
1
]
=
READ_PERI_REG
(
SPI_W0
(
spi_no
)
+
wn
*
4
);
spi_buf
.
word
[
1
]
=
swap_endianess
(
spi_buf
.
word
[
1
]);
if
(
wn
<
15
)
{
spi_buf
.
word
[
0
]
=
READ_PERI_REG
(
SPI_W0
(
spi_no
)
+
(
wn
+
1
)
*
4
);
spi_buf
.
word
[
0
]
=
swap_endianess
(
spi_buf
.
word
[
0
]);
}
result
=
(
uint32
)(
spi_buf
.
dword
>>
(
64
-
((
offset
&
0x1f
)
+
bitlen
)));
...
...
@@ -419,12 +448,12 @@ void spi_slave_init(uint8 spi_no)
//bit9 should be cleared when HSPI clock doesn't equal CPU clock
//bit8 should be cleared when SPI clock doesn't equal CPU clock
////WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9//TEST
if
(
spi_no
==
SPI
){
if
(
spi_no
==
SPI
_SPI
){
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_CLK_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_CMD_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_DATA0_U
,
1
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_SD_DATA1_U
,
1
);
//configure io to spi mode
}
else
if
(
spi_no
==
HSPI
){
}
else
if
(
spi_no
==
SPI_
HSPI
){
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTDI_U
,
2
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTCK_U
,
2
);
//configure io to spi mode
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_MTMS_U
,
2
);
//configure io to spi mode
...
...
@@ -511,10 +540,10 @@ void hspi_master_readwrite_repeat(void)
uint8
temp
;
os_timer_disarm
(
&
timer2
);
spi_byte_read_espslave
(
HSPI
,
&
temp
);
spi_byte_read_espslave
(
SPI_
HSPI
,
&
temp
);
temp
++
;
spi_byte_write_espslave
(
HSPI
,
temp
);
spi_byte_write_espslave
(
SPI_
HSPI
,
temp
);
os_timer_setfn
(
&
timer2
,
(
os_timer_func_t
*
)
hspi_master_readwrite_repeat
,
NULL
);
os_timer_arm
(
&
timer2
,
500
,
0
);
}
...
...
@@ -570,23 +599,23 @@ void spi_slave_isr_handler(void *para)
if
(
READ_PERI_REG
(
0x3ff00020
)
&
BIT4
){
//following 3 lines is to clear isr signal
CLEAR_PERI_REG_MASK
(
SPI_SLAVE
(
SPI
),
0x3ff
);
CLEAR_PERI_REG_MASK
(
SPI_SLAVE
(
SPI
_SPI
),
0x3ff
);
}
else
if
(
READ_PERI_REG
(
0x3ff00020
)
&
BIT7
){
//bit7 is for hspi isr,
regvalue
=
READ_PERI_REG
(
SPI_SLAVE
(
HSPI
));
CLEAR_PERI_REG_MASK
(
SPI_SLAVE
(
HSPI
),
regvalue
=
READ_PERI_REG
(
SPI_SLAVE
(
SPI_
HSPI
));
CLEAR_PERI_REG_MASK
(
SPI_SLAVE
(
SPI_
HSPI
),
SPI_TRANS_DONE_EN
|
SPI_SLV_WR_STA_DONE_EN
|
SPI_SLV_RD_STA_DONE_EN
|
SPI_SLV_WR_BUF_DONE_EN
|
SPI_SLV_RD_BUF_DONE_EN
);
SET_PERI_REG_MASK
(
SPI_SLAVE
(
HSPI
),
SPI_SYNC_RESET
);
CLEAR_PERI_REG_MASK
(
SPI_SLAVE
(
HSPI
),
SET_PERI_REG_MASK
(
SPI_SLAVE
(
SPI_
HSPI
),
SPI_SYNC_RESET
);
CLEAR_PERI_REG_MASK
(
SPI_SLAVE
(
SPI_
HSPI
),
SPI_TRANS_DONE
|
SPI_SLV_WR_STA_DONE
|
SPI_SLV_RD_STA_DONE
|
SPI_SLV_WR_BUF_DONE
|
SPI_SLV_RD_BUF_DONE
);
SET_PERI_REG_MASK
(
SPI_SLAVE
(
HSPI
),
SET_PERI_REG_MASK
(
SPI_SLAVE
(
SPI_
HSPI
),
SPI_TRANS_DONE_EN
|
SPI_SLV_WR_STA_DONE_EN
|
SPI_SLV_RD_STA_DONE_EN
|
...
...
@@ -597,7 +626,7 @@ void spi_slave_isr_handler(void *para)
GPIO_OUTPUT_SET
(
0
,
0
);
idx
=
0
;
while
(
idx
<
8
){
recv_data
=
READ_PERI_REG
(
SPI_W0
(
HSPI
)
+
(
idx
<<
2
));
recv_data
=
READ_PERI_REG
(
SPI_W0
(
SPI_
HSPI
)
+
(
idx
<<
2
));
spi_data
[
idx
<<
2
]
=
recv_data
&
0xff
;
spi_data
[(
idx
<<
2
)
+
1
]
=
(
recv_data
>>
8
)
&
0xff
;
spi_data
[(
idx
<<
2
)
+
2
]
=
(
recv_data
>>
16
)
&
0xff
;
...
...
@@ -627,15 +656,15 @@ void ICACHE_FLASH_ATTR
set_miso_data
()
{
if
(
GPIO_INPUT_GET
(
2
)
==
0
){
WRITE_PERI_REG
(
SPI_W8
(
HSPI
),
0x05040302
);
WRITE_PERI_REG
(
SPI_W9
(
HSPI
),
0x09080706
);
WRITE_PERI_REG
(
SPI_W10
(
HSPI
),
0x0d0c0b0a
);
WRITE_PERI_REG
(
SPI_W11
(
HSPI
),
0x11100f0e
);
WRITE_PERI_REG
(
SPI_W12
(
HSPI
),
0x15141312
);
WRITE_PERI_REG
(
SPI_W13
(
HSPI
),
0x19181716
);
WRITE_PERI_REG
(
SPI_W14
(
HSPI
),
0x1d1c1b1a
);
WRITE_PERI_REG
(
SPI_W15
(
HSPI
),
0x21201f1e
);
WRITE_PERI_REG
(
SPI_W8
(
SPI_
HSPI
),
0x05040302
);
WRITE_PERI_REG
(
SPI_W9
(
SPI_
HSPI
),
0x09080706
);
WRITE_PERI_REG
(
SPI_W10
(
SPI_
HSPI
),
0x0d0c0b0a
);
WRITE_PERI_REG
(
SPI_W11
(
SPI_
HSPI
),
0x11100f0e
);
WRITE_PERI_REG
(
SPI_W12
(
SPI_
HSPI
),
0x15141312
);
WRITE_PERI_REG
(
SPI_W13
(
SPI_
HSPI
),
0x19181716
);
WRITE_PERI_REG
(
SPI_W14
(
SPI_
HSPI
),
0x1d1c1b1a
);
WRITE_PERI_REG
(
SPI_W15
(
SPI_
HSPI
),
0x21201f1e
);
GPIO_OUTPUT_SET
(
2
,
1
);
}
}
...
...
@@ -697,7 +726,7 @@ void ICACHE_FLASH_ATTR
spi_test_init
()
{
os_printf
(
"spi init
\n\r
"
);
spi_slave_init
(
HSPI
);
spi_slave_init
(
SPI_
HSPI
);
os_printf
(
"gpio init
\n\r
"
);
gpio_init
();
os_printf
(
"spi task init
\n\r
"
);
...
...
app/driver/uart.c
View file @
c8ac5cfb
...
...
@@ -43,6 +43,22 @@ static void (*alt_uart0_tx)(char txchar);
LOCAL
void
ICACHE_RAM_ATTR
uart0_rx_intr_handler
(
void
*
para
);
/******************************************************************************
* FunctionName : uart_wait_tx_empty
* Description : Internal used function
* Wait for TX FIFO to become empty.
* Parameters : uart_no, use UART0 or UART1 defined ahead
* Returns : NONE
*******************************************************************************/
LOCAL
void
ICACHE_FLASH_ATTR
uart_wait_tx_empty
(
uint8
uart_no
)
{
while
((
READ_PERI_REG
(
UART_STATUS
(
uart_no
))
&
(
UART_TXFIFO_CNT
<<
UART_TXFIFO_CNT_S
))
>
0
)
;
}
/******************************************************************************
* FunctionName : uart_config
* Description : Internal used function
...
...
@@ -54,6 +70,8 @@ uart0_rx_intr_handler(void *para);
LOCAL
void
ICACHE_FLASH_ATTR
uart_config
(
uint8
uart_no
)
{
uart_wait_tx_empty
(
uart_no
);
if
(
uart_no
==
UART1
)
{
PIN_FUNC_SELECT
(
PERIPHS_IO_MUX_GPIO2_U
,
FUNC_U1TXD_BK
);
}
else
{
...
...
@@ -98,6 +116,8 @@ uart_config(uint8 uart_no)
void
ICACHE_FLASH_ATTR
uart0_alt
(
uint8
on
)
{
uart_wait_tx_empty
(
UART0
);
if
(
on
)
{
PIN_PULLUP_DIS
(
PERIPHS_IO_MUX_MTDO_U
);
...
...
@@ -348,6 +368,8 @@ uart_setup(uint8 uart_no)
#ifdef BIT_RATE_AUTOBAUD
uart_stop_autobaud
();
#endif
// poll Tx FIFO empty outside before disabling interrupts
uart_wait_tx_empty
(
uart_no
);
ETS_UART_INTR_DISABLE
();
uart_config
(
uart_no
);
ETS_UART_INTR_ENABLE
();
...
...
Prev
1
2
3
4
5
6
…
8
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment