# Every subdirectory with source files must be described here
SUBDIRS := \
-src \
+source \
# -include src/subdir.mk
# Add inputs and outputs from these tool invocations to the build variables
-CPP_SRCS += \
-../src/main/main.cpp \
-../src/comfun.cpp \
-../src/testcase.cpp \
-../src/httpserver.cpp \
-../src/json/json_reader.cpp \
-../src/json/json_value.cpp \
-../src/json/json_writer.cpp
+#CPP_SRCS += \
+../source/main/main.cpp \
+../source/comfun.cpp \
+../source/testcase.cpp \
+../source/httpserver.cpp \
+../source/json/json_reader.cpp \
+../source/json/json_value.cpp \
+../source/json/json_writer.cpp
OBJS += \
-./src/main/main.o \
-./src/comfun.o \
-./src/testcase.o \
-./src/httpserver.o \
-./src/json/json_reader.o \
-./src/json/json_value.o \
-./src/json/json_writer.o
+./source/main/main.o \
+./source/comfun.o \
+./source/testcase.o \
+./source/httpserver.o \
+./source/json/json_reader.o \
+./source/json/json_value.o \
+./source/json/json_writer.o
-CPP_DEPS += \
-./src/main/main.d \
-./src/comfun.d \
-./src/testcase.d \
-./src/httpserver.d \
-./src/json/json_reader.d \
-./src/json/json_value.d \
-./src/json/json_writer.d
+#CPP_DEPS += \
+./source/main/main.d \
+./source/comfun.d \
+./source/testcase.d \
+./source/httpserver.d \
+./source/json/json_reader.d \
+./source/json/json_value.d \
+./source/json/json_writer.d
# Each subdirectory must supply rules for building sources it contributes
-src/%.o: ../src/%.cpp
+source/%.o: ../source/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: C++ Compiler'
$(CC) -I"pch" -D_DEBUG -O0 -g3 -Wall -c -fmessage-length=0 $(INCLUDE_PATH) $(INCLUDES) $(CFLAG) -D_APP_LOG -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
# Add inputs and outputs from these tool invocations to the build variables
# All Target
-all: httpserver secondary-outputs
+all: testkit-stub secondary-outputs
init:
- mkdir -p src/json
- mkdir -p src/main
+ mkdir -p source/json
+ mkdir -p source/main
# Tool invocations
-httpserver: init $(OBJS) $(USER_OBJS)
+testkit-stub: init $(OBJS) $(USER_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: C++ Linker'
- $(CC) -o"httpserver" $(OBJS) $(USER_OBJS) $(LIBS) $(LFLAG)
+ $(CC) -o"testkit-stub" $(OBJS) $(USER_OBJS) $(LIBS) $(LFLAG)
@echo 'Finished building target: $@'
@echo ' '
# Other Targets
clean:
- -$(RM) src httpserver
+ -$(RM) source testkit-stub
secondary-outputs: $(MO_FILES) $(EDJ_FILES)
--- /dev/null
+TCT-stub
+========
+
+Intel Tizen Compatibility Test Stub
+
+###to build and install x86 version on linux pc,###
+1, make
+
+2, sudo make install
+
+
+
+###to build ARM version locally(without OBS), please make sure ###
+
+1, install tizen2.0 SDK with all component selected,
+
+2, replace all "/home/danny/" in file "CommandLineBuild/build_data" with your own home path, such as "/home/test/"
+
+3, run native-make -t device in CommandLineBuild folder.
+
+
+to build unit test, just run "make ut" in root folder of the project. then run valgrind to check memory leak.
+
+valgrind --tool=memcheck --leak-check=yes --track-origins=yes -v ./ut
+
+###to build on windows###
+1, use git bash to maintain code
+
+2, use msys and mingw to compile
+
+3, to build the target, run "make win"
+
+###for Android###
+1, for x86 device, run "make android"
+
+2, for ARM or mips, install Android NDK at first, then run ndk-build in jni folder
+
+3, use eclipse+ADT to import android project from TCT-stub folder, build apk file for wrapper app of stub in android target
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="testkit.stub"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <uses-sdk android:minSdkVersion="4" />
+
+ <application
+ android:debuggable="false"
+ android:theme="@android:style/Theme"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".TestkitStub"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+../libs/
\ No newline at end of file
--- /dev/null
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -fexceptions
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include
+LOCAL_MODULE := testkit-stub
+LOCAL_SRC_FILES := ../../source/comfun.cpp ../../source/httpserver.cpp ../../source/testcase.cpp ../../source/main/main.cpp ../../source/json/json_reader.cpp ../../source/json/json_value.cpp ../../source/json/json_writer.cpp
+include $(BUILD_EXECUTABLE)
--- /dev/null
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS += -fexceptions
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include
+LOCAL_MODULE := testkit-stub
+LOCAL_SRC_FILES := ../../source/comfun.cpp ../../source/httpserver.cpp ../../source/testcase.cpp ../../source/main/main.cpp ../../source/json/json_reader.cpp ../../source/json/json_value.cpp ../../source/json/json_writer.cpp
+include $(BUILD_EXECUTABLE)
--- /dev/null
+# Build both ARMv5TE and ARMv7-A machine code.
+APP_ABI := armeabi armeabi-v7a x86 mips
+APP_STL := gnustl_static
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-15
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">testkit-stub</string>
+</resources>
--- /dev/null
+/*
+ * Copyright (C) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package testkit.stub;
+
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import android.app.Activity;
+import android.os.Build;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class TestkitStub extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ TextView tv = new TextView(this);
+ tv.setClickable(false);
+ setContentView(tv);
+
+ String stub = "testkit-stub";
+ String path = getFilesDir().getPath() + "/";
+ try {// if can't open, then create it
+ FileInputStream fis = openFileInput(stub);
+ try {fis.close();} catch (IOException e) {}
+ } catch (FileNotFoundException e1) {
+ try {
+ InputStream input = getAssets().open("bins/" + Build.CPU_ABI + "/" + stub); // create stub according to ABI
+ FileOutputStream fo = openFileOutput(stub, 0);
+ int length = input.available();
+ byte [] buffer = new byte[length];// how to delete buffer?
+ input.read(buffer);
+ input.close();
+ fo.write(buffer);
+ fo.flush();
+ fo.close();
+ //getAssets().close(); // this will cause fc if launch again
+ Runtime.getRuntime().exec("chmod 744 " + path + stub);
+ } catch (IOException e) {
+ tv.setText(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ try {
+ Process p = Runtime.getRuntime().exec(path + stub);
+ String line = "", res = "";
+
+ InputStream input = p.getInputStream();
+ DataInputStream osRes = new DataInputStream(input);
+ while((line = osRes.readLine()) != null) res += line + "\n";
+ osRes.close();
+ input.close();
+
+ input = p.getErrorStream();
+ osRes = new DataInputStream(input);
+ while((line = osRes.readLine()) != null) res += line + "\n";
+ osRes.close();
+ input.close();
+
+ tv.setText(res);
+ } catch (IOException e) {
+ tv.setText(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
#include <stdio.h>
#include <string.h>
#include <string>
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
#include <stdio.h>
#include <fstream>
#include <string.h>
bool get_auto_case(string content, string *type);
void checkResult(TestCase* testcase);
void killAllWidget();
- void start_client();
- bool run_cmd(string cmdString, string expectString, bool showcmdAnyway);
+ //void start_client();
+ bool run_cmd(string cmdString, string expectString, std::vector<string> *output);
void print_info_string(int case_index);
- void find_purpose(Json::Value paras, bool auto_test);
+ void find_id(Json::Value paras, bool auto_test);
void getCurrentTime();
void cancel_time_check();
void set_timer(int timeout_value);
- void getAllWidget();
Json::Value splitContent(string content);
+ void timeout_action();
+#if defined(__WIN32__) || defined(__WIN64__)
+#else
struct sigaction sa;
struct itimerval timer;
+#endif
int gIsRun;
- int clientsocket;
-
- int gServerStatus;
string m_exeType; //auto;manual
TestCase *m_test_cases; //the case array
Json::Value m_capability;
//TestStatus
int m_timeout_count; // continusously time out count
+ Json::Value m_result;
int m_killing_widget;
- std::vector<string> m_widgets; // store all the widgets short name
-
string m_running_session;
string m_last_auto_result;
int m_failto_launch; // time of fail to launch
-
- bool m_rerun; // true when re-run a case
+ int m_max_fail_launch;
//some variables get from cmd line
- bool g_show_log;
int g_port;
string g_launch_cmd;
string g_kill_cmd;
string g_launcher;//lancher name:wrt-launcher/browser
string m_suite_name;
+ string m_suite_id;
bool g_run_wiget;//whether run on the device with wiget
-
- ofstream outputFile;
};
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
#include <stdio.h>
#include <string.h>
string start_at;
string end_at;
string std_out;
- bool is_executed;
// below m_case are sent from Com-module for each case.
Json::Value m_case;
- string purpose;
string case_id;
int timeout_value;
-TARGET = httpserver
+TARGET = testkit-stub
+WIN_TARGET = testkit-stub.exe
UT_TARGET = ut
-OBJ_PATH = objs
+OBJ_PATH = obj
PREFIX_BIN =
CC = g++
LIBS =
CFLAGS =-Wall -Werror
LINKFLAGS = -lpthread
+WIN_LINKFLAGS = -lpthread -lwsock32 -static
+ANDROID_LINKFLAGS = -lpthread -static
-JSON_SRCDIR = src/json
-SERVER_SRCDIR = src
-MAIN_SRCDIR = src/main
-UT_SRCDIR = src/ut
+SERVER_SRCDIR = source
+JSON_SRCDIR = $(SERVER_SRCDIR)/json
+MAIN_SRCDIR = $(SERVER_SRCDIR)/main
+UT_SRCDIR = $(SERVER_SRCDIR)/ut
JSON_SOURCES = $(foreach d,$(JSON_SRCDIR),$(wildcard $(d)/*.cpp) )
JSON_OBJS = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(JSON_SOURCES))
UT_OBJS = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(UT_SOURCES))
default:init compile
+win:init win_compile
+android:init android_compile
ut:init ut_compile
ut: CC += -DDEBUG -g
debug: CC += -DDEBUG -g
compile:$(JSON_OBJS) $(SERVER_OBJS) $(MAIN_OBJS)
$(CC) $^ -o $(TARGET) $(LINKFLAGS) $(LIBS)
+win_compile:$(JSON_OBJS) $(SERVER_OBJS) $(MAIN_OBJS)
+ $(CC) $^ -o $(WIN_TARGET) $(WIN_LINKFLAGS) $(LIBS)
+
+android_compile:$(JSON_OBJS) $(SERVER_OBJS) $(MAIN_OBJS)
+ $(CC) $^ -o $(TARGET) $(ANDROID_LINKFLAGS) $(LIBS)
+
clean:
rm -rf $(OBJ_PATH)
rm -f $(TARGET)
+ rm -f $(WIN_TARGET)
rm -f $(UT_TARGET)
+ rm -fr bin
+ rm -fr gen
install: $(TARGET)
- #cp $(TARGET) $(PREFIX_BIN)
install -d $(DESTDIR)/usr/bin/
install -m 755 $(TARGET) $(DESTDIR)/usr/bin/
uninstall:
- rm -f $(PREFIX_BIN)/$(TARGET)
+ rm /usr/bin/$(TARGET)
rebuild: clean compile
Name: testkit-stub
Summary: test
-Version: 1.3
+Version: 1.0
Release: 1
Group: Development/Debug
License: GPL v2 only
%files
%defattr(-,root,root,-)
# >> files
-%{_bindir}/httpserver
+%{_bindir}/testkit-stub
# << files
Name: testkit-stub
Summary: test
-Version: 1.3
+Version: 1.0
Release: 1
Group: Development/Debug
License: GPL v2 only
%files
%defattr(-,root,root,-)
# >> files
-%{_bindir}/httpserver
+%{_bindir}/testkit-stub
# << files
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <stdio.h>
+#include "comfun.h"
+
+ComFun::ComFun() {
+
+}
+ComFun::~ComFun() {
+
+}
+
+char ComFun::CharToInt(char ch) {
+ if (ch >= '0' && ch <= '9')
+ return (char) (ch - '0');
+ if (ch >= 'a' && ch <= 'f')
+ return (char) (ch - 'a' + 10);
+ if (ch >= 'A' && ch <= 'F')
+ return (char) (ch - 'A' + 10);
+ return -1;
+}
+
+char ComFun::StrToBin(char *str) {
+ char tempWord[2];
+ char chn;
+ tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011
+ tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000
+ chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000
+ return chn;
+}
+//url decode
+char* ComFun::UrlDecode(const char *str) {
+ char tmp[2];
+ int i = 0, len = strlen(str);
+ char *output = new char[len + 1];
+ memset(output, 0, len + 1);
+ int j = 0;
+ while (i < len) {
+ if (*(str + i) == '%') {
+ tmp[0] = *(str + i + 1);
+ tmp[1] = *(str + i + 2);
+ *(output + j) = StrToBin(tmp);
+ i = i + 3;
+ j++;
+ } else if (*(str + i) == '+') {
+ *(output + j) = ' ';
+ i++;
+ j++;
+ } else {
+ *(output + j) = *(str + i);
+ i++;
+ j++;
+ }
+ }
+ return output;
+}
+
+//split function for string
+std::vector<std::string> ComFun::split(std::string str, std::string pattern) {
+ std::string::size_type pos;
+ std::vector < std::string > result;
+ str += pattern; //extend string so that operate easyly
+ unsigned int size = str.size();
+ int count = 0;
+ for (unsigned int i = 0; i < size; i++) {
+ if ((pattern == "=")&&(count == 1)){
+ std::string s = str.substr(i, size-1-i);
+ result.push_back(s);
+ break;
+ }
+ pos = str.find(pattern, i);
+ if (pos < size) {
+ std::string s = str.substr(i, pos - i);
+ result.push_back(s);
+ i = pos + pattern.size() - 1;
+ }
+ count++;
+ }
+ return result;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sstream>
+
+#include "httpserver.h"
+
+#if defined(__WIN32__) || defined(__WIN64__)
+# include <winsock2.h>
+# define sleep(n) Sleep(1000 * (n))
+ struct Timer_thread_info { /* Used as argument to thread */
+ pthread_t thread_id; /* ID returned by pthread_create() */
+ int timeout;
+ };
+ Timer_thread_info timer_thread_info;
+
+void* win_timer_callback(void* para) {
+ Timer_thread_info *tinfo = (Timer_thread_info *) para;
+ pthread_testcancel();
+ sleep(tinfo->timeout);
+ pthread_testcancel();
+ timer_handler(0);
+ pthread_exit (NULL);
+ return 0;
+}
+
+#else
+# include <sys/socket.h>
+# include <sys/ioctl.h>
+# include <unistd.h>
+# include <arpa/inet.h>
+ struct sigaction sa;
+ struct itimerval timer;
+#endif
+
+#include <json/json.h>
+#include "comfun.h"
+
+#define MAX_BUF 300000
+
+#define GET 0
+#define HEAD 2
+#define POST 3
+#define BAD_REQUEST -1
+
+extern bool g_show_log;
+bool g_openlog_fail = false;
+#ifndef DBG_ONLY
+ #define DBG_ONLY(x) {if (g_openlog_fail) cout << x << endl; else outputFile << x << endl;}
+#endif
+
+#if defined(DEBUG) | defined(_DEBUG)
+ #define SHOW_FORCE true
+#else
+ #define SHOW_FORCE false
+#endif
+
+ofstream outputFile;
+HttpServer httpserver;
+int serversocket;
+
+struct thread_info { /* Used as argument to thread */
+ pthread_t thread_id;/* ID returned by pthread_create() */
+ int clientsocket;
+ HttpServer *server;
+};
+
+pthread_mutex_t result_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int g_error_code = 0;
+
+HttpServer::HttpServer() {
+ m_test_cases = NULL;
+ m_exeType = "auto"; // set default to auto
+ m_totalBlocks = 0;
+ m_current_block_index = 1;
+ m_totalcaseCount = 0;
+ m_block_case_index = 0;
+ m_block_case_count = 0;
+ m_total_case_index = 0;
+ m_last_auto_result = "N/A";
+ m_running_session = "";
+ m_server_checked = false;
+ m_check_times = 0;
+ g_port = 8000; // if use 8080 for server_port, it will not work with chrome
+ g_run_wiget = false;
+ g_launcher = "";
+ m_block_finished = true;
+ m_set_finished = true;
+ m_timeout_count = 0;
+ m_failto_launch = 0;
+ m_max_fail_launch = 3;
+ m_killing_widget = false;
+ m_suite_name = "";
+ m_suite_id = "";
+
+#if defined(__WIN32__) || defined(__WIN64__)
+#else
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = timer_handler;
+ sa.sa_flags = SA_RESTART;
+ sigaction(SIGALRM, &sa, NULL);
+#endif
+
+ if(SHOW_FORCE) g_show_log = true;
+}
+
+HttpServer::~HttpServer() {
+ if (m_test_cases) {
+ delete[] m_test_cases;
+ m_test_cases = NULL;
+ }
+ if(g_show_log) outputFile.close();
+}
+
+// generate response code. send response
+void HttpServer::sendresponse(int s, int code, struct HttpRequest *prequest,
+ string content) {
+ string buffer;
+ stringstream len_stream;
+ len_stream << content.length();
+ prequest->responsecode = code;
+ // generate response head
+ switch (code) {
+ case 200: {
+ buffer =
+ "HTTP/1.1 200 OK\r\nServer: testkit-stub/1.0\r\nContent-Type: "
+ + prequest->prefix
+ + "\r\nAccept-Ranges: bytes\r\nContent-Length: "
+ + len_stream.str()
+ + "\r\nConnection: close\r\nAccess-Control-Allow-Origin: *\r\n\r\n"
+ + content;
+ break;
+ }
+ default:
+ break;
+ }
+
+ // send out the http response
+ send(s, buffer.c_str(), buffer.length(), 0);
+}
+
+// parse the http request
+int HttpServer::getrequest(string requestbuf, struct HttpRequest *prequest) {
+ std::vector < std::string > splitstr = ComFun::split(requestbuf, " ");
+ if (splitstr.size() >= 2) {
+ prequest->method = splitstr[0];
+ prequest->path = splitstr[1];
+ }
+
+ if (prequest->path.find('?') == string::npos) {
+ //get the com module send data
+ int content_index = requestbuf.find("\r\n\r\n", 0);
+ if (content_index > -1) {
+ prequest->content = requestbuf.substr(
+ content_index + strlen("\r\n\r\n"));
+ }
+ } else {
+ int session_index = prequest->path.find("?");
+ prequest->content = prequest->path.substr(session_index + 1);
+ }
+ if (prequest->method == "GET") {
+ return GET;
+ } else if (prequest->method == "POST") {
+ return POST;
+ }
+ return -1;
+}
+
+// parse the test case data sent by com-module with init_test cmd
+void HttpServer::parse_json_str(string case_node) {
+ Json::Reader reader;
+ Json::Value value;
+
+ bool parsed = reader.parse(case_node, value);
+ if (!parsed) // try to parse as a file if parse fail
+ { // "test.json" is for verify
+ if(g_show_log) DBG_ONLY(case_node);
+ std::ifstream test(case_node.c_str(), std::ifstream::binary);
+ parsed = reader.parse(test, value, false);
+ }
+
+ if (parsed) {
+ m_totalBlocks = atoi(value["totalBlk"].asString().c_str());
+ m_current_block_index = atoi(value["currentBlk"].asString().c_str());
+ m_totalcaseCount = atoi(value["casecount"].asString().c_str());
+ m_exeType = value["exetype"].asString();
+
+ const Json::Value arrayObj = value["cases"];
+ m_block_case_count = arrayObj.size();
+
+ if (m_test_cases) {
+ delete[] m_test_cases;
+ m_test_cases = NULL;
+ }
+ m_test_cases = new TestCase[m_block_case_count];
+
+ for (int i = 0; i < m_block_case_count; i++) {
+ m_test_cases[i].init(arrayObj[i]);
+ }
+ }
+}
+
+void HttpServer::cancel_time_check() {
+#if defined(__WIN32__) || defined(__WIN64__)
+ if (timer_thread_info.thread_id.p) {
+ pthread_cancel(timer_thread_info.thread_id);
+ memset(&timer_thread_info.thread_id, 0, sizeof(timer_thread_info.thread_id));
+ }
+#else
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = 0;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 0;
+ int ret = setitimer(ITIMER_REAL, &timer, NULL); // set timer with value 0 will stop the timer
+ if ((ret < 0) && (g_show_log))
+ DBG_ONLY("fail to cancel timer !!!");
+ // refer to http://linux.die.net/man/2/setitimer, each process only have 1 timer of the same type.
+#endif
+}
+
+// set timeout value to 90 seconds for each case
+void HttpServer::set_timer(int timeout_value) {
+#if defined(__WIN32__) || defined(__WIN64__)
+ cancel_time_check(); // clear timer if any
+ timer_thread_info.timeout = timeout_value;
+ pthread_create(&timer_thread_info.thread_id, NULL, win_timer_callback, &timer_thread_info);
+#else
+ timer.it_value.tv_sec = timeout_value;
+ timer.it_value.tv_usec = 0;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 0;
+ int ret = setitimer(ITIMER_REAL, &timer, NULL);
+ if ((ret < 0) && (g_show_log))
+ DBG_ONLY("fail to set timer !!!");
+#endif
+}
+
+Json::Value HttpServer::splitContent(string content) {
+ Json::Value httpParas;
+ if (content != "") {
+ std::vector < std::string > splitstr = ComFun::split(content, "&");
+ for (unsigned int i = 0; i < splitstr.size(); i++) {
+ vector < string > resultkey = ComFun::split(splitstr[i], "=");
+ char* tmp = ComFun::UrlDecode(resultkey[0].c_str());
+ string key = tmp;
+ delete[] tmp; // free memory from comfun
+ if (resultkey[1] != "") {
+ tmp = ComFun::UrlDecode(resultkey[1].c_str());
+ string value = tmp;
+ delete[] tmp; // free memory from comfun
+ httpParas[key] = value;
+ }
+ else httpParas["myContent"] = key;
+ }
+ if(g_show_log)
+ DBG_ONLY(httpParas.toStyledString());
+ }
+ return httpParas;
+}
+
+/** send out response according to different http request.
+a typical workflow of auto case would be
+/check_server_status (by com-module)
+/init_test (by com-module)
+/set_testcase (by com-module)
+/check_server (by widget)
+/init_session_id?session_id=2033 (by widget)
+/auto_test_task?session_id=2033 (by widget)
+/check_execution_progress?session_id=2033 (by widget)
+/ask_next_step?session_id=2033 (by widget)
+/commit_result (by widget)
+/auto_test_task?session_id=2033 (by widget)
+/manual_cases (by widget)
+/generate_xml (by widget)
+/check_server_status (by com-module)
+/get_test_result (by com-module)
+
+
+a typical workflow of manual case would be
+/check_server_status (by com-module)
+/init_test (by com-module)
+/set_testcase (by com-module)
+/check_server (by widget)
+/init_session_id?session_id=2033 (by widget)
+/auto_test_task?session_id=2033 (by widget)
+/manual_cases (by widget)
+/check_server_status (by com-module)
+/commit_manual_result (by widget)
+...
+/check_server_status (by com-module)
+/commit_manual_result (by widget)
+/generate_xml (by widget)
+/get_test_result (by com-module)
+
+**/
+void HttpServer::processpost(int s, struct HttpRequest *prequest) {
+ prequest->prefix = "application/json";
+ string json_str = "{\"OK\":1}";
+
+#if defined(__WIN32__) || defined(__WIN64__)
+ cout << "prequest->path is:" << prequest->path << endl;
+ cout << "prequest->content is:" << prequest->content << endl;
+#else
+ if(g_show_log) {
+ DBG_ONLY("prequest->path is:" << prequest->path);
+ DBG_ONLY("prequest->content is:" << prequest->content);
+ }
+#endif
+
+ if (prequest->path.find("/init_test") != string::npos) {// invoke by com-module to init some para for test
+ Json::Reader reader;
+ Json::Value value;
+ if(g_show_log)
+ DBG_ONLY("[ init the test suite ]");
+
+ bool parsed = reader.parse(prequest->content, value);
+ if (parsed) {
+ g_launcher = value["launcher"].asString();
+ m_suite_name = value["suite_name"].asString();
+ if (g_launcher == "wrt-launcher")
+ {
+ g_run_wiget = true;
+ m_suite_id = value["suite_id"].asString();
+
+ g_launch_cmd = g_launcher + " -s " + m_suite_id;
+ g_kill_cmd = g_launcher + " -k " + m_suite_id;
+ killAllWidget();
+ }
+ else if (g_launcher == "xwalk") {// xwalk on android
+ g_run_wiget = false;
+ //am start -n org.xwalk.tct-2dtransforms-css3-tests/.tct-2dtransforms-css3-testsActivity
+ //g_launch_cmd = "am start -n org.xwalk." + m_suite_name + "/." + m_suite_name + "Activity";
+ //g_kill_cmd = "am force-stop org.xwalk." + m_suite_name;
+ g_launch_cmd = "";
+ g_kill_cmd = "";
+ }
+ else
+ {
+#if defined(__WIN32__) || defined(__WIN64__)
+ g_launch_cmd = "start /b " + g_launcher;
+ g_kill_cmd = "";
+#else
+ g_launch_cmd = g_launcher + " &";
+ if (g_launcher.find("xwalk") != string::npos) //kill xwalk
+ g_kill_cmd = "pkill xwalk";
+ //g_kill_cmd = "ps ax | grep xwalk | grep -v testkit-lite | grep -v grep | awk '{print $1F}' | xargs kill -9;";
+ else g_kill_cmd = ""; // not kill browser
+#endif
+ g_run_wiget = false;
+ //wait for the index window.close, otherwise will occur bind aleady error
+ sleep(1);
+ }
+ }
+ else {
+ if(g_show_log){
+ DBG_ONLY("error while parse para from com-module, can't start test");
+ DBG_ONLY(prequest->content);
+ }
+ json_str = "{\"Error\":\"parse error\"}";
+ }
+ } else if (prequest->path.find("/set_testcase") != string::npos) {// invoke by com-module to send testcase data
+ m_block_finished = false;
+ m_set_finished = false;
+ m_timeout_count = 0;
+ m_server_checked = false;
+ if(g_show_log)
+ DBG_ONLY("[ set test cases ]");
+ parse_json_str(prequest->content);
+
+ //start_client();
+// if(g_run_wiget == true)//not set timeout when run on browser
+ set_timer(20); // set timer here incase widget hang.
+ m_check_times = 0;
+
+ m_block_case_index = 0;
+ if (m_current_block_index == 1)
+ m_total_case_index = 0;
+ } else if (prequest->path == "/check_server") {// invoke by index.html to find server running or not
+ m_server_checked = true;
+ m_check_times = 0;
+ cancel_time_check();
+ if(g_show_log)
+ DBG_ONLY("[ checking server, and found the server is running ]");
+ } else if (prequest->path == "/check_server_status") {// invoke by com-module to get server status
+ Json::Value status;
+ status["block_finished"] = m_block_finished ? 1 : 0;
+ status["finished"] = m_set_finished ? 1 : 0;
+ if (m_failto_launch > m_max_fail_launch) {
+ status["error_code"] = 2;
+ status["finished"] = 1; // finish current set if can't launch widget
+ }
+ else if (g_error_code > 0) {
+ status["error_code"] = g_error_code;
+ g_error_code = 0;
+ }
+
+ pthread_mutex_lock( &result_mutex );
+ char count[8];
+ memset(count, 0, 8);
+ sprintf(count, "%d", m_result.size());
+ status["count"] = count;
+ status["cases"] = m_result;
+ m_result.clear();
+ pthread_mutex_unlock( &result_mutex );
+
+ json_str = status.toStyledString();
+
+ if (!m_server_checked) {
+ if(g_show_log)
+ DBG_ONLY("wait for widget check_server, please check on device." << endl);
+ }
+ if (m_totalBlocks > 0)
+ {
+ if(g_show_log)
+ DBG_ONLY("group: " << m_current_block_index << "/" << m_totalBlocks << ", total case: " << m_total_case_index << "/" << m_totalcaseCount << ", group case: " << m_block_case_index << "/" << m_block_case_count << ", m_timeout_count:" << m_timeout_count);
+ if (m_exeType != "auto") {
+ if(g_show_log)
+ DBG_ONLY("manual cases. please check on device." << endl);
+ }
+ }
+ } else if (prequest->path == "/shut_down_server") {
+ if (g_run_wiget == true)
+ killAllWidget(); // kill all widget when shutdown server
+ gIsRun = 0;
+ } else if (prequest->path.find("/init_session_id") != string::npos) {// invoke by index.html to record a session id
+ int index = prequest->path.find('=');
+ if (index != -1) {
+ m_running_session = prequest->path.substr(index + 1);
+ if(g_show_log)
+ DBG_ONLY("[ sessionID: " << m_running_session << " is gotten from the client ]");
+ } else {
+ if(g_show_log)
+ DBG_ONLY("[ invalid session id ]");
+ }
+ } else if (prequest->path.find("/ask_next_step") != string::npos) {// invoke by index.html to check whether there are more cases
+ if (m_block_finished || m_set_finished)
+ json_str = "{\"step\":\"stop\"}";
+ else
+ json_str = "{\"step\":\"continue\"}";
+
+ m_timeout_count = 0; // reset the timeout count
+ } else if (prequest->path.find("/auto_test_task") != string::npos) {// invoke by index.html to get current auto case
+ if (m_test_cases == NULL) {
+ json_str = "{\"Error\":\"no case\"}";
+ } else if (m_exeType != "auto") {
+ json_str = "{\"none\":0}";
+ } else {
+ string error_type = "";
+ bool find_tc = get_auto_case(prequest->content, &error_type);
+ if (find_tc == false) {
+ json_str = "{\"" + error_type + "\":0}";
+ } else {
+ json_str = m_test_cases[m_block_case_index].to_json().toStyledString();
+ }
+ }
+ } else if (prequest->path.find("/manual_cases") != string::npos) {// invoke by index.html to get all manual cases
+ cancel_time_check(); // should not timeout in manual mode
+ if (!m_test_cases) {
+ json_str = "{\"Error\":\"no case\"}";
+ } else if (m_exeType == "auto") {
+ json_str = "{\"none\":0}";
+ } else {
+ Json::Value arrayObj;
+ for (int i = 0; i < m_block_case_count; i++)
+ arrayObj.append(m_test_cases[i].to_json());
+
+ json_str = arrayObj.toStyledString();
+ set_timer(60); // check every 60 seconds to make sure widget alive when run manual cases.
+ }
+ } else if (prequest->path.find("/commit_manual_result") != string::npos) {// invoke by index.html to provide result of a manual case.
+ if ((prequest->content.length() == 0) || (!m_test_cases)) {
+ json_str = "{\"Error\":\"no manual result\"}";
+ } else {
+ find_id(splitContent(prequest->content), false); // will set index in find_id
+ }
+ } else if (prequest->path.find("/check_execution_progress") != string::npos) {//invoke by index.html to get test result of last auto case
+ char *total_count = new char[16];
+ sprintf(total_count, "%d", m_totalcaseCount);
+ char *current_index = new char[16];
+ sprintf(current_index, "%d", m_total_case_index + 1);
+
+ string count_str(total_count);
+ string index_str(current_index);
+ json_str = "{\"total\":" + count_str + ",\"current\":" + index_str
+ + ",\"last_test_result\":\"" + m_last_auto_result + "\"}";
+
+ delete[] total_count;
+ delete[] current_index;
+ }
+ //generate_xml:from index_html, a maually block finished when click done in widget, or no manual cases anymore(when run auto block)
+ else if (prequest->path == "/generate_xml") {
+ if (m_exeType != "auto") {
+ cancel_time_check();
+ m_block_finished = true;
+ if (m_current_block_index == m_totalBlocks)
+ m_set_finished = true;
+ }
+ }
+ //from com module,when m_set_finished is true
+ else if (prequest->path == "/get_test_result") {
+ cancel_time_check();
+ if (!m_test_cases) {
+ json_str = "{\"Error\":\"no case\"}";
+ } else {
+ Json::Value root;
+ root["count"] = "0";
+ root["cases"] = m_result;// m_result will always be empty here
+ json_str = root.toStyledString();
+ }
+ }
+ // index.html invoke this with id and result of an auto case, auto case commit result.
+ // we need find correct test case by id, and record test result to it.
+ else if (prequest->path == "/commit_result") {
+ if ((prequest->content.length() == 0) || (!m_test_cases)) {
+ json_str = "{\"Error\":\"no result\"}";
+ m_last_auto_result = "BLOCK";
+ } else {
+ Json::Value paras = splitContent(prequest->content);
+ if (m_running_session == paras["session_id"].asString()) {
+ find_id(paras, true);
+ }
+ }
+ } else if (prequest->path == "/set_capability") {// by com-module to send capability data
+ Json::Reader reader;
+
+ reader.parse(prequest->content, m_capability);
+ } else if (prequest->path.find("/capability") != string::npos) {// by test suite. only one query parameter each time
+ json_str = "{\"support\":0}";
+
+ Json::Value paras = splitContent(prequest->content);
+ string value = paras["value"].asString();
+ string name = paras["name"].asString();
+ for (unsigned int i = 0; i < name.size(); i++)
+ name[i] = tolower(name[i]);
+
+ if (m_capability[name].isBool()) {// for bool value, omit the value part
+ json_str = "{\"support\":1}";
+ }
+ else if (m_capability[name].isInt()) {
+ if (m_capability[name].asInt() == atoi(value.c_str()))
+ json_str = "{\"support\":1}";
+ }
+ else if (m_capability[name].isString()) {
+ if (m_capability[name].asString() == value)
+ json_str = "{\"support\":1}";
+ }
+ } else {
+ json_str = "{\"Error\":\"unknown request\"}";
+ }
+
+ if (json_str != "")
+ sendresponse(s, 200, prequest, json_str);
+
+#if defined(__WIN32__) || defined(__WIN64__)
+ cout << "server response is:" << json_str << endl;
+#else
+ if(g_show_log)
+ DBG_ONLY("server response is:" << json_str);
+#endif
+}
+
+// find correct case according the id sent by widget
+void HttpServer::find_id(Json::Value paras, bool auto_test) {
+ string id = paras["case_id"].asString();
+
+ bool found = false;
+ for (int i = 0; i < m_block_case_count; i++) {
+ if (m_test_cases[i].case_id == id) {
+ m_test_cases[i].set_result(paras);
+ found = true;
+ if (!auto_test) // should auto test use this logic?
+ m_block_case_index = i; // set index by id found
+ print_info_string(i);
+ break;
+ }
+ }
+ if (!found) {
+ if(g_show_log)
+ DBG_ONLY("[ Error: can't find any test case by id: " << id << " ]");
+ }
+
+ if (auto_test)
+ m_last_auto_result = paras["result"].asString();
+}
+
+// create new thread for each http request
+void* processthread(void *para) {
+ string recvstr = "";
+ char *buffer = new char[MAX_BUF]; // suppose 1 case need 1k, 100 cases will be sent each time, we need 100k memory?
+ memset(buffer, 0, MAX_BUF);
+ long iDataNum = 0;
+ int recvnum = 0;
+ thread_info *tinfo = (thread_info *) para;
+ struct HttpRequest httprequest;
+ httprequest.content = "";
+ httprequest.path = "";
+
+ int content_length = 0;
+ int real_content_length = 0;
+ while (1) {
+ iDataNum = recv(tinfo->clientsocket, buffer + recvnum,
+ MAX_BUF - recvnum - 1, 0);
+ if (iDataNum <= 0) {
+ delete[] buffer;
+ close(tinfo->clientsocket);
+ pthread_exit (NULL);
+ return 0;
+ }
+ recvnum += iDataNum;
+
+ // to calculate content length and real content read
+ if (content_length == 0) {
+ char* Content_Length = strstr(buffer, "Content-Length: ");
+ if (Content_Length != NULL) {
+ char tmplen[32];
+ sscanf(Content_Length, "%[^:]:%d", tmplen, &content_length);
+ if (content_length > 0) {
+ char* tmp = strstr(buffer, "\r\n\r\n");
+ if (tmp == NULL) {
+ tmp = strstr(buffer, "\n\n");
+ if (tmp != NULL)
+ real_content_length = iDataNum - (tmp-buffer) -2;
+ else {
+ if(g_show_log)
+ DBG_ONLY("[ can't find \\r\\n\\r\\n or \\n\\n ]");
+ break;
+ }
+ }
+ else real_content_length = iDataNum - (tmp-buffer) - 4;
+ }
+ }
+ else real_content_length += iDataNum;
+ }
+ else real_content_length += iDataNum;
+
+ if (real_content_length >= content_length) break;
+ }
+ buffer[recvnum] = '\0';
+ recvstr = buffer;
+ delete[] buffer;
+
+ // parse request and process it
+ switch (tinfo->server->getrequest(recvstr, &httprequest)) {
+ case GET:
+ case POST:
+ tinfo->server->processpost(tinfo->clientsocket, &httprequest);
+ break;
+ default:
+ break;
+ }
+ close(tinfo->clientsocket);
+ pthread_exit (NULL);
+ return 0;
+}
+
+void timer_handler(int signum) {
+ DBG_ONLY("receive signum = " << signum);
+ httpserver.timeout_action();
+}
+
+void HttpServer::timeout_action() {
+ string json_str = "{\"OK\":1}";
+ if (!m_server_checked) {// start widget again in case it dead. browser not need to restart
+ g_error_code = 1;
+ /*if (m_check_times < 3) {
+ m_check_times++;
+ if(g_show_log)
+ DBG_ONLY("[ checking the client " << m_check_times << " times ]");
+ if (g_run_wiget == true) start_client();
+ set_timer(20);
+ } else {// widget fail for 3 times. finish current set.
+ m_set_finished = true;
+ m_block_finished = true;
+ }*/
+ } else if (!m_test_cases) {
+ json_str = "{\"Error\":\"no case\"}";
+ } else if (m_exeType != "auto") {// skip to next set if widget crash when run manual cases
+ if (g_run_wiget == true) {// check whether widget is running
+ string cmd = "ps ax | grep " + m_suite_id + " | grep -v grep | awk '{print $NF}'";
+ if (!run_cmd(cmd, m_suite_id, NULL)) {
+ m_set_finished = true;
+ m_block_finished = true;
+ }
+ else set_timer(60); // continue to set timer for manual cases
+ }
+ } else if (m_block_case_index < m_block_case_count) {
+ g_error_code = 3;
+ checkResult(&m_test_cases[m_block_case_index]);
+ json_str = "{\"OK\":\"send timeout\"}";
+ } else {
+ json_str = "{\"Error\":\"case out of index\"}";
+ }
+ if (g_show_log) DBG_ONLY(json_str);
+}
+
+void HttpServer::print_info_string(int case_index) {
+ if(g_show_log){
+ DBG_ONLY(endl << "execute case: ");
+ DBG_ONLY(m_suite_name << " # " << m_test_cases[case_index].case_id << " ..(" << m_test_cases[case_index].result << ")");
+
+ if (m_test_cases[case_index].result != "PASS") // print error message if case not pass
+ DBG_ONLY(m_test_cases[case_index].std_out);
+ }
+
+ pthread_mutex_lock( &result_mutex );
+ m_result.append(m_test_cases[case_index].result_to_json());
+ if (m_exeType == "auto") {
+ if (m_block_case_index < m_block_case_count) {
+ m_block_case_index++;
+ m_total_case_index++;
+ }
+ }
+ pthread_mutex_unlock( &result_mutex );
+}
+
+// prepare to run current auto case by set the start time, etc.
+bool HttpServer::get_auto_case(string content, string *type) {
+ if (!m_killing_widget) {
+ if (content != "") {
+ string value = content.substr(content.find("=") + 1);
+ if (value.length() > 0) {
+ if (m_running_session == value) {
+ if (m_block_case_index < m_block_case_count) {
+ set_timer(m_test_cases[m_block_case_index].timeout_value+10); // +10 is to avoid dup result from suite if case timeout
+ m_test_cases[m_block_case_index].set_start_at();
+ if(g_show_log)
+ DBG_ONLY(endl << "start time: " << m_test_cases[m_block_case_index].start_at);
+ return true;
+ } else {
+ if(g_show_log)
+ DBG_ONLY(endl << "[ no auto case is available any more ]");
+ *type = "none";
+ m_block_finished = true;
+ if (m_current_block_index == m_totalBlocks)
+ m_set_finished = true; // the set is finished if current block is the last block
+ }
+ } else {
+ if(g_show_log)
+ DBG_ONLY("[ Error: invalid session ID ]");
+ *type = "invalid";
+ }
+ }
+ }
+ } else {
+ if(g_show_log)
+ DBG_ONLY(endl << "[ restart client process is activated, exit current client ]");
+ *type = "stop";
+ }
+ return false;
+}
+
+void* socket_thread(void *para) {
+#if defined(__WIN32__) || defined(__WIN64__)
+#else
+ sigset_t set;
+ int s;
+
+ /* Block SIGALRM; other threads created by main() will inherit
+ a copy of the signal mask. */
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ s = pthread_sigmask(SIG_BLOCK, &set, NULL);
+ if ((s != 0) && (g_show_log))
+ DBG_ONLY("fail to pthread_sigmask !!!");
+#endif
+
+ struct sockaddr_in clientAddr;
+ int addr_len = sizeof(clientAddr);
+
+ while (httpserver.gIsRun) {
+#if defined(__WIN32__) || defined(__WIN64__)
+ int clientsocket = accept(serversocket, (struct sockaddr *) &clientAddr,
+ (int*) &addr_len);
+#else
+ int clientsocket = accept(serversocket, (struct sockaddr *) &clientAddr,
+ (socklen_t*) &addr_len);
+#endif
+ if (clientsocket < 0) {
+ if(g_show_log)
+ DBG_ONLY("fail to accept client socket !!!");
+ } else {
+ thread_info tinfo;
+ tinfo.server = &httpserver;
+ tinfo.clientsocket = clientsocket;
+ if(g_show_log)
+ DBG_ONLY("open " << clientsocket);
+ pthread_create(&tinfo.thread_id, NULL, processthread, &tinfo);
+ //if (tinfo.thread_id != 0) pthread_detach(tinfo.thread_id);// this will release resource after threat exit. otherwise it may not execute the thread after run for a while. but still cause some strange issue
+#if defined(__WIN32__) || defined(__WIN64__)
+ if (tinfo.thread_id.p)
+ pthread_join(tinfo.thread_id, NULL);
+ else if(g_show_log)
+ DBG_ONLY("fail to create thread !!!");
+#else
+ if (tinfo.thread_id != 0)
+ pthread_join(tinfo.thread_id, NULL);
+ else if(g_show_log)
+ DBG_ONLY("fail to create thread !!!");
+#endif
+ }
+ }
+ close(serversocket);
+ pthread_exit (NULL);
+ return 0;
+}
+
+//start the socket server, listen to client
+void HttpServer::StartUp() {
+ if(g_show_log){
+ outputFile.open("httpserver_log.txt", ios::out);
+ if ( (outputFile.rdstate() & std::ifstream::failbit ) != 0 ) {
+ cout << "Error opening 'httpserver_log.txt'" << endl;
+ g_openlog_fail = true;
+ }
+ DBG_ONLY("httpserver.g_port is:" << g_port);
+ }
+
+#if defined(__WIN32__) || defined(__WIN64__)
+ WSADATA wsa;
+ if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
+ cout << "fail to init socket !!!" << endl;
+ if (g_show_log)
+ DBG_ONLY("fail to init socket !!!");
+ return;
+ }
+#endif
+
+ if ((serversocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("fail to create server socket !!!");
+ if(g_show_log)
+ DBG_ONLY("fail to create server socket !!!");
+ return;
+ }
+
+ struct sockaddr_in server_addr;
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(g_port);
+ server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ int tmp = 1;
+#if defined(__WIN32__) || defined(__WIN64__)
+ if (setsockopt(serversocket, SOL_SOCKET, SO_REUSEADDR, (char*) &tmp, sizeof(int)) < 0);
+#else
+ if (setsockopt(serversocket, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(int)) < 0)
+#endif
+ if(g_show_log) DBG_ONLY("fail to set SO_REUSEADDR !!!");
+
+ struct linger so_linger;
+ so_linger.l_onoff = true;
+ so_linger.l_linger = 10; // wait 10 seconds to close, to avoid TIME_WAIT of client
+#if defined(__WIN32__) || defined(__WIN64__)
+ if (setsockopt(serversocket, SOL_SOCKET, SO_LINGER, (char*) &so_linger, sizeof(so_linger)) < 0)
+#else
+ if (setsockopt(serversocket, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)) < 0)
+#endif
+ if(g_show_log) DBG_ONLY("fail to set SO_LINGER !!!");
+
+ if (bind(serversocket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
+ perror("fail to bind address !!!");
+ if(g_show_log) DBG_ONLY("fail to bind address !!!");
+ return;
+ }
+
+ if (listen(serversocket, 5) < 0) {
+ perror("fail to listen !!!");
+ if(g_show_log) DBG_ONLY("fail to listen !!!");
+ return;
+ }
+ gIsRun = 1;
+ cout << "[ Server is running, bind to " << g_port << " .....]" << endl;
+ if(g_show_log)
+ DBG_ONLY("[ Server is running, bind to " << g_port << " .....]");
+
+#if defined(__WIN32__) || defined(__WIN64__)
+ pthread_t thread_id;
+ pthread_create(&thread_id, NULL, socket_thread, NULL);
+ if (thread_id.p) pthread_join(thread_id, NULL);
+ WSACleanup();
+#else
+ daemon(0,0);
+ pthread_t thread_id;
+ pthread_create(&thread_id, NULL, socket_thread, NULL);
+ if (thread_id != 0) pthread_join(thread_id, NULL);
+#endif
+}
+
+// set result to block for current case if timeout
+void HttpServer::checkResult(TestCase* testcase) {
+ Json::Value result;
+ result["result"] = "BLOCK";
+ result["msg"] = "Time is out";
+ testcase->set_result(result);
+ m_last_auto_result = "BLOCK";
+
+ print_info_string(m_block_case_index);
+
+ m_timeout_count++;
+
+ if(g_show_log) DBG_ONLY("[ start new client now ]");
+ //start_client(); // start widget again in case it dead. browser not need to restart
+}
+
+// try to kill all widget listed by wrt-launch -l
+void HttpServer::killAllWidget() {
+ m_killing_widget = true;
+ string cmd = "killall " + g_launcher + " 2>/dev/null";
+ system(cmd.c_str());
+
+ std::vector<string> widgets;
+ cmd = g_launcher+" -l | awk '{print $NF}' | sed -n '3,$p'";
+ run_cmd(cmd, "", &widgets);
+
+ std::vector<string> processes;
+ cmd = "ps ax | awk '{print $NF}' | sed -n '2,$p'";
+ run_cmd(cmd, "", &processes);
+
+ for (unsigned int i = 0; i < widgets.size(); i++)
+ for (unsigned int j = 0; j < processes.size(); j++)
+ if (string::npos != processes[j].find(widgets[i])) {
+ string cmd = g_launcher +" -k " + widgets[i]; // use wrt-launcher to kill widget
+ run_cmd(cmd, "result: killed", NULL);
+ break;
+ }
+ m_killing_widget = false;
+}
+
+// try to start widget
+/*void HttpServer::start_client() {
+ if (m_set_finished) return;// not restart widget if set finished
+ if(g_run_wiget == true){
+ run_cmd(g_kill_cmd, "result: killed", NULL);// kill before launch incase sometime relaunch fail, widget hang
+ sleep(2);
+ while (!run_cmd(g_launch_cmd, "result: launched", NULL)) {
+ m_failto_launch++;
+ if(g_show_log)
+ DBG_ONLY("m_failto_launch: " << m_failto_launch);
+ if (m_failto_launch >= m_max_fail_launch) {
+ m_set_finished = true;
+ m_block_finished = true;
+ m_total_case_index = m_totalcaseCount;
+ break;
+ }
+ run_cmd(g_kill_cmd, "result: killed", NULL);
+ sleep(5); // try until start widget success
+ }
+ m_failto_launch = 0;
+ }
+ else{
+ if (g_launcher == "") return;// do nothing if comm-module send an empty g_launcher
+
+ if (g_kill_cmd != "") run_cmd(g_kill_cmd, "", NULL);
+ sleep(5); // sleep 5 seconds to avoid launch browser too frequently, otherwise may launch fail.
+ int status = system(g_launch_cmd.c_str()); // can't use popen here for it will not return until cmd finish
+ if ((status != 0) && g_show_log)
+ DBG_ONLY("[cmd: " << g_launch_cmd << " error]");
+ }
+}*/
+
+// run shell cmd. return true if the output equal to expectString. show cmd and output if showcmdAnyway.
+bool HttpServer::run_cmd(string cmdString, string expectString, std::vector<string> *output) {
+ bool ret = false;
+
+ char buf[128];
+ memset(buf, 0, 128);
+ FILE *pp;
+ if ((pp = popen(cmdString.c_str(), "r")) == NULL) {
+ if(g_show_log) DBG_ONLY("popen() error!");
+ return ret;
+ }
+ if(g_show_log) DBG_ONLY(cmdString);
+ while (fgets(buf, sizeof buf, pp)) {
+ if(g_show_log) DBG_ONLY(buf);
+ buf[strlen(buf) - 1] = 0; // remove the character return at the end.
+ if (strstr(buf, expectString.c_str())) ret = true;
+ if (output) output->push_back(buf);
+ memset(buf, 0, 128);
+ }
+ pclose(pp);
+ return ret;
+}
--- /dev/null
+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+# include <stdlib.h>
+# include <assert.h>
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+namespace Json {
+
+/* Fast memory allocator.
+ *
+ * This memory allocator allocates memory for a batch of object (specified by
+ * the page size, the number of object in each page).
+ *
+ * It does not allow the destruction of a single object. All the allocated objects
+ * can be destroyed at once. The memory can be either released or reused for future
+ * allocation.
+ *
+ * The in-place new operator must be used to construct the object using the pointer
+ * returned by allocate.
+ */
+template<typename AllocatedType, const unsigned int objectPerAllocation>
+class BatchAllocator {
+public:
+ typedef AllocatedType Type;
+
+ BatchAllocator(unsigned int objectsPerPage = 255) :
+ freeHead_(0), objectsPerPage_(objectsPerPage) {
+// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
+ assert(
+ sizeof(AllocatedType) * objectPerAllocation
+ >= sizeof(AllocatedType *)); // We must be able to store a slist in the object free space.
+ assert(objectsPerPage >= 16);
+ batches_ = allocateBatch(0); // allocated a dummy page
+ currentBatch_ = batches_;
+ }
+
+ ~BatchAllocator() {
+ for (BatchInfo *batch = batches_; batch;) {
+ BatchInfo *nextBatch = batch->next_;
+ free(batch);
+ batch = nextBatch;
+ }
+ }
+
+ /// allocate space for an array of objectPerAllocation object.
+ /// @warning it is the responsability of the caller to call objects constructors.
+ AllocatedType *allocate() {
+ if (freeHead_) // returns node from free list.
+ {
+ AllocatedType *object = freeHead_;
+ freeHead_ = *(AllocatedType **) object;
+ return object;
+ }
+ if (currentBatch_->used_ == currentBatch_->end_) {
+ currentBatch_ = currentBatch_->next_;
+ while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_)
+ currentBatch_ = currentBatch_->next_;
+
+ if (!currentBatch_) // no free batch found, allocate a new one
+ {
+ currentBatch_ = allocateBatch(objectsPerPage_);
+ currentBatch_->next_ = batches_; // insert at the head of the list
+ batches_ = currentBatch_;
+ }
+ }
+ AllocatedType *allocated = currentBatch_->used_;
+ currentBatch_->used_ += objectPerAllocation;
+ return allocated;
+ }
+
+ /// Release the object.
+ /// @warning it is the responsability of the caller to actually destruct the object.
+ void release(AllocatedType *object) {
+ assert(object != 0);
+ *(AllocatedType **) object = freeHead_;
+ freeHead_ = object;
+ }
+
+private:
+ struct BatchInfo {
+ BatchInfo *next_;
+ AllocatedType *used_;
+ AllocatedType *end_;
+ AllocatedType buffer_[objectPerAllocation];
+ };
+
+ // disabled copy constructor and assignement operator.
+ BatchAllocator(const BatchAllocator &);
+ void operator =(const BatchAllocator &);
+
+ static BatchInfo *allocateBatch(unsigned int objectsPerPage) {
+ const unsigned int mallocSize = sizeof(BatchInfo)
+ - sizeof(AllocatedType) * objectPerAllocation
+ + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
+ BatchInfo *batch = static_cast<BatchInfo*>(malloc(mallocSize));
+ batch->next_ = 0;
+ batch->used_ = batch->buffer_;
+ batch->end_ = batch->buffer_ + objectsPerPage;
+ return batch;
+ }
+
+ BatchInfo *batches_;
+ BatchInfo *currentBatch_;
+ /// Head of a single linked list within the allocated space of freeed object
+ AllocatedType *freeHead_;
+ unsigned int objectsPerPage_;
+};
+
+} // namespace Json
+
+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
--- /dev/null
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueArrayAllocator::~ValueArrayAllocator()
+{
+}
+
+// //////////////////////////////////////////////////////////////////
+// class DefaultValueArrayAllocator
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ return new ValueInternalArray();
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ return new ValueInternalArray( other );
+ }
+
+ virtual void destructArray( ValueInternalArray *array )
+ {
+ delete array;
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ free( value );
+ }
+};
+
+#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ ValueInternalArray *array = arraysAllocator_.allocate();
+ new (array) ValueInternalArray(); // placement new
+ return array;
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ ValueInternalArray *array = arraysAllocator_.allocate();
+ new (array) ValueInternalArray( other ); // placement new
+ return array;
+ }
+
+ virtual void destructArray( ValueInternalArray *array )
+ {
+ if ( array )
+ {
+ array->~ValueInternalArray();
+ arraysAllocator_.release( array );
+ }
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( pagesAllocator_.allocate() );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ pagesAllocator_.release( value );
+ }
+private:
+ BatchAllocator<ValueInternalArray,1> arraysAllocator_;
+ BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
+};
+#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+static ValueArrayAllocator *&arrayAllocator()
+{
+ static DefaultValueArrayAllocator defaultAllocator;
+ static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
+ return arrayAllocator;
+}
+
+static struct DummyArrayAllocatorInitializer {
+ DummyArrayAllocatorInitializer()
+ {
+ arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
+ }
+} dummyArrayAllocatorInitializer;
+
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+bool
+ValueInternalArray::equals( const IteratorState &x,
+ const IteratorState &other )
+{
+ return x.array_ == other.array_
+ && x.currentItemIndex_ == other.currentItemIndex_
+ && x.currentPageIndex_ == other.currentPageIndex_;
+}
+
+
+void
+ValueInternalArray::increment( IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ &&
+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+ != it.array_->size_,
+ "ValueInternalArray::increment(): moving iterator beyond end" );
+ ++(it.currentItemIndex_);
+ if ( it.currentItemIndex_ == itemsPerPage )
+ {
+ it.currentItemIndex_ = 0;
+ ++(it.currentPageIndex_);
+ }
+}
+
+
+void
+ValueInternalArray::decrement( IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
+ && it.currentItemIndex_ == 0,
+ "ValueInternalArray::decrement(): moving iterator beyond end" );
+ if ( it.currentItemIndex_ == 0 )
+ {
+ it.currentItemIndex_ = itemsPerPage-1;
+ --(it.currentPageIndex_);
+ }
+ else
+ {
+ --(it.currentItemIndex_);
+ }
+}
+
+
+Value &
+ValueInternalArray::unsafeDereference( const IteratorState &it )
+{
+ return (*(it.currentPageIndex_))[it.currentItemIndex_];
+}
+
+
+Value &
+ValueInternalArray::dereference( const IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ &&
+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+ < it.array_->size_,
+ "ValueInternalArray::dereference(): dereferencing invalid iterator" );
+ return unsafeDereference( it );
+}
+
+void
+ValueInternalArray::makeBeginIterator( IteratorState &it ) const
+{
+ it.array_ = const_cast<ValueInternalArray *>( this );
+ it.currentItemIndex_ = 0;
+ it.currentPageIndex_ = pages_;
+}
+
+
+void
+ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
+{
+ it.array_ = const_cast<ValueInternalArray *>( this );
+ it.currentItemIndex_ = index % itemsPerPage;
+ it.currentPageIndex_ = pages_ + index / itemsPerPage;
+}
+
+
+void
+ValueInternalArray::makeEndIterator( IteratorState &it ) const
+{
+ makeIterator( it, size_ );
+}
+
+
+ValueInternalArray::ValueInternalArray()
+ : pages_( 0 )
+ , size_( 0 )
+ , pageCount_( 0 )
+{
+}
+
+
+ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
+ : pages_( 0 )
+ , pageCount_( 0 )
+ , size_( other.size_ )
+{
+ PageIndex minNewPages = other.size_ / itemsPerPage;
+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
+ "ValueInternalArray::reserve(): bad reallocation" );
+ IteratorState itOther;
+ other.makeBeginIterator( itOther );
+ Value *value;
+ for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
+ {
+ if ( index % itemsPerPage == 0 )
+ {
+ PageIndex pageIndex = index / itemsPerPage;
+ value = arrayAllocator()->allocateArrayPage();
+ pages_[pageIndex] = value;
+ }
+ new (value) Value( dereference( itOther ) );
+ }
+}
+
+
+ValueInternalArray &
+ValueInternalArray::operator =( const ValueInternalArray &other )
+{
+ ValueInternalArray temp( other );
+ swap( temp );
+ return *this;
+}
+
+
+ValueInternalArray::~ValueInternalArray()
+{
+ // destroy all constructed items
+ IteratorState it;
+ IteratorState itEnd;
+ makeBeginIterator( it);
+ makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ value->~Value();
+ }
+ // release all pages
+ PageIndex lastPageIndex = size_ / itemsPerPage;
+ for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+ // release pages index
+ arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
+}
+
+
+void
+ValueInternalArray::swap( ValueInternalArray &other )
+{
+ Value **tempPages = pages_;
+ pages_ = other.pages_;
+ other.pages_ = tempPages;
+ ArrayIndex tempSize = size_;
+ size_ = other.size_;
+ other.size_ = tempSize;
+ PageIndex tempPageCount = pageCount_;
+ pageCount_ = other.pageCount_;
+ other.pageCount_ = tempPageCount;
+}
+
+void
+ValueInternalArray::clear()
+{
+ ValueInternalArray dummy;
+ swap( dummy );
+}
+
+
+void
+ValueInternalArray::resize( ArrayIndex newSize )
+{
+ if ( newSize == 0 )
+ clear();
+ else if ( newSize < size_ )
+ {
+ IteratorState it;
+ IteratorState itEnd;
+ makeIterator( it, newSize );
+ makeIterator( itEnd, size_ );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ value->~Value();
+ }
+ PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
+ PageIndex lastPageIndex = size_ / itemsPerPage;
+ for ( ; pageIndex < lastPageIndex; ++pageIndex )
+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+ size_ = newSize;
+ }
+ else if ( newSize > size_ )
+ resolveReference( newSize );
+}
+
+
+void
+ValueInternalArray::makeIndexValid( ArrayIndex index )
+{
+ // Need to enlarge page index ?
+ if ( index >= pageCount_ * itemsPerPage )
+ {
+ PageIndex minNewPages = (index + 1) / itemsPerPage;
+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
+ }
+
+ // Need to allocate new pages ?
+ ArrayIndex nextPageIndex =
+ (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
+ : size_;
+ if ( nextPageIndex <= index )
+ {
+ PageIndex pageIndex = nextPageIndex / itemsPerPage;
+ PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
+ for ( ; pageToAllocate-- > 0; ++pageIndex )
+ pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
+ }
+
+ // Initialize all new entries
+ IteratorState it;
+ IteratorState itEnd;
+ makeIterator( it, size_ );
+ size_ = index + 1;
+ makeIterator( itEnd, size_ );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ new (value) Value(); // Construct a default value using placement new
+ }
+}
+
+Value &
+ValueInternalArray::resolveReference( ArrayIndex index )
+{
+ if ( index >= size_ )
+ makeIndexValid( index );
+ return pages_[index/itemsPerPage][index%itemsPerPage];
+}
+
+Value *
+ValueInternalArray::find( ArrayIndex index ) const
+{
+ if ( index >= size_ )
+ return 0;
+ return &(pages_[index/itemsPerPage][index%itemsPerPage]);
+}
+
+ValueInternalArray::ArrayIndex
+ValueInternalArray::size() const
+{
+ return size_;
+}
+
+int
+ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
+{
+ return indexOf(y) - indexOf(x);
+}
+
+
+ValueInternalArray::ArrayIndex
+ValueInternalArray::indexOf( const IteratorState &iterator )
+{
+ if ( !iterator.array_ )
+ return ArrayIndex(-1);
+ return ArrayIndex(
+ (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
+ + iterator.currentItemIndex_ );
+}
+
+
+int
+ValueInternalArray::compare( const ValueInternalArray &other ) const
+{
+ int sizeDiff( size_ - other.size_ );
+ if ( sizeDiff != 0 )
+ return sizeDiff;
+
+ for ( ArrayIndex index =0; index < size_; ++index )
+ {
+ int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
+ other.pages_[index/itemsPerPage][index%itemsPerPage] );
+ if ( diff != 0 )
+ return diff;
+ }
+ return 0;
+}
--- /dev/null
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalMap
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
+ * This optimization is used by the fast allocator.
+ */
+ValueInternalLink::ValueInternalLink()
+ : previous_( 0 )
+ , next_( 0 )
+{
+}
+
+ValueInternalLink::~ValueInternalLink()
+{
+ for ( int index =0; index < itemPerLink; ++index )
+ {
+ if ( !items_[index].isItemAvailable() )
+ {
+ if ( !items_[index].isMemberNameStatic() )
+ free( keys_[index] );
+ }
+ else
+ break;
+ }
+}
+
+
+
+ValueMapAllocator::~ValueMapAllocator()
+{
+}
+
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ return new ValueInternalMap();
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ return new ValueInternalMap( other );
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ delete map;
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ return new ValueInternalLink();
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ delete link;
+ }
+};
+#else
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ ValueInternalMap *map = mapsAllocator_.allocate();
+ new (map) ValueInternalMap(); // placement new
+ return map;
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ ValueInternalMap *map = mapsAllocator_.allocate();
+ new (map) ValueInternalMap( other ); // placement new
+ return map;
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ if ( map )
+ {
+ map->~ValueInternalMap();
+ mapsAllocator_.release( map );
+ }
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ ValueInternalLink *link = linksAllocator_.allocate();
+ memset( link, 0, sizeof(ValueInternalLink) );
+ return link;
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ link->~ValueInternalLink();
+ linksAllocator_.release( link );
+ }
+private:
+ BatchAllocator<ValueInternalMap,1> mapsAllocator_;
+ BatchAllocator<ValueInternalLink,1> linksAllocator_;
+};
+#endif
+
+static ValueMapAllocator *&mapAllocator()
+{
+ static DefaultValueMapAllocator defaultAllocator;
+ static ValueMapAllocator *mapAllocator = &defaultAllocator;
+ return mapAllocator;
+}
+
+static struct DummyMapAllocatorInitializer {
+ DummyMapAllocatorInitializer()
+ {
+ mapAllocator(); // ensure mapAllocator() statics are initialized before main().
+ }
+} dummyMapAllocatorInitializer;
+
+
+
+// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
+
+/*
+use linked list hash map.
+buckets array is a container.
+linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
+value have extra state: valid, available, deleted
+*/
+
+
+ValueInternalMap::ValueInternalMap()
+ : buckets_( 0 )
+ , tailLink_( 0 )
+ , bucketsSize_( 0 )
+ , itemCount_( 0 )
+{
+}
+
+
+ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
+ : buckets_( 0 )
+ , tailLink_( 0 )
+ , bucketsSize_( 0 )
+ , itemCount_( 0 )
+{
+ reserve( other.itemCount_ );
+ IteratorState it;
+ IteratorState itEnd;
+ other.makeBeginIterator( it );
+ other.makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ bool isStatic;
+ const char *memberName = key( it, isStatic );
+ const Value &aValue = value( it );
+ resolveReference(memberName, isStatic) = aValue;
+ }
+}
+
+
+ValueInternalMap &
+ValueInternalMap::operator =( const ValueInternalMap &other )
+{
+ ValueInternalMap dummy( other );
+ swap( dummy );
+ return *this;
+}
+
+
+ValueInternalMap::~ValueInternalMap()
+{
+ if ( buckets_ )
+ {
+ for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
+ {
+ ValueInternalLink *link = buckets_[bucketIndex].next_;
+ while ( link )
+ {
+ ValueInternalLink *linkToRelease = link;
+ link = link->next_;
+ mapAllocator()->releaseMapLink( linkToRelease );
+ }
+ }
+ mapAllocator()->releaseMapBuckets( buckets_ );
+ }
+}
+
+
+void
+ValueInternalMap::swap( ValueInternalMap &other )
+{
+ ValueInternalLink *tempBuckets = buckets_;
+ buckets_ = other.buckets_;
+ other.buckets_ = tempBuckets;
+ ValueInternalLink *tempTailLink = tailLink_;
+ tailLink_ = other.tailLink_;
+ other.tailLink_ = tempTailLink;
+ BucketIndex tempBucketsSize = bucketsSize_;
+ bucketsSize_ = other.bucketsSize_;
+ other.bucketsSize_ = tempBucketsSize;
+ BucketIndex tempItemCount = itemCount_;
+ itemCount_ = other.itemCount_;
+ other.itemCount_ = tempItemCount;
+}
+
+
+void
+ValueInternalMap::clear()
+{
+ ValueInternalMap dummy;
+ swap( dummy );
+}
+
+
+ValueInternalMap::BucketIndex
+ValueInternalMap::size() const
+{
+ return itemCount_;
+}
+
+bool
+ValueInternalMap::reserveDelta( BucketIndex growth )
+{
+ return reserve( itemCount_ + growth );
+}
+
+bool
+ValueInternalMap::reserve( BucketIndex newItemCount )
+{
+ if ( !buckets_ && newItemCount > 0 )
+ {
+ buckets_ = mapAllocator()->allocateMapBuckets( 1 );
+ bucketsSize_ = 1;
+ tailLink_ = &buckets_[0];
+ }
+// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
+ return true;
+}
+
+
+const Value *
+ValueInternalMap::find( const char *key ) const
+{
+ if ( !bucketsSize_ )
+ return 0;
+ HashKey hashedKey = hash( key );
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ for ( const ValueInternalLink *current = &buckets_[bucketIndex];
+ current != 0;
+ current = current->next_ )
+ {
+ for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( current->items_[index].isItemAvailable() )
+ return 0;
+ if ( strcmp( key, current->keys_[index] ) == 0 )
+ return ¤t->items_[index];
+ }
+ }
+ return 0;
+}
+
+
+Value *
+ValueInternalMap::find( const char *key )
+{
+ const ValueInternalMap *constThis = this;
+ return const_cast<Value *>( constThis->find( key ) );
+}
+
+
+Value &
+ValueInternalMap::resolveReference( const char *key,
+ bool isStatic )
+{
+ HashKey hashedKey = hash( key );
+ if ( bucketsSize_ )
+ {
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ ValueInternalLink **previous = 0;
+ BucketIndex index;
+ for ( ValueInternalLink *current = &buckets_[bucketIndex];
+ current != 0;
+ previous = ¤t->next_, current = current->next_ )
+ {
+ for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( current->items_[index].isItemAvailable() )
+ return setNewItem( key, isStatic, current, index );
+ if ( strcmp( key, current->keys_[index] ) == 0 )
+ return current->items_[index];
+ }
+ }
+ }
+
+ reserveDelta( 1 );
+ return unsafeAdd( key, isStatic, hashedKey );
+}
+
+
+void
+ValueInternalMap::remove( const char *key )
+{
+ HashKey hashedKey = hash( key );
+ if ( !bucketsSize_ )
+ return;
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ for ( ValueInternalLink *link = &buckets_[bucketIndex];
+ link != 0;
+ link = link->next_ )
+ {
+ BucketIndex index;
+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( link->items_[index].isItemAvailable() )
+ return;
+ if ( strcmp( key, link->keys_[index] ) == 0 )
+ {
+ doActualRemove( link, index, bucketIndex );
+ return;
+ }
+ }
+ }
+}
+
+void
+ValueInternalMap::doActualRemove( ValueInternalLink *link,
+ BucketIndex index,
+ BucketIndex bucketIndex )
+{
+ // find last item of the bucket and swap it with the 'removed' one.
+ // set removed items flags to 'available'.
+ // if last page only contains 'available' items, then desallocate it (it's empty)
+ ValueInternalLink *&lastLink = getLastLinkInBucket( index );
+ BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
+ for ( ;
+ lastItemIndex < ValueInternalLink::itemPerLink;
+ ++lastItemIndex ) // may be optimized with dicotomic search
+ {
+ if ( lastLink->items_[lastItemIndex].isItemAvailable() )
+ break;
+ }
+
+ BucketIndex lastUsedIndex = lastItemIndex - 1;
+ Value *valueToDelete = &link->items_[index];
+ Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
+ if ( valueToDelete != valueToPreserve )
+ valueToDelete->swap( *valueToPreserve );
+ if ( lastUsedIndex == 0 ) // page is now empty
+ { // remove it from bucket linked list and delete it.
+ ValueInternalLink *linkPreviousToLast = lastLink->previous_;
+ if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
+ {
+ mapAllocator()->releaseMapLink( lastLink );
+ linkPreviousToLast->next_ = 0;
+ lastLink = linkPreviousToLast;
+ }
+ }
+ else
+ {
+ Value dummy;
+ valueToPreserve->swap( dummy ); // restore deleted to default Value.
+ valueToPreserve->setItemUsed( false );
+ }
+ --itemCount_;
+}
+
+
+ValueInternalLink *&
+ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
+{
+ if ( bucketIndex == bucketsSize_ - 1 )
+ return tailLink_;
+ ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
+ if ( !previous )
+ previous = &buckets_[bucketIndex];
+ return previous;
+}
+
+
+Value &
+ValueInternalMap::setNewItem( const char *key,
+ bool isStatic,
+ ValueInternalLink *link,
+ BucketIndex index )
+{
+ char *duplicatedKey = valueAllocator()->makeMemberName( key );
+ ++itemCount_;
+ link->keys_[index] = duplicatedKey;
+ link->items_[index].setItemUsed();
+ link->items_[index].setMemberNameIsStatic( isStatic );
+ return link->items_[index]; // items already default constructed.
+}
+
+
+Value &
+ValueInternalMap::unsafeAdd( const char *key,
+ bool isStatic,
+ HashKey hashedKey )
+{
+ JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
+ ValueInternalLink *link = previousLink;
+ BucketIndex index;
+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( link->items_[index].isItemAvailable() )
+ break;
+ }
+ if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
+ {
+ ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
+ index = 0;
+ link->next_ = newLink;
+ previousLink = newLink;
+ link = newLink;
+ }
+ return setNewItem( key, isStatic, link, index );
+}
+
+
+ValueInternalMap::HashKey
+ValueInternalMap::hash( const char *key ) const
+{
+ HashKey hash = 0;
+ while ( *key )
+ hash += *key++ * 37;
+ return hash;
+}
+
+
+int
+ValueInternalMap::compare( const ValueInternalMap &other ) const
+{
+ int sizeDiff( itemCount_ - other.itemCount_ );
+ if ( sizeDiff != 0 )
+ return sizeDiff;
+ // Strict order guaranty is required. Compare all keys FIRST, then compare values.
+ IteratorState it;
+ IteratorState itEnd;
+ makeBeginIterator( it );
+ makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ if ( !other.find( key( it ) ) )
+ return 1;
+ }
+
+ // All keys are equals, let's compare values
+ makeBeginIterator( it );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ const Value *otherValue = other.find( key( it ) );
+ int valueDiff = value(it).compare( *otherValue );
+ if ( valueDiff != 0 )
+ return valueDiff;
+ }
+ return 0;
+}
+
+
+void
+ValueInternalMap::makeBeginIterator( IteratorState &it ) const
+{
+ it.map_ = const_cast<ValueInternalMap *>( this );
+ it.bucketIndex_ = 0;
+ it.itemIndex_ = 0;
+ it.link_ = buckets_;
+}
+
+
+void
+ValueInternalMap::makeEndIterator( IteratorState &it ) const
+{
+ it.map_ = const_cast<ValueInternalMap *>( this );
+ it.bucketIndex_ = bucketsSize_;
+ it.itemIndex_ = 0;
+ it.link_ = 0;
+}
+
+
+bool
+ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
+{
+ return x.map_ == other.map_
+ && x.bucketIndex_ == other.bucketIndex_
+ && x.link_ == other.link_
+ && x.itemIndex_ == other.itemIndex_;
+}
+
+
+void
+ValueInternalMap::incrementBucket( IteratorState &iterator )
+{
+ ++iterator.bucketIndex_;
+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
+ if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
+ iterator.link_ = 0;
+ else
+ iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
+ iterator.itemIndex_ = 0;
+}
+
+
+void
+ValueInternalMap::increment( IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
+ ++iterator.itemIndex_;
+ if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
+ {
+ JSON_ASSERT_MESSAGE( iterator.link_ != 0,
+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
+ iterator.link_ = iterator.link_->next_;
+ if ( iterator.link_ == 0 )
+ incrementBucket( iterator );
+ }
+ else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
+ {
+ incrementBucket( iterator );
+ }
+}
+
+
+void
+ValueInternalMap::decrement( IteratorState &iterator )
+{
+ if ( iterator.itemIndex_ == 0 )
+ {
+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
+ if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
+ {
+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
+ --(iterator.bucketIndex_);
+ }
+ iterator.link_ = iterator.link_->previous_;
+ iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
+ }
+}
+
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
+ return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+
+Value &
+ValueInternalMap::value( const IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ return iterator.link_->items_[iterator.itemIndex_];
+}
+
+
+int
+ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
+{
+ int offset = 0;
+ IteratorState it = x;
+ while ( !equals( it, y ) )
+ increment( it );
+ return offset;
+}
--- /dev/null
+#include <json/reader.h>
+#include <json/value.h>
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features() :
+ allowComments_(true), strictRoot_(false) {
+}
+
+Features Features::all() {
+ return Features();
+}
+
+Features Features::strictMode() {
+ Features features;
+ features.allowComments_ = false;
+ features.strictRoot_ = true;
+ return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+static inline bool in(Reader::Char c, Reader::Char c1, Reader::Char c2,
+ Reader::Char c3, Reader::Char c4) {
+ return c == c1 || c == c2 || c == c3 || c == c4;
+}
+
+static inline bool in(Reader::Char c, Reader::Char c1, Reader::Char c2,
+ Reader::Char c3, Reader::Char c4, Reader::Char c5) {
+ return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
+}
+
+static bool containsNewLine(Reader::Location begin, Reader::Location end) {
+ for (; begin < end; ++begin)
+ if (*begin == '\n' || *begin == '\r')
+ return true;
+ return false;
+}
+
+static std::string codePointToUTF8(unsigned int cp) {
+ std::string result;
+
+ // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+ if (cp <= 0x7f) {
+ result.resize(1);
+ result[0] = static_cast<char>(cp);
+ } else if (cp <= 0x7FF) {
+ result.resize(2);
+ result[1] = static_cast<char>(0x80 | (0x3f & cp));
+ result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+ } else if (cp <= 0xFFFF) {
+ result.resize(3);
+ result[2] = static_cast<char>(0x80 | (0x3f & cp));
+ result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
+ result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+ } else if (cp <= 0x10FFFF) {
+ result.resize(4);
+ result[3] = static_cast<char>(0x80 | (0x3f & cp));
+ result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+ result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+ }
+
+ return result;
+}
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader() :
+ features_(Features::all()) {
+}
+
+Reader::Reader(const Features &features) :
+ features_(features) {
+}
+
+bool Reader::parse(const std::string &document, Value &root,
+ bool collectComments) {
+ document_ = document;
+ const char *begin = document_.c_str();
+ const char *end = begin + document_.length();
+ return parse(begin, end, root, collectComments);
+}
+
+bool Reader::parse(std::istream& sin, Value &root, bool collectComments) {
+ //std::istream_iterator<char> begin(sin);
+ //std::istream_iterator<char> end;
+ // Those would allow streamed input from a file, if parse() were a
+ // template function.
+
+ // Since std::string is reference-counted, this at least does not
+ // create an extra copy.
+ std::string doc;
+ std::getline(sin, doc, (char) EOF);
+ return parse(doc, root, collectComments);
+}
+
+bool Reader::parse(const char *beginDoc, const char *endDoc, Value &root,
+ bool collectComments) {
+ if (!features_.allowComments_) {
+ collectComments = false;
+ }
+
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = 0;
+ lastValue_ = 0;
+ commentsBefore_ = "";
+ errors_.clear();
+ while (!nodes_.empty())
+ nodes_.pop();
+ nodes_.push(&root);
+
+ bool successful = readValue();
+ Token token;
+ skipCommentTokens(token);
+ if (collectComments_ && !commentsBefore_.empty())
+ root.setComment(commentsBefore_, commentAfter);
+ if (features_.strictRoot_) {
+ if (!root.isArray() && !root.isObject()) {
+ // Set error location to start of doc, ideally should be first token found in doc
+ token.type_ = tokenError;
+ token.start_ = beginDoc;
+ token.end_ = endDoc;
+ addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
+ return false;
+ }
+ }
+ return successful;
+}
+
+bool Reader::readValue() {
+ Token token;
+ skipCommentTokens(token);
+ bool successful = true;
+
+ if (collectComments_ && !commentsBefore_.empty()) {
+ currentValue().setComment(commentsBefore_, commentBefore);
+ commentsBefore_ = "";
+ }
+
+ switch (token.type_) {
+ case tokenObjectBegin:
+ successful = readObject(token);
+ break;
+ case tokenArrayBegin:
+ successful = readArray(token);
+ break;
+ case tokenNumber:
+ successful = decodeNumber(token);
+ break;
+ case tokenString:
+ successful = decodeString(token);
+ break;
+ case tokenTrue:
+ currentValue() = true;
+ break;
+ case tokenFalse:
+ currentValue() = false;
+ break;
+ case tokenNull:
+ currentValue() = Value();
+ break;
+ default:
+ return addError("Syntax error: value, object or array expected.", token);
+ }
+
+ if (collectComments_) {
+ lastValueEnd_ = current_;
+ lastValue_ = ¤tValue();
+ }
+
+ return successful;
+}
+
+void Reader::skipCommentTokens(Token &token) {
+ if (features_.allowComments_) {
+ do {
+ readToken(token);
+ } while (token.type_ == tokenComment);
+ } else {
+ readToken(token);
+ }
+}
+
+bool Reader::expectToken(TokenType type, Token &token, const char *message) {
+ readToken(token);
+ if (token.type_ != type)
+ return addError(message, token);
+ return true;
+}
+
+bool Reader::readToken(Token &token) {
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
+ bool ok = true;
+ switch (c) {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ token.type_ = tokenNumber;
+ readNumber();
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match("ull", 3);
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ token.type_ = tokenError;
+ token.end_ = current_;
+ return true;
+}
+
+void Reader::skipSpaces() {
+ while (current_ != end_) {
+ Char c = *current_;
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ ++current_;
+ else
+ break;
+ }
+}
+
+bool Reader::match(Location pattern, int patternLength) {
+ if (end_ - current_ < patternLength)
+ return false;
+ int index = patternLength;
+ while (index--)
+ if (current_[index] != pattern[index])
+ return false;
+ current_ += patternLength;
+ return true;
+}
+
+bool Reader::readComment() {
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
+ bool successful = false;
+ if (c == '*')
+ successful = readCStyleComment();
+ else if (c == '/')
+ successful = readCppStyleComment();
+ if (!successful)
+ return false;
+
+ if (collectComments_) {
+ CommentPlacement placement = commentBefore;
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, current_))
+ placement = commentAfterOnSameLine;
+ }
+
+ addComment(commentBegin, current_, placement);
+ }
+ return true;
+}
+
+void Reader::addComment(Location begin, Location end,
+ CommentPlacement placement) {
+ assert(collectComments_);
+ if (placement == commentAfterOnSameLine) {
+ assert(lastValue_ != 0);
+ lastValue_->setComment(std::string(begin, end), placement);
+ } else {
+ if (!commentsBefore_.empty())
+ commentsBefore_ += "\n";
+ commentsBefore_ += std::string(begin, end);
+ }
+}
+
+bool Reader::readCStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
+ if (c == '*' && *current_ == '/')
+ break;
+ }
+ return getNextChar() == '/';
+}
+
+bool Reader::readCppStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
+ if (c == '\r' || c == '\n')
+ break;
+ }
+ return true;
+}
+
+void Reader::readNumber() {
+ while (current_ != end_) {
+ if (!(*current_ >= '0' && *current_ <= '9')
+ && !in(*current_, '.', 'e', 'E', '+', '-'))
+ break;
+ ++current_;
+ }
+}
+
+bool Reader::readString() {
+ Char c = 0;
+ while (current_ != end_) {
+ c = getNextChar();
+ if (c == '\\')
+ getNextChar();
+ else if (c == '"')
+ break;
+ }
+ return c == '"';
+}
+
+bool Reader::readObject(Token &tokenStart) {
+ Token tokenName;
+ std::string name;
+ currentValue() = Value(objectValue);
+ while (readToken(tokenName)) {
+ bool initialTokenOk = true;
+ while (tokenName.type_ == tokenComment && initialTokenOk)
+ initialTokenOk = readToken(tokenName);
+ if (!initialTokenOk)
+ break;
+ if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+ return true;
+ if (tokenName.type_ != tokenString)
+ break;
+
+ name = "";
+ if (!decodeString(tokenName, name))
+ return recoverFromError(tokenObjectEnd);
+
+ Token colon;
+ if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return addErrorAndRecover("Missing ':' after object member name",
+ colon, tokenObjectEnd);
+ }
+ Value &value = currentValue()[name];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenObjectEnd);
+
+ Token comma;
+ if (!readToken(comma)
+ || (comma.type_ != tokenObjectEnd
+ && comma.type_ != tokenArraySeparator
+ && comma.type_ != tokenComment)) {
+ return addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma,
+ tokenObjectEnd);
+ }
+ bool finalizeTokenOk = true;
+ while (comma.type_ == tokenComment && finalizeTokenOk)
+ finalizeTokenOk = readToken(comma);
+ if (comma.type_ == tokenObjectEnd)
+ return true;
+ }
+ return addErrorAndRecover("Missing '}' or object member name", tokenName,
+ tokenObjectEnd);
+}
+
+bool Reader::readArray(Token &tokenStart) {
+ currentValue() = Value(arrayValue);
+ skipSpaces();
+ if (*current_ == ']') // empty array
+ {
+ Token endArray;
+ readToken(endArray);
+ return true;
+ }
+ int index = 0;
+ while (true) {
+ Value &value = currentValue()[index++];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenArrayEnd);
+
+ Token token;
+ // Accept Comment after last item in the array.
+ ok = readToken(token);
+ while (token.type_ == tokenComment && ok) {
+ ok = readToken(token);
+ }
+ bool badTokenType = (token.type_ == tokenArraySeparator
+ && token.type_ == tokenArrayEnd);
+ if (!ok || badTokenType) {
+ return addErrorAndRecover("Missing ',' or ']' in array declaration",
+ token, tokenArrayEnd);
+ }
+ if (token.type_ == tokenArrayEnd)
+ break;
+ }
+ return true;
+}
+
+bool Reader::decodeNumber(Token &token) {
+ bool isDouble = false;
+ for (Location inspect = token.start_; inspect != token.end_; ++inspect) {
+ isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+')
+ || (*inspect == '-' && inspect != token.start_);
+ }
+ if (isDouble)
+ return decodeDouble(token);
+ Location current = token.start_;
+ bool isNegative = *current == '-';
+ if (isNegative)
+ ++current;
+ Value::UInt threshold = (
+ isNegative ? Value::UInt(-Value::minInt) : Value::maxUInt) / 10;
+ Value::UInt value = 0;
+ while (current < token.end_) {
+ Char c = *current++;
+ if (c < '0' || c > '9')
+ return addError(
+ "'" + std::string(token.start_, token.end_)
+ + "' is not a number.", token);
+ if (value >= threshold)
+ return decodeDouble(token);
+ value = value * 10 + Value::UInt(c - '0');
+ }
+ if (isNegative)
+ currentValue() = -Value::Int(value);
+ else if (value <= Value::UInt(Value::maxInt))
+ currentValue() = Value::Int(value);
+ else
+ currentValue() = value;
+ return true;
+}
+
+bool Reader::decodeDouble(Token &token) {
+ double value = 0;
+ const int bufferSize = 32;
+ int count;
+ int length = int(token.end_ - token.start_);
+ if (length <= bufferSize) {
+ Char buffer[bufferSize];
+ memcpy(buffer, token.start_, length);
+ buffer[length] = 0;
+ count = sscanf(buffer, "%lf", &value);
+ } else {
+ std::string buffer(token.start_, token.end_);
+ count = sscanf(buffer.c_str(), "%lf", &value);
+ }
+
+ if (count != 1)
+ return addError(
+ "'" + std::string(token.start_, token.end_)
+ + "' is not a number.", token);
+ currentValue() = value;
+ return true;
+}
+
+bool Reader::decodeString(Token &token) {
+ std::string decoded;
+ if (!decodeString(token, decoded))
+ return false;
+ currentValue() = decoded;
+ return true;
+}
+
+bool Reader::decodeString(Token &token, std::string &decoded) {
+ decoded.reserve(token.end_ - token.start_ - 2);
+ Location current = token.start_ + 1; // skip '"'
+ Location end = token.end_ - 1; // do not include '"'
+ while (current != end) {
+ Char c = *current++;
+ if (c == '"')
+ break;
+ else if (c == '\\') {
+ if (current == end)
+ return addError("Empty escape sequence in string", token,
+ current);
+ Char escape = *current++;
+ switch (escape) {
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ }
+ break;
+ default:
+ return addError("Bad escape sequence in string", token, current);
+ }
+ } else {
+ decoded += c;
+ }
+ }
+ return true;
+}
+
+bool Reader::decodeUnicodeCodePoint(Token &token, Location ¤t,
+ Location end, unsigned int &unicode) {
+
+ if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ return false;
+ if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+ // surrogate pairs
+ if (end - current < 6)
+ return addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token, current);
+ unsigned int surrogatePair;
+ if (*(current++) == '\\' && *(current++) == 'u') {
+ if (decodeUnicodeEscapeSequence(token, current, end,
+ surrogatePair)) {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10)
+ + (surrogatePair & 0x3FF);
+ } else
+ return false;
+ } else
+ return addError(
+ "expecting another \\u token to begin the second half of a unicode surrogate pair",
+ token, current);
+ }
+ return true;
+}
+
+bool Reader::decodeUnicodeEscapeSequence(Token &token, Location ¤t,
+ Location end, unsigned int &unicode) {
+ if (end - current < 4)
+ return addError(
+ "Bad unicode escape sequence in string: four digits expected.",
+ token, current);
+ unicode = 0;
+ for (int index = 0; index < 4; ++index) {
+ Char c = *current++;
+ unicode *= 16;
+ if (c >= '0' && c <= '9')
+ unicode += c - '0';
+ else if (c >= 'a' && c <= 'f')
+ unicode += c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ unicode += c - 'A' + 10;
+ else
+ return addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token, current);
+ }
+ return true;
+}
+
+bool Reader::addError(const std::string &message, Token &token,
+ Location extra) {
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = extra;
+ errors_.push_back(info);
+ return false;
+}
+
+bool Reader::recoverFromError(TokenType skipUntilToken) {
+ int errorCount = int(errors_.size());
+ Token skip;
+ while (true) {
+ if (!readToken(skip))
+ errors_.resize(errorCount); // discard errors caused by recovery
+ if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+ break;
+ }
+ errors_.resize(errorCount);
+ return false;
+}
+
+bool Reader::addErrorAndRecover(const std::string &message, Token &token,
+ TokenType skipUntilToken) {
+ addError(message, token);
+ return recoverFromError(skipUntilToken);
+}
+
+Value &
+Reader::currentValue() {
+ return *(nodes_.top());
+}
+
+Reader::Char Reader::getNextChar() {
+ if (current_ == end_)
+ return 0;
+ return *current_++;
+}
+
+void Reader::getLocationLineAndColumn(Location location, int &line,
+ int &column) const {
+ Location current = begin_;
+ Location lastLineStart = current;
+ line = 0;
+ while (current < location && current != end_) {
+ Char c = *current++;
+ if (c == '\r') {
+ if (*current == '\n')
+ ++current;
+ lastLineStart = current;
+ ++line;
+ } else if (c == '\n') {
+ lastLineStart = current;
+ ++line;
+ }
+ }
+ // column & line start at 1
+ column = int(location - lastLineStart) + 1;
+ ++line;
+}
+
+std::string Reader::getLocationLineAndColumn(Location location) const {
+ int line, column;
+ getLocationLineAndColumn(location, line, column);
+ char buffer[18 + 16 + 16 + 1];
+ sprintf(buffer, "Line %d, Column %d", line, column);
+ return buffer;
+}
+
+std::string Reader::getFormatedErrorMessages() const {
+ std::string formattedMessage;
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end(); ++itError) {
+ const ErrorInfo &error = *itError;
+ formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_)
+ + "\n";
+ formattedMessage += " " + error.message_ + "\n";
+ if (error.extra_)
+ formattedMessage += "See " + getLocationLineAndColumn(error.extra_)
+ + " for detail.\n";
+ }
+ return formattedMessage;
+}
+
+std::istream& operator>>(std::istream &sin, Value &root) {
+ Json::Reader reader;
+ bool ok = reader.parse(sin, root, true);
+ //JSON_ASSERT( ok );
+ if (!ok)
+ throw std::runtime_error(reader.getFormatedErrorMessages());
+ return sin;
+}
+
+} // namespace Json
--- /dev/null
+#include <iostream>
+#include <json/value.h>
+#include <json/writer.h>
+#include <utility>
+#include <stdexcept>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+# include <cpptl/conststring.h>
+#endif
+#include <cstddef> // size_t
+#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+# include "json_batchallocator.h"
+#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+#define JSON_ASSERT_UNREACHABLE assert( false )
+#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
+#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
+
+namespace Json {
+
+const Value Value::null;
+const Int Value::minInt = Int(~(UInt(-1) / 2));
+const Int Value::maxInt = Int(UInt(-1) / 2);
+const UInt Value::maxUInt = UInt(-1);
+
+// A "safe" implementation of strdup. Allow null pointer to be passed.
+// Also avoid warning on msvc80.
+//
+//inline char *safeStringDup( const char *czstring )
+//{
+// if ( czstring )
+// {
+// const size_t length = (unsigned int)( strlen(czstring) + 1 );
+// char *newString = static_cast<char *>( malloc( length ) );
+// memcpy( newString, czstring, length );
+// return newString;
+// }
+// return 0;
+//}
+//
+//inline char *safeStringDup( const std::string &str )
+//{
+// if ( !str.empty() )
+// {
+// const size_t length = str.length();
+// char *newString = static_cast<char *>( malloc( length + 1 ) );
+// memcpy( newString, str.c_str(), length );
+// newString[length] = 0;
+// return newString;
+// }
+// return 0;
+//}
+
+ValueAllocator::~ValueAllocator() {
+}
+
+class DefaultValueAllocator: public ValueAllocator {
+public:
+ virtual ~DefaultValueAllocator() {
+ }
+
+ virtual char *makeMemberName(const char *memberName) {
+ return duplicateStringValue(memberName);
+ }
+
+ virtual void releaseMemberName(char *memberName) {
+ releaseStringValue(memberName);
+ }
+
+ virtual char *duplicateStringValue(const char *value, unsigned int length =
+ unknown) {
+ //@todo invesgate this old optimization
+ //if ( !value || value[0] == 0 )
+ // return 0;
+
+ if (length == unknown)
+ length = (unsigned int) strlen(value);
+ char *newString = static_cast<char *>(malloc(length + 1));
+ memcpy(newString, value, length);
+ newString[length] = 0;
+ return newString;
+ }
+
+ virtual void releaseStringValue(char *value) {
+ if (value)
+ free(value);
+ }
+};
+
+static ValueAllocator *&valueAllocator() {
+ static DefaultValueAllocator defaultAllocator;
+ static ValueAllocator *valueAllocator = &defaultAllocator;
+ return valueAllocator;
+}
+
+static struct DummyValueAllocatorInitializer {
+ DummyValueAllocatorInitializer() {
+ valueAllocator(); // ensure valueAllocator() statics are initialized before main().
+ }
+} dummyValueAllocatorInitializer;
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+# include "json_internalarray.inl"
+# include "json_internalmap.inl"
+#endif // JSON_VALUE_USE_INTERNAL_MAP
+# include "json_valueiterator.inl"
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+Value::CommentInfo::CommentInfo() :
+ comment_(0) {
+}
+
+Value::CommentInfo::~CommentInfo() {
+ if (comment_)
+ valueAllocator()->releaseStringValue(comment_);
+}
+
+void Value::CommentInfo::setComment(const char *text) {
+ if (comment_)
+ valueAllocator()->releaseStringValue(comment_);
+ JSON_ASSERT(text);
+ JSON_ASSERT_MESSAGE(text[0] == '\0' || text[0] == '/',
+ "Comments must start with /");
+ // It seems that /**/ style comments are acceptable as well.
+ comment_ = valueAllocator()->duplicateStringValue(text);
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+// Notes: index_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString(int index) :
+ cstr_(0), index_(index) {
+}
+
+Value::CZString::CZString(const char *cstr, DuplicationPolicy allocate) :
+ cstr_(
+ allocate == duplicate ?
+ valueAllocator()->makeMemberName(cstr) : cstr), index_(
+ allocate) {
+}
+
+Value::CZString::CZString(const CZString &other) :
+ cstr_(
+ other.index_ != noDuplication && other.cstr_ != 0 ?
+ valueAllocator()->makeMemberName(other.cstr_) :
+ other.cstr_), index_(
+ other.cstr_ ?
+ (other.index_ == noDuplication ?
+ noDuplication : duplicate) :
+ other.index_) {
+}
+
+Value::CZString::~CZString() {
+ if (cstr_ && index_ == duplicate)
+ valueAllocator()->releaseMemberName(const_cast<char *>(cstr_));
+}
+
+void Value::CZString::swap(CZString &other) {
+ std::swap(cstr_, other.cstr_);
+ std::swap(index_, other.index_);
+}
+
+Value::CZString &
+Value::CZString::operator =(const CZString &other) {
+ CZString temp(other);
+ swap(temp);
+ return *this;
+}
+
+bool Value::CZString::operator<(const CZString &other) const {
+ if (cstr_)
+ return strcmp(cstr_, other.cstr_) < 0;
+ return index_ < other.index_;
+}
+
+bool Value::CZString::operator==(const CZString &other) const {
+ if (cstr_)
+ return strcmp(cstr_, other.cstr_) == 0;
+ return index_ == other.index_;
+}
+
+int Value::CZString::index() const {
+ return index_;
+}
+
+const char *
+Value::CZString::c_str() const {
+ return cstr_;
+}
+
+bool Value::CZString::isStaticString() const {
+ return index_ == noDuplication;
+}
+
+#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value(ValueType type) :
+ type_(type), allocated_(0), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ switch (type) {
+ case nullValue:
+ break;
+ case intValue:
+ case uintValue:
+ value_.int_ = 0;
+ break;
+ case realValue:
+ value_.real_ = 0.0;
+ break;
+ case stringValue:
+ value_.string_ = 0;
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues();
+ break;
+#else
+ case arrayValue:
+ value_.array_ = arrayAllocator()->newArray();
+ break;
+ case objectValue:
+ value_.map_ = mapAllocator()->newMap();
+ break;
+#endif
+ case booleanValue:
+ value_.bool_ = false;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+Value::Value(Int value) :
+ type_(intValue), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.int_ = value;
+}
+
+Value::Value(UInt value) :
+ type_(uintValue), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.uint_ = value;
+}
+
+Value::Value(double value) :
+ type_(realValue), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.real_ = value;
+}
+
+Value::Value(const char *value) :
+ type_(stringValue), allocated_(true), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue(value);
+}
+
+Value::Value(const char *beginValue, const char *endValue) :
+ type_(stringValue), allocated_(true), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue(beginValue,
+ UInt(endValue - beginValue));
+}
+
+Value::Value(const std::string &value) :
+ type_(stringValue), allocated_(true), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue(value.c_str(),
+ (unsigned int) value.length());
+
+}
+
+Value::Value(const StaticString &value) :
+ type_(stringValue), allocated_(false), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = const_cast<char *>(value.c_str());
+}
+
+# ifdef JSON_USE_CPPTL
+Value::Value( const CppTL::ConstString &value )
+: type_( stringValue )
+, allocated_( true )
+, comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
+}
+# endif
+
+Value::Value(bool value) :
+ type_(booleanValue), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ value_.bool_ = value;
+}
+
+Value::Value(const Value &other) :
+ type_(other.type_), comments_(0)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+, itemIsUsed_( 0 )
+#endif
+{
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ value_ = other.value_;
+ break;
+ case stringValue:
+ if (other.value_.string_) {
+ value_.string_ = valueAllocator()->duplicateStringValue(
+ other.value_.string_);
+ allocated_ = true;
+ } else
+ value_.string_ = 0;
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues(*other.value_.map_);
+ break;
+#else
+ case arrayValue:
+ value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
+ break;
+ case objectValue:
+ value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
+ break;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ if (other.comments_) {
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
+ const CommentInfo &otherComment = other.comments_[comment];
+ if (otherComment.comment_)
+ comments_[comment].setComment(otherComment.comment_);
+ }
+ }
+}
+
+Value::~Value() {
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if (allocated_)
+ valueAllocator()->releaseStringValue(value_.string_);
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ delete value_.map_;
+ break;
+#else
+ case arrayValue:
+ arrayAllocator()->destructArray( value_.array_ );
+ break;
+ case objectValue:
+ mapAllocator()->destructMap( value_.map_ );
+ break;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+
+ if (comments_)
+ delete[] comments_;
+}
+
+Value &
+Value::operator=(const Value &other) {
+ Value temp(other);
+ swap(temp);
+ return *this;
+}
+
+void Value::swap(Value &other) {
+ ValueType temp = type_;
+ type_ = other.type_;
+ other.type_ = temp;
+ std::swap(value_, other.value_);
+ int temp2 = allocated_;
+ allocated_ = other.allocated_;
+ other.allocated_ = temp2;
+}
+
+ValueType Value::type() const {
+ return type_;
+}
+
+int Value::compare(const Value &other) {
+ /*
+ int typeDelta = other.type_ - type_;
+ switch ( type_ )
+ {
+ case nullValue:
+
+ return other.type_ == type_;
+ case intValue:
+ if ( other.type_.isNumeric()
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue,
+ break;
+ case arrayValue:
+ delete value_.array_;
+ break;
+ case objectValue:
+ delete value_.map_;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ */
+ return 0; // unreachable
+}
+
+bool Value::operator <(const Value &other) const {
+ int typeDelta = type_ - other.type_;
+ if (typeDelta)
+ return typeDelta < 0 ? true : false;
+ switch (type_) {
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ < other.value_.int_;
+ case uintValue:
+ return value_.uint_ < other.value_.uint_;
+ case realValue:
+ return value_.real_ < other.value_.real_;
+ case booleanValue:
+ return value_.bool_ < other.value_.bool_;
+ case stringValue:
+ return (value_.string_ == 0 && other.value_.string_)
+ || (other.value_.string_ && value_.string_
+ && strcmp(value_.string_, other.value_.string_) < 0);
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue: {
+ int delta = int(value_.map_->size() - other.value_.map_->size());
+ if (delta)
+ return delta < 0;
+ return (*value_.map_) < (*other.value_.map_);
+ }
+#else
+ case arrayValue:
+ return value_.array_->compare( *(other.value_.array_) ) < 0;
+ case objectValue:
+ return value_.map_->compare( *(other.value_.map_) ) < 0;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable
+}
+
+bool Value::operator <=(const Value &other) const {
+ return !(other > *this);
+}
+
+bool Value::operator >=(const Value &other) const {
+ return !(*this < other);
+}
+
+bool Value::operator >(const Value &other) const {
+ return other < *this;
+}
+
+bool Value::operator ==(const Value &other) const {
+ //if ( type_ != other.type_ )
+ // GCC 2.95.3 says:
+ // attempt to take address of bit-field structure member `Json::Value::type_'
+ // Beats me, but a temp solves the problem.
+ int temp = other.type_;
+ if (type_ != temp)
+ return false;
+ switch (type_) {
+ case nullValue:
+ return true;
+ case intValue:
+ return value_.int_ == other.value_.int_;
+ case uintValue:
+ return value_.uint_ == other.value_.uint_;
+ case realValue:
+ return value_.real_ == other.value_.real_;
+ case booleanValue:
+ return value_.bool_ == other.value_.bool_;
+ case stringValue:
+ return (value_.string_ == other.value_.string_)
+ || (other.value_.string_ && value_.string_
+ && strcmp(value_.string_, other.value_.string_) == 0);
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() == other.value_.map_->size()
+ && (*value_.map_) == (*other.value_.map_);
+#else
+ case arrayValue:
+ return value_.array_->compare( *(other.value_.array_) ) == 0;
+ case objectValue:
+ return value_.map_->compare( *(other.value_.map_) ) == 0;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable
+}
+
+bool Value::operator !=(const Value &other) const {
+ return !(*this == other);
+}
+
+const char *
+Value::asCString() const {
+ JSON_ASSERT(type_ == stringValue);
+ return value_.string_;
+}
+
+std::string Value::asString() const {
+ switch (type_) {
+ case nullValue:
+ return "";
+ case stringValue:
+ return value_.string_ ? value_.string_ : "";
+ case booleanValue:
+ return value_.bool_ ? "true" : "false";
+ case intValue:
+ case uintValue:
+ case realValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE(false, "Type is not convertible to string")
+ ;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return ""; // unreachable
+}
+
+# ifdef JSON_USE_CPPTL
+CppTL::ConstString
+Value::asConstString() const
+{
+ return CppTL::ConstString( asString().c_str() );
+}
+# endif
+
+Value::Int Value::asInt() const {
+ switch (type_) {
+ case nullValue:
+ return 0;
+ case intValue:
+ return value_.int_;
+ case uintValue:
+ JSON_ASSERT_MESSAGE(value_.uint_ < (unsigned )maxInt,
+ "integer out of signed integer range")
+ ;
+ return value_.uint_;
+ case realValue:
+ JSON_ASSERT_MESSAGE(value_.real_ >= minInt && value_.real_ <= maxInt,
+ "Real out of signed integer range")
+ ;
+ return Int(value_.real_);
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE(false, "Type is not convertible to int")
+ ;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+Value::UInt Value::asUInt() const {
+ switch (type_) {
+ case nullValue:
+ return 0;
+ case intValue:
+ JSON_ASSERT_MESSAGE(value_.int_ >= 0,
+ "Negative integer can not be converted to unsigned integer")
+ ;
+ return value_.int_;
+ case uintValue:
+ return value_.uint_;
+ case realValue:
+ JSON_ASSERT_MESSAGE(value_.real_ >= 0 && value_.real_ <= maxUInt,
+ "Real out of unsigned integer range")
+ ;
+ return UInt(value_.real_);
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE(false, "Type is not convertible to uint")
+ ;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+double Value::asDouble() const {
+ switch (type_) {
+ case nullValue:
+ return 0.0;
+ case intValue:
+ return value_.int_;
+ case uintValue:
+ return value_.uint_;
+ case realValue:
+ return value_.real_;
+ case booleanValue:
+ return value_.bool_ ? 1.0 : 0.0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE(false, "Type is not convertible to double")
+ ;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+bool Value::asBool() const {
+ switch (type_) {
+ case nullValue:
+ return false;
+ case intValue:
+ case uintValue:
+ return value_.int_ != 0;
+ case realValue:
+ return value_.real_ != 0.0;
+ case booleanValue:
+ return value_.bool_;
+ case stringValue:
+ return value_.string_ && value_.string_[0] != 0;
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() != 0;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable;
+}
+
+bool Value::isConvertibleTo(ValueType other) const {
+ switch (type_) {
+ case nullValue:
+ return true;
+ case intValue:
+ return (other == nullValue && value_.int_ == 0) || other == intValue
+ || (other == uintValue && value_.int_ >= 0)
+ || other == realValue || other == stringValue
+ || other == booleanValue;
+ case uintValue:
+ return (other == nullValue && value_.uint_ == 0)
+ || (other == intValue && value_.uint_ <= (unsigned) maxInt)
+ || other == uintValue || other == realValue
+ || other == stringValue || other == booleanValue;
+ case realValue:
+ return (other == nullValue && value_.real_ == 0.0)
+ || (other == intValue && value_.real_ >= minInt
+ && value_.real_ <= maxInt)
+ || (other == uintValue && value_.real_ >= 0
+ && value_.real_ <= maxUInt) || other == realValue
+ || other == stringValue || other == booleanValue;
+ case booleanValue:
+ return (other == nullValue && value_.bool_ == false)
+ || other == intValue || other == uintValue || other == realValue
+ || other == stringValue || other == booleanValue;
+ case stringValue:
+ return other == stringValue
+ || (other == nullValue
+ && (!value_.string_ || value_.string_[0] == 0));
+ case arrayValue:
+ return other == arrayValue
+ || (other == nullValue && value_.map_->size() == 0);
+ case objectValue:
+ return other == objectValue
+ || (other == nullValue && value_.map_->size() == 0);
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable;
+}
+
+/// Number of values in array or object
+Value::UInt Value::size() const {
+ switch (type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ case stringValue:
+ return 0;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue: // size of the array is highest index + 1
+ if (!value_.map_->empty()) {
+ ObjectValues::const_iterator itLast = value_.map_->end();
+ --itLast;
+ return (*itLast).first.index() + 1;
+ }
+ return 0;
+ case objectValue:
+ return Int(value_.map_->size());
+#else
+ case arrayValue:
+ return Int( value_.array_->size() );
+ case objectValue:
+ return Int( value_.map_->size() );
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+bool Value::empty() const {
+ if (isNull() || isArray() || isObject())
+ return size() == 0u;
+ else
+ return false;
+}
+
+bool Value::operator!() const {
+ return isNull();
+}
+
+void Value::clear() {
+ JSON_ASSERT(
+ type_ == nullValue || type_ == arrayValue || type_ == objectValue);
+
+ switch (type_) {
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_->clear();
+ break;
+#else
+ case arrayValue:
+ value_.array_->clear();
+ break;
+ case objectValue:
+ value_.map_->clear();
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+void Value::resize(UInt newSize) {
+ JSON_ASSERT(type_ == nullValue || type_ == arrayValue);
+ if (type_ == nullValue)
+ *this = Value(arrayValue);
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ UInt oldSize = size();
+ if (newSize == 0)
+ clear();
+ else if (newSize > oldSize)
+ (*this)[newSize - 1];
+ else {
+ for (UInt index = newSize; index < oldSize; ++index)
+ value_.map_->erase(index);
+ assert(size() == newSize);
+ }
+#else
+ value_.array_->resize( newSize );
+#endif
+}
+
+Value &
+Value::operator[](UInt index) {
+ JSON_ASSERT(type_ == nullValue || type_ == arrayValue);
+ if (type_ == nullValue)
+ *this = Value(arrayValue);
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString key(index);
+ ObjectValues::iterator it = value_.map_->lower_bound(key);
+ if (it != value_.map_->end() && (*it).first == key)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(key, null);
+ it = value_.map_->insert(it, defaultValue);
+ return (*it).second;
+#else
+ return value_.array_->resolveReference( index );
+#endif
+}
+
+const Value &
+Value::operator[](UInt index) const {
+ JSON_ASSERT(type_ == nullValue || type_ == arrayValue);
+ if (type_ == nullValue)
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString key(index);
+ ObjectValues::const_iterator it = value_.map_->find(key);
+ if (it == value_.map_->end())
+ return null;
+ return (*it).second;
+#else
+ Value *value = value_.array_->find( index );
+ return value ? *value : null;
+#endif
+}
+
+Value &
+Value::operator[](const char *key) {
+ return resolveReference(key, false);
+}
+
+Value &
+Value::resolveReference(const char *key, bool isStatic) {
+ JSON_ASSERT(type_ == nullValue || type_ == objectValue);
+ if (type_ == nullValue)
+ *this = Value(objectValue);
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey(key,
+ isStatic ? CZString::noDuplication : CZString::duplicateOnCopy);
+ ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+ if (it != value_.map_->end() && (*it).first == actualKey)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(actualKey, null);
+ it = value_.map_->insert(it, defaultValue);
+ Value &value = (*it).second;
+ return value;
+#else
+ return value_.map_->resolveReference( key, isStatic );
+#endif
+}
+
+Value Value::get(UInt index, const Value &defaultValue) const {
+ const Value *value = &((*this)[index]);
+ return value == &null ? defaultValue : *value;
+}
+
+bool Value::isValidIndex(UInt index) const {
+ return index < size();
+}
+
+const Value &
+Value::operator[](const char *key) const {
+ JSON_ASSERT(type_ == nullValue || type_ == objectValue);
+ if (type_ == nullValue)
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey(key, CZString::noDuplication);
+ ObjectValues::const_iterator it = value_.map_->find(actualKey);
+ if (it == value_.map_->end())
+ return null;
+ return (*it).second;
+#else
+ const Value *value = value_.map_->find( key );
+ return value ? *value : null;
+#endif
+}
+
+Value &
+Value::operator[](const std::string &key) {
+ return (*this)[key.c_str()];
+}
+
+const Value &
+Value::operator[](const std::string &key) const {
+ return (*this)[key.c_str()];
+}
+
+Value &
+Value::operator[](const StaticString &key) {
+ return resolveReference(key, true);
+}
+
+# ifdef JSON_USE_CPPTL
+Value &
+Value::operator[]( const CppTL::ConstString &key )
+{
+ return (*this)[ key.c_str() ];
+}
+
+const Value &
+Value::operator[]( const CppTL::ConstString &key ) const
+{
+ return (*this)[ key.c_str() ];
+}
+# endif
+
+Value &
+Value::append(const Value &value) {
+ return (*this)[size()] = value;
+}
+
+Value Value::get(const char *key, const Value &defaultValue) const {
+ const Value *value = &((*this)[key]);
+ return value == &null ? defaultValue : *value;
+}
+
+Value Value::get(const std::string &key, const Value &defaultValue) const {
+ return get(key.c_str(), defaultValue);
+}
+
+Value Value::removeMember(const char* key) {
+ JSON_ASSERT(type_ == nullValue || type_ == objectValue);
+ if (type_ == nullValue)
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey(key, CZString::noDuplication);
+ ObjectValues::iterator it = value_.map_->find(actualKey);
+ if (it == value_.map_->end())
+ return null;
+ Value old(it->second);
+ value_.map_->erase(it);
+ return old;
+#else
+ Value *value = value_.map_->find( key );
+ if (value) {
+ Value old(*value);
+ value_.map_.remove( key );
+ return old;
+ } else {
+ return null;
+ }
+#endif
+}
+
+Value Value::removeMember(const std::string &key) {
+ return removeMember(key.c_str());
+}
+
+# ifdef JSON_USE_CPPTL
+Value
+Value::get( const CppTL::ConstString &key,
+ const Value &defaultValue ) const
+{
+ return get( key.c_str(), defaultValue );
+}
+# endif
+
+bool Value::isMember(const char *key) const {
+ const Value *value = &((*this)[key]);
+ return value != &null;
+}
+
+bool Value::isMember(const std::string &key) const {
+ return isMember(key.c_str());
+}
+
+# ifdef JSON_USE_CPPTL
+bool
+Value::isMember( const CppTL::ConstString &key ) const
+{
+ return isMember( key.c_str() );
+}
+#endif
+
+Value::Members Value::getMemberNames() const {
+ JSON_ASSERT(type_ == nullValue || type_ == objectValue);
+ if (type_ == nullValue)
+ return Value::Members();
+ Members members;
+ members.reserve(value_.map_->size());
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ ObjectValues::const_iterator it = value_.map_->begin();
+ ObjectValues::const_iterator itEnd = value_.map_->end();
+ for (; it != itEnd; ++it)
+ members.push_back(std::string((*it).first.c_str()));
+#else
+ ValueInternalMap::IteratorState it;
+ ValueInternalMap::IteratorState itEnd;
+ value_.map_->makeBeginIterator( it );
+ value_.map_->makeEndIterator( itEnd );
+ for (; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
+ members.push_back( std::string( ValueInternalMap::key( it ) ) );
+#endif
+ return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+//EnumMemberNames
+//Value::enumMemberNames() const
+//{
+// if ( type_ == objectValue )
+// {
+// return CppTL::Enum::any( CppTL::Enum::transform(
+// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+// MemberNamesTransform() ) );
+// }
+// return EnumMemberNames();
+//}
+//
+//
+//EnumValues
+//Value::enumValues() const
+//{
+// if ( type_ == objectValue || type_ == arrayValue )
+// return CppTL::Enum::anyValues( *(value_.map_),
+// CppTL::Type<const Value &>() );
+// return EnumValues();
+//}
+//
+//# endif
+
+bool Value::isNull() const {
+ return type_ == nullValue;
+}
+
+bool Value::isBool() const {
+ return type_ == booleanValue;
+}
+
+bool Value::isInt() const {
+ return type_ == intValue;
+}
+
+bool Value::isUInt() const {
+ return type_ == uintValue;
+}
+
+bool Value::isIntegral() const {
+ return type_ == intValue || type_ == uintValue || type_ == booleanValue;
+}
+
+bool Value::isDouble() const {
+ return type_ == realValue;
+}
+
+bool Value::isNumeric() const {
+ return isIntegral() || isDouble();
+}
+
+bool Value::isString() const {
+ return type_ == stringValue;
+}
+
+bool Value::isArray() const {
+ return type_ == nullValue || type_ == arrayValue;
+}
+
+bool Value::isObject() const {
+ return type_ == nullValue || type_ == objectValue;
+}
+
+void Value::setComment(const char *comment, CommentPlacement placement) {
+ if (!comments_)
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ comments_[placement].setComment(comment);
+}
+
+void Value::setComment(const std::string &comment, CommentPlacement placement) {
+ setComment(comment.c_str(), placement);
+}
+
+bool Value::hasComment(CommentPlacement placement) const {
+ return comments_ != 0 && comments_[placement].comment_ != 0;
+}
+
+std::string Value::getComment(CommentPlacement placement) const {
+ if (hasComment(placement))
+ return comments_[placement].comment_;
+ return "";
+}
+
+std::string Value::toStyledString() const {
+ StyledWriter writer;
+ return writer.write(*this);
+}
+
+Value::const_iterator Value::begin() const {
+ switch (type_) {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeBeginIterator( it );
+ return const_iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeBeginIterator( it );
+ return const_iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->begin());
+ break;
+#endif
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+Value::const_iterator Value::end() const {
+ switch (type_) {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeEndIterator( it );
+ return const_iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeEndIterator( it );
+ return const_iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->end());
+ break;
+#endif
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+Value::iterator Value::begin() {
+ switch (type_) {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeBeginIterator( it );
+ return iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeBeginIterator( it );
+ return iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->begin());
+ break;
+#endif
+ default:
+ break;
+ }
+ return iterator();
+}
+
+Value::iterator Value::end() {
+ switch (type_) {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeEndIterator( it );
+ return iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeEndIterator( it );
+ return iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->end());
+ break;
+#endif
+ default:
+ break;
+ }
+ return iterator();
+}
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument() :
+ kind_(kindNone) {
+}
+
+PathArgument::PathArgument(Value::UInt index) :
+ index_(index), kind_(kindIndex) {
+}
+
+PathArgument::PathArgument(const char *key) :
+ key_(key), kind_(kindKey) {
+}
+
+PathArgument::PathArgument(const std::string &key) :
+ key_(key.c_str()), kind_(kindKey) {
+}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path(const std::string &path, const PathArgument &a1,
+ const PathArgument &a2, const PathArgument &a3, const PathArgument &a4,
+ const PathArgument &a5) {
+ InArgs in;
+ in.push_back(&a1);
+ in.push_back(&a2);
+ in.push_back(&a3);
+ in.push_back(&a4);
+ in.push_back(&a5);
+ makePath(path, in);
+}
+
+void Path::makePath(const std::string &path, const InArgs &in) {
+ const char *current = path.c_str();
+ const char *end = current + path.length();
+ InArgs::const_iterator itInArg = in.begin();
+ while (current != end) {
+ if (*current == '[') {
+ ++current;
+ if (*current == '%')
+ addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+ else {
+ Value::UInt index = 0;
+ for (; current != end && *current >= '0' && *current <= '9';
+ ++current)
+ index = index * 10 + Value::UInt(*current - '0');
+ args_.push_back(index);
+ }
+ if (current == end || *current++ != ']')
+ invalidPath(path, int(current - path.c_str()));
+ } else if (*current == '%') {
+ addPathInArg(path, in, itInArg, PathArgument::kindKey);
+ ++current;
+ } else if (*current == '.') {
+ ++current;
+ } else {
+ const char *beginName = current;
+ while (current != end && !strchr("[.", *current))
+ ++current;
+ args_.push_back(std::string(beginName, current));
+ }
+ }
+}
+
+void Path::addPathInArg(const std::string &path, const InArgs &in,
+ InArgs::const_iterator &itInArg, PathArgument::Kind kind) {
+ if (itInArg == in.end()) {
+ // Error: missing argument %d
+ } else if ((*itInArg)->kind_ != kind) {
+ // Error: bad argument type
+ } else {
+ args_.push_back(**itInArg);
+ }
+}
+
+void Path::invalidPath(const std::string &path, int location) {
+ // Error: invalid path.
+}
+
+const Value &
+Path::resolve(const Value &root) const {
+ const Value *node = &root;
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ const PathArgument &arg = *it;
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray() || node->isValidIndex(arg.index_)) {
+ // Error: unable to resolve path (array value expected at position...
+ }
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject()) {
+ // Error: unable to resolve path (object value expected at position...)
+ }
+ node = &((*node)[arg.key_]);
+ if (node == &Value::null) {
+ // Error: unable to resolve path (object has no member named '' at position...)
+ }
+ }
+ }
+ return *node;
+}
+
+Value Path::resolve(const Value &root, const Value &defaultValue) const {
+ const Value *node = &root;
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ const PathArgument &arg = *it;
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray() || node->isValidIndex(arg.index_))
+ return defaultValue;
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject())
+ return defaultValue;
+ node = &((*node)[arg.key_]);
+ if (node == &Value::null)
+ return defaultValue;
+ }
+ }
+ return *node;
+}
+
+Value &
+Path::make(Value &root) const {
+ Value *node = &root;
+ for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ const PathArgument &arg = *it;
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray()) {
+ // Error: node is not an array at position ...
+ }
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject()) {
+ // Error: node is not an object at position...
+ }
+ node = &((*node)[arg.key_]);
+ }
+ }
+ return *node;
+}
+
+} // namespace Json
--- /dev/null
+// included by json_value.cpp
+// everything is within Json namespace
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ : current_()
+ , isNull_( true )
+{
+}
+#else
+ : isArray_( true )
+ , isNull_( true )
+{
+ iterator_.array_ = ValueInternalArray::IteratorState();
+}
+#endif
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t )
+ : current_( current )
+ , isNull_( false )
+{
+}
+#else
+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
+ : isArray_( true )
+{
+ iterator_.array_ = state;
+}
+
+
+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
+ : isArray_( false )
+{
+ iterator_.map_ = state;
+}
+#endif
+
+Value &
+ValueIteratorBase::deref() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ return current_->second;
+#else
+ if ( isArray_ )
+ return ValueInternalArray::dereference( iterator_.array_ );
+ return ValueInternalMap::value( iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::increment()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ ++current_;
+#else
+ if ( isArray_ )
+ ValueInternalArray::increment( iterator_.array_ );
+ ValueInternalMap::increment( iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::decrement()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ --current_;
+#else
+ if ( isArray_ )
+ ValueInternalArray::decrement( iterator_.array_ );
+ ValueInternalMap::decrement( iterator_.map_ );
+#endif
+}
+
+
+ValueIteratorBase::difference_type
+ValueIteratorBase::computeDistance( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+# ifdef JSON_USE_CPPTL_SMALLMAP
+ return current_ - other.current_;
+# else
+ // Iterator for null value are initialized using the default
+ // constructor, which initialize current_ to the default
+ // std::map::iterator. As begin() and end() are two instance
+ // of the default std::map::iterator, they can not be compared.
+ // To allow this, we handle this comparison specifically.
+ if ( isNull_ && other.isNull_ )
+ {
+ return 0;
+ }
+
+
+ // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
+ // which is the one used by default).
+ // Using a portable hand-made version for non random iterator instead:
+ // return difference_type( std::distance( current_, other.current_ ) );
+ difference_type myDistance = 0;
+ for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
+ {
+ ++myDistance;
+ }
+ return myDistance;
+# endif
+#else
+ if ( isArray_ )
+ return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
+ return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+bool
+ValueIteratorBase::isEqual( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ if ( isNull_ )
+ {
+ return other.isNull_;
+ }
+ return current_ == other.current_;
+#else
+ if ( isArray_ )
+ return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
+ return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::copy( const SelfType &other )
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ current_ = other.current_;
+#else
+ if ( isArray_ )
+ iterator_.array_ = other.iterator_.array_;
+ iterator_.map_ = other.iterator_.map_;
+#endif
+}
+
+
+Value
+ValueIteratorBase::key() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const Value::CZString czstring = (*current_).first;
+ if ( czstring.c_str() )
+ {
+ if ( czstring.isStaticString() )
+ return Value( StaticString( czstring.c_str() ) );
+ return Value( czstring.c_str() );
+ }
+ return Value( czstring.index() );
+#else
+ if ( isArray_ )
+ return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
+ bool isStatic;
+ const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
+ if ( isStatic )
+ return Value( StaticString( memberName ) );
+ return Value( memberName );
+#endif
+}
+
+
+UInt
+ValueIteratorBase::index() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const Value::CZString czstring = (*current_).first;
+ if ( !czstring.c_str() )
+ return czstring.index();
+ return Value::UInt( -1 );
+#else
+ if ( isArray_ )
+ return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
+ return Value::UInt( -1 );
+#endif
+}
+
+
+const char *
+ValueIteratorBase::memberName() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const char *name = (*current_).first.c_str();
+ return name ? name : "";
+#else
+ if ( !isArray_ )
+ return ValueInternalMap::key( iterator_.map_ );
+ return "";
+#endif
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t )
+ : ValueIteratorBase( current )
+{
+}
+#else
+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+
+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueConstIterator &
+ValueConstIterator::operator =( const ValueIteratorBase &other )
+{
+ copy( other );
+ return *this;
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t )
+ : ValueIteratorBase( current )
+{
+}
+#else
+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+
+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueIterator::ValueIterator( const ValueConstIterator &other )
+ : ValueIteratorBase( other )
+{
+}
+
+ValueIterator::ValueIterator( const ValueIterator &other )
+ : ValueIteratorBase( other )
+{
+}
+
+ValueIterator &
+ValueIterator::operator =( const SelfType &other )
+{
+ copy( other );
+ return *this;
+}
--- /dev/null
+#include <json/writer.h>
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+static bool isControlCharacter(char ch) {
+ return ch > 0 && ch <= 0x1F;
+}
+
+static bool containsControlCharacter(const char* str) {
+ while (*str) {
+ if (isControlCharacter(*(str++)))
+ return true;
+ }
+ return false;
+}
+static void uintToString(unsigned int value, char *¤t) {
+ *--current = 0;
+ do {
+ *--current = (value % 10) + '0';
+ value /= 10;
+ } while (value != 0);
+}
+
+std::string valueToString(Int value) {
+ char buffer[32];
+ char *current = buffer + sizeof(buffer);
+ bool isNegative = value < 0;
+ if (isNegative)
+ value = -value;
+ uintToString(UInt(value), current);
+ if (isNegative)
+ *--current = '-';
+ assert(current >= buffer);
+ return current;
+}
+
+std::string valueToString(UInt value) {
+ char buffer[32];
+ char *current = buffer + sizeof(buffer);
+ uintToString(value, current);
+ assert(current >= buffer);
+ return current;
+}
+
+std::string valueToString(double value) {
+ char buffer[32];
+#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
+ sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
+#else
+ sprintf(buffer, "%#.16g", value);
+#endif
+ char* ch = buffer + strlen(buffer) - 1;
+ if (*ch != '0')
+ return buffer; // nothing to truncate, so save time
+ while (ch > buffer && *ch == '0') {
+ --ch;
+ }
+ char* last_nonzero = ch;
+ while (ch >= buffer) {
+ switch (*ch) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ --ch;
+ continue;
+ case '.':
+ // Truncate zeroes to save bytes in output, but keep one.
+ *(last_nonzero + 2) = '\0';
+ return buffer;
+ default:
+ return buffer;
+ }
+ }
+ return buffer;
+}
+
+std::string valueToString(bool value) {
+ return value ? "true" : "false";
+}
+
+std::string valueToQuotedString(const char *value) {
+ // Not sure how to handle unicode...
+ if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL
+ && !containsControlCharacter(value))
+ return std::string("\"") + value + "\"";
+ // We have to walk value and escape any special characters.
+ // Appending to std::string is not efficient, but this should be rare.
+ // (Note: forward slashes are *not* rare, but I am not escaping them.)
+ unsigned maxsize = strlen(value) * 2 + 3; // allescaped+quotes+NULL
+ std::string result;
+ result.reserve(maxsize); // to avoid lots of mallocs
+ result += "\"";
+ for (const char* c = value; *c != 0; ++c) {
+ switch (*c) {
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ //case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default:
+ if (isControlCharacter(*c)) {
+ std::ostringstream oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ } else {
+ result += *c;
+ }
+ break;
+ }
+ }
+ result += "\"";
+ return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer() {
+}
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter() :
+ yamlCompatiblityEnabled_(false) {
+}
+
+void FastWriter::enableYAMLCompatibility() {
+ yamlCompatiblityEnabled_ = true;
+}
+
+std::string FastWriter::write(const Value &root) {
+ document_ = "";
+ writeValue(root);
+ document_ += "\n";
+ return document_;
+}
+
+void FastWriter::writeValue(const Value &value) {
+ switch (value.type()) {
+ case nullValue:
+ document_ += "null";
+ break;
+ case intValue:
+ document_ += valueToString(value.asInt());
+ break;
+ case uintValue:
+ document_ += valueToString(value.asUInt());
+ break;
+ case realValue:
+ document_ += valueToString(value.asDouble());
+ break;
+ case stringValue:
+ document_ += valueToQuotedString(value.asCString());
+ break;
+ case booleanValue:
+ document_ += valueToString(value.asBool());
+ break;
+ case arrayValue: {
+ document_ += "[";
+ int size = value.size();
+ for (int index = 0; index < size; ++index) {
+ if (index > 0)
+ document_ += ",";
+ writeValue(value[index]);
+ }
+ document_ += "]";
+ }
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ document_ += "{";
+ for (Value::Members::iterator it = members.begin(); it != members.end();
+ ++it) {
+ const std::string &name = *it;
+ if (it != members.begin())
+ document_ += ",";
+ document_ += valueToQuotedString(name.c_str());
+ document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+ writeValue(value[name]);
+ }
+ document_ += "}";
+ }
+ break;
+ }
+}
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter() :
+ rightMargin_(74), indentSize_(3) {
+}
+
+std::string StyledWriter::write(const Value &root) {
+ document_ = "";
+ addChildValues_ = false;
+ indentString_ = "";
+ writeCommentBeforeValue(root);
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ document_ += "\n";
+ return document_;
+}
+
+void StyledWriter::writeValue(const Value &value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue:
+ pushValue(valueToQuotedString(value.asCString()));
+ break;
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ while (true) {
+ const std::string &name = *it;
+ const Value &childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ document_ += " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ document_ += ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ }
+ break;
+ }
+}
+
+void StyledWriter::writeArrayValue(const Value &value) {
+ unsigned size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isArrayMultiLine = isMultineArray(value);
+ if (isArrayMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index = 0;
+ while (true) {
+ const Value &childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ writeIndent();
+ writeValue(childValue);
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ document_ += ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ document_ += "[ ";
+ for (unsigned index = 0; index < size; ++index) {
+ if (index > 0)
+ document_ += ", ";
+ document_ += childValues_[index];
+ }
+ document_ += " ]";
+ }
+ }
+}
+
+bool StyledWriter::isMultineArray(const Value &value) {
+ int size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (int index = 0; index < size && !isMultiLine; ++index) {
+ const Value &childValue = value[index];
+ isMultiLine = isMultiLine
+ || ((childValue.isArray() || childValue.isObject())
+ && childValue.size() > 0);
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (int index = 0; index < size && !isMultiLine; ++index) {
+ writeValue(value[index]);
+ lineLength += int(childValues_[index].length());
+ isMultiLine = isMultiLine && hasCommentForValue(value[index]);
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void StyledWriter::pushValue(const std::string &value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ document_ += value;
+}
+
+void StyledWriter::writeIndent() {
+ if (!document_.empty()) {
+ char last = document_[document_.length() - 1];
+ if (last == ' ') // already indented
+ return;
+ if (last != '\n') // Comments may add new-line
+ document_ += '\n';
+ }
+ document_ += indentString_;
+}
+
+void StyledWriter::writeWithIndent(const std::string &value) {
+ writeIndent();
+ document_ += value;
+}
+
+void StyledWriter::indent() {
+ indentString_ += std::string(indentSize_, ' ');
+}
+
+void StyledWriter::unindent() {
+ assert(int(indentString_.size()) >= indentSize_);
+ indentString_.resize(indentString_.size() - indentSize_);
+}
+
+void StyledWriter::writeCommentBeforeValue(const Value &root) {
+ if (!root.hasComment(commentBefore))
+ return;
+ document_ += normalizeEOL(root.getComment(commentBefore));
+ document_ += "\n";
+}
+
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value &root) {
+ if (root.hasComment(commentAfterOnSameLine))
+ document_ += " "
+ + normalizeEOL(root.getComment(commentAfterOnSameLine));
+
+ if (root.hasComment(commentAfter)) {
+ document_ += "\n";
+ document_ += normalizeEOL(root.getComment(commentAfter));
+ document_ += "\n";
+ }
+}
+
+bool StyledWriter::hasCommentForValue(const Value &value) {
+ return value.hasComment(commentBefore)
+ || value.hasComment(commentAfterOnSameLine)
+ || value.hasComment(commentAfter);
+}
+
+std::string StyledWriter::normalizeEOL(const std::string &text) {
+ std::string normalized;
+ normalized.reserve(text.length());
+ const char *begin = text.c_str();
+ const char *end = begin + text.length();
+ const char *current = begin;
+ while (current != end) {
+ char c = *current++;
+ if (c == '\r') // mac or dos EOL
+ {
+ if (*current == '\n') // convert dos EOL
+ ++current;
+ normalized += '\n';
+ } else
+ // handle unix EOL & other char
+ normalized += c;
+ }
+ return normalized;
+}
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter(std::string indentation) :
+ document_(NULL), rightMargin_(74), indentation_(indentation) {
+}
+
+void StyledStreamWriter::write(std::ostream &out, const Value &root) {
+ document_ = &out;
+ addChildValues_ = false;
+ indentString_ = "";
+ writeCommentBeforeValue(root);
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ *document_ << "\n";
+ document_ = NULL; // Forget the stream, for safety.
+}
+
+void StyledStreamWriter::writeValue(const Value &value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue:
+ pushValue(valueToQuotedString(value.asCString()));
+ break;
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ Value::Members::iterator it = members.begin();
+ while (true) {
+ const std::string &name = *it;
+ const Value &childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ *document_ << " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ }
+ break;
+ }
+}
+
+void StyledStreamWriter::writeArrayValue(const Value &value) {
+ unsigned size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isArrayMultiLine = isMultineArray(value);
+ if (isArrayMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index = 0;
+ while (true) {
+ const Value &childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ writeIndent();
+ writeValue(childValue);
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ *document_ << "[ ";
+ for (unsigned index = 0; index < size; ++index) {
+ if (index > 0)
+ *document_ << ", ";
+ *document_ << childValues_[index];
+ }
+ *document_ << " ]";
+ }
+ }
+}
+
+bool StyledStreamWriter::isMultineArray(const Value &value) {
+ int size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (int index = 0; index < size && !isMultiLine; ++index) {
+ const Value &childValue = value[index];
+ isMultiLine = isMultiLine
+ || ((childValue.isArray() || childValue.isObject())
+ && childValue.size() > 0);
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (int index = 0; index < size && !isMultiLine; ++index) {
+ writeValue(value[index]);
+ lineLength += int(childValues_[index].length());
+ isMultiLine = isMultiLine && hasCommentForValue(value[index]);
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void StyledStreamWriter::pushValue(const std::string &value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ *document_ << value;
+}
+
+void StyledStreamWriter::writeIndent() {
+ /*
+ Some comments in this method would have been nice. ;-)
+
+ if ( !document_.empty() )
+ {
+ char last = document_[document_.length()-1];
+ if ( last == ' ' ) // already indented
+ return;
+ if ( last != '\n' ) // Comments may add new-line
+ *document_ << '\n';
+ }
+ */
+ *document_ << '\n' << indentString_;
+}
+
+void StyledStreamWriter::writeWithIndent(const std::string &value) {
+ writeIndent();
+ *document_ << value;
+}
+
+void StyledStreamWriter::indent() {
+ indentString_ += indentation_;
+}
+
+void StyledStreamWriter::unindent() {
+ assert(indentString_.size() >= indentation_.size());
+ indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void StyledStreamWriter::writeCommentBeforeValue(const Value &root) {
+ if (!root.hasComment(commentBefore))
+ return;
+ *document_ << normalizeEOL(root.getComment(commentBefore));
+ *document_ << "\n";
+}
+
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value &root) {
+ if (root.hasComment(commentAfterOnSameLine))
+ *document_
+ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
+
+ if (root.hasComment(commentAfter)) {
+ *document_ << "\n";
+ *document_ << normalizeEOL(root.getComment(commentAfter));
+ *document_ << "\n";
+ }
+}
+
+bool StyledStreamWriter::hasCommentForValue(const Value &value) {
+ return value.hasComment(commentBefore)
+ || value.hasComment(commentAfterOnSameLine)
+ || value.hasComment(commentAfter);
+}
+
+std::string StyledStreamWriter::normalizeEOL(const std::string &text) {
+ std::string normalized;
+ normalized.reserve(text.length());
+ const char *begin = text.c_str();
+ const char *end = begin + text.length();
+ const char *current = begin;
+ while (current != end) {
+ char c = *current++;
+ if (c == '\r') // mac or dos EOL
+ {
+ if (*current == '\n') // convert dos EOL
+ ++current;
+ normalized += '\n';
+ } else
+ // handle unix EOL & other char
+ normalized += c;
+ }
+ return normalized;
+}
+
+std::ostream& operator<<(std::ostream &sout, const Value &root) {
+ Json::StyledStreamWriter writer;
+ writer.write(sout, root);
+ return sout;
+}
+
+} // namespace Json
--- /dev/null
+Import( 'env buildLibrary' )
+
+buildLibrary( env, Split( """
+ json_reader.cpp
+ json_value.cpp
+ json_writer.cpp
+ """ ),
+ 'json' )
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <stdlib.h>
+#include <string>
+#include <json/json.h>
+
+#include "httpserver.h"
+#if defined(__WIN32__) || defined(__WIN64__)
+#include <windows.h>
+#endif
+bool g_show_log = false;
+extern HttpServer httpserver;
+
+//parse the cmd line parameters
+void parse(int count, char *argv[], HttpServer *httpserver) {
+ for (int i = 1; i < count; ++i) {
+ string argvstr = argv[i];
+ if (argvstr == "--debug"){
+ g_show_log = true;
+ continue;
+ }
+ int sepindex = argvstr.find(":");
+ if (sepindex > -1) {
+ string key = argvstr.substr(0, sepindex);
+ string value = argvstr.substr(sepindex + 1);
+ if (key == "--port") {
+ httpserver->g_port = atoi(value.c_str());
+ }
+ }
+ }
+}
+
+int main(int argc, char *argv[]) {
+ if (argc > 1) {
+ parse(argc, argv, &httpserver);
+ }
+ httpserver.StartUp();
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <string>
+#include <json/json.h>
+#include <stdlib.h>
+
+#include "testcase.h"
+
+using namespace std;
+
+TestCase::TestCase() {
+ result = "N/A";
+
+ std_out = "";
+}
+
+TestCase::~TestCase() {
+}
+
+void TestCase::init(const Json::Value value) {
+ m_case = value;
+ case_id = value["case_id"].asString();
+ if (value["timeout"].isString())
+ timeout_value = atoi(value["timeout"].asString().c_str());
+ else {
+ timeout_value = 90;
+ m_case["timeout"] = "90";
+ }
+}
+
+Json::Value TestCase::to_json() {
+ return m_case;
+}
+
+Json::Value TestCase::result_to_json() {
+ Json::Value root;
+
+ root["order"] = m_case["order"];
+ root["case_id"] = m_case["case_id"];
+ root["result"] = result;
+
+ if (std_out != "") {
+ root["stdout"] = std_out;
+ root["start_at"] = start_at;
+ root["end_at"] = end_at;
+ }
+
+ return root;
+}
+
+void TestCase::set_result(Json::Value paras) {
+ result = paras["result"].asString();
+
+ std_out = paras["msg"].asString();
+
+ getCurrentTime();
+ end_at = m_str_time;
+}
+
+void TestCase::set_start_at() {
+ getCurrentTime();
+ start_at = m_str_time;
+}
+
+void TestCase::getCurrentTime() {
+ memset(m_str_time, 0, 32);
+ time_t timer;
+ time(&timer);
+#if defined(__WIN32__) || defined(__WIN64__)
+ struct tm* t_tm;
+ t_tm = localtime(&timer);
+ sprintf(m_str_time, "%4d-%02d-%02d %02d:%02d:%02d", t_tm->tm_year + 1900,
+ t_tm->tm_mon + 1, t_tm->tm_mday, t_tm->tm_hour, t_tm->tm_min,
+ t_tm->tm_sec);
+#else
+ struct tm t_tm = {0};
+ time(&timer);
+ localtime_r(&timer, &t_tm);
+ sprintf(m_str_time, "%4d-%02d-%02d %02d:%02d:%02d", t_tm.tm_year + 1900,
+ t_tm.tm_mon + 1, t_tm.tm_mday, t_tm.tm_hour, t_tm.tm_min,
+ t_tm.tm_sec);
+#endif
+}
--- /dev/null
+
+[ testing xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.xml ]
+
+[ split xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1.xml by <set> ]
+[ this might take some time, please wait ]
+[ total set number is: 10 ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_1.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_2.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_3.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_4.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_5.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_6.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_7.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_8.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_9.xml ]
+[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_1.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_2.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_3.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_4.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_5.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_6.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_7.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_8.xml ]
+[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_9.xml ]
+
+[ run set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml ]
+[ split xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml by <case> ]
+[ this might take some time, please wait ]
+[ prepare_starup_parameters ]
+[ waiting for kill http server ]
+[ forward server http://127.0.0.1:9002 ]
+[ launch the stub app ]
+httpserver->g_test_suite is: api2contt0
+[Server is running.....]
+wrt-launcher: no process found
+[ check server status, get ready! ]
+GET /check_server_status HTTP/1.1
+Host: 127.0.0.1:9002
+Content-Length: 0
+Accept-Encoding: gzip, deflate, compress
+Accept: */*
+User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
+
+
+block: 1/-1215935884, total case: 0/0, block case: 0/0, m_timeout_count:0
+server response is:{
+ "block_finished" : 0,
+ "finished" : 0
+}
+
+POST /init_test HTTP/1.1
+Host: 127.0.0.1:9002
+Content-Length: 587
+content-type: application/json
+Accept-Encoding: gzip, deflate, compress
+Accept: */*
+User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
+
+{"currentBlk": "1", "totalBlk": "1", "casecount": "1", "cases": [{"onload_delay": "3", "case_id": "video_addTextTrack_base", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned"}], "purpose": "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned", "entry": "/opt/tct-webapi-w3c-content-tests/Video/video_addTextTrack_base.html", "order": "1"}], "type": "compliance", "exetype": "auto"}
+[ init the test suite ]
+wrt-launcher -k api2contt0
+result: App isn't running
+
+[ test suite: tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml, block: 1/1 , finished: 0 ]
+wrt-launcher -s api2contt0
+result: launched
+
+server response is:{"OK":1}
+GET /check_server_status HTTP/1.1
+Host: 127.0.0.1:9002
+Content-Length: 0
+Accept-Encoding: gzip, deflate, compress
+Accept: */*
+User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
+
+
+block: 1/1, total case: 0/1, block case: 0/1, m_timeout_count:0
+server response is:{
+ "block_finished" : 0,
+ "finished" : 0
+}
+
+[ test suite: tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml, block: 1/1 , finished: 0 ]
+GET /check_server_status HTTP/1.1
+Host: 127.0.0.1:9002
+Content-Length: 0
+Accept-Encoding: gzip, deflate, compress
+Accept: */*
+User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
+
+
+block: 1/1, total case: 0/1, block case: 0/1, m_timeout_count:0
+server response is:{
+ "block_finished" : 0,
+ "finished" : 0
+}
+
+GET /check_server HTTP/1.1
+Host: 127.0.0.1:8000
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Accept: */*
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+
+
+[ checking server, and found the server is running ]
+server response is:{"OK":1}
+GET /init_session_id?session_id=6330 HTTP/1.1
+Host: 127.0.0.1:8000
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Accept: */*
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+
+
+[ sessionID: 6330 is gotten from the client ]
+server response is:{"OK":1}
+GET /auto_test_task?session_id=6330 HTTP/1.1
+Host: 127.0.0.1:8000
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Accept: text/plain, */*; q=0.01
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+
+
+
+start time: 1982-02-06 15:27:38
+
+[case] execute case: video_addTextTrack_base
+last_test_result: N/A
+server response is:{
+ "case_id" : "video_addTextTrack_base",
+ "entry" : "/opt/tct-webapi-w3c-content-tests/Video/video_addTextTrack_base.html",
+ "onload_delay" : "3",
+ "order" : "1",
+ "purpose" : "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned",
+ "steps" : [
+ {
+ "expected" : "Pass",
+ "order" : "1",
+ "step_desc" : "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned"
+ }
+ ]
+}
+
+GET /check_execution_progress?session_id=6330 HTTP/1.1
+Host: 127.0.0.1:8000
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Accept: text/plain, */*; q=0.01
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+
+
+server response is:{"total":1,"current":1,"last_test_result":"N/A"}
+GET /ask_next_step?session_id=6330 HTTP/1.1
+Host: 127.0.0.1:8000
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Accept: text/plain, */*; q=0.01
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+
+
+server response is:{"step":"continue"}
+POST /commit_result HTTP/1.1
+Host: 127.0.0.1:8000
+Origin: file://
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Content-Type: application/x-www-form-urlencoded
+Accept: application/json, text/javascript, */*; q=0.01
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+Content-Length: 177
+
+purpose=Check+if+the+vedio.addTextTrack+has+all+arguments+that+expected+a+new+MutableTextTrack+object+is+to+be+created+and+returned&result=PASS&msg=%5BMessage%5D&session_id=6330
+server response is:{"OK":1}
+GET /auto_test_task?session_id=6330 HTTP/1.1
+Host: 127.0.0.1:8000
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Accept: text/plain, */*; q=0.01
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+
+
+
+[ no auto case is available any more ]
+server response is:{"none":0}
+GET /manual_cases HTTP/1.1
+Host: 127.0.0.1:8000
+Accept-Language: en
+User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
+Accept: text/plain, */*; q=0.01
+Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
+x-Wap-Proxy-Cookie: none
+Accept-Encoding: gzip, deflate
+Connection: Keep-Alive
+
+
+server response is:{"none":0}
+[ test suite: tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml, block: 1/1 , finished: 1 ]
+GET /check_server_status HTTP/1.1
+Host: 127.0.0.1:9002
+Content-Length: 0
+Accept-Encoding: gzip, deflate, compress
+Accept: */*
+User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
+
+
+block: 1/1, total case: 1/1, block case: 1/1, m_timeout_count:0
+server response is:{
+ "block_finished" : 1,
+ "finished" : 1
+}
+
+GET /get_test_result HTTP/1.1
+Host: 127.0.0.1:9002
+Content-Length: 0
+Accept-Encoding: gzip, deflate, compress
+Accept: */*
+User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
+
+
+server response is:{
+ "cases" : [
+ {
+ "case_id" : "video_addTextTrack_base",
+ "end_at" : "1982-02-06 15:27:39",
+ "order" : "1",
+ "result" : "PASS",
+ "start_at" : "1982-02-06 15:27:38",
+ "stdout" : "[Message]"
+ }
+ ],
+ "count" : "1"
+}
+
+[ cases result saved to resultfile ]
+
+[ show down server ]
+GET /shut_down_server HTTP/1.1
+Host: 127.0.0.1:9002
+Content-Length: 0
+Accept-Encoding: gzip, deflate, compress
+Accept: */*
+User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
+
+
+wrt-launcher: no process found
+
+[ test complete at time: 2013-04-18_16_06_12 ]
+[ start merging test result xml files, this might take some time, please wait ]
+[ merge result files into /opt/testkit/lite/2013-04-18-16:05:48.429618/tests.result.xml ]
+|--[ merge webapi result file: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml ]
+----[ suite: tct-webapi-w3c-content-tests, set: Video, time: 2013-04-18_16_06_12 ]
+[ test summary ]
+ [ total case number: 1 ]
+ [ pass rate: 100.00% ]
+ [ PASS case number: 1 ]
+ [ FAIL case number: 0 ]
+ [ BLOCK case number: 0 ]
+ [ N/A case number: 0 ]
+[ generate result xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tests.result.xml ]
+[ merge complete, write to the result file, this might take some time, please wait ]
+wrt-launcher -k api2contt0
+result: killed
+
+server response is:{"OK":1}
+[ all tasks for testkit lite are accomplished, goodbye ]
+danny@danny-Latitude-E6400:~$
--- /dev/null
+{"currentBlk": "4", "totalBlk": "4", "casecount": "387", "cases": [{"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_setter.html", "pre_condition": "none", "case_id": "Uint16Array_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify setter of Uint16Array"}], "purpose": "Verify setter of Uint16Array", "order": "301"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_array.html", "pre_condition": "none", "case_id": "Uint16Array_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array) of Uint16Array"}], "purpose": "Verify set(array) of Uint16Array", "order": "302"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_array_offset.html", "pre_condition": "none", "case_id": "Uint16Array_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array, offset) of Uint16Array"}], "purpose": "Verify set(array, offset) of Uint16Array", "order": "303"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_exist.html", "pre_condition": "none", "case_id": "Uint16Array_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the set of Uint16Array exist"}], "purpose": "Check if the set of Uint16Array exist", "order": "304"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint16Array_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray) of Uint16Array"}], "purpose": "Verify set(typedarray) of Uint16Array", "order": "305"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint16Array_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray, offset) of Uint16Array"}], "purpose": "Verify set(typedarray, offset) of Uint16Array", "order": "306"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_subarray_begin.html", "pre_condition": "none", "case_id": "Uint16Array_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin) of Uint16Array"}], "purpose": "Verify subarray(begin) of Uint16Array", "order": "307"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint16Array_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin, end) of Uint16Array"}], "purpose": "Verify subarray(begin, end) of Uint16Array", "order": "308"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_subarray_exist.html", "pre_condition": "none", "case_id": "Uint16Array_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint16Array exist"}], "purpose": "Check if the subarray of Uint16Array exist", "order": "309"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_buffer.html", "pre_condition": "none", "case_id": "Uint32Array_buffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify buffer of Uint32Array"}], "purpose": "Verify buffer of Uint32Array", "order": "310"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_buffer_exist.html", "pre_condition": "none", "case_id": "Uint32Array_buffer_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the buffer of Uint32Array exist"}], "purpose": "Check if the buffer of Uint32Array exist", "order": "311"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteLength.html", "pre_condition": "none", "case_id": "Uint32Array_byteLength", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify byteLength of Uint32Array"}], "purpose": "Verify byteLength of Uint32Array", "order": "312"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteLength_exist.html", "pre_condition": "none", "case_id": "Uint32Array_byteLength_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteLength of Uint32Array exist"}], "purpose": "Check if the byteLength of Uint32Array exist", "order": "313"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteOffset.html", "pre_condition": "none", "case_id": "Uint32Array_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify byteOffset of Uint32Array"}], "purpose": "Verify byteOffset of Uint32Array", "order": "314"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteOffset_exist.html", "pre_condition": "none", "case_id": "Uint32Array_byteOffset_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteOffset of Uint32Array exist"}], "purpose": "Check if the byteOffset of Uint32Array exist", "order": "315"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_BYTES_PER_ELEMENT_const_4.html", "pre_condition": "none", "case_id": "Uint32Array_BYTES_PER_ELEMENT_const_4", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify BYTES_PER_ELEMENT of Uint32Array is 4"}], "purpose": "Verify BYTES_PER_ELEMENT of Uint32Array is 4", "order": "316"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_BYTES_PER_ELEMENT_exist.html", "pre_condition": "none", "case_id": "Uint32Array_BYTES_PER_ELEMENT_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the BYTES_PER_ELEMENT of Uint32Array exist"}], "purpose": "Check if the BYTES_PER_ELEMENT of Uint32Array exist", "order": "317"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_array.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(array) of Uint32Array"}], "purpose": "Verify constructor(array) of Uint32Array", "order": "318"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_ArrayBuffer.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_ArrayBuffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer) of Uint32Array"}], "purpose": "Verify constructor(arraybuffer) of Uint32Array", "order": "319"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_ArrayBuffer_byteOffset.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_ArrayBuffer_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer, byteOffset) of Uint32Array"}], "purpose": "Verify constructor(arraybuffer, byteOffset) of Uint32Array", "order": "320"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_ArrayBuffer_byteOffset_length.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_ArrayBuffer_byteOffset_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer, byteOffset, length) of Uint32Array"}], "purpose": "Verify constructor(arraybuffer, byteOffset, length) of Uint32Array", "order": "321"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_length.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(length) of Uint32Array"}], "purpose": "Verify constructor(length) of Uint32Array", "order": "322"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_TypedArray.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(typedarray) of Uint32Array"}], "purpose": "Verify constructor(typedarray) of Uint32Array", "order": "323"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_getter.html", "pre_condition": "none", "case_id": "Uint32Array_getter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify getter of Uint32Array"}], "purpose": "Verify getter of Uint32Array", "order": "324"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_length.html", "pre_condition": "none", "case_id": "Uint32Array_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify length of Uint32Array"}], "purpose": "Verify length of Uint32Array", "order": "325"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_length_exist.html", "pre_condition": "none", "case_id": "Uint32Array_length_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the length of Uint32Array exist"}], "purpose": "Check if the length of Uint32Array exist", "order": "326"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_setter.html", "pre_condition": "none", "case_id": "Uint32Array_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify setter of Uint32Array"}], "purpose": "Verify setter of Uint32Array", "order": "327"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_array.html", "pre_condition": "none", "case_id": "Uint32Array_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array) of Uint32Array"}], "purpose": "Verify set(array) of Uint32Array", "order": "328"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_array_offset.html", "pre_condition": "none", "case_id": "Uint32Array_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array, offset) of Uint32Array"}], "purpose": "Verify set(array, offset) of Uint32Array", "order": "329"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_exist.html", "pre_condition": "none", "case_id": "Uint32Array_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the set of Uint32Array exist"}], "purpose": "Check if the set of Uint32Array exist", "order": "330"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint32Array_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray) of Uint32Array"}], "purpose": "Verify set(typedarray) of Uint32Array", "order": "331"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint32Array_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray, offset) of Uint32Array"}], "purpose": "Verify set(typedarray, offset) of Uint32Array", "order": "332"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_subarray_begin.html", "pre_condition": "none", "case_id": "Uint32Array_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin) of Uint32Array"}], "purpose": "Verify subarray(begin) of Uint32Array", "order": "333"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint32Array_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(begin, end) of Uint32Array"}], "purpose": "Verify set(begin, end) of Uint32Array", "order": "334"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_subarray_exist.html", "pre_condition": "none", "case_id": "Uint32Array_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint32Array exist"}], "purpose": "Check if the subarray of Uint32Array exist", "order": "335"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_buffer.html", "pre_condition": "none", "case_id": "Uint8Array_buffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the buffer of Uint8Array"}], "purpose": "Verify the buffer of Uint8Array", "order": "336"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_buffer_exist.html", "pre_condition": "none", "case_id": "Uint8Array_buffer_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the buffer of Uint8Array exist"}], "purpose": "Check if the buffer of Uint8Array exist", "order": "337"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteLength.html", "pre_condition": "none", "case_id": "Uint8Array_byteLength", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteLength of Uint8Array"}], "purpose": "Verify the byteLength of Uint8Array", "order": "338"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteLength_exist.html", "pre_condition": "none", "case_id": "Uint8Array_byteLength_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteLength of Uint8Array exist"}], "purpose": "Check if the byteLength of Uint8Array exist", "order": "339"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteOffset.html", "pre_condition": "none", "case_id": "Uint8Array_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteOffset of Uint8Array"}], "purpose": "Verify the byteOffset of Uint8Array", "order": "340"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteOffset_exist.html", "pre_condition": "none", "case_id": "Uint8Array_byteOffset_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteOffset of Uint8Array exist"}], "purpose": "Check if the byteOffset of Uint8Array exist", "order": "341"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_BYTES_PER_ELEMENT_const_1.html", "pre_condition": "none", "case_id": "Uint8Array_BYTES_PER_ELEMENT_const_1", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the BYTES_PER_ELEMENT of Uint8Array is 1"}], "purpose": "Verify the BYTES_PER_ELEMENT of Uint8Array is 1", "order": "342"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_BYTES_PER_ELEMENT_exist.html", "pre_condition": "none", "case_id": "Uint8Array_BYTES_PER_ELEMENT_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the BYTES_PER_ELEMENT of Uint8Array exist"}], "purpose": "Check if the BYTES_PER_ELEMENT of Uint8Array exist", "order": "343"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_array.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(array) of Uint8Array"}], "purpose": "Verify the constructor(array) of Uint8Array", "order": "344"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_ArrayBuffer.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_ArrayBuffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(arraybuffer) of Uint8Array"}], "purpose": "Verify the constructor(arraybuffer) of Uint8Array", "order": "345"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_ArrayBuffer_byteOffSet.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_ArrayBuffer_byteOffSet", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(arraybuffer, byteOffset) of Uint8Array"}], "purpose": "Verify the constructor(arraybuffer, byteOffset) of Uint8Array", "order": "346"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_ArrayBuffer_byteOffSet_length.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_ArrayBuffer_byteOffSet_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(arraybuffer, byteOffset, length) of Uint8Array"}], "purpose": "Verify the constructor(arraybuffer, byteOffset, length) of Uint8Array", "order": "347"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_length.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(length) of Uint8Array"}], "purpose": "Verify the constructor(length) of Uint8Array", "order": "348"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_TypedArray.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(typedarray) of Uint8Array"}], "purpose": "Verify the constructor(typedarray) of Uint8Array", "order": "349"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_getter.html", "pre_condition": "none", "case_id": "Uint8Array_getter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the getter of Uint8Array"}], "purpose": "Verify the getter of Uint8Array", "order": "350"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_length.html", "pre_condition": "none", "case_id": "Uint8Array_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the length of Uint8Array"}], "purpose": "Verify the length of Uint8Array", "order": "351"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_length_exist.html", "pre_condition": "none", "case_id": "Uint8Array_length_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the length of Uint8Array exist"}], "purpose": "Check if the length of Uint8Array exist", "order": "352"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_setter.html", "pre_condition": "none", "case_id": "Uint8Array_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the setter of Uint8Array"}], "purpose": "Verify the setter of Uint8Array", "order": "353"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_array.html", "pre_condition": "none", "case_id": "Uint8Array_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(array) of Uint8Array"}], "purpose": "Verify the set(array) of Uint8Array", "order": "354"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_array_offset.html", "pre_condition": "none", "case_id": "Uint8Array_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(array, offset) of Uint8Array"}], "purpose": "Verify the set(array, offset) of Uint8Array", "order": "355"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_exist.html", "pre_condition": "none", "case_id": "Uint8Array_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the set of Uint8Array exist"}], "purpose": "Check if the set of Uint8Array exist", "order": "356"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint8Array_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(typedarray) of Uint8Array"}], "purpose": "Verify the set(typedarray) of Uint8Array", "order": "357"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint8Array_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(typedarray, offset) of Uint8Array"}], "purpose": "Verify the set(typedarray, offset) of Uint8Array", "order": "358"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_subarray_begin.html", "pre_condition": "none", "case_id": "Uint8Array_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the subarray(begin) of Uint8Array"}], "purpose": "Verify the subarray(begin) of Uint8Array", "order": "359"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint8Array_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the subarray(begin, end) of Uint8Array"}], "purpose": "Verify the subarray(begin, end) of Uint8Array", "order": "360"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_subarray_exist.html", "pre_condition": "none", "case_id": "Uint8Array_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint8Array exist"}], "purpose": "Check if the subarray of Uint8Array exist", "order": "361"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_buffer.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_buffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the buffer of Uint8ClampedArray"}], "purpose": "Verify the buffer of Uint8ClampedArray", "order": "362"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_buffer_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_buffer_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "check if the buffer of Uint8ClampedArray exist"}], "purpose": "check if the buffer of Uint8ClampedArray exist", "order": "363"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteLength.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteLength", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteLength of Uint8ClampedArray"}], "purpose": "Verify the byteLength of Uint8ClampedArray", "order": "364"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteLength_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteLength_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteLength of Uint8ClampedArray exist"}], "purpose": "Check if the byteLength of Uint8ClampedArray exist", "order": "365"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteOffset.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteOffset of Uint8ClampedArray"}], "purpose": "Verify the byteOffset of Uint8ClampedArray", "order": "366"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteOffset_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteOffset_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "check if the byteOffset of Uint8ClampedArray exist"}], "purpose": "check if the byteOffset of Uint8ClampedArray exist", "order": "367"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_BYTES_PER_ELEMENT_const_1.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_BYTES_PER_ELEMENT_const_1", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the BYTES_PER-ELEMENT of Uint8ClampedArray is 1"}], "purpose": "Verify the BYTES_PER-ELEMENT of Uint8ClampedArray is 1", "order": "368"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_BYTES_PER_ELEMENT_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_BYTES_PER_ELEMENT_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the BYTES_PER_ELEMENT of Uint8ClampedArray exist"}], "purpose": "Check if the BYTES_PER_ELEMENT of Uint8ClampedArray exist", "order": "369"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_array.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(array) of Uint8ClampedArray"}], "purpose": "Verify constructor(array) of Uint8ClampedArray", "order": "370"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_ArrayBuffer.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_ArrayBuffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer) of Uint8ClampedArray"}], "purpose": "Verify constructor(arraybuffer) of Uint8ClampedArray", "order": "371"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer, byteOffset) of Uint8ClampedArray"}], "purpose": "Verify constructor(arraybuffer, byteOffset) of Uint8ClampedArray", "order": "372"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet_length.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(buffer, byteOffset, length) of Uint8ClampedArray"}], "purpose": "Verify constructor(buffer, byteOffset, length) of Uint8ClampedArray", "order": "373"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_length.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(length) of Uint8ClampedArray"}], "purpose": "Verify constructor(length) of Uint8ClampedArray", "order": "374"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_TypedArray.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(typedarray) of Uint8ClampedArray"}], "purpose": "Verify constructor(typedarray) of Uint8ClampedArray", "order": "375"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_getter.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_getter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify getter of Uint8ClampedArray"}], "purpose": "Verify getter of Uint8ClampedArray", "order": "376"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_length.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify length of Uint8ClampedArray"}], "purpose": "Verify length of Uint8ClampedArray", "order": "377"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_length_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_length_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the length of Uint8ClampedArray exist"}], "purpose": "Check if the length of Uint8ClampedArray exist", "order": "378"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_setter.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify setter of Uint8ClampedArray"}], "purpose": "Verify setter of Uint8ClampedArray", "order": "379"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_array.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array) of Uint8ClampedArray"}], "purpose": "Verify set(array) of Uint8ClampedArray", "order": "380"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_array_offset.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array, offset) of Uint8ClampedArray"}], "purpose": "Verify set(array, offset) of Uint8ClampedArray", "order": "381"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "check if the set of Uint8ClampedArray exist"}], "purpose": "check if the set of Uint8ClampedArray exist", "order": "382"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray) of Uint8ClampedArray"}], "purpose": "Verify set(typedarray) of Uint8ClampedArray", "order": "383"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray, offset) of Uint8ClampedArray"}], "purpose": "Verify set(typedarray, offset) of Uint8ClampedArray", "order": "384"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_subarray_begin.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin) of Uint8ClampedArray"}], "purpose": "Verify subarray(begin) of Uint8ClampedArray", "order": "385"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin, end) of Uint8ClampedArray"}], "purpose": "Verify subarray(begin, end) of Uint8ClampedArray", "order": "386"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_subarray_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint8ClampedArray exist"}], "purpose": "Check if the subarray of Uint8ClampedArray exist", "order": "387"}], "type": "compliance", "exetype": "auto"}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 Intel Corporation, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include "httpserver.h"
+
+int main() {
+ HttpServer* httpserver = new HttpServer();
+
+ httpserver->parse_json_str("src/ut/test.json");
+
+ struct HttpRequest httprequest;
+
+ httprequest.path = "/init_test";
+ httpserver->processpost(1, &httprequest);
+
+ httpserver->m_suite_name = "api3nonw3c";
+
+ httprequest.path = "/check_server";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/check_server_status";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/shut_down_server";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/ask_next_step";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/init_session_id?session_id=1024";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/auto_test_task?session_id=1024";
+ httprequest.content = "session_id=1024";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/manual_cases";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.content = "purpose=ut-cas&result=N/A";
+ httprequest.path = "/commit_manual_result";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/check_execution_progress";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/generate_xml";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.content = "purpose=Verify setter of Uint16Array&result=N/A";
+ httprequest.path = "/commit_result";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/check_execution_progress";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/set_capability";
+ httprequest.content = "{\"name1\":true, \"name2\":45, \"name3\":\"678\"}";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/capability";
+ httprequest.content = "name=name1";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/capability?name=name2&value=45";
+ httprequest.content = "name=name2&value=45";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/capability?name=name3&value=678";
+ httprequest.content = "name=name3&value=678";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/capability?name=name4";
+ httprequest.content = "name=name4";
+ httpserver->processpost(1, &httprequest);
+
+ httprequest.path = "/set_capability";
+ httprequest.content = "{\"bluetooth\":true, \"nfc\":true, \"multiTouchCount\":true, \"inputKeyboard\":true, \"wifi\":true, \"wifiDirect\":true, \"openglesVersion1_1\":true, \"openglesVersion2_0\":true, \"fmRadio\":true, \"platformVersion\":true, \"webApiVersion\":true, \"nativeApiVersion\":true, \"platformName\":true, \"cameraFront\":true, \"cameraFrontFlash\":true, \"cameraBack\":true, \"cameraBackFlash\":true, \"location\":true, \"locationGps\":true, \"locationWps\":true, \"microphone\":true, \"usbHost\":true, \"usbAccessory\":true, \"screenOutputRca\":true, \"screenOutputHdmi\":true, \"platformCoreCpuArch\":true, \"platformCoreFpuArch\":true, \"sipVoip\":true, \"duid\":true, \"speechRecognition\":true, \"accelerometer\":true, \"barometer\":true, \"gyroscope\":true, \"magnetometer\":true, \"proximity\":true}";
+ httpserver->processpost(1, &httprequest);
+
+ httpserver->StartUp();
+
+ delete httpserver;
+
+ return 0;
+}
+++ /dev/null
-#include <stdio.h>
-#include "comfun.h"
-
-ComFun::ComFun() {
-
-}
-ComFun::~ComFun() {
-
-}
-
-char ComFun::CharToInt(char ch) {
- if (ch >= '0' && ch <= '9')
- return (char) (ch - '0');
- if (ch >= 'a' && ch <= 'f')
- return (char) (ch - 'a' + 10);
- if (ch >= 'A' && ch <= 'F')
- return (char) (ch - 'A' + 10);
- return -1;
-}
-
-char ComFun::StrToBin(char *str) {
- char tempWord[2];
- char chn;
- tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011
- tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000
- chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000
- return chn;
-}
-//url decode
-char* ComFun::UrlDecode(const char *str) {
- char tmp[2];
- int i = 0, len = strlen(str);
- char *output = new char[len + 1];
- memset(output, 0, len + 1);
- int j = 0;
- while (i < len) {
- if (*(str + i) == '%') {
- tmp[0] = *(str + i + 1);
- tmp[1] = *(str + i + 2);
- *(output + j) = StrToBin(tmp);
- i = i + 3;
- j++;
- } else if (*(str + i) == '+') {
- *(output + j) = ' ';
- i++;
- j++;
- } else {
- *(output + j) = *(str + i);
- i++;
- j++;
- }
- }
- return output;
-}
-
-//split function for string
-std::vector<std::string> ComFun::split(std::string str, std::string pattern) {
- std::string::size_type pos;
- std::vector < std::string > result;
- str += pattern; //extend string so that operate easyly
- unsigned int size = str.size();
- int count = 0;
- for (unsigned int i = 0; i < size; i++) {
- if ((pattern == "=")&&(count == 1)){
- std::string s = str.substr(i, size-1-i);
- result.push_back(s);
- break;
- }
- pos = str.find(pattern, i);
- if (pos < size) {
- std::string s = str.substr(i, pos - i);
- result.push_back(s);
- i = pos + pattern.size() - 1;
- }
- count++;
- }
- return result;
-}
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <pthread.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sstream>
-
-#include <json/json.h>
-#include "comfun.h"
-#include "httpserver.h"
-
-#define MAX_BUF 102400
-
-#define GET 0
-#define HEAD 2
-#define POST 3
-#define BAD_REQUEST -1
-
-#if defined(DEBUG) | defined(_DEBUG)
- #ifndef DBG_ONLY
- #define DBG_ONLY(x) do { x } while (0)
- #endif
-#else
- #ifndef DBG_ONLY
- #define DBG_ONLY(x)
- #endif
-#endif
-
-// if use 8080 for server_port, it will not work with chrome
-int server_port = 8000;
-
-HttpServer::HttpServer() {
- m_test_cases = NULL;
- m_exeType = "auto"; // set default to auto
- m_totalBlocks = 0;
- m_current_block_index = 1;
- m_totalcaseCount = 0;
- m_block_case_index = 0;
- m_block_case_count = 0;
- m_total_case_index = 0;
- m_last_auto_result = "N/A";
- m_running_session = "";
- m_server_checked = false;
- m_check_times = 0;
- g_show_log = false;
- g_port = 8000;
- g_run_wiget = false;
- m_block_finished = false;
- m_set_finished = false;
- m_timeout_count = 0;
- m_failto_launch = 0;
- m_killing_widget = false;
- m_rerun = false;
- m_suite_name = "";
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = timer_handler;
- sigaction(SIGALRM, &sa, NULL);
-}
-
-HttpServer::~HttpServer() {
- if (m_test_cases) {
- delete[] m_test_cases;
- m_test_cases = NULL;
- }
- DBG_ONLY(outputFile.close(););
-}
-
-// generate response code. send response
-void HttpServer::sendresponse(int s, int code, struct HttpRequest *prequest,
- string content) {
- string buffer;
- stringstream len_stream;
- len_stream << content.length();
- prequest->responsecode = code;
- // generate response head
- switch (code) {
- case 200: {
- buffer =
- "HTTP/1.1 200 OK\r\nServer: testkit-stub/1.0\r\nContent-Type: "
- + prequest->prefix
- + "\r\nAccept-Ranges: bytes\r\nContent-Length: "
- + len_stream.str()
- + "\r\nConnection: close\r\nAccess-Control-Allow-Origin: *\r\n\r\n"
- + content;
- break;
- }
- default:
- break;
- }
-
- if (g_show_log) cout << buffer << endl;
- // send out the http response
- send(s, buffer.c_str(), buffer.length(), 0);
-}
-
-// parse the http request
-int HttpServer::getrequest(string requestbuf, struct HttpRequest *prequest) {
- std::vector < std::string > splitstr = ComFun::split(requestbuf, " ");
- if (splitstr.size() >= 2) {
- prequest->method = splitstr[0];
- prequest->path = splitstr[1];
- }
-
- if (prequest->path.find('?') == string::npos) {
- //get the com module send data
- int content_index = requestbuf.find("\r\n\r\n", 0);
- if (content_index > -1) {
- prequest->content = requestbuf.substr(
- content_index + strlen("\r\n\r\n"));
- }
- } else {
- int session_index = prequest->path.find("?");
- prequest->content = prequest->path.substr(session_index + 1);
- }
- if (prequest->method == "GET") {
- return GET;
- } else if (prequest->method == "POST") {
- return POST;
- }
- return -1;
-}
-
-// parse the test case data sent by com-module with init_test cmd
-void HttpServer::parse_json_str(string case_node) {
- Json::Reader reader;
- Json::Value value;
-
- bool parsed = reader.parse(case_node, value);
- if (!parsed) // try to parse as a file if parse fail
- { // "test.json" is for verify
- cout << case_node << endl;
- std::ifstream test(case_node.c_str(), std::ifstream::binary);
- parsed = reader.parse(test, value, false);
- }
-
- if (parsed) {
- m_totalBlocks = atoi(value["totalBlk"].asString().c_str());
- m_current_block_index = atoi(value["currentBlk"].asString().c_str());
- m_totalcaseCount = atoi(value["casecount"].asString().c_str());
- m_exeType = value["exetype"].asString();
-
- const Json::Value arrayObj = value["cases"];
- m_block_case_count = arrayObj.size();
-
- if (m_test_cases) {
- delete[] m_test_cases;
- m_test_cases = NULL;
- }
- m_test_cases = new TestCase[m_block_case_count];
-
- for (int i = 0; i < m_block_case_count; i++) {
- m_test_cases[i].init(arrayObj[i]);
- }
- }
-}
-
-void HttpServer::cancel_time_check() {
- timer.it_value.tv_sec = 0;
- timer.it_value.tv_usec = 0;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = 0;
- setitimer(ITIMER_REAL, &timer, NULL); // set timer with value 0 will stop the timer
- // refer to http://linux.die.net/man/2/setitimer, each process only have 1 timer of the same type.
-}
-
-// set timeout value to 90 seconds for each case
-void HttpServer::set_timer(int timeout_value) {
- timer.it_value.tv_sec = timeout_value;
- timer.it_value.tv_usec = 0;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = 0;
- int ret = setitimer(ITIMER_REAL, &timer, NULL);
- if (ret < 0)
- perror("error: set timer!!!");
-}
-
-Json::Value HttpServer::splitContent(string content) {
- Json::Value httpParas;
- if (content != "") {
- std::vector < std::string > splitstr = ComFun::split(content, "&");
- for (unsigned int i = 0; i < splitstr.size(); i++) {
- vector < string > resultkey = ComFun::split(splitstr[i], "=");
- char* tmp = ComFun::UrlDecode(resultkey[0].c_str());
- string key = tmp;
- delete[] tmp; // free memory from comfun
- if (resultkey[1] != "") {
- tmp = ComFun::UrlDecode(resultkey[1].c_str());
- string value = tmp;
- delete[] tmp; // free memory from comfun
- httpParas[key] = value;
- }
- else httpParas["myContent"] = key;
- }
- DBG_ONLY(outputFile << httpParas.toStyledString() << endl;);
- }
- return httpParas;
-}
-
-/** send out response according to different http request.
-a typical workflow of auto case would be
-/check_server_status (by com-module)
-/init_test (by com-module)
-/set_testcase (by com-module)
-/check_server (by widget)
-/init_session_id?session_id=2033 (by widget)
-/auto_test_task?session_id=2033 (by widget)
-/check_execution_progress?session_id=2033 (by widget)
-/ask_next_step?session_id=2033 (by widget)
-/commit_result (by widget)
-/auto_test_task?session_id=2033 (by widget)
-/manual_cases (by widget)
-/check_server_status (by com-module)
-/get_test_result (by com-module)
-/shut_down_server (by com-module)
-
-
-a typical workflow of manual case would be
-/check_server_status (by com-module)
-/init_test (by com-module)
-/check_server (by widget)
-/init_session_id?session_id=2033 (by widget)
-/auto_test_task?session_id=2033 (by widget)
-/manual_cases (by widget)
-/check_server_status (by com-module)
-/commit_manual_result (by widget)
-...
-/check_server_status (by com-module)
-/commit_manual_result (by widget)
-/generate_xml (by widget)
-/get_test_result (by com-module)
-/shut_down_server (by com-module)
-
-**/
-void HttpServer::processpost(int s, struct HttpRequest *prequest) {
- prequest->prefix = "application/json";
- string json_str = "";
-
- if (prequest->path.find("/init_test") != string::npos) {// invoke by com-module to init some para for test
- Json::Reader reader;
- Json::Value value;
-
- cout << "[ init the test suite ]" << endl;
- DBG_ONLY(outputFile << "[ init the test suite ]" << endl;);
-
- bool parsed = reader.parse(prequest->content, value);
- if (parsed) {
- g_launcher = value["launcher"].asString();
- m_suite_name = value["suite_name"].asString();
- cout << "launcher is " << g_launcher << endl;
- if (g_launcher == "wrt-launcher")
- {
- g_run_wiget = true;
- string test_suite = value["suite_id"].asString();
- cout << "test suite is " << test_suite << endl;
-
- g_launch_cmd = g_launcher + " -s " + test_suite;
- g_kill_cmd = g_launcher + " -k " + test_suite;
- getAllWidget();
- killAllWidget();
- }
- else
- {
- g_run_wiget = false;
- //wait for the index window.close, otherwise will occur bind aleady error
- sleep(1);
- }
-
- json_str = "{\"OK\":1}";
- }
- else {
- cout << "error while parse para from com-module, can't start test" << endl;
- cout << prequest->content;
- DBG_ONLY(outputFile << "error while parse para from com-module, can't start test" << endl;);
- DBG_ONLY(outputFile << prequest->content;);
- json_str = "{\"Error\":1}";
- }
- } else if (prequest->path.find("/set_testcase") != string::npos) {// invoke by com-module to send testcase data
- m_block_finished = false;
- m_set_finished = false;
- m_timeout_count = 0;
- m_server_checked = false;
- cout << "[ set test cases ]" << endl;
- DBG_ONLY(outputFile << "[ set test cases ]" << endl;);
- parse_json_str(prequest->content);
-
- start_client();
- if(g_run_wiget == true)//not set timeout when run on browser
- set_timer(20); // set timer here incase widget hang.
- m_check_times = 0;
-
- m_block_case_index = 0;
- if (m_current_block_index == 1)
- m_total_case_index = 0;
-
- json_str = "{\"OK\":1}";
- } else if (prequest->path == "/check_server") {// invoke by index.html to find server running or not
- m_server_checked = true;
- m_check_times = 0;
- cancel_time_check();
-
- cout << "[ checking server, and found the server is running ]" << endl;
- DBG_ONLY(outputFile << "[ checking server, and found the server is running ]" << endl;);
- json_str = "{\"OK\":1}";
- } else if (prequest->path == "/check_server_status") {// invoke by com-module to get server status
- Json::Value status;
- status["block_finished"] = m_block_finished ? 1 : 0;
- status["finished"] = m_set_finished ? 1 : 0;
- if (m_failto_launch > 10) {
- status["error_code"] = 2;
- status["finished"] = 1; // finish current set if can't launch widget
- }
- json_str = status.toStyledString();
-
- if (!m_server_checked) {
- cout << "waiting for widget check_server, please check on device." << endl << endl;
- DBG_ONLY(outputFile << "wait for widget check_server, please check on device." << endl << endl;);
- }
- if (m_totalBlocks > 0)
- {
- DBG_ONLY(cout << "group: " << m_current_block_index << "/" << m_totalBlocks << ", total case: " << m_total_case_index << "/" << m_totalcaseCount << ", group case: " << m_block_case_index << "/" << m_block_case_count << ", m_timeout_count:" << m_timeout_count << endl;);
- DBG_ONLY(outputFile << "group: " << m_current_block_index << "/" << m_totalBlocks << ", total case: " << m_total_case_index << "/" << m_totalcaseCount << ", group case: " << m_block_case_index << "/" << m_block_case_count << ", m_timeout_count:" << m_timeout_count << endl;);
- if (m_exeType != "auto") {
- cout << "manual cases. please check on device." << endl << endl;
- DBG_ONLY(outputFile << "manual cases. please check on device." << endl << endl;);
- }
- }
- } else if (prequest->path == "/shut_down_server") {
- if (g_run_wiget == true)
- killAllWidget(); // kill all widget when shutdown server
- json_str = "{\"OK\":1}";
- gIsRun = 0;
- } else if (prequest->path.find("/init_session_id") != string::npos) {// invoke by index.html to record a session id
- json_str = "{\"OK\":1}";
- int index = prequest->path.find('=');
- if (index != -1) {
- m_running_session = prequest->path.substr(index + 1);
- cout << "[ sessionID: " << m_running_session << " is gotten from the client ]" << endl;
- DBG_ONLY(outputFile << "[ sessionID: " << m_running_session << " is gotten from the client ]" << endl;);
- } else {
- cout << "[ invalid session id ]" << endl;
- DBG_ONLY(outputFile << "[ invalid session id ]" << endl;);
- }
- } else if (prequest->path.find("/ask_next_step") != string::npos) {// invoke by index.html to check whether there are more cases
- if (m_block_finished || m_set_finished)
- json_str = "{\"step\":\"stop\"}";
- else
- json_str = "{\"step\":\"continue\"}";
-
- m_timeout_count = 0; // reset the timeout count
- } else if (prequest->path.find("/auto_test_task") != string::npos) {// invoke by index.html to get current auto case
- if (m_test_cases == NULL) {
- json_str = "{\"Error\":\"no case\"}";
- } else if (m_exeType != "auto") {
- json_str = "{\"none\":0}";
- } else {
- string error_type = "";
- bool find_tc = get_auto_case(prequest->content, &error_type);
- if (find_tc == false) {
- json_str = "{\"" + error_type + "\":1}";// {none:0} will not work sometime
- } else {
- json_str = m_test_cases[m_block_case_index].to_json().toStyledString();
- }
- }
- } else if (prequest->path.find("/manual_cases") != string::npos) {// invoke by index.html to get all manual cases
- cancel_time_check(); // should not timeout in manual mode
- if (!m_test_cases) {
- json_str = "{\"Error\":\"no case\"}";
- } else if (m_exeType == "auto") {
- json_str = "{\"none\":0}";
- } else {
- Json::Value arrayObj;
- for (int i = 0; i < m_block_case_count; i++)
- arrayObj.append(m_test_cases[i].to_json());
-
- json_str = arrayObj.toStyledString();
- }
- } else if (prequest->path.find("/case_time_out") != string::npos) {// invoke by timer to notify case timeout
- if (!m_server_checked) {// start widget again in case it dead. browser not need to restart
- if (m_check_times < 3) {
- m_check_times++;
- cout << "[ checking the client " << m_check_times << " times ]" << endl;
- DBG_ONLY(outputFile << "[ checking the client " << m_check_times << " times ]" << endl;);
- if (g_run_wiget == true) start_client();
- set_timer(20);
- } else {// widget fail for 3 times. finish current set.
- m_set_finished = true;
- }
- } else if (!m_test_cases) {
- json_str = "{\"Error\":\"no case\"}";
- } else if (m_block_case_index < m_block_case_count) {
- checkResult(&m_test_cases[m_block_case_index]);
- json_str = "{\"OK\":\"timeout\"}";
- } else {
- json_str = "{\"Error\":\"case out of index\"}";
- }
- } else if (prequest->path.find("/commit_manual_result") != string::npos) {// invoke by index.html to provide result of a manual case.
- if ((prequest->content.length() == 0) || (!m_test_cases)) {
- json_str = "{\"Error\":\"no manual result\"}";
- } else {
- find_purpose(splitContent(prequest->content), false); // will set index in find_purpose
- json_str = "{\"OK\":1}";
- }
- } else if (prequest->path.find("/check_execution_progress") != string::npos) {//invoke by index.html to get test result of last auto case
- char *total_count = new char[16];
- sprintf(total_count, "%d", m_totalcaseCount);
- char *current_index = new char[16];
- sprintf(current_index, "%d", m_total_case_index + 1);
-
- string count_str(total_count);
- string index_str(current_index);
- json_str = "{\"total\":" + count_str + ",\"current\":" + index_str
- + ",\"last_test_result\":\"" + m_last_auto_result + "\"}";
-
- delete[] total_count;
- delete[] current_index;
- }
- //generate_xml:from index_html, a maually block finished when click done in widget
- else if (prequest->path == "/generate_xml") {
- cancel_time_check();
- m_block_finished = true;
- if (m_current_block_index == m_totalBlocks)
- m_set_finished = true;
-
- json_str = "{\"OK\":1}";
- }
- //from com module,when m_set_finished is true
- else if (prequest->path == "/get_test_result") {
- cancel_time_check();
- if (!m_test_cases) {
- json_str = "{\"Error\":\"no case\"}";
- } else {
- Json::Value root;
- Json::Value arrayObj;
- for (int i = 0; i < m_block_case_count; i++)
- arrayObj.append(m_test_cases[i].result_to_json());
-
- char count[8];
- memset(count, 0, 8);
- sprintf(count, "%d", m_block_case_count);
- root["count"] = count;
- root["cases"] = arrayObj;
-
- json_str = root.toStyledString();
- }
- }
- // index.html invoke this with purpose and result of an auto case, auto case commit result.
- // we need find correct test case by purpose, and record test result to it.
- else if (prequest->path == "/commit_result") {
- if ((prequest->content.length() == 0) || (!m_test_cases)) {
- json_str = "{\"Error\":\"no result\"}";
- m_last_auto_result = "BLOCK";
- m_rerun = true;
- } else {
- Json::Value paras = splitContent(prequest->content);
- if (m_running_session == paras["session_id"].asString()) {
- m_rerun = false;
- if (m_block_case_index < m_block_case_count) {
- m_block_case_index++;
- m_total_case_index++;
- }
-
- find_purpose(paras, true);
-
- json_str = "{\"OK\":1}";
- }
- }
- } else if (prequest->path == "/set_capability") {// by com-module to send capability data
- Json::Reader reader;
-
- reader.parse(prequest->content, m_capability);
-
- json_str = "{\"OK\":1}";
- } else if (prequest->path.find("/capability") != string::npos) {// by test suite. only one query parameter each time
- json_str = "{\"support\":0}";
-
- Json::Value paras = splitContent(prequest->content);
- string value = paras["value"].asString();
- string name = paras["name"].asString();
- for (unsigned int i = 0; i < name.size(); i++)
- name[i] = tolower(name[i]);
-
- if (m_capability[name].isBool()) {// for bool value, omit the value part
- json_str = "{\"support\":1}";
- }
- else if (m_capability[name].isInt()) {
- if (m_capability[name].asInt() == atoi(value.c_str()))
- json_str = "{\"support\":1}";
- }
- else if (m_capability[name].isString()) {
- if (m_capability[name].asString() == value)
- json_str = "{\"support\":1}";
- }
- } else {
- cout << "=================unknown request: " << prequest->path << endl;
- }
-
- DBG_ONLY(
- outputFile << "prequest->path is:" << prequest->path << endl;
- outputFile << "prequest->content is:" << prequest->content << endl;
- outputFile << "server response is:" << json_str << endl;
- );
- if (g_show_log == true)
- {
- cout << "prequest->path is:" << prequest->path << endl;
- cout << "prequest->content is:" << prequest->content << endl;
- cout << "server response is:" << json_str << endl;
- }
-
- if (json_str != "")
- sendresponse(s, 200, prequest, json_str);
-}
-
-// find correct case according the purpose sent by widget
-void HttpServer::find_purpose(Json::Value paras, bool auto_test) {
- string purpose = paras["purpose"].asString();
- string id = paras["case_id"].asString();
-
- bool found = false;
- for (int i = 0; i < m_block_case_count; i++) {
- if ((m_test_cases[i].case_id == id) || (m_test_cases[i].purpose == purpose)) {
- m_test_cases[i].set_result(paras);
- found = true;
- if (!auto_test) // should auto test use this logic?
- m_block_case_index = i; // set index by purpose found
- print_info_string(i);
- break;
- }
- }
- if (!found) {
- cout << "[ Error: can't find any test case by key: " << purpose << " ]" << endl;
- DBG_ONLY(outputFile << "[ Error: can't find any test case by key: " << purpose << " ]" << endl;);
- }
-
- if (auto_test)
- m_last_auto_result = paras["result"].asString();
-}
-
-// create new thread for each http request
-void* processthread(void *para) {
- string recvstr = "";
- char *buffer = new char[MAX_BUF]; // suppose 1 case need 1k, 100 cases will be sent each time, we need 100k memory?
- memset(buffer, 0, MAX_BUF);
- long iDataNum = 0;
- int recvnum = 0;
- HttpServer *server = (HttpServer *) para;
- struct HttpRequest httprequest;
- httprequest.content = "";
- httprequest.path = "";
-
- int content_length = 0;
- int real_content_length = 0;
- while (1) {
- iDataNum = recv(server->clientsocket, buffer + recvnum,
- MAX_BUF - recvnum - 1, 0);
- if (iDataNum <= 0) {
- delete[] buffer;
- close(server->clientsocket);
- pthread_exit (NULL);
- return 0;
- }
- recvnum += iDataNum;
-
- // to calculate content length and real content read
- if (content_length == 0) {
- char* Content_Length = strstr(buffer, "Content-Length: ");
- if (Content_Length != NULL) {
- char tmplen[32];
- sscanf(Content_Length, "%[^:]:%d", tmplen, &content_length);
- if (content_length > 0) {
- char* tmp = strstr(buffer, "\r\n\r\n");
- if (tmp == NULL) {
- tmp = strstr(buffer, "\n\n");
- if (tmp != NULL)
- real_content_length = iDataNum - (tmp-buffer) -2;
- else {
- cout << "[ can't find \\r\\n\\r\\n or \\n\\n ]" << endl;
- break;
- }
- }
- else real_content_length = iDataNum - (tmp-buffer) - 4;
- }
- }
- else real_content_length += iDataNum;
- }
- else real_content_length += iDataNum;
-
- if (real_content_length >= content_length) break;
- }
- buffer[recvnum] = '\0';
- recvstr = buffer;
- delete[] buffer;
-
- // parse request and process it
- switch (server->getrequest(recvstr, &httprequest)) {
- case GET:
- case POST:
- server->processpost(server->clientsocket, &httprequest);
- break;
- default:
- break;
- }
- close(server->clientsocket);
- pthread_exit (NULL);
- return 0;
-}
-
-// send out timeout request to server if timeout. timer handler must be a global function, so can't invoke server's member function directly.
-void timer_handler(int signum) {
- // when timeout, we send a http request to server, so server can check result. seems no other convinent way to do it.
- const char *strings =
- "GET /case_time_out HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: Close\r\n\r\n";
- int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- struct sockaddr_in address;
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = inet_addr("127.0.0.1");
- address.sin_port = htons(server_port);
- int len = sizeof(address);
- int result = connect(sockfd, (struct sockaddr *) &address, len);
- if (result == -1) {
- cout << "fail to send timeout request to server!" << endl;
- } else {
- write(sockfd, strings, strlen(strings));
- close(sockfd);
- }
-}
-
-void HttpServer::print_info_string(int case_index) {
- string result = m_test_cases[case_index].result;
-
- if (m_rerun) {
- cout << endl << "[case] again execute case: ";
- DBG_ONLY(outputFile << endl << "[case] again: ";);
- }
- else {
- cout << endl << "execute case: ";
- DBG_ONLY(outputFile << endl << "[case]: ";);
- }
- cout << m_suite_name << " # " << m_test_cases[case_index].case_id << " ..(" << result << ")" << endl;
- DBG_ONLY(outputFile << m_suite_name << " # " << m_test_cases[case_index].case_id << " ..(" << result << ")" << endl;);
-
- if (result != "PASS") {// print error message if case not pass
- cout << m_test_cases[case_index].std_out << endl;
- DBG_ONLY(outputFile << m_test_cases[case_index].std_out << endl;);
- }
-}
-
-// prepare to run current auto case by set the start time, etc.
-bool HttpServer::get_auto_case(string content, string *type) {
- if (!m_killing_widget) {
- if (content != "") {
- string value = content.substr(content.find("=") + 1);
- if (value.length() > 0) {
- if (m_running_session == value) {
- if (m_block_case_index < m_block_case_count) {
- set_timer(m_test_cases[m_block_case_index].timeout_value);
- m_test_cases[m_block_case_index].set_start_at();
- DBG_ONLY(outputFile << endl << "start time: " << m_test_cases[m_block_case_index].start_at << endl;);
- return true;
- } else {
- cout << endl << "[ no auto case is available any more ]" << endl;
- DBG_ONLY(outputFile << endl << "[ no auto case is available any more ]" << endl;);
- *type = "none";
- m_block_finished = true;
- if (m_current_block_index == m_totalBlocks)
- m_set_finished = true; // the set is finished if current block is the last block
- }
- } else {
- cout << "[ Error: invalid session ID ]" << endl;
- DBG_ONLY(outputFile << "[ Error: invalid session ID ]" << endl;);
- *type = "invalid";
- }
- }
- }
- } else {
- cout << "\n[ restart client process is activated, exit current client ]" << endl;
- DBG_ONLY(outputFile << "\n[ restart client process is activated, exit current client ]" << endl;);
- *type = "stop";
- }
- return false;
-}
-
-//start the socket server, listen to client
-void HttpServer::StartUp() {
- DBG_ONLY(
- outputFile.open("httpserver_log.txt",ios::out);
- outputFile << "httpserver.g_port is:" << g_port << endl;
- );
- if (g_show_log == true)
- {
- cout << "httpserver.g_show_log is:" << g_show_log << endl;
- cout << "httpserver.g_port is:" << g_port << endl;
- }
-
- int serversocket;
- gServerStatus = 1;
- struct sockaddr_in server_addr;
- struct sockaddr_in clientAddr;
- int addr_len = sizeof(clientAddr);
-
- if ((serversocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror( "error: create server socket!!!");
- return;
- }
-
- server_port = g_port;
- bzero(&server_addr, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(server_port);
- server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- int tmp = 1;
- setsockopt(serversocket, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(int));
- if (bind(serversocket, (struct sockaddr *) &server_addr,
- sizeof(server_addr)) < 0) {
- perror("error: bind address !!!!");
- return;
- }
-
- if (listen(serversocket, 5) < 0) {
- perror("error: listen !!!!");
- return;
- }
- gIsRun = 1;
- cout << "[Server is running.....]" << endl;
- DBG_ONLY(outputFile << "[Server is running.....]" << endl;);
-
- while (gIsRun) {
- clientsocket = accept(serversocket, (struct sockaddr *) &clientAddr,
- (socklen_t*) &addr_len);
- if (clientsocket < 0) {
- perror("error: accept client socket !!!");
- continue;
- }
- if (gServerStatus == 0) {
- close(clientsocket);
- } else if (gServerStatus == 1) {
- pthread_t threadid;
- pthread_create(&threadid, NULL, processthread, (void *) this);
- //must have,otherwise the thread can not exit
- if (threadid != 0) { // can't exit thread without below code?
- pthread_join(threadid, NULL);
- }
- }
- }
- close(serversocket);
-}
-
-// set result to current if timeout
-void HttpServer::checkResult(TestCase* testcase) {
- if (!testcase->is_executed) {
- cout << "[ Warning: time is out, test case \"" << testcase->purpose << "\" is timeout, set the result to \"BLOCK\", and restart the client ]" << endl;
- DBG_ONLY(outputFile << "[ Warning: time is out, test case \"" << testcase->purpose << "\" is timeout, set the result to \"BLOCK\", and restart the client ]" << endl;);
-
- Json::Value result;
- result["result"] = "BLOCK";
- result["msg"] = "Time is out";
- testcase->set_result(result);
- m_last_auto_result = "BLOCK";
-
- if (g_run_wiget == true){
- cout << "[ start new client in 5sec ]" << endl;
- DBG_ONLY(outputFile << "[ start new client in 5sec ]" << endl;);
- sleep(5);
- start_client(); // start widget again in case it dead. browser not need to restart
- }
- m_timeout_count++;
- if (m_block_case_index < m_block_case_count) {
- m_block_case_index++;
- m_total_case_index++;
- }
- } else {
- cout << "[ test case \"" << testcase->purpose << "\" is executed in time, and the result is testcase->result ]" << endl;
- DBG_ONLY(outputFile << "[ test case \"" << testcase->purpose << "\" is executed in time, and the result is testcase->result ]" << endl;);
- }
-
-}
-
-void HttpServer::getAllWidget() {
- char buf[128];
- memset(buf, 0, 128);
- FILE *pp;
- string cmd = g_launcher+" -l | awk '{print $NF}' | sed -n '3,$p'";
- if ((pp = popen(cmd.c_str(), "r")) == NULL) {
- cout << "popen() error!" << endl;
- DBG_ONLY(outputFile << "popen() error!" << endl;);
- return;
- }
-
- while (fgets(buf, sizeof buf, pp)) {
- buf[strlen(buf) - 1] = 0; // remove the character return at the end.
- m_widgets.push_back(buf);
- memset(buf, 0, 128);
- }
- pclose(pp);
-}
-
-// try to kill all widget listed by wrt-launch -l
-void HttpServer::killAllWidget() {
- m_killing_widget = true;
- string cmd = "killall " + g_launcher + " 2>/dev/null";
- system(cmd.c_str());
-
- char buf[128];
- memset(buf, 0, 128);
- FILE *pp;
- if ((pp = popen("ps ax | awk '{print $NF}' | sed -n '2,$p'", "r")) == NULL) {
- cout << "popen() error!" << endl;
- DBG_ONLY(outputFile << "popen() error!" << endl;);
- return;
- }
-
- std::vector<string> processes;
- while (fgets(buf, sizeof buf, pp)) {
- if(g_show_log == true)
- cout<<buf<<endl;
- buf[strlen(buf) - 1] = 0; // remove the character return at the end.
- processes.push_back(buf);
- memset(buf, 0, 128);
- }
- if(g_show_log == true)
- cout<<"end while"<<endl;
- pclose(pp);
-
-
- for (unsigned int i = 0; i < m_widgets.size(); i++)
- for (unsigned int j = 0; j < processes.size(); j++)
- if (string::npos != processes[j].find(m_widgets[i])) {
- string cmd = g_launcher +" -k " + m_widgets[i]; // use wrt-launcher to kill widget
- DBG_ONLY(outputFile<<cmd<<endl;);
- if(g_show_log == true)
- cout<<cmd<<endl;
- run_cmd(cmd, "result: killed", true);
- break;
- }
- if(g_show_log == true)
- cout<<"end for"<<endl;
- m_killing_widget = false;
-}
-
-// try to start widget
-void HttpServer::start_client() {
- if (m_set_finished) return;// not restart widget if set finished
- if(g_run_wiget == true){
- run_cmd(g_kill_cmd, "result: killed", true);// kill before launch incase sometime relaunch fail, widget hang
- sleep(5);
- while (!run_cmd(g_launch_cmd, "result: launched", true)) {
- m_failto_launch++;
- DBG_ONLY(outputFile << m_failto_launch << endl;);
- if(g_show_log == true)
- cout << m_failto_launch << endl;
- if (m_failto_launch > 10) {
- m_set_finished = true;
- m_block_finished = true;
- m_total_case_index = m_totalcaseCount;
- break;
- }
- run_cmd(g_kill_cmd, "result: killed", true);
- sleep(10); // try until start widget success
- }
- m_failto_launch = 0;
- }
- else{
- sleep(5); // sleep 5 seconds to avoid launch browser too frequently, otherwise may launch fail.
- string launch_cmd = "";
- launch_cmd = g_launcher +"&";
- int status = system(launch_cmd.c_str());
- if(status != 0)
- {
- cout<<"[cmd: "<<launch_cmd<<" error]"<<endl;
- return;
- }
- }
-}
-
-// run shell cmd. return true if the output equal to expectString. show cmd and output if showcmdAnyway.
-bool HttpServer::run_cmd(string cmdString, string expectString,
- bool showcmdAnyway) {
- bool ret = false;
-
- char buf[128];
- memset(buf, 0, 128);
- FILE *pp;
- if ((pp = popen(cmdString.c_str(), "r")) == NULL) {
- cout << "popen() error!" << endl;
- DBG_ONLY(outputFile << "popen() error!" << endl;);
- return ret;
- }
-
- while (fgets(buf, sizeof buf, pp)) {
- if (strstr(buf, expectString.c_str()))
- ret = true;
- if (ret || showcmdAnyway) { // show cmd and result if ret or showcmdAnyWay
- cout << cmdString << endl;
- cout << buf << endl;
- DBG_ONLY(outputFile << cmdString << endl;);
- DBG_ONLY(outputFile << buf << endl;);
- }
- memset(buf, 0, 128);
- }
- pclose(pp);
- return ret;
-}
\ No newline at end of file
+++ /dev/null
-#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
-# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
-
-# include <stdlib.h>
-# include <assert.h>
-
-# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-
-namespace Json {
-
-/* Fast memory allocator.
- *
- * This memory allocator allocates memory for a batch of object (specified by
- * the page size, the number of object in each page).
- *
- * It does not allow the destruction of a single object. All the allocated objects
- * can be destroyed at once. The memory can be either released or reused for future
- * allocation.
- *
- * The in-place new operator must be used to construct the object using the pointer
- * returned by allocate.
- */
-template<typename AllocatedType, const unsigned int objectPerAllocation>
-class BatchAllocator {
-public:
- typedef AllocatedType Type;
-
- BatchAllocator(unsigned int objectsPerPage = 255) :
- freeHead_(0), objectsPerPage_(objectsPerPage) {
-// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
- assert(
- sizeof(AllocatedType) * objectPerAllocation
- >= sizeof(AllocatedType *)); // We must be able to store a slist in the object free space.
- assert(objectsPerPage >= 16);
- batches_ = allocateBatch(0); // allocated a dummy page
- currentBatch_ = batches_;
- }
-
- ~BatchAllocator() {
- for (BatchInfo *batch = batches_; batch;) {
- BatchInfo *nextBatch = batch->next_;
- free(batch);
- batch = nextBatch;
- }
- }
-
- /// allocate space for an array of objectPerAllocation object.
- /// @warning it is the responsability of the caller to call objects constructors.
- AllocatedType *allocate() {
- if (freeHead_) // returns node from free list.
- {
- AllocatedType *object = freeHead_;
- freeHead_ = *(AllocatedType **) object;
- return object;
- }
- if (currentBatch_->used_ == currentBatch_->end_) {
- currentBatch_ = currentBatch_->next_;
- while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_)
- currentBatch_ = currentBatch_->next_;
-
- if (!currentBatch_) // no free batch found, allocate a new one
- {
- currentBatch_ = allocateBatch(objectsPerPage_);
- currentBatch_->next_ = batches_; // insert at the head of the list
- batches_ = currentBatch_;
- }
- }
- AllocatedType *allocated = currentBatch_->used_;
- currentBatch_->used_ += objectPerAllocation;
- return allocated;
- }
-
- /// Release the object.
- /// @warning it is the responsability of the caller to actually destruct the object.
- void release(AllocatedType *object) {
- assert(object != 0);
- *(AllocatedType **) object = freeHead_;
- freeHead_ = object;
- }
-
-private:
- struct BatchInfo {
- BatchInfo *next_;
- AllocatedType *used_;
- AllocatedType *end_;
- AllocatedType buffer_[objectPerAllocation];
- };
-
- // disabled copy constructor and assignement operator.
- BatchAllocator(const BatchAllocator &);
- void operator =(const BatchAllocator &);
-
- static BatchInfo *allocateBatch(unsigned int objectsPerPage) {
- const unsigned int mallocSize = sizeof(BatchInfo)
- - sizeof(AllocatedType) * objectPerAllocation
- + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
- BatchInfo *batch = static_cast<BatchInfo*>(malloc(mallocSize));
- batch->next_ = 0;
- batch->used_ = batch->buffer_;
- batch->end_ = batch->buffer_ + objectsPerPage;
- return batch;
- }
-
- BatchInfo *batches_;
- BatchInfo *currentBatch_;
- /// Head of a single linked list within the allocated space of freeed object
- AllocatedType *freeHead_;
- unsigned int objectsPerPage_;
-};
-
-} // namespace Json
-
-# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
-#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
+++ /dev/null
-// included by json_value.cpp
-// everything is within Json namespace
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueInternalArray
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueArrayAllocator::~ValueArrayAllocator()
-{
-}
-
-// //////////////////////////////////////////////////////////////////
-// class DefaultValueArrayAllocator
-// //////////////////////////////////////////////////////////////////
-#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-class DefaultValueArrayAllocator : public ValueArrayAllocator
-{
-public: // overridden from ValueArrayAllocator
- virtual ~DefaultValueArrayAllocator()
- {
- }
-
- virtual ValueInternalArray *newArray()
- {
- return new ValueInternalArray();
- }
-
- virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
- {
- return new ValueInternalArray( other );
- }
-
- virtual void destructArray( ValueInternalArray *array )
- {
- delete array;
- }
-
- virtual void reallocateArrayPageIndex( Value **&indexes,
- ValueInternalArray::PageIndex &indexCount,
- ValueInternalArray::PageIndex minNewIndexCount )
- {
- ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
- if ( minNewIndexCount > newIndexCount )
- newIndexCount = minNewIndexCount;
- void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
- if ( !newIndexes )
- throw std::bad_alloc();
- indexCount = newIndexCount;
- indexes = static_cast<Value **>( newIndexes );
- }
- virtual void releaseArrayPageIndex( Value **indexes,
- ValueInternalArray::PageIndex indexCount )
- {
- if ( indexes )
- free( indexes );
- }
-
- virtual Value *allocateArrayPage()
- {
- return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
- }
-
- virtual void releaseArrayPage( Value *value )
- {
- if ( value )
- free( value );
- }
-};
-
-#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-/// @todo make this thread-safe (lock when accessign batch allocator)
-class DefaultValueArrayAllocator : public ValueArrayAllocator
-{
-public: // overridden from ValueArrayAllocator
- virtual ~DefaultValueArrayAllocator()
- {
- }
-
- virtual ValueInternalArray *newArray()
- {
- ValueInternalArray *array = arraysAllocator_.allocate();
- new (array) ValueInternalArray(); // placement new
- return array;
- }
-
- virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
- {
- ValueInternalArray *array = arraysAllocator_.allocate();
- new (array) ValueInternalArray( other ); // placement new
- return array;
- }
-
- virtual void destructArray( ValueInternalArray *array )
- {
- if ( array )
- {
- array->~ValueInternalArray();
- arraysAllocator_.release( array );
- }
- }
-
- virtual void reallocateArrayPageIndex( Value **&indexes,
- ValueInternalArray::PageIndex &indexCount,
- ValueInternalArray::PageIndex minNewIndexCount )
- {
- ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
- if ( minNewIndexCount > newIndexCount )
- newIndexCount = minNewIndexCount;
- void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
- if ( !newIndexes )
- throw std::bad_alloc();
- indexCount = newIndexCount;
- indexes = static_cast<Value **>( newIndexes );
- }
- virtual void releaseArrayPageIndex( Value **indexes,
- ValueInternalArray::PageIndex indexCount )
- {
- if ( indexes )
- free( indexes );
- }
-
- virtual Value *allocateArrayPage()
- {
- return static_cast<Value *>( pagesAllocator_.allocate() );
- }
-
- virtual void releaseArrayPage( Value *value )
- {
- if ( value )
- pagesAllocator_.release( value );
- }
-private:
- BatchAllocator<ValueInternalArray,1> arraysAllocator_;
- BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
-};
-#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-
-static ValueArrayAllocator *&arrayAllocator()
-{
- static DefaultValueArrayAllocator defaultAllocator;
- static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
- return arrayAllocator;
-}
-
-static struct DummyArrayAllocatorInitializer {
- DummyArrayAllocatorInitializer()
- {
- arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
- }
-} dummyArrayAllocatorInitializer;
-
-// //////////////////////////////////////////////////////////////////
-// class ValueInternalArray
-// //////////////////////////////////////////////////////////////////
-bool
-ValueInternalArray::equals( const IteratorState &x,
- const IteratorState &other )
-{
- return x.array_ == other.array_
- && x.currentItemIndex_ == other.currentItemIndex_
- && x.currentPageIndex_ == other.currentPageIndex_;
-}
-
-
-void
-ValueInternalArray::increment( IteratorState &it )
-{
- JSON_ASSERT_MESSAGE( it.array_ &&
- (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
- != it.array_->size_,
- "ValueInternalArray::increment(): moving iterator beyond end" );
- ++(it.currentItemIndex_);
- if ( it.currentItemIndex_ == itemsPerPage )
- {
- it.currentItemIndex_ = 0;
- ++(it.currentPageIndex_);
- }
-}
-
-
-void
-ValueInternalArray::decrement( IteratorState &it )
-{
- JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
- && it.currentItemIndex_ == 0,
- "ValueInternalArray::decrement(): moving iterator beyond end" );
- if ( it.currentItemIndex_ == 0 )
- {
- it.currentItemIndex_ = itemsPerPage-1;
- --(it.currentPageIndex_);
- }
- else
- {
- --(it.currentItemIndex_);
- }
-}
-
-
-Value &
-ValueInternalArray::unsafeDereference( const IteratorState &it )
-{
- return (*(it.currentPageIndex_))[it.currentItemIndex_];
-}
-
-
-Value &
-ValueInternalArray::dereference( const IteratorState &it )
-{
- JSON_ASSERT_MESSAGE( it.array_ &&
- (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
- < it.array_->size_,
- "ValueInternalArray::dereference(): dereferencing invalid iterator" );
- return unsafeDereference( it );
-}
-
-void
-ValueInternalArray::makeBeginIterator( IteratorState &it ) const
-{
- it.array_ = const_cast<ValueInternalArray *>( this );
- it.currentItemIndex_ = 0;
- it.currentPageIndex_ = pages_;
-}
-
-
-void
-ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
-{
- it.array_ = const_cast<ValueInternalArray *>( this );
- it.currentItemIndex_ = index % itemsPerPage;
- it.currentPageIndex_ = pages_ + index / itemsPerPage;
-}
-
-
-void
-ValueInternalArray::makeEndIterator( IteratorState &it ) const
-{
- makeIterator( it, size_ );
-}
-
-
-ValueInternalArray::ValueInternalArray()
- : pages_( 0 )
- , size_( 0 )
- , pageCount_( 0 )
-{
-}
-
-
-ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
- : pages_( 0 )
- , pageCount_( 0 )
- , size_( other.size_ )
-{
- PageIndex minNewPages = other.size_ / itemsPerPage;
- arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
- JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
- "ValueInternalArray::reserve(): bad reallocation" );
- IteratorState itOther;
- other.makeBeginIterator( itOther );
- Value *value;
- for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
- {
- if ( index % itemsPerPage == 0 )
- {
- PageIndex pageIndex = index / itemsPerPage;
- value = arrayAllocator()->allocateArrayPage();
- pages_[pageIndex] = value;
- }
- new (value) Value( dereference( itOther ) );
- }
-}
-
-
-ValueInternalArray &
-ValueInternalArray::operator =( const ValueInternalArray &other )
-{
- ValueInternalArray temp( other );
- swap( temp );
- return *this;
-}
-
-
-ValueInternalArray::~ValueInternalArray()
-{
- // destroy all constructed items
- IteratorState it;
- IteratorState itEnd;
- makeBeginIterator( it);
- makeEndIterator( itEnd );
- for ( ; !equals(it,itEnd); increment(it) )
- {
- Value *value = &dereference(it);
- value->~Value();
- }
- // release all pages
- PageIndex lastPageIndex = size_ / itemsPerPage;
- for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
- arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
- // release pages index
- arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
-}
-
-
-void
-ValueInternalArray::swap( ValueInternalArray &other )
-{
- Value **tempPages = pages_;
- pages_ = other.pages_;
- other.pages_ = tempPages;
- ArrayIndex tempSize = size_;
- size_ = other.size_;
- other.size_ = tempSize;
- PageIndex tempPageCount = pageCount_;
- pageCount_ = other.pageCount_;
- other.pageCount_ = tempPageCount;
-}
-
-void
-ValueInternalArray::clear()
-{
- ValueInternalArray dummy;
- swap( dummy );
-}
-
-
-void
-ValueInternalArray::resize( ArrayIndex newSize )
-{
- if ( newSize == 0 )
- clear();
- else if ( newSize < size_ )
- {
- IteratorState it;
- IteratorState itEnd;
- makeIterator( it, newSize );
- makeIterator( itEnd, size_ );
- for ( ; !equals(it,itEnd); increment(it) )
- {
- Value *value = &dereference(it);
- value->~Value();
- }
- PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
- PageIndex lastPageIndex = size_ / itemsPerPage;
- for ( ; pageIndex < lastPageIndex; ++pageIndex )
- arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
- size_ = newSize;
- }
- else if ( newSize > size_ )
- resolveReference( newSize );
-}
-
-
-void
-ValueInternalArray::makeIndexValid( ArrayIndex index )
-{
- // Need to enlarge page index ?
- if ( index >= pageCount_ * itemsPerPage )
- {
- PageIndex minNewPages = (index + 1) / itemsPerPage;
- arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
- JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
- }
-
- // Need to allocate new pages ?
- ArrayIndex nextPageIndex =
- (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
- : size_;
- if ( nextPageIndex <= index )
- {
- PageIndex pageIndex = nextPageIndex / itemsPerPage;
- PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
- for ( ; pageToAllocate-- > 0; ++pageIndex )
- pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
- }
-
- // Initialize all new entries
- IteratorState it;
- IteratorState itEnd;
- makeIterator( it, size_ );
- size_ = index + 1;
- makeIterator( itEnd, size_ );
- for ( ; !equals(it,itEnd); increment(it) )
- {
- Value *value = &dereference(it);
- new (value) Value(); // Construct a default value using placement new
- }
-}
-
-Value &
-ValueInternalArray::resolveReference( ArrayIndex index )
-{
- if ( index >= size_ )
- makeIndexValid( index );
- return pages_[index/itemsPerPage][index%itemsPerPage];
-}
-
-Value *
-ValueInternalArray::find( ArrayIndex index ) const
-{
- if ( index >= size_ )
- return 0;
- return &(pages_[index/itemsPerPage][index%itemsPerPage]);
-}
-
-ValueInternalArray::ArrayIndex
-ValueInternalArray::size() const
-{
- return size_;
-}
-
-int
-ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
-{
- return indexOf(y) - indexOf(x);
-}
-
-
-ValueInternalArray::ArrayIndex
-ValueInternalArray::indexOf( const IteratorState &iterator )
-{
- if ( !iterator.array_ )
- return ArrayIndex(-1);
- return ArrayIndex(
- (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
- + iterator.currentItemIndex_ );
-}
-
-
-int
-ValueInternalArray::compare( const ValueInternalArray &other ) const
-{
- int sizeDiff( size_ - other.size_ );
- if ( sizeDiff != 0 )
- return sizeDiff;
-
- for ( ArrayIndex index =0; index < size_; ++index )
- {
- int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
- other.pages_[index/itemsPerPage][index%itemsPerPage] );
- if ( diff != 0 )
- return diff;
- }
- return 0;
-}
+++ /dev/null
-// included by json_value.cpp
-// everything is within Json namespace
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueInternalMap
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
- * This optimization is used by the fast allocator.
- */
-ValueInternalLink::ValueInternalLink()
- : previous_( 0 )
- , next_( 0 )
-{
-}
-
-ValueInternalLink::~ValueInternalLink()
-{
- for ( int index =0; index < itemPerLink; ++index )
- {
- if ( !items_[index].isItemAvailable() )
- {
- if ( !items_[index].isMemberNameStatic() )
- free( keys_[index] );
- }
- else
- break;
- }
-}
-
-
-
-ValueMapAllocator::~ValueMapAllocator()
-{
-}
-
-#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-class DefaultValueMapAllocator : public ValueMapAllocator
-{
-public: // overridden from ValueMapAllocator
- virtual ValueInternalMap *newMap()
- {
- return new ValueInternalMap();
- }
-
- virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
- {
- return new ValueInternalMap( other );
- }
-
- virtual void destructMap( ValueInternalMap *map )
- {
- delete map;
- }
-
- virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
- {
- return new ValueInternalLink[size];
- }
-
- virtual void releaseMapBuckets( ValueInternalLink *links )
- {
- delete [] links;
- }
-
- virtual ValueInternalLink *allocateMapLink()
- {
- return new ValueInternalLink();
- }
-
- virtual void releaseMapLink( ValueInternalLink *link )
- {
- delete link;
- }
-};
-#else
-/// @todo make this thread-safe (lock when accessign batch allocator)
-class DefaultValueMapAllocator : public ValueMapAllocator
-{
-public: // overridden from ValueMapAllocator
- virtual ValueInternalMap *newMap()
- {
- ValueInternalMap *map = mapsAllocator_.allocate();
- new (map) ValueInternalMap(); // placement new
- return map;
- }
-
- virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
- {
- ValueInternalMap *map = mapsAllocator_.allocate();
- new (map) ValueInternalMap( other ); // placement new
- return map;
- }
-
- virtual void destructMap( ValueInternalMap *map )
- {
- if ( map )
- {
- map->~ValueInternalMap();
- mapsAllocator_.release( map );
- }
- }
-
- virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
- {
- return new ValueInternalLink[size];
- }
-
- virtual void releaseMapBuckets( ValueInternalLink *links )
- {
- delete [] links;
- }
-
- virtual ValueInternalLink *allocateMapLink()
- {
- ValueInternalLink *link = linksAllocator_.allocate();
- memset( link, 0, sizeof(ValueInternalLink) );
- return link;
- }
-
- virtual void releaseMapLink( ValueInternalLink *link )
- {
- link->~ValueInternalLink();
- linksAllocator_.release( link );
- }
-private:
- BatchAllocator<ValueInternalMap,1> mapsAllocator_;
- BatchAllocator<ValueInternalLink,1> linksAllocator_;
-};
-#endif
-
-static ValueMapAllocator *&mapAllocator()
-{
- static DefaultValueMapAllocator defaultAllocator;
- static ValueMapAllocator *mapAllocator = &defaultAllocator;
- return mapAllocator;
-}
-
-static struct DummyMapAllocatorInitializer {
- DummyMapAllocatorInitializer()
- {
- mapAllocator(); // ensure mapAllocator() statics are initialized before main().
- }
-} dummyMapAllocatorInitializer;
-
-
-
-// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
-
-/*
-use linked list hash map.
-buckets array is a container.
-linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
-value have extra state: valid, available, deleted
-*/
-
-
-ValueInternalMap::ValueInternalMap()
- : buckets_( 0 )
- , tailLink_( 0 )
- , bucketsSize_( 0 )
- , itemCount_( 0 )
-{
-}
-
-
-ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
- : buckets_( 0 )
- , tailLink_( 0 )
- , bucketsSize_( 0 )
- , itemCount_( 0 )
-{
- reserve( other.itemCount_ );
- IteratorState it;
- IteratorState itEnd;
- other.makeBeginIterator( it );
- other.makeEndIterator( itEnd );
- for ( ; !equals(it,itEnd); increment(it) )
- {
- bool isStatic;
- const char *memberName = key( it, isStatic );
- const Value &aValue = value( it );
- resolveReference(memberName, isStatic) = aValue;
- }
-}
-
-
-ValueInternalMap &
-ValueInternalMap::operator =( const ValueInternalMap &other )
-{
- ValueInternalMap dummy( other );
- swap( dummy );
- return *this;
-}
-
-
-ValueInternalMap::~ValueInternalMap()
-{
- if ( buckets_ )
- {
- for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
- {
- ValueInternalLink *link = buckets_[bucketIndex].next_;
- while ( link )
- {
- ValueInternalLink *linkToRelease = link;
- link = link->next_;
- mapAllocator()->releaseMapLink( linkToRelease );
- }
- }
- mapAllocator()->releaseMapBuckets( buckets_ );
- }
-}
-
-
-void
-ValueInternalMap::swap( ValueInternalMap &other )
-{
- ValueInternalLink *tempBuckets = buckets_;
- buckets_ = other.buckets_;
- other.buckets_ = tempBuckets;
- ValueInternalLink *tempTailLink = tailLink_;
- tailLink_ = other.tailLink_;
- other.tailLink_ = tempTailLink;
- BucketIndex tempBucketsSize = bucketsSize_;
- bucketsSize_ = other.bucketsSize_;
- other.bucketsSize_ = tempBucketsSize;
- BucketIndex tempItemCount = itemCount_;
- itemCount_ = other.itemCount_;
- other.itemCount_ = tempItemCount;
-}
-
-
-void
-ValueInternalMap::clear()
-{
- ValueInternalMap dummy;
- swap( dummy );
-}
-
-
-ValueInternalMap::BucketIndex
-ValueInternalMap::size() const
-{
- return itemCount_;
-}
-
-bool
-ValueInternalMap::reserveDelta( BucketIndex growth )
-{
- return reserve( itemCount_ + growth );
-}
-
-bool
-ValueInternalMap::reserve( BucketIndex newItemCount )
-{
- if ( !buckets_ && newItemCount > 0 )
- {
- buckets_ = mapAllocator()->allocateMapBuckets( 1 );
- bucketsSize_ = 1;
- tailLink_ = &buckets_[0];
- }
-// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
- return true;
-}
-
-
-const Value *
-ValueInternalMap::find( const char *key ) const
-{
- if ( !bucketsSize_ )
- return 0;
- HashKey hashedKey = hash( key );
- BucketIndex bucketIndex = hashedKey % bucketsSize_;
- for ( const ValueInternalLink *current = &buckets_[bucketIndex];
- current != 0;
- current = current->next_ )
- {
- for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
- {
- if ( current->items_[index].isItemAvailable() )
- return 0;
- if ( strcmp( key, current->keys_[index] ) == 0 )
- return ¤t->items_[index];
- }
- }
- return 0;
-}
-
-
-Value *
-ValueInternalMap::find( const char *key )
-{
- const ValueInternalMap *constThis = this;
- return const_cast<Value *>( constThis->find( key ) );
-}
-
-
-Value &
-ValueInternalMap::resolveReference( const char *key,
- bool isStatic )
-{
- HashKey hashedKey = hash( key );
- if ( bucketsSize_ )
- {
- BucketIndex bucketIndex = hashedKey % bucketsSize_;
- ValueInternalLink **previous = 0;
- BucketIndex index;
- for ( ValueInternalLink *current = &buckets_[bucketIndex];
- current != 0;
- previous = ¤t->next_, current = current->next_ )
- {
- for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
- {
- if ( current->items_[index].isItemAvailable() )
- return setNewItem( key, isStatic, current, index );
- if ( strcmp( key, current->keys_[index] ) == 0 )
- return current->items_[index];
- }
- }
- }
-
- reserveDelta( 1 );
- return unsafeAdd( key, isStatic, hashedKey );
-}
-
-
-void
-ValueInternalMap::remove( const char *key )
-{
- HashKey hashedKey = hash( key );
- if ( !bucketsSize_ )
- return;
- BucketIndex bucketIndex = hashedKey % bucketsSize_;
- for ( ValueInternalLink *link = &buckets_[bucketIndex];
- link != 0;
- link = link->next_ )
- {
- BucketIndex index;
- for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
- {
- if ( link->items_[index].isItemAvailable() )
- return;
- if ( strcmp( key, link->keys_[index] ) == 0 )
- {
- doActualRemove( link, index, bucketIndex );
- return;
- }
- }
- }
-}
-
-void
-ValueInternalMap::doActualRemove( ValueInternalLink *link,
- BucketIndex index,
- BucketIndex bucketIndex )
-{
- // find last item of the bucket and swap it with the 'removed' one.
- // set removed items flags to 'available'.
- // if last page only contains 'available' items, then desallocate it (it's empty)
- ValueInternalLink *&lastLink = getLastLinkInBucket( index );
- BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
- for ( ;
- lastItemIndex < ValueInternalLink::itemPerLink;
- ++lastItemIndex ) // may be optimized with dicotomic search
- {
- if ( lastLink->items_[lastItemIndex].isItemAvailable() )
- break;
- }
-
- BucketIndex lastUsedIndex = lastItemIndex - 1;
- Value *valueToDelete = &link->items_[index];
- Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
- if ( valueToDelete != valueToPreserve )
- valueToDelete->swap( *valueToPreserve );
- if ( lastUsedIndex == 0 ) // page is now empty
- { // remove it from bucket linked list and delete it.
- ValueInternalLink *linkPreviousToLast = lastLink->previous_;
- if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
- {
- mapAllocator()->releaseMapLink( lastLink );
- linkPreviousToLast->next_ = 0;
- lastLink = linkPreviousToLast;
- }
- }
- else
- {
- Value dummy;
- valueToPreserve->swap( dummy ); // restore deleted to default Value.
- valueToPreserve->setItemUsed( false );
- }
- --itemCount_;
-}
-
-
-ValueInternalLink *&
-ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
-{
- if ( bucketIndex == bucketsSize_ - 1 )
- return tailLink_;
- ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
- if ( !previous )
- previous = &buckets_[bucketIndex];
- return previous;
-}
-
-
-Value &
-ValueInternalMap::setNewItem( const char *key,
- bool isStatic,
- ValueInternalLink *link,
- BucketIndex index )
-{
- char *duplicatedKey = valueAllocator()->makeMemberName( key );
- ++itemCount_;
- link->keys_[index] = duplicatedKey;
- link->items_[index].setItemUsed();
- link->items_[index].setMemberNameIsStatic( isStatic );
- return link->items_[index]; // items already default constructed.
-}
-
-
-Value &
-ValueInternalMap::unsafeAdd( const char *key,
- bool isStatic,
- HashKey hashedKey )
-{
- JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
- BucketIndex bucketIndex = hashedKey % bucketsSize_;
- ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
- ValueInternalLink *link = previousLink;
- BucketIndex index;
- for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
- {
- if ( link->items_[index].isItemAvailable() )
- break;
- }
- if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
- {
- ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
- index = 0;
- link->next_ = newLink;
- previousLink = newLink;
- link = newLink;
- }
- return setNewItem( key, isStatic, link, index );
-}
-
-
-ValueInternalMap::HashKey
-ValueInternalMap::hash( const char *key ) const
-{
- HashKey hash = 0;
- while ( *key )
- hash += *key++ * 37;
- return hash;
-}
-
-
-int
-ValueInternalMap::compare( const ValueInternalMap &other ) const
-{
- int sizeDiff( itemCount_ - other.itemCount_ );
- if ( sizeDiff != 0 )
- return sizeDiff;
- // Strict order guaranty is required. Compare all keys FIRST, then compare values.
- IteratorState it;
- IteratorState itEnd;
- makeBeginIterator( it );
- makeEndIterator( itEnd );
- for ( ; !equals(it,itEnd); increment(it) )
- {
- if ( !other.find( key( it ) ) )
- return 1;
- }
-
- // All keys are equals, let's compare values
- makeBeginIterator( it );
- for ( ; !equals(it,itEnd); increment(it) )
- {
- const Value *otherValue = other.find( key( it ) );
- int valueDiff = value(it).compare( *otherValue );
- if ( valueDiff != 0 )
- return valueDiff;
- }
- return 0;
-}
-
-
-void
-ValueInternalMap::makeBeginIterator( IteratorState &it ) const
-{
- it.map_ = const_cast<ValueInternalMap *>( this );
- it.bucketIndex_ = 0;
- it.itemIndex_ = 0;
- it.link_ = buckets_;
-}
-
-
-void
-ValueInternalMap::makeEndIterator( IteratorState &it ) const
-{
- it.map_ = const_cast<ValueInternalMap *>( this );
- it.bucketIndex_ = bucketsSize_;
- it.itemIndex_ = 0;
- it.link_ = 0;
-}
-
-
-bool
-ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
-{
- return x.map_ == other.map_
- && x.bucketIndex_ == other.bucketIndex_
- && x.link_ == other.link_
- && x.itemIndex_ == other.itemIndex_;
-}
-
-
-void
-ValueInternalMap::incrementBucket( IteratorState &iterator )
-{
- ++iterator.bucketIndex_;
- JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
- "ValueInternalMap::increment(): attempting to iterate beyond end." );
- if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
- iterator.link_ = 0;
- else
- iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
- iterator.itemIndex_ = 0;
-}
-
-
-void
-ValueInternalMap::increment( IteratorState &iterator )
-{
- JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
- ++iterator.itemIndex_;
- if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
- {
- JSON_ASSERT_MESSAGE( iterator.link_ != 0,
- "ValueInternalMap::increment(): attempting to iterate beyond end." );
- iterator.link_ = iterator.link_->next_;
- if ( iterator.link_ == 0 )
- incrementBucket( iterator );
- }
- else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
- {
- incrementBucket( iterator );
- }
-}
-
-
-void
-ValueInternalMap::decrement( IteratorState &iterator )
-{
- if ( iterator.itemIndex_ == 0 )
- {
- JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
- if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
- {
- JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
- --(iterator.bucketIndex_);
- }
- iterator.link_ = iterator.link_->previous_;
- iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
- }
-}
-
-
-const char *
-ValueInternalMap::key( const IteratorState &iterator )
-{
- JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
- return iterator.link_->keys_[iterator.itemIndex_];
-}
-
-const char *
-ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
-{
- JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
- isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
- return iterator.link_->keys_[iterator.itemIndex_];
-}
-
-
-Value &
-ValueInternalMap::value( const IteratorState &iterator )
-{
- JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
- return iterator.link_->items_[iterator.itemIndex_];
-}
-
-
-int
-ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
-{
- int offset = 0;
- IteratorState it = x;
- while ( !equals( it, y ) )
- increment( it );
- return offset;
-}
+++ /dev/null
-#include <json/reader.h>
-#include <json/value.h>
-#include <utility>
-#include <cstdio>
-#include <cassert>
-#include <cstring>
-#include <iostream>
-#include <stdexcept>
-
-#if _MSC_VER >= 1400 // VC++ 8.0
-#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
-#endif
-
-namespace Json {
-
-// Implementation of class Features
-// ////////////////////////////////
-
-Features::Features() :
- allowComments_(true), strictRoot_(false) {
-}
-
-Features Features::all() {
- return Features();
-}
-
-Features Features::strictMode() {
- Features features;
- features.allowComments_ = false;
- features.strictRoot_ = true;
- return features;
-}
-
-// Implementation of class Reader
-// ////////////////////////////////
-
-static inline bool in(Reader::Char c, Reader::Char c1, Reader::Char c2,
- Reader::Char c3, Reader::Char c4) {
- return c == c1 || c == c2 || c == c3 || c == c4;
-}
-
-static inline bool in(Reader::Char c, Reader::Char c1, Reader::Char c2,
- Reader::Char c3, Reader::Char c4, Reader::Char c5) {
- return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
-}
-
-static bool containsNewLine(Reader::Location begin, Reader::Location end) {
- for (; begin < end; ++begin)
- if (*begin == '\n' || *begin == '\r')
- return true;
- return false;
-}
-
-static std::string codePointToUTF8(unsigned int cp) {
- std::string result;
-
- // based on description from http://en.wikipedia.org/wiki/UTF-8
-
- if (cp <= 0x7f) {
- result.resize(1);
- result[0] = static_cast<char>(cp);
- } else if (cp <= 0x7FF) {
- result.resize(2);
- result[1] = static_cast<char>(0x80 | (0x3f & cp));
- result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
- } else if (cp <= 0xFFFF) {
- result.resize(3);
- result[2] = static_cast<char>(0x80 | (0x3f & cp));
- result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
- result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
- } else if (cp <= 0x10FFFF) {
- result.resize(4);
- result[3] = static_cast<char>(0x80 | (0x3f & cp));
- result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
- result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
- result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
- }
-
- return result;
-}
-
-// Class Reader
-// //////////////////////////////////////////////////////////////////
-
-Reader::Reader() :
- features_(Features::all()) {
-}
-
-Reader::Reader(const Features &features) :
- features_(features) {
-}
-
-bool Reader::parse(const std::string &document, Value &root,
- bool collectComments) {
- document_ = document;
- const char *begin = document_.c_str();
- const char *end = begin + document_.length();
- return parse(begin, end, root, collectComments);
-}
-
-bool Reader::parse(std::istream& sin, Value &root, bool collectComments) {
- //std::istream_iterator<char> begin(sin);
- //std::istream_iterator<char> end;
- // Those would allow streamed input from a file, if parse() were a
- // template function.
-
- // Since std::string is reference-counted, this at least does not
- // create an extra copy.
- std::string doc;
- std::getline(sin, doc, (char) EOF);
- return parse(doc, root, collectComments);
-}
-
-bool Reader::parse(const char *beginDoc, const char *endDoc, Value &root,
- bool collectComments) {
- if (!features_.allowComments_) {
- collectComments = false;
- }
-
- begin_ = beginDoc;
- end_ = endDoc;
- collectComments_ = collectComments;
- current_ = begin_;
- lastValueEnd_ = 0;
- lastValue_ = 0;
- commentsBefore_ = "";
- errors_.clear();
- while (!nodes_.empty())
- nodes_.pop();
- nodes_.push(&root);
-
- bool successful = readValue();
- Token token;
- skipCommentTokens(token);
- if (collectComments_ && !commentsBefore_.empty())
- root.setComment(commentsBefore_, commentAfter);
- if (features_.strictRoot_) {
- if (!root.isArray() && !root.isObject()) {
- // Set error location to start of doc, ideally should be first token found in doc
- token.type_ = tokenError;
- token.start_ = beginDoc;
- token.end_ = endDoc;
- addError(
- "A valid JSON document must be either an array or an object value.",
- token);
- return false;
- }
- }
- return successful;
-}
-
-bool Reader::readValue() {
- Token token;
- skipCommentTokens(token);
- bool successful = true;
-
- if (collectComments_ && !commentsBefore_.empty()) {
- currentValue().setComment(commentsBefore_, commentBefore);
- commentsBefore_ = "";
- }
-
- switch (token.type_) {
- case tokenObjectBegin:
- successful = readObject(token);
- break;
- case tokenArrayBegin:
- successful = readArray(token);
- break;
- case tokenNumber:
- successful = decodeNumber(token);
- break;
- case tokenString:
- successful = decodeString(token);
- break;
- case tokenTrue:
- currentValue() = true;
- break;
- case tokenFalse:
- currentValue() = false;
- break;
- case tokenNull:
- currentValue() = Value();
- break;
- default:
- return addError("Syntax error: value, object or array expected.", token);
- }
-
- if (collectComments_) {
- lastValueEnd_ = current_;
- lastValue_ = ¤tValue();
- }
-
- return successful;
-}
-
-void Reader::skipCommentTokens(Token &token) {
- if (features_.allowComments_) {
- do {
- readToken(token);
- } while (token.type_ == tokenComment);
- } else {
- readToken(token);
- }
-}
-
-bool Reader::expectToken(TokenType type, Token &token, const char *message) {
- readToken(token);
- if (token.type_ != type)
- return addError(message, token);
- return true;
-}
-
-bool Reader::readToken(Token &token) {
- skipSpaces();
- token.start_ = current_;
- Char c = getNextChar();
- bool ok = true;
- switch (c) {
- case '{':
- token.type_ = tokenObjectBegin;
- break;
- case '}':
- token.type_ = tokenObjectEnd;
- break;
- case '[':
- token.type_ = tokenArrayBegin;
- break;
- case ']':
- token.type_ = tokenArrayEnd;
- break;
- case '"':
- token.type_ = tokenString;
- ok = readString();
- break;
- case '/':
- token.type_ = tokenComment;
- ok = readComment();
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '-':
- token.type_ = tokenNumber;
- readNumber();
- break;
- case 't':
- token.type_ = tokenTrue;
- ok = match("rue", 3);
- break;
- case 'f':
- token.type_ = tokenFalse;
- ok = match("alse", 4);
- break;
- case 'n':
- token.type_ = tokenNull;
- ok = match("ull", 3);
- break;
- case ',':
- token.type_ = tokenArraySeparator;
- break;
- case ':':
- token.type_ = tokenMemberSeparator;
- break;
- case 0:
- token.type_ = tokenEndOfStream;
- break;
- default:
- ok = false;
- break;
- }
- if (!ok)
- token.type_ = tokenError;
- token.end_ = current_;
- return true;
-}
-
-void Reader::skipSpaces() {
- while (current_ != end_) {
- Char c = *current_;
- if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- ++current_;
- else
- break;
- }
-}
-
-bool Reader::match(Location pattern, int patternLength) {
- if (end_ - current_ < patternLength)
- return false;
- int index = patternLength;
- while (index--)
- if (current_[index] != pattern[index])
- return false;
- current_ += patternLength;
- return true;
-}
-
-bool Reader::readComment() {
- Location commentBegin = current_ - 1;
- Char c = getNextChar();
- bool successful = false;
- if (c == '*')
- successful = readCStyleComment();
- else if (c == '/')
- successful = readCppStyleComment();
- if (!successful)
- return false;
-
- if (collectComments_) {
- CommentPlacement placement = commentBefore;
- if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, current_))
- placement = commentAfterOnSameLine;
- }
-
- addComment(commentBegin, current_, placement);
- }
- return true;
-}
-
-void Reader::addComment(Location begin, Location end,
- CommentPlacement placement) {
- assert(collectComments_);
- if (placement == commentAfterOnSameLine) {
- assert(lastValue_ != 0);
- lastValue_->setComment(std::string(begin, end), placement);
- } else {
- if (!commentsBefore_.empty())
- commentsBefore_ += "\n";
- commentsBefore_ += std::string(begin, end);
- }
-}
-
-bool Reader::readCStyleComment() {
- while (current_ != end_) {
- Char c = getNextChar();
- if (c == '*' && *current_ == '/')
- break;
- }
- return getNextChar() == '/';
-}
-
-bool Reader::readCppStyleComment() {
- while (current_ != end_) {
- Char c = getNextChar();
- if (c == '\r' || c == '\n')
- break;
- }
- return true;
-}
-
-void Reader::readNumber() {
- while (current_ != end_) {
- if (!(*current_ >= '0' && *current_ <= '9')
- && !in(*current_, '.', 'e', 'E', '+', '-'))
- break;
- ++current_;
- }
-}
-
-bool Reader::readString() {
- Char c = 0;
- while (current_ != end_) {
- c = getNextChar();
- if (c == '\\')
- getNextChar();
- else if (c == '"')
- break;
- }
- return c == '"';
-}
-
-bool Reader::readObject(Token &tokenStart) {
- Token tokenName;
- std::string name;
- currentValue() = Value(objectValue);
- while (readToken(tokenName)) {
- bool initialTokenOk = true;
- while (tokenName.type_ == tokenComment && initialTokenOk)
- initialTokenOk = readToken(tokenName);
- if (!initialTokenOk)
- break;
- if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
- return true;
- if (tokenName.type_ != tokenString)
- break;
-
- name = "";
- if (!decodeString(tokenName, name))
- return recoverFromError(tokenObjectEnd);
-
- Token colon;
- if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return addErrorAndRecover("Missing ':' after object member name",
- colon, tokenObjectEnd);
- }
- Value &value = currentValue()[name];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
- if (!ok) // error already set
- return recoverFromError(tokenObjectEnd);
-
- Token comma;
- if (!readToken(comma)
- || (comma.type_ != tokenObjectEnd
- && comma.type_ != tokenArraySeparator
- && comma.type_ != tokenComment)) {
- return addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma,
- tokenObjectEnd);
- }
- bool finalizeTokenOk = true;
- while (comma.type_ == tokenComment && finalizeTokenOk)
- finalizeTokenOk = readToken(comma);
- if (comma.type_ == tokenObjectEnd)
- return true;
- }
- return addErrorAndRecover("Missing '}' or object member name", tokenName,
- tokenObjectEnd);
-}
-
-bool Reader::readArray(Token &tokenStart) {
- currentValue() = Value(arrayValue);
- skipSpaces();
- if (*current_ == ']') // empty array
- {
- Token endArray;
- readToken(endArray);
- return true;
- }
- int index = 0;
- while (true) {
- Value &value = currentValue()[index++];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
- if (!ok) // error already set
- return recoverFromError(tokenArrayEnd);
-
- Token token;
- // Accept Comment after last item in the array.
- ok = readToken(token);
- while (token.type_ == tokenComment && ok) {
- ok = readToken(token);
- }
- bool badTokenType = (token.type_ == tokenArraySeparator
- && token.type_ == tokenArrayEnd);
- if (!ok || badTokenType) {
- return addErrorAndRecover("Missing ',' or ']' in array declaration",
- token, tokenArrayEnd);
- }
- if (token.type_ == tokenArrayEnd)
- break;
- }
- return true;
-}
-
-bool Reader::decodeNumber(Token &token) {
- bool isDouble = false;
- for (Location inspect = token.start_; inspect != token.end_; ++inspect) {
- isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+')
- || (*inspect == '-' && inspect != token.start_);
- }
- if (isDouble)
- return decodeDouble(token);
- Location current = token.start_;
- bool isNegative = *current == '-';
- if (isNegative)
- ++current;
- Value::UInt threshold = (
- isNegative ? Value::UInt(-Value::minInt) : Value::maxUInt) / 10;
- Value::UInt value = 0;
- while (current < token.end_) {
- Char c = *current++;
- if (c < '0' || c > '9')
- return addError(
- "'" + std::string(token.start_, token.end_)
- + "' is not a number.", token);
- if (value >= threshold)
- return decodeDouble(token);
- value = value * 10 + Value::UInt(c - '0');
- }
- if (isNegative)
- currentValue() = -Value::Int(value);
- else if (value <= Value::UInt(Value::maxInt))
- currentValue() = Value::Int(value);
- else
- currentValue() = value;
- return true;
-}
-
-bool Reader::decodeDouble(Token &token) {
- double value = 0;
- const int bufferSize = 32;
- int count;
- int length = int(token.end_ - token.start_);
- if (length <= bufferSize) {
- Char buffer[bufferSize];
- memcpy(buffer, token.start_, length);
- buffer[length] = 0;
- count = sscanf(buffer, "%lf", &value);
- } else {
- std::string buffer(token.start_, token.end_);
- count = sscanf(buffer.c_str(), "%lf", &value);
- }
-
- if (count != 1)
- return addError(
- "'" + std::string(token.start_, token.end_)
- + "' is not a number.", token);
- currentValue() = value;
- return true;
-}
-
-bool Reader::decodeString(Token &token) {
- std::string decoded;
- if (!decodeString(token, decoded))
- return false;
- currentValue() = decoded;
- return true;
-}
-
-bool Reader::decodeString(Token &token, std::string &decoded) {
- decoded.reserve(token.end_ - token.start_ - 2);
- Location current = token.start_ + 1; // skip '"'
- Location end = token.end_ - 1; // do not include '"'
- while (current != end) {
- Char c = *current++;
- if (c == '"')
- break;
- else if (c == '\\') {
- if (current == end)
- return addError("Empty escape sequence in string", token,
- current);
- Char escape = *current++;
- switch (escape) {
- case '"':
- decoded += '"';
- break;
- case '/':
- decoded += '/';
- break;
- case '\\':
- decoded += '\\';
- break;
- case 'b':
- decoded += '\b';
- break;
- case 'f':
- decoded += '\f';
- break;
- case 'n':
- decoded += '\n';
- break;
- case 'r':
- decoded += '\r';
- break;
- case 't':
- decoded += '\t';
- break;
- case 'u': {
- unsigned int unicode;
- if (!decodeUnicodeCodePoint(token, current, end, unicode))
- return false;
- decoded += codePointToUTF8(unicode);
- }
- break;
- default:
- return addError("Bad escape sequence in string", token, current);
- }
- } else {
- decoded += c;
- }
- }
- return true;
-}
-
-bool Reader::decodeUnicodeCodePoint(Token &token, Location ¤t,
- Location end, unsigned int &unicode) {
-
- if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
- return false;
- if (unicode >= 0xD800 && unicode <= 0xDBFF) {
- // surrogate pairs
- if (end - current < 6)
- return addError(
- "additional six characters expected to parse unicode surrogate pair.",
- token, current);
- unsigned int surrogatePair;
- if (*(current++) == '\\' && *(current++) == 'u') {
- if (decodeUnicodeEscapeSequence(token, current, end,
- surrogatePair)) {
- unicode = 0x10000 + ((unicode & 0x3FF) << 10)
- + (surrogatePair & 0x3FF);
- } else
- return false;
- } else
- return addError(
- "expecting another \\u token to begin the second half of a unicode surrogate pair",
- token, current);
- }
- return true;
-}
-
-bool Reader::decodeUnicodeEscapeSequence(Token &token, Location ¤t,
- Location end, unsigned int &unicode) {
- if (end - current < 4)
- return addError(
- "Bad unicode escape sequence in string: four digits expected.",
- token, current);
- unicode = 0;
- for (int index = 0; index < 4; ++index) {
- Char c = *current++;
- unicode *= 16;
- if (c >= '0' && c <= '9')
- unicode += c - '0';
- else if (c >= 'a' && c <= 'f')
- unicode += c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- unicode += c - 'A' + 10;
- else
- return addError(
- "Bad unicode escape sequence in string: hexadecimal digit expected.",
- token, current);
- }
- return true;
-}
-
-bool Reader::addError(const std::string &message, Token &token,
- Location extra) {
- ErrorInfo info;
- info.token_ = token;
- info.message_ = message;
- info.extra_ = extra;
- errors_.push_back(info);
- return false;
-}
-
-bool Reader::recoverFromError(TokenType skipUntilToken) {
- int errorCount = int(errors_.size());
- Token skip;
- while (true) {
- if (!readToken(skip))
- errors_.resize(errorCount); // discard errors caused by recovery
- if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
- break;
- }
- errors_.resize(errorCount);
- return false;
-}
-
-bool Reader::addErrorAndRecover(const std::string &message, Token &token,
- TokenType skipUntilToken) {
- addError(message, token);
- return recoverFromError(skipUntilToken);
-}
-
-Value &
-Reader::currentValue() {
- return *(nodes_.top());
-}
-
-Reader::Char Reader::getNextChar() {
- if (current_ == end_)
- return 0;
- return *current_++;
-}
-
-void Reader::getLocationLineAndColumn(Location location, int &line,
- int &column) const {
- Location current = begin_;
- Location lastLineStart = current;
- line = 0;
- while (current < location && current != end_) {
- Char c = *current++;
- if (c == '\r') {
- if (*current == '\n')
- ++current;
- lastLineStart = current;
- ++line;
- } else if (c == '\n') {
- lastLineStart = current;
- ++line;
- }
- }
- // column & line start at 1
- column = int(location - lastLineStart) + 1;
- ++line;
-}
-
-std::string Reader::getLocationLineAndColumn(Location location) const {
- int line, column;
- getLocationLineAndColumn(location, line, column);
- char buffer[18 + 16 + 16 + 1];
- sprintf(buffer, "Line %d, Column %d", line, column);
- return buffer;
-}
-
-std::string Reader::getFormatedErrorMessages() const {
- std::string formattedMessage;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end(); ++itError) {
- const ErrorInfo &error = *itError;
- formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_)
- + "\n";
- formattedMessage += " " + error.message_ + "\n";
- if (error.extra_)
- formattedMessage += "See " + getLocationLineAndColumn(error.extra_)
- + " for detail.\n";
- }
- return formattedMessage;
-}
-
-std::istream& operator>>(std::istream &sin, Value &root) {
- Json::Reader reader;
- bool ok = reader.parse(sin, root, true);
- //JSON_ASSERT( ok );
- if (!ok)
- throw std::runtime_error(reader.getFormatedErrorMessages());
- return sin;
-}
-
-} // namespace Json
+++ /dev/null
-#include <iostream>
-#include <json/value.h>
-#include <json/writer.h>
-#include <utility>
-#include <stdexcept>
-#include <cstring>
-#include <cassert>
-#ifdef JSON_USE_CPPTL
-# include <cpptl/conststring.h>
-#endif
-#include <cstddef> // size_t
-#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-# include "json_batchallocator.h"
-#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-#define JSON_ASSERT_UNREACHABLE assert( false )
-#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
-#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
-
-namespace Json {
-
-const Value Value::null;
-const Int Value::minInt = Int(~(UInt(-1) / 2));
-const Int Value::maxInt = Int(UInt(-1) / 2);
-const UInt Value::maxUInt = UInt(-1);
-
-// A "safe" implementation of strdup. Allow null pointer to be passed.
-// Also avoid warning on msvc80.
-//
-//inline char *safeStringDup( const char *czstring )
-//{
-// if ( czstring )
-// {
-// const size_t length = (unsigned int)( strlen(czstring) + 1 );
-// char *newString = static_cast<char *>( malloc( length ) );
-// memcpy( newString, czstring, length );
-// return newString;
-// }
-// return 0;
-//}
-//
-//inline char *safeStringDup( const std::string &str )
-//{
-// if ( !str.empty() )
-// {
-// const size_t length = str.length();
-// char *newString = static_cast<char *>( malloc( length + 1 ) );
-// memcpy( newString, str.c_str(), length );
-// newString[length] = 0;
-// return newString;
-// }
-// return 0;
-//}
-
-ValueAllocator::~ValueAllocator() {
-}
-
-class DefaultValueAllocator: public ValueAllocator {
-public:
- virtual ~DefaultValueAllocator() {
- }
-
- virtual char *makeMemberName(const char *memberName) {
- return duplicateStringValue(memberName);
- }
-
- virtual void releaseMemberName(char *memberName) {
- releaseStringValue(memberName);
- }
-
- virtual char *duplicateStringValue(const char *value, unsigned int length =
- unknown) {
- //@todo invesgate this old optimization
- //if ( !value || value[0] == 0 )
- // return 0;
-
- if (length == unknown)
- length = (unsigned int) strlen(value);
- char *newString = static_cast<char *>(malloc(length + 1));
- memcpy(newString, value, length);
- newString[length] = 0;
- return newString;
- }
-
- virtual void releaseStringValue(char *value) {
- if (value)
- free(value);
- }
-};
-
-static ValueAllocator *&valueAllocator() {
- static DefaultValueAllocator defaultAllocator;
- static ValueAllocator *valueAllocator = &defaultAllocator;
- return valueAllocator;
-}
-
-static struct DummyValueAllocatorInitializer {
- DummyValueAllocatorInitializer() {
- valueAllocator(); // ensure valueAllocator() statics are initialized before main().
- }
-} dummyValueAllocatorInitializer;
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// ValueInternals...
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-# include "json_internalarray.inl"
-# include "json_internalmap.inl"
-#endif // JSON_VALUE_USE_INTERNAL_MAP
-# include "json_valueiterator.inl"
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::CommentInfo
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-Value::CommentInfo::CommentInfo() :
- comment_(0) {
-}
-
-Value::CommentInfo::~CommentInfo() {
- if (comment_)
- valueAllocator()->releaseStringValue(comment_);
-}
-
-void Value::CommentInfo::setComment(const char *text) {
- if (comment_)
- valueAllocator()->releaseStringValue(comment_);
- JSON_ASSERT(text);
- JSON_ASSERT_MESSAGE(text[0] == '\0' || text[0] == '/',
- "Comments must start with /");
- // It seems that /**/ style comments are acceptable as well.
- comment_ = valueAllocator()->duplicateStringValue(text);
-}
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::CZString
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-# ifndef JSON_VALUE_USE_INTERNAL_MAP
-
-// Notes: index_ indicates if the string was allocated when
-// a string is stored.
-
-Value::CZString::CZString(int index) :
- cstr_(0), index_(index) {
-}
-
-Value::CZString::CZString(const char *cstr, DuplicationPolicy allocate) :
- cstr_(
- allocate == duplicate ?
- valueAllocator()->makeMemberName(cstr) : cstr), index_(
- allocate) {
-}
-
-Value::CZString::CZString(const CZString &other) :
- cstr_(
- other.index_ != noDuplication && other.cstr_ != 0 ?
- valueAllocator()->makeMemberName(other.cstr_) :
- other.cstr_), index_(
- other.cstr_ ?
- (other.index_ == noDuplication ?
- noDuplication : duplicate) :
- other.index_) {
-}
-
-Value::CZString::~CZString() {
- if (cstr_ && index_ == duplicate)
- valueAllocator()->releaseMemberName(const_cast<char *>(cstr_));
-}
-
-void Value::CZString::swap(CZString &other) {
- std::swap(cstr_, other.cstr_);
- std::swap(index_, other.index_);
-}
-
-Value::CZString &
-Value::CZString::operator =(const CZString &other) {
- CZString temp(other);
- swap(temp);
- return *this;
-}
-
-bool Value::CZString::operator<(const CZString &other) const {
- if (cstr_)
- return strcmp(cstr_, other.cstr_) < 0;
- return index_ < other.index_;
-}
-
-bool Value::CZString::operator==(const CZString &other) const {
- if (cstr_)
- return strcmp(cstr_, other.cstr_) == 0;
- return index_ == other.index_;
-}
-
-int Value::CZString::index() const {
- return index_;
-}
-
-const char *
-Value::CZString::c_str() const {
- return cstr_;
-}
-
-bool Value::CZString::isStaticString() const {
- return index_ == noDuplication;
-}
-
-#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::Value
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-/*! \internal Default constructor initialization must be equivalent to:
- * memset( this, 0, sizeof(Value) )
- * This optimization is used in ValueInternalMap fast allocator.
- */
-Value::Value(ValueType type) :
- type_(type), allocated_(0), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- switch (type) {
- case nullValue:
- break;
- case intValue:
- case uintValue:
- value_.int_ = 0;
- break;
- case realValue:
- value_.real_ = 0.0;
- break;
- case stringValue:
- value_.string_ = 0;
- break;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- case objectValue:
- value_.map_ = new ObjectValues();
- break;
-#else
- case arrayValue:
- value_.array_ = arrayAllocator()->newArray();
- break;
- case objectValue:
- value_.map_ = mapAllocator()->newMap();
- break;
-#endif
- case booleanValue:
- value_.bool_ = false;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
-}
-
-Value::Value(Int value) :
- type_(intValue), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.int_ = value;
-}
-
-Value::Value(UInt value) :
- type_(uintValue), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.uint_ = value;
-}
-
-Value::Value(double value) :
- type_(realValue), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.real_ = value;
-}
-
-Value::Value(const char *value) :
- type_(stringValue), allocated_(true), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.string_ = valueAllocator()->duplicateStringValue(value);
-}
-
-Value::Value(const char *beginValue, const char *endValue) :
- type_(stringValue), allocated_(true), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.string_ = valueAllocator()->duplicateStringValue(beginValue,
- UInt(endValue - beginValue));
-}
-
-Value::Value(const std::string &value) :
- type_(stringValue), allocated_(true), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.string_ = valueAllocator()->duplicateStringValue(value.c_str(),
- (unsigned int) value.length());
-
-}
-
-Value::Value(const StaticString &value) :
- type_(stringValue), allocated_(false), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.string_ = const_cast<char *>(value.c_str());
-}
-
-# ifdef JSON_USE_CPPTL
-Value::Value( const CppTL::ConstString &value )
-: type_( stringValue )
-, allocated_( true )
-, comments_( 0 )
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
-}
-# endif
-
-Value::Value(bool value) :
- type_(booleanValue), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- value_.bool_ = value;
-}
-
-Value::Value(const Value &other) :
- type_(other.type_), comments_(0)
-# ifdef JSON_VALUE_USE_INTERNAL_MAP
-, itemIsUsed_( 0 )
-#endif
-{
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- value_ = other.value_;
- break;
- case stringValue:
- if (other.value_.string_) {
- value_.string_ = valueAllocator()->duplicateStringValue(
- other.value_.string_);
- allocated_ = true;
- } else
- value_.string_ = 0;
- break;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- case objectValue:
- value_.map_ = new ObjectValues(*other.value_.map_);
- break;
-#else
- case arrayValue:
- value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
- break;
- case objectValue:
- value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
- break;
-#endif
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- if (other.comments_) {
- comments_ = new CommentInfo[numberOfCommentPlacement];
- for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
- const CommentInfo &otherComment = other.comments_[comment];
- if (otherComment.comment_)
- comments_[comment].setComment(otherComment.comment_);
- }
- }
-}
-
-Value::~Value() {
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- break;
- case stringValue:
- if (allocated_)
- valueAllocator()->releaseStringValue(value_.string_);
- break;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- case objectValue:
- delete value_.map_;
- break;
-#else
- case arrayValue:
- arrayAllocator()->destructArray( value_.array_ );
- break;
- case objectValue:
- mapAllocator()->destructMap( value_.map_ );
- break;
-#endif
- default:
- JSON_ASSERT_UNREACHABLE;
- }
-
- if (comments_)
- delete[] comments_;
-}
-
-Value &
-Value::operator=(const Value &other) {
- Value temp(other);
- swap(temp);
- return *this;
-}
-
-void Value::swap(Value &other) {
- ValueType temp = type_;
- type_ = other.type_;
- other.type_ = temp;
- std::swap(value_, other.value_);
- int temp2 = allocated_;
- allocated_ = other.allocated_;
- other.allocated_ = temp2;
-}
-
-ValueType Value::type() const {
- return type_;
-}
-
-int Value::compare(const Value &other) {
- /*
- int typeDelta = other.type_ - type_;
- switch ( type_ )
- {
- case nullValue:
-
- return other.type_ == type_;
- case intValue:
- if ( other.type_.isNumeric()
- case uintValue:
- case realValue:
- case booleanValue:
- break;
- case stringValue,
- break;
- case arrayValue:
- delete value_.array_;
- break;
- case objectValue:
- delete value_.map_;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- */
- return 0; // unreachable
-}
-
-bool Value::operator <(const Value &other) const {
- int typeDelta = type_ - other.type_;
- if (typeDelta)
- return typeDelta < 0 ? true : false;
- switch (type_) {
- case nullValue:
- return false;
- case intValue:
- return value_.int_ < other.value_.int_;
- case uintValue:
- return value_.uint_ < other.value_.uint_;
- case realValue:
- return value_.real_ < other.value_.real_;
- case booleanValue:
- return value_.bool_ < other.value_.bool_;
- case stringValue:
- return (value_.string_ == 0 && other.value_.string_)
- || (other.value_.string_ && value_.string_
- && strcmp(value_.string_, other.value_.string_) < 0);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- case objectValue: {
- int delta = int(value_.map_->size() - other.value_.map_->size());
- if (delta)
- return delta < 0;
- return (*value_.map_) < (*other.value_.map_);
- }
-#else
- case arrayValue:
- return value_.array_->compare( *(other.value_.array_) ) < 0;
- case objectValue:
- return value_.map_->compare( *(other.value_.map_) ) < 0;
-#endif
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return 0; // unreachable
-}
-
-bool Value::operator <=(const Value &other) const {
- return !(other > *this);
-}
-
-bool Value::operator >=(const Value &other) const {
- return !(*this < other);
-}
-
-bool Value::operator >(const Value &other) const {
- return other < *this;
-}
-
-bool Value::operator ==(const Value &other) const {
- //if ( type_ != other.type_ )
- // GCC 2.95.3 says:
- // attempt to take address of bit-field structure member `Json::Value::type_'
- // Beats me, but a temp solves the problem.
- int temp = other.type_;
- if (type_ != temp)
- return false;
- switch (type_) {
- case nullValue:
- return true;
- case intValue:
- return value_.int_ == other.value_.int_;
- case uintValue:
- return value_.uint_ == other.value_.uint_;
- case realValue:
- return value_.real_ == other.value_.real_;
- case booleanValue:
- return value_.bool_ == other.value_.bool_;
- case stringValue:
- return (value_.string_ == other.value_.string_)
- || (other.value_.string_ && value_.string_
- && strcmp(value_.string_, other.value_.string_) == 0);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- case objectValue:
- return value_.map_->size() == other.value_.map_->size()
- && (*value_.map_) == (*other.value_.map_);
-#else
- case arrayValue:
- return value_.array_->compare( *(other.value_.array_) ) == 0;
- case objectValue:
- return value_.map_->compare( *(other.value_.map_) ) == 0;
-#endif
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return 0; // unreachable
-}
-
-bool Value::operator !=(const Value &other) const {
- return !(*this == other);
-}
-
-const char *
-Value::asCString() const {
- JSON_ASSERT(type_ == stringValue);
- return value_.string_;
-}
-
-std::string Value::asString() const {
- switch (type_) {
- case nullValue:
- return "";
- case stringValue:
- return value_.string_ ? value_.string_ : "";
- case booleanValue:
- return value_.bool_ ? "true" : "false";
- case intValue:
- case uintValue:
- case realValue:
- case arrayValue:
- case objectValue:
- JSON_ASSERT_MESSAGE(false, "Type is not convertible to string")
- ;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return ""; // unreachable
-}
-
-# ifdef JSON_USE_CPPTL
-CppTL::ConstString
-Value::asConstString() const
-{
- return CppTL::ConstString( asString().c_str() );
-}
-# endif
-
-Value::Int Value::asInt() const {
- switch (type_) {
- case nullValue:
- return 0;
- case intValue:
- return value_.int_;
- case uintValue:
- JSON_ASSERT_MESSAGE(value_.uint_ < (unsigned )maxInt,
- "integer out of signed integer range")
- ;
- return value_.uint_;
- case realValue:
- JSON_ASSERT_MESSAGE(value_.real_ >= minInt && value_.real_ <= maxInt,
- "Real out of signed integer range")
- ;
- return Int(value_.real_);
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- case stringValue:
- case arrayValue:
- case objectValue:
- JSON_ASSERT_MESSAGE(false, "Type is not convertible to int")
- ;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return 0; // unreachable;
-}
-
-Value::UInt Value::asUInt() const {
- switch (type_) {
- case nullValue:
- return 0;
- case intValue:
- JSON_ASSERT_MESSAGE(value_.int_ >= 0,
- "Negative integer can not be converted to unsigned integer")
- ;
- return value_.int_;
- case uintValue:
- return value_.uint_;
- case realValue:
- JSON_ASSERT_MESSAGE(value_.real_ >= 0 && value_.real_ <= maxUInt,
- "Real out of unsigned integer range")
- ;
- return UInt(value_.real_);
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- case stringValue:
- case arrayValue:
- case objectValue:
- JSON_ASSERT_MESSAGE(false, "Type is not convertible to uint")
- ;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return 0; // unreachable;
-}
-
-double Value::asDouble() const {
- switch (type_) {
- case nullValue:
- return 0.0;
- case intValue:
- return value_.int_;
- case uintValue:
- return value_.uint_;
- case realValue:
- return value_.real_;
- case booleanValue:
- return value_.bool_ ? 1.0 : 0.0;
- case stringValue:
- case arrayValue:
- case objectValue:
- JSON_ASSERT_MESSAGE(false, "Type is not convertible to double")
- ;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return 0; // unreachable;
-}
-
-bool Value::asBool() const {
- switch (type_) {
- case nullValue:
- return false;
- case intValue:
- case uintValue:
- return value_.int_ != 0;
- case realValue:
- return value_.real_ != 0.0;
- case booleanValue:
- return value_.bool_;
- case stringValue:
- return value_.string_ && value_.string_[0] != 0;
- case arrayValue:
- case objectValue:
- return value_.map_->size() != 0;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return false; // unreachable;
-}
-
-bool Value::isConvertibleTo(ValueType other) const {
- switch (type_) {
- case nullValue:
- return true;
- case intValue:
- return (other == nullValue && value_.int_ == 0) || other == intValue
- || (other == uintValue && value_.int_ >= 0)
- || other == realValue || other == stringValue
- || other == booleanValue;
- case uintValue:
- return (other == nullValue && value_.uint_ == 0)
- || (other == intValue && value_.uint_ <= (unsigned) maxInt)
- || other == uintValue || other == realValue
- || other == stringValue || other == booleanValue;
- case realValue:
- return (other == nullValue && value_.real_ == 0.0)
- || (other == intValue && value_.real_ >= minInt
- && value_.real_ <= maxInt)
- || (other == uintValue && value_.real_ >= 0
- && value_.real_ <= maxUInt) || other == realValue
- || other == stringValue || other == booleanValue;
- case booleanValue:
- return (other == nullValue && value_.bool_ == false)
- || other == intValue || other == uintValue || other == realValue
- || other == stringValue || other == booleanValue;
- case stringValue:
- return other == stringValue
- || (other == nullValue
- && (!value_.string_ || value_.string_[0] == 0));
- case arrayValue:
- return other == arrayValue
- || (other == nullValue && value_.map_->size() == 0);
- case objectValue:
- return other == objectValue
- || (other == nullValue && value_.map_->size() == 0);
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return false; // unreachable;
-}
-
-/// Number of values in array or object
-Value::UInt Value::size() const {
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- case stringValue:
- return 0;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue: // size of the array is highest index + 1
- if (!value_.map_->empty()) {
- ObjectValues::const_iterator itLast = value_.map_->end();
- --itLast;
- return (*itLast).first.index() + 1;
- }
- return 0;
- case objectValue:
- return Int(value_.map_->size());
-#else
- case arrayValue:
- return Int( value_.array_->size() );
- case objectValue:
- return Int( value_.map_->size() );
-#endif
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return 0; // unreachable;
-}
-
-bool Value::empty() const {
- if (isNull() || isArray() || isObject())
- return size() == 0u;
- else
- return false;
-}
-
-bool Value::operator!() const {
- return isNull();
-}
-
-void Value::clear() {
- JSON_ASSERT(
- type_ == nullValue || type_ == arrayValue || type_ == objectValue);
-
- switch (type_) {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- case objectValue:
- value_.map_->clear();
- break;
-#else
- case arrayValue:
- value_.array_->clear();
- break;
- case objectValue:
- value_.map_->clear();
- break;
-#endif
- default:
- break;
- }
-}
-
-void Value::resize(UInt newSize) {
- JSON_ASSERT(type_ == nullValue || type_ == arrayValue);
- if (type_ == nullValue)
- *this = Value(arrayValue);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- UInt oldSize = size();
- if (newSize == 0)
- clear();
- else if (newSize > oldSize)
- (*this)[newSize - 1];
- else {
- for (UInt index = newSize; index < oldSize; ++index)
- value_.map_->erase(index);
- assert(size() == newSize);
- }
-#else
- value_.array_->resize( newSize );
-#endif
-}
-
-Value &
-Value::operator[](UInt index) {
- JSON_ASSERT(type_ == nullValue || type_ == arrayValue);
- if (type_ == nullValue)
- *this = Value(arrayValue);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- CZString key(index);
- ObjectValues::iterator it = value_.map_->lower_bound(key);
- if (it != value_.map_->end() && (*it).first == key)
- return (*it).second;
-
- ObjectValues::value_type defaultValue(key, null);
- it = value_.map_->insert(it, defaultValue);
- return (*it).second;
-#else
- return value_.array_->resolveReference( index );
-#endif
-}
-
-const Value &
-Value::operator[](UInt index) const {
- JSON_ASSERT(type_ == nullValue || type_ == arrayValue);
- if (type_ == nullValue)
- return null;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- CZString key(index);
- ObjectValues::const_iterator it = value_.map_->find(key);
- if (it == value_.map_->end())
- return null;
- return (*it).second;
-#else
- Value *value = value_.array_->find( index );
- return value ? *value : null;
-#endif
-}
-
-Value &
-Value::operator[](const char *key) {
- return resolveReference(key, false);
-}
-
-Value &
-Value::resolveReference(const char *key, bool isStatic) {
- JSON_ASSERT(type_ == nullValue || type_ == objectValue);
- if (type_ == nullValue)
- *this = Value(objectValue);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- CZString actualKey(key,
- isStatic ? CZString::noDuplication : CZString::duplicateOnCopy);
- ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
- if (it != value_.map_->end() && (*it).first == actualKey)
- return (*it).second;
-
- ObjectValues::value_type defaultValue(actualKey, null);
- it = value_.map_->insert(it, defaultValue);
- Value &value = (*it).second;
- return value;
-#else
- return value_.map_->resolveReference( key, isStatic );
-#endif
-}
-
-Value Value::get(UInt index, const Value &defaultValue) const {
- const Value *value = &((*this)[index]);
- return value == &null ? defaultValue : *value;
-}
-
-bool Value::isValidIndex(UInt index) const {
- return index < size();
-}
-
-const Value &
-Value::operator[](const char *key) const {
- JSON_ASSERT(type_ == nullValue || type_ == objectValue);
- if (type_ == nullValue)
- return null;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- CZString actualKey(key, CZString::noDuplication);
- ObjectValues::const_iterator it = value_.map_->find(actualKey);
- if (it == value_.map_->end())
- return null;
- return (*it).second;
-#else
- const Value *value = value_.map_->find( key );
- return value ? *value : null;
-#endif
-}
-
-Value &
-Value::operator[](const std::string &key) {
- return (*this)[key.c_str()];
-}
-
-const Value &
-Value::operator[](const std::string &key) const {
- return (*this)[key.c_str()];
-}
-
-Value &
-Value::operator[](const StaticString &key) {
- return resolveReference(key, true);
-}
-
-# ifdef JSON_USE_CPPTL
-Value &
-Value::operator[]( const CppTL::ConstString &key )
-{
- return (*this)[ key.c_str() ];
-}
-
-const Value &
-Value::operator[]( const CppTL::ConstString &key ) const
-{
- return (*this)[ key.c_str() ];
-}
-# endif
-
-Value &
-Value::append(const Value &value) {
- return (*this)[size()] = value;
-}
-
-Value Value::get(const char *key, const Value &defaultValue) const {
- const Value *value = &((*this)[key]);
- return value == &null ? defaultValue : *value;
-}
-
-Value Value::get(const std::string &key, const Value &defaultValue) const {
- return get(key.c_str(), defaultValue);
-}
-
-Value Value::removeMember(const char* key) {
- JSON_ASSERT(type_ == nullValue || type_ == objectValue);
- if (type_ == nullValue)
- return null;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- CZString actualKey(key, CZString::noDuplication);
- ObjectValues::iterator it = value_.map_->find(actualKey);
- if (it == value_.map_->end())
- return null;
- Value old(it->second);
- value_.map_->erase(it);
- return old;
-#else
- Value *value = value_.map_->find( key );
- if (value) {
- Value old(*value);
- value_.map_.remove( key );
- return old;
- } else {
- return null;
- }
-#endif
-}
-
-Value Value::removeMember(const std::string &key) {
- return removeMember(key.c_str());
-}
-
-# ifdef JSON_USE_CPPTL
-Value
-Value::get( const CppTL::ConstString &key,
- const Value &defaultValue ) const
-{
- return get( key.c_str(), defaultValue );
-}
-# endif
-
-bool Value::isMember(const char *key) const {
- const Value *value = &((*this)[key]);
- return value != &null;
-}
-
-bool Value::isMember(const std::string &key) const {
- return isMember(key.c_str());
-}
-
-# ifdef JSON_USE_CPPTL
-bool
-Value::isMember( const CppTL::ConstString &key ) const
-{
- return isMember( key.c_str() );
-}
-#endif
-
-Value::Members Value::getMemberNames() const {
- JSON_ASSERT(type_ == nullValue || type_ == objectValue);
- if (type_ == nullValue)
- return Value::Members();
- Members members;
- members.reserve(value_.map_->size());
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- ObjectValues::const_iterator it = value_.map_->begin();
- ObjectValues::const_iterator itEnd = value_.map_->end();
- for (; it != itEnd; ++it)
- members.push_back(std::string((*it).first.c_str()));
-#else
- ValueInternalMap::IteratorState it;
- ValueInternalMap::IteratorState itEnd;
- value_.map_->makeBeginIterator( it );
- value_.map_->makeEndIterator( itEnd );
- for (; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
- members.push_back( std::string( ValueInternalMap::key( it ) ) );
-#endif
- return members;
-}
-//
-//# ifdef JSON_USE_CPPTL
-//EnumMemberNames
-//Value::enumMemberNames() const
-//{
-// if ( type_ == objectValue )
-// {
-// return CppTL::Enum::any( CppTL::Enum::transform(
-// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
-// MemberNamesTransform() ) );
-// }
-// return EnumMemberNames();
-//}
-//
-//
-//EnumValues
-//Value::enumValues() const
-//{
-// if ( type_ == objectValue || type_ == arrayValue )
-// return CppTL::Enum::anyValues( *(value_.map_),
-// CppTL::Type<const Value &>() );
-// return EnumValues();
-//}
-//
-//# endif
-
-bool Value::isNull() const {
- return type_ == nullValue;
-}
-
-bool Value::isBool() const {
- return type_ == booleanValue;
-}
-
-bool Value::isInt() const {
- return type_ == intValue;
-}
-
-bool Value::isUInt() const {
- return type_ == uintValue;
-}
-
-bool Value::isIntegral() const {
- return type_ == intValue || type_ == uintValue || type_ == booleanValue;
-}
-
-bool Value::isDouble() const {
- return type_ == realValue;
-}
-
-bool Value::isNumeric() const {
- return isIntegral() || isDouble();
-}
-
-bool Value::isString() const {
- return type_ == stringValue;
-}
-
-bool Value::isArray() const {
- return type_ == nullValue || type_ == arrayValue;
-}
-
-bool Value::isObject() const {
- return type_ == nullValue || type_ == objectValue;
-}
-
-void Value::setComment(const char *comment, CommentPlacement placement) {
- if (!comments_)
- comments_ = new CommentInfo[numberOfCommentPlacement];
- comments_[placement].setComment(comment);
-}
-
-void Value::setComment(const std::string &comment, CommentPlacement placement) {
- setComment(comment.c_str(), placement);
-}
-
-bool Value::hasComment(CommentPlacement placement) const {
- return comments_ != 0 && comments_[placement].comment_ != 0;
-}
-
-std::string Value::getComment(CommentPlacement placement) const {
- if (hasComment(placement))
- return comments_[placement].comment_;
- return "";
-}
-
-std::string Value::toStyledString() const {
- StyledWriter writer;
- return writer.write(*this);
-}
-
-Value::const_iterator Value::begin() const {
- switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- if ( value_.array_ )
- {
- ValueInternalArray::IteratorState it;
- value_.array_->makeBeginIterator( it );
- return const_iterator( it );
- }
- break;
- case objectValue:
- if ( value_.map_ )
- {
- ValueInternalMap::IteratorState it;
- value_.map_->makeBeginIterator( it );
- return const_iterator( it );
- }
- break;
-#else
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->begin());
- break;
-#endif
- default:
- break;
- }
- return const_iterator();
-}
-
-Value::const_iterator Value::end() const {
- switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- if ( value_.array_ )
- {
- ValueInternalArray::IteratorState it;
- value_.array_->makeEndIterator( it );
- return const_iterator( it );
- }
- break;
- case objectValue:
- if ( value_.map_ )
- {
- ValueInternalMap::IteratorState it;
- value_.map_->makeEndIterator( it );
- return const_iterator( it );
- }
- break;
-#else
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->end());
- break;
-#endif
- default:
- break;
- }
- return const_iterator();
-}
-
-Value::iterator Value::begin() {
- switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- if ( value_.array_ )
- {
- ValueInternalArray::IteratorState it;
- value_.array_->makeBeginIterator( it );
- return iterator( it );
- }
- break;
- case objectValue:
- if ( value_.map_ )
- {
- ValueInternalMap::IteratorState it;
- value_.map_->makeBeginIterator( it );
- return iterator( it );
- }
- break;
-#else
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->begin());
- break;
-#endif
- default:
- break;
- }
- return iterator();
-}
-
-Value::iterator Value::end() {
- switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
- case arrayValue:
- if ( value_.array_ )
- {
- ValueInternalArray::IteratorState it;
- value_.array_->makeEndIterator( it );
- return iterator( it );
- }
- break;
- case objectValue:
- if ( value_.map_ )
- {
- ValueInternalMap::IteratorState it;
- value_.map_->makeEndIterator( it );
- return iterator( it );
- }
- break;
-#else
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->end());
- break;
-#endif
- default:
- break;
- }
- return iterator();
-}
-
-// class PathArgument
-// //////////////////////////////////////////////////////////////////
-
-PathArgument::PathArgument() :
- kind_(kindNone) {
-}
-
-PathArgument::PathArgument(Value::UInt index) :
- index_(index), kind_(kindIndex) {
-}
-
-PathArgument::PathArgument(const char *key) :
- key_(key), kind_(kindKey) {
-}
-
-PathArgument::PathArgument(const std::string &key) :
- key_(key.c_str()), kind_(kindKey) {
-}
-
-// class Path
-// //////////////////////////////////////////////////////////////////
-
-Path::Path(const std::string &path, const PathArgument &a1,
- const PathArgument &a2, const PathArgument &a3, const PathArgument &a4,
- const PathArgument &a5) {
- InArgs in;
- in.push_back(&a1);
- in.push_back(&a2);
- in.push_back(&a3);
- in.push_back(&a4);
- in.push_back(&a5);
- makePath(path, in);
-}
-
-void Path::makePath(const std::string &path, const InArgs &in) {
- const char *current = path.c_str();
- const char *end = current + path.length();
- InArgs::const_iterator itInArg = in.begin();
- while (current != end) {
- if (*current == '[') {
- ++current;
- if (*current == '%')
- addPathInArg(path, in, itInArg, PathArgument::kindIndex);
- else {
- Value::UInt index = 0;
- for (; current != end && *current >= '0' && *current <= '9';
- ++current)
- index = index * 10 + Value::UInt(*current - '0');
- args_.push_back(index);
- }
- if (current == end || *current++ != ']')
- invalidPath(path, int(current - path.c_str()));
- } else if (*current == '%') {
- addPathInArg(path, in, itInArg, PathArgument::kindKey);
- ++current;
- } else if (*current == '.') {
- ++current;
- } else {
- const char *beginName = current;
- while (current != end && !strchr("[.", *current))
- ++current;
- args_.push_back(std::string(beginName, current));
- }
- }
-}
-
-void Path::addPathInArg(const std::string &path, const InArgs &in,
- InArgs::const_iterator &itInArg, PathArgument::Kind kind) {
- if (itInArg == in.end()) {
- // Error: missing argument %d
- } else if ((*itInArg)->kind_ != kind) {
- // Error: bad argument type
- } else {
- args_.push_back(**itInArg);
- }
-}
-
-void Path::invalidPath(const std::string &path, int location) {
- // Error: invalid path.
-}
-
-const Value &
-Path::resolve(const Value &root) const {
- const Value *node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
- const PathArgument &arg = *it;
- if (arg.kind_ == PathArgument::kindIndex) {
- if (!node->isArray() || node->isValidIndex(arg.index_)) {
- // Error: unable to resolve path (array value expected at position...
- }
- node = &((*node)[arg.index_]);
- } else if (arg.kind_ == PathArgument::kindKey) {
- if (!node->isObject()) {
- // Error: unable to resolve path (object value expected at position...)
- }
- node = &((*node)[arg.key_]);
- if (node == &Value::null) {
- // Error: unable to resolve path (object has no member named '' at position...)
- }
- }
- }
- return *node;
-}
-
-Value Path::resolve(const Value &root, const Value &defaultValue) const {
- const Value *node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
- const PathArgument &arg = *it;
- if (arg.kind_ == PathArgument::kindIndex) {
- if (!node->isArray() || node->isValidIndex(arg.index_))
- return defaultValue;
- node = &((*node)[arg.index_]);
- } else if (arg.kind_ == PathArgument::kindKey) {
- if (!node->isObject())
- return defaultValue;
- node = &((*node)[arg.key_]);
- if (node == &Value::null)
- return defaultValue;
- }
- }
- return *node;
-}
-
-Value &
-Path::make(Value &root) const {
- Value *node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
- const PathArgument &arg = *it;
- if (arg.kind_ == PathArgument::kindIndex) {
- if (!node->isArray()) {
- // Error: node is not an array at position ...
- }
- node = &((*node)[arg.index_]);
- } else if (arg.kind_ == PathArgument::kindKey) {
- if (!node->isObject()) {
- // Error: node is not an object at position...
- }
- node = &((*node)[arg.key_]);
- }
- }
- return *node;
-}
-
-} // namespace Json
+++ /dev/null
-// included by json_value.cpp
-// everything is within Json namespace
-
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueIteratorBase
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueIteratorBase::ValueIteratorBase()
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- : current_()
- , isNull_( true )
-{
-}
-#else
- : isArray_( true )
- , isNull_( true )
-{
- iterator_.array_ = ValueInternalArray::IteratorState();
-}
-#endif
-
-
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t )
- : current_( current )
- , isNull_( false )
-{
-}
-#else
-ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
- : isArray_( true )
-{
- iterator_.array_ = state;
-}
-
-
-ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
- : isArray_( false )
-{
- iterator_.map_ = state;
-}
-#endif
-
-Value &
-ValueIteratorBase::deref() const
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- return current_->second;
-#else
- if ( isArray_ )
- return ValueInternalArray::dereference( iterator_.array_ );
- return ValueInternalMap::value( iterator_.map_ );
-#endif
-}
-
-
-void
-ValueIteratorBase::increment()
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- ++current_;
-#else
- if ( isArray_ )
- ValueInternalArray::increment( iterator_.array_ );
- ValueInternalMap::increment( iterator_.map_ );
-#endif
-}
-
-
-void
-ValueIteratorBase::decrement()
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- --current_;
-#else
- if ( isArray_ )
- ValueInternalArray::decrement( iterator_.array_ );
- ValueInternalMap::decrement( iterator_.map_ );
-#endif
-}
-
-
-ValueIteratorBase::difference_type
-ValueIteratorBase::computeDistance( const SelfType &other ) const
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-# ifdef JSON_USE_CPPTL_SMALLMAP
- return current_ - other.current_;
-# else
- // Iterator for null value are initialized using the default
- // constructor, which initialize current_ to the default
- // std::map::iterator. As begin() and end() are two instance
- // of the default std::map::iterator, they can not be compared.
- // To allow this, we handle this comparison specifically.
- if ( isNull_ && other.isNull_ )
- {
- return 0;
- }
-
-
- // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
- // which is the one used by default).
- // Using a portable hand-made version for non random iterator instead:
- // return difference_type( std::distance( current_, other.current_ ) );
- difference_type myDistance = 0;
- for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
- {
- ++myDistance;
- }
- return myDistance;
-# endif
-#else
- if ( isArray_ )
- return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
- return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
-#endif
-}
-
-
-bool
-ValueIteratorBase::isEqual( const SelfType &other ) const
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- if ( isNull_ )
- {
- return other.isNull_;
- }
- return current_ == other.current_;
-#else
- if ( isArray_ )
- return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
- return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
-#endif
-}
-
-
-void
-ValueIteratorBase::copy( const SelfType &other )
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- current_ = other.current_;
-#else
- if ( isArray_ )
- iterator_.array_ = other.iterator_.array_;
- iterator_.map_ = other.iterator_.map_;
-#endif
-}
-
-
-Value
-ValueIteratorBase::key() const
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- const Value::CZString czstring = (*current_).first;
- if ( czstring.c_str() )
- {
- if ( czstring.isStaticString() )
- return Value( StaticString( czstring.c_str() ) );
- return Value( czstring.c_str() );
- }
- return Value( czstring.index() );
-#else
- if ( isArray_ )
- return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
- bool isStatic;
- const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
- if ( isStatic )
- return Value( StaticString( memberName ) );
- return Value( memberName );
-#endif
-}
-
-
-UInt
-ValueIteratorBase::index() const
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- const Value::CZString czstring = (*current_).first;
- if ( !czstring.c_str() )
- return czstring.index();
- return Value::UInt( -1 );
-#else
- if ( isArray_ )
- return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
- return Value::UInt( -1 );
-#endif
-}
-
-
-const char *
-ValueIteratorBase::memberName() const
-{
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
- const char *name = (*current_).first.c_str();
- return name ? name : "";
-#else
- if ( !isArray_ )
- return ValueInternalMap::key( iterator_.map_ );
- return "";
-#endif
-}
-
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueConstIterator
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueConstIterator::ValueConstIterator()
-{
-}
-
-
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t )
- : ValueIteratorBase( current )
-{
-}
-#else
-ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
- : ValueIteratorBase( state )
-{
-}
-
-ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
- : ValueIteratorBase( state )
-{
-}
-#endif
-
-ValueConstIterator &
-ValueConstIterator::operator =( const ValueIteratorBase &other )
-{
- copy( other );
- return *this;
-}
-
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueIterator
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueIterator::ValueIterator()
-{
-}
-
-
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t )
- : ValueIteratorBase( current )
-{
-}
-#else
-ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
- : ValueIteratorBase( state )
-{
-}
-
-ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
- : ValueIteratorBase( state )
-{
-}
-#endif
-
-ValueIterator::ValueIterator( const ValueConstIterator &other )
- : ValueIteratorBase( other )
-{
-}
-
-ValueIterator::ValueIterator( const ValueIterator &other )
- : ValueIteratorBase( other )
-{
-}
-
-ValueIterator &
-ValueIterator::operator =( const SelfType &other )
-{
- copy( other );
- return *this;
-}
+++ /dev/null
-#include <json/writer.h>
-#include <utility>
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-
-#if _MSC_VER >= 1400 // VC++ 8.0
-#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
-#endif
-
-namespace Json {
-
-static bool isControlCharacter(char ch) {
- return ch > 0 && ch <= 0x1F;
-}
-
-static bool containsControlCharacter(const char* str) {
- while (*str) {
- if (isControlCharacter(*(str++)))
- return true;
- }
- return false;
-}
-static void uintToString(unsigned int value, char *¤t) {
- *--current = 0;
- do {
- *--current = (value % 10) + '0';
- value /= 10;
- } while (value != 0);
-}
-
-std::string valueToString(Int value) {
- char buffer[32];
- char *current = buffer + sizeof(buffer);
- bool isNegative = value < 0;
- if (isNegative)
- value = -value;
- uintToString(UInt(value), current);
- if (isNegative)
- *--current = '-';
- assert(current >= buffer);
- return current;
-}
-
-std::string valueToString(UInt value) {
- char buffer[32];
- char *current = buffer + sizeof(buffer);
- uintToString(value, current);
- assert(current >= buffer);
- return current;
-}
-
-std::string valueToString(double value) {
- char buffer[32];
-#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
- sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
-#else
- sprintf(buffer, "%#.16g", value);
-#endif
- char* ch = buffer + strlen(buffer) - 1;
- if (*ch != '0')
- return buffer; // nothing to truncate, so save time
- while (ch > buffer && *ch == '0') {
- --ch;
- }
- char* last_nonzero = ch;
- while (ch >= buffer) {
- switch (*ch) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- --ch;
- continue;
- case '.':
- // Truncate zeroes to save bytes in output, but keep one.
- *(last_nonzero + 2) = '\0';
- return buffer;
- default:
- return buffer;
- }
- }
- return buffer;
-}
-
-std::string valueToString(bool value) {
- return value ? "true" : "false";
-}
-
-std::string valueToQuotedString(const char *value) {
- // Not sure how to handle unicode...
- if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL
- && !containsControlCharacter(value))
- return std::string("\"") + value + "\"";
- // We have to walk value and escape any special characters.
- // Appending to std::string is not efficient, but this should be rare.
- // (Note: forward slashes are *not* rare, but I am not escaping them.)
- unsigned maxsize = strlen(value) * 2 + 3; // allescaped+quotes+NULL
- std::string result;
- result.reserve(maxsize); // to avoid lots of mallocs
- result += "\"";
- for (const char* c = value; *c != 0; ++c) {
- switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- //case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.
- // blep notes: actually escaping \/ may be useful in javascript to avoid </
- // sequence.
- // Should add a flag to allow this compatibility mode and prevent this
- // sequence from occurring.
- default:
- if (isControlCharacter(*c)) {
- std::ostringstream oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
- }
- }
- result += "\"";
- return result;
-}
-
-// Class Writer
-// //////////////////////////////////////////////////////////////////
-Writer::~Writer() {
-}
-
-// Class FastWriter
-// //////////////////////////////////////////////////////////////////
-
-FastWriter::FastWriter() :
- yamlCompatiblityEnabled_(false) {
-}
-
-void FastWriter::enableYAMLCompatibility() {
- yamlCompatiblityEnabled_ = true;
-}
-
-std::string FastWriter::write(const Value &root) {
- document_ = "";
- writeValue(root);
- document_ += "\n";
- return document_;
-}
-
-void FastWriter::writeValue(const Value &value) {
- switch (value.type()) {
- case nullValue:
- document_ += "null";
- break;
- case intValue:
- document_ += valueToString(value.asInt());
- break;
- case uintValue:
- document_ += valueToString(value.asUInt());
- break;
- case realValue:
- document_ += valueToString(value.asDouble());
- break;
- case stringValue:
- document_ += valueToQuotedString(value.asCString());
- break;
- case booleanValue:
- document_ += valueToString(value.asBool());
- break;
- case arrayValue: {
- document_ += "[";
- int size = value.size();
- for (int index = 0; index < size; ++index) {
- if (index > 0)
- document_ += ",";
- writeValue(value[index]);
- }
- document_ += "]";
- }
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- document_ += "{";
- for (Value::Members::iterator it = members.begin(); it != members.end();
- ++it) {
- const std::string &name = *it;
- if (it != members.begin())
- document_ += ",";
- document_ += valueToQuotedString(name.c_str());
- document_ += yamlCompatiblityEnabled_ ? ": " : ":";
- writeValue(value[name]);
- }
- document_ += "}";
- }
- break;
- }
-}
-
-// Class StyledWriter
-// //////////////////////////////////////////////////////////////////
-
-StyledWriter::StyledWriter() :
- rightMargin_(74), indentSize_(3) {
-}
-
-std::string StyledWriter::write(const Value &root) {
- document_ = "";
- addChildValues_ = false;
- indentString_ = "";
- writeCommentBeforeValue(root);
- writeValue(root);
- writeCommentAfterValueOnSameLine(root);
- document_ += "\n";
- return document_;
-}
-
-void StyledWriter::writeValue(const Value &value) {
- switch (value.type()) {
- case nullValue:
- pushValue("null");
- break;
- case intValue:
- pushValue(valueToString(value.asInt()));
- break;
- case uintValue:
- pushValue(valueToString(value.asUInt()));
- break;
- case realValue:
- pushValue(valueToString(value.asDouble()));
- break;
- case stringValue:
- pushValue(valueToQuotedString(value.asCString()));
- break;
- case booleanValue:
- pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- pushValue("{}");
- else {
- writeWithIndent("{");
- indent();
- Value::Members::iterator it = members.begin();
- while (true) {
- const std::string &name = *it;
- const Value &childValue = value[name];
- writeCommentBeforeValue(childValue);
- writeWithIndent(valueToQuotedString(name.c_str()));
- document_ += " : ";
- writeValue(childValue);
- if (++it == members.end()) {
- writeCommentAfterValueOnSameLine(childValue);
- break;
- }
- document_ += ",";
- writeCommentAfterValueOnSameLine(childValue);
- }
- unindent();
- writeWithIndent("}");
- }
- }
- break;
- }
-}
-
-void StyledWriter::writeArrayValue(const Value &value) {
- unsigned size = value.size();
- if (size == 0)
- pushValue("[]");
- else {
- bool isArrayMultiLine = isMultineArray(value);
- if (isArrayMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
- unsigned index = 0;
- while (true) {
- const Value &childValue = value[index];
- writeCommentBeforeValue(childValue);
- if (hasChildValue)
- writeWithIndent(childValues_[index]);
- else {
- writeIndent();
- writeValue(childValue);
- }
- if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
- break;
- }
- document_ += ",";
- writeCommentAfterValueOnSameLine(childValue);
- }
- unindent();
- writeWithIndent("]");
- } else // output on a single line
- {
- assert(childValues_.size() == size);
- document_ += "[ ";
- for (unsigned index = 0; index < size; ++index) {
- if (index > 0)
- document_ += ", ";
- document_ += childValues_[index];
- }
- document_ += " ]";
- }
- }
-}
-
-bool StyledWriter::isMultineArray(const Value &value) {
- int size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
- for (int index = 0; index < size && !isMultiLine; ++index) {
- const Value &childValue = value[index];
- isMultiLine = isMultiLine
- || ((childValue.isArray() || childValue.isObject())
- && childValue.size() > 0);
- }
- if (!isMultiLine) // check if line length > max line length
- {
- childValues_.reserve(size);
- addChildValues_ = true;
- int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
- for (int index = 0; index < size && !isMultiLine; ++index) {
- writeValue(value[index]);
- lineLength += int(childValues_[index].length());
- isMultiLine = isMultiLine && hasCommentForValue(value[index]);
- }
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
- }
- return isMultiLine;
-}
-
-void StyledWriter::pushValue(const std::string &value) {
- if (addChildValues_)
- childValues_.push_back(value);
- else
- document_ += value;
-}
-
-void StyledWriter::writeIndent() {
- if (!document_.empty()) {
- char last = document_[document_.length() - 1];
- if (last == ' ') // already indented
- return;
- if (last != '\n') // Comments may add new-line
- document_ += '\n';
- }
- document_ += indentString_;
-}
-
-void StyledWriter::writeWithIndent(const std::string &value) {
- writeIndent();
- document_ += value;
-}
-
-void StyledWriter::indent() {
- indentString_ += std::string(indentSize_, ' ');
-}
-
-void StyledWriter::unindent() {
- assert(int(indentString_.size()) >= indentSize_);
- indentString_.resize(indentString_.size() - indentSize_);
-}
-
-void StyledWriter::writeCommentBeforeValue(const Value &root) {
- if (!root.hasComment(commentBefore))
- return;
- document_ += normalizeEOL(root.getComment(commentBefore));
- document_ += "\n";
-}
-
-void StyledWriter::writeCommentAfterValueOnSameLine(const Value &root) {
- if (root.hasComment(commentAfterOnSameLine))
- document_ += " "
- + normalizeEOL(root.getComment(commentAfterOnSameLine));
-
- if (root.hasComment(commentAfter)) {
- document_ += "\n";
- document_ += normalizeEOL(root.getComment(commentAfter));
- document_ += "\n";
- }
-}
-
-bool StyledWriter::hasCommentForValue(const Value &value) {
- return value.hasComment(commentBefore)
- || value.hasComment(commentAfterOnSameLine)
- || value.hasComment(commentAfter);
-}
-
-std::string StyledWriter::normalizeEOL(const std::string &text) {
- std::string normalized;
- normalized.reserve(text.length());
- const char *begin = text.c_str();
- const char *end = begin + text.length();
- const char *current = begin;
- while (current != end) {
- char c = *current++;
- if (c == '\r') // mac or dos EOL
- {
- if (*current == '\n') // convert dos EOL
- ++current;
- normalized += '\n';
- } else
- // handle unix EOL & other char
- normalized += c;
- }
- return normalized;
-}
-
-// Class StyledStreamWriter
-// //////////////////////////////////////////////////////////////////
-
-StyledStreamWriter::StyledStreamWriter(std::string indentation) :
- document_(NULL), rightMargin_(74), indentation_(indentation) {
-}
-
-void StyledStreamWriter::write(std::ostream &out, const Value &root) {
- document_ = &out;
- addChildValues_ = false;
- indentString_ = "";
- writeCommentBeforeValue(root);
- writeValue(root);
- writeCommentAfterValueOnSameLine(root);
- *document_ << "\n";
- document_ = NULL; // Forget the stream, for safety.
-}
-
-void StyledStreamWriter::writeValue(const Value &value) {
- switch (value.type()) {
- case nullValue:
- pushValue("null");
- break;
- case intValue:
- pushValue(valueToString(value.asInt()));
- break;
- case uintValue:
- pushValue(valueToString(value.asUInt()));
- break;
- case realValue:
- pushValue(valueToString(value.asDouble()));
- break;
- case stringValue:
- pushValue(valueToQuotedString(value.asCString()));
- break;
- case booleanValue:
- pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- pushValue("{}");
- else {
- writeWithIndent("{");
- indent();
- Value::Members::iterator it = members.begin();
- while (true) {
- const std::string &name = *it;
- const Value &childValue = value[name];
- writeCommentBeforeValue(childValue);
- writeWithIndent(valueToQuotedString(name.c_str()));
- *document_ << " : ";
- writeValue(childValue);
- if (++it == members.end()) {
- writeCommentAfterValueOnSameLine(childValue);
- break;
- }
- *document_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
- }
- unindent();
- writeWithIndent("}");
- }
- }
- break;
- }
-}
-
-void StyledStreamWriter::writeArrayValue(const Value &value) {
- unsigned size = value.size();
- if (size == 0)
- pushValue("[]");
- else {
- bool isArrayMultiLine = isMultineArray(value);
- if (isArrayMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
- unsigned index = 0;
- while (true) {
- const Value &childValue = value[index];
- writeCommentBeforeValue(childValue);
- if (hasChildValue)
- writeWithIndent(childValues_[index]);
- else {
- writeIndent();
- writeValue(childValue);
- }
- if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
- break;
- }
- *document_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
- }
- unindent();
- writeWithIndent("]");
- } else // output on a single line
- {
- assert(childValues_.size() == size);
- *document_ << "[ ";
- for (unsigned index = 0; index < size; ++index) {
- if (index > 0)
- *document_ << ", ";
- *document_ << childValues_[index];
- }
- *document_ << " ]";
- }
- }
-}
-
-bool StyledStreamWriter::isMultineArray(const Value &value) {
- int size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
- for (int index = 0; index < size && !isMultiLine; ++index) {
- const Value &childValue = value[index];
- isMultiLine = isMultiLine
- || ((childValue.isArray() || childValue.isObject())
- && childValue.size() > 0);
- }
- if (!isMultiLine) // check if line length > max line length
- {
- childValues_.reserve(size);
- addChildValues_ = true;
- int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
- for (int index = 0; index < size && !isMultiLine; ++index) {
- writeValue(value[index]);
- lineLength += int(childValues_[index].length());
- isMultiLine = isMultiLine && hasCommentForValue(value[index]);
- }
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
- }
- return isMultiLine;
-}
-
-void StyledStreamWriter::pushValue(const std::string &value) {
- if (addChildValues_)
- childValues_.push_back(value);
- else
- *document_ << value;
-}
-
-void StyledStreamWriter::writeIndent() {
- /*
- Some comments in this method would have been nice. ;-)
-
- if ( !document_.empty() )
- {
- char last = document_[document_.length()-1];
- if ( last == ' ' ) // already indented
- return;
- if ( last != '\n' ) // Comments may add new-line
- *document_ << '\n';
- }
- */
- *document_ << '\n' << indentString_;
-}
-
-void StyledStreamWriter::writeWithIndent(const std::string &value) {
- writeIndent();
- *document_ << value;
-}
-
-void StyledStreamWriter::indent() {
- indentString_ += indentation_;
-}
-
-void StyledStreamWriter::unindent() {
- assert(indentString_.size() >= indentation_.size());
- indentString_.resize(indentString_.size() - indentation_.size());
-}
-
-void StyledStreamWriter::writeCommentBeforeValue(const Value &root) {
- if (!root.hasComment(commentBefore))
- return;
- *document_ << normalizeEOL(root.getComment(commentBefore));
- *document_ << "\n";
-}
-
-void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value &root) {
- if (root.hasComment(commentAfterOnSameLine))
- *document_
- << " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
-
- if (root.hasComment(commentAfter)) {
- *document_ << "\n";
- *document_ << normalizeEOL(root.getComment(commentAfter));
- *document_ << "\n";
- }
-}
-
-bool StyledStreamWriter::hasCommentForValue(const Value &value) {
- return value.hasComment(commentBefore)
- || value.hasComment(commentAfterOnSameLine)
- || value.hasComment(commentAfter);
-}
-
-std::string StyledStreamWriter::normalizeEOL(const std::string &text) {
- std::string normalized;
- normalized.reserve(text.length());
- const char *begin = text.c_str();
- const char *end = begin + text.length();
- const char *current = begin;
- while (current != end) {
- char c = *current++;
- if (c == '\r') // mac or dos EOL
- {
- if (*current == '\n') // convert dos EOL
- ++current;
- normalized += '\n';
- } else
- // handle unix EOL & other char
- normalized += c;
- }
- return normalized;
-}
-
-std::ostream& operator<<(std::ostream &sout, const Value &root) {
- Json::StyledStreamWriter writer;
- writer.write(sout, root);
- return sout;
-}
-
-} // namespace Json
+++ /dev/null
-Import( 'env buildLibrary' )\r
-\r
-buildLibrary( env, Split( """\r
- json_reader.cpp \r
- json_value.cpp \r
- json_writer.cpp\r
- """ ),\r
- 'json' )\r
+++ /dev/null
-#include <stdlib.h>
-#include <string>
-#include <json/json.h>
-
-#include "httpserver.h"
-
-//parse the cmd line parameters
-void parse(int count, char *argv[], HttpServer *httpserver) {
- for (int i = 1; i < count; ++i) {
- string argvstr = argv[i];
- if (argvstr == "--debug"){
- httpserver->g_show_log = true;
- continue;
- }
- int sepindex = argvstr.find(":");
- if (sepindex > -1) {
- string key = argvstr.substr(0, sepindex);
- string value = argvstr.substr(sepindex + 1);
- if (key == "--port") {
- httpserver->g_port = atoi(value.c_str());
- }
- }
- }
-}
-
-int main(int argc, char *argv[]) {
- HttpServer httpserver;
- if (argc > 1) {
- parse(argc, argv, &httpserver);
- }
- httpserver.StartUp();
- return 0;
-}
-
+++ /dev/null
-#include <string>
-#include <json/json.h>
-#include <stdlib.h>
-
-#include "testcase.h"
-
-using namespace std;
-
-TestCase::TestCase() {
- result = "N/A";
-
- std_out = "";
-
- is_executed = false;
-}
-
-TestCase::~TestCase() {
-}
-
-void TestCase::init(const Json::Value value) {
- m_case = value;
- purpose = value["purpose"].asString(); // server will use this string directly
- case_id = value["case_id"].asString();
- if (value["timeout"].isString())
- timeout_value = atoi(value["timeout"].asString().c_str());
- else timeout_value = 90;
-}
-
-Json::Value TestCase::to_json() {
- return m_case;
-}
-
-Json::Value TestCase::result_to_json() {
- Json::Value root;
-
- root["order"] = m_case["order"];
- root["case_id"] = m_case["case_id"];
- root["result"] = result;
-
- if (std_out != "") {
- root["stdout"] = std_out;
- root["start_at"] = start_at;
- root["end_at"] = end_at;
- }
-
- return root;
-}
-
-void TestCase::set_result(Json::Value paras) {
- is_executed = true;
-
- result = paras["result"].asString();
-
- std_out = paras["msg"].asString();
-
- getCurrentTime();
- end_at = m_str_time;
-}
-
-void TestCase::set_start_at() {
- getCurrentTime();
- start_at = m_str_time;
-}
-
-void TestCase::getCurrentTime() {
- memset(m_str_time, 0, 32);
- time_t timer;
- struct tm* t_tm;
- time(&timer);
- t_tm = localtime(&timer);
- sprintf(m_str_time, "%4d-%02d-%02d %02d:%02d:%02d", t_tm->tm_year + 1900,
- t_tm->tm_mon + 1, t_tm->tm_mday, t_tm->tm_hour, t_tm->tm_min,
- t_tm->tm_sec);
-}
\ No newline at end of file
+++ /dev/null
-
-[ testing xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.xml ]
-
-[ split xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1.xml by <set> ]
-[ this might take some time, please wait ]
-[ total set number is: 10 ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_1.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_2.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_3.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_4.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_5.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_6.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_7.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_8.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_9.xml ]
-[ process set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_1.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_2.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_3.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_4.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_5.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_6.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_7.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_8.xml ]
-[ remove empty set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_9.xml ]
-
-[ run set: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml ]
-[ split xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml by <case> ]
-[ this might take some time, please wait ]
-[ prepare_starup_parameters ]
-[ waiting for kill http server ]
-[ forward server http://127.0.0.1:9002 ]
-[ launch the stub app ]
-httpserver->g_test_suite is: api2contt0
-[Server is running.....]
-wrt-launcher: no process found
-[ check server status, get ready! ]
-GET /check_server_status HTTP/1.1
-Host: 127.0.0.1:9002
-Content-Length: 0
-Accept-Encoding: gzip, deflate, compress
-Accept: */*
-User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
-
-
-block: 1/-1215935884, total case: 0/0, block case: 0/0, m_timeout_count:0
-server response is:{
- "block_finished" : 0,
- "finished" : 0
-}
-
-POST /init_test HTTP/1.1
-Host: 127.0.0.1:9002
-Content-Length: 587
-content-type: application/json
-Accept-Encoding: gzip, deflate, compress
-Accept: */*
-User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
-
-{"currentBlk": "1", "totalBlk": "1", "casecount": "1", "cases": [{"onload_delay": "3", "case_id": "video_addTextTrack_base", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned"}], "purpose": "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned", "entry": "/opt/tct-webapi-w3c-content-tests/Video/video_addTextTrack_base.html", "order": "1"}], "type": "compliance", "exetype": "auto"}
-[ init the test suite ]
-wrt-launcher -k api2contt0
-result: App isn't running
-
-[ test suite: tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml, block: 1/1 , finished: 0 ]
-wrt-launcher -s api2contt0
-result: launched
-
-server response is:{"OK":1}
-GET /check_server_status HTTP/1.1
-Host: 127.0.0.1:9002
-Content-Length: 0
-Accept-Encoding: gzip, deflate, compress
-Accept: */*
-User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
-
-
-block: 1/1, total case: 0/1, block case: 0/1, m_timeout_count:0
-server response is:{
- "block_finished" : 0,
- "finished" : 0
-}
-
-[ test suite: tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml, block: 1/1 , finished: 0 ]
-GET /check_server_status HTTP/1.1
-Host: 127.0.0.1:9002
-Content-Length: 0
-Accept-Encoding: gzip, deflate, compress
-Accept: */*
-User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
-
-
-block: 1/1, total case: 0/1, block case: 0/1, m_timeout_count:0
-server response is:{
- "block_finished" : 0,
- "finished" : 0
-}
-
-GET /check_server HTTP/1.1
-Host: 127.0.0.1:8000
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Accept: */*
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-
-
-[ checking server, and found the server is running ]
-server response is:{"OK":1}
-GET /init_session_id?session_id=6330 HTTP/1.1
-Host: 127.0.0.1:8000
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Accept: */*
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-
-
-[ sessionID: 6330 is gotten from the client ]
-server response is:{"OK":1}
-GET /auto_test_task?session_id=6330 HTTP/1.1
-Host: 127.0.0.1:8000
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Accept: text/plain, */*; q=0.01
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-
-
-
-start time: 1982-02-06 15:27:38
-
-[case] execute case: video_addTextTrack_base
-last_test_result: N/A
-server response is:{
- "case_id" : "video_addTextTrack_base",
- "entry" : "/opt/tct-webapi-w3c-content-tests/Video/video_addTextTrack_base.html",
- "onload_delay" : "3",
- "order" : "1",
- "purpose" : "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned",
- "steps" : [
- {
- "expected" : "Pass",
- "order" : "1",
- "step_desc" : "Check if the vedio.addTextTrack has all arguments that expected a new MutableTextTrack object is to be created and returned"
- }
- ]
-}
-
-GET /check_execution_progress?session_id=6330 HTTP/1.1
-Host: 127.0.0.1:8000
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Accept: text/plain, */*; q=0.01
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-
-
-server response is:{"total":1,"current":1,"last_test_result":"N/A"}
-GET /ask_next_step?session_id=6330 HTTP/1.1
-Host: 127.0.0.1:8000
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Accept: text/plain, */*; q=0.01
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-
-
-server response is:{"step":"continue"}
-POST /commit_result HTTP/1.1
-Host: 127.0.0.1:8000
-Origin: file://
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Content-Type: application/x-www-form-urlencoded
-Accept: application/json, text/javascript, */*; q=0.01
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-Content-Length: 177
-
-purpose=Check+if+the+vedio.addTextTrack+has+all+arguments+that+expected+a+new+MutableTextTrack+object+is+to+be+created+and+returned&result=PASS&msg=%5BMessage%5D&session_id=6330
-server response is:{"OK":1}
-GET /auto_test_task?session_id=6330 HTTP/1.1
-Host: 127.0.0.1:8000
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Accept: text/plain, */*; q=0.01
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-
-
-
-[ no auto case is available any more ]
-server response is:{"none":0}
-GET /manual_cases HTTP/1.1
-Host: 127.0.0.1:8000
-Accept-Language: en
-User-Agent: Mozilla/5.0 (Linux; U; Tizen 2.0; en-us) AppleWebKit/537.1 (KHTML, like Gecko) Version/2.0 Mobile
-Accept: text/plain, */*; q=0.01
-Accept-Charset: iso-8859-1, utf-8, utf16, *;q=0.1
-x-Wap-Proxy-Cookie: none
-Accept-Encoding: gzip, deflate
-Connection: Keep-Alive
-
-
-server response is:{"none":0}
-[ test suite: tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml, block: 1/1 , finished: 1 ]
-GET /check_server_status HTTP/1.1
-Host: 127.0.0.1:9002
-Content-Length: 0
-Accept-Encoding: gzip, deflate, compress
-Accept: */*
-User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
-
-
-block: 1/1, total case: 1/1, block case: 1/1, m_timeout_count:0
-server response is:{
- "block_finished" : 1,
- "finished" : 1
-}
-
-GET /get_test_result HTTP/1.1
-Host: 127.0.0.1:9002
-Content-Length: 0
-Accept-Encoding: gzip, deflate, compress
-Accept: */*
-User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
-
-
-server response is:{
- "cases" : [
- {
- "case_id" : "video_addTextTrack_base",
- "end_at" : "1982-02-06 15:27:39",
- "order" : "1",
- "result" : "PASS",
- "start_at" : "1982-02-06 15:27:38",
- "stdout" : "[Message]"
- }
- ],
- "count" : "1"
-}
-
-[ cases result saved to resultfile ]
-
-[ show down server ]
-GET /shut_down_server HTTP/1.1
-Host: 127.0.0.1:9002
-Content-Length: 0
-Accept-Encoding: gzip, deflate, compress
-Accept: */*
-User-Agent: python-requests/1.1.0 CPython/2.7.3 Linux/3.5.0-27-generic
-
-
-wrt-launcher: no process found
-
-[ test complete at time: 2013-04-18_16_06_12 ]
-[ start merging test result xml files, this might take some time, please wait ]
-[ merge result files into /opt/testkit/lite/2013-04-18-16:05:48.429618/tests.result.xml ]
-|--[ merge webapi result file: /opt/testkit/lite/2013-04-18-16:05:48.429618/tct-webapi-w3c-content-tests.auto.suite_1_set_10.xml ]
-----[ suite: tct-webapi-w3c-content-tests, set: Video, time: 2013-04-18_16_06_12 ]
-[ test summary ]
- [ total case number: 1 ]
- [ pass rate: 100.00% ]
- [ PASS case number: 1 ]
- [ FAIL case number: 0 ]
- [ BLOCK case number: 0 ]
- [ N/A case number: 0 ]
-[ generate result xml: /opt/testkit/lite/2013-04-18-16:05:48.429618/tests.result.xml ]
-[ merge complete, write to the result file, this might take some time, please wait ]
-wrt-launcher -k api2contt0
-result: killed
-
-server response is:{"OK":1}
-[ all tasks for testkit lite are accomplished, goodbye ]
-danny@danny-Latitude-E6400:~$
+++ /dev/null
-{"currentBlk": "4", "totalBlk": "4", "casecount": "387", "cases": [{"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_setter.html", "pre_condition": "none", "case_id": "Uint16Array_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify setter of Uint16Array"}], "purpose": "Verify setter of Uint16Array", "order": "301"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_array.html", "pre_condition": "none", "case_id": "Uint16Array_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array) of Uint16Array"}], "purpose": "Verify set(array) of Uint16Array", "order": "302"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_array_offset.html", "pre_condition": "none", "case_id": "Uint16Array_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array, offset) of Uint16Array"}], "purpose": "Verify set(array, offset) of Uint16Array", "order": "303"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_exist.html", "pre_condition": "none", "case_id": "Uint16Array_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the set of Uint16Array exist"}], "purpose": "Check if the set of Uint16Array exist", "order": "304"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint16Array_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray) of Uint16Array"}], "purpose": "Verify set(typedarray) of Uint16Array", "order": "305"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint16Array_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray, offset) of Uint16Array"}], "purpose": "Verify set(typedarray, offset) of Uint16Array", "order": "306"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_subarray_begin.html", "pre_condition": "none", "case_id": "Uint16Array_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin) of Uint16Array"}], "purpose": "Verify subarray(begin) of Uint16Array", "order": "307"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint16Array_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin, end) of Uint16Array"}], "purpose": "Verify subarray(begin, end) of Uint16Array", "order": "308"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint16Array_subarray_exist.html", "pre_condition": "none", "case_id": "Uint16Array_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint16Array exist"}], "purpose": "Check if the subarray of Uint16Array exist", "order": "309"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_buffer.html", "pre_condition": "none", "case_id": "Uint32Array_buffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify buffer of Uint32Array"}], "purpose": "Verify buffer of Uint32Array", "order": "310"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_buffer_exist.html", "pre_condition": "none", "case_id": "Uint32Array_buffer_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the buffer of Uint32Array exist"}], "purpose": "Check if the buffer of Uint32Array exist", "order": "311"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteLength.html", "pre_condition": "none", "case_id": "Uint32Array_byteLength", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify byteLength of Uint32Array"}], "purpose": "Verify byteLength of Uint32Array", "order": "312"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteLength_exist.html", "pre_condition": "none", "case_id": "Uint32Array_byteLength_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteLength of Uint32Array exist"}], "purpose": "Check if the byteLength of Uint32Array exist", "order": "313"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteOffset.html", "pre_condition": "none", "case_id": "Uint32Array_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify byteOffset of Uint32Array"}], "purpose": "Verify byteOffset of Uint32Array", "order": "314"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_byteOffset_exist.html", "pre_condition": "none", "case_id": "Uint32Array_byteOffset_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteOffset of Uint32Array exist"}], "purpose": "Check if the byteOffset of Uint32Array exist", "order": "315"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_BYTES_PER_ELEMENT_const_4.html", "pre_condition": "none", "case_id": "Uint32Array_BYTES_PER_ELEMENT_const_4", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify BYTES_PER_ELEMENT of Uint32Array is 4"}], "purpose": "Verify BYTES_PER_ELEMENT of Uint32Array is 4", "order": "316"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_BYTES_PER_ELEMENT_exist.html", "pre_condition": "none", "case_id": "Uint32Array_BYTES_PER_ELEMENT_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the BYTES_PER_ELEMENT of Uint32Array exist"}], "purpose": "Check if the BYTES_PER_ELEMENT of Uint32Array exist", "order": "317"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_array.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(array) of Uint32Array"}], "purpose": "Verify constructor(array) of Uint32Array", "order": "318"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_ArrayBuffer.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_ArrayBuffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer) of Uint32Array"}], "purpose": "Verify constructor(arraybuffer) of Uint32Array", "order": "319"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_ArrayBuffer_byteOffset.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_ArrayBuffer_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer, byteOffset) of Uint32Array"}], "purpose": "Verify constructor(arraybuffer, byteOffset) of Uint32Array", "order": "320"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_ArrayBuffer_byteOffset_length.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_ArrayBuffer_byteOffset_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer, byteOffset, length) of Uint32Array"}], "purpose": "Verify constructor(arraybuffer, byteOffset, length) of Uint32Array", "order": "321"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_length.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(length) of Uint32Array"}], "purpose": "Verify constructor(length) of Uint32Array", "order": "322"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_constructor_TypedArray.html", "pre_condition": "none", "case_id": "Uint32Array_constructor_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(typedarray) of Uint32Array"}], "purpose": "Verify constructor(typedarray) of Uint32Array", "order": "323"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_getter.html", "pre_condition": "none", "case_id": "Uint32Array_getter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify getter of Uint32Array"}], "purpose": "Verify getter of Uint32Array", "order": "324"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_length.html", "pre_condition": "none", "case_id": "Uint32Array_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify length of Uint32Array"}], "purpose": "Verify length of Uint32Array", "order": "325"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_length_exist.html", "pre_condition": "none", "case_id": "Uint32Array_length_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the length of Uint32Array exist"}], "purpose": "Check if the length of Uint32Array exist", "order": "326"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_setter.html", "pre_condition": "none", "case_id": "Uint32Array_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify setter of Uint32Array"}], "purpose": "Verify setter of Uint32Array", "order": "327"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_array.html", "pre_condition": "none", "case_id": "Uint32Array_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array) of Uint32Array"}], "purpose": "Verify set(array) of Uint32Array", "order": "328"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_array_offset.html", "pre_condition": "none", "case_id": "Uint32Array_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array, offset) of Uint32Array"}], "purpose": "Verify set(array, offset) of Uint32Array", "order": "329"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_exist.html", "pre_condition": "none", "case_id": "Uint32Array_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the set of Uint32Array exist"}], "purpose": "Check if the set of Uint32Array exist", "order": "330"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint32Array_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray) of Uint32Array"}], "purpose": "Verify set(typedarray) of Uint32Array", "order": "331"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint32Array_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray, offset) of Uint32Array"}], "purpose": "Verify set(typedarray, offset) of Uint32Array", "order": "332"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_subarray_begin.html", "pre_condition": "none", "case_id": "Uint32Array_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin) of Uint32Array"}], "purpose": "Verify subarray(begin) of Uint32Array", "order": "333"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint32Array_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(begin, end) of Uint32Array"}], "purpose": "Verify set(begin, end) of Uint32Array", "order": "334"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint32Array_subarray_exist.html", "pre_condition": "none", "case_id": "Uint32Array_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint32Array exist"}], "purpose": "Check if the subarray of Uint32Array exist", "order": "335"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_buffer.html", "pre_condition": "none", "case_id": "Uint8Array_buffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the buffer of Uint8Array"}], "purpose": "Verify the buffer of Uint8Array", "order": "336"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_buffer_exist.html", "pre_condition": "none", "case_id": "Uint8Array_buffer_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the buffer of Uint8Array exist"}], "purpose": "Check if the buffer of Uint8Array exist", "order": "337"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteLength.html", "pre_condition": "none", "case_id": "Uint8Array_byteLength", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteLength of Uint8Array"}], "purpose": "Verify the byteLength of Uint8Array", "order": "338"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteLength_exist.html", "pre_condition": "none", "case_id": "Uint8Array_byteLength_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteLength of Uint8Array exist"}], "purpose": "Check if the byteLength of Uint8Array exist", "order": "339"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteOffset.html", "pre_condition": "none", "case_id": "Uint8Array_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteOffset of Uint8Array"}], "purpose": "Verify the byteOffset of Uint8Array", "order": "340"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_byteOffset_exist.html", "pre_condition": "none", "case_id": "Uint8Array_byteOffset_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteOffset of Uint8Array exist"}], "purpose": "Check if the byteOffset of Uint8Array exist", "order": "341"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_BYTES_PER_ELEMENT_const_1.html", "pre_condition": "none", "case_id": "Uint8Array_BYTES_PER_ELEMENT_const_1", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the BYTES_PER_ELEMENT of Uint8Array is 1"}], "purpose": "Verify the BYTES_PER_ELEMENT of Uint8Array is 1", "order": "342"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_BYTES_PER_ELEMENT_exist.html", "pre_condition": "none", "case_id": "Uint8Array_BYTES_PER_ELEMENT_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the BYTES_PER_ELEMENT of Uint8Array exist"}], "purpose": "Check if the BYTES_PER_ELEMENT of Uint8Array exist", "order": "343"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_array.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(array) of Uint8Array"}], "purpose": "Verify the constructor(array) of Uint8Array", "order": "344"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_ArrayBuffer.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_ArrayBuffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(arraybuffer) of Uint8Array"}], "purpose": "Verify the constructor(arraybuffer) of Uint8Array", "order": "345"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_ArrayBuffer_byteOffSet.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_ArrayBuffer_byteOffSet", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(arraybuffer, byteOffset) of Uint8Array"}], "purpose": "Verify the constructor(arraybuffer, byteOffset) of Uint8Array", "order": "346"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_ArrayBuffer_byteOffSet_length.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_ArrayBuffer_byteOffSet_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(arraybuffer, byteOffset, length) of Uint8Array"}], "purpose": "Verify the constructor(arraybuffer, byteOffset, length) of Uint8Array", "order": "347"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_length.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(length) of Uint8Array"}], "purpose": "Verify the constructor(length) of Uint8Array", "order": "348"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_constructor_TypedArray.html", "pre_condition": "none", "case_id": "Uint8Array_constructor_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the constructor(typedarray) of Uint8Array"}], "purpose": "Verify the constructor(typedarray) of Uint8Array", "order": "349"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_getter.html", "pre_condition": "none", "case_id": "Uint8Array_getter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the getter of Uint8Array"}], "purpose": "Verify the getter of Uint8Array", "order": "350"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_length.html", "pre_condition": "none", "case_id": "Uint8Array_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the length of Uint8Array"}], "purpose": "Verify the length of Uint8Array", "order": "351"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_length_exist.html", "pre_condition": "none", "case_id": "Uint8Array_length_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the length of Uint8Array exist"}], "purpose": "Check if the length of Uint8Array exist", "order": "352"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_setter.html", "pre_condition": "none", "case_id": "Uint8Array_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the setter of Uint8Array"}], "purpose": "Verify the setter of Uint8Array", "order": "353"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_array.html", "pre_condition": "none", "case_id": "Uint8Array_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(array) of Uint8Array"}], "purpose": "Verify the set(array) of Uint8Array", "order": "354"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_array_offset.html", "pre_condition": "none", "case_id": "Uint8Array_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(array, offset) of Uint8Array"}], "purpose": "Verify the set(array, offset) of Uint8Array", "order": "355"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_exist.html", "pre_condition": "none", "case_id": "Uint8Array_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the set of Uint8Array exist"}], "purpose": "Check if the set of Uint8Array exist", "order": "356"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint8Array_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(typedarray) of Uint8Array"}], "purpose": "Verify the set(typedarray) of Uint8Array", "order": "357"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint8Array_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the set(typedarray, offset) of Uint8Array"}], "purpose": "Verify the set(typedarray, offset) of Uint8Array", "order": "358"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_subarray_begin.html", "pre_condition": "none", "case_id": "Uint8Array_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the subarray(begin) of Uint8Array"}], "purpose": "Verify the subarray(begin) of Uint8Array", "order": "359"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint8Array_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the subarray(begin, end) of Uint8Array"}], "purpose": "Verify the subarray(begin, end) of Uint8Array", "order": "360"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8Array_subarray_exist.html", "pre_condition": "none", "case_id": "Uint8Array_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint8Array exist"}], "purpose": "Check if the subarray of Uint8Array exist", "order": "361"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_buffer.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_buffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the buffer of Uint8ClampedArray"}], "purpose": "Verify the buffer of Uint8ClampedArray", "order": "362"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_buffer_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_buffer_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "check if the buffer of Uint8ClampedArray exist"}], "purpose": "check if the buffer of Uint8ClampedArray exist", "order": "363"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteLength.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteLength", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteLength of Uint8ClampedArray"}], "purpose": "Verify the byteLength of Uint8ClampedArray", "order": "364"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteLength_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteLength_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the byteLength of Uint8ClampedArray exist"}], "purpose": "Check if the byteLength of Uint8ClampedArray exist", "order": "365"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteOffset.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteOffset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the byteOffset of Uint8ClampedArray"}], "purpose": "Verify the byteOffset of Uint8ClampedArray", "order": "366"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_byteOffset_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_byteOffset_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "check if the byteOffset of Uint8ClampedArray exist"}], "purpose": "check if the byteOffset of Uint8ClampedArray exist", "order": "367"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_BYTES_PER_ELEMENT_const_1.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_BYTES_PER_ELEMENT_const_1", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify the BYTES_PER-ELEMENT of Uint8ClampedArray is 1"}], "purpose": "Verify the BYTES_PER-ELEMENT of Uint8ClampedArray is 1", "order": "368"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_BYTES_PER_ELEMENT_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_BYTES_PER_ELEMENT_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the BYTES_PER_ELEMENT of Uint8ClampedArray exist"}], "purpose": "Check if the BYTES_PER_ELEMENT of Uint8ClampedArray exist", "order": "369"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_array.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(array) of Uint8ClampedArray"}], "purpose": "Verify constructor(array) of Uint8ClampedArray", "order": "370"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_ArrayBuffer.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_ArrayBuffer", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer) of Uint8ClampedArray"}], "purpose": "Verify constructor(arraybuffer) of Uint8ClampedArray", "order": "371"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(arraybuffer, byteOffset) of Uint8ClampedArray"}], "purpose": "Verify constructor(arraybuffer, byteOffset) of Uint8ClampedArray", "order": "372"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet_length.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_ArrayBuffer_byteOffSet_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(buffer, byteOffset, length) of Uint8ClampedArray"}], "purpose": "Verify constructor(buffer, byteOffset, length) of Uint8ClampedArray", "order": "373"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_length.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(length) of Uint8ClampedArray"}], "purpose": "Verify constructor(length) of Uint8ClampedArray", "order": "374"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_constructor_TypedArray.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_constructor_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify constructor(typedarray) of Uint8ClampedArray"}], "purpose": "Verify constructor(typedarray) of Uint8ClampedArray", "order": "375"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_getter.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_getter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify getter of Uint8ClampedArray"}], "purpose": "Verify getter of Uint8ClampedArray", "order": "376"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_length.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_length", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify length of Uint8ClampedArray"}], "purpose": "Verify length of Uint8ClampedArray", "order": "377"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_length_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_length_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the length of Uint8ClampedArray exist"}], "purpose": "Check if the length of Uint8ClampedArray exist", "order": "378"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_setter.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_setter", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify setter of Uint8ClampedArray"}], "purpose": "Verify setter of Uint8ClampedArray", "order": "379"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_array.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_array", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array) of Uint8ClampedArray"}], "purpose": "Verify set(array) of Uint8ClampedArray", "order": "380"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_array_offset.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_array_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(array, offset) of Uint8ClampedArray"}], "purpose": "Verify set(array, offset) of Uint8ClampedArray", "order": "381"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "check if the set of Uint8ClampedArray exist"}], "purpose": "check if the set of Uint8ClampedArray exist", "order": "382"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_TypedArray.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_TypedArray", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray) of Uint8ClampedArray"}], "purpose": "Verify set(typedarray) of Uint8ClampedArray", "order": "383"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_set_TypedArray_offset.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_set_TypedArray_offset", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify set(typedarray, offset) of Uint8ClampedArray"}], "purpose": "Verify set(typedarray, offset) of Uint8ClampedArray", "order": "384"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_subarray_begin.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_subarray_begin", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin) of Uint8ClampedArray"}], "purpose": "Verify subarray(begin) of Uint8ClampedArray", "order": "385"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_subarray_begin_end.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_subarray_begin_end", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Verify subarray(begin, end) of Uint8ClampedArray"}], "purpose": "Verify subarray(begin, end) of Uint8ClampedArray", "order": "386"}, {"post_condition": "none", "onload_delay": "3", "test_script_entry": "/opt/tct-webapi-nonw3c-tests/TypedArrays/Uint8ClampedArray_subarray_exist.html", "pre_condition": "none", "case_id": "Uint8ClampedArray_subarray_exist", "steps": [{"expected": "Pass", "order": "1", "step_desc": "Check if the subarray of Uint8ClampedArray exist"}], "purpose": "Check if the subarray of Uint8ClampedArray exist", "order": "387"}], "type": "compliance", "exetype": "auto"}
\ No newline at end of file
+++ /dev/null
-#include "httpserver.h"
-
-int main() {
- HttpServer* httpserver = new HttpServer();
-
- httpserver->parse_json_str("src/ut/test.json");
-
- struct HttpRequest httprequest;
-
- httprequest.path = "/init_test";
- httpserver->processpost(1, &httprequest);
-
- httpserver->g_test_suite = "api3nonw3c";
-
- httprequest.path = "/check_server";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/check_server_status";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/shut_down_server";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/ask_next_step";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/init_session_id?session_id=1024";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/auto_test_task?session_id=1024";
- httprequest.content = "session_id=1024";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/manual_cases";
- httpserver->processpost(1, &httprequest);
-
- httprequest.content = "purpose=ut-cas&result=N/A";
- httprequest.path = "/commit_manual_result";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/check_execution_progress";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/generate_xml";
- httpserver->processpost(1, &httprequest);
-
- httprequest.content = "purpose=Verify setter of Uint16Array&result=N/A";
- httprequest.path = "/commit_result";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/check_execution_progress";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/set_capability";
- httprequest.content = "{\"name1\":true, \"name2\":45, \"name3\":\"678\"}";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/capability";
- httprequest.content = "name=name1";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/capability?name=name2&value=45";
- httprequest.content = "name=name2&value=45";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/capability?name=name3&value=678";
- httprequest.content = "name=name3&value=678";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/capability?name=name4";
- httprequest.content = "name=name4";
- httpserver->processpost(1, &httprequest);
-
- httprequest.path = "/set_capability";
- httprequest.content = "{\"bluetooth\":true, \"nfc\":true, \"multiTouchCount\":true, \"inputKeyboard\":true, \"wifi\":true, \"wifiDirect\":true, \"openglesVersion1_1\":true, \"openglesVersion2_0\":true, \"fmRadio\":true, \"platformVersion\":true, \"webApiVersion\":true, \"nativeApiVersion\":true, \"platformName\":true, \"cameraFront\":true, \"cameraFrontFlash\":true, \"cameraBack\":true, \"cameraBackFlash\":true, \"location\":true, \"locationGps\":true, \"locationWps\":true, \"microphone\":true, \"usbHost\":true, \"usbAccessory\":true, \"screenOutputRca\":true, \"screenOutputHdmi\":true, \"platformCoreCpuArch\":true, \"platformCoreFpuArch\":true, \"sipVoip\":true, \"duid\":true, \"speechRecognition\":true, \"accelerometer\":true, \"barometer\":true, \"gyroscope\":true, \"magnetometer\":true, \"proximity\":true}";
- httpserver->processpost(1, &httprequest);
-
- httpserver->StartUp();
-
- delete httpserver;
-
- return 0;
-}