mayah / tinytoml Goto Github PK
View Code? Open in Web Editor NEWA header only C++11 library for parsing TOML
License: BSD 2-Clause "Simplified" License
A header only C++11 library for parsing TOML
License: BSD 2-Clause "Simplified" License
Here is the seed that cause the ABRT when parse it use parseFile. you can use your parse_file.cc to reproduce the ABRT.
I think it occured at
void toml::failwith<char const
toml::Value::ensureValue
In the Qt Framework the DateTime, Date, and Time objects main conversion type is std::time_t. This conversion requires a rather long call:
return QVariant(QDateTime::fromTime_t(std::chrono::system_clock::to_time_t(value.as<std::time_t>())));
Is it possible that toml::Value could also provide .asstd::time_t() for time types? Is it possible that toml::Value could also distinguish between Date, Time, and DateTime? It would be useful in our Qt application which has separate QDateEdit, QTimeEdit, and QDateTime edit so as to not have to create the third control when either Date or Time is not needed.
It would be nice to be able to support our own custom types to the TOML parser through templates, so that we could simply write value.as<My_t>()
for any My_t
that we want . Based on my reading of the source, it's already possible without touching the source by adding new template specialization for a few types. I made a macro in my project to do this; I haven't tested it yet, but would you be interested in a pull request to add this type of functionality?
I'd also like to provide an automatic way to deserialize a custom type, but I'm not sure how to do that yet; it might require source modification.
Edit: forgot to mention, I also used this in my project to provide parsers for all the different integer and float types, because the project currently only accepts int64_t
and double
. Would you be interested in that as well?
Given failwith
is the only function incompatible when -fno-exceptions
is specified, I think it would be great to provide a version where exceptions are disabled. The compilation condition can be guarded by a macro guard.
README says:
// For convenience way, you can use get() when you're sure that the value exists.
// If type error occurred, std::runtime_error is raised.
toml::Value v = ...;
cout << v.get<string>("foo.bar") << endl;
However, get is templated to return actual types rather than Value objects like so:
string& s = v.get<string>("foo.bar");
cout << s << endl;
Fixing it to return a value as advertised wouldn't change the syntax much, and would allow us to confirm the type before getting the actual value.
toml::Value& v = root.get("foo.bar");
if (v.is<string>())
cout << v.as<string>() << endl;
If the original behaviour is still desired, it is probably best as an overload to Value::as since the template version has no params:
string& s = v.as<string>("foo.bar");
cout << s << endl;
i ahve a toml file that uses for double numbers a leading 0 in the exponent
Distortion-Factors = [
8.246,0.0812962,-0.000452233,0.109974,-5.38649e-05,
2.77189e-08,
]
with that parsins throws exception
Distortion-Factors = [
8.246,0.0812962,-0.000452233,0.109974,-5.38649e-5,
2.77189e-8,
]
removing leading zeros in exponent fixes the issue, but quite problematic
Hello, I am wondering if it would be possible to add support for comparing toml::Value using the equality operators? toml::Value has some type information to cast and do the comparison. It would also be nice to have .compare_as<T,T>() for comparisons.
I'm trying to compile a simple CUDA file using tinytoml:
// test_toml.cu
#include <iostream>
#include "toml.h"
int main ()
{
std::cerr << "TOML in .cu file!" << std::endl;
return 0;
}
using
nvcc --std=c++11 test_toml.cu -o test_toml
I get a compiler error like the following:
toml.h: In member function ‘toml::Value toml::internal::Parser::parse()’:
toml.h:1775:24: error: cannot convert ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’ in initialization
Value* currentValue = &root;
^~~~
toml.h:1782:41: error: no matching function for call to ‘toml::internal::Parser::parseGroupKey(toml::Value (*)(toml::Table (*)()))’
currentValue = parseGroupKey(&root);
^
toml.h:356:15: note: candidate: toml::Value* toml::internal::Parser::parseGroupKey(toml::Value*)
Value* parseGroupKey(Value* root);
^~~~~~~~~~~~~
toml.h:356:15: note: no known conversion for argument 1 from ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’
toml.h: In member function ‘bool toml::internal::Parser::parseInlineTable(toml::Value*)’:
toml.h:2033:7: error: request for member ‘has’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
if (t.has(key)) {
^ ~
toml.h:2038:3: error: request for member ‘set’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
t.set(key, v);
^
[dshaff@farnarkle1 sandbox]$ nvcc --std=c++11 test_toml.cu -o test_toml
toml.h: In member function ‘toml::Value toml::internal::Parser::parse()’:
toml.h:1775:24: error: cannot convert ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’ in initialization
Value* currentValue = &root;
^~~~
toml.h:1782:41: error: no matching function for call to ‘toml::internal::Parser::parseGroupKey(toml::Value (*)(toml::Table (*)()))’
currentValue = parseGroupKey(&root);
^
toml.h:356:15: note: candidate: toml::Value* toml::internal::Parser::parseGroupKey(toml::Value*)
Value* parseGroupKey(Value* root);
^~~~~~~~~~~~~
toml.h:356:15: note: no known conversion for argument 1 from ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’
toml.h: In member function ‘bool toml::internal::Parser::parseInlineTable(toml::Value*)’:
toml.h:2033:7: error: request for member ‘has’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
if (t.has(key)) {
^ ~
toml.h:2038:3: error: request for member ‘set’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
t.set(key, v);
^
Here's the input that will trigger the issue:
int_overflow.txt
Feed it into master(c2444ed) parse_stdin built with UndefinedBehaviorSanitizer and linked with libstdc++(shipped with gcc 7.1.1) will crash the parser:
> cat int_overflow.txt | ./parse_stdin
/usr/lib64/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1/chrono:176:38: runtime error: signed integer overflow: -61948886400 * 1000000000 cannot be represented in type 'long'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib64/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1/chrono:176:38 in
Interestingly, the issue would disappear if I choose to use libc++ instead.
With a simple int main()
and g++ -std=c++11 main.cpp -o tinytomltest.exe
that only includes the tinytoml header, I get the following:
toml.h: In member function 'void toml::Value::write(std::ostream*, const string&, int) const':
toml.h:1298:25: error: 'gmtime_r' was not declared in this scope
gmtime_r(&tt, &t);
^
This was tested with an older version of MinGW that is shipped with the ENIGMA game engine. gcc -v
gives:
gcc version 4.8.2 (GCC)
I tried with Visual Studio 2015 and created an empty Console Application, which worked just fine using the MSVC 2015 compiler.
So it loos like the entire issue is with MinGW. I guess tinytoml wants to use gmtime_r
because this represents universal time.
https://linux.die.net/man/3/gmtime_r
I know with this version of MinGW that I tested, localtime
does in fact work. I know because it's used in ENIGMA's engine to implement GameMaker's date and time functions.
https://github.com/enigma-dev/enigma-dev/blob/master/ENIGMAsystem/SHELL/Universal_System/Extensions/DateTime/date_time.cpp#L46
But that won't work with tinytoml because localtime
would format the dates and times in the users local timezone making them be incorrect when read back from the toml file if read on a computer with a different timezone.
I read on another GitHub post that some things changed with POSIX in newer MinGW releases. I still could not solve the tinytoml issue by defining _POSIX_C_SOURCE 200809L
even though I know it's irrelevant for my MinGW version.
The full source of what won't compile with MinGW gcc version 4.8.0:
#define _POSIX_C_SOURCE 200809L
#include <time.h>
#include "tinytoml.h"
int main() {
return 0;
}
One work around I have found that makes this build with this MinGW is adding the following to tinytoml.h:
#if defined(_WIN32)
// gmtime_r can be defined by mingw
#ifndef gmtime_r
static struct tm* gmtime_r(const time_t* t, struct tm* r)
{
// gmtime is threadsafe in windows because it uses TLS
struct tm *theTm = gmtime(t);
if (theTm) {
*r = *theTm;
return r;
} else {
return 0;
}
}
#endif // gmtime_r
#else
extern struct tm* gmtime_r(const time_t* t, struct tm* r);
#endif
This patch was taken from here:
http://redmine.webtoolkit.eu/boards/2/topics/7316
With this patch I can build the following with the MinGW GCC version 4.8.0, though it was hard to figure out how to use time types in tinytoml.h:
#include "tinytoml.h"
#include <fstream>
int main() {
std::ofstream ofs("C:/Users/Owner/Desktop/tinytomltest.toml");
toml::Table root;
toml::Table sceneValue = toml::Table();
sceneValue["name"] = "Scene0";
time_t rawtime;
localtime(&rawtime);
sceneValue["created"] = std::chrono::system_clock::from_time_t(rawtime);
root["scene"] = sceneValue;
ofs << root;
ofs.close();
return 0;
}
And this is the output:
[scene]
created = 1970-03-16T07:53:44Z
name = "Scene0"
Perhaps this could be added to the examples in the README.md since it just prints the current date and time to make it clearer how to use dates and times?
There seems to be a convention to name top level path of header files to match the corresponding library name. This is followed by many other projects, eg: opencv, gsl. Would you consider doing the same for this library too?
Thanks for this project. This is my preferred library for parsing configuration files in my own projects.
I use AFL when fuzzing and got some crashes.
==3780==ERROR: LeakSanitizer: detected memory leaks
==18948==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc3803dbc8 (pc 0x0000004982e9 bp 0x7ffc3803e410 sp 0x7ffc3803dbd0 T0)
#0 0x4982e9 in __asan_memcpy (/home/yzy/fuzzsoftware/tinytoml/out/Debug/parse_file+0x4982e9)
#1 0x4e9c11 in toml::internal::Token::operator=(toml::internal::Token&&) /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:270:7
#2 0x4e9c11 in toml::internal::Parser::nextValue() /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:347:31
#3 0x4e9c11 in toml::internal::Parser::consumeForValue(toml::internal::TokenType) /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:1740:9
#4 0x4eb186 in toml::internal::Parser::parseArray(toml::Value*) /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:1966:10
#5 0x4ea364 in toml::internal::Parser::parseValue(toml::Value*) /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:1919:16
#6 0x4eb4b2 in toml::internal::Parser::parseArray(toml::Value*) /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:1978:14
#7 0x4ea364 in toml::internal::Parser::parseValue(toml::Value*) /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:1919:16
#8 0x4eb4b2 in toml::internal::Parser::parseArray(toml::Value*) /home/yzy/fuzzsoftware/tinytoml/src/../include/toml/toml.h:1978:14
SUMMARY: AddressSanitizer: stack-overflow (/home/yzy/fuzzsoftware/tinytoml/out/Debug/parse_file+0x4982e9) in __asan_memcpy
==18948==ABORTING
tinytoml/out/Debug/parse_file ./POC
Ubuntu 20.04
CLang 10.0.1
tinytoml Version:ea34092
Hello,
Love this parser. Do you have plans to support hex/binary inputs for integers? I can write it if you think it's a good idea. Let me know.
Hello,
I'd like to use your code in a personal project. Would you be able to tag a release so that I can more-easily avoid breaking changes/updates? I'd like to pin my project to a specific version of your library and I'd like to avoid embedding 'master' or an ugly hash in my build system.
Thanks!
Using tinytoml to write a toml document, I am wondering if it is possible to specify that a nested table should be inline? Tinytoml has absolutely no problem reading inline tables, but in the following example it would be desirable to have it write size = { width = 800, height = 600 }
std::ofstream ofs(path);
toml::Table root;
toml::Table sceneValue = toml::Table();
sceneValue["name"] = scene.name;
// would be nice to have this table written inline
toml::Table sizeValue = toml::Table();
sizeValue["width"] = scene.width;
sizeValue["height"] = scene.height;
sceneValue["size"] = sizeValue;
root["scene"] = sceneValue;
ofs << root;
ofs.close();
So the desired output is:
[scene]
name = "Main Menu"
size = { width = 800, height = 600 }
First off, thanks for your work here. Great library.
I was having trouble with line toml.h:831
tp += std::chrono::microseconds(static_cast<int>(std::round(ss * 1000000)));
It seems std::round (a C++11 feature) has a variety of support issues. It appears visual studio hadn't implemented it as of 2012. And the issue I ran into: building with GCC 4.9.3 for cygwin, std::round
is undefined (a bug), but round
(no namespace) is, and works (it also builds without std::
using GCC 5.1.0 for mingw). It may thus be preferable to use this formulation, but it would be worth testing if this works under linux and visual studio. Alternatively, considering that computer clock precision is rarely in the 1 microsecond range, the round() call could be skipped altogether.
The other question is whether ss*1000000
could overflow if int is 32 bits (as is usually the case). It looks like not given how it's used, but on my platform anyway, microseconds appears to be using int64_t, so would it make sense to cast to that anyway?
It would be nice if my own code could access "typeToString()", for example when generating error messages in my own parsing code (e.x. Expected a 'string', but got 'table'). Is there a reason it was left private?
Hey! I want to use TinyTOML in my Qt project, I've added the line QMAKE_CXXFLAGS += -std=c++11
to set the flags for C++11.
Now when I start building I get the following error:
In file included from src/core/project.cpp:29:0:
src/core/../../externals/tinytoml/toml.h: In static member function 'static bool toml::Parser::parseTime(const string&, toml::Value*)':
src/core/../../externals/tinytoml/toml.h:829:58: error: 'timegm' was not declared in this scope
*v = std::chrono::system_clock::from_time_t(timegm(&t));
^
mingw32-make[1]: *** [debug/project.o] Error 1
Makefile.Debug:143: recipe for target 'debug/project.o' failed
mingw32-make[1]: Leaving directory 'C:/arden'
mingw32-make: *** [debug] Error 2
makefile:34: recipe for target 'debug' failed
[Finished in 2.5s]
How can I fix this?
~ Jan
Hey @mayah. I use this project a lot, and made a Conan recipe for it, now maintained by Bincrafters: https://github.com/bincrafters/conan-tinytoml. Thanks for making tinytoml! 🍻
In toml version 0.2.0, we don't need to consider timezone.
However, now we need to consider timezone when writing toml::Value back to a file.
We need to break backward compatibility to support it. Sigh.
If you have a plan but you don't have the time, I'd like to try it.
Hello! I’m trying to parse nested arrays but without success.
Example:
[[widgets]]
type = "image"
width = 1000
[[widgets.topics]]
topic = "some"
count = 3
[[widgets.topics]]
topic = "something"
count = 4
I am getting "Error: line 27: error when parsing group key" when I check if it's valid.
Line 27 in my toml file is "topic = "some"".
Derived from #26.
Use sscanf_s instead of disabling warning? This seems better for me.
Hi,
With Visual Studio 2015, the following code :
{
std::ifstream ifs(<utf-8 file with BOM marker>);
toml::ParseResult pr = toml::parse(ifs);
// ...
}
raised this assertion in the crt:
File: minkernel\crts\ucrt\src\appcrt\convert\isctype.cpp
Line: 36
Expression: c >= -1 && c <= 255
in this line,
while (current(&c) && (isalnum(c) || c == '_' || c == '-')) {
of the Lexer::nextKey() function, when the 3 char of the UTF-8 BOM is present in front of the stream.
The code works well when the BOM is not present.
This workaround resolved the problem for me:
{
// ...
std::filebuf* pbuf = ifs.rdbuf();
unsigned char cUTF8_BOM[3];
pbuf->sgetn((char *)cUTF8_BOM, sizeof(cUTF8_BOM));
// UTF-8 BOM?
const unsigned char g_UTF8_BOM[3] = { 0xEF, 0xBB, 0xBF };
if ((g_UTF8_BOM[0] == cUTF8_BOM[0]) && (g_UTF8_BOM[1] == cUTF8_BOM[1]) && (g_UTF8_BOM[2] == cUTF8_BOM[2]))
pbuf->pubseekpos(sizeof(g_UTF8_BOM), std::ios_base::cur);
// ...
}
But I believe it could be easily fixed in your library.
Sincerely.
Hi, I'm getting some weird output when trying to write 2-dimensional arrays with objects/tables inside. I'm trying to save the equivalent of JSON {"A": [ [ {"value": 1} ] ] }
.
My code:
toml::Value base;
toml::Array outer;
toml::Array inner;
toml::Value object;
object["value"] = 1;
inner.push_back(object);
outer.push_back(inner);
base["A"] = outer;
base.write(&std::cout);
The code produces:
A = [[value = 1
]]
and toml::parse()
flags this as invalid.
Could the curly braces be missing for a correct inline table? I.e.
A = [[{value = 1}]]
Or is there something I should do differently in the code?
Thanks,
Michael
It will be convenient for users to know what version we are using.
It would be nice if there were an easier way to get the elements from a toml::Array
. Since an Array is just a std::vector<toml::Value>
, you have to manually convert each Value
element to the underlying type.
I would like to be able to do something like this:
toml::Value v = ...;
toml::Array arr = v.get<toml::Array>("foo");
std::vector<int> int_vec = toml::array_convert<int>(arr);
// or maybe add an additional template argument:
std::vector<int> arr = v.get<toml::Array, int>("foo");
Would something like this be a good candidate for the library?
Perhaps another option would be to make Array
a class and not an alias for vector, and then you could add is<T>()
and as<T>()
methods similar to toml::Value
.
Hi,
As TOML v0.4.0 specify that "Key/value pairs within tables are not guaranteed to be in any specific order.", wouldn't be better if tinytoml represented tables internally using std;;unordered_map instead of std::map?
Thanks.
Currently passing failed/bad stream results in successful parsing(which actually parses nothing at all).
Simple case would be pass ifstream to non-existing fail
std::ifstream ifs("foo.toml");
toml::ParseResult pr = toml::parse(ifs);
if (!pr.valid()) {
cout << pr.errorReason << endl;
return;
}
It is a bit tricky as it should be up to user to provide a valid output.
But on other hand there is no way it would be possible parse failed/bad stream.
What do you think?
Should there be error on such cases?
hardware_scheme.toml
[DRV8830]
x = [4, 30]
y = [5, 30]
z = [6, 30]
[MMC]
s1 = 0
s2 = 1
s3 = 2
[MUX]
path = "/dev/i2c-"
[GAINS]
xyz = [0.29, 0.29, 0.34]
xyz_ohms = [25, 25, 27]
[CALS]
s1 = [0, 0, 0, 0, 0, 0, 0, 0, 0] # 9 dobule array for calibration and rotation of values
s2 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
s3 = [0, 0, 0, 0, 0, 0, 0, 0, 0]
[FILTER]
w = [1] # array of max length
[TESTING]
target = "127.0.0.1"
port = 7777
[MISC]
rate = 10000
gdb debug info
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from simdot...done.
(gdb) run ../src/hardware_scheme.toml
Starting program: /home/debian/Bdot-Controller/binaries/simdot ../src/hardware_scheme.toml
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
Parsing Config File
Loaded TOML Tables
Program received signal SIGSEGV, Segmentation fault.
0x0040ba18 in toml::Value::type (this=0x0) at toml.h:108
108 Type type() const { return type_; }
(gdb)
build script:
#!/bin/bash
export CC="g++"
echo "Building Simulation Software"
$CC -w -g bdot_testing.cpp -lzmq -lfmt -li2c -I ../eigen-3.4.0 -lpthread --std=c++11 -o ../binaries/simdot
Does anyone have any solutions to this? Am I missing a compile flag?
It is not in my actual code, the error comes from line 108 of toml.h.
Any help would be appreciated!
A new TOML spec version has been released.
While the progress on tinytoml grew silent in the last months, are you still planning to support TOML v5.0?
Hi,
I have found a bug when I fuzzing . When I enter an input file to a program use toml.h with parseFile, it cause a stack-overflow at parseFile function. I think there maybe too much loop or other bug cause this . my stack size is 8192kbs.
I know that we can avoid it by ulimit -s , but I think parse a toml file about 32k that cause 8M stack overflow maybe not a good way. If I make a file follow some pattern , the file may be minimized and smaller than 10k.
Here is the backtrace:
#0 __asan_memset ()
at /src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:26
#1 std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__zero() () at /usr/local/bin/../include/c++/v1/string:1563
#2 std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string() () at /usr/local/bin/../include/c++/v1/string:1812
#3 toml::internal::Token::Token(toml::internal::TokenType) () at ./include/toml/toml.h:272
#4 toml::internal::Lexer::nextToken(bool) () at ./include/toml/toml.h:1022
#5 toml::internal::Lexer::nextValueToken() () at ./include/toml/toml.h:967
#6 toml::internal::Parser::nextValue() () at ./include/toml/toml.h:347
#7 toml::internal::Parser::consumeForValue(toml::internal::TokenType) ()
at ./include/toml/toml.h:1740
(and maybe 20000 times repeat below two lines)
toml::internal::Parser::parseArray(toml::Value*) () at ./include/toml/toml.h:1978
toml::internal::Parser::parseValue(toml::Value*) () at ./include/toml/toml.h:1919
and this below:
toml::internal::Parser::parseKeyValue(toml::Value*) () at ./include/toml/toml.h:1883
toml::internal::Parser::parse() () at ./include/toml/toml.h:1790
toml::parse(std::__1::basic_istream<char, std::__1::char_traits<char> >&) ()
at ./include/toml/toml.h:385
toml::parseFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) () at ./include/toml/toml.h:401
LLVMFuzzerTestOneInput () at /src/parse_file.cc:16
fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) ()
RunOneTest () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:323
fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) ()
main () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
the testcase I use is like parse_file.cc in your project. you can just compile use your code and input my file to the parse_file. stack size is 8192kbs. And you will get a segment fault caused by stack overflow. I have upload the file causes this.
crashcase.zip
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.