From ee7d6cc0fdae6a252fcd2a94a28647381c42239b Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Sat, 16 Apr 2016 19:49:12 +0900 Subject: [PATCH 001/483] Refactor and re-design tinyobjloader. * Separete attribs(vtx,normal,texcoords) and shape. * Support different index for vtx/normal/texcoord. --- README.md | 1 + .../catmark_torus_creases0.obj | 0 .../cornell_box_multimaterial.obj | 0 cube.mtl => models/cube.mtl | 0 cube.obj => models/cube.obj | 0 .../missing_material_file.obj | 0 no_material.obj => models/no_material.obj | 0 test-nan.obj => models/test-nan.obj | 0 test.cc | 74 ++++-- tiny_obj_loader.h | 242 +++++++++--------- 10 files changed, 171 insertions(+), 146 deletions(-) rename catmark_torus_creases0.obj => models/catmark_torus_creases0.obj (100%) rename cornell_box_multimaterial.obj => models/cornell_box_multimaterial.obj (100%) rename cube.mtl => models/cube.mtl (100%) rename cube.obj => models/cube.obj (100%) rename missing_material_file.obj => models/missing_material_file.obj (100%) rename no_material.obj => models/no_material.obj (100%) rename test-nan.obj => models/test-nan.obj (100%) diff --git a/README.md b/README.md index 8bc365a1..056f7c3a 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Tiny but powerful single file wavefront obj loader written in C++. No dependency What's new ---------- +* XX YY, ZZZZ : New data strcutre and API! * Jan 29, 2016 : Support n-polygon(no triangulation) and OpenSubdiv crease tag! Thanks dboogert! * Nov 26, 2015 : Now single-header only!. * Nov 08, 2015 : Improved API. diff --git a/catmark_torus_creases0.obj b/models/catmark_torus_creases0.obj similarity index 100% rename from catmark_torus_creases0.obj rename to models/catmark_torus_creases0.obj diff --git a/cornell_box_multimaterial.obj b/models/cornell_box_multimaterial.obj similarity index 100% rename from cornell_box_multimaterial.obj rename to models/cornell_box_multimaterial.obj diff --git a/cube.mtl b/models/cube.mtl similarity index 100% rename from cube.mtl rename to models/cube.mtl diff --git a/cube.obj b/models/cube.obj similarity index 100% rename from cube.obj rename to models/cube.obj diff --git a/missing_material_file.obj b/models/missing_material_file.obj similarity index 100% rename from missing_material_file.obj rename to models/missing_material_file.obj diff --git a/no_material.obj b/models/no_material.obj similarity index 100% rename from no_material.obj rename to models/no_material.obj diff --git a/test-nan.obj b/models/test-nan.obj similarity index 100% rename from test-nan.obj rename to models/test-nan.obj diff --git a/test.cc b/test.cc index 2539faaa..88d8be18 100644 --- a/test.cc +++ b/test.cc @@ -8,11 +8,35 @@ #include #include -static void PrintInfo(const std::vector& shapes, const std::vector& materials, bool triangulate = true) +static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector& shapes, const std::vector& materials, bool triangulate = true) { + std::cout << "# of positions : " << (attrib.positions.size() / 3) << std::endl; + std::cout << "# of normals : " << (attrib.normals.size() / 3) << std::endl; + std::cout << "# of texcoords : " << (attrib.texcoords.size() / 2) << std::endl; + std::cout << "# of shapes : " << shapes.size() << std::endl; std::cout << "# of materials : " << materials.size() << std::endl; + for (size_t v = 0; v < attrib.positions.size() / 3; v++) { + printf(" v[%ld] = (%f, %f, %f)\n", v, + static_cast(attrib.positions[3*v+0]), + static_cast(attrib.positions[3*v+1]), + static_cast(attrib.positions[3*v+2])); + } + + for (size_t v = 0; v < attrib.normals.size() / 3; v++) { + printf(" n[%ld] = (%f, %f, %f)\n", v, + static_cast(attrib.normals[3*v+0]), + static_cast(attrib.normals[3*v+1]), + static_cast(attrib.normals[3*v+2])); + } + + for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) { + printf(" uv[%ld] = (%f, %f)\n", v, + static_cast(attrib.texcoords[2*v+0]), + static_cast(attrib.texcoords[2*v+1])); + } + for (size_t i = 0; i < shapes.size(); i++) { printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str()); printf("Size of shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size()); @@ -22,11 +46,19 @@ static void PrintInfo(const std::vector& shapes, const std::ve printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size()); assert((shapes[i].mesh.indices.size() % 3) == 0); for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) { - printf(" idx[%ld] = %d, %d, %d. mat_id = %d\n", f, shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2], shapes[i].mesh.material_ids[f]); + tinyobj::index_t i0 = shapes[i].mesh.indices[3*f+0]; + tinyobj::index_t i1 = shapes[i].mesh.indices[3*f+1]; + tinyobj::index_t i2 = shapes[i].mesh.indices[3*f+2]; + printf(" idx[%ld] = %d/%d/%d, %d/%d/%d, %d/%d/%d. mat_id = %d\n", f, + i0.vertex_index, i0.normal_index, i0.texcoord_index, + i1.vertex_index, i1.normal_index, i1.texcoord_index, + i2.vertex_index, i2.normal_index, i2.texcoord_index, + shapes[i].mesh.material_ids[f]); } } else { for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) { - printf(" idx[%ld] = %d\n", f, shapes[i].mesh.indices[f]); + tinyobj::index_t idx = shapes[i].mesh.indices[f]; + printf(" idx[%ld] = %d/%d/%d\n", f, idx.vertex_index, idx.normal_index, idx.texcoord_index); } printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size()); @@ -44,14 +76,14 @@ static void PrintInfo(const std::vector& shapes, const std::ve static_cast(shapes[i].mesh.num_vertices[v])); } - printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size()); - assert((shapes[i].mesh.positions.size() % 3) == 0); - for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) { - printf(" v[%ld] = (%f, %f, %f)\n", v, - shapes[i].mesh.positions[3*v+0], - shapes[i].mesh.positions[3*v+1], - shapes[i].mesh.positions[3*v+2]); - } + //printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size()); + //assert((shapes[i].mesh.positions.size() % 3) == 0); + //for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) { + // printf(" v[%ld] = (%f, %f, %f)\n", v, + // static_cast(shapes[i].mesh.positions[3*v+0]), + // static_cast(shapes[i].mesh.positions[3*v+1]), + // static_cast(shapes[i].mesh.positions[3*v+2])); + //} printf("shape[%ld].num_tags: %ld\n", i, shapes[i].mesh.tags.size()); for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) { @@ -70,7 +102,7 @@ static void PrintInfo(const std::vector& shapes, const std::ve printf(" floats: ["); for (size_t j = 0; j < shapes[i].mesh.tags[t].floatValues.size(); ++j) { - printf("%f", shapes[i].mesh.tags[t].floatValues[j]); + printf("%f", static_cast(shapes[i].mesh.tags[t].floatValues[j])); if (j < (shapes[i].mesh.tags[t].floatValues.size()-1)) { printf(", "); @@ -128,11 +160,12 @@ TestLoadObj( { std::cout << "Loading " << filename << std::endl; + tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string err; - bool ret = tinyobj::LoadObj(shapes, materials, err, filename, basepath, triangulate); + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, basepath, triangulate); if (!err.empty()) { std::cerr << err << std::endl; @@ -143,7 +176,7 @@ TestLoadObj( return false; } - PrintInfo(shapes, materials, triangulate); + PrintInfo(attrib, shapes, materials, triangulate); return true; } @@ -223,13 +256,13 @@ std::string matStream( virtual ~MaterialStringStreamReader() {} virtual bool operator() ( const std::string& matId, - std::vector& materials, - std::map& matMap, - std::string& err) + std::vector* materials, + std::map* matMap, + std::string* err) { (void)matId; (void)err; - LoadMtl(matMap, materials, m_matSStream); + LoadMtl(matMap, materials, &m_matSStream); return true; } @@ -238,10 +271,11 @@ std::string matStream( }; MaterialStringStreamReader matSSReader(matStream); + tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string err; - bool ret = tinyobj::LoadObj(shapes, materials, err, objStream, matSSReader); + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &objStream, &matSSReader); if (!err.empty()) { std::cerr << err << std::endl; @@ -251,7 +285,7 @@ std::string matStream( return false; } - PrintInfo(shapes, materials); + PrintInfo(attrib, shapes, materials); return true; } diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 8bdd0a32..b3a7589c 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -1,10 +1,11 @@ // -// Copyright 2012-2015, Syoyo Fujita. +// Copyright 2012-2016, Syoyo Fujita. // // Licensed under 2-clause BSD license. // // +// version devel : Change data structure. Support different index for vertex/normal/texcoord(#73, #39) // version 0.9.20: Fixes creating per-face material using `usemtl`(#68) // version 0.9.17: Support n-polygon and crease tag(OpenSubdiv extension) // version 0.9.16: Make tinyobjloader header-only @@ -81,11 +82,16 @@ typedef struct { std::vector stringValues; } tag_t; +// Index struct to support differnt indices for vtx/normal/texcoord. +// -1 means not used. typedef struct { - std::vector positions; - std::vector normals; - std::vector texcoords; - std::vector indices; + int vertex_index; + int normal_index; + int texcoord_index; +} index_t; + +typedef struct { + std::vector indices; std::vector num_vertices; // The number of vertices per face. Up to 255. std::vector material_ids; // per-face material ID @@ -97,15 +103,21 @@ typedef struct { mesh_t mesh; } shape_t; +typedef struct { + std::vector positions; + std::vector normals; + std::vector texcoords; +} attrib_t; + class MaterialReader { public: MaterialReader() {} virtual ~MaterialReader(); virtual bool operator()(const std::string &matId, - std::vector &materials, - std::map &matMap, - std::string &err) = 0; + std::vector *materials, + std::map *matMap, + std::string *err) = 0; }; class MaterialFileReader : public MaterialReader { @@ -114,14 +126,15 @@ class MaterialFileReader : public MaterialReader { : m_mtlBasePath(mtl_basepath) {} virtual ~MaterialFileReader() {} virtual bool operator()(const std::string &matId, - std::vector &materials, - std::map &matMap, std::string &err); + std::vector *materials, + std::map *matMap, std::string *err); private: std::string m_mtlBasePath; }; /// Loads .obj from a file. +/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data /// 'shapes' will be filled with parsed shape data /// The function returns error string. /// Returns true when loading .obj become success. @@ -129,9 +142,10 @@ class MaterialFileReader : public MaterialReader { /// 'mtl_basepath' is optional, and used for base path for .mtl file. /// 'triangulate' is optional, and used whether triangulate polygon face in .obj /// or not. -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, // [output] +bool LoadObj(attrib_t *attrib, + std::vector *shapes, + std::vector *materials, + std::string *err, const char *filename, const char *mtl_basepath = NULL, bool triangulate = true); @@ -139,16 +153,17 @@ bool LoadObj(std::vector &shapes, // [output] /// std::istream for materials. /// Returns true when loading .obj become success. /// Returns warning and error message into `err` -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, // [output] - std::istream &inStream, MaterialReader &readMatFn, +bool LoadObj(attrib_t *attrib, + std::vector *shapes, + std::vector *materials, + std::string *err, + std::istream *inStream, MaterialReader *readMatFn, bool triangulate = true); /// Loads materials into std::map -void LoadMtl(std::map &material_map, // [output] - std::vector &materials, // [output] - std::istream &inStream); +void LoadMtl(std::map *material_map, + std::vector *materials, + std::istream *inStream); } #ifdef TINYOBJLOADER_IMPLEMENTATION @@ -204,7 +219,7 @@ struct obj_shape { }; #define IS_SPACE( x ) ( ( (x) == ' ') || ( (x) == '\t') ) -#define IS_DIGIT( x ) ( (unsigned int)( (x) - '0' ) < (unsigned int)10 ) +#define IS_DIGIT( x ) ( static_cast( (x) - '0' ) < static_cast(10) ) #define IS_NEW_LINE( x ) ( ( (x) == '\r') || ( (x) == '\n') || ( (x) == '\0') ) // Make index zero-base, and also support relative index. @@ -447,45 +462,6 @@ static vertex_index parseTriple(const char *&token, int vsize, int vnsize, return vi; } -static unsigned int -updateVertex(std::map &vertexCache, - std::vector &positions, std::vector &normals, - std::vector &texcoords, - const std::vector &in_positions, - const std::vector &in_normals, - const std::vector &in_texcoords, const vertex_index &i) { - const std::map::iterator it = vertexCache.find(i); - - if (it != vertexCache.end()) { - // found cache - return it->second; - } - - assert(in_positions.size() > static_cast(3 * i.v_idx + 2)); - - positions.push_back(in_positions[3 * static_cast(i.v_idx) + 0]); - positions.push_back(in_positions[3 * static_cast(i.v_idx) + 1]); - positions.push_back(in_positions[3 * static_cast(i.v_idx) + 2]); - - if ((i.vn_idx >= 0) && - (static_cast(i.vn_idx * 3 + 2) < in_normals.size())) { - normals.push_back(in_normals[3 * static_cast(i.vn_idx) + 0]); - normals.push_back(in_normals[3 * static_cast(i.vn_idx) + 1]); - normals.push_back(in_normals[3 * static_cast(i.vn_idx) + 2]); - } - - if ((i.vt_idx >= 0) && - (static_cast(i.vt_idx * 2 + 1) < in_texcoords.size())) { - texcoords.push_back(in_texcoords[2 * static_cast(i.vt_idx) + 0]); - texcoords.push_back(in_texcoords[2 * static_cast(i.vt_idx) + 1]); - } - - unsigned int idx = static_cast(positions.size() / 3 - 1); - vertexCache[i] = idx; - - return idx; -} - static void InitMaterial(material_t &material) { material.name = ""; material.ambient_texname = ""; @@ -510,13 +486,13 @@ static void InitMaterial(material_t &material) { } static bool exportFaceGroupToShape( - shape_t &shape, std::map vertexCache, + shape_t &shape, const std::vector &in_positions, const std::vector &in_normals, const std::vector &in_texcoords, const std::vector > &faceGroup, std::vector &tags, const int material_id, const std::string &name, - bool clearCache, bool triangulate) { + bool triangulate) { if (faceGroup.empty()) { return false; } @@ -538,19 +514,20 @@ static bool exportFaceGroupToShape( i1 = i2; i2 = face[k]; - unsigned int v0 = updateVertex( - vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i0); - unsigned int v1 = updateVertex( - vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i1); - unsigned int v2 = updateVertex( - vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i2); - - shape.mesh.indices.push_back(v0); - shape.mesh.indices.push_back(v1); - shape.mesh.indices.push_back(v2); + index_t idx0, idx1, idx2; + idx0.vertex_index = i0.v_idx; + idx0.normal_index = i0.vn_idx; + idx0.texcoord_index = i0.vt_idx; + idx1.vertex_index = i1.v_idx; + idx1.normal_index = i1.vn_idx; + idx1.texcoord_index = i1.vt_idx; + idx2.vertex_index = i2.v_idx; + idx2.normal_index = i2.vn_idx; + idx2.texcoord_index = i2.vt_idx; + + shape.mesh.indices.push_back(idx0); + shape.mesh.indices.push_back(idx1); + shape.mesh.indices.push_back(idx2); shape.mesh.num_vertices.push_back(3); shape.mesh.material_ids.push_back(material_id); @@ -558,12 +535,10 @@ static bool exportFaceGroupToShape( } else { for (size_t k = 0; k < npolys; k++) { - unsigned int v = - updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, - in_texcoords, face[k]); - - shape.mesh.indices.push_back(v); + index_t idx; + idx.vertex_index = face[k].v_idx; + idx.normal_index = face[k].vn_idx; + idx.texcoord_index = face[k].vt_idx; } shape.mesh.num_vertices.push_back(static_cast(npolys)); @@ -574,14 +549,11 @@ static bool exportFaceGroupToShape( shape.name = name; shape.mesh.tags.swap(tags); - if (clearCache) - vertexCache.clear(); - return true; } -void LoadMtl(std::map &material_map, - std::vector &materials, std::istream &inStream) { +void LoadMtl(std::map *material_map, + std::vector *materials, std::istream *inStream) { // Create a default material anyway. material_t material; @@ -589,8 +561,8 @@ void LoadMtl(std::map &material_map, size_t maxchars = 8192; // Alloc enough size. std::vector buf(maxchars); // Alloc enough size. - while (inStream.peek() != -1) { - inStream.getline(&buf[0], static_cast(maxchars)); + while (inStream->peek() != -1) { + inStream->getline(&buf[0], static_cast(maxchars)); std::string linebuf(&buf[0]); @@ -624,9 +596,9 @@ void LoadMtl(std::map &material_map, if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { // flush previous material. if (!material.name.empty()) { - material_map.insert(std::pair( - material.name, static_cast(materials.size()))); - materials.push_back(material); + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); } // initial temporary material @@ -803,15 +775,15 @@ void LoadMtl(std::map &material_map, } } // flush last material. - material_map.insert(std::pair( - material.name, static_cast(materials.size()))); - materials.push_back(material); + material_map->insert(std::pair( + material.name, static_cast(materials->size()))); + materials->push_back(material); } bool MaterialFileReader::operator()(const std::string &matId, - std::vector &materials, - std::map &matMap, - std::string &err) { + std::vector *materials, + std::map *matMap, + std::string *err) { std::string filepath; if (!m_mtlBasePath.empty()) { @@ -821,29 +793,37 @@ bool MaterialFileReader::operator()(const std::string &matId, } std::ifstream matIStream(filepath.c_str()); - LoadMtl(matMap, materials, matIStream); + LoadMtl(matMap, materials, &matIStream); if (!matIStream) { std::stringstream ss; ss << "WARN: Material file [ " << filepath << " ] not found. Created a default material."; - err += ss.str(); + if (err) { + (*err) += ss.str(); + } } return true; } -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, const char *filename, const char *mtl_basepath, +bool LoadObj(attrib_t *attrib, + std::vector *shapes, + std::vector *materials, + std::string *err, const char *filename, const char *mtl_basepath, bool trianglulate) { - shapes.clear(); + attrib->positions.clear(); + attrib->normals.clear(); + attrib->texcoords.clear(); + shapes->clear(); std::stringstream errss; std::ifstream ifs(filename); if (!ifs) { errss << "Cannot open file [" << filename << "]" << std::endl; - err = errss.str(); + if (err) { + (*err) = errss.str(); + } return false; } @@ -853,13 +833,14 @@ bool LoadObj(std::vector &shapes, // [output] } MaterialFileReader matFileReader(basePath); - return LoadObj(shapes, materials, err, ifs, matFileReader, trianglulate); + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, trianglulate); } -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, std::istream &inStream, - MaterialReader &readMatFn, bool triangulate) { +bool LoadObj(attrib_t *attrib, + std::vector *shapes, + std::vector *materials, + std::string *err, std::istream *inStream, + MaterialReader *readMatFn, bool triangulate) { std::stringstream errss; std::vector v; @@ -871,15 +852,15 @@ bool LoadObj(std::vector &shapes, // [output] // material std::map material_map; - std::map vertexCache; + //std::map vertexCache; int material = -1; shape_t shape; int maxchars = 8192; // Alloc enough size. std::vector buf(static_cast(maxchars)); // Alloc enough size. - while (inStream.peek() != -1) { - inStream.getline(&buf[0], maxchars); + while (inStream->peek() != -1) { + inStream->getline(&buf[0], maxchars); std::string linebuf(&buf[0]); @@ -985,8 +966,8 @@ bool LoadObj(std::vector &shapes, // [output] if (newMaterialId != material) { // Create per-face material - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, - material, name, true, triangulate); + exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, + material, name, triangulate); faceGroup.clear(); material = newMaterialId; } @@ -1005,8 +986,10 @@ bool LoadObj(std::vector &shapes, // [output] #endif std::string err_mtl; - bool ok = readMatFn(namebuf, materials, material_map, err_mtl); - err += err_mtl; + bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } if (!ok) { faceGroup.clear(); // for safety @@ -1021,10 +1004,10 @@ bool LoadObj(std::vector &shapes, // [output] // flush previous face group. bool ret = - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, - material, name, true, triangulate); + exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, + material, name, triangulate); if (ret) { - shapes.push_back(shape); + shapes->push_back(shape); } shape = shape_t(); @@ -1058,10 +1041,10 @@ bool LoadObj(std::vector &shapes, // [output] // flush previous face group. bool ret = - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, - material, name, true, triangulate); + exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, + material, name, triangulate); if (ret) { - shapes.push_back(shape); + shapes->push_back(shape); } // material = -1; @@ -1129,14 +1112,21 @@ bool LoadObj(std::vector &shapes, // [output] // Ignore unknown command. } - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, - tags, material, name, true, triangulate); + bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, + tags, material, name, triangulate); if (ret) { - shapes.push_back(shape); + shapes->push_back(shape); } faceGroup.clear(); // for safety - err += errss.str(); + if (err) { + (*err) += errss.str(); + } + + attrib->positions.swap(v); + attrib->normals.swap(vn); + attrib->texcoords.swap(vt); + return true; } From 54bd46014c20790d8c8cd19bb94cce2904cfb28a Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Sat, 16 Apr 2016 20:25:33 +0900 Subject: [PATCH 002/483] Use google C++ code style. --- .clang-format | 2 +- test.cc | 28 ++-- tiny_obj_loader.h | 391 +++++++++++++++++++++------------------------- 3 files changed, 197 insertions(+), 224 deletions(-) diff --git a/.clang-format b/.clang-format index a94a2c44..74210b03 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,5 @@ --- -BasedOnStyle: LLVM +BasedOnStyle: Google IndentWidth: 2 TabWidth: 2 UseTab: Never diff --git a/test.cc b/test.cc index 88d8be18..72b4fa21 100644 --- a/test.cc +++ b/test.cc @@ -10,18 +10,18 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector& shapes, const std::vector& materials, bool triangulate = true) { - std::cout << "# of positions : " << (attrib.positions.size() / 3) << std::endl; + std::cout << "# of vertices : " << (attrib.vertices.size() / 3) << std::endl; std::cout << "# of normals : " << (attrib.normals.size() / 3) << std::endl; std::cout << "# of texcoords : " << (attrib.texcoords.size() / 2) << std::endl; std::cout << "# of shapes : " << shapes.size() << std::endl; std::cout << "# of materials : " << materials.size() << std::endl; - for (size_t v = 0; v < attrib.positions.size() / 3; v++) { + for (size_t v = 0; v < attrib.vertices.size() / 3; v++) { printf(" v[%ld] = (%f, %f, %f)\n", v, - static_cast(attrib.positions[3*v+0]), - static_cast(attrib.positions[3*v+1]), - static_cast(attrib.positions[3*v+2])); + static_cast(attrib.vertices[3*v+0]), + static_cast(attrib.vertices[3*v+1]), + static_cast(attrib.vertices[3*v+2])); } for (size_t v = 0; v < attrib.normals.size() / 3; v++) { @@ -126,15 +126,15 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector(materials[i].ambient[0]), static_cast(materials[i].ambient[1]), static_cast(materials[i].ambient[2])); + printf(" material.Kd = (%f, %f ,%f)\n", static_cast(materials[i].diffuse[0]), static_cast(materials[i].diffuse[1]), static_cast(materials[i].diffuse[2])); + printf(" material.Ks = (%f, %f ,%f)\n", static_cast(materials[i].specular[0]), static_cast(materials[i].specular[1]), static_cast(materials[i].specular[2])); + printf(" material.Tr = (%f, %f ,%f)\n", static_cast(materials[i].transmittance[0]), static_cast(materials[i].transmittance[1]), static_cast(materials[i].transmittance[2])); + printf(" material.Ke = (%f, %f ,%f)\n", static_cast(materials[i].emission[0]), static_cast(materials[i].emission[1]), static_cast(materials[i].emission[2])); + printf(" material.Ns = %f\n", static_cast(materials[i].shininess)); + printf(" material.Ni = %f\n", static_cast(materials[i].ior)); + printf(" material.dissolve = %f\n", static_cast(materials[i].dissolve)); + printf(" material.illum = %d\n", materials[i].illum); printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str()); printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str()); printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str()); diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index b3a7589c..e67bed32 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -5,7 +5,8 @@ // // -// version devel : Change data structure. Support different index for vertex/normal/texcoord(#73, #39) +// version devel : Change data structure. Support different index for +// vertex/normal/texcoord(#73, #39) // version 0.9.20: Fixes creating per-face material using `usemtl`(#68) // version 0.9.17: Support n-polygon and crease tag(OpenSubdiv extension) // version 0.9.16: Make tinyobjloader header-only @@ -57,20 +58,20 @@ typedef struct { float transmittance[3]; float emission[3]; float shininess; - float ior; // index of refraction - float dissolve; // 1 == opaque; 0 == fully transparent + float ior; // index of refraction + float dissolve; // 1 == opaque; 0 == fully transparent // illumination model (see http://www.fileformat.info/format/material/) int illum; - int dummy; // Suppress padding warning. + int dummy; // Suppress padding warning. - std::string ambient_texname; // map_Ka - std::string diffuse_texname; // map_Kd - std::string specular_texname; // map_Ks - std::string specular_highlight_texname; // map_Ns - std::string bump_texname; // map_bump, bump - std::string displacement_texname; // disp - std::string alpha_texname; // map_d + std::string ambient_texname; // map_Ka + std::string diffuse_texname; // map_Kd + std::string specular_texname; // map_Ks + std::string specular_highlight_texname; // map_Ns + std::string bump_texname; // map_bump, bump + std::string displacement_texname; // disp + std::string alpha_texname; // map_d std::map unknown_parameter; } material_t; @@ -93,9 +94,9 @@ typedef struct { typedef struct { std::vector indices; std::vector - num_vertices; // The number of vertices per face. Up to 255. - std::vector material_ids; // per-face material ID - std::vector tags; // SubD tag + num_vertices; // The number of vertices per face. Up to 255. + std::vector material_ids; // per-face material ID + std::vector tags; // SubD tag } mesh_t; typedef struct { @@ -103,14 +104,15 @@ typedef struct { mesh_t mesh; } shape_t; +// Vertex attributes typedef struct { - std::vector positions; - std::vector normals; - std::vector texcoords; + std::vector vertices; // 'v' + std::vector normals; // 'vn' + std::vector texcoords; // 'vt' } attrib_t; class MaterialReader { -public: + public: MaterialReader() {} virtual ~MaterialReader(); @@ -121,15 +123,15 @@ class MaterialReader { }; class MaterialFileReader : public MaterialReader { -public: - MaterialFileReader(const std::string &mtl_basepath) + public: + explicit MaterialFileReader(const std::string &mtl_basepath) : m_mtlBasePath(mtl_basepath) {} virtual ~MaterialFileReader() {} virtual bool operator()(const std::string &matId, std::vector *materials, std::map *matMap, std::string *err); -private: + private: std::string m_mtlBasePath; }; @@ -142,10 +144,8 @@ class MaterialFileReader : public MaterialReader { /// 'mtl_basepath' is optional, and used for base path for .mtl file. /// 'triangulate' is optional, and used whether triangulate polygon face in .obj /// or not. -bool LoadObj(attrib_t *attrib, - std::vector *shapes, - std::vector *materials, - std::string *err, +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, const char *filename, const char *mtl_basepath = NULL, bool triangulate = true); @@ -153,18 +153,16 @@ bool LoadObj(attrib_t *attrib, /// std::istream for materials. /// Returns true when loading .obj become success. /// Returns warning and error message into `err` -bool LoadObj(attrib_t *attrib, - std::vector *shapes, - std::vector *materials, - std::string *err, +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, std::istream *inStream, MaterialReader *readMatFn, bool triangulate = true); /// Loads materials into std::map void LoadMtl(std::map *material_map, - std::vector *materials, - std::istream *inStream); -} + std::vector *materials, std::istream *inStream); + +} // namespace tinyobj #ifdef TINYOBJLOADER_IMPLEMENTATION #include @@ -173,12 +171,11 @@ void LoadMtl(std::map *material_map, #include #include #include +#include #include #include -#include "tiny_obj_loader.h" - namespace tinyobj { MaterialReader::~MaterialReader() {} @@ -202,12 +199,9 @@ struct tag_sizes { // for std::map static inline bool operator<(const vertex_index &a, const vertex_index &b) { - if (a.v_idx != b.v_idx) - return (a.v_idx < b.v_idx); - if (a.vn_idx != b.vn_idx) - return (a.vn_idx < b.vn_idx); - if (a.vt_idx != b.vt_idx) - return (a.vt_idx < b.vt_idx); + if (a.v_idx != b.v_idx) return (a.v_idx < b.v_idx); + if (a.vn_idx != b.vn_idx) return (a.vn_idx < b.vn_idx); + if (a.vt_idx != b.vt_idx) return (a.vt_idx < b.vt_idx); return false; } @@ -218,32 +212,31 @@ struct obj_shape { std::vector vt; }; -#define IS_SPACE( x ) ( ( (x) == ' ') || ( (x) == '\t') ) -#define IS_DIGIT( x ) ( static_cast( (x) - '0' ) < static_cast(10) ) -#define IS_NEW_LINE( x ) ( ( (x) == '\r') || ( (x) == '\n') || ( (x) == '\0') ) +#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) +#define IS_DIGIT(x) \ + (static_cast((x) - '0') < static_cast(10)) +#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) // Make index zero-base, and also support relative index. static inline int fixIndex(int idx, int n) { - if (idx > 0) - return idx - 1; - if (idx == 0) - return 0; - return n + idx; // negative value = relative + if (idx > 0) return idx - 1; + if (idx == 0) return 0; + return n + idx; // negative value = relative } -static inline std::string parseString(const char *&token) { +static inline std::string parseString(const char **token) { std::string s; - token += strspn(token, " \t"); - size_t e = strcspn(token, " \t\r"); - s = std::string(token, &token[e]); - token += e; + (*token) += strspn((*token), " \t"); + size_t e = strcspn((*token), " \t\r"); + s = std::string((*token), &(*token)[e]); + (*token) += e; return s; } -static inline int parseInt(const char *&token) { - token += strspn(token, " \t"); - int i = atoi(token); - token += strcspn(token, " \t\r"); +static inline int parseInt(const char **token) { + (*token) += strspn((*token), " \t"); + int i = atoi((*token)); + (*token) += strcspn((*token), " \t\r"); return i; } @@ -261,7 +254,7 @@ static inline int parseInt(const char *&token) { // float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; // // Valid strings are for example: -// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 +// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 // // If the parsing is a success, result is set to the parsed value and true // is returned. @@ -322,11 +315,9 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { } // We must make sure we actually got something. - if (read == 0) - goto fail; + if (read == 0) goto fail; // We allow numbers of form "#", "###" etc. - if (!end_not_reached) - goto assemble; + if (!end_not_reached) goto assemble; // Read the decimal part. if (*curr == '.') { @@ -343,8 +334,7 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { goto assemble; } - if (!end_not_reached) - goto assemble; + if (!end_not_reached) goto assemble; // Read the exponent part. if (*curr == 'e' || *curr == 'E') { @@ -367,8 +357,7 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { read++; } exponent *= (exp_sign == '+' ? 1 : -1); - if (read == 0) - goto fail; + if (read == 0) goto fail; } assemble: @@ -378,121 +367,118 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { fail: return false; } -static inline float parseFloat(const char *&token) { - token += strspn(token, " \t"); + +static inline float parseFloat(const char **token) { + (*token) += strspn((*token), " \t"); #ifdef TINY_OBJ_LOADER_OLD_FLOAT_PARSER - float f = (float)atof(token); - token += strcspn(token, " \t\r"); + float f = static_cast(atof(*token)); + (*token) += strcspn((*token), " \t\r"); #else - const char *end = token + strcspn(token, " \t\r"); + const char *end = (*token) + strcspn((*token), " \t\r"); double val = 0.0; - tryParseDouble(token, end, &val); + tryParseDouble((*token), end, &val); float f = static_cast(val); - token = end; + (*token) = end; #endif return f; } -static inline void parseFloat2(float &x, float &y, const char *&token) { - x = parseFloat(token); - y = parseFloat(token); +static inline void parseFloat2(float *x, float *y, const char **token) { + (*x) = parseFloat(token); + (*y) = parseFloat(token); } -static inline void parseFloat3(float &x, float &y, float &z, - const char *&token) { - x = parseFloat(token); - y = parseFloat(token); - z = parseFloat(token); +static inline void parseFloat3(float *x, float *y, float *z, + const char **token) { + (*x) = parseFloat(token); + (*y) = parseFloat(token); + (*z) = parseFloat(token); } -static tag_sizes parseTagTriple(const char *&token) { +static tag_sizes parseTagTriple(const char **token) { tag_sizes ts; - ts.num_ints = atoi(token); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { + ts.num_ints = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { return ts; } - token++; + (*token)++; - ts.num_floats = atoi(token); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { + ts.num_floats = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { return ts; } - token++; + (*token)++; - ts.num_strings = atoi(token); - token += strcspn(token, "/ \t\r") + 1; + ts.num_strings = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r") + 1; return ts; } // Parse triples: i, i/j/k, i//k, i/j -static vertex_index parseTriple(const char *&token, int vsize, int vnsize, +static vertex_index parseTriple(const char **token, int vsize, int vnsize, int vtsize) { vertex_index vi(-1); - vi.v_idx = fixIndex(atoi(token), vsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { + vi.v_idx = fixIndex(atoi((*token)), vsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { return vi; } - token++; + (*token)++; // i//k - if (token[0] == '/') { - token++; - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); return vi; } // i/j/k or i/j - vi.vt_idx = fixIndex(atoi(token), vtsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { + vi.vt_idx = fixIndex(atoi((*token)), vtsize); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { return vi; } // i/j/k - token++; // skip '/' - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); + (*token)++; // skip '/' + vi.vn_idx = fixIndex(atoi((*token)), vnsize); + (*token) += strcspn((*token), "/ \t\r"); return vi; } -static void InitMaterial(material_t &material) { - material.name = ""; - material.ambient_texname = ""; - material.diffuse_texname = ""; - material.specular_texname = ""; - material.specular_highlight_texname = ""; - material.bump_texname = ""; - material.displacement_texname = ""; - material.alpha_texname = ""; +static void InitMaterial(material_t *material) { + material->name = ""; + material->ambient_texname = ""; + material->diffuse_texname = ""; + material->specular_texname = ""; + material->specular_highlight_texname = ""; + material->bump_texname = ""; + material->displacement_texname = ""; + material->alpha_texname = ""; for (int i = 0; i < 3; i++) { - material.ambient[i] = 0.f; - material.diffuse[i] = 0.f; - material.specular[i] = 0.f; - material.transmittance[i] = 0.f; - material.emission[i] = 0.f; + material->ambient[i] = 0.f; + material->diffuse[i] = 0.f; + material->specular[i] = 0.f; + material->transmittance[i] = 0.f; + material->emission[i] = 0.f; } - material.illum = 0; - material.dissolve = 1.f; - material.shininess = 1.f; - material.ior = 1.f; - material.unknown_parameter.clear(); + material->illum = 0; + material->dissolve = 1.f; + material->shininess = 1.f; + material->ior = 1.f; + material->unknown_parameter.clear(); } static bool exportFaceGroupToShape( - shape_t &shape, - const std::vector &in_positions, - const std::vector &in_normals, - const std::vector &in_texcoords, - const std::vector > &faceGroup, - std::vector &tags, const int material_id, const std::string &name, - bool triangulate) { + shape_t *shape, const std::vector > &faceGroup, + const std::vector &tags, const int material_id, + const std::string &name, bool triangulate) { if (faceGroup.empty()) { return false; } @@ -508,7 +494,6 @@ static bool exportFaceGroupToShape( size_t npolys = face.size(); if (triangulate) { - // Polygon -> triangle fan conversion for (size_t k = 2; k < npolys; k++) { i1 = i2; @@ -525,15 +510,14 @@ static bool exportFaceGroupToShape( idx2.normal_index = i2.vn_idx; idx2.texcoord_index = i2.vt_idx; - shape.mesh.indices.push_back(idx0); - shape.mesh.indices.push_back(idx1); - shape.mesh.indices.push_back(idx2); + shape->mesh.indices.push_back(idx0); + shape->mesh.indices.push_back(idx1); + shape->mesh.indices.push_back(idx2); - shape.mesh.num_vertices.push_back(3); - shape.mesh.material_ids.push_back(material_id); + shape->mesh.num_vertices.push_back(3); + shape->mesh.material_ids.push_back(material_id); } } else { - for (size_t k = 0; k < npolys; k++) { index_t idx; idx.vertex_index = face[k].v_idx; @@ -541,26 +525,25 @@ static bool exportFaceGroupToShape( idx.texcoord_index = face[k].vt_idx; } - shape.mesh.num_vertices.push_back(static_cast(npolys)); - shape.mesh.material_ids.push_back(material_id); // per face + shape->mesh.num_vertices.push_back(static_cast(npolys)); + shape->mesh.material_ids.push_back(material_id); // per face } } - shape.name = name; - shape.mesh.tags.swap(tags); + shape->name = name; + shape->mesh.tags = tags; return true; } void LoadMtl(std::map *material_map, std::vector *materials, std::istream *inStream) { - // Create a default material anyway. material_t material; - InitMaterial(material); + InitMaterial(&material); - size_t maxchars = 8192; // Alloc enough size. - std::vector buf(maxchars); // Alloc enough size. + size_t maxchars = 8192; // Alloc enough size. + std::vector buf(maxchars); // Alloc enough size. while (inStream->peek() != -1) { inStream->getline(&buf[0], static_cast(maxchars)); @@ -586,11 +569,9 @@ void LoadMtl(std::map *material_map, token += strspn(token, " \t"); assert(token); - if (token[0] == '\0') - continue; // empty line + if (token[0] == '\0') continue; // empty line - if (token[0] == '#') - continue; // comment line + if (token[0] == '#') continue; // comment line // new mtl if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { @@ -602,7 +583,7 @@ void LoadMtl(std::map *material_map, } // initial temporary material - InitMaterial(material); + InitMaterial(&material); // set new mtl name char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; @@ -620,7 +601,7 @@ void LoadMtl(std::map *material_map, if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { token += 2; float r, g, b; - parseFloat3(r, g, b, token); + parseFloat3(&r, &g, &b, &token); material.ambient[0] = r; material.ambient[1] = g; material.ambient[2] = b; @@ -631,7 +612,7 @@ void LoadMtl(std::map *material_map, if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { token += 2; float r, g, b; - parseFloat3(r, g, b, token); + parseFloat3(&r, &g, &b, &token); material.diffuse[0] = r; material.diffuse[1] = g; material.diffuse[2] = b; @@ -642,7 +623,7 @@ void LoadMtl(std::map *material_map, if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { token += 2; float r, g, b; - parseFloat3(r, g, b, token); + parseFloat3(&r, &g, &b, &token); material.specular[0] = r; material.specular[1] = g; material.specular[2] = b; @@ -653,7 +634,7 @@ void LoadMtl(std::map *material_map, if (token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) { token += 2; float r, g, b; - parseFloat3(r, g, b, token); + parseFloat3(&r, &g, &b, &token); material.transmittance[0] = r; material.transmittance[1] = g; material.transmittance[2] = b; @@ -663,7 +644,7 @@ void LoadMtl(std::map *material_map, // ior(index of refraction) if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { token += 2; - material.ior = parseFloat(token); + material.ior = parseFloat(&token); continue; } @@ -671,7 +652,7 @@ void LoadMtl(std::map *material_map, if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { token += 2; float r, g, b; - parseFloat3(r, g, b, token); + parseFloat3(&r, &g, &b, &token); material.emission[0] = r; material.emission[1] = g; material.emission[2] = b; @@ -681,27 +662,27 @@ void LoadMtl(std::map *material_map, // shininess if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { token += 2; - material.shininess = parseFloat(token); + material.shininess = parseFloat(&token); continue; } // illum model if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { token += 6; - material.illum = parseInt(token); + material.illum = parseInt(&token); continue; } // dissolve if ((token[0] == 'd' && IS_SPACE(token[1]))) { token += 1; - material.dissolve = parseFloat(token); + material.dissolve = parseFloat(&token); continue; } if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { token += 2; // Invert value of Tr(assume Tr is in range [0, 1]) - material.dissolve = 1.0f - parseFloat(token); + material.dissolve = 1.0f - parseFloat(&token); continue; } @@ -805,13 +786,11 @@ bool MaterialFileReader::operator()(const std::string &matId, return true; } -bool LoadObj(attrib_t *attrib, - std::vector *shapes, - std::vector *materials, - std::string *err, const char *filename, const char *mtl_basepath, +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + const char *filename, const char *mtl_basepath, bool trianglulate) { - - attrib->positions.clear(); + attrib->vertices.clear(); attrib->normals.clear(); attrib->texcoords.clear(); shapes->clear(); @@ -833,14 +812,14 @@ bool LoadObj(attrib_t *attrib, } MaterialFileReader matFileReader(basePath); - return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, trianglulate); + return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader, + trianglulate); } -bool LoadObj(attrib_t *attrib, - std::vector *shapes, - std::vector *materials, - std::string *err, std::istream *inStream, - MaterialReader *readMatFn, bool triangulate) { +bool LoadObj(attrib_t *attrib, std::vector *shapes, + std::vector *materials, std::string *err, + std::istream *inStream, MaterialReader *readMatFn, + bool triangulate) { std::stringstream errss; std::vector v; @@ -852,13 +831,13 @@ bool LoadObj(attrib_t *attrib, // material std::map material_map; - //std::map vertexCache; + // std::map vertexCache; int material = -1; shape_t shape; - int maxchars = 8192; // Alloc enough size. - std::vector buf(static_cast(maxchars)); // Alloc enough size. + int maxchars = 8192; // Alloc enough size. + std::vector buf(static_cast(maxchars)); // Alloc enough size. while (inStream->peek() != -1) { inStream->getline(&buf[0], maxchars); @@ -884,17 +863,15 @@ bool LoadObj(attrib_t *attrib, token += strspn(token, " \t"); assert(token); - if (token[0] == '\0') - continue; // empty line + if (token[0] == '\0') continue; // empty line - if (token[0] == '#') - continue; // comment line + if (token[0] == '#') continue; // comment line // vertex if (token[0] == 'v' && IS_SPACE((token[1]))) { token += 2; float x, y, z; - parseFloat3(x, y, z, token); + parseFloat3(&x, &y, &z, &token); v.push_back(x); v.push_back(y); v.push_back(z); @@ -905,7 +882,7 @@ bool LoadObj(attrib_t *attrib, if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { token += 3; float x, y, z; - parseFloat3(x, y, z, token); + parseFloat3(&x, &y, &z, &token); vn.push_back(x); vn.push_back(y); vn.push_back(z); @@ -916,7 +893,7 @@ bool LoadObj(attrib_t *attrib, if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { token += 3; float x, y; - parseFloat2(x, y, token); + parseFloat2(&x, &y, &token); vt.push_back(x); vt.push_back(y); continue; @@ -931,7 +908,7 @@ bool LoadObj(attrib_t *attrib, face.reserve(3); while (!IS_NEW_LINE(token[0])) { - vertex_index vi = parseTriple(token, static_cast(v.size() / 3), + vertex_index vi = parseTriple(&token, static_cast(v.size() / 3), static_cast(vn.size() / 3), static_cast(vt.size() / 2)); face.push_back(vi); @@ -948,7 +925,6 @@ bool LoadObj(attrib_t *attrib, // use mtl if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { - char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; token += 7; #ifdef _MSC_VER @@ -966,8 +942,8 @@ bool LoadObj(attrib_t *attrib, if (newMaterialId != material) { // Create per-face material - exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, - material, name, triangulate); + exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); faceGroup.clear(); material = newMaterialId; } @@ -992,7 +968,7 @@ bool LoadObj(attrib_t *attrib, } if (!ok) { - faceGroup.clear(); // for safety + faceGroup.clear(); // for safety return false; } @@ -1001,11 +977,9 @@ bool LoadObj(attrib_t *attrib, // group name if (token[0] == 'g' && IS_SPACE((token[1]))) { - // flush previous face group. - bool ret = - exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, - material, name, triangulate); + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); if (ret) { shapes->push_back(shape); } @@ -1019,9 +993,9 @@ bool LoadObj(attrib_t *attrib, names.reserve(2); while (!IS_NEW_LINE(token[0])) { - std::string str = parseString(token); + std::string str = parseString(&token); names.push_back(str); - token += strspn(token, " \t\r"); // skip tag + token += strspn(token, " \t\r"); // skip tag } assert(names.size() > 0); @@ -1038,11 +1012,9 @@ bool LoadObj(attrib_t *attrib, // object name if (token[0] == 'o' && IS_SPACE((token[1]))) { - // flush previous face group. - bool ret = - exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, - material, name, triangulate); + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); if (ret) { shapes->push_back(shape); } @@ -1078,7 +1050,7 @@ bool LoadObj(attrib_t *attrib, token += tag.name.size() + 1; - tag_sizes ts = parseTagTriple(token); + tag_sizes ts = parseTagTriple(&token); tag.intValues.resize(static_cast(ts.num_ints)); @@ -1089,7 +1061,7 @@ bool LoadObj(attrib_t *attrib, tag.floatValues.resize(static_cast(ts.num_floats)); for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { - tag.floatValues[i] = parseFloat(token); + tag.floatValues[i] = parseFloat(&token); token += strcspn(token, "/ \t\r") + 1; } @@ -1098,7 +1070,8 @@ bool LoadObj(attrib_t *attrib, char stringValueBuffer[4096]; #ifdef _MSC_VER - sscanf_s(token, "%s", stringValueBuffer, (unsigned)_countof(stringValueBuffer)); + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); #else sscanf(token, "%s", stringValueBuffer); #endif @@ -1112,26 +1085,26 @@ bool LoadObj(attrib_t *attrib, // Ignore unknown command. } - bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, - tags, material, name, triangulate); + bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name, + triangulate); if (ret) { shapes->push_back(shape); } - faceGroup.clear(); // for safety + faceGroup.clear(); // for safety if (err) { (*err) += errss.str(); } - attrib->positions.swap(v); + attrib->vertices.swap(v); attrib->normals.swap(vn); attrib->texcoords.swap(vt); return true; } -} // namespace +} // namespace tinyobj #endif -#endif // TINY_OBJ_LOADER_H_ +#endif // TINY_OBJ_LOADER_H_ From 72ef6cbb76bea690288f20e9d6fa61241ee3e0be Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 18 Apr 2016 16:03:24 +0900 Subject: [PATCH 003/483] Add initial unit test codes using Catch. Add Kuroga build script. --- build.ninja | 8 +- deps/cpplint.py | 6323 ++++++++++++ test.cc => loader_example.cc | 4 +- cornell_box.mtl => models/cornell_box.mtl | 0 cornell_box.obj => models/cornell_box.obj | 0 premake4.lua | 6 +- tests/Makefile | 13 + tests/README.md | 25 + tests/catch.hpp | 10445 ++++++++++++++++++++ tests/config-msvc.py | 52 + tests/config-posix.py | 53 + tests/kuroga.py | 312 + tests/tester.cc | 324 + tests/vcbuild.bat | 3 + tiny_obj_loader.h | 340 +- 15 files changed, 17897 insertions(+), 11 deletions(-) create mode 100755 deps/cpplint.py rename test.cc => loader_example.cc (98%) rename cornell_box.mtl => models/cornell_box.mtl (100%) rename cornell_box.obj => models/cornell_box.obj (100%) create mode 100644 tests/Makefile create mode 100644 tests/README.md create mode 100644 tests/catch.hpp create mode 100644 tests/config-msvc.py create mode 100644 tests/config-posix.py create mode 100755 tests/kuroga.py create mode 100644 tests/tester.cc create mode 100644 tests/vcbuild.bat diff --git a/build.ninja b/build.ninja index 3a26d974..5048ff1d 100644 --- a/build.ninja +++ b/build.ninja @@ -3,6 +3,8 @@ cc = clang cxx = clang++ cflags = -Werror -Weverything cxxflags = -Werror -Weverything +#cflags = -O2 +#cxxflags = -O2 rule compile command = $cxx $cxxflags -c $in -o $out @@ -10,7 +12,7 @@ rule compile rule link command = $cxx $in -o $out -build test.o: compile test.cc -build test: link test.o +build loader_example.o: compile loader_example.cc +build loader_example: link loader_example.o -default test +default loader_example diff --git a/deps/cpplint.py b/deps/cpplint.py new file mode 100755 index 00000000..ccc25d4c --- /dev/null +++ b/deps/cpplint.py @@ -0,0 +1,6323 @@ +#!/usr/bin/env python +# +# Copyright (c) 2009 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Does google-lint on c++ files. + +The goal of this script is to identify places in the code that *may* +be in non-compliance with google style. It does not attempt to fix +up these problems -- the point is to educate. It does also not +attempt to find all problems, or to ensure that everything it does +find is legitimately a problem. + +In particular, we can get very confused by /* and // inside strings! +We do a small hack, which is to ignore //'s with "'s after them on the +same line, but it is far from perfect (in either direction). +""" + +import codecs +import copy +import getopt +import math # for log +import os +import re +import sre_compile +import string +import sys +import unicodedata + + +_USAGE = """ +Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] + [--counting=total|toplevel|detailed] [--root=subdir] + [--linelength=digits] + [file] ... + + The style guidelines this tries to follow are those in + http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml + + Every problem is given a confidence score from 1-5, with 5 meaning we are + certain of the problem, and 1 meaning it could be a legitimate construct. + This will miss some errors, and is not a substitute for a code review. + + To suppress false-positive errors of a certain category, add a + 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) + suppresses errors of all categories on that line. + + The files passed in will be linted; at least one file must be provided. + Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the + extensions with the --extensions flag. + + Flags: + + output=vs7 + By default, the output is formatted to ease emacs parsing. Visual Studio + compatible output (vs7) may also be used. Other formats are unsupported. + + verbose=# + Specify a number 0-5 to restrict errors to certain verbosity levels. + + filter=-x,+y,... + Specify a comma-separated list of category-filters to apply: only + error messages whose category names pass the filters will be printed. + (Category names are printed with the message and look like + "[whitespace/indent]".) Filters are evaluated left to right. + "-FOO" and "FOO" means "do not print categories that start with FOO". + "+FOO" means "do print categories that start with FOO". + + Examples: --filter=-whitespace,+whitespace/braces + --filter=whitespace,runtime/printf,+runtime/printf_format + --filter=-,+build/include_what_you_use + + To see a list of all the categories used in cpplint, pass no arg: + --filter= + + counting=total|toplevel|detailed + The total number of errors found is always printed. If + 'toplevel' is provided, then the count of errors in each of + the top-level categories like 'build' and 'whitespace' will + also be printed. If 'detailed' is provided, then a count + is provided for each category like 'build/class'. + + root=subdir + The root directory used for deriving header guard CPP variable. + By default, the header guard CPP variable is calculated as the relative + path to the directory that contains .git, .hg, or .svn. When this flag + is specified, the relative path is calculated from the specified + directory. If the specified directory does not exist, this flag is + ignored. + + Examples: + Assuming that src/.git exists, the header guard CPP variables for + src/chrome/browser/ui/browser.h are: + + No flag => CHROME_BROWSER_UI_BROWSER_H_ + --root=chrome => BROWSER_UI_BROWSER_H_ + --root=chrome/browser => UI_BROWSER_H_ + + linelength=digits + This is the allowed line length for the project. The default value is + 80 characters. + + Examples: + --linelength=120 + + extensions=extension,extension,... + The allowed file extensions that cpplint will check + + Examples: + --extensions=hpp,cpp + + cpplint.py supports per-directory configurations specified in CPPLINT.cfg + files. CPPLINT.cfg file can contain a number of key=value pairs. + Currently the following options are supported: + + set noparent + filter=+filter1,-filter2,... + exclude_files=regex + linelength=80 + + "set noparent" option prevents cpplint from traversing directory tree + upwards looking for more .cfg files in parent directories. This option + is usually placed in the top-level project directory. + + The "filter" option is similar in function to --filter flag. It specifies + message filters in addition to the |_DEFAULT_FILTERS| and those specified + through --filter command-line flag. + + "exclude_files" allows to specify a regular expression to be matched against + a file name. If the expression matches, the file is skipped and not run + through liner. + + "linelength" allows to specify the allowed line length for the project. + + CPPLINT.cfg has an effect on files in the same directory and all + sub-directories, unless overridden by a nested configuration file. + + Example file: + filter=-build/include_order,+build/include_alpha + exclude_files=.*\.cc + + The above example disables build/include_order warning and enables + build/include_alpha as well as excludes all .cc from being + processed by linter, in the current directory (where the .cfg + file is located) and all sub-directories. +""" + +# We categorize each error message we print. Here are the categories. +# We want an explicit list so we can list them all in cpplint --filter=. +# If you add a new error message with a new category, add it to the list +# here! cpplint_unittest.py should tell you if you forget to do this. +_ERROR_CATEGORIES = [ + 'build/class', + 'build/c++11', + 'build/deprecated', + 'build/endif_comment', + 'build/explicit_make_pair', + 'build/forward_decl', + 'build/header_guard', + 'build/include', + 'build/include_alpha', + 'build/include_order', + 'build/include_what_you_use', + 'build/namespaces', + 'build/printf_format', + 'build/storage_class', + 'legal/copyright', + 'readability/alt_tokens', + 'readability/braces', + 'readability/casting', + 'readability/check', + 'readability/constructors', + 'readability/fn_size', + 'readability/function', + 'readability/inheritance', + 'readability/multiline_comment', + 'readability/multiline_string', + 'readability/namespace', + 'readability/nolint', + 'readability/nul', + 'readability/strings', + 'readability/todo', + 'readability/utf8', + 'runtime/arrays', + 'runtime/casting', + 'runtime/explicit', + 'runtime/int', + 'runtime/init', + 'runtime/invalid_increment', + 'runtime/member_string_references', + 'runtime/memset', + 'runtime/indentation_namespace', + 'runtime/operator', + 'runtime/printf', + 'runtime/printf_format', + 'runtime/references', + 'runtime/string', + 'runtime/threadsafe_fn', + 'runtime/vlog', + 'whitespace/blank_line', + 'whitespace/braces', + 'whitespace/comma', + 'whitespace/comments', + 'whitespace/empty_conditional_body', + 'whitespace/empty_loop_body', + 'whitespace/end_of_line', + 'whitespace/ending_newline', + 'whitespace/forcolon', + 'whitespace/indent', + 'whitespace/line_length', + 'whitespace/newline', + 'whitespace/operators', + 'whitespace/parens', + 'whitespace/semicolon', + 'whitespace/tab', + 'whitespace/todo', + ] + +# These error categories are no longer enforced by cpplint, but for backwards- +# compatibility they may still appear in NOLINT comments. +_LEGACY_ERROR_CATEGORIES = [ + 'readability/streams', + ] + +# The default state of the category filter. This is overridden by the --filter= +# flag. By default all errors are on, so only add here categories that should be +# off by default (i.e., categories that must be enabled by the --filter= flags). +# All entries here should start with a '-' or '+', as in the --filter= flag. +_DEFAULT_FILTERS = ['-build/include_alpha'] + +# We used to check for high-bit characters, but after much discussion we +# decided those were OK, as long as they were in UTF-8 and didn't represent +# hard-coded international strings, which belong in a separate i18n file. + +# C++ headers +_CPP_HEADERS = frozenset([ + # Legacy + 'algobase.h', + 'algo.h', + 'alloc.h', + 'builtinbuf.h', + 'bvector.h', + 'complex.h', + 'defalloc.h', + 'deque.h', + 'editbuf.h', + 'fstream.h', + 'function.h', + 'hash_map', + 'hash_map.h', + 'hash_set', + 'hash_set.h', + 'hashtable.h', + 'heap.h', + 'indstream.h', + 'iomanip.h', + 'iostream.h', + 'istream.h', + 'iterator.h', + 'list.h', + 'map.h', + 'multimap.h', + 'multiset.h', + 'ostream.h', + 'pair.h', + 'parsestream.h', + 'pfstream.h', + 'procbuf.h', + 'pthread_alloc', + 'pthread_alloc.h', + 'rope', + 'rope.h', + 'ropeimpl.h', + 'set.h', + 'slist', + 'slist.h', + 'stack.h', + 'stdiostream.h', + 'stl_alloc.h', + 'stl_relops.h', + 'streambuf.h', + 'stream.h', + 'strfile.h', + 'strstream.h', + 'tempbuf.h', + 'tree.h', + 'type_traits.h', + 'vector.h', + # 17.6.1.2 C++ library headers + 'algorithm', + 'array', + 'atomic', + 'bitset', + 'chrono', + 'codecvt', + 'complex', + 'condition_variable', + 'deque', + 'exception', + 'forward_list', + 'fstream', + 'functional', + 'future', + 'initializer_list', + 'iomanip', + 'ios', + 'iosfwd', + 'iostream', + 'istream', + 'iterator', + 'limits', + 'list', + 'locale', + 'map', + 'memory', + 'mutex', + 'new', + 'numeric', + 'ostream', + 'queue', + 'random', + 'ratio', + 'regex', + 'set', + 'sstream', + 'stack', + 'stdexcept', + 'streambuf', + 'string', + 'strstream', + 'system_error', + 'thread', + 'tuple', + 'typeindex', + 'typeinfo', + 'type_traits', + 'unordered_map', + 'unordered_set', + 'utility', + 'valarray', + 'vector', + # 17.6.1.2 C++ headers for C library facilities + 'cassert', + 'ccomplex', + 'cctype', + 'cerrno', + 'cfenv', + 'cfloat', + 'cinttypes', + 'ciso646', + 'climits', + 'clocale', + 'cmath', + 'csetjmp', + 'csignal', + 'cstdalign', + 'cstdarg', + 'cstdbool', + 'cstddef', + 'cstdint', + 'cstdio', + 'cstdlib', + 'cstring', + 'ctgmath', + 'ctime', + 'cuchar', + 'cwchar', + 'cwctype', + ]) + + +# These headers are excluded from [build/include] and [build/include_order] +# checks: +# - Anything not following google file name conventions (containing an +# uppercase character, such as Python.h or nsStringAPI.h, for example). +# - Lua headers. +_THIRD_PARTY_HEADERS_PATTERN = re.compile( + r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$') + + +# Assertion macros. These are defined in base/logging.h and +# testing/base/gunit.h. Note that the _M versions need to come first +# for substring matching to work. +_CHECK_MACROS = [ + 'DCHECK', 'CHECK', + 'EXPECT_TRUE_M', 'EXPECT_TRUE', + 'ASSERT_TRUE_M', 'ASSERT_TRUE', + 'EXPECT_FALSE_M', 'EXPECT_FALSE', + 'ASSERT_FALSE_M', 'ASSERT_FALSE', + ] + +# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE +_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) + +for op, replacement in [('==', 'EQ'), ('!=', 'NE'), + ('>=', 'GE'), ('>', 'GT'), + ('<=', 'LE'), ('<', 'LT')]: + _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement + _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement + _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement + _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement + _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement + _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement + +for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), + ('>=', 'LT'), ('>', 'LE'), + ('<=', 'GT'), ('<', 'GE')]: + _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement + _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement + _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement + _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement + +# Alternative tokens and their replacements. For full list, see section 2.5 +# Alternative tokens [lex.digraph] in the C++ standard. +# +# Digraphs (such as '%:') are not included here since it's a mess to +# match those on a word boundary. +_ALT_TOKEN_REPLACEMENT = { + 'and': '&&', + 'bitor': '|', + 'or': '||', + 'xor': '^', + 'compl': '~', + 'bitand': '&', + 'and_eq': '&=', + 'or_eq': '|=', + 'xor_eq': '^=', + 'not': '!', + 'not_eq': '!=' + } + +# Compile regular expression that matches all the above keywords. The "[ =()]" +# bit is meant to avoid matching these keywords outside of boolean expressions. +# +# False positives include C-style multi-line comments and multi-line strings +# but those have always been troublesome for cpplint. +_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( + r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') + + +# These constants define types of headers for use with +# _IncludeState.CheckNextIncludeOrder(). +_C_SYS_HEADER = 1 +_CPP_SYS_HEADER = 2 +_LIKELY_MY_HEADER = 3 +_POSSIBLE_MY_HEADER = 4 +_OTHER_HEADER = 5 + +# These constants define the current inline assembly state +_NO_ASM = 0 # Outside of inline assembly block +_INSIDE_ASM = 1 # Inside inline assembly block +_END_ASM = 2 # Last line of inline assembly block +_BLOCK_ASM = 3 # The whole block is an inline assembly block + +# Match start of assembly blocks +_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)' + r'(?:\s+(volatile|__volatile__))?' + r'\s*[{(]') + + +_regexp_compile_cache = {} + +# {str, set(int)}: a map from error categories to sets of linenumbers +# on which those errors are expected and should be suppressed. +_error_suppressions = {} + +# The root directory used for deriving header guard CPP variable. +# This is set by --root flag. +_root = None + +# The allowed line length of files. +# This is set by --linelength flag. +_line_length = 80 + +# The allowed extensions for file names +# This is set by --extensions flag. +_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh']) + +def ParseNolintSuppressions(filename, raw_line, linenum, error): + """Updates the global list of error-suppressions. + + Parses any NOLINT comments on the current line, updating the global + error_suppressions store. Reports an error if the NOLINT comment + was malformed. + + Args: + filename: str, the name of the input file. + raw_line: str, the line of input text, with comments. + linenum: int, the number of the current line. + error: function, an error handler. + """ + matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line) + if matched: + if matched.group(1): + suppressed_line = linenum + 1 + else: + suppressed_line = linenum + category = matched.group(2) + if category in (None, '(*)'): # => "suppress all" + _error_suppressions.setdefault(None, set()).add(suppressed_line) + else: + if category.startswith('(') and category.endswith(')'): + category = category[1:-1] + if category in _ERROR_CATEGORIES: + _error_suppressions.setdefault(category, set()).add(suppressed_line) + elif category not in _LEGACY_ERROR_CATEGORIES: + error(filename, linenum, 'readability/nolint', 5, + 'Unknown NOLINT error category: %s' % category) + + +def ResetNolintSuppressions(): + """Resets the set of NOLINT suppressions to empty.""" + _error_suppressions.clear() + + +def IsErrorSuppressedByNolint(category, linenum): + """Returns true if the specified error category is suppressed on this line. + + Consults the global error_suppressions map populated by + ParseNolintSuppressions/ResetNolintSuppressions. + + Args: + category: str, the category of the error. + linenum: int, the current line number. + Returns: + bool, True iff the error should be suppressed due to a NOLINT comment. + """ + return (linenum in _error_suppressions.get(category, set()) or + linenum in _error_suppressions.get(None, set())) + + +def Match(pattern, s): + """Matches the string with the pattern, caching the compiled regexp.""" + # The regexp compilation caching is inlined in both Match and Search for + # performance reasons; factoring it out into a separate function turns out + # to be noticeably expensive. + if pattern not in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].match(s) + + +def ReplaceAll(pattern, rep, s): + """Replaces instances of pattern in a string with a replacement. + + The compiled regex is kept in a cache shared by Match and Search. + + Args: + pattern: regex pattern + rep: replacement text + s: search string + + Returns: + string with replacements made (or original string if no replacements) + """ + if pattern not in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].sub(rep, s) + + +def Search(pattern, s): + """Searches the string for the pattern, caching the compiled regexp.""" + if pattern not in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].search(s) + + +class _IncludeState(object): + """Tracks line numbers for includes, and the order in which includes appear. + + include_list contains list of lists of (header, line number) pairs. + It's a lists of lists rather than just one flat list to make it + easier to update across preprocessor boundaries. + + Call CheckNextIncludeOrder() once for each header in the file, passing + in the type constants defined above. Calls in an illegal order will + raise an _IncludeError with an appropriate error message. + + """ + # self._section will move monotonically through this set. If it ever + # needs to move backwards, CheckNextIncludeOrder will raise an error. + _INITIAL_SECTION = 0 + _MY_H_SECTION = 1 + _C_SECTION = 2 + _CPP_SECTION = 3 + _OTHER_H_SECTION = 4 + + _TYPE_NAMES = { + _C_SYS_HEADER: 'C system header', + _CPP_SYS_HEADER: 'C++ system header', + _LIKELY_MY_HEADER: 'header this file implements', + _POSSIBLE_MY_HEADER: 'header this file may implement', + _OTHER_HEADER: 'other header', + } + _SECTION_NAMES = { + _INITIAL_SECTION: "... nothing. (This can't be an error.)", + _MY_H_SECTION: 'a header this file implements', + _C_SECTION: 'C system header', + _CPP_SECTION: 'C++ system header', + _OTHER_H_SECTION: 'other header', + } + + def __init__(self): + self.include_list = [[]] + self.ResetSection('') + + def FindHeader(self, header): + """Check if a header has already been included. + + Args: + header: header to check. + Returns: + Line number of previous occurrence, or -1 if the header has not + been seen before. + """ + for section_list in self.include_list: + for f in section_list: + if f[0] == header: + return f[1] + return -1 + + def ResetSection(self, directive): + """Reset section checking for preprocessor directive. + + Args: + directive: preprocessor directive (e.g. "if", "else"). + """ + # The name of the current section. + self._section = self._INITIAL_SECTION + # The path of last found header. + self._last_header = '' + + # Update list of includes. Note that we never pop from the + # include list. + if directive in ('if', 'ifdef', 'ifndef'): + self.include_list.append([]) + elif directive in ('else', 'elif'): + self.include_list[-1] = [] + + def SetLastHeader(self, header_path): + self._last_header = header_path + + def CanonicalizeAlphabeticalOrder(self, header_path): + """Returns a path canonicalized for alphabetical comparison. + + - replaces "-" with "_" so they both cmp the same. + - removes '-inl' since we don't require them to be after the main header. + - lowercase everything, just in case. + + Args: + header_path: Path to be canonicalized. + + Returns: + Canonicalized path. + """ + return header_path.replace('-inl.h', '.h').replace('-', '_').lower() + + def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path): + """Check if a header is in alphabetical order with the previous header. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + header_path: Canonicalized header to be checked. + + Returns: + Returns true if the header is in alphabetical order. + """ + # If previous section is different from current section, _last_header will + # be reset to empty string, so it's always less than current header. + # + # If previous line was a blank line, assume that the headers are + # intentionally sorted the way they are. + if (self._last_header > header_path and + Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])): + return False + return True + + def CheckNextIncludeOrder(self, header_type): + """Returns a non-empty error message if the next header is out of order. + + This function also updates the internal state to be ready to check + the next include. + + Args: + header_type: One of the _XXX_HEADER constants defined above. + + Returns: + The empty string if the header is in the right order, or an + error message describing what's wrong. + + """ + error_message = ('Found %s after %s' % + (self._TYPE_NAMES[header_type], + self._SECTION_NAMES[self._section])) + + last_section = self._section + + if header_type == _C_SYS_HEADER: + if self._section <= self._C_SECTION: + self._section = self._C_SECTION + else: + self._last_header = '' + return error_message + elif header_type == _CPP_SYS_HEADER: + if self._section <= self._CPP_SECTION: + self._section = self._CPP_SECTION + else: + self._last_header = '' + return error_message + elif header_type == _LIKELY_MY_HEADER: + if self._section <= self._MY_H_SECTION: + self._section = self._MY_H_SECTION + else: + self._section = self._OTHER_H_SECTION + elif header_type == _POSSIBLE_MY_HEADER: + if self._section <= self._MY_H_SECTION: + self._section = self._MY_H_SECTION + else: + # This will always be the fallback because we're not sure + # enough that the header is associated with this file. + self._section = self._OTHER_H_SECTION + else: + assert header_type == _OTHER_HEADER + self._section = self._OTHER_H_SECTION + + if last_section != self._section: + self._last_header = '' + + return '' + + +class _CppLintState(object): + """Maintains module-wide state..""" + + def __init__(self): + self.verbose_level = 1 # global setting. + self.error_count = 0 # global count of reported errors + # filters to apply when emitting error messages + self.filters = _DEFAULT_FILTERS[:] + # backup of filter list. Used to restore the state after each file. + self._filters_backup = self.filters[:] + self.counting = 'total' # In what way are we counting errors? + self.errors_by_category = {} # string to int dict storing error counts + + # output format: + # "emacs" - format that emacs can parse (default) + # "vs7" - format that Microsoft Visual Studio 7 can parse + self.output_format = 'emacs' + + def SetOutputFormat(self, output_format): + """Sets the output format for errors.""" + self.output_format = output_format + + def SetVerboseLevel(self, level): + """Sets the module's verbosity, and returns the previous setting.""" + last_verbose_level = self.verbose_level + self.verbose_level = level + return last_verbose_level + + def SetCountingStyle(self, counting_style): + """Sets the module's counting options.""" + self.counting = counting_style + + def SetFilters(self, filters): + """Sets the error-message filters. + + These filters are applied when deciding whether to emit a given + error message. + + Args: + filters: A string of comma-separated filters (eg "+whitespace/indent"). + Each filter should start with + or -; else we die. + + Raises: + ValueError: The comma-separated filters did not all start with '+' or '-'. + E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" + """ + # Default filters always have less priority than the flag ones. + self.filters = _DEFAULT_FILTERS[:] + self.AddFilters(filters) + + def AddFilters(self, filters): + """ Adds more filters to the existing list of error-message filters. """ + for filt in filters.split(','): + clean_filt = filt.strip() + if clean_filt: + self.filters.append(clean_filt) + for filt in self.filters: + if not (filt.startswith('+') or filt.startswith('-')): + raise ValueError('Every filter in --filters must start with + or -' + ' (%s does not)' % filt) + + def BackupFilters(self): + """ Saves the current filter list to backup storage.""" + self._filters_backup = self.filters[:] + + def RestoreFilters(self): + """ Restores filters previously backed up.""" + self.filters = self._filters_backup[:] + + def ResetErrorCounts(self): + """Sets the module's error statistic back to zero.""" + self.error_count = 0 + self.errors_by_category = {} + + def IncrementErrorCount(self, category): + """Bumps the module's error statistic.""" + self.error_count += 1 + if self.counting in ('toplevel', 'detailed'): + if self.counting != 'detailed': + category = category.split('/')[0] + if category not in self.errors_by_category: + self.errors_by_category[category] = 0 + self.errors_by_category[category] += 1 + + def PrintErrorCounts(self): + """Print a summary of errors by category, and the total.""" + for category, count in self.errors_by_category.iteritems(): + sys.stderr.write('Category \'%s\' errors found: %d\n' % + (category, count)) + sys.stderr.write('Total errors found: %d\n' % self.error_count) + +_cpplint_state = _CppLintState() + + +def _OutputFormat(): + """Gets the module's output format.""" + return _cpplint_state.output_format + + +def _SetOutputFormat(output_format): + """Sets the module's output format.""" + _cpplint_state.SetOutputFormat(output_format) + + +def _VerboseLevel(): + """Returns the module's verbosity setting.""" + return _cpplint_state.verbose_level + + +def _SetVerboseLevel(level): + """Sets the module's verbosity, and returns the previous setting.""" + return _cpplint_state.SetVerboseLevel(level) + + +def _SetCountingStyle(level): + """Sets the module's counting options.""" + _cpplint_state.SetCountingStyle(level) + + +def _Filters(): + """Returns the module's list of output filters, as a list.""" + return _cpplint_state.filters + + +def _SetFilters(filters): + """Sets the module's error-message filters. + + These filters are applied when deciding whether to emit a given + error message. + + Args: + filters: A string of comma-separated filters (eg "whitespace/indent"). + Each filter should start with + or -; else we die. + """ + _cpplint_state.SetFilters(filters) + +def _AddFilters(filters): + """Adds more filter overrides. + + Unlike _SetFilters, this function does not reset the current list of filters + available. + + Args: + filters: A string of comma-separated filters (eg "whitespace/indent"). + Each filter should start with + or -; else we die. + """ + _cpplint_state.AddFilters(filters) + +def _BackupFilters(): + """ Saves the current filter list to backup storage.""" + _cpplint_state.BackupFilters() + +def _RestoreFilters(): + """ Restores filters previously backed up.""" + _cpplint_state.RestoreFilters() + +class _FunctionState(object): + """Tracks current function name and the number of lines in its body.""" + + _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. + _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. + + def __init__(self): + self.in_a_function = False + self.lines_in_function = 0 + self.current_function = '' + + def Begin(self, function_name): + """Start analyzing function body. + + Args: + function_name: The name of the function being tracked. + """ + self.in_a_function = True + self.lines_in_function = 0 + self.current_function = function_name + + def Count(self): + """Count line in current function body.""" + if self.in_a_function: + self.lines_in_function += 1 + + def Check(self, error, filename, linenum): + """Report if too many lines in function body. + + Args: + error: The function to call with any errors found. + filename: The name of the current file. + linenum: The number of the line to check. + """ + if Match(r'T(EST|est)', self.current_function): + base_trigger = self._TEST_TRIGGER + else: + base_trigger = self._NORMAL_TRIGGER + trigger = base_trigger * 2**_VerboseLevel() + + if self.lines_in_function > trigger: + error_level = int(math.log(self.lines_in_function / base_trigger, 2)) + # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... + if error_level > 5: + error_level = 5 + error(filename, linenum, 'readability/fn_size', error_level, + 'Small and focused functions are preferred:' + ' %s has %d non-comment lines' + ' (error triggered by exceeding %d lines).' % ( + self.current_function, self.lines_in_function, trigger)) + + def End(self): + """Stop analyzing function body.""" + self.in_a_function = False + + +class _IncludeError(Exception): + """Indicates a problem with the include order in a file.""" + pass + + +class FileInfo(object): + """Provides utility functions for filenames. + + FileInfo provides easy access to the components of a file's path + relative to the project root. + """ + + def __init__(self, filename): + self._filename = filename + + def FullName(self): + """Make Windows paths like Unix.""" + return os.path.abspath(self._filename).replace('\\', '/') + + def RepositoryName(self): + """FullName after removing the local path to the repository. + + If we have a real absolute path name here we can try to do something smart: + detecting the root of the checkout and truncating /path/to/checkout from + the name so that we get header guards that don't include things like + "C:\Documents and Settings\..." or "/home/username/..." in them and thus + people on different computers who have checked the source out to different + locations won't see bogus errors. + """ + fullname = self.FullName() + + if os.path.exists(fullname): + project_dir = os.path.dirname(fullname) + + if os.path.exists(os.path.join(project_dir, ".svn")): + # If there's a .svn file in the current directory, we recursively look + # up the directory tree for the top of the SVN checkout + root_dir = project_dir + one_up_dir = os.path.dirname(root_dir) + while os.path.exists(os.path.join(one_up_dir, ".svn")): + root_dir = os.path.dirname(root_dir) + one_up_dir = os.path.dirname(one_up_dir) + + prefix = os.path.commonprefix([root_dir, project_dir]) + return fullname[len(prefix) + 1:] + + # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by + # searching up from the current path. + root_dir = os.path.dirname(fullname) + while (root_dir != os.path.dirname(root_dir) and + not os.path.exists(os.path.join(root_dir, ".git")) and + not os.path.exists(os.path.join(root_dir, ".hg")) and + not os.path.exists(os.path.join(root_dir, ".svn"))): + root_dir = os.path.dirname(root_dir) + + if (os.path.exists(os.path.join(root_dir, ".git")) or + os.path.exists(os.path.join(root_dir, ".hg")) or + os.path.exists(os.path.join(root_dir, ".svn"))): + prefix = os.path.commonprefix([root_dir, project_dir]) + return fullname[len(prefix) + 1:] + + # Don't know what to do; header guard warnings may be wrong... + return fullname + + def Split(self): + """Splits the file into the directory, basename, and extension. + + For 'chrome/browser/browser.cc', Split() would + return ('chrome/browser', 'browser', '.cc') + + Returns: + A tuple of (directory, basename, extension). + """ + + googlename = self.RepositoryName() + project, rest = os.path.split(googlename) + return (project,) + os.path.splitext(rest) + + def BaseName(self): + """File base name - text after the final slash, before the final period.""" + return self.Split()[1] + + def Extension(self): + """File extension - text following the final period.""" + return self.Split()[2] + + def NoExtension(self): + """File has no source file extension.""" + return '/'.join(self.Split()[0:2]) + + def IsSource(self): + """File has a source file extension.""" + return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') + + +def _ShouldPrintError(category, confidence, linenum): + """If confidence >= verbose, category passes filter and is not suppressed.""" + + # There are three ways we might decide not to print an error message: + # a "NOLINT(category)" comment appears in the source, + # the verbosity level isn't high enough, or the filters filter it out. + if IsErrorSuppressedByNolint(category, linenum): + return False + + if confidence < _cpplint_state.verbose_level: + return False + + is_filtered = False + for one_filter in _Filters(): + if one_filter.startswith('-'): + if category.startswith(one_filter[1:]): + is_filtered = True + elif one_filter.startswith('+'): + if category.startswith(one_filter[1:]): + is_filtered = False + else: + assert False # should have been checked for in SetFilter. + if is_filtered: + return False + + return True + + +def Error(filename, linenum, category, confidence, message): + """Logs the fact we've found a lint error. + + We log where the error was found, and also our confidence in the error, + that is, how certain we are this is a legitimate style regression, and + not a misidentification or a use that's sometimes justified. + + False positives can be suppressed by the use of + "cpplint(category)" comments on the offending line. These are + parsed into _error_suppressions. + + Args: + filename: The name of the file containing the error. + linenum: The number of the line containing the error. + category: A string used to describe the "category" this bug + falls under: "whitespace", say, or "runtime". Categories + may have a hierarchy separated by slashes: "whitespace/indent". + confidence: A number from 1-5 representing a confidence score for + the error, with 5 meaning that we are certain of the problem, + and 1 meaning that it could be a legitimate construct. + message: The error message. + """ + if _ShouldPrintError(category, confidence, linenum): + _cpplint_state.IncrementErrorCount(category) + if _cpplint_state.output_format == 'vs7': + sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + elif _cpplint_state.output_format == 'eclipse': + sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + else: + sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + + +# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. +_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( + r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') +# Match a single C style comment on the same line. +_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/' +# Matches multi-line C style comments. +# This RE is a little bit more complicated than one might expect, because we +# have to take care of space removals tools so we can handle comments inside +# statements better. +# The current rule is: We only clear spaces from both sides when we're at the +# end of the line. Otherwise, we try to remove spaces from the right side, +# if this doesn't work we try on left side but only if there's a non-character +# on the right. +_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( + r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' + + _RE_PATTERN_C_COMMENTS + r'\s+|' + + r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' + + _RE_PATTERN_C_COMMENTS + r')') + + +def IsCppString(line): + """Does line terminate so, that the next symbol is in string constant. + + This function does not consider single-line nor multi-line comments. + + Args: + line: is a partial line of code starting from the 0..n. + + Returns: + True, if next character appended to 'line' is inside a + string constant. + """ + + line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" + return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 + + +def CleanseRawStrings(raw_lines): + """Removes C++11 raw strings from lines. + + Before: + static const char kData[] = R"( + multi-line string + )"; + + After: + static const char kData[] = "" + (replaced by blank line) + ""; + + Args: + raw_lines: list of raw lines. + + Returns: + list of lines with C++11 raw strings replaced by empty strings. + """ + + delimiter = None + lines_without_raw_strings = [] + for line in raw_lines: + if delimiter: + # Inside a raw string, look for the end + end = line.find(delimiter) + if end >= 0: + # Found the end of the string, match leading space for this + # line and resume copying the original lines, and also insert + # a "" on the last line. + leading_space = Match(r'^(\s*)\S', line) + line = leading_space.group(1) + '""' + line[end + len(delimiter):] + delimiter = None + else: + # Haven't found the end yet, append a blank line. + line = '""' + + # Look for beginning of a raw string, and replace them with + # empty strings. This is done in a loop to handle multiple raw + # strings on the same line. + while delimiter is None: + # Look for beginning of a raw string. + # See 2.14.15 [lex.string] for syntax. + matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) + if matched: + delimiter = ')' + matched.group(2) + '"' + + end = matched.group(3).find(delimiter) + if end >= 0: + # Raw string ended on same line + line = (matched.group(1) + '""' + + matched.group(3)[end + len(delimiter):]) + delimiter = None + else: + # Start of a multi-line raw string + line = matched.group(1) + '""' + else: + break + + lines_without_raw_strings.append(line) + + # TODO(unknown): if delimiter is not None here, we might want to + # emit a warning for unterminated string. + return lines_without_raw_strings + + +def FindNextMultiLineCommentStart(lines, lineix): + """Find the beginning marker for a multiline comment.""" + while lineix < len(lines): + if lines[lineix].strip().startswith('/*'): + # Only return this marker if the comment goes beyond this line + if lines[lineix].strip().find('*/', 2) < 0: + return lineix + lineix += 1 + return len(lines) + + +def FindNextMultiLineCommentEnd(lines, lineix): + """We are inside a comment, find the end marker.""" + while lineix < len(lines): + if lines[lineix].strip().endswith('*/'): + return lineix + lineix += 1 + return len(lines) + + +def RemoveMultiLineCommentsFromRange(lines, begin, end): + """Clears a range of lines for multi-line comments.""" + # Having // dummy comments makes the lines non-empty, so we will not get + # unnecessary blank line warnings later in the code. + for i in range(begin, end): + lines[i] = '/**/' + + +def RemoveMultiLineComments(filename, lines, error): + """Removes multiline (c-style) comments from lines.""" + lineix = 0 + while lineix < len(lines): + lineix_begin = FindNextMultiLineCommentStart(lines, lineix) + if lineix_begin >= len(lines): + return + lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin) + if lineix_end >= len(lines): + error(filename, lineix_begin + 1, 'readability/multiline_comment', 5, + 'Could not find end of multi-line comment') + return + RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1) + lineix = lineix_end + 1 + + +def CleanseComments(line): + """Removes //-comments and single-line C-style /* */ comments. + + Args: + line: A line of C++ source. + + Returns: + The line with single-line comments removed. + """ + commentpos = line.find('//') + if commentpos != -1 and not IsCppString(line[:commentpos]): + line = line[:commentpos].rstrip() + # get rid of /* ... */ + return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) + + +class CleansedLines(object): + """Holds 4 copies of all lines with different preprocessing applied to them. + + 1) elided member contains lines without strings and comments. + 2) lines member contains lines without comments. + 3) raw_lines member contains all the lines without processing. + 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw + strings removed. + All these members are of , and of the same length. + """ + + def __init__(self, lines): + self.elided = [] + self.lines = [] + self.raw_lines = lines + self.num_lines = len(lines) + self.lines_without_raw_strings = CleanseRawStrings(lines) + for linenum in range(len(self.lines_without_raw_strings)): + self.lines.append(CleanseComments( + self.lines_without_raw_strings[linenum])) + elided = self._CollapseStrings(self.lines_without_raw_strings[linenum]) + self.elided.append(CleanseComments(elided)) + + def NumLines(self): + """Returns the number of lines represented.""" + return self.num_lines + + @staticmethod + def _CollapseStrings(elided): + """Collapses strings and chars on a line to simple "" or '' blocks. + + We nix strings first so we're not fooled by text like '"http://"' + + Args: + elided: The line being processed. + + Returns: + The line with collapsed strings. + """ + if _RE_PATTERN_INCLUDE.match(elided): + return elided + + # Remove escaped characters first to make quote/single quote collapsing + # basic. Things that look like escaped characters shouldn't occur + # outside of strings and chars. + elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) + + # Replace quoted strings and digit separators. Both single quotes + # and double quotes are processed in the same loop, otherwise + # nested quotes wouldn't work. + collapsed = '' + while True: + # Find the first quote character + match = Match(r'^([^\'"]*)([\'"])(.*)$', elided) + if not match: + collapsed += elided + break + head, quote, tail = match.groups() + + if quote == '"': + # Collapse double quoted strings + second_quote = tail.find('"') + if second_quote >= 0: + collapsed += head + '""' + elided = tail[second_quote + 1:] + else: + # Unmatched double quote, don't bother processing the rest + # of the line since this is probably a multiline string. + collapsed += elided + break + else: + # Found single quote, check nearby text to eliminate digit separators. + # + # There is no special handling for floating point here, because + # the integer/fractional/exponent parts would all be parsed + # correctly as long as there are digits on both sides of the + # separator. So we are fine as long as we don't see something + # like "0.'3" (gcc 4.9.0 will not allow this literal). + if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head): + match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail) + collapsed += head + match_literal.group(1).replace("'", '') + elided = match_literal.group(2) + else: + second_quote = tail.find('\'') + if second_quote >= 0: + collapsed += head + "''" + elided = tail[second_quote + 1:] + else: + # Unmatched single quote + collapsed += elided + break + + return collapsed + + +def FindEndOfExpressionInLine(line, startpos, stack): + """Find the position just after the end of current parenthesized expression. + + Args: + line: a CleansedLines line. + startpos: start searching at this position. + stack: nesting stack at startpos. + + Returns: + On finding matching end: (index just after matching end, None) + On finding an unclosed expression: (-1, None) + Otherwise: (-1, new stack at end of this line) + """ + for i in xrange(startpos, len(line)): + char = line[i] + if char in '([{': + # Found start of parenthesized expression, push to expression stack + stack.append(char) + elif char == '<': + # Found potential start of template argument list + if i > 0 and line[i - 1] == '<': + # Left shift operator + if stack and stack[-1] == '<': + stack.pop() + if not stack: + return (-1, None) + elif i > 0 and Search(r'\boperator\s*$', line[0:i]): + # operator<, don't add to stack + continue + else: + # Tentative start of template argument list + stack.append('<') + elif char in ')]}': + # Found end of parenthesized expression. + # + # If we are currently expecting a matching '>', the pending '<' + # must have been an operator. Remove them from expression stack. + while stack and stack[-1] == '<': + stack.pop() + if not stack: + return (-1, None) + if ((stack[-1] == '(' and char == ')') or + (stack[-1] == '[' and char == ']') or + (stack[-1] == '{' and char == '}')): + stack.pop() + if not stack: + return (i + 1, None) + else: + # Mismatched parentheses + return (-1, None) + elif char == '>': + # Found potential end of template argument list. + + # Ignore "->" and operator functions + if (i > 0 and + (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))): + continue + + # Pop the stack if there is a matching '<'. Otherwise, ignore + # this '>' since it must be an operator. + if stack: + if stack[-1] == '<': + stack.pop() + if not stack: + return (i + 1, None) + elif char == ';': + # Found something that look like end of statements. If we are currently + # expecting a '>', the matching '<' must have been an operator, since + # template argument list should not contain statements. + while stack and stack[-1] == '<': + stack.pop() + if not stack: + return (-1, None) + + # Did not find end of expression or unbalanced parentheses on this line + return (-1, stack) + + +def CloseExpression(clean_lines, linenum, pos): + """If input points to ( or { or [ or <, finds the position that closes it. + + If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the + linenum/pos that correspond to the closing of the expression. + + TODO(unknown): cpplint spends a fair bit of time matching parentheses. + Ideally we would want to index all opening and closing parentheses once + and have CloseExpression be just a simple lookup, but due to preprocessor + tricks, this is not so easy. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + pos: A position on the line. + + Returns: + A tuple (line, linenum, pos) pointer *past* the closing brace, or + (line, len(lines), -1) if we never find a close. Note we ignore + strings and comments when matching; and the line we return is the + 'cleansed' line at linenum. + """ + + line = clean_lines.elided[linenum] + if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]): + return (line, clean_lines.NumLines(), -1) + + # Check first line + (end_pos, stack) = FindEndOfExpressionInLine(line, pos, []) + if end_pos > -1: + return (line, linenum, end_pos) + + # Continue scanning forward + while stack and linenum < clean_lines.NumLines() - 1: + linenum += 1 + line = clean_lines.elided[linenum] + (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack) + if end_pos > -1: + return (line, linenum, end_pos) + + # Did not find end of expression before end of file, give up + return (line, clean_lines.NumLines(), -1) + + +def FindStartOfExpressionInLine(line, endpos, stack): + """Find position at the matching start of current expression. + + This is almost the reverse of FindEndOfExpressionInLine, but note + that the input position and returned position differs by 1. + + Args: + line: a CleansedLines line. + endpos: start searching at this position. + stack: nesting stack at endpos. + + Returns: + On finding matching start: (index at matching start, None) + On finding an unclosed expression: (-1, None) + Otherwise: (-1, new stack at beginning of this line) + """ + i = endpos + while i >= 0: + char = line[i] + if char in ')]}': + # Found end of expression, push to expression stack + stack.append(char) + elif char == '>': + # Found potential end of template argument list. + # + # Ignore it if it's a "->" or ">=" or "operator>" + if (i > 0 and + (line[i - 1] == '-' or + Match(r'\s>=\s', line[i - 1:]) or + Search(r'\boperator\s*$', line[0:i]))): + i -= 1 + else: + stack.append('>') + elif char == '<': + # Found potential start of template argument list + if i > 0 and line[i - 1] == '<': + # Left shift operator + i -= 1 + else: + # If there is a matching '>', we can pop the expression stack. + # Otherwise, ignore this '<' since it must be an operator. + if stack and stack[-1] == '>': + stack.pop() + if not stack: + return (i, None) + elif char in '([{': + # Found start of expression. + # + # If there are any unmatched '>' on the stack, they must be + # operators. Remove those. + while stack and stack[-1] == '>': + stack.pop() + if not stack: + return (-1, None) + if ((char == '(' and stack[-1] == ')') or + (char == '[' and stack[-1] == ']') or + (char == '{' and stack[-1] == '}')): + stack.pop() + if not stack: + return (i, None) + else: + # Mismatched parentheses + return (-1, None) + elif char == ';': + # Found something that look like end of statements. If we are currently + # expecting a '<', the matching '>' must have been an operator, since + # template argument list should not contain statements. + while stack and stack[-1] == '>': + stack.pop() + if not stack: + return (-1, None) + + i -= 1 + + return (-1, stack) + + +def ReverseCloseExpression(clean_lines, linenum, pos): + """If input points to ) or } or ] or >, finds the position that opens it. + + If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the + linenum/pos that correspond to the opening of the expression. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + pos: A position on the line. + + Returns: + A tuple (line, linenum, pos) pointer *at* the opening brace, or + (line, 0, -1) if we never find the matching opening brace. Note + we ignore strings and comments when matching; and the line we + return is the 'cleansed' line at linenum. + """ + line = clean_lines.elided[linenum] + if line[pos] not in ')}]>': + return (line, 0, -1) + + # Check last line + (start_pos, stack) = FindStartOfExpressionInLine(line, pos, []) + if start_pos > -1: + return (line, linenum, start_pos) + + # Continue scanning backward + while stack and linenum > 0: + linenum -= 1 + line = clean_lines.elided[linenum] + (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack) + if start_pos > -1: + return (line, linenum, start_pos) + + # Did not find start of expression before beginning of file, give up + return (line, 0, -1) + + +def CheckForCopyright(filename, lines, error): + """Logs an error if no Copyright message appears at the top of the file.""" + + # We'll say it should occur by line 10. Don't forget there's a + # dummy line at the front. + for line in xrange(1, min(len(lines), 11)): + if re.search(r'Copyright', lines[line], re.I): break + else: # means no copyright line was found + error(filename, 0, 'legal/copyright', 5, + 'No copyright message found. ' + 'You should have a line: "Copyright [year] "') + + +def GetIndentLevel(line): + """Return the number of leading spaces in line. + + Args: + line: A string to check. + + Returns: + An integer count of leading spaces, possibly zero. + """ + indent = Match(r'^( *)\S', line) + if indent: + return len(indent.group(1)) + else: + return 0 + + +def GetHeaderGuardCPPVariable(filename): + """Returns the CPP variable that should be used as a header guard. + + Args: + filename: The name of a C++ header file. + + Returns: + The CPP variable that should be used as a header guard in the + named file. + + """ + + # Restores original filename in case that cpplint is invoked from Emacs's + # flymake. + filename = re.sub(r'_flymake\.h$', '.h', filename) + filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename) + # Replace 'c++' with 'cpp'. + filename = filename.replace('C++', 'cpp').replace('c++', 'cpp') + + fileinfo = FileInfo(filename) + file_path_from_root = fileinfo.RepositoryName() + if _root: + file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root) + return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_' + + +def CheckForHeaderGuard(filename, clean_lines, error): + """Checks that the file contains a header guard. + + Logs an error if no #ifndef header guard is present. For other + headers, checks that the full pathname is used. + + Args: + filename: The name of the C++ header file. + clean_lines: A CleansedLines instance containing the file. + error: The function to call with any errors found. + """ + + # Don't check for header guards if there are error suppression + # comments somewhere in this file. + # + # Because this is silencing a warning for a nonexistent line, we + # only support the very specific NOLINT(build/header_guard) syntax, + # and not the general NOLINT or NOLINT(*) syntax. + raw_lines = clean_lines.lines_without_raw_strings + for i in raw_lines: + if Search(r'//\s*NOLINT\(build/header_guard\)', i): + return + + cppvar = GetHeaderGuardCPPVariable(filename) + + ifndef = '' + ifndef_linenum = 0 + define = '' + endif = '' + endif_linenum = 0 + for linenum, line in enumerate(raw_lines): + linesplit = line.split() + if len(linesplit) >= 2: + # find the first occurrence of #ifndef and #define, save arg + if not ifndef and linesplit[0] == '#ifndef': + # set ifndef to the header guard presented on the #ifndef line. + ifndef = linesplit[1] + ifndef_linenum = linenum + if not define and linesplit[0] == '#define': + define = linesplit[1] + # find the last occurrence of #endif, save entire line + if line.startswith('#endif'): + endif = line + endif_linenum = linenum + + if not ifndef or not define or ifndef != define: + error(filename, 0, 'build/header_guard', 5, + 'No #ifndef header guard found, suggested CPP variable is: %s' % + cppvar) + return + + # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__ + # for backward compatibility. + if ifndef != cppvar: + error_level = 0 + if ifndef != cppvar + '_': + error_level = 5 + + ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum, + error) + error(filename, ifndef_linenum, 'build/header_guard', error_level, + '#ifndef header guard has wrong style, please use: %s' % cppvar) + + # Check for "//" comments on endif line. + ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum, + error) + match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif) + if match: + if match.group(1) == '_': + # Issue low severity warning for deprecated double trailing underscore + error(filename, endif_linenum, 'build/header_guard', 0, + '#endif line should be "#endif // %s"' % cppvar) + return + + # Didn't find the corresponding "//" comment. If this file does not + # contain any "//" comments at all, it could be that the compiler + # only wants "/**/" comments, look for those instead. + no_single_line_comments = True + for i in xrange(1, len(raw_lines) - 1): + line = raw_lines[i] + if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line): + no_single_line_comments = False + break + + if no_single_line_comments: + match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif) + if match: + if match.group(1) == '_': + # Low severity warning for double trailing underscore + error(filename, endif_linenum, 'build/header_guard', 0, + '#endif line should be "#endif /* %s */"' % cppvar) + return + + # Didn't find anything + error(filename, endif_linenum, 'build/header_guard', 5, + '#endif line should be "#endif // %s"' % cppvar) + + +def CheckHeaderFileIncluded(filename, include_state, error): + """Logs an error if a .cc file does not include its header.""" + + # Do not check test files + if filename.endswith('_test.cc') or filename.endswith('_unittest.cc'): + return + + fileinfo = FileInfo(filename) + headerfile = filename[0:len(filename) - 2] + 'h' + if not os.path.exists(headerfile): + return + headername = FileInfo(headerfile).RepositoryName() + first_include = 0 + for section_list in include_state.include_list: + for f in section_list: + if headername in f[0] or f[0] in headername: + return + if not first_include: + first_include = f[1] + + error(filename, first_include, 'build/include', 5, + '%s should include its header file %s' % (fileinfo.RepositoryName(), + headername)) + + +def CheckForBadCharacters(filename, lines, error): + """Logs an error for each line containing bad characters. + + Two kinds of bad characters: + + 1. Unicode replacement characters: These indicate that either the file + contained invalid UTF-8 (likely) or Unicode replacement characters (which + it shouldn't). Note that it's possible for this to throw off line + numbering if the invalid UTF-8 occurred adjacent to a newline. + + 2. NUL bytes. These are problematic for some tools. + + Args: + filename: The name of the current file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + for linenum, line in enumerate(lines): + if u'\ufffd' in line: + error(filename, linenum, 'readability/utf8', 5, + 'Line contains invalid UTF-8 (or Unicode replacement character).') + if '\0' in line: + error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.') + + +def CheckForNewlineAtEOF(filename, lines, error): + """Logs an error if there is no newline char at the end of the file. + + Args: + filename: The name of the current file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + + # The array lines() was created by adding two newlines to the + # original file (go figure), then splitting on \n. + # To verify that the file ends in \n, we just have to make sure the + # last-but-two element of lines() exists and is empty. + if len(lines) < 3 or lines[-2]: + error(filename, len(lines) - 2, 'whitespace/ending_newline', 5, + 'Could not find a newline character at the end of the file.') + + +def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error): + """Logs an error if we see /* ... */ or "..." that extend past one line. + + /* ... */ comments are legit inside macros, for one line. + Otherwise, we prefer // comments, so it's ok to warn about the + other. Likewise, it's ok for strings to extend across multiple + lines, as long as a line continuation character (backslash) + terminates each line. Although not currently prohibited by the C++ + style guide, it's ugly and unnecessary. We don't do well with either + in this lint program, so we warn about both. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Remove all \\ (escaped backslashes) from the line. They are OK, and the + # second (escaped) slash may trigger later \" detection erroneously. + line = line.replace('\\\\', '') + + if line.count('/*') > line.count('*/'): + error(filename, linenum, 'readability/multiline_comment', 5, + 'Complex multi-line /*...*/-style comment found. ' + 'Lint may give bogus warnings. ' + 'Consider replacing these with //-style comments, ' + 'with #if 0...#endif, ' + 'or with more clearly structured multi-line comments.') + + if (line.count('"') - line.count('\\"')) % 2: + error(filename, linenum, 'readability/multiline_string', 5, + 'Multi-line string ("...") found. This lint script doesn\'t ' + 'do well with such strings, and may give bogus warnings. ' + 'Use C++11 raw strings or concatenation instead.') + + +# (non-threadsafe name, thread-safe alternative, validation pattern) +# +# The validation pattern is used to eliminate false positives such as: +# _rand(); // false positive due to substring match. +# ->rand(); // some member function rand(). +# ACMRandom rand(seed); // some variable named rand. +# ISAACRandom rand(); // another variable named rand. +# +# Basically we require the return value of these functions to be used +# in some expression context on the same line by matching on some +# operator before the function name. This eliminates constructors and +# member function calls. +_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)' +_THREADING_LIST = ( + ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'), + ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'), + ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'), + ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'), + ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'), + ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'), + ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'), + ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'), + ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'), + ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'), + ('strtok(', 'strtok_r(', + _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'), + ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'), + ) + + +def CheckPosixThreading(filename, clean_lines, linenum, error): + """Checks for calls to thread-unsafe functions. + + Much code has been originally written without consideration of + multi-threading. Also, engineers are relying on their old experience; + they have learned posix before threading extensions were added. These + tests guide the engineers to use thread-safe functions (when using + posix directly). + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST: + # Additional pattern matching check to confirm that this is the + # function we are looking for + if Search(pattern, line): + error(filename, linenum, 'runtime/threadsafe_fn', 2, + 'Consider using ' + multithread_safe_func + + '...) instead of ' + single_thread_func + + '...) for improved thread safety.') + + +def CheckVlogArguments(filename, clean_lines, linenum, error): + """Checks that VLOG() is only used for defining a logging level. + + For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and + VLOG(FATAL) are not. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line): + error(filename, linenum, 'runtime/vlog', 5, + 'VLOG() should be used with numeric verbosity level. ' + 'Use LOG() if you want symbolic severity levels.') + +# Matches invalid increment: *count++, which moves pointer instead of +# incrementing a value. +_RE_PATTERN_INVALID_INCREMENT = re.compile( + r'^\s*\*\w+(\+\+|--);') + + +def CheckInvalidIncrement(filename, clean_lines, linenum, error): + """Checks for invalid increment *count++. + + For example following function: + void increment_counter(int* count) { + *count++; + } + is invalid, because it effectively does count++, moving pointer, and should + be replaced with ++*count, (*count)++ or *count += 1. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + if _RE_PATTERN_INVALID_INCREMENT.match(line): + error(filename, linenum, 'runtime/invalid_increment', 5, + 'Changing pointer instead of value (or unused value of operator*).') + + +def IsMacroDefinition(clean_lines, linenum): + if Search(r'^#define', clean_lines[linenum]): + return True + + if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]): + return True + + return False + + +def IsForwardClassDeclaration(clean_lines, linenum): + return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum]) + + +class _BlockInfo(object): + """Stores information about a generic block of code.""" + + def __init__(self, seen_open_brace): + self.seen_open_brace = seen_open_brace + self.open_parentheses = 0 + self.inline_asm = _NO_ASM + self.check_namespace_indentation = False + + def CheckBegin(self, filename, clean_lines, linenum, error): + """Run checks that applies to text up to the opening brace. + + This is mostly for checking the text after the class identifier + and the "{", usually where the base class is specified. For other + blocks, there isn't much to check, so we always pass. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + pass + + def CheckEnd(self, filename, clean_lines, linenum, error): + """Run checks that applies to text after the closing brace. + + This is mostly used for checking end of namespace comments. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + pass + + def IsBlockInfo(self): + """Returns true if this block is a _BlockInfo. + + This is convenient for verifying that an object is an instance of + a _BlockInfo, but not an instance of any of the derived classes. + + Returns: + True for this class, False for derived classes. + """ + return self.__class__ == _BlockInfo + + +class _ExternCInfo(_BlockInfo): + """Stores information about an 'extern "C"' block.""" + + def __init__(self): + _BlockInfo.__init__(self, True) + + +class _ClassInfo(_BlockInfo): + """Stores information about a class.""" + + def __init__(self, name, class_or_struct, clean_lines, linenum): + _BlockInfo.__init__(self, False) + self.name = name + self.starting_linenum = linenum + self.is_derived = False + self.check_namespace_indentation = True + if class_or_struct == 'struct': + self.access = 'public' + self.is_struct = True + else: + self.access = 'private' + self.is_struct = False + + # Remember initial indentation level for this class. Using raw_lines here + # instead of elided to account for leading comments. + self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum]) + + # Try to find the end of the class. This will be confused by things like: + # class A { + # } *x = { ... + # + # But it's still good enough for CheckSectionSpacing. + self.last_line = 0 + depth = 0 + for i in range(linenum, clean_lines.NumLines()): + line = clean_lines.elided[i] + depth += line.count('{') - line.count('}') + if not depth: + self.last_line = i + break + + def CheckBegin(self, filename, clean_lines, linenum, error): + # Look for a bare ':' + if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]): + self.is_derived = True + + def CheckEnd(self, filename, clean_lines, linenum, error): + # If there is a DISALLOW macro, it should appear near the end of + # the class. + seen_last_thing_in_class = False + for i in xrange(linenum - 1, self.starting_linenum, -1): + match = Search( + r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' + + self.name + r'\)', + clean_lines.elided[i]) + if match: + if seen_last_thing_in_class: + error(filename, i, 'readability/constructors', 3, + match.group(1) + ' should be the last thing in the class') + break + + if not Match(r'^\s*$', clean_lines.elided[i]): + seen_last_thing_in_class = True + + # Check that closing brace is aligned with beginning of the class. + # Only do this if the closing brace is indented by only whitespaces. + # This means we will not check single-line class definitions. + indent = Match(r'^( *)\}', clean_lines.elided[linenum]) + if indent and len(indent.group(1)) != self.class_indent: + if self.is_struct: + parent = 'struct ' + self.name + else: + parent = 'class ' + self.name + error(filename, linenum, 'whitespace/indent', 3, + 'Closing brace should be aligned with beginning of %s' % parent) + + +class _NamespaceInfo(_BlockInfo): + """Stores information about a namespace.""" + + def __init__(self, name, linenum): + _BlockInfo.__init__(self, False) + self.name = name or '' + self.starting_linenum = linenum + self.check_namespace_indentation = True + + def CheckEnd(self, filename, clean_lines, linenum, error): + """Check end of namespace comments.""" + line = clean_lines.raw_lines[linenum] + + # Check how many lines is enclosed in this namespace. Don't issue + # warning for missing namespace comments if there aren't enough + # lines. However, do apply checks if there is already an end of + # namespace comment and it's incorrect. + # + # TODO(unknown): We always want to check end of namespace comments + # if a namespace is large, but sometimes we also want to apply the + # check if a short namespace contained nontrivial things (something + # other than forward declarations). There is currently no logic on + # deciding what these nontrivial things are, so this check is + # triggered by namespace size only, which works most of the time. + if (linenum - self.starting_linenum < 10 + and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)): + return + + # Look for matching comment at end of namespace. + # + # Note that we accept C style "/* */" comments for terminating + # namespaces, so that code that terminate namespaces inside + # preprocessor macros can be cpplint clean. + # + # We also accept stuff like "// end of namespace ." with the + # period at the end. + # + # Besides these, we don't accept anything else, otherwise we might + # get false negatives when existing comment is a substring of the + # expected namespace. + if self.name: + # Named namespace + if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + + r'[\*/\.\\\s]*$'), + line): + error(filename, linenum, 'readability/namespace', 5, + 'Namespace should be terminated with "// namespace %s"' % + self.name) + else: + # Anonymous namespace + if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): + # If "// namespace anonymous" or "// anonymous namespace (more text)", + # mention "// anonymous namespace" as an acceptable form + if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line): + error(filename, linenum, 'readability/namespace', 5, + 'Anonymous namespace should be terminated with "// namespace"' + ' or "// anonymous namespace"') + else: + error(filename, linenum, 'readability/namespace', 5, + 'Anonymous namespace should be terminated with "// namespace"') + + +class _PreprocessorInfo(object): + """Stores checkpoints of nesting stacks when #if/#else is seen.""" + + def __init__(self, stack_before_if): + # The entire nesting stack before #if + self.stack_before_if = stack_before_if + + # The entire nesting stack up to #else + self.stack_before_else = [] + + # Whether we have already seen #else or #elif + self.seen_else = False + + +class NestingState(object): + """Holds states related to parsing braces.""" + + def __init__(self): + # Stack for tracking all braces. An object is pushed whenever we + # see a "{", and popped when we see a "}". Only 3 types of + # objects are possible: + # - _ClassInfo: a class or struct. + # - _NamespaceInfo: a namespace. + # - _BlockInfo: some other type of block. + self.stack = [] + + # Top of the previous stack before each Update(). + # + # Because the nesting_stack is updated at the end of each line, we + # had to do some convoluted checks to find out what is the current + # scope at the beginning of the line. This check is simplified by + # saving the previous top of nesting stack. + # + # We could save the full stack, but we only need the top. Copying + # the full nesting stack would slow down cpplint by ~10%. + self.previous_stack_top = [] + + # Stack of _PreprocessorInfo objects. + self.pp_stack = [] + + def SeenOpenBrace(self): + """Check if we have seen the opening brace for the innermost block. + + Returns: + True if we have seen the opening brace, False if the innermost + block is still expecting an opening brace. + """ + return (not self.stack) or self.stack[-1].seen_open_brace + + def InNamespaceBody(self): + """Check if we are currently one level inside a namespace body. + + Returns: + True if top of the stack is a namespace block, False otherwise. + """ + return self.stack and isinstance(self.stack[-1], _NamespaceInfo) + + def InExternC(self): + """Check if we are currently one level inside an 'extern "C"' block. + + Returns: + True if top of the stack is an extern block, False otherwise. + """ + return self.stack and isinstance(self.stack[-1], _ExternCInfo) + + def InClassDeclaration(self): + """Check if we are currently one level inside a class or struct declaration. + + Returns: + True if top of the stack is a class/struct, False otherwise. + """ + return self.stack and isinstance(self.stack[-1], _ClassInfo) + + def InAsmBlock(self): + """Check if we are currently one level inside an inline ASM block. + + Returns: + True if the top of the stack is a block containing inline ASM. + """ + return self.stack and self.stack[-1].inline_asm != _NO_ASM + + def InTemplateArgumentList(self, clean_lines, linenum, pos): + """Check if current position is inside template argument list. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + pos: position just after the suspected template argument. + Returns: + True if (linenum, pos) is inside template arguments. + """ + while linenum < clean_lines.NumLines(): + # Find the earliest character that might indicate a template argument + line = clean_lines.elided[linenum] + match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:]) + if not match: + linenum += 1 + pos = 0 + continue + token = match.group(1) + pos += len(match.group(0)) + + # These things do not look like template argument list: + # class Suspect { + # class Suspect x; } + if token in ('{', '}', ';'): return False + + # These things look like template argument list: + # template + # template + # template + # template + if token in ('>', '=', '[', ']', '.'): return True + + # Check if token is an unmatched '<'. + # If not, move on to the next character. + if token != '<': + pos += 1 + if pos >= len(line): + linenum += 1 + pos = 0 + continue + + # We can't be sure if we just find a single '<', and need to + # find the matching '>'. + (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1) + if end_pos < 0: + # Not sure if template argument list or syntax error in file + return False + linenum = end_line + pos = end_pos + return False + + def UpdatePreprocessor(self, line): + """Update preprocessor stack. + + We need to handle preprocessors due to classes like this: + #ifdef SWIG + struct ResultDetailsPageElementExtensionPoint { + #else + struct ResultDetailsPageElementExtensionPoint : public Extension { + #endif + + We make the following assumptions (good enough for most files): + - Preprocessor condition evaluates to true from #if up to first + #else/#elif/#endif. + + - Preprocessor condition evaluates to false from #else/#elif up + to #endif. We still perform lint checks on these lines, but + these do not affect nesting stack. + + Args: + line: current line to check. + """ + if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line): + # Beginning of #if block, save the nesting stack here. The saved + # stack will allow us to restore the parsing state in the #else case. + self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack))) + elif Match(r'^\s*#\s*(else|elif)\b', line): + # Beginning of #else block + if self.pp_stack: + if not self.pp_stack[-1].seen_else: + # This is the first #else or #elif block. Remember the + # whole nesting stack up to this point. This is what we + # keep after the #endif. + self.pp_stack[-1].seen_else = True + self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack) + + # Restore the stack to how it was before the #if + self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if) + else: + # TODO(unknown): unexpected #else, issue warning? + pass + elif Match(r'^\s*#\s*endif\b', line): + # End of #if or #else blocks. + if self.pp_stack: + # If we saw an #else, we will need to restore the nesting + # stack to its former state before the #else, otherwise we + # will just continue from where we left off. + if self.pp_stack[-1].seen_else: + # Here we can just use a shallow copy since we are the last + # reference to it. + self.stack = self.pp_stack[-1].stack_before_else + # Drop the corresponding #if + self.pp_stack.pop() + else: + # TODO(unknown): unexpected #endif, issue warning? + pass + + # TODO(unknown): Update() is too long, but we will refactor later. + def Update(self, filename, clean_lines, linenum, error): + """Update nesting state with current line. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Remember top of the previous nesting stack. + # + # The stack is always pushed/popped and not modified in place, so + # we can just do a shallow copy instead of copy.deepcopy. Using + # deepcopy would slow down cpplint by ~28%. + if self.stack: + self.previous_stack_top = self.stack[-1] + else: + self.previous_stack_top = None + + # Update pp_stack + self.UpdatePreprocessor(line) + + # Count parentheses. This is to avoid adding struct arguments to + # the nesting stack. + if self.stack: + inner_block = self.stack[-1] + depth_change = line.count('(') - line.count(')') + inner_block.open_parentheses += depth_change + + # Also check if we are starting or ending an inline assembly block. + if inner_block.inline_asm in (_NO_ASM, _END_ASM): + if (depth_change != 0 and + inner_block.open_parentheses == 1 and + _MATCH_ASM.match(line)): + # Enter assembly block + inner_block.inline_asm = _INSIDE_ASM + else: + # Not entering assembly block. If previous line was _END_ASM, + # we will now shift to _NO_ASM state. + inner_block.inline_asm = _NO_ASM + elif (inner_block.inline_asm == _INSIDE_ASM and + inner_block.open_parentheses == 0): + # Exit assembly block + inner_block.inline_asm = _END_ASM + + # Consume namespace declaration at the beginning of the line. Do + # this in a loop so that we catch same line declarations like this: + # namespace proto2 { namespace bridge { class MessageSet; } } + while True: + # Match start of namespace. The "\b\s*" below catches namespace + # declarations even if it weren't followed by a whitespace, this + # is so that we don't confuse our namespace checker. The + # missing spaces will be flagged by CheckSpacing. + namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line) + if not namespace_decl_match: + break + + new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum) + self.stack.append(new_namespace) + + line = namespace_decl_match.group(2) + if line.find('{') != -1: + new_namespace.seen_open_brace = True + line = line[line.find('{') + 1:] + + # Look for a class declaration in whatever is left of the line + # after parsing namespaces. The regexp accounts for decorated classes + # such as in: + # class LOCKABLE API Object { + # }; + class_decl_match = Match( + r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?' + r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))' + r'(.*)$', line) + if (class_decl_match and + (not self.stack or self.stack[-1].open_parentheses == 0)): + # We do not want to accept classes that are actually template arguments: + # template , + # template class Ignore3> + # void Function() {}; + # + # To avoid template argument cases, we scan forward and look for + # an unmatched '>'. If we see one, assume we are inside a + # template argument list. + end_declaration = len(class_decl_match.group(1)) + if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration): + self.stack.append(_ClassInfo( + class_decl_match.group(3), class_decl_match.group(2), + clean_lines, linenum)) + line = class_decl_match.group(4) + + # If we have not yet seen the opening brace for the innermost block, + # run checks here. + if not self.SeenOpenBrace(): + self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) + + # Update access control if we are inside a class/struct + if self.stack and isinstance(self.stack[-1], _ClassInfo): + classinfo = self.stack[-1] + access_match = Match( + r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' + r':(?:[^:]|$)', + line) + if access_match: + classinfo.access = access_match.group(2) + + # Check that access keywords are indented +1 space. Skip this + # check if the keywords are not preceded by whitespaces. + indent = access_match.group(1) + if (len(indent) != classinfo.class_indent + 1 and + Match(r'^\s*$', indent)): + if classinfo.is_struct: + parent = 'struct ' + classinfo.name + else: + parent = 'class ' + classinfo.name + slots = '' + if access_match.group(3): + slots = access_match.group(3) + error(filename, linenum, 'whitespace/indent', 3, + '%s%s: should be indented +1 space inside %s' % ( + access_match.group(2), slots, parent)) + + # Consume braces or semicolons from what's left of the line + while True: + # Match first brace, semicolon, or closed parenthesis. + matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line) + if not matched: + break + + token = matched.group(1) + if token == '{': + # If namespace or class hasn't seen a opening brace yet, mark + # namespace/class head as complete. Push a new block onto the + # stack otherwise. + if not self.SeenOpenBrace(): + self.stack[-1].seen_open_brace = True + elif Match(r'^extern\s*"[^"]*"\s*\{', line): + self.stack.append(_ExternCInfo()) + else: + self.stack.append(_BlockInfo(True)) + if _MATCH_ASM.match(line): + self.stack[-1].inline_asm = _BLOCK_ASM + + elif token == ';' or token == ')': + # If we haven't seen an opening brace yet, but we already saw + # a semicolon, this is probably a forward declaration. Pop + # the stack for these. + # + # Similarly, if we haven't seen an opening brace yet, but we + # already saw a closing parenthesis, then these are probably + # function arguments with extra "class" or "struct" keywords. + # Also pop these stack for these. + if not self.SeenOpenBrace(): + self.stack.pop() + else: # token == '}' + # Perform end of block checks and pop the stack. + if self.stack: + self.stack[-1].CheckEnd(filename, clean_lines, linenum, error) + self.stack.pop() + line = matched.group(2) + + def InnermostClass(self): + """Get class info on the top of the stack. + + Returns: + A _ClassInfo object if we are inside a class, or None otherwise. + """ + for i in range(len(self.stack), 0, -1): + classinfo = self.stack[i - 1] + if isinstance(classinfo, _ClassInfo): + return classinfo + return None + + def CheckCompletedBlocks(self, filename, error): + """Checks that all classes and namespaces have been completely parsed. + + Call this when all lines in a file have been processed. + Args: + filename: The name of the current file. + error: The function to call with any errors found. + """ + # Note: This test can result in false positives if #ifdef constructs + # get in the way of brace matching. See the testBuildClass test in + # cpplint_unittest.py for an example of this. + for obj in self.stack: + if isinstance(obj, _ClassInfo): + error(filename, obj.starting_linenum, 'build/class', 5, + 'Failed to find complete declaration of class %s' % + obj.name) + elif isinstance(obj, _NamespaceInfo): + error(filename, obj.starting_linenum, 'build/namespaces', 5, + 'Failed to find complete declaration of namespace %s' % + obj.name) + + +def CheckForNonStandardConstructs(filename, clean_lines, linenum, + nesting_state, error): + r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. + + Complain about several constructs which gcc-2 accepts, but which are + not standard C++. Warning about these in lint is one way to ease the + transition to new compilers. + - put storage class first (e.g. "static const" instead of "const static"). + - "%lld" instead of %qd" in printf-type functions. + - "%1$d" is non-standard in printf-type functions. + - "\%" is an undefined character escape sequence. + - text after #endif is not allowed. + - invalid inner-style forward declaration. + - >? and ?= and )\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', + line): + error(filename, linenum, 'build/deprecated', 3, + '>? and ))?' + # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' + error(filename, linenum, 'runtime/member_string_references', 2, + 'const string& members are dangerous. It is much better to use ' + 'alternatives, such as pointers or simple constants.') + + # Everything else in this function operates on class declarations. + # Return early if the top of the nesting stack is not a class, or if + # the class head is not completed yet. + classinfo = nesting_state.InnermostClass() + if not classinfo or not classinfo.seen_open_brace: + return + + # The class may have been declared with namespace or classname qualifiers. + # The constructor and destructor will not have those qualifiers. + base_classname = classinfo.name.split('::')[-1] + + # Look for single-argument constructors that aren't marked explicit. + # Technically a valid construct, but against style. Also look for + # non-single-argument constructors which are also technically valid, but + # strongly suggest something is wrong. + explicit_constructor_match = Match( + r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*' + r'\(((?:[^()]|\([^()]*\))*)\)' + % re.escape(base_classname), + line) + + if explicit_constructor_match: + is_marked_explicit = explicit_constructor_match.group(1) + + if not explicit_constructor_match.group(2): + constructor_args = [] + else: + constructor_args = explicit_constructor_match.group(2).split(',') + + # collapse arguments so that commas in template parameter lists and function + # argument parameter lists don't split arguments in two + i = 0 + while i < len(constructor_args): + constructor_arg = constructor_args[i] + while (constructor_arg.count('<') > constructor_arg.count('>') or + constructor_arg.count('(') > constructor_arg.count(')')): + constructor_arg += ',' + constructor_args[i + 1] + del constructor_args[i + 1] + constructor_args[i] = constructor_arg + i += 1 + + defaulted_args = [arg for arg in constructor_args if '=' in arg] + noarg_constructor = (not constructor_args or # empty arg list + # 'void' arg specifier + (len(constructor_args) == 1 and + constructor_args[0].strip() == 'void')) + onearg_constructor = ((len(constructor_args) == 1 and # exactly one arg + not noarg_constructor) or + # all but at most one arg defaulted + (len(constructor_args) >= 1 and + not noarg_constructor and + len(defaulted_args) >= len(constructor_args) - 1)) + initializer_list_constructor = bool( + onearg_constructor and + Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0])) + copy_constructor = bool( + onearg_constructor and + Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&' + % re.escape(base_classname), constructor_args[0].strip())) + + if (not is_marked_explicit and + onearg_constructor and + not initializer_list_constructor and + not copy_constructor): + if defaulted_args: + error(filename, linenum, 'runtime/explicit', 5, + 'Constructors callable with one argument ' + 'should be marked explicit.') + else: + error(filename, linenum, 'runtime/explicit', 5, + 'Single-parameter constructors should be marked explicit.') + elif is_marked_explicit and not onearg_constructor: + if noarg_constructor: + error(filename, linenum, 'runtime/explicit', 5, + 'Zero-parameter constructors should not be marked explicit.') + else: + error(filename, linenum, 'runtime/explicit', 0, + 'Constructors that require multiple arguments ' + 'should not be marked explicit.') + + +def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error): + """Checks for the correctness of various spacing around function calls. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Since function calls often occur inside if/for/while/switch + # expressions - which have their own, more liberal conventions - we + # first see if we should be looking inside such an expression for a + # function call, to which we can apply more strict standards. + fncall = line # if there's no control flow construct, look at whole line + for pattern in (r'\bif\s*\((.*)\)\s*{', + r'\bfor\s*\((.*)\)\s*{', + r'\bwhile\s*\((.*)\)\s*[{;]', + r'\bswitch\s*\((.*)\)\s*{'): + match = Search(pattern, line) + if match: + fncall = match.group(1) # look inside the parens for function calls + break + + # Except in if/for/while/switch, there should never be space + # immediately inside parens (eg "f( 3, 4 )"). We make an exception + # for nested parens ( (a+b) + c ). Likewise, there should never be + # a space before a ( when it's a function argument. I assume it's a + # function argument when the char before the whitespace is legal in + # a function name (alnum + _) and we're not starting a macro. Also ignore + # pointers and references to arrays and functions coz they're too tricky: + # we use a very simple way to recognize these: + # " (something)(maybe-something)" or + # " (something)(maybe-something," or + # " (something)[something]" + # Note that we assume the contents of [] to be short enough that + # they'll never need to wrap. + if ( # Ignore control structures. + not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b', + fncall) and + # Ignore pointers/references to functions. + not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and + # Ignore pointers/references to arrays. + not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): + if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call + error(filename, linenum, 'whitespace/parens', 4, + 'Extra space after ( in function call') + elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): + error(filename, linenum, 'whitespace/parens', 2, + 'Extra space after (') + if (Search(r'\w\s+\(', fncall) and + not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and + not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and + not Search(r'\bcase\s+\(', fncall)): + # TODO(unknown): Space after an operator function seem to be a common + # error, silence those for now by restricting them to highest verbosity. + if Search(r'\boperator_*\b', line): + error(filename, linenum, 'whitespace/parens', 0, + 'Extra space before ( in function call') + else: + error(filename, linenum, 'whitespace/parens', 4, + 'Extra space before ( in function call') + # If the ) is followed only by a newline or a { + newline, assume it's + # part of a control statement (if/while/etc), and don't complain + if Search(r'[^)]\s+\)\s*[^{\s]', fncall): + # If the closing parenthesis is preceded by only whitespaces, + # try to give a more descriptive error message. + if Search(r'^\s+\)', fncall): + error(filename, linenum, 'whitespace/parens', 2, + 'Closing ) should be moved to the previous line') + else: + error(filename, linenum, 'whitespace/parens', 2, + 'Extra space before )') + + +def IsBlankLine(line): + """Returns true if the given line is blank. + + We consider a line to be blank if the line is empty or consists of + only white spaces. + + Args: + line: A line of a string. + + Returns: + True, if the given line is blank. + """ + return not line or line.isspace() + + +def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line, + error): + is_namespace_indent_item = ( + len(nesting_state.stack) > 1 and + nesting_state.stack[-1].check_namespace_indentation and + isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and + nesting_state.previous_stack_top == nesting_state.stack[-2]) + + if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item, + clean_lines.elided, line): + CheckItemIndentationInNamespace(filename, clean_lines.elided, + line, error) + + +def CheckForFunctionLengths(filename, clean_lines, linenum, + function_state, error): + """Reports for long function bodies. + + For an overview why this is done, see: + http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions + + Uses a simplistic algorithm assuming other style guidelines + (especially spacing) are followed. + Only checks unindented functions, so class members are unchecked. + Trivial bodies are unchecked, so constructors with huge initializer lists + may be missed. + Blank/comment lines are not counted so as to avoid encouraging the removal + of vertical space and comments just to get through a lint check. + NOLINT *on the last line of a function* disables this check. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + function_state: Current function name and lines in body so far. + error: The function to call with any errors found. + """ + lines = clean_lines.lines + line = lines[linenum] + joined_line = '' + + starting_func = False + regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... + match_result = Match(regexp, line) + if match_result: + # If the name is all caps and underscores, figure it's a macro and + # ignore it, unless it's TEST or TEST_F. + function_name = match_result.group(1).split()[-1] + if function_name == 'TEST' or function_name == 'TEST_F' or ( + not Match(r'[A-Z_]+$', function_name)): + starting_func = True + + if starting_func: + body_found = False + for start_linenum in xrange(linenum, clean_lines.NumLines()): + start_line = lines[start_linenum] + joined_line += ' ' + start_line.lstrip() + if Search(r'(;|})', start_line): # Declarations and trivial functions + body_found = True + break # ... ignore + elif Search(r'{', start_line): + body_found = True + function = Search(r'((\w|:)*)\(', line).group(1) + if Match(r'TEST', function): # Handle TEST... macros + parameter_regexp = Search(r'(\(.*\))', joined_line) + if parameter_regexp: # Ignore bad syntax + function += parameter_regexp.group(1) + else: + function += '()' + function_state.Begin(function) + break + if not body_found: + # No body for the function (or evidence of a non-function) was found. + error(filename, linenum, 'readability/fn_size', 5, + 'Lint failed to find start of function body.') + elif Match(r'^\}\s*$', line): # function end + function_state.Check(error, filename, linenum) + function_state.End() + elif not Match(r'^\s*$', line): + function_state.Count() # Count non-blank/non-comment lines. + + +_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') + + +def CheckComment(line, filename, linenum, next_line_start, error): + """Checks for common mistakes in comments. + + Args: + line: The line in question. + filename: The name of the current file. + linenum: The number of the line to check. + next_line_start: The first non-whitespace column of the next line. + error: The function to call with any errors found. + """ + commentpos = line.find('//') + if commentpos != -1: + # Check if the // may be in quotes. If so, ignore it + # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison + if (line.count('"', 0, commentpos) - + line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes + # Allow one space for new scopes, two spaces otherwise: + if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and + ((commentpos >= 1 and + line[commentpos-1] not in string.whitespace) or + (commentpos >= 2 and + line[commentpos-2] not in string.whitespace))): + error(filename, linenum, 'whitespace/comments', 2, + 'At least two spaces is best between code and comments') + + # Checks for common mistakes in TODO comments. + comment = line[commentpos:] + match = _RE_PATTERN_TODO.match(comment) + if match: + # One whitespace is correct; zero whitespace is handled elsewhere. + leading_whitespace = match.group(1) + if len(leading_whitespace) > 1: + error(filename, linenum, 'whitespace/todo', 2, + 'Too many spaces before TODO') + + username = match.group(2) + if not username: + error(filename, linenum, 'readability/todo', 2, + 'Missing username in TODO; it should look like ' + '"// TODO(my_username): Stuff."') + + middle_whitespace = match.group(3) + # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison + if middle_whitespace != ' ' and middle_whitespace != '': + error(filename, linenum, 'whitespace/todo', 2, + 'TODO(my_username) should be followed by a space') + + # If the comment contains an alphanumeric character, there + # should be a space somewhere between it and the // unless + # it's a /// or //! Doxygen comment. + if (Match(r'//[^ ]*\w', comment) and + not Match(r'(///|//\!)(\s+|$)', comment)): + error(filename, linenum, 'whitespace/comments', 4, + 'Should have a space between // and comment') + + +def CheckAccess(filename, clean_lines, linenum, nesting_state, error): + """Checks for improper use of DISALLOW* macros. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] # get rid of comments and strings + + matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|' + r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line) + if not matched: + return + if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo): + if nesting_state.stack[-1].access != 'private': + error(filename, linenum, 'readability/constructors', 3, + '%s must be in the private: section' % matched.group(1)) + + else: + # Found DISALLOW* macro outside a class declaration, or perhaps it + # was used inside a function when it should have been part of the + # class declaration. We could issue a warning here, but it + # probably resulted in a compiler error already. + pass + + +def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): + """Checks for the correctness of various spacing issues in the code. + + Things we check for: spaces around operators, spaces after + if/for/while/switch, no spaces around parens in function calls, two + spaces between code and comment, don't start a block with a blank + line, don't end a function with a blank line, don't add a blank line + after public/protected/private, don't have too many blank lines in a row. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + + # Don't use "elided" lines here, otherwise we can't check commented lines. + # Don't want to use "raw" either, because we don't want to check inside C++11 + # raw strings, + raw = clean_lines.lines_without_raw_strings + line = raw[linenum] + + # Before nixing comments, check if the line is blank for no good + # reason. This includes the first line after a block is opened, and + # blank lines at the end of a function (ie, right before a line like '}' + # + # Skip all the blank line checks if we are immediately inside a + # namespace body. In other words, don't issue blank line warnings + # for this block: + # namespace { + # + # } + # + # A warning about missing end of namespace comments will be issued instead. + # + # Also skip blank line checks for 'extern "C"' blocks, which are formatted + # like namespaces. + if (IsBlankLine(line) and + not nesting_state.InNamespaceBody() and + not nesting_state.InExternC()): + elided = clean_lines.elided + prev_line = elided[linenum - 1] + prevbrace = prev_line.rfind('{') + # TODO(unknown): Don't complain if line before blank line, and line after, + # both start with alnums and are indented the same amount. + # This ignores whitespace at the start of a namespace block + # because those are not usually indented. + if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1: + # OK, we have a blank line at the start of a code block. Before we + # complain, we check if it is an exception to the rule: The previous + # non-empty line has the parameters of a function header that are indented + # 4 spaces (because they did not fit in a 80 column line when placed on + # the same line as the function name). We also check for the case where + # the previous line is indented 6 spaces, which may happen when the + # initializers of a constructor do not fit into a 80 column line. + exception = False + if Match(r' {6}\w', prev_line): # Initializer list? + # We are looking for the opening column of initializer list, which + # should be indented 4 spaces to cause 6 space indentation afterwards. + search_position = linenum-2 + while (search_position >= 0 + and Match(r' {6}\w', elided[search_position])): + search_position -= 1 + exception = (search_position >= 0 + and elided[search_position][:5] == ' :') + else: + # Search for the function arguments or an initializer list. We use a + # simple heuristic here: If the line is indented 4 spaces; and we have a + # closing paren, without the opening paren, followed by an opening brace + # or colon (for initializer lists) we assume that it is the last line of + # a function header. If we have a colon indented 4 spaces, it is an + # initializer list. + exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', + prev_line) + or Match(r' {4}:', prev_line)) + + if not exception: + error(filename, linenum, 'whitespace/blank_line', 2, + 'Redundant blank line at the start of a code block ' + 'should be deleted.') + # Ignore blank lines at the end of a block in a long if-else + # chain, like this: + # if (condition1) { + # // Something followed by a blank line + # + # } else if (condition2) { + # // Something else + # } + if linenum + 1 < clean_lines.NumLines(): + next_line = raw[linenum + 1] + if (next_line + and Match(r'\s*}', next_line) + and next_line.find('} else ') == -1): + error(filename, linenum, 'whitespace/blank_line', 3, + 'Redundant blank line at the end of a code block ' + 'should be deleted.') + + matched = Match(r'\s*(public|protected|private):', prev_line) + if matched: + error(filename, linenum, 'whitespace/blank_line', 3, + 'Do not leave a blank line after "%s:"' % matched.group(1)) + + # Next, check comments + next_line_start = 0 + if linenum + 1 < clean_lines.NumLines(): + next_line = raw[linenum + 1] + next_line_start = len(next_line) - len(next_line.lstrip()) + CheckComment(line, filename, linenum, next_line_start, error) + + # get rid of comments and strings + line = clean_lines.elided[linenum] + + # You shouldn't have spaces before your brackets, except maybe after + # 'delete []' or 'return []() {};' + if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line): + error(filename, linenum, 'whitespace/braces', 5, + 'Extra space before [') + + # In range-based for, we wanted spaces before and after the colon, but + # not around "::" tokens that might appear. + if (Search(r'for *\(.*[^:]:[^: ]', line) or + Search(r'for *\(.*[^: ]:[^:]', line)): + error(filename, linenum, 'whitespace/forcolon', 2, + 'Missing space around colon in range-based for loop') + + +def CheckOperatorSpacing(filename, clean_lines, linenum, error): + """Checks for horizontal spacing around operators. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Don't try to do spacing checks for operator methods. Do this by + # replacing the troublesome characters with something else, + # preserving column position for all other characters. + # + # The replacement is done repeatedly to avoid false positives from + # operators that call operators. + while True: + match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line) + if match: + line = match.group(1) + ('_' * len(match.group(2))) + match.group(3) + else: + break + + # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". + # Otherwise not. Note we only check for non-spaces on *both* sides; + # sometimes people put non-spaces on one side when aligning ='s among + # many lines (not that this is behavior that I approve of...) + if ((Search(r'[\w.]=', line) or + Search(r'=[\w.]', line)) + and not Search(r'\b(if|while|for) ', line) + # Operators taken from [lex.operators] in C++11 standard. + and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line) + and not Search(r'operator=', line)): + error(filename, linenum, 'whitespace/operators', 4, + 'Missing spaces around =') + + # It's ok not to have spaces around binary operators like + - * /, but if + # there's too little whitespace, we get concerned. It's hard to tell, + # though, so we punt on this one for now. TODO. + + # You should always have whitespace around binary operators. + # + # Check <= and >= first to avoid false positives with < and >, then + # check non-include lines for spacing around < and >. + # + # If the operator is followed by a comma, assume it's be used in a + # macro context and don't do any checks. This avoids false + # positives. + # + # Note that && is not included here. Those are checked separately + # in CheckRValueReference + match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line) + if match: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around %s' % match.group(1)) + elif not Match(r'#.*include', line): + # Look for < that is not surrounded by spaces. This is only + # triggered if both sides are missing spaces, even though + # technically should should flag if at least one side is missing a + # space. This is done to avoid some false positives with shifts. + match = Match(r'^(.*[^\s<])<[^\s=<,]', line) + if match: + (_, _, end_pos) = CloseExpression( + clean_lines, linenum, len(match.group(1))) + if end_pos <= -1: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around <') + + # Look for > that is not surrounded by spaces. Similar to the + # above, we only trigger if both sides are missing spaces to avoid + # false positives with shifts. + match = Match(r'^(.*[^-\s>])>[^\s=>,]', line) + if match: + (_, _, start_pos) = ReverseCloseExpression( + clean_lines, linenum, len(match.group(1))) + if start_pos <= -1: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around >') + + # We allow no-spaces around << when used like this: 10<<20, but + # not otherwise (particularly, not when used as streams) + # + # We also allow operators following an opening parenthesis, since + # those tend to be macros that deal with operators. + match = Search(r'(operator|[^\s(<])(?:L|UL|ULL|l|ul|ull)?<<([^\s,=<])', line) + if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and + not (match.group(1) == 'operator' and match.group(2) == ';')): + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around <<') + + # We allow no-spaces around >> for almost anything. This is because + # C++11 allows ">>" to close nested templates, which accounts for + # most cases when ">>" is not followed by a space. + # + # We still warn on ">>" followed by alpha character, because that is + # likely due to ">>" being used for right shifts, e.g.: + # value >> alpha + # + # When ">>" is used to close templates, the alphanumeric letter that + # follows would be part of an identifier, and there should still be + # a space separating the template type and the identifier. + # type> alpha + match = Search(r'>>[a-zA-Z_]', line) + if match: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around >>') + + # There shouldn't be space around unary operators + match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) + if match: + error(filename, linenum, 'whitespace/operators', 4, + 'Extra space for operator %s' % match.group(1)) + + +def CheckParenthesisSpacing(filename, clean_lines, linenum, error): + """Checks for horizontal spacing around parentheses. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # No spaces after an if, while, switch, or for + match = Search(r' (if\(|for\(|while\(|switch\()', line) + if match: + error(filename, linenum, 'whitespace/parens', 5, + 'Missing space before ( in %s' % match.group(1)) + + # For if/for/while/switch, the left and right parens should be + # consistent about how many spaces are inside the parens, and + # there should either be zero or one spaces inside the parens. + # We don't want: "if ( foo)" or "if ( foo )". + # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. + match = Search(r'\b(if|for|while|switch)\s*' + r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', + line) + if match: + if len(match.group(2)) != len(match.group(4)): + if not (match.group(3) == ';' and + len(match.group(2)) == 1 + len(match.group(4)) or + not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): + error(filename, linenum, 'whitespace/parens', 5, + 'Mismatching spaces inside () in %s' % match.group(1)) + if len(match.group(2)) not in [0, 1]: + error(filename, linenum, 'whitespace/parens', 5, + 'Should have zero or one spaces inside ( and ) in %s' % + match.group(1)) + + +def CheckCommaSpacing(filename, clean_lines, linenum, error): + """Checks for horizontal spacing near commas and semicolons. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + raw = clean_lines.lines_without_raw_strings + line = clean_lines.elided[linenum] + + # You should always have a space after a comma (either as fn arg or operator) + # + # This does not apply when the non-space character following the + # comma is another comma, since the only time when that happens is + # for empty macro arguments. + # + # We run this check in two passes: first pass on elided lines to + # verify that lines contain missing whitespaces, second pass on raw + # lines to confirm that those missing whitespaces are not due to + # elided comments. + if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and + Search(r',[^,\s]', raw[linenum])): + error(filename, linenum, 'whitespace/comma', 3, + 'Missing space after ,') + + # You should always have a space after a semicolon + # except for few corner cases + # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more + # space after ; + if Search(r';[^\s};\\)/]', line): + error(filename, linenum, 'whitespace/semicolon', 3, + 'Missing space after ;') + + +def CheckBracesSpacing(filename, clean_lines, linenum, error): + """Checks for horizontal spacing near commas. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Except after an opening paren, or after another opening brace (in case of + # an initializer list, for instance), you should have spaces before your + # braces. And since you should never have braces at the beginning of a line, + # this is an easy test. + match = Match(r'^(.*[^ ({>]){', line) + if match: + # Try a bit harder to check for brace initialization. This + # happens in one of the following forms: + # Constructor() : initializer_list_{} { ... } + # Constructor{}.MemberFunction() + # Type variable{}; + # FunctionCall(type{}, ...); + # LastArgument(..., type{}); + # LOG(INFO) << type{} << " ..."; + # map_of_type[{...}] = ...; + # ternary = expr ? new type{} : nullptr; + # OuterTemplate{}> + # + # We check for the character following the closing brace, and + # silence the warning if it's one of those listed above, i.e. + # "{.;,)<>]:". + # + # To account for nested initializer list, we allow any number of + # closing braces up to "{;,)<". We can't simply silence the + # warning on first sight of closing brace, because that would + # cause false negatives for things that are not initializer lists. + # Silence this: But not this: + # Outer{ if (...) { + # Inner{...} if (...){ // Missing space before { + # }; } + # + # There is a false negative with this approach if people inserted + # spurious semicolons, e.g. "if (cond){};", but we will catch the + # spurious semicolon with a separate check. + (endline, endlinenum, endpos) = CloseExpression( + clean_lines, linenum, len(match.group(1))) + trailing_text = '' + if endpos > -1: + trailing_text = endline[endpos:] + for offset in xrange(endlinenum + 1, + min(endlinenum + 3, clean_lines.NumLines() - 1)): + trailing_text += clean_lines.elided[offset] + if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text): + error(filename, linenum, 'whitespace/braces', 5, + 'Missing space before {') + + # Make sure '} else {' has spaces. + if Search(r'}else', line): + error(filename, linenum, 'whitespace/braces', 5, + 'Missing space before else') + + # You shouldn't have a space before a semicolon at the end of the line. + # There's a special case for "for" since the style guide allows space before + # the semicolon there. + if Search(r':\s*;\s*$', line): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Semicolon defining empty statement. Use {} instead.') + elif Search(r'^\s*;\s*$', line): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Line contains only semicolon. If this should be an empty statement, ' + 'use {} instead.') + elif (Search(r'\s+;\s*$', line) and + not Search(r'\bfor\b', line)): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Extra space before last semicolon. If this should be an empty ' + 'statement, use {} instead.') + + +def IsDecltype(clean_lines, linenum, column): + """Check if the token ending on (linenum, column) is decltype(). + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: the number of the line to check. + column: end column of the token to check. + Returns: + True if this token is decltype() expression, False otherwise. + """ + (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column) + if start_col < 0: + return False + if Search(r'\bdecltype\s*$', text[0:start_col]): + return True + return False + + +def IsTemplateParameterList(clean_lines, linenum, column): + """Check if the token ending on (linenum, column) is the end of template<>. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: the number of the line to check. + column: end column of the token to check. + Returns: + True if this token is end of a template parameter list, False otherwise. + """ + (_, startline, startpos) = ReverseCloseExpression( + clean_lines, linenum, column) + if (startpos > -1 and + Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])): + return True + return False + + +def IsRValueType(typenames, clean_lines, nesting_state, linenum, column): + """Check if the token ending on (linenum, column) is a type. + + Assumes that text to the right of the column is "&&" or a function + name. + + Args: + typenames: set of type names from template-argument-list. + clean_lines: A CleansedLines instance containing the file. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + linenum: the number of the line to check. + column: end column of the token to check. + Returns: + True if this token is a type, False if we are not sure. + """ + prefix = clean_lines.elided[linenum][0:column] + + # Get one word to the left. If we failed to do so, this is most + # likely not a type, since it's unlikely that the type name and "&&" + # would be split across multiple lines. + match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix) + if not match: + return False + + # Check text following the token. If it's "&&>" or "&&," or "&&...", it's + # most likely a rvalue reference used inside a template. + suffix = clean_lines.elided[linenum][column:] + if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix): + return True + + # Check for known types and end of templates: + # int&& variable + # vector&& variable + # + # Because this function is called recursively, we also need to + # recognize pointer and reference types: + # int* Function() + # int& Function() + if (match.group(2) in typenames or + match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool', + 'short', 'int', 'long', 'signed', 'unsigned', + 'float', 'double', 'void', 'auto', '>', '*', '&']): + return True + + # If we see a close parenthesis, look for decltype on the other side. + # decltype would unambiguously identify a type, anything else is + # probably a parenthesized expression and not a type. + if match.group(2) == ')': + return IsDecltype( + clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1) + + # Check for casts and cv-qualifiers. + # match.group(1) remainder + # -------------- --------- + # const_cast< type&& + # const type&& + # type const&& + if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|' + r'reinterpret_cast\s*<|\w+\s)\s*$', + match.group(1)): + return True + + # Look for a preceding symbol that might help differentiate the context. + # These are the cases that would be ambiguous: + # match.group(1) remainder + # -------------- --------- + # Call ( expression && + # Declaration ( type&& + # sizeof ( type&& + # if ( expression && + # while ( expression && + # for ( type&& + # for( ; expression && + # statement ; type&& + # block { type&& + # constructor { expression && + start = linenum + line = match.group(1) + match_symbol = None + while start >= 0: + # We want to skip over identifiers and commas to get to a symbol. + # Commas are skipped so that we can find the opening parenthesis + # for function parameter lists. + match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line) + if match_symbol: + break + start -= 1 + line = clean_lines.elided[start] + + if not match_symbol: + # Probably the first statement in the file is an rvalue reference + return True + + if match_symbol.group(2) == '}': + # Found closing brace, probably an indicate of this: + # block{} type&& + return True + + if match_symbol.group(2) == ';': + # Found semicolon, probably one of these: + # for(; expression && + # statement; type&& + + # Look for the previous 'for(' in the previous lines. + before_text = match_symbol.group(1) + for i in xrange(start - 1, max(start - 6, 0), -1): + before_text = clean_lines.elided[i] + before_text + if Search(r'for\s*\([^{};]*$', before_text): + # This is the condition inside a for-loop + return False + + # Did not find a for-init-statement before this semicolon, so this + # is probably a new statement and not a condition. + return True + + if match_symbol.group(2) == '{': + # Found opening brace, probably one of these: + # block{ type&& = ... ; } + # constructor{ expression && expression } + + # Look for a closing brace or a semicolon. If we see a semicolon + # first, this is probably a rvalue reference. + line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1] + end = start + depth = 1 + while True: + for ch in line: + if ch == ';': + return True + elif ch == '{': + depth += 1 + elif ch == '}': + depth -= 1 + if depth == 0: + return False + end += 1 + if end >= clean_lines.NumLines(): + break + line = clean_lines.elided[end] + # Incomplete program? + return False + + if match_symbol.group(2) == '(': + # Opening parenthesis. Need to check what's to the left of the + # parenthesis. Look back one extra line for additional context. + before_text = match_symbol.group(1) + if linenum > 1: + before_text = clean_lines.elided[linenum - 1] + before_text + before_text = match_symbol.group(1) + + # Patterns that are likely to be types: + # [](type&& + # for (type&& + # sizeof(type&& + # operator=(type&& + # + if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text): + return True + + # Patterns that are likely to be expressions: + # if (expression && + # while (expression && + # : initializer(expression && + # , initializer(expression && + # ( FunctionCall(expression && + # + FunctionCall(expression && + # + (expression && + # + # The last '+' represents operators such as '+' and '-'. + if Search(r'(?:\bif|\bwhile|[-+=%^(]*>)?\s*$', + match_symbol.group(1)) + if match_func: + # Check for constructors, which don't have return types. + if Search(r'\b(?:explicit|inline)$', match_func.group(1)): + return True + implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix) + if (implicit_constructor and + implicit_constructor.group(1) == implicit_constructor.group(2)): + return True + return IsRValueType(typenames, clean_lines, nesting_state, linenum, + len(match_func.group(1))) + + # Nothing before the function name. If this is inside a block scope, + # this is probably a function call. + return not (nesting_state.previous_stack_top and + nesting_state.previous_stack_top.IsBlockInfo()) + + if match_symbol.group(2) == '>': + # Possibly a closing bracket, check that what's on the other side + # looks like the start of a template. + return IsTemplateParameterList( + clean_lines, start, len(match_symbol.group(1))) + + # Some other symbol, usually something like "a=b&&c". This is most + # likely not a type. + return False + + +def IsDeletedOrDefault(clean_lines, linenum): + """Check if current constructor or operator is deleted or default. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + Returns: + True if this is a deleted or default constructor. + """ + open_paren = clean_lines.elided[linenum].find('(') + if open_paren < 0: + return False + (close_line, _, close_paren) = CloseExpression( + clean_lines, linenum, open_paren) + if close_paren < 0: + return False + return Match(r'\s*=\s*(?:delete|default)\b', close_line[close_paren:]) + + +def IsRValueAllowed(clean_lines, linenum, typenames): + """Check if RValue reference is allowed on a particular line. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + typenames: set of type names from template-argument-list. + Returns: + True if line is within the region where RValue references are allowed. + """ + # Allow region marked by PUSH/POP macros + for i in xrange(linenum, 0, -1): + line = clean_lines.elided[i] + if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): + if not line.endswith('PUSH'): + return False + for j in xrange(linenum, clean_lines.NumLines(), 1): + line = clean_lines.elided[j] + if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): + return line.endswith('POP') + + # Allow operator= + line = clean_lines.elided[linenum] + if Search(r'\boperator\s*=\s*\(', line): + return IsDeletedOrDefault(clean_lines, linenum) + + # Allow constructors + match = Match(r'\s*(?:[\w<>]+::)*([\w<>]+)\s*::\s*([\w<>]+)\s*\(', line) + if match and match.group(1) == match.group(2): + return IsDeletedOrDefault(clean_lines, linenum) + if Search(r'\b(?:explicit|inline)\s+[\w<>]+\s*\(', line): + return IsDeletedOrDefault(clean_lines, linenum) + + if Match(r'\s*[\w<>]+\s*\(', line): + previous_line = 'ReturnType' + if linenum > 0: + previous_line = clean_lines.elided[linenum - 1] + if Match(r'^\s*$', previous_line) or Search(r'[{}:;]\s*$', previous_line): + return IsDeletedOrDefault(clean_lines, linenum) + + # Reject types not mentioned in template-argument-list + while line: + match = Match(r'^.*?(\w+)\s*&&(.*)$', line) + if not match: + break + if match.group(1) not in typenames: + return False + line = match.group(2) + + # All RValue types that were in template-argument-list should have + # been removed by now. Those were allowed, assuming that they will + # be forwarded. + # + # If there are no remaining RValue types left (i.e. types that were + # not found in template-argument-list), flag those as not allowed. + return line.find('&&') < 0 + + +def GetTemplateArgs(clean_lines, linenum): + """Find list of template arguments associated with this function declaration. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: Line number containing the start of the function declaration, + usually one line after the end of the template-argument-list. + Returns: + Set of type names, or empty set if this does not appear to have + any template parameters. + """ + # Find start of function + func_line = linenum + while func_line > 0: + line = clean_lines.elided[func_line] + if Match(r'^\s*$', line): + return set() + if line.find('(') >= 0: + break + func_line -= 1 + if func_line == 0: + return set() + + # Collapse template-argument-list into a single string + argument_list = '' + match = Match(r'^(\s*template\s*)<', clean_lines.elided[func_line]) + if match: + # template-argument-list on the same line as function name + start_col = len(match.group(1)) + _, end_line, end_col = CloseExpression(clean_lines, func_line, start_col) + if end_col > -1 and end_line == func_line: + start_col += 1 # Skip the opening bracket + argument_list = clean_lines.elided[func_line][start_col:end_col] + + elif func_line > 1: + # template-argument-list one line before function name + match = Match(r'^(.*)>\s*$', clean_lines.elided[func_line - 1]) + if match: + end_col = len(match.group(1)) + _, start_line, start_col = ReverseCloseExpression( + clean_lines, func_line - 1, end_col) + if start_col > -1: + start_col += 1 # Skip the opening bracket + while start_line < func_line - 1: + argument_list += clean_lines.elided[start_line][start_col:] + start_col = 0 + start_line += 1 + argument_list += clean_lines.elided[func_line - 1][start_col:end_col] + + if not argument_list: + return set() + + # Extract type names + typenames = set() + while True: + match = Match(r'^[,\s]*(?:typename|class)(?:\.\.\.)?\s+(\w+)(.*)$', + argument_list) + if not match: + break + typenames.add(match.group(1)) + argument_list = match.group(2) + return typenames + + +def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error): + """Check for rvalue references. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + # Find lines missing spaces around &&. + # TODO(unknown): currently we don't check for rvalue references + # with spaces surrounding the && to avoid false positives with + # boolean expressions. + line = clean_lines.elided[linenum] + match = Match(r'^(.*\S)&&', line) + if not match: + match = Match(r'(.*)&&\S', line) + if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)): + return + + # Either poorly formed && or an rvalue reference, check the context + # to get a more accurate error message. Mostly we want to determine + # if what's to the left of "&&" is a type or not. + typenames = GetTemplateArgs(clean_lines, linenum) + and_pos = len(match.group(1)) + if IsRValueType(typenames, clean_lines, nesting_state, linenum, and_pos): + if not IsRValueAllowed(clean_lines, linenum, typenames): + error(filename, linenum, 'build/c++11', 3, + 'RValue references are an unapproved C++ feature.') + else: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around &&') + + +def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): + """Checks for additional blank line issues related to sections. + + Currently the only thing checked here is blank line before protected/private. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + class_info: A _ClassInfo objects. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + # Skip checks if the class is small, where small means 25 lines or less. + # 25 lines seems like a good cutoff since that's the usual height of + # terminals, and any class that can't fit in one screen can't really + # be considered "small". + # + # Also skip checks if we are on the first line. This accounts for + # classes that look like + # class Foo { public: ... }; + # + # If we didn't find the end of the class, last_line would be zero, + # and the check will be skipped by the first condition. + if (class_info.last_line - class_info.starting_linenum <= 24 or + linenum <= class_info.starting_linenum): + return + + matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) + if matched: + # Issue warning if the line before public/protected/private was + # not a blank line, but don't do this if the previous line contains + # "class" or "struct". This can happen two ways: + # - We are at the beginning of the class. + # - We are forward-declaring an inner class that is semantically + # private, but needed to be public for implementation reasons. + # Also ignores cases where the previous line ends with a backslash as can be + # common when defining classes in C macros. + prev_line = clean_lines.lines[linenum - 1] + if (not IsBlankLine(prev_line) and + not Search(r'\b(class|struct)\b', prev_line) and + not Search(r'\\$', prev_line)): + # Try a bit harder to find the beginning of the class. This is to + # account for multi-line base-specifier lists, e.g.: + # class Derived + # : public Base { + end_class_head = class_info.starting_linenum + for i in range(class_info.starting_linenum, linenum): + if Search(r'\{\s*$', clean_lines.lines[i]): + end_class_head = i + break + if end_class_head < linenum - 1: + error(filename, linenum, 'whitespace/blank_line', 3, + '"%s:" should be preceded by a blank line' % matched.group(1)) + + +def GetPreviousNonBlankLine(clean_lines, linenum): + """Return the most recent non-blank line and its line number. + + Args: + clean_lines: A CleansedLines instance containing the file contents. + linenum: The number of the line to check. + + Returns: + A tuple with two elements. The first element is the contents of the last + non-blank line before the current line, or the empty string if this is the + first non-blank line. The second is the line number of that line, or -1 + if this is the first non-blank line. + """ + + prevlinenum = linenum - 1 + while prevlinenum >= 0: + prevline = clean_lines.elided[prevlinenum] + if not IsBlankLine(prevline): # if not a blank line... + return (prevline, prevlinenum) + prevlinenum -= 1 + return ('', -1) + + +def CheckBraces(filename, clean_lines, linenum, error): + """Looks for misplaced braces (e.g. at the end of line). + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + line = clean_lines.elided[linenum] # get rid of comments and strings + + if Match(r'\s*{\s*$', line): + # We allow an open brace to start a line in the case where someone is using + # braces in a block to explicitly create a new scope, which is commonly used + # to control the lifetime of stack-allocated variables. Braces are also + # used for brace initializers inside function calls. We don't detect this + # perfectly: we just don't complain if the last non-whitespace character on + # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the + # previous line starts a preprocessor block. + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if (not Search(r'[,;:}{(]\s*$', prevline) and + not Match(r'\s*#', prevline)): + error(filename, linenum, 'whitespace/braces', 4, + '{ should almost always be at the end of the previous line') + + # An else clause should be on the same line as the preceding closing brace. + if Match(r'\s*else\b\s*(?:if\b|\{|$)', line): + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if Match(r'\s*}\s*$', prevline): + error(filename, linenum, 'whitespace/newline', 4, + 'An else should appear on the same line as the preceding }') + + # If braces come on one side of an else, they should be on both. + # However, we have to worry about "else if" that spans multiple lines! + if Search(r'else if\s*\(', line): # could be multi-line if + brace_on_left = bool(Search(r'}\s*else if\s*\(', line)) + # find the ( after the if + pos = line.find('else if') + pos = line.find('(', pos) + if pos > 0: + (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) + brace_on_right = endline[endpos:].find('{') != -1 + if brace_on_left != brace_on_right: # must be brace after if + error(filename, linenum, 'readability/braces', 5, + 'If an else has a brace on one side, it should have it on both') + elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): + error(filename, linenum, 'readability/braces', 5, + 'If an else has a brace on one side, it should have it on both') + + # Likewise, an else should never have the else clause on the same line + if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): + error(filename, linenum, 'whitespace/newline', 4, + 'Else clause should never be on same line as else (use 2 lines)') + + # In the same way, a do/while should never be on one line + if Match(r'\s*do [^\s{]', line): + error(filename, linenum, 'whitespace/newline', 4, + 'do/while clauses should not be on a single line') + + # Check single-line if/else bodies. The style guide says 'curly braces are not + # required for single-line statements'. We additionally allow multi-line, + # single statements, but we reject anything with more than one semicolon in + # it. This means that the first semicolon after the if should be at the end of + # its line, and the line after that should have an indent level equal to or + # lower than the if. We also check for ambiguous if/else nesting without + # braces. + if_else_match = Search(r'\b(if\s*\(|else\b)', line) + if if_else_match and not Match(r'\s*#', line): + if_indent = GetIndentLevel(line) + endline, endlinenum, endpos = line, linenum, if_else_match.end() + if_match = Search(r'\bif\s*\(', line) + if if_match: + # This could be a multiline if condition, so find the end first. + pos = if_match.end() - 1 + (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos) + # Check for an opening brace, either directly after the if or on the next + # line. If found, this isn't a single-statement conditional. + if (not Match(r'\s*{', endline[endpos:]) + and not (Match(r'\s*$', endline[endpos:]) + and endlinenum < (len(clean_lines.elided) - 1) + and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))): + while (endlinenum < len(clean_lines.elided) + and ';' not in clean_lines.elided[endlinenum][endpos:]): + endlinenum += 1 + endpos = 0 + if endlinenum < len(clean_lines.elided): + endline = clean_lines.elided[endlinenum] + # We allow a mix of whitespace and closing braces (e.g. for one-liner + # methods) and a single \ after the semicolon (for macros) + endpos = endline.find(';') + if not Match(r';[\s}]*(\\?)$', endline[endpos:]): + # Semicolon isn't the last character, there's something trailing. + # Output a warning if the semicolon is not contained inside + # a lambda expression. + if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$', + endline): + error(filename, linenum, 'readability/braces', 4, + 'If/else bodies with multiple statements require braces') + elif endlinenum < len(clean_lines.elided) - 1: + # Make sure the next line is dedented + next_line = clean_lines.elided[endlinenum + 1] + next_indent = GetIndentLevel(next_line) + # With ambiguous nested if statements, this will error out on the + # if that *doesn't* match the else, regardless of whether it's the + # inner one or outer one. + if (if_match and Match(r'\s*else\b', next_line) + and next_indent != if_indent): + error(filename, linenum, 'readability/braces', 4, + 'Else clause should be indented at the same level as if. ' + 'Ambiguous nested if/else chains require braces.') + elif next_indent > if_indent: + error(filename, linenum, 'readability/braces', 4, + 'If/else bodies with multiple statements require braces') + + +def CheckTrailingSemicolon(filename, clean_lines, linenum, error): + """Looks for redundant trailing semicolon. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + line = clean_lines.elided[linenum] + + # Block bodies should not be followed by a semicolon. Due to C++11 + # brace initialization, there are more places where semicolons are + # required than not, so we use a whitelist approach to check these + # rather than a blacklist. These are the places where "};" should + # be replaced by just "}": + # 1. Some flavor of block following closing parenthesis: + # for (;;) {}; + # while (...) {}; + # switch (...) {}; + # Function(...) {}; + # if (...) {}; + # if (...) else if (...) {}; + # + # 2. else block: + # if (...) else {}; + # + # 3. const member function: + # Function(...) const {}; + # + # 4. Block following some statement: + # x = 42; + # {}; + # + # 5. Block at the beginning of a function: + # Function(...) { + # {}; + # } + # + # Note that naively checking for the preceding "{" will also match + # braces inside multi-dimensional arrays, but this is fine since + # that expression will not contain semicolons. + # + # 6. Block following another block: + # while (true) {} + # {}; + # + # 7. End of namespaces: + # namespace {}; + # + # These semicolons seems far more common than other kinds of + # redundant semicolons, possibly due to people converting classes + # to namespaces. For now we do not warn for this case. + # + # Try matching case 1 first. + match = Match(r'^(.*\)\s*)\{', line) + if match: + # Matched closing parenthesis (case 1). Check the token before the + # matching opening parenthesis, and don't warn if it looks like a + # macro. This avoids these false positives: + # - macro that defines a base class + # - multi-line macro that defines a base class + # - macro that defines the whole class-head + # + # But we still issue warnings for macros that we know are safe to + # warn, specifically: + # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P + # - TYPED_TEST + # - INTERFACE_DEF + # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: + # + # We implement a whitelist of safe macros instead of a blacklist of + # unsafe macros, even though the latter appears less frequently in + # google code and would have been easier to implement. This is because + # the downside for getting the whitelist wrong means some extra + # semicolons, while the downside for getting the blacklist wrong + # would result in compile errors. + # + # In addition to macros, we also don't want to warn on + # - Compound literals + # - Lambdas + # - alignas specifier with anonymous structs: + closing_brace_pos = match.group(1).rfind(')') + opening_parenthesis = ReverseCloseExpression( + clean_lines, linenum, closing_brace_pos) + if opening_parenthesis[2] > -1: + line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] + macro = Search(r'\b([A-Z_]+)\s*$', line_prefix) + func = Match(r'^(.*\])\s*$', line_prefix) + if ((macro and + macro.group(1) not in ( + 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', + 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', + 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or + (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or + Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or + Search(r'\s+=\s*$', line_prefix)): + match = None + if (match and + opening_parenthesis[1] > 1 and + Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])): + # Multi-line lambda-expression + match = None + + else: + # Try matching cases 2-3. + match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) + if not match: + # Try matching cases 4-6. These are always matched on separate lines. + # + # Note that we can't simply concatenate the previous line to the + # current line and do a single match, otherwise we may output + # duplicate warnings for the blank line case: + # if (cond) { + # // blank line + # } + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if prevline and Search(r'[;{}]\s*$', prevline): + match = Match(r'^(\s*)\{', line) + + # Check matching closing brace + if match: + (endline, endlinenum, endpos) = CloseExpression( + clean_lines, linenum, len(match.group(1))) + if endpos > -1 and Match(r'^\s*;', endline[endpos:]): + # Current {} pair is eligible for semicolon check, and we have found + # the redundant semicolon, output warning here. + # + # Note: because we are scanning forward for opening braces, and + # outputting warnings for the matching closing brace, if there are + # nested blocks with trailing semicolons, we will get the error + # messages in reversed order. + error(filename, endlinenum, 'readability/braces', 4, + "You don't need a ; after a }") + + +def CheckEmptyBlockBody(filename, clean_lines, linenum, error): + """Look for empty loop/conditional body with only a single semicolon. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + # Search for loop keywords at the beginning of the line. Because only + # whitespaces are allowed before the keywords, this will also ignore most + # do-while-loops, since those lines should start with closing brace. + # + # We also check "if" blocks here, since an empty conditional block + # is likely an error. + line = clean_lines.elided[linenum] + matched = Match(r'\s*(for|while|if)\s*\(', line) + if matched: + # Find the end of the conditional expression + (end_line, end_linenum, end_pos) = CloseExpression( + clean_lines, linenum, line.find('(')) + + # Output warning if what follows the condition expression is a semicolon. + # No warning for all other cases, including whitespace or newline, since we + # have a separate check for semicolons preceded by whitespace. + if end_pos >= 0 and Match(r';', end_line[end_pos:]): + if matched.group(1) == 'if': + error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, + 'Empty conditional bodies should use {}') + else: + error(filename, end_linenum, 'whitespace/empty_loop_body', 5, + 'Empty loop bodies should use {} or continue') + + +def FindCheckMacro(line): + """Find a replaceable CHECK-like macro. + + Args: + line: line to search on. + Returns: + (macro name, start position), or (None, -1) if no replaceable + macro is found. + """ + for macro in _CHECK_MACROS: + i = line.find(macro) + if i >= 0: + # Find opening parenthesis. Do a regular expression match here + # to make sure that we are matching the expected CHECK macro, as + # opposed to some other macro that happens to contain the CHECK + # substring. + matched = Match(r'^(.*\b' + macro + r'\s*)\(', line) + if not matched: + continue + return (macro, len(matched.group(1))) + return (None, -1) + + +def CheckCheck(filename, clean_lines, linenum, error): + """Checks the use of CHECK and EXPECT macros. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + # Decide the set of replacement macros that should be suggested + lines = clean_lines.elided + (check_macro, start_pos) = FindCheckMacro(lines[linenum]) + if not check_macro: + return + + # Find end of the boolean expression by matching parentheses + (last_line, end_line, end_pos) = CloseExpression( + clean_lines, linenum, start_pos) + if end_pos < 0: + return + + # If the check macro is followed by something other than a + # semicolon, assume users will log their own custom error messages + # and don't suggest any replacements. + if not Match(r'\s*;', last_line[end_pos:]): + return + + if linenum == end_line: + expression = lines[linenum][start_pos + 1:end_pos - 1] + else: + expression = lines[linenum][start_pos + 1:] + for i in xrange(linenum + 1, end_line): + expression += lines[i] + expression += last_line[0:end_pos - 1] + + # Parse expression so that we can take parentheses into account. + # This avoids false positives for inputs like "CHECK((a < 4) == b)", + # which is not replaceable by CHECK_LE. + lhs = '' + rhs = '' + operator = None + while expression: + matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' + r'==|!=|>=|>|<=|<|\()(.*)$', expression) + if matched: + token = matched.group(1) + if token == '(': + # Parenthesized operand + expression = matched.group(2) + (end, _) = FindEndOfExpressionInLine(expression, 0, ['(']) + if end < 0: + return # Unmatched parenthesis + lhs += '(' + expression[0:end] + expression = expression[end:] + elif token in ('&&', '||'): + # Logical and/or operators. This means the expression + # contains more than one term, for example: + # CHECK(42 < a && a < b); + # + # These are not replaceable with CHECK_LE, so bail out early. + return + elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'): + # Non-relational operator + lhs += token + expression = matched.group(2) + else: + # Relational operator + operator = token + rhs = matched.group(2) + break + else: + # Unparenthesized operand. Instead of appending to lhs one character + # at a time, we do another regular expression match to consume several + # characters at once if possible. Trivial benchmark shows that this + # is more efficient when the operands are longer than a single + # character, which is generally the case. + matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression) + if not matched: + matched = Match(r'^(\s*\S)(.*)$', expression) + if not matched: + break + lhs += matched.group(1) + expression = matched.group(2) + + # Only apply checks if we got all parts of the boolean expression + if not (lhs and operator and rhs): + return + + # Check that rhs do not contain logical operators. We already know + # that lhs is fine since the loop above parses out && and ||. + if rhs.find('&&') > -1 or rhs.find('||') > -1: + return + + # At least one of the operands must be a constant literal. This is + # to avoid suggesting replacements for unprintable things like + # CHECK(variable != iterator) + # + # The following pattern matches decimal, hex integers, strings, and + # characters (in that order). + lhs = lhs.strip() + rhs = rhs.strip() + match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' + if Match(match_constant, lhs) or Match(match_constant, rhs): + # Note: since we know both lhs and rhs, we can provide a more + # descriptive error message like: + # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42) + # Instead of: + # Consider using CHECK_EQ instead of CHECK(a == b) + # + # We are still keeping the less descriptive message because if lhs + # or rhs gets long, the error message might become unreadable. + error(filename, linenum, 'readability/check', 2, + 'Consider using %s instead of %s(a %s b)' % ( + _CHECK_REPLACEMENT[check_macro][operator], + check_macro, operator)) + + +def CheckAltTokens(filename, clean_lines, linenum, error): + """Check alternative keywords being used in boolean expressions. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Avoid preprocessor lines + if Match(r'^\s*#', line): + return + + # Last ditch effort to avoid multi-line comments. This will not help + # if the comment started before the current line or ended after the + # current line, but it catches most of the false positives. At least, + # it provides a way to workaround this warning for people who use + # multi-line comments in preprocessor macros. + # + # TODO(unknown): remove this once cpplint has better support for + # multi-line comments. + if line.find('/*') >= 0 or line.find('*/') >= 0: + return + + for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line): + error(filename, linenum, 'readability/alt_tokens', 2, + 'Use operator %s instead of %s' % ( + _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1))) + + +def GetLineWidth(line): + """Determines the width of the line in column positions. + + Args: + line: A string, which may be a Unicode string. + + Returns: + The width of the line in column positions, accounting for Unicode + combining characters and wide characters. + """ + if isinstance(line, unicode): + width = 0 + for uc in unicodedata.normalize('NFC', line): + if unicodedata.east_asian_width(uc) in ('W', 'F'): + width += 2 + elif not unicodedata.combining(uc): + width += 1 + return width + else: + return len(line) + + +def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, + error): + """Checks rules from the 'C++ style rules' section of cppguide.html. + + Most of these rules are hard to test (naming, comment style), but we + do what we can. In particular we check for 2-space indents, line lengths, + tab usage, spaces inside code, etc. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + file_extension: The extension (without the dot) of the filename. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + + # Don't use "elided" lines here, otherwise we can't check commented lines. + # Don't want to use "raw" either, because we don't want to check inside C++11 + # raw strings, + raw_lines = clean_lines.lines_without_raw_strings + line = raw_lines[linenum] + + if line.find('\t') != -1: + error(filename, linenum, 'whitespace/tab', 1, + 'Tab found; better to use spaces') + + # One or three blank spaces at the beginning of the line is weird; it's + # hard to reconcile that with 2-space indents. + # NOTE: here are the conditions rob pike used for his tests. Mine aren't + # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces + # if(RLENGTH > 20) complain = 0; + # if(match($0, " +(error|private|public|protected):")) complain = 0; + # if(match(prev, "&& *$")) complain = 0; + # if(match(prev, "\\|\\| *$")) complain = 0; + # if(match(prev, "[\",=><] *$")) complain = 0; + # if(match($0, " <<")) complain = 0; + # if(match(prev, " +for \\(")) complain = 0; + # if(prevodd && match(prevprev, " +for \\(")) complain = 0; + scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$' + classinfo = nesting_state.InnermostClass() + initial_spaces = 0 + cleansed_line = clean_lines.elided[linenum] + while initial_spaces < len(line) and line[initial_spaces] == ' ': + initial_spaces += 1 + if line and line[-1].isspace(): + error(filename, linenum, 'whitespace/end_of_line', 4, + 'Line ends in whitespace. Consider deleting these extra spaces.') + # There are certain situations we allow one space, notably for + # section labels, and also lines containing multi-line raw strings. + elif ((initial_spaces == 1 or initial_spaces == 3) and + not Match(scope_or_label_pattern, cleansed_line) and + not (clean_lines.raw_lines[linenum] != line and + Match(r'^\s*""', line))): + error(filename, linenum, 'whitespace/indent', 3, + 'Weird number of spaces at line-start. ' + 'Are you using a 2-space indent?') + + # Check if the line is a header guard. + is_header_guard = False + if file_extension == 'h': + cppvar = GetHeaderGuardCPPVariable(filename) + if (line.startswith('#ifndef %s' % cppvar) or + line.startswith('#define %s' % cppvar) or + line.startswith('#endif // %s' % cppvar)): + is_header_guard = True + # #include lines and header guards can be long, since there's no clean way to + # split them. + # + # URLs can be long too. It's possible to split these, but it makes them + # harder to cut&paste. + # + # The "$Id:...$" comment may also get very long without it being the + # developers fault. + if (not line.startswith('#include') and not is_header_guard and + not Match(r'^\s*//.*http(s?)://\S*$', line) and + not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): + line_width = GetLineWidth(line) + extended_length = int((_line_length * 1.25)) + if line_width > extended_length: + error(filename, linenum, 'whitespace/line_length', 4, + 'Lines should very rarely be longer than %i characters' % + extended_length) + elif line_width > _line_length: + error(filename, linenum, 'whitespace/line_length', 2, + 'Lines should be <= %i characters long' % _line_length) + + if (cleansed_line.count(';') > 1 and + # for loops are allowed two ;'s (and may run over two lines). + cleansed_line.find('for') == -1 and + (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or + GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and + # It's ok to have many commands in a switch case that fits in 1 line + not ((cleansed_line.find('case ') != -1 or + cleansed_line.find('default:') != -1) and + cleansed_line.find('break;') != -1)): + error(filename, linenum, 'whitespace/newline', 0, + 'More than one command on the same line') + + # Some more style checks + CheckBraces(filename, clean_lines, linenum, error) + CheckTrailingSemicolon(filename, clean_lines, linenum, error) + CheckEmptyBlockBody(filename, clean_lines, linenum, error) + CheckAccess(filename, clean_lines, linenum, nesting_state, error) + CheckSpacing(filename, clean_lines, linenum, nesting_state, error) + CheckOperatorSpacing(filename, clean_lines, linenum, error) + CheckParenthesisSpacing(filename, clean_lines, linenum, error) + CheckCommaSpacing(filename, clean_lines, linenum, error) + CheckBracesSpacing(filename, clean_lines, linenum, error) + CheckSpacingForFunctionCall(filename, clean_lines, linenum, error) + CheckRValueReference(filename, clean_lines, linenum, nesting_state, error) + CheckCheck(filename, clean_lines, linenum, error) + CheckAltTokens(filename, clean_lines, linenum, error) + classinfo = nesting_state.InnermostClass() + if classinfo: + CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) + + +_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') +# Matches the first component of a filename delimited by -s and _s. That is: +# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' +_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') + + +def _DropCommonSuffixes(filename): + """Drops common suffixes like _test.cc or -inl.h from filename. + + For example: + >>> _DropCommonSuffixes('foo/foo-inl.h') + 'foo/foo' + >>> _DropCommonSuffixes('foo/bar/foo.cc') + 'foo/bar/foo' + >>> _DropCommonSuffixes('foo/foo_internal.h') + 'foo/foo' + >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') + 'foo/foo_unusualinternal' + + Args: + filename: The input filename. + + Returns: + The filename with the common suffix removed. + """ + for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', + 'inl.h', 'impl.h', 'internal.h'): + if (filename.endswith(suffix) and len(filename) > len(suffix) and + filename[-len(suffix) - 1] in ('-', '_')): + return filename[:-len(suffix) - 1] + return os.path.splitext(filename)[0] + + +def _IsTestFilename(filename): + """Determines if the given filename has a suffix that identifies it as a test. + + Args: + filename: The input filename. + + Returns: + True if 'filename' looks like a test, False otherwise. + """ + if (filename.endswith('_test.cc') or + filename.endswith('_unittest.cc') or + filename.endswith('_regtest.cc')): + return True + else: + return False + + +def _ClassifyInclude(fileinfo, include, is_system): + """Figures out what kind of header 'include' is. + + Args: + fileinfo: The current file cpplint is running over. A FileInfo instance. + include: The path to a #included file. + is_system: True if the #include used <> rather than "". + + Returns: + One of the _XXX_HEADER constants. + + For example: + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) + _C_SYS_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) + _CPP_SYS_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) + _LIKELY_MY_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), + ... 'bar/foo_other_ext.h', False) + _POSSIBLE_MY_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) + _OTHER_HEADER + """ + # This is a list of all standard c++ header files, except + # those already checked for above. + is_cpp_h = include in _CPP_HEADERS + + if is_system: + if is_cpp_h: + return _CPP_SYS_HEADER + else: + return _C_SYS_HEADER + + # If the target file and the include we're checking share a + # basename when we drop common extensions, and the include + # lives in . , then it's likely to be owned by the target file. + target_dir, target_base = ( + os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) + include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) + if target_base == include_base and ( + include_dir == target_dir or + include_dir == os.path.normpath(target_dir + '/../public')): + return _LIKELY_MY_HEADER + + # If the target and include share some initial basename + # component, it's possible the target is implementing the + # include, so it's allowed to be first, but we'll never + # complain if it's not there. + target_first_component = _RE_FIRST_COMPONENT.match(target_base) + include_first_component = _RE_FIRST_COMPONENT.match(include_base) + if (target_first_component and include_first_component and + target_first_component.group(0) == + include_first_component.group(0)): + return _POSSIBLE_MY_HEADER + + return _OTHER_HEADER + + + +def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): + """Check rules that are applicable to #include lines. + + Strings on #include lines are NOT removed from elided line, to make + certain tasks easier. However, to prevent false positives, checks + applicable to #include lines in CheckLanguage must be put here. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + include_state: An _IncludeState instance in which the headers are inserted. + error: The function to call with any errors found. + """ + fileinfo = FileInfo(filename) + line = clean_lines.lines[linenum] + + # "include" should use the new style "foo/bar.h" instead of just "bar.h" + # Only do this check if the included header follows google naming + # conventions. If not, assume that it's a 3rd party API that + # requires special include conventions. + # + # We also make an exception for Lua headers, which follow google + # naming convention but not the include convention. + match = Match(r'#include\s*"([^/]+\.h)"', line) + if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)): + error(filename, linenum, 'build/include', 4, + 'Include the directory when naming .h files') + + # we shouldn't include a file more than once. actually, there are a + # handful of instances where doing so is okay, but in general it's + # not. + match = _RE_PATTERN_INCLUDE.search(line) + if match: + include = match.group(2) + is_system = (match.group(1) == '<') + duplicate_line = include_state.FindHeader(include) + if duplicate_line >= 0: + error(filename, linenum, 'build/include', 4, + '"%s" already included at %s:%s' % + (include, filename, duplicate_line)) + elif (include.endswith('.cc') and + os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)): + error(filename, linenum, 'build/include', 4, + 'Do not include .cc files from other packages') + elif not _THIRD_PARTY_HEADERS_PATTERN.match(include): + include_state.include_list[-1].append((include, linenum)) + + # We want to ensure that headers appear in the right order: + # 1) for foo.cc, foo.h (preferred location) + # 2) c system files + # 3) cpp system files + # 4) for foo.cc, foo.h (deprecated location) + # 5) other google headers + # + # We classify each include statement as one of those 5 types + # using a number of techniques. The include_state object keeps + # track of the highest type seen, and complains if we see a + # lower type after that. + error_message = include_state.CheckNextIncludeOrder( + _ClassifyInclude(fileinfo, include, is_system)) + if error_message: + error(filename, linenum, 'build/include_order', 4, + '%s. Should be: %s.h, c system, c++ system, other.' % + (error_message, fileinfo.BaseName())) + canonical_include = include_state.CanonicalizeAlphabeticalOrder(include) + if not include_state.IsInAlphabeticalOrder( + clean_lines, linenum, canonical_include): + error(filename, linenum, 'build/include_alpha', 4, + 'Include "%s" not in alphabetical order' % include) + include_state.SetLastHeader(canonical_include) + + + +def _GetTextInside(text, start_pattern): + r"""Retrieves all the text between matching open and close parentheses. + + Given a string of lines and a regular expression string, retrieve all the text + following the expression and between opening punctuation symbols like + (, [, or {, and the matching close-punctuation symbol. This properly nested + occurrences of the punctuations, so for the text like + printf(a(), b(c())); + a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. + start_pattern must match string having an open punctuation symbol at the end. + + Args: + text: The lines to extract text. Its comments and strings must be elided. + It can be single line and can span multiple lines. + start_pattern: The regexp string indicating where to start extracting + the text. + Returns: + The extracted text. + None if either the opening string or ending punctuation could not be found. + """ + # TODO(unknown): Audit cpplint.py to see what places could be profitably + # rewritten to use _GetTextInside (and use inferior regexp matching today). + + # Give opening punctuations to get the matching close-punctuations. + matching_punctuation = {'(': ')', '{': '}', '[': ']'} + closing_punctuation = set(matching_punctuation.itervalues()) + + # Find the position to start extracting text. + match = re.search(start_pattern, text, re.M) + if not match: # start_pattern not found in text. + return None + start_position = match.end(0) + + assert start_position > 0, ( + 'start_pattern must ends with an opening punctuation.') + assert text[start_position - 1] in matching_punctuation, ( + 'start_pattern must ends with an opening punctuation.') + # Stack of closing punctuations we expect to have in text after position. + punctuation_stack = [matching_punctuation[text[start_position - 1]]] + position = start_position + while punctuation_stack and position < len(text): + if text[position] == punctuation_stack[-1]: + punctuation_stack.pop() + elif text[position] in closing_punctuation: + # A closing punctuation without matching opening punctuations. + return None + elif text[position] in matching_punctuation: + punctuation_stack.append(matching_punctuation[text[position]]) + position += 1 + if punctuation_stack: + # Opening punctuations left without matching close-punctuations. + return None + # punctuations match. + return text[start_position:position - 1] + + +# Patterns for matching call-by-reference parameters. +# +# Supports nested templates up to 2 levels deep using this messy pattern: +# < (?: < (?: < [^<>]* +# > +# | [^<>] )* +# > +# | [^<>] )* +# > +_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]* +_RE_PATTERN_TYPE = ( + r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' + r'(?:\w|' + r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' + r'::)+') +# A call-by-reference parameter ends with '& identifier'. +_RE_PATTERN_REF_PARAM = re.compile( + r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*' + r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]') +# A call-by-const-reference parameter either ends with 'const& identifier' +# or looks like 'const type& identifier' when 'type' is atomic. +_RE_PATTERN_CONST_REF_PARAM = ( + r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT + + r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')') + + +def CheckLanguage(filename, clean_lines, linenum, file_extension, + include_state, nesting_state, error): + """Checks rules from the 'C++ language rules' section of cppguide.html. + + Some of these rules are hard to test (function overloading, using + uint32 inappropriately), but we do the best we can. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + file_extension: The extension (without the dot) of the filename. + include_state: An _IncludeState instance in which the headers are inserted. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + # If the line is empty or consists of entirely a comment, no need to + # check it. + line = clean_lines.elided[linenum] + if not line: + return + + match = _RE_PATTERN_INCLUDE.search(line) + if match: + CheckIncludeLine(filename, clean_lines, linenum, include_state, error) + return + + # Reset include state across preprocessor directives. This is meant + # to silence warnings for conditional includes. + match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line) + if match: + include_state.ResetSection(match.group(1)) + + # Make Windows paths like Unix. + fullname = os.path.abspath(filename).replace('\\', '/') + + # Perform other checks now that we are sure that this is not an include line + CheckCasts(filename, clean_lines, linenum, error) + CheckGlobalStatic(filename, clean_lines, linenum, error) + CheckPrintf(filename, clean_lines, linenum, error) + + if file_extension == 'h': + # TODO(unknown): check that 1-arg constructors are explicit. + # How to tell it's a constructor? + # (handled in CheckForNonStandardConstructs for now) + # TODO(unknown): check that classes declare or disable copy/assign + # (level 1 error) + pass + + # Check if people are using the verboten C basic types. The only exception + # we regularly allow is "unsigned short port" for port. + if Search(r'\bshort port\b', line): + if not Search(r'\bunsigned short port\b', line): + error(filename, linenum, 'runtime/int', 4, + 'Use "unsigned short" for ports, not "short"') + else: + match = Search(r'\b(short|long(?! +double)|long long)\b', line) + if match: + error(filename, linenum, 'runtime/int', 4, + 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) + + # Check if some verboten operator overloading is going on + # TODO(unknown): catch out-of-line unary operator&: + # class X {}; + # int operator&(const X& x) { return 42; } // unary operator& + # The trick is it's hard to tell apart from binary operator&: + # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& + if Search(r'\boperator\s*&\s*\(\s*\)', line): + error(filename, linenum, 'runtime/operator', 4, + 'Unary operator& is dangerous. Do not use it.') + + # Check for suspicious usage of "if" like + # } if (a == b) { + if Search(r'\}\s*if\s*\(', line): + error(filename, linenum, 'readability/braces', 4, + 'Did you mean "else if"? If not, start a new line for "if".') + + # Check for potential format string bugs like printf(foo). + # We constrain the pattern not to pick things like DocidForPrintf(foo). + # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) + # TODO(unknown): Catch the following case. Need to change the calling + # convention of the whole function to process multiple line to handle it. + # printf( + # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); + printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') + if printf_args: + match = Match(r'([\w.\->()]+)$', printf_args) + if match and match.group(1) != '__VA_ARGS__': + function_name = re.search(r'\b((?:string)?printf)\s*\(', + line, re.I).group(1) + error(filename, linenum, 'runtime/printf', 4, + 'Potential format string bug. Do %s("%%s", %s) instead.' + % (function_name, match.group(1))) + + # Check for potential memset bugs like memset(buf, sizeof(buf), 0). + match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) + if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): + error(filename, linenum, 'runtime/memset', 4, + 'Did you mean "memset(%s, 0, %s)"?' + % (match.group(1), match.group(2))) + + if Search(r'\busing namespace\b', line): + error(filename, linenum, 'build/namespaces', 5, + 'Do not use namespace using-directives. ' + 'Use using-declarations instead.') + + # Detect variable-length arrays. + match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) + if (match and match.group(2) != 'return' and match.group(2) != 'delete' and + match.group(3).find(']') == -1): + # Split the size using space and arithmetic operators as delimiters. + # If any of the resulting tokens are not compile time constants then + # report the error. + tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3)) + is_const = True + skip_next = False + for tok in tokens: + if skip_next: + skip_next = False + continue + + if Search(r'sizeof\(.+\)', tok): continue + if Search(r'arraysize\(\w+\)', tok): continue + + tok = tok.lstrip('(') + tok = tok.rstrip(')') + if not tok: continue + if Match(r'\d+', tok): continue + if Match(r'0[xX][0-9a-fA-F]+', tok): continue + if Match(r'k[A-Z0-9]\w*', tok): continue + if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue + if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue + # A catch all for tricky sizeof cases, including 'sizeof expression', + # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' + # requires skipping the next token because we split on ' ' and '*'. + if tok.startswith('sizeof'): + skip_next = True + continue + is_const = False + break + if not is_const: + error(filename, linenum, 'runtime/arrays', 1, + 'Do not use variable-length arrays. Use an appropriately named ' + "('k' followed by CamelCase) compile-time constant for the size.") + + # Check for use of unnamed namespaces in header files. Registration + # macros are typically OK, so we allow use of "namespace {" on lines + # that end with backslashes. + if (file_extension == 'h' + and Search(r'\bnamespace\s*{', line) + and line[-1] != '\\'): + error(filename, linenum, 'build/namespaces', 4, + 'Do not use unnamed namespaces in header files. See ' + 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' + ' for more information.') + + +def CheckGlobalStatic(filename, clean_lines, linenum, error): + """Check for unsafe global or static objects. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Match two lines at a time to support multiline declarations + if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line): + line += clean_lines.elided[linenum + 1].strip() + + # Check for people declaring static/global STL strings at the top level. + # This is dangerous because the C++ language does not guarantee that + # globals with constructors are initialized before the first access. + match = Match( + r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', + line) + + # Remove false positives: + # - String pointers (as opposed to values). + # string *pointer + # const string *pointer + # string const *pointer + # string *const pointer + # + # - Functions and template specializations. + # string Function(... + # string Class::Method(... + # + # - Operators. These are matched separately because operator names + # cross non-word boundaries, and trying to match both operators + # and functions at the same time would decrease accuracy of + # matching identifiers. + # string Class::operator*() + if (match and + not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and + not Search(r'\boperator\W', line) and + not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(3))): + error(filename, linenum, 'runtime/string', 4, + 'For a static/global string constant, use a C style string instead: ' + '"%schar %s[]".' % + (match.group(1), match.group(2))) + + if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): + error(filename, linenum, 'runtime/init', 4, + 'You seem to be initializing a member variable with itself.') + + +def CheckPrintf(filename, clean_lines, linenum, error): + """Check for printf related issues. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # When snprintf is used, the second argument shouldn't be a literal. + match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) + if match and match.group(2) != '0': + # If 2nd arg is zero, snprintf is used to calculate size. + error(filename, linenum, 'runtime/printf', 3, + 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' + 'to snprintf.' % (match.group(1), match.group(2))) + + # Check if some verboten C functions are being used. + if Search(r'\bsprintf\s*\(', line): + error(filename, linenum, 'runtime/printf', 5, + 'Never use sprintf. Use snprintf instead.') + match = Search(r'\b(strcpy|strcat)\s*\(', line) + if match: + error(filename, linenum, 'runtime/printf', 4, + 'Almost always, snprintf is better than %s' % match.group(1)) + + +def IsDerivedFunction(clean_lines, linenum): + """Check if current line contains an inherited function. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + Returns: + True if current line contains a function with "override" + virt-specifier. + """ + # Scan back a few lines for start of current function + for i in xrange(linenum, max(-1, linenum - 10), -1): + match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i]) + if match: + # Look for "override" after the matching closing parenthesis + line, _, closing_paren = CloseExpression( + clean_lines, i, len(match.group(1))) + return (closing_paren >= 0 and + Search(r'\boverride\b', line[closing_paren:])) + return False + + +def IsOutOfLineMethodDefinition(clean_lines, linenum): + """Check if current line contains an out-of-line method definition. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + Returns: + True if current line contains an out-of-line method definition. + """ + # Scan back a few lines for start of current function + for i in xrange(linenum, max(-1, linenum - 10), -1): + if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]): + return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None + return False + + +def IsInitializerList(clean_lines, linenum): + """Check if current line is inside constructor initializer list. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + Returns: + True if current line appears to be inside constructor initializer + list, False otherwise. + """ + for i in xrange(linenum, 1, -1): + line = clean_lines.elided[i] + if i == linenum: + remove_function_body = Match(r'^(.*)\{\s*$', line) + if remove_function_body: + line = remove_function_body.group(1) + + if Search(r'\s:\s*\w+[({]', line): + # A lone colon tend to indicate the start of a constructor + # initializer list. It could also be a ternary operator, which + # also tend to appear in constructor initializer lists as + # opposed to parameter lists. + return True + if Search(r'\}\s*,\s*$', line): + # A closing brace followed by a comma is probably the end of a + # brace-initialized member in constructor initializer list. + return True + if Search(r'[{};]\s*$', line): + # Found one of the following: + # - A closing brace or semicolon, probably the end of the previous + # function. + # - An opening brace, probably the start of current class or namespace. + # + # Current line is probably not inside an initializer list since + # we saw one of those things without seeing the starting colon. + return False + + # Got to the beginning of the file without seeing the start of + # constructor initializer list. + return False + + +def CheckForNonConstReference(filename, clean_lines, linenum, + nesting_state, error): + """Check for non-const references. + + Separate from CheckLanguage since it scans backwards from current + line, instead of scanning forward. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: The function to call with any errors found. + """ + # Do nothing if there is no '&' on current line. + line = clean_lines.elided[linenum] + if '&' not in line: + return + + # If a function is inherited, current function doesn't have much of + # a choice, so any non-const references should not be blamed on + # derived function. + if IsDerivedFunction(clean_lines, linenum): + return + + # Don't warn on out-of-line method definitions, as we would warn on the + # in-line declaration, if it isn't marked with 'override'. + if IsOutOfLineMethodDefinition(clean_lines, linenum): + return + + # Long type names may be broken across multiple lines, usually in one + # of these forms: + # LongType + # ::LongTypeContinued &identifier + # LongType:: + # LongTypeContinued &identifier + # LongType< + # ...>::LongTypeContinued &identifier + # + # If we detected a type split across two lines, join the previous + # line to current line so that we can match const references + # accordingly. + # + # Note that this only scans back one line, since scanning back + # arbitrary number of lines would be expensive. If you have a type + # that spans more than 2 lines, please use a typedef. + if linenum > 1: + previous = None + if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line): + # previous_line\n + ::current_line + previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$', + clean_lines.elided[linenum - 1]) + elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line): + # previous_line::\n + current_line + previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$', + clean_lines.elided[linenum - 1]) + if previous: + line = previous.group(1) + line.lstrip() + else: + # Check for templated parameter that is split across multiple lines + endpos = line.rfind('>') + if endpos > -1: + (_, startline, startpos) = ReverseCloseExpression( + clean_lines, linenum, endpos) + if startpos > -1 and startline < linenum: + # Found the matching < on an earlier line, collect all + # pieces up to current line. + line = '' + for i in xrange(startline, linenum + 1): + line += clean_lines.elided[i].strip() + + # Check for non-const references in function parameters. A single '&' may + # found in the following places: + # inside expression: binary & for bitwise AND + # inside expression: unary & for taking the address of something + # inside declarators: reference parameter + # We will exclude the first two cases by checking that we are not inside a + # function body, including one that was just introduced by a trailing '{'. + # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare]. + if (nesting_state.previous_stack_top and + not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or + isinstance(nesting_state.previous_stack_top, _NamespaceInfo))): + # Not at toplevel, not within a class, and not within a namespace + return + + # Avoid initializer lists. We only need to scan back from the + # current line for something that starts with ':'. + # + # We don't need to check the current line, since the '&' would + # appear inside the second set of parentheses on the current line as + # opposed to the first set. + if linenum > 0: + for i in xrange(linenum - 1, max(0, linenum - 10), -1): + previous_line = clean_lines.elided[i] + if not Search(r'[),]\s*$', previous_line): + break + if Match(r'^\s*:\s+\S', previous_line): + return + + # Avoid preprocessors + if Search(r'\\\s*$', line): + return + + # Avoid constructor initializer lists + if IsInitializerList(clean_lines, linenum): + return + + # We allow non-const references in a few standard places, like functions + # called "swap()" or iostream operators like "<<" or ">>". Do not check + # those function parameters. + # + # We also accept & in static_assert, which looks like a function but + # it's actually a declaration expression. + whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' + r'operator\s*[<>][<>]|' + r'static_assert|COMPILE_ASSERT' + r')\s*\(') + if Search(whitelisted_functions, line): + return + elif not Search(r'\S+\([^)]*$', line): + # Don't see a whitelisted function on this line. Actually we + # didn't see any function name on this line, so this is likely a + # multi-line parameter list. Try a bit harder to catch this case. + for i in xrange(2): + if (linenum > i and + Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): + return + + decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body + for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): + if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter): + error(filename, linenum, 'runtime/references', 2, + 'Is this a non-const reference? ' + 'If so, make const or use a pointer: ' + + ReplaceAll(' *<', '<', parameter)) + + +def CheckCasts(filename, clean_lines, linenum, error): + """Various cast related checks. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Check to see if they're using an conversion function cast. + # I just try to capture the most common basic types, though there are more. + # Parameterless conversion functions, such as bool(), are allowed as they are + # probably a member operator declaration or default constructor. + match = Search( + r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b' + r'(int|float|double|bool|char|int32|uint32|int64|uint64)' + r'(\([^)].*)', line) + expecting_function = ExpectingFunctionArgs(clean_lines, linenum) + if match and not expecting_function: + matched_type = match.group(2) + + # matched_new_or_template is used to silence two false positives: + # - New operators + # - Template arguments with function types + # + # For template arguments, we match on types immediately following + # an opening bracket without any spaces. This is a fast way to + # silence the common case where the function type is the first + # template argument. False negative with less-than comparison is + # avoided because those operators are usually followed by a space. + # + # function // bracket + no space = false positive + # value < double(42) // bracket + space = true positive + matched_new_or_template = match.group(1) + + # Avoid arrays by looking for brackets that come after the closing + # parenthesis. + if Match(r'\([^()]+\)\s*\[', match.group(3)): + return + + # Other things to ignore: + # - Function pointers + # - Casts to pointer types + # - Placement new + # - Alias declarations + matched_funcptr = match.group(3) + if (matched_new_or_template is None and + not (matched_funcptr and + (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(', + matched_funcptr) or + matched_funcptr.startswith('(*)'))) and + not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and + not Search(r'new\(\S+\)\s*' + matched_type, line)): + error(filename, linenum, 'readability/casting', 4, + 'Using deprecated casting style. ' + 'Use static_cast<%s>(...) instead' % + matched_type) + + if not expecting_function: + CheckCStyleCast(filename, clean_lines, linenum, 'static_cast', + r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) + + # This doesn't catch all cases. Consider (const char * const)"hello". + # + # (char *) "foo" should always be a const_cast (reinterpret_cast won't + # compile). + if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast', + r'\((char\s?\*+\s?)\)\s*"', error): + pass + else: + # Check pointer casts for other than string constants + CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast', + r'\((\w+\s?\*+\s?)\)', error) + + # In addition, we look for people taking the address of a cast. This + # is dangerous -- casts can assign to temporaries, so the pointer doesn't + # point where you think. + # + # Some non-identifier character is required before the '&' for the + # expression to be recognized as a cast. These are casts: + # expression = &static_cast(temporary()); + # function(&(int*)(temporary())); + # + # This is not a cast: + # reference_type&(int* function_param); + match = Search( + r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|' + r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line) + if match: + # Try a better error message when the & is bound to something + # dereferenced by the casted pointer, as opposed to the casted + # pointer itself. + parenthesis_error = False + match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line) + if match: + _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1))) + if x1 >= 0 and clean_lines.elided[y1][x1] == '(': + _, y2, x2 = CloseExpression(clean_lines, y1, x1) + if x2 >= 0: + extended_line = clean_lines.elided[y2][x2:] + if y2 < clean_lines.NumLines() - 1: + extended_line += clean_lines.elided[y2 + 1] + if Match(r'\s*(?:->|\[)', extended_line): + parenthesis_error = True + + if parenthesis_error: + error(filename, linenum, 'readability/casting', 4, + ('Are you taking an address of something dereferenced ' + 'from a cast? Wrapping the dereferenced expression in ' + 'parentheses will make the binding more obvious')) + else: + error(filename, linenum, 'runtime/casting', 4, + ('Are you taking an address of a cast? ' + 'This is dangerous: could be a temp var. ' + 'Take the address before doing the cast, rather than after')) + + +def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error): + """Checks for a C-style cast by looking for the pattern. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + cast_type: The string for the C++ cast to recommend. This is either + reinterpret_cast, static_cast, or const_cast, depending. + pattern: The regular expression used to find C-style casts. + error: The function to call with any errors found. + + Returns: + True if an error was emitted. + False otherwise. + """ + line = clean_lines.elided[linenum] + match = Search(pattern, line) + if not match: + return False + + # Exclude lines with keywords that tend to look like casts + context = line[0:match.start(1) - 1] + if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context): + return False + + # Try expanding current context to see if we one level of + # parentheses inside a macro. + if linenum > 0: + for i in xrange(linenum - 1, max(0, linenum - 5), -1): + context = clean_lines.elided[i] + context + if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context): + return False + + # operator++(int) and operator--(int) + if context.endswith(' operator++') or context.endswith(' operator--'): + return False + + # A single unnamed argument for a function tends to look like old + # style cast. If we see those, don't issue warnings for deprecated + # casts, instead issue warnings for unnamed arguments where + # appropriate. + # + # These are things that we want warnings for, since the style guide + # explicitly require all parameters to be named: + # Function(int); + # Function(int) { + # ConstMember(int) const; + # ConstMember(int) const { + # ExceptionMember(int) throw (...); + # ExceptionMember(int) throw (...) { + # PureVirtual(int) = 0; + # [](int) -> bool { + # + # These are functions of some sort, where the compiler would be fine + # if they had named parameters, but people often omit those + # identifiers to reduce clutter: + # (FunctionPointer)(int); + # (FunctionPointer)(int) = value; + # Function((function_pointer_arg)(int)) + # Function((function_pointer_arg)(int), int param) + # ; + # <(FunctionPointerTemplateArgument)(int)>; + remainder = line[match.end(0):] + if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)', + remainder): + # Looks like an unnamed parameter. + + # Don't warn on any kind of template arguments. + if Match(r'^\s*>', remainder): + return False + + # Don't warn on assignments to function pointers, but keep warnings for + # unnamed parameters to pure virtual functions. Note that this pattern + # will also pass on assignments of "0" to function pointers, but the + # preferred values for those would be "nullptr" or "NULL". + matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder) + if matched_zero and matched_zero.group(1) != '0': + return False + + # Don't warn on function pointer declarations. For this we need + # to check what came before the "(type)" string. + if Match(r'.*\)\s*$', line[0:match.start(0)]): + return False + + # Don't warn if the parameter is named with block comments, e.g.: + # Function(int /*unused_param*/); + raw_line = clean_lines.raw_lines[linenum] + if '/*' in raw_line: + return False + + # Passed all filters, issue warning here. + error(filename, linenum, 'readability/function', 3, + 'All parameters should be named in a function') + return True + + # At this point, all that should be left is actual casts. + error(filename, linenum, 'readability/casting', 4, + 'Using C-style cast. Use %s<%s>(...) instead' % + (cast_type, match.group(1))) + + return True + + +def ExpectingFunctionArgs(clean_lines, linenum): + """Checks whether where function type arguments are expected. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + + Returns: + True if the line at 'linenum' is inside something that expects arguments + of function types. + """ + line = clean_lines.elided[linenum] + return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or + (linenum >= 2 and + (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$', + clean_lines.elided[linenum - 1]) or + Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$', + clean_lines.elided[linenum - 2]) or + Search(r'\bstd::m?function\s*\<\s*$', + clean_lines.elided[linenum - 1])))) + + +_HEADERS_CONTAINING_TEMPLATES = ( + ('', ('deque',)), + ('', ('unary_function', 'binary_function', + 'plus', 'minus', 'multiplies', 'divides', 'modulus', + 'negate', + 'equal_to', 'not_equal_to', 'greater', 'less', + 'greater_equal', 'less_equal', + 'logical_and', 'logical_or', 'logical_not', + 'unary_negate', 'not1', 'binary_negate', 'not2', + 'bind1st', 'bind2nd', + 'pointer_to_unary_function', + 'pointer_to_binary_function', + 'ptr_fun', + 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', + 'mem_fun_ref_t', + 'const_mem_fun_t', 'const_mem_fun1_t', + 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', + 'mem_fun_ref', + )), + ('', ('numeric_limits',)), + ('', ('list',)), + ('', ('map', 'multimap',)), + ('', ('allocator',)), + ('', ('queue', 'priority_queue',)), + ('', ('set', 'multiset',)), + ('', ('stack',)), + ('', ('char_traits', 'basic_string',)), + ('', ('tuple',)), + ('', ('pair',)), + ('', ('vector',)), + + # gcc extensions. + # Note: std::hash is their hash, ::hash is our hash + ('', ('hash_map', 'hash_multimap',)), + ('', ('hash_set', 'hash_multiset',)), + ('', ('slist',)), + ) + +_RE_PATTERN_STRING = re.compile(r'\bstring\b') + +_re_pattern_algorithm_header = [] +for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', + 'transform'): + # Match max(..., ...), max(..., ...), but not foo->max, foo.max or + # type::max(). + _re_pattern_algorithm_header.append( + (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), + _template, + '')) + +_re_pattern_templates = [] +for _header, _templates in _HEADERS_CONTAINING_TEMPLATES: + for _template in _templates: + _re_pattern_templates.append( + (re.compile(r'(\<|\b)' + _template + r'\s*\<'), + _template + '<>', + _header)) + + +def FilesBelongToSameModule(filename_cc, filename_h): + """Check if these two filenames belong to the same module. + + The concept of a 'module' here is a as follows: + foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the + same 'module' if they are in the same directory. + some/path/public/xyzzy and some/path/internal/xyzzy are also considered + to belong to the same module here. + + If the filename_cc contains a longer path than the filename_h, for example, + '/absolute/path/to/base/sysinfo.cc', and this file would include + 'base/sysinfo.h', this function also produces the prefix needed to open the + header. This is used by the caller of this function to more robustly open the + header file. We don't have access to the real include paths in this context, + so we need this guesswork here. + + Known bugs: tools/base/bar.cc and base/bar.h belong to the same module + according to this implementation. Because of this, this function gives + some false positives. This should be sufficiently rare in practice. + + Args: + filename_cc: is the path for the .cc file + filename_h: is the path for the header path + + Returns: + Tuple with a bool and a string: + bool: True if filename_cc and filename_h belong to the same module. + string: the additional prefix needed to open the header file. + """ + + if not filename_cc.endswith('.cc'): + return (False, '') + filename_cc = filename_cc[:-len('.cc')] + if filename_cc.endswith('_unittest'): + filename_cc = filename_cc[:-len('_unittest')] + elif filename_cc.endswith('_test'): + filename_cc = filename_cc[:-len('_test')] + filename_cc = filename_cc.replace('/public/', '/') + filename_cc = filename_cc.replace('/internal/', '/') + + if not filename_h.endswith('.h'): + return (False, '') + filename_h = filename_h[:-len('.h')] + if filename_h.endswith('-inl'): + filename_h = filename_h[:-len('-inl')] + filename_h = filename_h.replace('/public/', '/') + filename_h = filename_h.replace('/internal/', '/') + + files_belong_to_same_module = filename_cc.endswith(filename_h) + common_path = '' + if files_belong_to_same_module: + common_path = filename_cc[:-len(filename_h)] + return files_belong_to_same_module, common_path + + +def UpdateIncludeState(filename, include_dict, io=codecs): + """Fill up the include_dict with new includes found from the file. + + Args: + filename: the name of the header to read. + include_dict: a dictionary in which the headers are inserted. + io: The io factory to use to read the file. Provided for testability. + + Returns: + True if a header was successfully added. False otherwise. + """ + headerfile = None + try: + headerfile = io.open(filename, 'r', 'utf8', 'replace') + except IOError: + return False + linenum = 0 + for line in headerfile: + linenum += 1 + clean_line = CleanseComments(line) + match = _RE_PATTERN_INCLUDE.search(clean_line) + if match: + include = match.group(2) + include_dict.setdefault(include, linenum) + return True + + +def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, + io=codecs): + """Reports for missing stl includes. + + This function will output warnings to make sure you are including the headers + necessary for the stl containers and functions that you use. We only give one + reason to include a header. For example, if you use both equal_to<> and + less<> in a .h file, only one (the latter in the file) of these will be + reported as a reason to include the . + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + include_state: An _IncludeState instance. + error: The function to call with any errors found. + io: The IO factory to use to read the header file. Provided for unittest + injection. + """ + required = {} # A map of header name to linenumber and the template entity. + # Example of required: { '': (1219, 'less<>') } + + for linenum in xrange(clean_lines.NumLines()): + line = clean_lines.elided[linenum] + if not line or line[0] == '#': + continue + + # String is special -- it is a non-templatized type in STL. + matched = _RE_PATTERN_STRING.search(line) + if matched: + # Don't warn about strings in non-STL namespaces: + # (We check only the first match per line; good enough.) + prefix = line[:matched.start()] + if prefix.endswith('std::') or not prefix.endswith('::'): + required[''] = (linenum, 'string') + + for pattern, template, header in _re_pattern_algorithm_header: + if pattern.search(line): + required[header] = (linenum, template) + + # The following function is just a speed up, no semantics are changed. + if not '<' in line: # Reduces the cpu time usage by skipping lines. + continue + + for pattern, template, header in _re_pattern_templates: + if pattern.search(line): + required[header] = (linenum, template) + + # The policy is that if you #include something in foo.h you don't need to + # include it again in foo.cc. Here, we will look at possible includes. + # Let's flatten the include_state include_list and copy it into a dictionary. + include_dict = dict([item for sublist in include_state.include_list + for item in sublist]) + + # Did we find the header for this file (if any) and successfully load it? + header_found = False + + # Use the absolute path so that matching works properly. + abs_filename = FileInfo(filename).FullName() + + # For Emacs's flymake. + # If cpplint is invoked from Emacs's flymake, a temporary file is generated + # by flymake and that file name might end with '_flymake.cc'. In that case, + # restore original file name here so that the corresponding header file can be + # found. + # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' + # instead of 'foo_flymake.h' + abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) + + # include_dict is modified during iteration, so we iterate over a copy of + # the keys. + header_keys = include_dict.keys() + for header in header_keys: + (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) + fullpath = common_path + header + if same_module and UpdateIncludeState(fullpath, include_dict, io): + header_found = True + + # If we can't find the header file for a .cc, assume it's because we don't + # know where to look. In that case we'll give up as we're not sure they + # didn't include it in the .h file. + # TODO(unknown): Do a better job of finding .h files so we are confident that + # not having the .h file means there isn't one. + if filename.endswith('.cc') and not header_found: + return + + # All the lines have been processed, report the errors found. + for required_header_unstripped in required: + template = required[required_header_unstripped][1] + if required_header_unstripped.strip('<>"') not in include_dict: + error(filename, required[required_header_unstripped][0], + 'build/include_what_you_use', 4, + 'Add #include ' + required_header_unstripped + ' for ' + template) + + +_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') + + +def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): + """Check that make_pair's template arguments are deduced. + + G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are + specified explicitly, and such use isn't intended in any case. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) + if match: + error(filename, linenum, 'build/explicit_make_pair', + 4, # 4 = high confidence + 'For C++11-compatibility, omit template arguments from make_pair' + ' OR use pair directly OR if appropriate, construct a pair directly') + + +def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error): + """Check that default lambda captures are not used. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # A lambda introducer specifies a default capture if it starts with "[=" + # or if it starts with "[&" _not_ followed by an identifier. + match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line) + if match: + # Found a potential error, check what comes after the lambda-introducer. + # If it's not open parenthesis (for lambda-declarator) or open brace + # (for compound-statement), it's not a lambda. + line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1))) + if pos >= 0 and Match(r'^\s*[{(]', line[pos:]): + error(filename, linenum, 'build/c++11', + 4, # 4 = high confidence + 'Default lambda captures are an unapproved C++ feature.') + + +def CheckRedundantVirtual(filename, clean_lines, linenum, error): + """Check if line contains a redundant "virtual" function-specifier. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + # Look for "virtual" on current line. + line = clean_lines.elided[linenum] + virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line) + if not virtual: return + + # Ignore "virtual" keywords that are near access-specifiers. These + # are only used in class base-specifier and do not apply to member + # functions. + if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or + Match(r'^\s+(public|protected|private)\b', virtual.group(3))): + return + + # Ignore the "virtual" keyword from virtual base classes. Usually + # there is a column on the same line in these cases (virtual base + # classes are rare in google3 because multiple inheritance is rare). + if Match(r'^.*[^:]:[^:].*$', line): return + + # Look for the next opening parenthesis. This is the start of the + # parameter list (possibly on the next line shortly after virtual). + # TODO(unknown): doesn't work if there are virtual functions with + # decltype() or other things that use parentheses, but csearch suggests + # that this is rare. + end_col = -1 + end_line = -1 + start_col = len(virtual.group(2)) + for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())): + line = clean_lines.elided[start_line][start_col:] + parameter_list = Match(r'^([^(]*)\(', line) + if parameter_list: + # Match parentheses to find the end of the parameter list + (_, end_line, end_col) = CloseExpression( + clean_lines, start_line, start_col + len(parameter_list.group(1))) + break + start_col = 0 + + if end_col < 0: + return # Couldn't find end of parameter list, give up + + # Look for "override" or "final" after the parameter list + # (possibly on the next few lines). + for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())): + line = clean_lines.elided[i][end_col:] + match = Search(r'\b(override|final)\b', line) + if match: + error(filename, linenum, 'readability/inheritance', 4, + ('"virtual" is redundant since function is ' + 'already declared as "%s"' % match.group(1))) + + # Set end_col to check whole lines after we are done with the + # first line. + end_col = 0 + if Search(r'[^\w]\s*$', line): + break + + +def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error): + """Check if line contains a redundant "override" or "final" virt-specifier. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + # Look for closing parenthesis nearby. We need one to confirm where + # the declarator ends and where the virt-specifier starts to avoid + # false positives. + line = clean_lines.elided[linenum] + declarator_end = line.rfind(')') + if declarator_end >= 0: + fragment = line[declarator_end:] + else: + if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0: + fragment = line + else: + return + + # Check that at most one of "override" or "final" is present, not both + if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment): + error(filename, linenum, 'readability/inheritance', 4, + ('"override" is redundant since function is ' + 'already declared as "final"')) + + + + +# Returns true if we are at a new block, and it is directly +# inside of a namespace. +def IsBlockInNameSpace(nesting_state, is_forward_declaration): + """Checks that the new block is directly in a namespace. + + Args: + nesting_state: The _NestingState object that contains info about our state. + is_forward_declaration: If the class is a forward declared class. + Returns: + Whether or not the new block is directly in a namespace. + """ + if is_forward_declaration: + if len(nesting_state.stack) >= 1 and ( + isinstance(nesting_state.stack[-1], _NamespaceInfo)): + return True + else: + return False + + return (len(nesting_state.stack) > 1 and + nesting_state.stack[-1].check_namespace_indentation and + isinstance(nesting_state.stack[-2], _NamespaceInfo)) + + +def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item, + raw_lines_no_comments, linenum): + """This method determines if we should apply our namespace indentation check. + + Args: + nesting_state: The current nesting state. + is_namespace_indent_item: If we just put a new class on the stack, True. + If the top of the stack is not a class, or we did not recently + add the class, False. + raw_lines_no_comments: The lines without the comments. + linenum: The current line number we are processing. + + Returns: + True if we should apply our namespace indentation check. Currently, it + only works for classes and namespaces inside of a namespace. + """ + + is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments, + linenum) + + if not (is_namespace_indent_item or is_forward_declaration): + return False + + # If we are in a macro, we do not want to check the namespace indentation. + if IsMacroDefinition(raw_lines_no_comments, linenum): + return False + + return IsBlockInNameSpace(nesting_state, is_forward_declaration) + + +# Call this method if the line is directly inside of a namespace. +# If the line above is blank (excluding comments) or the start of +# an inner namespace, it cannot be indented. +def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum, + error): + line = raw_lines_no_comments[linenum] + if Match(r'^\s+', line): + error(filename, linenum, 'runtime/indentation_namespace', 4, + 'Do not indent within a namespace') + + +def ProcessLine(filename, file_extension, clean_lines, line, + include_state, function_state, nesting_state, error, + extra_check_functions=[]): + """Processes a single line in the file. + + Args: + filename: Filename of the file that is being processed. + file_extension: The extension (dot not included) of the file. + clean_lines: An array of strings, each representing a line of the file, + with comments stripped. + line: Number of line being processed. + include_state: An _IncludeState instance in which the headers are inserted. + function_state: A _FunctionState instance which counts function lines, etc. + nesting_state: A NestingState instance which maintains information about + the current stack of nested blocks being parsed. + error: A callable to which errors are reported, which takes 4 arguments: + filename, line number, error level, and message + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + raw_lines = clean_lines.raw_lines + ParseNolintSuppressions(filename, raw_lines[line], line, error) + nesting_state.Update(filename, clean_lines, line, error) + CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line, + error) + if nesting_state.InAsmBlock(): return + CheckForFunctionLengths(filename, clean_lines, line, function_state, error) + CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) + CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) + CheckLanguage(filename, clean_lines, line, file_extension, include_state, + nesting_state, error) + CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) + CheckForNonStandardConstructs(filename, clean_lines, line, + nesting_state, error) + CheckVlogArguments(filename, clean_lines, line, error) + CheckPosixThreading(filename, clean_lines, line, error) + CheckInvalidIncrement(filename, clean_lines, line, error) + CheckMakePairUsesDeduction(filename, clean_lines, line, error) + CheckDefaultLambdaCaptures(filename, clean_lines, line, error) + CheckRedundantVirtual(filename, clean_lines, line, error) + CheckRedundantOverrideOrFinal(filename, clean_lines, line, error) + for check_fn in extra_check_functions: + check_fn(filename, clean_lines, line, error) + +def FlagCxx11Features(filename, clean_lines, linenum, error): + """Flag those c++11 features that we only allow in certain places. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Flag unapproved C++11 headers. + include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line) + if include and include.group(1) in ('cfenv', + 'condition_variable', + 'fenv.h', + 'future', + 'mutex', + 'thread', + 'chrono', + 'ratio', + 'regex', + 'system_error', + ): + error(filename, linenum, 'build/c++11', 5, + ('<%s> is an unapproved C++11 header.') % include.group(1)) + + # The only place where we need to worry about C++11 keywords and library + # features in preprocessor directives is in macro definitions. + if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return + + # These are classes and free functions. The classes are always + # mentioned as std::*, but we only catch the free functions if + # they're not found by ADL. They're alphabetical by header. + for top_name in ( + # type_traits + 'alignment_of', + 'aligned_union', + ): + if Search(r'\bstd::%s\b' % top_name, line): + error(filename, linenum, 'build/c++11', 5, + ('std::%s is an unapproved C++11 class or function. Send c-style ' + 'an example of where it would make your code more readable, and ' + 'they may let you use it.') % top_name) + + +def ProcessFileData(filename, file_extension, lines, error, + extra_check_functions=[]): + """Performs lint checks and reports any errors to the given error function. + + Args: + filename: Filename of the file that is being processed. + file_extension: The extension (dot not included) of the file. + lines: An array of strings, each representing a line of the file, with the + last element being empty if the file is terminated with a newline. + error: A callable to which errors are reported, which takes 4 arguments: + filename, line number, error level, and message + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + lines = (['// marker so line numbers and indices both start at 1'] + lines + + ['// marker so line numbers end in a known way']) + + include_state = _IncludeState() + function_state = _FunctionState() + nesting_state = NestingState() + + ResetNolintSuppressions() + + CheckForCopyright(filename, lines, error) + + RemoveMultiLineComments(filename, lines, error) + clean_lines = CleansedLines(lines) + + if file_extension == 'h': + CheckForHeaderGuard(filename, clean_lines, error) + + for line in xrange(clean_lines.NumLines()): + ProcessLine(filename, file_extension, clean_lines, line, + include_state, function_state, nesting_state, error, + extra_check_functions) + FlagCxx11Features(filename, clean_lines, line, error) + nesting_state.CheckCompletedBlocks(filename, error) + + CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) + + # Check that the .cc file has included its header if it exists. + if file_extension == 'cc': + CheckHeaderFileIncluded(filename, include_state, error) + + # We check here rather than inside ProcessLine so that we see raw + # lines rather than "cleaned" lines. + CheckForBadCharacters(filename, lines, error) + + CheckForNewlineAtEOF(filename, lines, error) + +def ProcessConfigOverrides(filename): + """ Loads the configuration files and processes the config overrides. + + Args: + filename: The name of the file being processed by the linter. + + Returns: + False if the current |filename| should not be processed further. + """ + + abs_filename = os.path.abspath(filename) + cfg_filters = [] + keep_looking = True + while keep_looking: + abs_path, base_name = os.path.split(abs_filename) + if not base_name: + break # Reached the root directory. + + cfg_file = os.path.join(abs_path, "CPPLINT.cfg") + abs_filename = abs_path + if not os.path.isfile(cfg_file): + continue + + try: + with open(cfg_file) as file_handle: + for line in file_handle: + line, _, _ = line.partition('#') # Remove comments. + if not line.strip(): + continue + + name, _, val = line.partition('=') + name = name.strip() + val = val.strip() + if name == 'set noparent': + keep_looking = False + elif name == 'filter': + cfg_filters.append(val) + elif name == 'exclude_files': + # When matching exclude_files pattern, use the base_name of + # the current file name or the directory name we are processing. + # For example, if we are checking for lint errors in /foo/bar/baz.cc + # and we found the .cfg file at /foo/CPPLINT.cfg, then the config + # file's "exclude_files" filter is meant to be checked against "bar" + # and not "baz" nor "bar/baz.cc". + if base_name: + pattern = re.compile(val) + if pattern.match(base_name): + sys.stderr.write('Ignoring "%s": file excluded by "%s". ' + 'File path component "%s" matches ' + 'pattern "%s"\n' % + (filename, cfg_file, base_name, val)) + return False + elif name == 'linelength': + global _line_length + try: + _line_length = int(val) + except ValueError: + sys.stderr.write('Line length must be numeric.') + else: + sys.stderr.write( + 'Invalid configuration option (%s) in file %s\n' % + (name, cfg_file)) + + except IOError: + sys.stderr.write( + "Skipping config file '%s': Can't open for reading\n" % cfg_file) + keep_looking = False + + # Apply all the accumulated filters in reverse order (top-level directory + # config options having the least priority). + for filter in reversed(cfg_filters): + _AddFilters(filter) + + return True + + +def ProcessFile(filename, vlevel, extra_check_functions=[]): + """Does google-lint on a single file. + + Args: + filename: The name of the file to parse. + + vlevel: The level of errors to report. Every error of confidence + >= verbose_level will be reported. 0 is a good default. + + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + + _SetVerboseLevel(vlevel) + _BackupFilters() + + if not ProcessConfigOverrides(filename): + _RestoreFilters() + return + + lf_lines = [] + crlf_lines = [] + try: + # Support the UNIX convention of using "-" for stdin. Note that + # we are not opening the file with universal newline support + # (which codecs doesn't support anyway), so the resulting lines do + # contain trailing '\r' characters if we are reading a file that + # has CRLF endings. + # If after the split a trailing '\r' is present, it is removed + # below. + if filename == '-': + lines = codecs.StreamReaderWriter(sys.stdin, + codecs.getreader('utf8'), + codecs.getwriter('utf8'), + 'replace').read().split('\n') + else: + lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') + + # Remove trailing '\r'. + # The -1 accounts for the extra trailing blank line we get from split() + for linenum in range(len(lines) - 1): + if lines[linenum].endswith('\r'): + lines[linenum] = lines[linenum].rstrip('\r') + crlf_lines.append(linenum + 1) + else: + lf_lines.append(linenum + 1) + + except IOError: + sys.stderr.write( + "Skipping input '%s': Can't open for reading\n" % filename) + _RestoreFilters() + return + + # Note, if no dot is found, this will give the entire filename as the ext. + file_extension = filename[filename.rfind('.') + 1:] + + # When reading from stdin, the extension is unknown, so no cpplint tests + # should rely on the extension. + if filename != '-' and file_extension not in _valid_extensions: + sys.stderr.write('Ignoring %s; not a valid file name ' + '(%s)\n' % (filename, ', '.join(_valid_extensions))) + else: + ProcessFileData(filename, file_extension, lines, Error, + extra_check_functions) + + # If end-of-line sequences are a mix of LF and CR-LF, issue + # warnings on the lines with CR. + # + # Don't issue any warnings if all lines are uniformly LF or CR-LF, + # since critique can handle these just fine, and the style guide + # doesn't dictate a particular end of line sequence. + # + # We can't depend on os.linesep to determine what the desired + # end-of-line sequence should be, since that will return the + # server-side end-of-line sequence. + if lf_lines and crlf_lines: + # Warn on every line with CR. An alternative approach might be to + # check whether the file is mostly CRLF or just LF, and warn on the + # minority, we bias toward LF here since most tools prefer LF. + for linenum in crlf_lines: + Error(filename, linenum, 'whitespace/newline', 1, + 'Unexpected \\r (^M) found; better to use only \\n') + + sys.stderr.write('Done processing %s\n' % filename) + _RestoreFilters() + + +def PrintUsage(message): + """Prints a brief usage string and exits, optionally with an error message. + + Args: + message: The optional error message. + """ + sys.stderr.write(_USAGE) + if message: + sys.exit('\nFATAL ERROR: ' + message) + else: + sys.exit(1) + + +def PrintCategories(): + """Prints a list of all the error-categories used by error messages. + + These are the categories used to filter messages via --filter. + """ + sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES)) + sys.exit(0) + + +def ParseArguments(args): + """Parses the command line arguments. + + This may set the output format and verbosity level as side-effects. + + Args: + args: The command line arguments: + + Returns: + The list of filenames to lint. + """ + try: + (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', + 'counting=', + 'filter=', + 'root=', + 'linelength=', + 'extensions=']) + except getopt.GetoptError: + PrintUsage('Invalid arguments.') + + verbosity = _VerboseLevel() + output_format = _OutputFormat() + filters = '' + counting_style = '' + + for (opt, val) in opts: + if opt == '--help': + PrintUsage(None) + elif opt == '--output': + if val not in ('emacs', 'vs7', 'eclipse'): + PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.') + output_format = val + elif opt == '--verbose': + verbosity = int(val) + elif opt == '--filter': + filters = val + if not filters: + PrintCategories() + elif opt == '--counting': + if val not in ('total', 'toplevel', 'detailed'): + PrintUsage('Valid counting options are total, toplevel, and detailed') + counting_style = val + elif opt == '--root': + global _root + _root = val + elif opt == '--linelength': + global _line_length + try: + _line_length = int(val) + except ValueError: + PrintUsage('Line length must be digits.') + elif opt == '--extensions': + global _valid_extensions + try: + _valid_extensions = set(val.split(',')) + except ValueError: + PrintUsage('Extensions must be comma seperated list.') + + if not filenames: + PrintUsage('No files were specified.') + + _SetOutputFormat(output_format) + _SetVerboseLevel(verbosity) + _SetFilters(filters) + _SetCountingStyle(counting_style) + + return filenames + + +def main(): + filenames = ParseArguments(sys.argv[1:]) + + # Change stderr to write with replacement characters so we don't die + # if we try to print something containing non-ASCII characters. + sys.stderr = codecs.StreamReaderWriter(sys.stderr, + codecs.getreader('utf8'), + codecs.getwriter('utf8'), + 'replace') + + _cpplint_state.ResetErrorCounts() + for filename in filenames: + ProcessFile(filename, _cpplint_state.verbose_level) + _cpplint_state.PrintErrorCounts() + + sys.exit(_cpplint_state.error_count > 0) + + +if __name__ == '__main__': + main() diff --git a/test.cc b/loader_example.cc similarity index 98% rename from test.cc rename to loader_example.cc index 72b4fa21..d91baaa6 100644 --- a/test.cc +++ b/loader_example.cc @@ -296,7 +296,7 @@ main( char **argv) { if (argc > 1) { - const char* basepath = NULL; + const char* basepath = "models/"; if (argc > 2) { basepath = argv[2]; } @@ -305,7 +305,7 @@ main( //assert(true == TestLoadObj("cornell_box.obj")); //assert(true == TestLoadObj("cube.obj")); assert(true == TestStreamLoadObj()); - assert(true == TestLoadObj("catmark_torus_creases0.obj", NULL, false)); + assert(true == TestLoadObj("models/catmark_torus_creases0.obj", "models/", false)); } return 0; diff --git a/cornell_box.mtl b/models/cornell_box.mtl similarity index 100% rename from cornell_box.mtl rename to models/cornell_box.mtl diff --git a/cornell_box.obj b/models/cornell_box.obj similarity index 100% rename from cornell_box.obj rename to models/cornell_box.obj diff --git a/premake4.lua b/premake4.lua index cbfdfd92..cd5b2952 100644 --- a/premake4.lua +++ b/premake4.lua @@ -1,5 +1,5 @@ sources = { - "test.cc", + "loader_example.cc", } -- premake4.lua @@ -21,9 +21,9 @@ solution "TinyObjLoaderSolution" configuration "Debug" defines { "DEBUG" } -- -DDEBUG flags { "Symbols" } - targetname "test_tinyobjloader_debug" + targetname "loader_example_debug" configuration "Release" -- defines { "NDEBUG" } -- -NDEBUG flags { "Symbols", "Optimize" } - targetname "test_tinyobjloader" + targetname "loader_example" diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 00000000..1a1434ab --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,13 @@ +.PHONY: clean + +tester: tester.cc + g++ -g -O0 -o tester tester.cc + +all: tester + +check: tester + ./tester + +clean: + rm -rf tester + diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..6ed65ff9 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,25 @@ +# Build&Test + +## Use makefile + + $ make check + +## Use ninja + kuroga + +Assume + +* ninja 1.4+ +* python 2.6+ + +Are installed. + +### Linux/MacOSX + + $ python kuroga.py config-posix.py + $ ninja + +### Windows + + > python kuroga.py config-msvc.py + > vcbuild.bat + diff --git a/tests/catch.hpp b/tests/catch.hpp new file mode 100644 index 00000000..2a7146a7 --- /dev/null +++ b/tests/catch.hpp @@ -0,0 +1,10445 @@ +/* + * Catch v1.4.0 + * Generated: 2016-03-15 07:23:12.623111 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#if defined(__cplusplus) && __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( ... ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + namespace{ \ + struct TestName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + namespace{ \ + struct TestCaseName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestCaseName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return bool( opCast( lhs ) == opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) != opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) < opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) > opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) >= opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) <= opCast( rhs ) ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( nullptr, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template + struct EnumStringMaker + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast::type>(v) + ); + } + }; +#endif + template + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template + static std::string convert( T const& v ) + { + return EnumStringMaker::convert( v ); + } +#else + template + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template +//struct StringMaker > { +// static std::string convert( std::vector const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template +std::string toString( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get(tuple)); + ElementPrinter::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template +struct StringMaker> { + + static std::string convert( const std::tuple& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && static_cast(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = (matcher).toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( (matcher).match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + std::auto_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector getReporterNames() const { return m_data.reporterNames; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + std::auto_ptr m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.1.1 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_ form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + // Use this to try and stop compiler from warning about unreachable code + inline bool isTrue( bool value ) { return value; } + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + if( isTrue( true ) ) + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const* const argv[], std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const* const argv[] ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const* argv[], ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes|no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + }; + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map > FactoryMap; + typedef std::vector > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast( childTracker ); + assert( section ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + do { + m_trackerContext.startRun(); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "#" + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + int run( int argc, char* argv[] ) { + return run( argc, const_cast( argv ) ); + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace Catch { + + struct LexSort { + bool operator() (TestCase i,TestCase j) const { return (i sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector const& getAllTests() const { + return m_functions; + } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 4, 0, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public SharedImpl { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/tests/config-msvc.py b/tests/config-msvc.py new file mode 100644 index 00000000..06fae62f --- /dev/null +++ b/tests/config-msvc.py @@ -0,0 +1,52 @@ +exe = "tester.exe" + +toolchain = "msvc" + +# optional +link_pool_depth = 1 + +# optional +builddir = { + "gnu" : "build" + , "msvc" : "build" + , "clang" : "build" + } + +includes = { + "gnu" : [ "-I." ] + , "msvc" : [ "/I." ] + , "clang" : [ "-I." ] + } + +defines = { + "gnu" : [ "-DEXAMPLE=1" ] + , "msvc" : [ "/DEXAMPLE=1" ] + , "clang" : [ "-DEXAMPLE=1" ] + } + +cflags = { + "gnu" : [ "-O2", "-g" ] + , "msvc" : [ "/O2" ] + , "clang" : [ "-O2", "-g" ] + } + +cxxflags = { + "gnu" : [ "-O2", "-g" ] + , "msvc" : [ "/O2" ] + , "clang" : [ "-O2", "-g", "-fsanitize=address" ] + } + +ldflags = { + "gnu" : [ ] + , "msvc" : [ ] + , "clang" : [ "-fsanitize=address" ] + } + +# optionsl +cxx_files = [ "tester.cc" ] +c_files = [ ] + +# You can register your own toolchain through register_toolchain function +def register_toolchain(ninja): + pass + diff --git a/tests/config-posix.py b/tests/config-posix.py new file mode 100644 index 00000000..29cc4d55 --- /dev/null +++ b/tests/config-posix.py @@ -0,0 +1,53 @@ +exe = "tester" + +# "gnu" or "clang" +toolchain = "gnu" + +# optional +link_pool_depth = 1 + +# optional +builddir = { + "gnu" : "build" + , "msvc" : "build" + , "clang" : "build" + } + +includes = { + "gnu" : [ "-I." ] + , "msvc" : [ "/I." ] + , "clang" : [ "-I." ] + } + +defines = { + "gnu" : [ ] + , "msvc" : [ ] + , "clang" : [ ] + } + +cflags = { + "gnu" : [ "-O2", "-g" ] + , "msvc" : [ "/O2" ] + , "clang" : [ "-O2", "-g" ] + } + +# Warn as much as possible: http://qiita.com/MitsutakaTakeda/items/6b9966f890cc9b944d75 +cxxflags = { + "gnu" : [ "-O2", "-g", "-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused", "-fsanitize=address" ] + , "msvc" : [ "/O2", "/W4" ] + , "clang" : [ "-O2", "-g", "-Werror -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic", "-fsanitize=address" ] + } + +ldflags = { + "gnu" : [ "-fsanitize=address" ] + , "msvc" : [ ] + , "clang" : [ "-fsanitize=address" ] + } + +cxx_files = [ "tester.cc" ] +c_files = [ ] + +# You can register your own toolchain through register_toolchain function +def register_toolchain(ninja): + pass + diff --git a/tests/kuroga.py b/tests/kuroga.py new file mode 100755 index 00000000..56d3f863 --- /dev/null +++ b/tests/kuroga.py @@ -0,0 +1,312 @@ +#!/usr/bin/env python + +# +# Kuroga, single python file meta-build system for ninja +# https://github.com/lighttransport/kuroga +# +# Requirements: python 2.6 or 2.7 +# +# Usage: $ python kuroga.py input.py +# + +import imp +import re +import textwrap +import glob +import os +import sys + +# gcc preset +def add_gnu_rule(ninja): + ninja.rule('gnucxx', description='CXX $out', + command='$gnucxx -MMD -MF $out.d $gnudefines $gnuincludes $gnucxxflags -c $in -o $out', + depfile='$out.d', deps='gcc') + ninja.rule('gnucc', description='CC $out', + command='$gnucc -MMD -MF $out.d $gnudefines $gnuincludes $gnucflags -c $in -o $out', + depfile='$out.d', deps='gcc') + ninja.rule('gnulink', description='LINK $out', pool='link_pool', + command='$gnuld -o $out $in $libs $gnuldflags') + ninja.rule('gnuar', description='AR $out', pool='link_pool', + command='$gnuar rsc $out $in') + ninja.rule('gnustamp', description='STAMP $out', command='touch $out') + ninja.newline() + + ninja.variable('gnucxx', 'g++') + ninja.variable('gnucc', 'gcc') + ninja.variable('gnuld', '$gnucxx') + ninja.variable('gnuar', 'ar') + ninja.newline() + +# clang preset +def add_clang_rule(ninja): + ninja.rule('clangcxx', description='CXX $out', + command='$clangcxx -MMD -MF $out.d $clangdefines $clangincludes $clangcxxflags -c $in -o $out', + depfile='$out.d', deps='gcc') + ninja.rule('clangcc', description='CC $out', + command='$clangcc -MMD -MF $out.d $clangdefines $clangincludes $clangcflags -c $in -o $out', + depfile='$out.d', deps='gcc') + ninja.rule('clanglink', description='LINK $out', pool='link_pool', + command='$clangld -o $out $in $libs $clangldflags') + ninja.rule('clangar', description='AR $out', pool='link_pool', + command='$clangar rsc $out $in') + ninja.rule('clangstamp', description='STAMP $out', command='touch $out') + ninja.newline() + + ninja.variable('clangcxx', 'clang++') + ninja.variable('clangcc', 'clang') + ninja.variable('clangld', '$clangcxx') + ninja.variable('clangar', 'ar') + ninja.newline() + +# msvc preset +def add_msvc_rule(ninja): + ninja.rule('msvccxx', description='CXX $out', + command='$msvccxx /TP /showIncludes $msvcdefines $msvcincludes $msvccxxflags -c $in /Fo$out', + depfile='$out.d', deps='msvc') + ninja.rule('msvccc', description='CC $out', + command='$msvccc /TC /showIncludes $msvcdefines $msvcincludes $msvccflags -c $in /Fo$out', + depfile='$out.d', deps='msvc') + ninja.rule('msvclink', description='LINK $out', pool='link_pool', + command='$msvcld $msvcldflags $in $libs /OUT:$out') + ninja.rule('msvcar', description='AR $out', pool='link_pool', + command='$msvcar $in /OUT:$out') + #ninja.rule('msvcstamp', description='STAMP $out', command='touch $out') + ninja.newline() + + ninja.variable('msvccxx', 'cl.exe') + ninja.variable('msvccc', 'cl.exe') + ninja.variable('msvcld', 'link.exe') + ninja.variable('msvcar', 'lib.exe') + ninja.newline() + +# -- from ninja_syntax.py -- +def escape_path(word): + return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') + +class Writer(object): + def __init__(self, output, width=78): + self.output = output + self.width = width + + def newline(self): + self.output.write('\n') + + def comment(self, text, has_path=False): + for line in textwrap.wrap(text, self.width - 2, break_long_words=False, + break_on_hyphens=False): + self.output.write('# ' + line + '\n') + + def variable(self, key, value, indent=0): + if value is None: + return + if isinstance(value, list): + value = ' '.join(filter(None, value)) # Filter out empty strings. + self._line('%s = %s' % (key, value), indent) + + def pool(self, name, depth): + self._line('pool %s' % name) + self.variable('depth', depth, indent=1) + + def rule(self, name, command, description=None, depfile=None, + generator=False, pool=None, restat=False, rspfile=None, + rspfile_content=None, deps=None): + self._line('rule %s' % name) + self.variable('command', command, indent=1) + if description: + self.variable('description', description, indent=1) + if depfile: + self.variable('depfile', depfile, indent=1) + if generator: + self.variable('generator', '1', indent=1) + if pool: + self.variable('pool', pool, indent=1) + if restat: + self.variable('restat', '1', indent=1) + if rspfile: + self.variable('rspfile', rspfile, indent=1) + if rspfile_content: + self.variable('rspfile_content', rspfile_content, indent=1) + if deps: + self.variable('deps', deps, indent=1) + + def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, + variables=None): + outputs = as_list(outputs) + out_outputs = [escape_path(x) for x in outputs] + all_inputs = [escape_path(x) for x in as_list(inputs)] + + if implicit: + implicit = [escape_path(x) for x in as_list(implicit)] + all_inputs.append('|') + all_inputs.extend(implicit) + if order_only: + order_only = [escape_path(x) for x in as_list(order_only)] + all_inputs.append('||') + all_inputs.extend(order_only) + + self._line('build %s: %s' % (' '.join(out_outputs), + ' '.join([rule] + all_inputs))) + + if variables: + if isinstance(variables, dict): + iterator = iter(variables.items()) + else: + iterator = iter(variables) + + for key, val in iterator: + self.variable(key, val, indent=1) + + return outputs + + def include(self, path): + self._line('include %s' % path) + + def subninja(self, path): + self._line('subninja %s' % path) + + def default(self, paths): + self._line('default %s' % ' '.join(as_list(paths))) + + def _count_dollars_before_index(self, s, i): + """Returns the number of '$' characters right in front of s[i].""" + dollar_count = 0 + dollar_index = i - 1 + while dollar_index > 0 and s[dollar_index] == '$': + dollar_count += 1 + dollar_index -= 1 + return dollar_count + + def _line(self, text, indent=0): + """Write 'text' word-wrapped at self.width characters.""" + leading_space = ' ' * indent + while len(leading_space) + len(text) > self.width: + # The text is too wide; wrap if possible. + + # Find the rightmost space that would obey our width constraint and + # that's not an escaped space. + available_space = self.width - len(leading_space) - len(' $') + space = available_space + while True: + space = text.rfind(' ', 0, space) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break + + if space < 0: + # No such space; just use the first unescaped space we can find. + space = available_space - 1 + while True: + space = text.find(' ', space + 1) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break + if space < 0: + # Give up on breaking. + break + + self.output.write(leading_space + text[0:space] + ' $\n') + text = text[space+1:] + + # Subsequent lines are continuations, so indent them. + leading_space = ' ' * (indent+2) + + self.output.write(leading_space + text + '\n') + + def close(self): + self.output.close() + + +def as_list(input): + if input is None: + return [] + if isinstance(input, list): + return input + return [input] + +# -- end from ninja_syntax.py -- + +def gen(ninja, toolchain, config): + + ninja.variable('ninja_required_version', '1.4') + ninja.newline() + + if hasattr(config, "builddir"): + builddir = config.builddir[toolchain] + ninja.variable(toolchain + 'builddir', builddir) + else: + builddir = '' + + ninja.variable(toolchain + 'defines', config.defines[toolchain] or []) + ninja.variable(toolchain + 'includes', config.includes[toolchain] or []) + ninja.variable(toolchain + 'cflags', config.cflags[toolchain] or []) + ninja.variable(toolchain + 'cxxflags', config.cxxflags[toolchain] or []) + ninja.variable(toolchain + 'ldflags', config.ldflags[toolchain] or []) + ninja.newline() + + if hasattr(config, "link_pool_depth"): + ninja.pool('link_pool', depth=config.link_pool_depth) + else: + ninja.pool('link_pool', depth=4) + ninja.newline() + + # Add default toolchain(gnu, clang and msvc) + add_gnu_rule(ninja) + add_clang_rule(ninja) + add_msvc_rule(ninja) + + obj_files = [] + + cc = toolchain + 'cc' + cxx = toolchain + 'cxx' + link = toolchain + 'link' + ar = toolchain + 'ar' + + if hasattr(config, "cxx_files"): + for src in config.cxx_files: + srcfile = src + obj = os.path.splitext(srcfile)[0] + '.o' + obj = os.path.join(builddir, obj); + obj_files.append(obj) + ninja.build(obj, cxx, srcfile) + ninja.newline() + + if hasattr(config, "c_files"): + for src in config.c_files: + srcfile = src + obj = os.path.splitext(srcfile)[0] + '.o' + obj = os.path.join(builddir, obj); + obj_files.append(obj) + ninja.build(obj, cc, srcfile) + ninja.newline() + + targetlist = [] + if hasattr(config, "exe"): + ninja.build(config.exe, link, obj_files) + targetlist.append(config.exe) + + if hasattr(config, "staticlib"): + ninja.build(config.staticlib, ar, obj_files) + targetlist.append(config.staticlib) + + ninja.build('all', 'phony', targetlist) + ninja.newline() + + ninja.default('all') + +def main(): + if len(sys.argv) < 2: + print("Usage: python kuroga.py config.py") + sys.exit(1) + + config = imp.load_source("config", sys.argv[1]) + + f = open('build.ninja', 'w') + ninja = Writer(f) + + if hasattr(config, "register_toolchain"): + config.register_toolchain(ninja) + + gen(ninja, config.toolchain, config) + f.close() + +main() diff --git a/tests/tester.cc b/tests/tester.cc new file mode 100644 index 00000000..edb92ba6 --- /dev/null +++ b/tests/tester.cc @@ -0,0 +1,324 @@ +#define TINYOBJLOADER_IMPLEMENTATION +#include "../tiny_obj_loader.h" + +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include "catch.hpp" + +#include +#include +#include +#include +#include +#include + +static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector& shapes, const std::vector& materials, bool triangulate = true) +{ + std::cout << "# of vertices : " << (attrib.vertices.size() / 3) << std::endl; + std::cout << "# of normals : " << (attrib.normals.size() / 3) << std::endl; + std::cout << "# of texcoords : " << (attrib.texcoords.size() / 2) << std::endl; + + std::cout << "# of shapes : " << shapes.size() << std::endl; + std::cout << "# of materials : " << materials.size() << std::endl; + + for (size_t v = 0; v < attrib.vertices.size() / 3; v++) { + printf(" v[%ld] = (%f, %f, %f)\n", v, + static_cast(attrib.vertices[3*v+0]), + static_cast(attrib.vertices[3*v+1]), + static_cast(attrib.vertices[3*v+2])); + } + + for (size_t v = 0; v < attrib.normals.size() / 3; v++) { + printf(" n[%ld] = (%f, %f, %f)\n", v, + static_cast(attrib.normals[3*v+0]), + static_cast(attrib.normals[3*v+1]), + static_cast(attrib.normals[3*v+2])); + } + + for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) { + printf(" uv[%ld] = (%f, %f)\n", v, + static_cast(attrib.texcoords[2*v+0]), + static_cast(attrib.texcoords[2*v+1])); + } + + for (size_t i = 0; i < shapes.size(); i++) { + printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str()); + printf("Size of shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size()); + + if (triangulate) + { + printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size()); + assert((shapes[i].mesh.indices.size() % 3) == 0); + for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) { + tinyobj::index_t i0 = shapes[i].mesh.indices[3*f+0]; + tinyobj::index_t i1 = shapes[i].mesh.indices[3*f+1]; + tinyobj::index_t i2 = shapes[i].mesh.indices[3*f+2]; + printf(" idx[%ld] = %d/%d/%d, %d/%d/%d, %d/%d/%d. mat_id = %d\n", f, + i0.vertex_index, i0.normal_index, i0.texcoord_index, + i1.vertex_index, i1.normal_index, i1.texcoord_index, + i2.vertex_index, i2.normal_index, i2.texcoord_index, + shapes[i].mesh.material_ids[f]); + } + } else { + for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) { + tinyobj::index_t idx = shapes[i].mesh.indices[f]; + printf(" idx[%ld] = %d/%d/%d\n", f, idx.vertex_index, idx.normal_index, idx.texcoord_index); + } + + printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size()); + assert(shapes[i].mesh.material_ids.size() == shapes[i].mesh.num_vertices.size()); + for (size_t m = 0; m < shapes[i].mesh.material_ids.size(); m++) { + printf(" material_id[%ld] = %d\n", m, + shapes[i].mesh.material_ids[m]); + } + + } + + printf("shape[%ld].num_faces: %ld\n", i, shapes[i].mesh.num_vertices.size()); + for (size_t v = 0; v < shapes[i].mesh.num_vertices.size(); v++) { + printf(" num_vertices[%ld] = %ld\n", v, + static_cast(shapes[i].mesh.num_vertices[v])); + } + + //printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size()); + //assert((shapes[i].mesh.positions.size() % 3) == 0); + //for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) { + // printf(" v[%ld] = (%f, %f, %f)\n", v, + // static_cast(shapes[i].mesh.positions[3*v+0]), + // static_cast(shapes[i].mesh.positions[3*v+1]), + // static_cast(shapes[i].mesh.positions[3*v+2])); + //} + + printf("shape[%ld].num_tags: %ld\n", i, shapes[i].mesh.tags.size()); + for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) { + printf(" tag[%ld] = %s ", t, shapes[i].mesh.tags[t].name.c_str()); + printf(" ints: ["); + for (size_t j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j) + { + printf("%ld", static_cast(shapes[i].mesh.tags[t].intValues[j])); + if (j < (shapes[i].mesh.tags[t].intValues.size()-1)) + { + printf(", "); + } + } + printf("]"); + + printf(" floats: ["); + for (size_t j = 0; j < shapes[i].mesh.tags[t].floatValues.size(); ++j) + { + printf("%f", static_cast(shapes[i].mesh.tags[t].floatValues[j])); + if (j < (shapes[i].mesh.tags[t].floatValues.size()-1)) + { + printf(", "); + } + } + printf("]"); + + printf(" strings: ["); + for (size_t j = 0; j < shapes[i].mesh.tags[t].stringValues.size(); ++j) + { + printf("%s", shapes[i].mesh.tags[t].stringValues[j].c_str()); + if (j < (shapes[i].mesh.tags[t].stringValues.size()-1)) + { + printf(", "); + } + } + printf("]"); + printf("\n"); + } + } + + for (size_t i = 0; i < materials.size(); i++) { + printf("material[%ld].name = %s\n", i, materials[i].name.c_str()); + printf(" material.Ka = (%f, %f ,%f)\n", static_cast(materials[i].ambient[0]), static_cast(materials[i].ambient[1]), static_cast(materials[i].ambient[2])); + printf(" material.Kd = (%f, %f ,%f)\n", static_cast(materials[i].diffuse[0]), static_cast(materials[i].diffuse[1]), static_cast(materials[i].diffuse[2])); + printf(" material.Ks = (%f, %f ,%f)\n", static_cast(materials[i].specular[0]), static_cast(materials[i].specular[1]), static_cast(materials[i].specular[2])); + printf(" material.Tr = (%f, %f ,%f)\n", static_cast(materials[i].transmittance[0]), static_cast(materials[i].transmittance[1]), static_cast(materials[i].transmittance[2])); + printf(" material.Ke = (%f, %f ,%f)\n", static_cast(materials[i].emission[0]), static_cast(materials[i].emission[1]), static_cast(materials[i].emission[2])); + printf(" material.Ns = %f\n", static_cast(materials[i].shininess)); + printf(" material.Ni = %f\n", static_cast(materials[i].ior)); + printf(" material.dissolve = %f\n", static_cast(materials[i].dissolve)); + printf(" material.illum = %d\n", materials[i].illum); + printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str()); + printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str()); + printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str()); + printf(" material.map_Ns = %s\n", materials[i].specular_highlight_texname.c_str()); + printf(" material.map_bump = %s\n", materials[i].bump_texname.c_str()); + printf(" material.map_d = %s\n", materials[i].alpha_texname.c_str()); + printf(" material.disp = %s\n", materials[i].displacement_texname.c_str()); + std::map::const_iterator it(materials[i].unknown_parameter.begin()); + std::map::const_iterator itEnd(materials[i].unknown_parameter.end()); + + for (; it != itEnd; it++) { + printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str()); + } + printf("\n"); + } +} + +static bool +TestLoadObj( + const char* filename, + const char* basepath = NULL, + bool triangulate = true) +{ + std::cout << "Loading " << filename << std::endl; + + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, basepath, triangulate); + + if (!err.empty()) { + std::cerr << err << std::endl; + } + + if (!ret) { + printf("Failed to load/parse .obj.\n"); + return false; + } + + PrintInfo(attrib, shapes, materials, triangulate); + + return true; +} + + +static bool +TestStreamLoadObj() +{ + std::cout << "Stream Loading " << std::endl; + + std::stringstream objStream; + objStream + << "mtllib cube.mtl\n" + "\n" + "v 0.000000 2.000000 2.000000\n" + "v 0.000000 0.000000 2.000000\n" + "v 2.000000 0.000000 2.000000\n" + "v 2.000000 2.000000 2.000000\n" + "v 0.000000 2.000000 0.000000\n" + "v 0.000000 0.000000 0.000000\n" + "v 2.000000 0.000000 0.000000\n" + "v 2.000000 2.000000 0.000000\n" + "# 8 vertices\n" + "\n" + "g front cube\n" + "usemtl white\n" + "f 1 2 3 4\n" + "g back cube\n" + "# expects white material\n" + "f 8 7 6 5\n" + "g right cube\n" + "usemtl red\n" + "f 4 3 7 8\n" + "g top cube\n" + "usemtl white\n" + "f 5 1 4 8\n" + "g left cube\n" + "usemtl green\n" + "f 5 6 2 1\n" + "g bottom cube\n" + "usemtl white\n" + "f 2 6 7 3\n" + "# 6 elements"; + +std::string matStream( + "newmtl white\n" + "Ka 0 0 0\n" + "Kd 1 1 1\n" + "Ks 0 0 0\n" + "\n" + "newmtl red\n" + "Ka 0 0 0\n" + "Kd 1 0 0\n" + "Ks 0 0 0\n" + "\n" + "newmtl green\n" + "Ka 0 0 0\n" + "Kd 0 1 0\n" + "Ks 0 0 0\n" + "\n" + "newmtl blue\n" + "Ka 0 0 0\n" + "Kd 0 0 1\n" + "Ks 0 0 0\n" + "\n" + "newmtl light\n" + "Ka 20 20 20\n" + "Kd 1 1 1\n" + "Ks 0 0 0"); + + using namespace tinyobj; + class MaterialStringStreamReader: + public MaterialReader + { + public: + MaterialStringStreamReader(const std::string& matSStream): m_matSStream(matSStream) {} + virtual ~MaterialStringStreamReader() {} + virtual bool operator() ( + const std::string& matId, + std::vector* materials, + std::map* matMap, + std::string* err) + { + (void)matId; + (void)err; + LoadMtl(matMap, materials, &m_matSStream); + return true; + } + + private: + std::stringstream m_matSStream; + }; + + MaterialStringStreamReader matSSReader(matStream); + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &objStream, &matSSReader); + + if (!err.empty()) { + std::cerr << err << std::endl; + } + + if (!ret) { + return false; + } + + PrintInfo(attrib, shapes, materials); + + return true; +} + +const char* gMtlBasePath = "../models"; + +TEST_CASE("cornell_box", "[Loader]") { + + REQUIRE(true == TestLoadObj("../models/cornell_box.obj", gMtlBasePath)); +} + +#if 0 +int +main( + int argc, + char **argv) +{ + if (argc > 1) { + const char* basepath = NULL; + if (argc > 2) { + basepath = argv[2]; + } + assert(true == TestLoadObj(argv[1], basepath)); + } else { + //assert(true == TestLoadObj("cornell_box.obj")); + //assert(true == TestLoadObj("cube.obj")); + assert(true == TestStreamLoadObj()); + assert(true == TestLoadObj("catmark_torus_creases0.obj", NULL, false)); + } + + return 0; +} +#endif diff --git a/tests/vcbuild.bat b/tests/vcbuild.bat new file mode 100644 index 00000000..3dbc6c16 --- /dev/null +++ b/tests/vcbuild.bat @@ -0,0 +1,3 @@ +chcp 437 +call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64 +ninja diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index e67bed32..9a03489e 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -111,6 +111,33 @@ typedef struct { std::vector texcoords; // 'vt' } attrib_t; +typedef struct callback_t_ { + void (*vertex_cb)(void *user_data, float x, float y, float z); + void (*normal_cb)(void *user_data, float x, float y, float z); + void (*texcoord_cb)(void *user_data, float x, float y); + // -2147483648 will be passed for undefined index + void (*index_cb)(void *user_data, int v_idx, int vn_idx, int vt_idx); + // Index to material + void (*usemtl_cb)(void *user_data, int material_idx); + void (*mtllib_cb)(void *user_data, const material_t *materials, + int num_materials); + // There may be multiple group names + void (*group_cb)(void *user_data, const char **names, int num_names); + void (*object_cb)(void *user_data, const char *name); + + callback_t_() : + vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) { + } + +} callback_t; + class MaterialReader { public: MaterialReader() {} @@ -138,7 +165,6 @@ class MaterialFileReader : public MaterialReader { /// Loads .obj from a file. /// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data /// 'shapes' will be filled with parsed shape data -/// The function returns error string. /// Returns true when loading .obj become success. /// Returns warning and error message into `err` /// 'mtl_basepath' is optional, and used for base path for .mtl file. @@ -149,6 +175,18 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, const char *filename, const char *mtl_basepath = NULL, bool triangulate = true); +/// Loads .obj from a file with custom user callback. +/// .mtl is loaded as usual and parsed material_t data will be passed to +/// `callback.mtllib_cb`. +/// Returns true when loading .obj/.mtl become success. +/// Returns warning and error message into `err` +/// 'mtl_basepath' is optional, and used for base path for .mtl file. +/// 'triangulate' is optional, and used whether triangulate polygon face in .obj +/// or not. +bool LoadObjWithCallback(void *user_data, const callback_t &callback, + std::string *err, std::istream *inStream, + MaterialReader *readMatFn); + /// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve /// std::istream for materials. /// Returns true when loading .obj become success. @@ -418,7 +456,7 @@ static tag_sizes parseTagTriple(const char **token) { return ts; } -// Parse triples: i, i/j/k, i//k, i/j +// Parse triples with index offsets: i, i/j/k, i//k, i/j static vertex_index parseTriple(const char **token, int vsize, int vnsize, int vtsize) { vertex_index vi(-1); @@ -452,6 +490,39 @@ static vertex_index parseTriple(const char **token, int vsize, int vnsize, return vi; } +// Parse raw triples: i, i/j/k, i//k, i/j +static vertex_index parseRawTriple(const char **token) { + vertex_index vi(0x8000000); // -2147483648 = invalid + + vi.v_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + (*token)++; + + // i//k + if ((*token)[0] == '/') { + (*token)++; + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; + } + + // i/j/k or i/j + vi.vt_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + if ((*token)[0] != '/') { + return vi; + } + + // i/j/k + (*token)++; // skip '/' + vi.vn_idx = atoi((*token)); + (*token) += strcspn((*token), "/ \t\r"); + return vi; +} + static void InitMaterial(material_t *material) { material->name = ""; material->ambient_texname = ""; @@ -831,7 +902,6 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, // material std::map material_map; - // std::map vertexCache; int material = -1; shape_t shape; @@ -1103,6 +1173,270 @@ bool LoadObj(attrib_t *attrib, std::vector *shapes, return true; } +bool LoadObjWithCallback(void *user_data, const callback_t &callback, + std::string *err, std::istream *inStream, + MaterialReader *readMatFn) { + std::stringstream errss; + + std::string name; + + // material + std::map material_map; + int material = -1; + + shape_t shape; + + int maxchars = 8192; // Alloc enough size. + std::vector buf(static_cast(maxchars)); // Alloc enough size. + while (inStream->peek() != -1) { + inStream->getline(&buf[0], maxchars); + + std::string linebuf(&buf[0]); + + // Trim newline '\r\n' or '\n' + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\n') + linebuf.erase(linebuf.size() - 1); + } + if (linebuf.size() > 0) { + if (linebuf[linebuf.size() - 1] == '\r') + linebuf.erase(linebuf.size() - 1); + } + + // Skip if empty line. + if (linebuf.empty()) { + continue; + } + + // Skip leading space. + const char *token = linebuf.c_str(); + token += strspn(token, " \t"); + + assert(token); + if (token[0] == '\0') continue; // empty line + + if (token[0] == '#') continue; // comment line + + // vertex + if (token[0] == 'v' && IS_SPACE((token[1]))) { + token += 2; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.vertex_cb) { + callback.vertex_cb(user_data, x, y, z); + } + continue; + } + + // normal + if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { + token += 3; + float x, y, z; + parseFloat3(&x, &y, &z, &token); + if (callback.normal_cb) { + callback.normal_cb(user_data, x, y, z); + } + continue; + } + + // texcoord + if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { + token += 3; + float x, y; + parseFloat2(&x, &y, &token); + if (callback.texcoord_cb) { + callback.texcoord_cb(user_data, x, y); + } + continue; + } + + // face + if (token[0] == 'f' && IS_SPACE((token[1]))) { + token += 2; + token += strspn(token, " \t"); + + while (!IS_NEW_LINE(token[0])) { + vertex_index vi = parseRawTriple(&token); + if (callback.index_cb) { + callback.index_cb(user_data, vi.v_idx, vi.vn_idx, vi.vt_idx); + } + size_t n = strspn(token, " \t\r"); + token += n; + } + + continue; + } + + // use mtl + if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + int newMaterialId = -1; + if (material_map.find(namebuf) != material_map.end()) { + newMaterialId = material_map[namebuf]; + } else { + // { error!! material not found } + } + + if (newMaterialId != material) { + material = newMaterialId; + } + + if (callback.usemtl_cb) { + callback.usemtl_cb(user_data, material); + } + + continue; + } + + // load mtl + if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 7; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + + std::string err_mtl; + std::vector materials; + bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl); + if (err) { + (*err) += err_mtl; + } + + if (!ok) { + return false; + } + + if (callback.mtllib_cb) { + callback.mtllib_cb(user_data, &materials.at(0), + static_cast(materials.size())); + } + + continue; + } + + // group name + if (token[0] == 'g' && IS_SPACE((token[1]))) { + std::vector names; + names.reserve(2); + + while (!IS_NEW_LINE(token[0])) { + std::string str = parseString(&token); + names.push_back(str); + token += strspn(token, " \t\r"); // skip tag + } + + assert(names.size() > 0); + + // names[0] must be 'g', so skip the 0th element. + if (names.size() > 1) { + name = names[1]; + } else { + name = ""; + } + + if (callback.group_cb) { + if (names.size() > 1) { + // create const char* array. + std::vector tmp(names.size() - 1); + for (size_t j = 0; j < tmp.size(); j++) { + tmp[j] = names[j + 1].c_str(); + } + callback.group_cb(user_data, &tmp.at(0), + static_cast(tmp.size())); + + } else { + callback.group_cb(user_data, NULL, 0); + } + + continue; + } + + // object name + if (token[0] == 'o' && IS_SPACE((token[1]))) { + // @todo { multiple object name? } + char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + name = std::string(namebuf); + + if (callback.object_cb) { + callback.object_cb(user_data, name.c_str()); + } + + continue; + } + +#if 0 // @todo + if (token[0] == 't' && IS_SPACE(token[1])) { + tag_t tag; + + char namebuf[4096]; + token += 2; +#ifdef _MSC_VER + sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); +#else + sscanf(token, "%s", namebuf); +#endif + tag.name = std::string(namebuf); + + token += tag.name.size() + 1; + + tag_sizes ts = parseTagTriple(&token); + + tag.intValues.resize(static_cast(ts.num_ints)); + + for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { + tag.intValues[i] = atoi(token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.floatValues.resize(static_cast(ts.num_floats)); + for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { + tag.floatValues[i] = parseFloat(&token); + token += strcspn(token, "/ \t\r") + 1; + } + + tag.stringValues.resize(static_cast(ts.num_strings)); + for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { + char stringValueBuffer[4096]; + +#ifdef _MSC_VER + sscanf_s(token, "%s", stringValueBuffer, + (unsigned)_countof(stringValueBuffer)); +#else + sscanf(token, "%s", stringValueBuffer); +#endif + tag.stringValues[i] = stringValueBuffer; + token += tag.stringValues[i].size() + 1; + } + + tags.push_back(tag); +#endif + } + + // Ignore unknown command. + } + + if (err) { + (*err) += errss.str(); + } + + return true; +} } // namespace tinyobj #endif From 93acf631571ded19556a4f4684541f5ecb3c8f10 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 18 Apr 2016 16:48:37 +0900 Subject: [PATCH 004/483] Change API for usemtl callback. --- tiny_obj_loader.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 9a03489e..d46c704d 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -117,8 +117,9 @@ typedef struct callback_t_ { void (*texcoord_cb)(void *user_data, float x, float y); // -2147483648 will be passed for undefined index void (*index_cb)(void *user_data, int v_idx, int vn_idx, int vt_idx); - // Index to material - void (*usemtl_cb)(void *user_data, int material_idx); + // `name` material name, `materialId` = the array index of material_t[]. -1 if a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char* name, int materialId); + // `materials` = parsed material data. void (*mtllib_cb)(void *user_data, const material_t *materials, int num_materials); // There may be multiple group names @@ -1178,13 +1179,9 @@ bool LoadObjWithCallback(void *user_data, const callback_t &callback, MaterialReader *readMatFn) { std::stringstream errss; - std::string name; - // material std::map material_map; - int material = -1; - - shape_t shape; + int materialId = -1; // -1 = invalid int maxchars = 8192; // Alloc enough size. std::vector buf(static_cast(maxchars)); // Alloc enough size. @@ -1284,12 +1281,12 @@ bool LoadObjWithCallback(void *user_data, const callback_t &callback, // { error!! material not found } } - if (newMaterialId != material) { - material = newMaterialId; + if (newMaterialId != materialId) { + materialId = newMaterialId; } if (callback.usemtl_cb) { - callback.usemtl_cb(user_data, material); + callback.usemtl_cb(user_data, namebuf, materialId); } continue; @@ -1337,6 +1334,7 @@ bool LoadObjWithCallback(void *user_data, const callback_t &callback, assert(names.size() > 0); + std::string name; // names[0] must be 'g', so skip the 0th element. if (names.size() > 1) { name = names[1]; From 1e663342bf8d3ea41378e536abd26a609cb45ca0 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 18 Apr 2016 17:52:04 +0900 Subject: [PATCH 005/483] Add callback API example. Fix a sentinel value for the vertex index. --- README.md | 5 ++ examples/callback_api/Makefile | 2 + examples/callback_api/main.cc | 155 +++++++++++++++++++++++++++++++++ tiny_obj_loader.h | 2 +- 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 examples/callback_api/Makefile create mode 100644 examples/callback_api/main.cc diff --git a/README.md b/README.md index 056f7c3a..a180d701 100644 --- a/README.md +++ b/README.md @@ -193,3 +193,8 @@ for (size_t i = 0; i < shapes.size(); i++) { } ``` + +Tests +----- + +Unit tests are provided. see `tests` directory for details. diff --git a/examples/callback_api/Makefile b/examples/callback_api/Makefile new file mode 100644 index 00000000..45d60d85 --- /dev/null +++ b/examples/callback_api/Makefile @@ -0,0 +1,2 @@ +all: + clang++ -I../../ -Wall -g -o example main.cc diff --git a/examples/callback_api/main.cc b/examples/callback_api/main.cc new file mode 100644 index 00000000..4f492d02 --- /dev/null +++ b/examples/callback_api/main.cc @@ -0,0 +1,155 @@ +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include +#include +#include +#include +#include +#include + +typedef struct +{ + std::vector vertices; + std::vector normals; + std::vector texcoords; + std::vector v_indices; + std::vector vn_indices; + std::vector vt_indices; + + std::vector materials; + +} MyMesh; + +void vertex_cb(void *user_data, float x, float y, float z) +{ + MyMesh *mesh = reinterpret_cast(user_data); + printf("v[%ld] = %f, %f, %f\n", mesh->vertices.size() / 3, x, y, z); + + mesh->vertices.push_back(x); + mesh->vertices.push_back(y); + mesh->vertices.push_back(z); +} + +void normal_cb(void *user_data, float x, float y, float z) +{ + MyMesh *mesh = reinterpret_cast(user_data); + printf("vn[%ld] = %f, %f, %f\n", mesh->normals.size() / 3, x, y, z); + + mesh->normals.push_back(x); + mesh->normals.push_back(y); + mesh->normals.push_back(z); +} + +void texcoord_cb(void *user_data, float x, float y) +{ + MyMesh *mesh = reinterpret_cast(user_data); + printf("vt[%ld] = %f, %f\n", mesh->texcoords.size() / 2, x, y); + + mesh->texcoords.push_back(x); + mesh->texcoords.push_back(y); +} + +void index_cb(void *user_data, int v_idx, int vn_idx, int vt_idx) +{ + // NOTE: the value of each index is raw value. + // For example, the application must manually adjust the index with offset + // (e.g. v_indices.size()) when the value is negative(relative index). + // See fixIndex() function in tiny_obj_loader.h for details. + // Also, -2147483648(0x80000000) is set for the index value which does not exist in .obj + MyMesh *mesh = reinterpret_cast(user_data); + printf("idx[%ld] = %d, %d, %d\n", mesh->v_indices.size(), v_idx, vn_idx, vt_idx); + + if (v_idx != 0x80000000) { + mesh->v_indices.push_back(v_idx); + } + if (vn_idx != 0x80000000) { + mesh->vn_indices.push_back(vn_idx); + } + if (vt_idx != 0x80000000) { + mesh->vt_indices.push_back(vt_idx); + } +} + +void usemtl_cb(void *user_data, const char* name, int material_idx) +{ + MyMesh *mesh = reinterpret_cast(user_data); + if ((material_idx > -1) && (material_idx < mesh->materials.size())) { + printf("usemtl. material id = %d(name = %s)\n", material_idx, mesh->materials[material_idx].name.c_str()); + } else { + printf("usemtl. name = %s\n", name); + } +} + +void mtllib_cb(void *user_data, const tinyobj::material_t *materials, int num_materials) +{ + MyMesh *mesh = reinterpret_cast(user_data); + printf("mtllib. # of materials = %d\n", num_materials); + + for (int i = 0; i < num_materials; i++) { + mesh->materials.push_back(materials[i]); + } +} + +void group_cb(void *user_data, const char **names, int num_names) +{ + //MyMesh *mesh = reinterpret_cast(user_data); + printf("group : name = \n"); + + for (int i = 0; i < num_names; i++) { + printf(" %s\n", names[i]); + } +} + +void object_cb(void *user_data, const char *name) +{ + //MyMesh *mesh = reinterpret_cast(user_data); + printf("object : name = %s\n", name); + +} + +int +main(int argc, char** argv) +{ + tinyobj::callback_t cb; + cb.vertex_cb = vertex_cb; + cb.normal_cb = normal_cb; + cb.texcoord_cb = texcoord_cb; + cb.index_cb = index_cb; + cb.usemtl_cb = usemtl_cb; + cb.mtllib_cb = mtllib_cb; + cb.group_cb = group_cb; + cb.object_cb = object_cb; + + MyMesh mesh; + std::string err; + std::ifstream ifs("../../models/cornell_box.obj"); + + if (ifs.fail()) { + std::cerr << "file not found." << std::endl; + return EXIT_FAILURE; + } + + tinyobj::MaterialFileReader mtlReader("../../models/"); + + bool ret = tinyobj::LoadObjWithCallback(&mesh, cb, &err, &ifs, &mtlReader); + + if (!err.empty()) { + std::cerr << err << std::endl; + } + + if (!ret) { + std::cerr << "Failed to parse .obj" << std::endl; + return EXIT_FAILURE; + } + + printf("# of vertices = %ld\n", mesh.vertices.size() / 3); + printf("# of normals = %ld\n", mesh.normals.size() / 3); + printf("# of texcoords = %ld\n", mesh.texcoords.size() / 2); + printf("# of vertex indices = %ld\n", mesh.v_indices.size()); + printf("# of normal indices = %ld\n", mesh.vn_indices.size()); + printf("# of texcoord indices = %ld\n", mesh.vt_indices.size()); + printf("# of materials = %ld\n", mesh.materials.size()); + + return EXIT_SUCCESS; +} diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index d46c704d..d2aae380 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -493,7 +493,7 @@ static vertex_index parseTriple(const char **token, int vsize, int vnsize, // Parse raw triples: i, i/j/k, i//k, i/j static vertex_index parseRawTriple(const char **token) { - vertex_index vi(0x8000000); // -2147483648 = invalid + vertex_index vi(0x80000000); // 0x80000000 = -2147483648 = invalid vi.v_idx = atoi((*token)); (*token) += strcspn((*token), "/ \t\r"); From 90d33c33c02359b3a545664cd60eae84d04788a2 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 18 Apr 2016 17:59:17 +0900 Subject: [PATCH 006/483] Fix CI scripts. --- .travis.yml | 11 ++--------- tests/Makefile | 5 ++++- wercker.yml | 6 ++---- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index bde52f6f..3ec9e45a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,15 +42,8 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user cpp-coveralls; fi script: -- mkdir build && cd build -- export CC="${CC}-${COMPILER_VERSION}" -- export CXX="${CXX}-${COMPILER_VERSION}" -- ${CC} -v -- cmake --version -- cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DTINYOBJLOADER_BUILD_TEST_LOADER=On -G Ninja - .. -- ninja -- ./test_loader ../cornell_box.obj +- cd tests +- make check - if [ -n "$REPORT_COVERAGE" ]; then coveralls -b . -r .. -e examples -e tools -e jni -e python -e images -E ".*CompilerId.*" -E ".*feature_tests.*" ; fi - cd .. diff --git a/tests/Makefile b/tests/Makefile index 1a1434ab..4a18c713 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,10 @@ .PHONY: clean +CXX ?= g++ +CXXFLAGS ?= -g -O2 + tester: tester.cc - g++ -g -O0 -o tester tester.cc + $(CXX) $(CXXFLAGS) -o tester tester.cc all: tester diff --git a/wercker.yml b/wercker.yml index 3c1583c1..1d1aa26f 100644 --- a/wercker.yml +++ b/wercker.yml @@ -6,7 +6,5 @@ build: name: build code: | git clone https://github.com/syoyo/orebuildenv.git - chmod +x ./orebuildenv/build/linux/bin/premake4 - ./orebuildenv/build/linux/bin/premake4 gmake - make - ./test_tinyobjloader + cd tests + make check From 153de2b3f04a44245ae6acd09eeaf0fff2e3efe0 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 18 Apr 2016 19:29:59 +0900 Subject: [PATCH 007/483] Update Android build. --- README.md | 90 +++----------------------------------------------- jni/Android.mk | 4 +-- 2 files changed, 6 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index a180d701..35dfd1e2 100644 --- a/README.md +++ b/README.md @@ -73,12 +73,13 @@ Features * Material * Unknown material attributes are returned as key-value(value is string) map. * Crease tag('t'). This is OpenSubdiv specific(not in wavefront .obj specification) +* Callback API for custom loading. TODO ---- -* [ ] Support different indices for vertex/normal/texcoord +* [ ] Read .obj/.mtl from memory License ------- @@ -88,7 +89,6 @@ Licensed under 2 clause BSD. Usage ----- -TinyObjLoader triangulate input .obj by default. ```c++ #define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc #include "tiny_obj_loader.h" @@ -108,93 +108,11 @@ if (!ret) { exit(1); } -std::cout << "# of shapes : " << shapes.size() << std::endl; -std::cout << "# of materials : " << materials.size() << std::endl; - -for (size_t i = 0; i < shapes.size(); i++) { - printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str()); - printf("Size of shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size()); - printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size()); - assert((shapes[i].mesh.indices.size() % 3) == 0); - for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) { - printf(" idx[%ld] = %d, %d, %d. mat_id = %d\n", f, shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2], shapes[i].mesh.material_ids[f]); - } - - printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size()); - assert((shapes[i].mesh.positions.size() % 3) == 0); - for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) { - printf(" v[%ld] = (%f, %f, %f)\n", v, - shapes[i].mesh.positions[3*v+0], - shapes[i].mesh.positions[3*v+1], - shapes[i].mesh.positions[3*v+2]); - } -} - -for (size_t i = 0; i < materials.size(); i++) { - printf("material[%ld].name = %s\n", i, materials[i].name.c_str()); - printf(" material.Ka = (%f, %f ,%f)\n", materials[i].ambient[0], materials[i].ambient[1], materials[i].ambient[2]); - printf(" material.Kd = (%f, %f ,%f)\n", materials[i].diffuse[0], materials[i].diffuse[1], materials[i].diffuse[2]); - printf(" material.Ks = (%f, %f ,%f)\n", materials[i].specular[0], materials[i].specular[1], materials[i].specular[2]); - printf(" material.Tr = (%f, %f ,%f)\n", materials[i].transmittance[0], materials[i].transmittance[1], materials[i].transmittance[2]); - printf(" material.Ke = (%f, %f ,%f)\n", materials[i].emission[0], materials[i].emission[1], materials[i].emission[2]); - printf(" material.Ns = %f\n", materials[i].shininess); - printf(" material.Ni = %f\n", materials[i].ior); - printf(" material.dissolve = %f\n", materials[i].dissolve); - printf(" material.illum = %d\n", materials[i].illum); - printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str()); - printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str()); - printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str()); - printf(" material.map_Ns = %s\n", materials[i].specular_highlight_texname.c_str()); - std::map::const_iterator it(materials[i].unknown_parameter.begin()); - std::map::const_iterator itEnd(materials[i].unknown_parameter.end()); - for (; it != itEnd; it++) { - printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str()); - } - printf("\n"); -} +// See loader_example.cc for more details. ``` -Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(indices). `num_vertices[i]` stores the number of vertices for ith face. -```c++ -#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc -#include "tiny_obj_loader.h" - -std::string inputfile = "cornell_box.obj"; -std::vector shapes; -std::vector materials; - -std::string err; -bool triangulate = false; -bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str(), triangulate); - -if (!err.empty()) { // `err` may contain warning message. - std::cerr << err << std::endl; -} - -if (!ret) { - exit(1); -} - -for (size_t i = 0; i < shapes.size(); i++) { - - size_t indexOffset = 0; - for (size_t n = 0; n < shapes[i].mesh.num_vertices.size(); n++) { - int ngon = shapes[i].mesh.num_vertices[n]; - for (size_t f = 0; f < ngon; f++) { - unsigned int v = shapes[i].mesh.indices[indexOffset + f]; - printf(" face[%ld] v[%ld] = (%f, %f, %f)\n", n, - shapes[i].mesh.positions[3*v+0], - shapes[i].mesh.positions[3*v+1], - shapes[i].mesh.positions[3*v+2]); - - } - indexOffset += ngon; - } - -} -``` Tests ----- -Unit tests are provided. see `tests` directory for details. +Unit tests are provided in `tests` directory. See `tests/README.md` for details. diff --git a/jni/Android.mk b/jni/Android.mk index eaed1b78..bc81f8f7 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -5,8 +5,8 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := tinyobjloader -LOCAL_SRC_FILES := ../tiny_obj_loader.cc ../test.cc +LOCAL_SRC_FILES := ../tiny_obj_loader.cc LOCAL_C_INCLUDES := ../ -include $(BUILD_EXECUTABLE) +include $(BUILD_STATIC_LIBRARY) From 1703ab087db0e90fc807ddd176a1ea426b7cf7a5 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 18 Apr 2016 20:07:04 +0900 Subject: [PATCH 008/483] Add simple OpenGL viewer example. --- examples/viewer/Makefile | 8 + examples/viewer/README.md | 1 + examples/viewer/trackball.cc | 292 +++++++++++++++++++++++++ examples/viewer/trackball.h | 75 +++++++ examples/viewer/viewer.cc | 403 +++++++++++++++++++++++++++++++++++ 5 files changed, 779 insertions(+) create mode 100644 examples/viewer/Makefile create mode 100644 examples/viewer/README.md create mode 100644 examples/viewer/trackball.cc create mode 100644 examples/viewer/trackball.h create mode 100644 examples/viewer/viewer.cc diff --git a/examples/viewer/Makefile b/examples/viewer/Makefile new file mode 100644 index 00000000..e5204fca --- /dev/null +++ b/examples/viewer/Makefile @@ -0,0 +1,8 @@ +GLFW_INC=-I/usr/local/include +GLFW_LIBS=-L/usr/local/lib -lglfw3 -lglew +GL_LIBS=-framework OpenGL + +CXX_FLAGS=-Wno-deprecated-declarations + +all: + g++ -fsanitize=address -O0 -g -o objviewer $(CXX_FLAGS) viewer.cc ../../tiny_obj_loader.cc trackball.cc $(GLFW_INC) $(GL_LIBS) $(GLFW_LIBS) diff --git a/examples/viewer/README.md b/examples/viewer/README.md new file mode 100644 index 00000000..4e0e0872 --- /dev/null +++ b/examples/viewer/README.md @@ -0,0 +1 @@ +Simple .obj viewer with glew + glfw3 + OpenGL diff --git a/examples/viewer/trackball.cc b/examples/viewer/trackball.cc new file mode 100644 index 00000000..86ff3b3f --- /dev/null +++ b/examples/viewer/trackball.cc @@ -0,0 +1,292 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ +#include +#include "trackball.h" + +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (0.8) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static float tb_project_to_sphere(float, float, float); +static void normalize_quat(float[4]); + +static void vzero(float *v) { + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +static void vset(float *v, float x, float y, float z) { + v[0] = x; + v[1] = y; + v[2] = z; +} + +static void vsub(const float *src1, const float *src2, float *dst) { + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +static void vcopy(const float *v1, float *v2) { + register int i; + for (i = 0; i < 3; i++) + v2[i] = v1[i]; +} + +static void vcross(const float *v1, const float *v2, float *cross) { + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +static float vlength(const float *v) { + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +static void vscale(float *v, float div) { + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +static void vnormal(float *v) { vscale(v, 1.0 / vlength(v)); } + +static float vdot(const float *v1, const float *v2) { + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; +} + +static void vadd(const float *src1, const float *src2, float *dst) { + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) { + float a[3]; /* Axis of rotation */ + float phi; /* how much to rotate about axis */ + float p1[3], p2[3], d[3]; + float t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y)); + vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2, p1, a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1, p2, d); + t = vlength(d) / (2.0 * TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) + t = 1.0; + if (t < -1.0) + t = -1.0; + phi = 2.0 * asin(t); + + axis_to_quat(a, phi, q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void axis_to_quat(float a[3], float phi, float q[4]) { + vnormal(a); + vcopy(a, q); + vscale(q, sin(phi / 2.0)); + q[3] = cos(phi / 2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static float tb_project_to_sphere(float r, float x, float y) { + float d, t, z; + + d = sqrt(x * x + y * y); + if (d < r * 0.70710678118654752440) { /* Inside sphere */ + z = sqrt(r * r - d * d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880; + z = t * t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void add_quats(float q1[4], float q2[4], float dest[4]) { + static int count = 0; + float t1[4], t2[4], t3[4]; + float tf[4]; + + vcopy(q1, t1); + vscale(t1, q2[3]); + + vcopy(q2, t2); + vscale(t2, q1[3]); + + vcross(q2, q1, t3); + vadd(t1, t2, tf); + vadd(t3, tf, tf); + tf[3] = q1[3] * q2[3] - vdot(q1, q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void normalize_quat(float q[4]) { + int i; + float mag; + + mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); + for (i = 0; i < 4; i++) + q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void build_rotmatrix(float m[4][4], const float q[4]) { + m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0; + + m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); + m[1][1] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0; + + m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0; + + m[3][0] = 0.0; + m[3][1] = 0.0; + m[3][2] = 0.0; + m[3][3] = 1.0; +} diff --git a/examples/viewer/trackball.h b/examples/viewer/trackball.h new file mode 100644 index 00000000..b1f94374 --- /dev/null +++ b/examples/viewer/trackball.h @@ -0,0 +1,75 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void trackball(float q[4], float p1x, float p1y, float p2x, float p2y); + +void negate_quat(float *q, float *qn); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void add_quats(float *q1, float *q2, float *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void build_rotmatrix(float m[4][4], const float q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void axis_to_quat(float a[3], float phi, float q[4]); diff --git a/examples/viewer/viewer.cc b/examples/viewer/viewer.cc new file mode 100644 index 00000000..d89fadc4 --- /dev/null +++ b/examples/viewer/viewer.cc @@ -0,0 +1,403 @@ +// +// Simple .obj viewer(vertex only) +// +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +#include "../../tiny_obj_loader.h" + +#include "trackball.h" + +typedef struct { + GLuint vb; // vertex buffer + int numTriangles; +} DrawObject; + +std::vector gDrawObjects; + +int width = 512; +int height = 512; + +double prevMouseX, prevMouseY; +bool mouseLeftPressed; +bool mouseMiddlePressed; +bool mouseRightPressed; +float curr_quat[4]; +float prev_quat[4]; +float eye[3], lookat[3], up[3]; + +GLFWwindow* window; + +void CheckErrors(std::string desc) { + GLenum e = glGetError(); + if (e != GL_NO_ERROR) { + fprintf(stderr, "OpenGL error in \"%s\": %d (%d)\n", desc.c_str(), e, e); + exit(20); + } +} + +void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) { + float v10[3]; + v10[0] = v1[0] - v0[0]; + v10[1] = v1[1] - v0[1]; + v10[2] = v1[2] - v0[2]; + + float v20[3]; + v20[0] = v2[0] - v0[0]; + v20[1] = v2[1] - v0[1]; + v20[2] = v2[2] - v0[2]; + + N[0] = v20[1] * v10[2] - v20[2] * v10[1]; + N[1] = v20[2] * v10[0] - v20[0] * v10[2]; + N[2] = v20[0] * v10[1] - v20[1] * v10[0]; + + float len2 = N[0] * N[0] + N[1] * N[1] + N[2] * N[2]; + if (len2 > 0.0f) { + float len = sqrtf(len2); + + N[0] /= len; + N[1] /= len; + } +} + +bool LoadObjAndConvert(float bmin[3], float bmax[3], std::vector& drawObjects, const char* filename) +{ + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, NULL); + if (!err.empty()) { + std::cerr << err << std::endl; + } + + if (!ret) { + std::cerr << "Failed to load " << filename << std::endl; + return false; + } + + printf("# of materials = %d\n", (int)materials.size()); + printf("# of shapes = %d\n", (int)shapes.size()); + + bmin[0] = bmin[1] = bmin[2] = std::numeric_limits::max(); + bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits::max(); + + { + for (size_t s = 0; s < shapes.size(); s++) { + DrawObject o; + std::vector vb; // pos(3float), normal(3float) + for (size_t f = 0; f < shapes[s].mesh.indices.size()/3; f++) { + + tinyobj::index_t idx0 = shapes[s].mesh.indices[3*f+0]; + tinyobj::index_t idx1 = shapes[s].mesh.indices[3*f+1]; + tinyobj::index_t idx2 = shapes[s].mesh.indices[3*f+2]; + + float v[3][3]; + for (int k = 0; k < 3; k++) { + int f0 = idx0.vertex_index; + int f1 = idx1.vertex_index; + int f2 = idx2.vertex_index; + + v[0][k] = attrib.vertices[3*f0+k]; + v[1][k] = attrib.vertices[3*f1+k]; + v[2][k] = attrib.vertices[3*f2+k]; + bmin[k] = std::min(v[0][k], bmin[k]); + bmin[k] = std::min(v[1][k], bmin[k]); + bmin[k] = std::min(v[2][k], bmin[k]); + bmax[k] = std::max(v[0][k], bmax[k]); + bmax[k] = std::max(v[1][k], bmax[k]); + bmax[k] = std::max(v[2][k], bmax[k]); + } + + float n[3][3]; + + if (attrib.normals.size() > 0) { + int f0 = idx0.normal_index; + int f1 = idx1.normal_index; + int f2 = idx2.normal_index; + for (int k = 0; k < 3; k++) { + n[0][k] = attrib.normals[3*f0+k]; + n[1][k] = attrib.normals[3*f1+k]; + n[2][k] = attrib.normals[3*f2+k]; + } + } else { + // compute geometric normal + CalcNormal(n[0], v[0], v[1], v[2]); + n[1][0] = n[0][0]; n[1][1] = n[0][1]; n[1][2] = n[0][2]; + n[2][0] = n[0][0]; n[2][1] = n[0][1]; n[2][2] = n[0][2]; + } + + for (int k = 0; k < 3; k++) { + vb.push_back(v[k][0]); + vb.push_back(v[k][1]); + vb.push_back(v[k][2]); + vb.push_back(n[k][0]); + vb.push_back(n[k][1]); + vb.push_back(n[k][2]); + } + + } + + o.vb = 0; + o.numTriangles = 0; + if (vb.size() > 0) { + glGenBuffers(1, &o.vb); + glBindBuffer(GL_ARRAY_BUFFER, o.vb); + glBufferData(GL_ARRAY_BUFFER, vb.size() * sizeof(float), &vb.at(0), GL_STATIC_DRAW); + o.numTriangles = vb.size() / 6 / 3; + } + + gDrawObjects.push_back(o); + } + } + + printf("bmin = %f, %f, %f\n", bmin[0], bmin[1], bmin[2]); + printf("bmax = %f, %f, %f\n", bmax[0], bmax[1], bmax[2]); + + return true; +} + +void reshapeFunc(GLFWwindow* window, int w, int h) +{ + printf("reshape\n"); + glViewport(0, 0, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45.0, (float)w / (float)h, 0.1f, 1000.0f); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + width = w; + height = h; +} + +void keyboardFunc(GLFWwindow *window, int key, int scancode, int action, int mods) { + if(action == GLFW_PRESS || action == GLFW_REPEAT){ + // Move camera + float mv_x = 0, mv_y = 0, mv_z = 0; + if(key == GLFW_KEY_K) mv_x += 1; + else if(key == GLFW_KEY_J) mv_x += -1; + else if(key == GLFW_KEY_L) mv_y += 1; + else if(key == GLFW_KEY_H) mv_y += -1; + else if(key == GLFW_KEY_P) mv_z += 1; + else if(key == GLFW_KEY_N) mv_z += -1; + //camera.move(mv_x * 0.05, mv_y * 0.05, mv_z * 0.05); + // Close window + if(key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, GL_TRUE); + + //init_frame = true; + } +} + +void clickFunc(GLFWwindow* window, int button, int action, int mods){ + if(button == GLFW_MOUSE_BUTTON_LEFT){ + if(action == GLFW_PRESS){ + mouseLeftPressed = true; + trackball(prev_quat, 0.0, 0.0, 0.0, 0.0); + } else if(action == GLFW_RELEASE){ + mouseLeftPressed = false; + } + } + if(button == GLFW_MOUSE_BUTTON_RIGHT){ + if(action == GLFW_PRESS){ + mouseRightPressed = true; + } else if(action == GLFW_RELEASE){ + mouseRightPressed = false; + } + } + if(button == GLFW_MOUSE_BUTTON_MIDDLE){ + if(action == GLFW_PRESS){ + mouseMiddlePressed = true; + } else if(action == GLFW_RELEASE){ + mouseMiddlePressed = false; + } + } +} + +void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y){ + float rotScale = 1.0f; + float transScale = 2.0f; + + if(mouseLeftPressed){ + trackball(prev_quat, + rotScale * (2.0f * prevMouseX - width) / (float)width, + rotScale * (height - 2.0f * prevMouseY) / (float)height, + rotScale * (2.0f * mouse_x - width) / (float)width, + rotScale * (height - 2.0f * mouse_y) / (float)height); + + add_quats(prev_quat, curr_quat, curr_quat); + } else if (mouseMiddlePressed) { + eye[0] += transScale * (mouse_x - prevMouseX) / (float)width; + lookat[0] += transScale * (mouse_x - prevMouseX) / (float)width; + eye[1] += transScale * (mouse_y - prevMouseY) / (float)height; + lookat[1] += transScale * (mouse_y - prevMouseY) / (float)height; + } else if (mouseRightPressed) { + eye[2] += transScale * (mouse_y - prevMouseY) / (float)height; + lookat[2] += transScale * (mouse_y - prevMouseY) / (float)height; + } + + // Update mouse point + prevMouseX = mouse_x; + prevMouseY = mouse_y; +} + +void Draw(const std::vector& drawObjects) +{ + glPolygonMode(GL_FRONT, GL_FILL); + glPolygonMode(GL_BACK, GL_FILL); + + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); + glColor3f(1.0f, 1.0f, 1.0f); + for (size_t i = 0; i < drawObjects.size(); i++) { + DrawObject o = drawObjects[i]; + if (o.vb < 1) { + continue; + } + + glBindBuffer(GL_ARRAY_BUFFER, o.vb); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glVertexPointer(3, GL_FLOAT, 24, (const void*)0); + glNormalPointer(GL_FLOAT, 24, (const void*)(sizeof(float)*3)); + + glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles); + CheckErrors("drawarrays"); + } + + // draw wireframe + glDisable(GL_POLYGON_OFFSET_FILL); + glPolygonMode(GL_FRONT, GL_LINE); + glPolygonMode(GL_BACK, GL_LINE); + + glColor3f(0.0f, 0.0f, 0.4f); + for (size_t i = 0; i < drawObjects.size(); i++) { + DrawObject o = drawObjects[i]; + if (o.vb < 1) { + continue; + } + + glBindBuffer(GL_ARRAY_BUFFER, o.vb); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glVertexPointer(3, GL_FLOAT, 24, (const void*)0); + glNormalPointer(GL_FLOAT, 24, (const void*)(sizeof(float)*3)); + + glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles); + CheckErrors("drawarrays"); + } +} + +static void Init() { + trackball(curr_quat, 0, 0, 0, 0); + + eye[0] = 0.0f; + eye[1] = 0.0f; + eye[2] = 3.0f; + + lookat[0] = 0.0f; + lookat[1] = 0.0f; + lookat[2] = 0.0f; + + up[0] = 0.0f; + up[1] = 1.0f; + up[2] = 0.0f; +} + + +int main(int argc, char **argv) +{ + if (argc < 2) { + std::cout << "Needs input.obj\n" << std::endl; + return 0; + } + + Init(); + + + if(!glfwInit()){ + std::cerr << "Failed to initialize GLFW." << std::endl; + return -1; + } + + + + window = glfwCreateWindow(width, height, "Obj viewer", NULL, NULL); + if(window == NULL){ + std::cerr << "Failed to open GLFW window. " << std::endl; + glfwTerminate(); + return 1; + } + + glfwMakeContextCurrent(window); + + // Callback + glfwSetWindowSizeCallback(window, reshapeFunc); + glfwSetKeyCallback(window, keyboardFunc); + glfwSetMouseButtonCallback(window, clickFunc); + glfwSetCursorPosCallback(window, motionFunc); + + glewExperimental = true; + if (glewInit() != GLEW_OK) { + std::cerr << "Failed to initialize GLEW." << std::endl; + return -1; + } + + reshapeFunc(window, width, height); + + float bmin[3], bmax[3]; + if (false == LoadObjAndConvert(bmin, bmax, gDrawObjects, argv[1])) { + return -1; + } + + float maxExtent = 0.5f * (bmax[0] - bmin[0]); + if (maxExtent < 0.5f * (bmax[1] - bmin[1])) { + maxExtent = 0.5f * (bmax[1] - bmin[1]); + } + if (maxExtent < 0.5f * (bmax[2] - bmin[2])) { + maxExtent = 0.5f * (bmax[2] - bmin[2]); + } + + while(glfwWindowShouldClose(window) == GL_FALSE) { + glfwPollEvents(); + glClearColor(0.1f, 0.2f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + + // camera & rotate + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + GLfloat mat[4][4]; + gluLookAt(eye[0], eye[1], eye[2], lookat[0], lookat[1], lookat[2], up[0], up[1], up[2]); + build_rotmatrix(mat, curr_quat); + glMultMatrixf(&mat[0][0]); + + // Fit to -1, 1 + glScalef(1.0f / maxExtent, 1.0f / maxExtent, 1.0f / maxExtent); + + // Centerize object. + glTranslatef(-0.5*(bmax[0] + bmin[0]), -0.5*(bmax[1] + bmin[1]), -0.5*(bmax[2] + bmin[2])); + + Draw(gDrawObjects); + + glfwSwapBuffers(window); + } + + glfwTerminate(); +} From 00ed158a8eed7c50549c3f294759f5e55664ce58 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 12:32:12 +0900 Subject: [PATCH 009/483] Update CMake. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4db707c7..f4f497ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,8 @@ set(tinyobjloader-Source ${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc ) -set(tinyobjloader-Test-Source - ${CMAKE_CURRENT_SOURCE_DIR}/test.cc +set(tinyobjloader-Example-Source + ${CMAKE_CURRENT_SOURCE_DIR}/loader_example.cc ) set(tinyobjloader-examples-objsticher @@ -26,10 +26,10 @@ add_library(tinyobjloader ${tinyobjloader-Source} ) -option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Test Loader Application" OFF) +option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Example Loader Application" OFF) if(TINYOBJLOADER_BUILD_TEST_LOADER) - add_executable(test_loader ${tinyobjloader-Test-Source}) + add_executable(test_loader ${tinyobjloader-Example-Source}) target_link_libraries(test_loader tinyobjloader) endif() From f4695de408516f45652b161a34bb62fbe6edec07 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 12:50:41 +0900 Subject: [PATCH 010/483] Suppress compiler warning. --- tiny_obj_loader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index d2aae380..af395ff3 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -493,7 +493,7 @@ static vertex_index parseTriple(const char **token, int vsize, int vnsize, // Parse raw triples: i, i/j/k, i//k, i/j static vertex_index parseRawTriple(const char **token) { - vertex_index vi(0x80000000); // 0x80000000 = -2147483648 = invalid + vertex_index vi(-2147483648); // 0x80000000 = -2147483648 = invalid vi.v_idx = atoi((*token)); (*token) += strcspn((*token), "/ \t\r"); From a55247574c2c2436989a9a0654c51a62cc7193ba Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 13:11:55 +0900 Subject: [PATCH 011/483] Suppress VC2013 warnings. Update AppVeyor script. --- appveyor.yml | 11 +++-------- build.ninja | 18 ------------------ tests/config-msvc.py | 2 +- tests/tester.cc | 23 +++++++++++++++++++++++ tests/vcbuild.bat | 1 + tiny_obj_loader.h | 26 ++++++++++++-------------- 6 files changed, 40 insertions(+), 41 deletions(-) delete mode 100644 build.ninja diff --git a/appveyor.yml b/appveyor.yml index 38eaf158..b52a6666 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,12 +1,7 @@ version: 0.9.{build} -# scripts that runs after repo cloning. -install: - - vcsetup.bat - platform: x64 -configuration: Release -build: - parallel: true - project: TinyObjLoaderSolution.sln +build_script: + - cd tests + - vcbuild.bat diff --git a/build.ninja b/build.ninja deleted file mode 100644 index 5048ff1d..00000000 --- a/build.ninja +++ /dev/null @@ -1,18 +0,0 @@ -# build.ninja -cc = clang -cxx = clang++ -cflags = -Werror -Weverything -cxxflags = -Werror -Weverything -#cflags = -O2 -#cxxflags = -O2 - -rule compile - command = $cxx $cxxflags -c $in -o $out - -rule link - command = $cxx $in -o $out - -build loader_example.o: compile loader_example.cc -build loader_example: link loader_example.o - -default loader_example diff --git a/tests/config-msvc.py b/tests/config-msvc.py index 06fae62f..a7771def 100644 --- a/tests/config-msvc.py +++ b/tests/config-msvc.py @@ -32,7 +32,7 @@ cxxflags = { "gnu" : [ "-O2", "-g" ] - , "msvc" : [ "/O2" ] + , "msvc" : [ "/O2", "/W4", "/EHsc"] , "clang" : [ "-O2", "-g", "-fsanitize=address" ] } diff --git a/tests/tester.cc b/tests/tester.cc index edb92ba6..f16eeb09 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -300,6 +300,29 @@ TEST_CASE("cornell_box", "[Loader]") { REQUIRE(true == TestLoadObj("../models/cornell_box.obj", gMtlBasePath)); } +TEST_CASE("catmark_torus_creases0", "[Loader]") { + + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/catmark_torus_creases0.obj", gMtlBasePath, /*triangulate*/false); + + if (!err.empty()) { + std::cerr << err << std::endl; + } + + REQUIRE(true == ret); + + REQUIRE(1 == shapes.size()); + REQUIRE(8 == shapes[0].mesh.tags.size()); +} + +TEST_CASE("stream_load", "[Stream]") { + REQUIRE(true == TestStreamLoadObj()); +} + #if 0 int main( diff --git a/tests/vcbuild.bat b/tests/vcbuild.bat index 3dbc6c16..e8646735 100644 --- a/tests/vcbuild.bat +++ b/tests/vcbuild.bat @@ -1,3 +1,4 @@ chcp 437 +python kuroga.py config-msvc.py call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64 ninja diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index af395ff3..5db2bb82 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -236,15 +236,6 @@ struct tag_sizes { int num_strings; }; -// for std::map -static inline bool operator<(const vertex_index &a, const vertex_index &b) { - if (a.v_idx != b.v_idx) return (a.v_idx < b.v_idx); - if (a.vn_idx != b.vn_idx) return (a.vn_idx < b.vn_idx); - if (a.vt_idx != b.vt_idx) return (a.vt_idx < b.vt_idx); - - return false; -} - struct obj_shape { std::vector v; std::vector vn; @@ -346,11 +337,13 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { } // Read the integer part. - while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) { + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { mantissa *= 10; mantissa += static_cast(*curr - 0x30); curr++; read++; + end_not_reached = (curr != s_end); } // We must make sure we actually got something. @@ -362,11 +355,13 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { if (*curr == '.') { curr++; read = 1; - while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) { + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { // NOTE: Don't use powf here, it will absolutely murder precision. mantissa += static_cast(*curr - 0x30) * pow(10.0, -read); read++; curr++; + end_not_reached = (curr != s_end); } } else if (*curr == 'e' || *curr == 'E') { } else { @@ -379,7 +374,8 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { if (*curr == 'e' || *curr == 'E') { curr++; // Figure out if a sign is present and if it is. - if ((end_not_reached = (curr != s_end)) && (*curr == '+' || *curr == '-')) { + end_not_reached = (curr != s_end); + if (end_not_reached && (*curr == '+' || *curr == '-')) { exp_sign = *curr; curr++; } else if (IS_DIGIT(*curr)) { /* Pass through. */ @@ -389,11 +385,13 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) { } read = 0; - while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) { + end_not_reached = (curr != s_end); + while (end_not_reached && IS_DIGIT(*curr)) { exponent *= 10; exponent += static_cast(*curr - 0x30); curr++; read++; + end_not_reached = (curr != s_end); } exponent *= (exp_sign == '+' ? 1 : -1); if (read == 0) goto fail; @@ -493,7 +491,7 @@ static vertex_index parseTriple(const char **token, int vsize, int vnsize, // Parse raw triples: i, i/j/k, i//k, i/j static vertex_index parseRawTriple(const char **token) { - vertex_index vi(-2147483648); // 0x80000000 = -2147483648 = invalid + vertex_index vi(static_cast(0x80000000)); // 0x80000000 = -2147483648 = invalid vi.v_idx = atoi((*token)); (*token) += strcspn((*token), "/ \t\r"); From 6b41e68bbc589cd2439845b5041e71ee5f60dd61 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 13:25:57 +0900 Subject: [PATCH 012/483] Install ninja in appveyor build. --- appveyor.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index b52a6666..22e3d7cf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,22 @@ version: 0.9.{build} platform: x64 +install: + ####################################################################################### + # All external dependencies are installed in C:\projects\deps + ####################################################################################### + - mkdir C:\projects\deps + - cd C:\projects\deps + + ####################################################################################### + # Install Ninja + ####################################################################################### + - set NINJA_URL="https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip" + - appveyor DownloadFile %NINJA_URL% -FileName ninja.zip + - 7z x ninja.zip -oC:\projects\deps\ninja > nul + - set PATH=C:\projects\deps\ninja;%PATH% + - ninja --version + build_script: - cd tests - vcbuild.bat From 9eecb4634d98cfe0fa09b1caac01f602f13ec9cb Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 13:27:44 +0900 Subject: [PATCH 013/483] Update Travis script. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3ec9e45a..0b1926d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ matrix: --coverage" REPORT_COVERAGE=1 before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi +- if [ -n "$REPORT_COVERAGE" ]; then pip install --user requests[security]; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user cpp-coveralls; fi script: - cd tests From 28d1bb55218467b935436bf4e651deed33801d5b Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 13:32:03 +0900 Subject: [PATCH 014/483] Update Travis. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0b1926d7..c9403fdb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ matrix: --coverage" REPORT_COVERAGE=1 before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi +- if [ -n "$REPORT_COVERAGE" ]; then pip install --upgrade pip; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user requests[security]; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user cpp-coveralls; fi script: From 016362234b0c28d010f9dfb70699bfb94eeb9e7d Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 13:36:46 +0900 Subject: [PATCH 015/483] Update Travis script. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c9403fdb..da93e43a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ matrix: --coverage" REPORT_COVERAGE=1 before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi -- if [ -n "$REPORT_COVERAGE" ]; then pip install --upgrade pip; fi +- if [ -n "$REPORT_COVERAGE" ]; then sudo pip install --upgrade pip; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user requests[security]; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user cpp-coveralls; fi script: From 170cb86870fe71224bc4c17c81a2e97f045150ac Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 13:56:27 +0900 Subject: [PATCH 016/483] Change to sudo required. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index da93e43a..78bbd0bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: cpp -sudo: false +sudo: required matrix: include: - addons: &1 From a66eab0f75dcc4c8f81c6adfc4c942114fafb221 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 14:03:43 +0900 Subject: [PATCH 017/483] More Travis fix. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 78bbd0bf..74ab5319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ matrix: --coverage" REPORT_COVERAGE=1 before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi +- if [ -n "$REPORT_COVERAGE" ]; then sudo apt-get install python-dev libffi-dev libssl-dev; fi - if [ -n "$REPORT_COVERAGE" ]; then sudo pip install --upgrade pip; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user requests[security]; fi - if [ -n "$REPORT_COVERAGE" ]; then pip install --user cpp-coveralls; fi From 2e6cccbfe415814f6c788dc7db3998d3c3a129e9 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 14:32:10 +0900 Subject: [PATCH 018/483] Force use g++ for pip install. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 74ab5319..a2a4428d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,8 +42,8 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi - if [ -n "$REPORT_COVERAGE" ]; then sudo apt-get install python-dev libffi-dev libssl-dev; fi - if [ -n "$REPORT_COVERAGE" ]; then sudo pip install --upgrade pip; fi -- if [ -n "$REPORT_COVERAGE" ]; then pip install --user requests[security]; fi -- if [ -n "$REPORT_COVERAGE" ]; then pip install --user cpp-coveralls; fi +- if [ -n "$REPORT_COVERAGE" ]; then CXX=g++ pip install --user requests[security]; fi +- if [ -n "$REPORT_COVERAGE" ]; then CXX=g++ pip install --user cpp-coveralls; fi script: - cd tests - make check From a608c3b5b1f867044ea99d1f7bc4847ea44ab01d Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 14:37:57 +0900 Subject: [PATCH 019/483] Update python. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a2a4428d..cc79cf5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ matrix: --coverage" REPORT_COVERAGE=1 before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi +- if [ -n "$REPORT_COVERAGE" ]; then sudo apt-get update python; fi - if [ -n "$REPORT_COVERAGE" ]; then sudo apt-get install python-dev libffi-dev libssl-dev; fi - if [ -n "$REPORT_COVERAGE" ]; then sudo pip install --upgrade pip; fi - if [ -n "$REPORT_COVERAGE" ]; then CXX=g++ pip install --user requests[security]; fi From 28fc3523d46470a9c5806635277730ba3b243879 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 14:46:23 +0900 Subject: [PATCH 020/483] Disable coveralls due to Travis + python bug? --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc79cf5d..06b2d758 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,7 @@ matrix: env: COMPILER_VERSION=4.9 BUILD_TYPE=Release - addons: *1 compiler: clang - env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug CFLAGS="-O0 --coverage" CXXFLAGS="-O0 - --coverage" REPORT_COVERAGE=1 + env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi - if [ -n "$REPORT_COVERAGE" ]; then sudo apt-get update python; fi From 7399aedfdd2097d8906dfc1760f8110ca257bd2e Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Tue, 19 Apr 2016 20:34:51 +0900 Subject: [PATCH 021/483] Initial support of linux for viewer example. --- examples/viewer/Makefile | 10 ++++++++-- examples/viewer/viewer.cc | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/viewer/Makefile b/examples/viewer/Makefile index e5204fca..9c1f621b 100644 --- a/examples/viewer/Makefile +++ b/examples/viewer/Makefile @@ -1,6 +1,12 @@ GLFW_INC=-I/usr/local/include -GLFW_LIBS=-L/usr/local/lib -lglfw3 -lglew -GL_LIBS=-framework OpenGL + +# OSX +#GLFW_LIBS=-L/usr/local/lib -lglfw3 -lGLEW +#GL_LIBS=-framework OpenGL + +# Linux +GLFW_LIBS=-L/usr/local/lib -lglfw3 -lGLEW +GL_LIBS=-lGL -lGLU -lX11 -lXrandr -lXi -lXxf86vm -lXcursor -lXinerama -ldl -pthread CXX_FLAGS=-Wno-deprecated-declarations diff --git a/examples/viewer/viewer.cc b/examples/viewer/viewer.cc index d89fadc4..20221688 100644 --- a/examples/viewer/viewer.cc +++ b/examples/viewer/viewer.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -345,6 +346,7 @@ int main(int argc, char **argv) } glfwMakeContextCurrent(window); + glfwSwapInterval(1); // Callback glfwSetWindowSizeCallback(window, reshapeFunc); From 58fa260605fe380387ac08e59bdbff87add72857 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Wed, 20 Apr 2016 16:00:45 +0900 Subject: [PATCH 022/483] Show normal vector in viewer example. --- README.md | 8 +++-- examples/viewer/Makefile | 12 +++++--- examples/viewer/viewer.cc | 42 +++++++++++++++++++------- loader_example.cc | 3 ++ tiny_obj_loader.h | 62 ++++++++++++++++++++++++++------------- 5 files changed, 88 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 35dfd1e2..838890f5 100644 --- a/README.md +++ b/README.md @@ -79,12 +79,13 @@ Features TODO ---- -* [ ] Read .obj/.mtl from memory +* [ ] Read .obj/.mtl from memory. +* [ ] Fix Python binding. License ------- -Licensed under 2 clause BSD. +Licensed under MIT license. Usage ----- @@ -94,11 +95,12 @@ Usage #include "tiny_obj_loader.h" std::string inputfile = "cornell_box.obj"; +tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string err; -bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str()); +bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, inputfile.c_str()); if (!err.empty()) { // `err` may contain warning message. std::cerr << err << std::endl; diff --git a/examples/viewer/Makefile b/examples/viewer/Makefile index 9c1f621b..f06e3d0b 100644 --- a/examples/viewer/Makefile +++ b/examples/viewer/Makefile @@ -1,12 +1,16 @@ GLFW_INC=-I/usr/local/include -# OSX -#GLFW_LIBS=-L/usr/local/lib -lglfw3 -lGLEW -#GL_LIBS=-framework OpenGL +UNAME=$(shell uname -s) -# Linux +ifeq ($(UNAME),Darwin) +# OSX +GLFW_LIBS=-L/usr/local/lib -lglfw3 -lGLEW +GL_LIBS=-framework OpenGL +else +# Assume Linux GLFW_LIBS=-L/usr/local/lib -lglfw3 -lGLEW GL_LIBS=-lGL -lGLU -lX11 -lXrandr -lXi -lXxf86vm -lXcursor -lXinerama -ldl -pthread +endif CXX_FLAGS=-Wno-deprecated-declarations diff --git a/examples/viewer/viewer.cc b/examples/viewer/viewer.cc index 20221688..a86c853b 100644 --- a/examples/viewer/viewer.cc +++ b/examples/viewer/viewer.cc @@ -30,8 +30,8 @@ typedef struct { std::vector gDrawObjects; -int width = 512; -int height = 512; +int width = 768; +int height = 768; double prevMouseX, prevMouseY; bool mouseLeftPressed; @@ -92,8 +92,11 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3], std::vector& dr return false; } + printf("# of vertices = %d\n", (int)(attrib.vertices.size()) / 3); + printf("# of normals = %d\n", (int)(attrib.normals.size()) / 3); + printf("# of texcoords = %d\n", (int)(attrib.texcoords.size()) / 2); printf("# of materials = %d\n", (int)materials.size()); - printf("# of shapes = %d\n", (int)shapes.size()); + printf("# of shapes = %d\n", (int)shapes.size()); bmin[0] = bmin[1] = bmin[2] = std::numeric_limits::max(); bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits::max(); @@ -101,7 +104,7 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3], std::vector& dr { for (size_t s = 0; s < shapes.size(); s++) { DrawObject o; - std::vector vb; // pos(3float), normal(3float) + std::vector vb; // pos(3float), normal(3float), color(3float) for (size_t f = 0; f < shapes[s].mesh.indices.size()/3; f++) { tinyobj::index_t idx0 = shapes[s].mesh.indices[3*f+0]; @@ -150,6 +153,19 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3], std::vector& dr vb.push_back(n[k][0]); vb.push_back(n[k][1]); vb.push_back(n[k][2]); + // Use normal as color. + float c[3] = {n[k][0], n[k][1], n[k][2]}; + float len2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2]; + if (len2 > 0.0f) { + float len = sqrtf(len2); + + c[0] /= len; + c[1] /= len; + c[2] /= len; + } + vb.push_back(c[0] * 0.5 + 0.5); + vb.push_back(c[1] * 0.5 + 0.5); + vb.push_back(c[2] * 0.5 + 0.5); } } @@ -160,7 +176,8 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3], std::vector& dr glGenBuffers(1, &o.vb); glBindBuffer(GL_ARRAY_BUFFER, o.vb); glBufferData(GL_ARRAY_BUFFER, vb.size() * sizeof(float), &vb.at(0), GL_STATIC_DRAW); - o.numTriangles = vb.size() / 6 / 3; + o.numTriangles = vb.size() / 9 / 3; + printf("shape[%d] # of triangles = %d\n", static_cast(s), o.numTriangles); } gDrawObjects.push_back(o); @@ -243,8 +260,8 @@ void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y){ add_quats(prev_quat, curr_quat, curr_quat); } else if (mouseMiddlePressed) { - eye[0] += transScale * (mouse_x - prevMouseX) / (float)width; - lookat[0] += transScale * (mouse_x - prevMouseX) / (float)width; + eye[0] -= transScale * (mouse_x - prevMouseX) / (float)width; + lookat[0] -= transScale * (mouse_x - prevMouseX) / (float)width; eye[1] += transScale * (mouse_y - prevMouseY) / (float)height; lookat[1] += transScale * (mouse_y - prevMouseY) / (float)height; } else if (mouseRightPressed) { @@ -274,8 +291,10 @@ void Draw(const std::vector& drawObjects) glBindBuffer(GL_ARRAY_BUFFER, o.vb); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 24, (const void*)0); - glNormalPointer(GL_FLOAT, 24, (const void*)(sizeof(float)*3)); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(3, GL_FLOAT, 36, (const void*)0); + glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float)*3)); + glColorPointer(3, GL_FLOAT, 36, (const void*)(sizeof(float)*6)); glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles); CheckErrors("drawarrays"); @@ -296,8 +315,9 @@ void Draw(const std::vector& drawObjects) glBindBuffer(GL_ARRAY_BUFFER, o.vb); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 24, (const void*)0); - glNormalPointer(GL_FLOAT, 24, (const void*)(sizeof(float)*3)); + glDisableClientState(GL_COLOR_ARRAY); + glVertexPointer(3, GL_FLOAT, 36, (const void*)0); + glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float)*3)); glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles); CheckErrors("drawarrays"); diff --git a/loader_example.cc b/loader_example.cc index d91baaa6..435684ee 100644 --- a/loader_example.cc +++ b/loader_example.cc @@ -1,3 +1,6 @@ +// +// g++ loader_example.cc +// #define TINYOBJLOADER_IMPLEMENTATION #include "tiny_obj_loader.h" diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 5db2bb82..8500fc91 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -1,11 +1,30 @@ -// -// Copyright 2012-2016, Syoyo Fujita. -// -// Licensed under 2-clause BSD license. -// +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 Syoyo Fujita and many contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ // -// version devel : Change data structure. Support different index for +// version 1.0.0 : Change data structure. Change license from BSD to MIT. +// Support different index for // vertex/normal/texcoord(#73, #39) // version 0.9.20: Fixes creating per-face material using `usemtl`(#68) // version 0.9.17: Support n-polygon and crease tag(OpenSubdiv extension) @@ -117,8 +136,9 @@ typedef struct callback_t_ { void (*texcoord_cb)(void *user_data, float x, float y); // -2147483648 will be passed for undefined index void (*index_cb)(void *user_data, int v_idx, int vn_idx, int vt_idx); - // `name` material name, `materialId` = the array index of material_t[]. -1 if a material not found in .mtl - void (*usemtl_cb)(void *user_data, const char* name, int materialId); + // `name` material name, `materialId` = the array index of material_t[]. -1 if + // a material not found in .mtl + void (*usemtl_cb)(void *user_data, const char *name, int materialId); // `materials` = parsed material data. void (*mtllib_cb)(void *user_data, const material_t *materials, int num_materials); @@ -126,17 +146,16 @@ typedef struct callback_t_ { void (*group_cb)(void *user_data, const char **names, int num_names); void (*object_cb)(void *user_data, const char *name); - callback_t_() : - vertex_cb(NULL), - normal_cb(NULL), - texcoord_cb(NULL), - index_cb(NULL), - usemtl_cb(NULL), - mtllib_cb(NULL), - group_cb(NULL), - object_cb(NULL) { - } - + callback_t_() + : vertex_cb(NULL), + normal_cb(NULL), + texcoord_cb(NULL), + index_cb(NULL), + usemtl_cb(NULL), + mtllib_cb(NULL), + group_cb(NULL), + object_cb(NULL) {} + } callback_t; class MaterialReader { @@ -491,7 +510,8 @@ static vertex_index parseTriple(const char **token, int vsize, int vnsize, // Parse raw triples: i, i/j/k, i//k, i/j static vertex_index parseRawTriple(const char **token) { - vertex_index vi(static_cast(0x80000000)); // 0x80000000 = -2147483648 = invalid + vertex_index vi( + static_cast(0x80000000)); // 0x80000000 = -2147483648 = invalid vi.v_idx = atoi((*token)); (*token) += strcspn((*token), "/ \t\r"); @@ -1179,7 +1199,7 @@ bool LoadObjWithCallback(void *user_data, const callback_t &callback, // material std::map material_map; - int materialId = -1; // -1 = invalid + int materialId = -1; // -1 = invalid int maxchars = 8192; // Alloc enough size. std::vector buf(static_cast(maxchars)); // Alloc enough size. From 9d6b58b90e879a87e4455f79ef9ae585f9bfed10 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Sun, 24 Apr 2016 00:34:05 +0900 Subject: [PATCH 023/483] Add new build.ninja. --- README.md | 1 + build.ninja | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 build.ninja diff --git a/README.md b/README.md index 838890f5..f24bc8d5 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ TODO * [ ] Read .obj/.mtl from memory. * [ ] Fix Python binding. +* [ ] Unit test codes. License ------- diff --git a/build.ninja b/build.ninja new file mode 100644 index 00000000..77801bb5 --- /dev/null +++ b/build.ninja @@ -0,0 +1,53 @@ +ninja_required_version = 1.4 + +gnubuilddir = build +gnudefines = +gnuincludes = -I. +gnucflags = -O2 -g +gnucxxflags = -O2 -g -pedantic -Wall -Wextra -Wcast-align -Wcast-qual $ + -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self $ + -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast $ + -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion $ + -Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror $ + -Wno-unused -fsanitize=address +gnuldflags = -fsanitize=address + +pool link_pool + depth = 1 + +rule gnucxx + command = $gnucxx -MMD -MF $out.d $gnudefines $gnuincludes $gnucxxflags $ + -c $in -o $out + description = CXX $out + depfile = $out.d + deps = gcc +rule gnucc + command = $gnucc -MMD -MF $out.d $gnudefines $gnuincludes $gnucflags -c $ + $in -o $out + description = CC $out + depfile = $out.d + deps = gcc +rule gnulink + command = $gnuld -o $out $in $libs $gnuldflags + description = LINK $out + pool = link_pool +rule gnuar + command = $gnuar rsc $out $in + description = AR $out + pool = link_pool +rule gnustamp + command = touch $out + description = STAMP $out + +gnucxx = g++ +gnucc = gcc +gnuld = $gnucxx +gnuar = ar + +build loader_example.o: gnucxx loader_example.cc + + +build loader_example: gnulink loader_example.o +build all: phony loader_example + +default all From 7dc1418e2b1826a7859393d4c0f08d2ece7808d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Apr 2016 19:42:42 +0200 Subject: [PATCH 024/483] viewer: Cleaned up Makefile and added a semblance of a Mingw64-target for Windows. --- examples/viewer/Makefile | 64 +++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/examples/viewer/Makefile b/examples/viewer/Makefile index f06e3d0b..d42278c3 100644 --- a/examples/viewer/Makefile +++ b/examples/viewer/Makefile @@ -1,18 +1,66 @@ -GLFW_INC=-I/usr/local/include +CXX_FLAGS=-O0 -g -Wno-deprecated-declarations +ifndef PLATFORM UNAME=$(shell uname -s) +# OSX TEST ifeq ($(UNAME),Darwin) -# OSX -GLFW_LIBS=-L/usr/local/lib -lglfw3 -lGLEW +PLATFORM=OSX +else +# WINDOWS MINGW TEST +ifeq ($(findstring MINGW, $(UNAME)), MINGW) + PLATFORM=WINDOWS_MINGW +else +# ASSUME LINUX + PLATFORM=LINUX +endif +endif + +endif +$(info PLATFORM SELECTED: $(PLATFORM)) + +ifeq ($(PLATFORM),OSX) +# OSX CONFIGURATION------------------------------------------------------------- +CXX_FLAGS+= -fsanitize=address +GLFW_INC=-I/usr/local/include +GLFW_LIB_DIR=/usr/local/lib +GLFW_LIBS=-L$(GLFW_LIB_DIR) -lglfw3 -lGLEW GL_LIBS=-framework OpenGL +# /OSX CONFIGURATION------------------------------------------------------------ else -# Assume Linux -GLFW_LIBS=-L/usr/local/lib -lglfw3 -lGLEW +ifeq ($(PLATFORM),LINUX) +# LINUX CONFIGURATION----------------------------------------------------------- +CXX_FLAGS+= -fsanitize=address +GLFW_INC=-I/usr/local/include +GLFW_LIB_DIR=/usr/local/lib +GLFW_LIBS=-L$(GLFW_LIB_DIR) -lglfw3 -lGLEW GL_LIBS=-lGL -lGLU -lX11 -lXrandr -lXi -lXxf86vm -lXcursor -lXinerama -ldl -pthread +# /LINUX CONFIGURATION---------------------------------------------------------- +else +ifeq ($(PLATFORM),WINDOWS_MINGW) +# WINDOWS MINGW CONFIGURATION--------------------------------------------------- +# Since Windows unfortunately doesn't have any defacto directories for third +# party libraries, we'll have to force the user to give us them. So we check +# that the user passed in GLFW-dirs in some way, via flag or environ. +ifndef GLFW_DIR +$(error NO GLFW_DIR SPECIFIED. PASS GLFW_DIR= TO MAKE) +endif +ifndef GLEW_DIR +$(error NO GLEW_DIR SPECIFIED. PASS GLEW_DIR= TO MAKE) endif - -CXX_FLAGS=-Wno-deprecated-declarations +GLFW_INC=-I$(GLFW_DIR)/include +GLFW_LIB_DIR=$(GLFW_DIR)/lib-mingw-w64 +GLFW_LIBS= -lglfw3 -L$(GLFW_LIB_DIR) +GL_LIBS= -lglew32 -lopengl32 -lglu32 -lgdi32 -I$(GLEW_DIR)/include -L$(GLEW_DIR)/bin/Release/x64 +# /WINDOWS CONFIGURATION-------------------------------------------------------- +else +$(error UNKNOWN PLATFORM "$(PLATFORM)") +endif #ifeq ($(PLATFORM),WINDOWS_MINGW) +endif #ifeq ($(PLATFORM),LINUX) +endif #ifeq ($(PLATFORM),OSX) all: - g++ -fsanitize=address -O0 -g -o objviewer $(CXX_FLAGS) viewer.cc ../../tiny_obj_loader.cc trackball.cc $(GLFW_INC) $(GL_LIBS) $(GLFW_LIBS) + g++ -o objviewer $(CXX_FLAGS) viewer.cc ../../tiny_obj_loader.cc trackball.cc $(GLFW_INC) $(GLFW_LIBS) $(GL_LIBS) +ifeq ($(PLATFORM), WINDOWS_MINGW) + cp $(GLEW_DIR)/bin/Release/x64/glew32.dll . +endif From 8d60b4963ae7a7cccd41d2bd22f2b2e17f1e0e9d Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Sun, 1 May 2016 21:30:50 +0900 Subject: [PATCH 025/483] Rename varialble for better understanding. Write some API usage in README.md. --- README.md | 36 +++++++++++++++++++++++++++++++++--- loader_example.cc | 10 +++++----- tests/tester.cc | 8 ++++---- tiny_obj_loader.h | 6 +++--- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f24bc8d5..74bc8f81 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,9 @@ Features TODO ---- -* [ ] Read .obj/.mtl from memory. * [ ] Fix Python binding. -* [ ] Unit test codes. +* [ ] Fix obj_sticker example. +* [ ] More unit test codes. License ------- @@ -91,6 +91,10 @@ Licensed under MIT license. Usage ----- +`attrib_t` contains single and linear array of vertex data(position, normal and texcoord). +Each `shape_t` does not contain vertex data but contains array index to `attrib_t`. +See `loader_example.cc` for more details. + ```c++ #define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc #include "tiny_obj_loader.h" @@ -111,7 +115,33 @@ if (!ret) { exit(1); } -// See loader_example.cc for more details. +// Loop over shapes +for (size_t s = 0; s < shapes.size(); s++) { + // Loop over faces(polygon) + size_t index_offset = 0; + for (size_t f = 0; f < shapes[i].mesh.num_face_vertices; f++) { + int fv = shapes[i].mesh.num_face_vertices[f]; + + // Loop over vertices in the face. + for (size_t v = 0; v < fv; f++) { + // access to vertex + tinyobj::index_t idx = shapes[i].mesh.indices[index_offset + v]; + float vx = attrib.positions[3*idx.vertex_index+0]; + float vy = attrib.positions[3*idx.vertex_index+1]; + float vz = attrib.positions[3*idx.vertex_index+2]; + float nx = attrib.normals[3*idx.normal_index+0]; + float ny = attrib.normals[3*idx.normal_index+1]; + float nz = attrib.normals[3*idx.normal_index+2]; + float tx = attrib.texcoords[2*idx.texcoord_index+0]; + float ty = attrib.texcoords[2*idx.texcoord_index+1]; + } + index_offset += fv; + + // per-face material + shapes[i].mesh.material_ids[f]; + } +} + ``` diff --git a/loader_example.cc b/loader_example.cc index 435684ee..e592e955 100644 --- a/loader_example.cc +++ b/loader_example.cc @@ -65,7 +65,7 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector(shapes[i].mesh.num_vertices[v])); + printf("shape[%ld].num_faces: %ld\n", i, shapes[i].mesh.num_face_vertices.size()); + for (size_t v = 0; v < shapes[i].mesh.num_face_vertices.size(); v++) { + printf(" num_face_vertices[%ld] = %ld\n", v, + static_cast(shapes[i].mesh.num_face_vertices[v])); } //printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size()); diff --git a/tests/tester.cc b/tests/tester.cc index f16eeb09..e8e3b42b 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -65,7 +65,7 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector(shapes[i].mesh.num_vertices[v])); + static_cast(shapes[i].mesh.num_face_vertices[v])); } //printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size()); diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 8500fc91..01ff721d 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -113,7 +113,7 @@ typedef struct { typedef struct { std::vector indices; std::vector - num_vertices; // The number of vertices per face. Up to 255. + num_face_vertices; // The number of vertices per face. 3 = polygon, 4 = quad, ... Up to 255. std::vector material_ids; // per-face material ID std::vector tags; // SubD tag } mesh_t; @@ -604,7 +604,7 @@ static bool exportFaceGroupToShape( shape->mesh.indices.push_back(idx1); shape->mesh.indices.push_back(idx2); - shape->mesh.num_vertices.push_back(3); + shape->mesh.num_face_vertices.push_back(3); shape->mesh.material_ids.push_back(material_id); } } else { @@ -615,7 +615,7 @@ static bool exportFaceGroupToShape( idx.texcoord_index = face[k].vt_idx; } - shape->mesh.num_vertices.push_back(static_cast(npolys)); + shape->mesh.num_face_vertices.push_back(static_cast(npolys)); shape->mesh.material_ids.push_back(material_id); // per face } } From 368312cb4bd95e2806da09a2d2f43d04de73cb41 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 2 May 2016 01:41:37 +0900 Subject: [PATCH 026/483] Fix index buffer was not filled when !triangulate case. Suppress VS2015 warnings. Update premake5.exe. --- loader_example.cc | 76 +++++++++++++------------------------ tiny_obj_loader.h | 1 + tools/windows/premake5.exe | Bin 514560 -> 912896 bytes 3 files changed, 28 insertions(+), 49 deletions(-) diff --git a/loader_example.cc b/loader_example.cc index e592e955..c44e0e76 100644 --- a/loader_example.cc +++ b/loader_example.cc @@ -11,7 +11,7 @@ #include #include -static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector& shapes, const std::vector& materials, bool triangulate = true) +static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector& shapes, const std::vector& materials) { std::cout << "# of vertices : " << (attrib.vertices.size() / 3) << std::endl; std::cout << "# of normals : " << (attrib.normals.size() / 3) << std::endl; @@ -21,76 +21,54 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector(v), static_cast(attrib.vertices[3*v+0]), static_cast(attrib.vertices[3*v+1]), static_cast(attrib.vertices[3*v+2])); } for (size_t v = 0; v < attrib.normals.size() / 3; v++) { - printf(" n[%ld] = (%f, %f, %f)\n", v, + printf(" n[%ld] = (%f, %f, %f)\n", static_cast(v), static_cast(attrib.normals[3*v+0]), static_cast(attrib.normals[3*v+1]), static_cast(attrib.normals[3*v+2])); } for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) { - printf(" uv[%ld] = (%f, %f)\n", v, + printf(" uv[%ld] = (%f, %f)\n", static_cast(v), static_cast(attrib.texcoords[2*v+0]), static_cast(attrib.texcoords[2*v+1])); } + // For each shape for (size_t i = 0; i < shapes.size(); i++) { - printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str()); - printf("Size of shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size()); + printf("shape[%ld].name = %s\n", static_cast(i), shapes[i].name.c_str()); + printf("Size of shape[%ld].indices: %lu\n", static_cast(i), static_cast(shapes[i].mesh.indices.size())); - if (triangulate) - { - printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size()); - assert((shapes[i].mesh.indices.size() % 3) == 0); - for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) { - tinyobj::index_t i0 = shapes[i].mesh.indices[3*f+0]; - tinyobj::index_t i1 = shapes[i].mesh.indices[3*f+1]; - tinyobj::index_t i2 = shapes[i].mesh.indices[3*f+2]; - printf(" idx[%ld] = %d/%d/%d, %d/%d/%d, %d/%d/%d. mat_id = %d\n", f, - i0.vertex_index, i0.normal_index, i0.texcoord_index, - i1.vertex_index, i1.normal_index, i1.texcoord_index, - i2.vertex_index, i2.normal_index, i2.texcoord_index, - shapes[i].mesh.material_ids[f]); - } - } else { - for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) { - tinyobj::index_t idx = shapes[i].mesh.indices[f]; - printf(" idx[%ld] = %d/%d/%d\n", f, idx.vertex_index, idx.normal_index, idx.texcoord_index); - } + size_t index_offset = 0; - printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size()); - assert(shapes[i].mesh.material_ids.size() == shapes[i].mesh.num_face_vertices.size()); - for (size_t m = 0; m < shapes[i].mesh.material_ids.size(); m++) { - printf(" material_id[%ld] = %d\n", m, - shapes[i].mesh.material_ids[m]); - } + assert(shapes[i].mesh.num_face_vertices.size() == shapes[i].mesh.material_ids.size()); - } + printf("shape[%ld].num_faces: %lu\n", static_cast(i), static_cast(shapes[i].mesh.num_face_vertices.size())); - printf("shape[%ld].num_faces: %ld\n", i, shapes[i].mesh.num_face_vertices.size()); - for (size_t v = 0; v < shapes[i].mesh.num_face_vertices.size(); v++) { - printf(" num_face_vertices[%ld] = %ld\n", v, - static_cast(shapes[i].mesh.num_face_vertices[v])); - } + // For each face + for (size_t f = 0; f < shapes[i].mesh.num_face_vertices.size(); f++) { + size_t fnum = shapes[i].mesh.num_face_vertices[f]; - //printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size()); - //assert((shapes[i].mesh.positions.size() % 3) == 0); - //for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) { - // printf(" v[%ld] = (%f, %f, %f)\n", v, - // static_cast(shapes[i].mesh.positions[3*v+0]), - // static_cast(shapes[i].mesh.positions[3*v+1]), - // static_cast(shapes[i].mesh.positions[3*v+2])); - //} + // For each vertex in the face + for (size_t v = 0; v < fnum; v++) { + tinyobj::index_t idx = shapes[i].mesh.indices[index_offset + v]; + printf(" face[%ld].v[%ld].idx = %d/%d/%d\n", static_cast(f), static_cast(v), idx.vertex_index, idx.normal_index, idx.texcoord_index); + } - printf("shape[%ld].num_tags: %ld\n", i, shapes[i].mesh.tags.size()); + printf(" face[%ld].material_id = %d\n", static_cast(f), shapes[i].mesh.material_ids[f]); + + index_offset += fnum; + } + + printf("shape[%ld].num_tags: %lu\n", static_cast(i), static_cast(shapes[i].mesh.tags.size())); for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) { - printf(" tag[%ld] = %s ", t, shapes[i].mesh.tags[t].name.c_str()); + printf(" tag[%ld] = %s ", static_cast(t), shapes[i].mesh.tags[t].name.c_str()); printf(" ints: ["); for (size_t j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j) { @@ -128,7 +106,7 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector(i), materials[i].name.c_str()); printf(" material.Ka = (%f, %f ,%f)\n", static_cast(materials[i].ambient[0]), static_cast(materials[i].ambient[1]), static_cast(materials[i].ambient[2])); printf(" material.Kd = (%f, %f ,%f)\n", static_cast(materials[i].diffuse[0]), static_cast(materials[i].diffuse[1]), static_cast(materials[i].diffuse[2])); printf(" material.Ks = (%f, %f ,%f)\n", static_cast(materials[i].specular[0]), static_cast(materials[i].specular[1]), static_cast(materials[i].specular[2])); @@ -179,7 +157,7 @@ TestLoadObj( return false; } - PrintInfo(attrib, shapes, materials, triangulate); + PrintInfo(attrib, shapes, materials); return true; } diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 01ff721d..2a931194 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -613,6 +613,7 @@ static bool exportFaceGroupToShape( idx.vertex_index = face[k].v_idx; idx.normal_index = face[k].vn_idx; idx.texcoord_index = face[k].vt_idx; + shape->mesh.indices.push_back(idx); } shape->mesh.num_face_vertices.push_back(static_cast(npolys)); diff --git a/tools/windows/premake5.exe b/tools/windows/premake5.exe index c0bf928d0ab4b377eed48ef1d0162e97d5d1eaeb..51c05a80b452f74326b5bd768397c94ca3ff830c 100644 GIT binary patch literal 912896 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

52S<r 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

}#W+yScl~^mFxU@*jMycgQMdb9B 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�v-CQo|jGbyPtPe;mm)6ih4rka7I`v8U`VeisD(M462=0JlS@K4(4guZUl3uCO znRN}Q&}DjaGazG|0X7HP#FKk++SQ7y1l!cK>Ys(Vi)ov`-Z^s!Mt_v9e(t- zn~=?kXGCRHqH-#2@gz_3W6ZDe80gh;&BRplc-*b2&rM_ICtoGB)}AVrvHvHza#pB~ z4#`lP^n*jKZ={Cejs@DV)K#v#Px^-=&>;Nqzt#X19h3zAr8u-cffrLJzS`j zXHCOuCLQ&bAJmIvV>g;(N{a-zy7f{boT`AUAUYseSBTO;ra)eT1$w@r#^bBtqrw#G zgFpgNL=>KIlO`=fgT7mZjL3|wGv;hcp9`8)XWz3FuppQ{;3$Me3S5O_r9!IoH_@^Z zs|{QVh*JTja+z^!A!|{#xCFu=Rooc-5Uu-x+&^%K*JBMdzJ)^rOuMed|7#se&AHY> zA0FtgHW&CXSmA=FKGs0j+ zi+b*|z;}cfb?^*H_NS-&=b_G4ahvL)DC^Lq3sV6B++uH?4L2-!fG#pz=2x2Z%)CXppr+5OOW#kOj98-ME3_l-{9H);l?^S;U2I5y?=cFTOB z>1ex;oO_$LEl6HX zC;$*aku?b)x70jA?6>sm!}j3m6iC2mYs|mY`}Wt^SFCZ{%gwLnLOtr&)+^D=lXp3w z_E)6-plk)WC$vZa&2(c#$7|o)e3Qq%0q#es07Wkbx~cLE+e7t#2`kXtDEyHE%?CJ5 zvGSl`?~46N1p4k(U1tiLtUy_s3s7PBti9)WacODz|4d`FACjd= zcf8KW*UTh`aRb_M@QFTqD=<`8h~9OD30dtiv;N17!YTD+tpB$e@%SorIA#a@K z=hL+$S|QD*dhVt_ii;k6h1c3&gD(X}oO7MFRJ`%YAIgtLhk+~Q*d!Z2SA|+0IQcPl z;8tn&ym;j>*A0(QYiq57M&DFlD@(46?Sp9&N4Qs+6hB5aGwj!d0bVXinL{u$ zl>L0~vbWqKWji#=wUcZrDtj-IWnNgDx<%d6Dx8n@JEaE_>u9cthl&6uZs`joBKHpI zh+K`PBQ=g9;4R|50R18c^3uyfg;}A3oTJK(`E~ZY_q%xU!;M@4oa&de&lG2Ia;l}~ zKbX+kDW|VJN~!=<0kO!s(2Q+h`!1Lhdse*^TF&ikQaabJuOrZWY9qh)eccrms*8tf z?Q6azy^ItmhqDimBgE%#2HWNo)TXydVcI4OYO_sce(X+a*|)a~YFA`56?^6^?cuw=23OkY7dYTosKg<`==SZzXN{Z+kuu`-55dKwCS+AUpM(9^M zf09g+Aq>nQL871pO%)9)3e=1N4Z?(24Gu;Uq6FcYZeG)yczOFJ@9~>vj9Py} zoZqjTWM_>(nT?NzRPoy_<=Ts7@``=XK zr<&x;)GC-U+=Ixn|4rfM7^6gpO2ISB-~PWTKSRo2O?g?Pt<(ACcu_!Wf*;QCy6ZSv z6XRVF!1{Sm5Kug;O%C_6QDqM!W?tRM@iO3y}i5aeU?q}BbHG?lBs8S^!Z*0Oe z*?dviiN@j*s+miG_*R~n!|pBtqS>*iMAd<4iS#1cq~86pXd^FBEcqLMl)oeK&DbR= zxIl<)uIEL+X#Gh!X01NID%|>r^i~?M{<=&p&+e#XrX@BCWKs6FRmgl;y0PdZe2cc< ze~u!8&c|tW4kbK0R|-{IPcC4ucuBHWtKe#Dad|1E4BR3TsVCQ_x>|2;q5YulabUP2f5J~-N8>IvRF>?4hiPI5NiAwjO^|z?Ntu(O7ZR~aFvGHtnF;IRYr35;;b)~p6D8(Q znfSdo6{gI52ljJDV6$M#Nc$rUNqbC%KjH}0(LC<5XPDdl%`$z?MA#FM(Y#rptDOtu zbv7H6%u!rTM#wt+B}Ir$g&*;IGn<=c%RtJFUD7Oy#O&P@p_=k5Zhs3|KeP*FDNJ#u zu-btW>x-;4*5TU)Sc<%TjeWNCC7EbulJ_$~n=Z29_)w8qWE+C-#r!Byz|^KWSRfc9 z{S1XQfajod?QK%tpC~84sTPd0ej-^QpJdMl`4kc^*YT+Rk}SP=RCw!9SM-NGvYIyw zZdzSo1(o={61v3P+i}9v{E&hR;8BR$m1*qW%1pUlT|oQ3CJ9JNg=#szSu5z25P48s zElI^8sm5xoAN_s=Tac63EW8+2okvZTQ&2*5I8EHwp~5b2;^!k%zs>Gn2JW~b?s!}} zxxBa|i&+=CV5+}aT`f)7GRpKE#?_d7I~L5qK}OjyoZ6NOoV>;px&OeJAyj&=+Trh3JZc!teN^5<1)lWjKGhjbGSp zBntTWDH!q}z{$aoYayv=47rMT2e^^E<=Xf(SRbH9z4CnU=?7GMnD?HHjFkahIS#h7NAUe=Nmz>=88E&g;-#`aC}* z@kh>6;SRqAQtYKv?7-(2oDyU&{g0uFv-Hn?TE!0dRt^{6sEX$&9vCX__C>$O52r&z zHNAO@d7$Hc&*+1<_;x(@GQE)J4(Iuj^L){H{=4)1x%2#)^L)X1iYq}W{}XvGmT~^` z@nVXQ9`Em~WxOFJ(6a%VrF(rlUJ}3D8|;{c!C}hZ+=r2nCUb zg+=30W353FsqjPhl)fbM$TssDEhd+#U7Q4~Z>|thHu2i^6-X_!l%Lk>{l$WTEt@*4|~E04&ZKWNJB$J;d1tl zKcvEPW7ivRGQ@#C9Gou3nZ*-cEKcw(>`BQEjzYT>=BAti~n8d3Kn{Y z21u_>iS)zG#I;XxMmFIFpRs%GgcfK@th_C>{_+^;#~$2Sgp) zG=}T~s5^QC9XEevcGEfnb$=*aFYO=vxwMZuTd%a=$wsP-DG}oSy8x2S_gqntS}A#- zBd_Sus;)jGSw+1XBZhQV(XSEpYGsX9WtFGX#|1VFLNGbrLK6WZo(7d|2(@QQhtOLV z&y|OfxJY9m8Y5n#b;)aLEsC-%-p6p7a#&EogRnx~nv0H>{f0{J^%M|^Zr*=FR?*8O z#;<<4qgLB*z1u0N34$o80OiBs8ht(`f#LAI*OBN$1{ z1A_u>qF|~`540WTgH{yw3M9H=??5(kT61o}0_1P>Ls@_%gbsy|ejBQMfV7Ot!$joF z@NH}&t36moX$D(I2U$sniPhY(>5^dUIZJj18g}{~-cFJFQGte5--A!{O7n?LJVkRI z`~;!5{p!o{X`Mm zIGKQfX)+bj~bvp|4ekWQGPYYysGTd8{v`d3fzB+)#PHPGUVj3b~H*J{m`DV)t) z;d%#U(EPUz`qeG!h1{YNL`>bH28XiLju z(2ZX3D=oFh_G!T7YwDrfbSrV3@u9XubD~0R{pNvmkIv_-QrVGkcQqf&AR$eyu_Zeb z$W>h<^e&K%{_;PZV*1TWQ$i_PP^tA&`h#{}c&nNfoZ+Xcx`TTa64jKedXtqSbVVq& zZm1M?Lx&`1vN*nFFHiihw}--yP?OaD*f9quGLgn*aevK>K+{`-cp2?=HRm$bWej~L zCe+M%KPJwlsF6PO5xANVs<~b{L6F;M2S-_hLCY6CL`#7-xt{bzrBxeoS+0U*+FS_; zt+$55YCN-$)uN$UEHPyLBayn5ybeRM!5*nck+Wwc?@$-C^Q)|9calez&Pr+zD4P-4v(%Ia z8V=#CtxYc9b*yG}vp%jS+$fF2N~{+vRgawv%gK-k4Vvds^pAMU;|8|h7P&FNnKrKEusa(CvcYl$$hbsfMPB5WhvX&#ViHS zYwdw1>R8c3^OO2_!AWOrKcnyy(_pXa%!XbNSk2laH_^Zk)VuMF+%qeVD}B*v^xdhh zU-s1mHg4skc9-J}ug<)-%6w`XRYdMYOuRK@{R{?*m)L`nC^qEEP%zdedRexqD;wdH zn0T3EMInEaWV;!=zcHDZa0rL!jl0xW{79;7>5B`_Iqm4=;wgPi#9{aFuf%RMCr6PMqK+LkIbxpkL^i(fU7xQ z+l-oc!_ltbQRR^dq;kF5E__+g!?o658wH!Fx1ca{Kxd zBJNsKB`M85y_n!85^rYR^>~$JO7Uc1oVr|}r3zdwU$kiprET^{dO_QWaUYZPdcU}( zw(s7`)bKepNDu_0Z^miJQ-%8m@o<96W%JbYc#3%Y`Iap4*K>HzHAEb2$(n;#TO9Qi z(7dmW3&%qk;>9X^OHXKtc<`^7XSD8Tcr~H!6t)EiJLum-P6gSk-COMD+9zdw(d}%!P4_E71JM#>4%fkzy~pCcyP5^%e{yv z5}s7>Nb^`i>KI*_yedAv*Vl$ee6$J4Mh)8e@$yW3(c)eF!8s#Jri;N9GY`|vUlJd= zcyH<7F4`0n_qi^F&5QJ-ah)*AgQfjg?SLI(vZITW>Y44& zl?^Gi&-|jSAtQCUFS?IRaU8QzWWe{}tNg+i?2z?3yQv_6Z=>9|n8ySz=eAhhDSZ#x~1EQ0a&I4dF(A zxy!nT-Ammj+g6K}(5P_Hqa0yEnC;bsC-Z9k__iSA0n zcD|7HkBi|(Bw9U}+`CMB_@2@?v~x?&A+ppi0So2~otnR-z!$xrN>GciQ%G4(MK@fTAr3C{StRsux@L-y@S6Q+F82!o~J@8HRFCUu%l9msBjHl@3XrX_HiySjIO)AtCZKnP2PfuYn4tx~Lgi zQ|~g*YUdLTl9}!6yL&n3J^%cW+KI<#JIYbQ<$LHm{9QN3Xp`7&@K;UzHQLCkDsX>VyTGn7DA&P zl9+n@QU01e^mYA73i^c$RvkTuj>5rR%B{~4W2!45o|D&~N5u7K*W+^hbNu?!vL;&r9q2R*!*QHVR$gW=bYslT1Zq@8}imUfoG}9{K<+#EU{W=~c4CYALRm? zvVDD6?rW`m42CbX&~F@1)b_ z#uf5+&*%n{9zw{tiXe`mq|?%IlG8!)J1m>2sCItn`U09RiRX zQ%pTSB2- zwE{O}bOTCuor5|1HJWxU2 zFjcb`lvy?luH!<%Uh$J(Q>E~N9?J1>EF}X$IE>q%4l-u#>jqY~aU9~v_;B5_f3J+l z@8tgjWMgEtR~u{dUF)u_$Lz`PT62kTiEBTlsb?svn)-k?1%$rn6C@dHmm%($qTVV< zn;>sgvkvz!eSFE5-)%BzK7OCSDmf|%c1O_b&T@&}S(GF(l9CNn`;6^L-WUBg<-?CW zf$+0?gWUV@(Pd4!&L(>!?ZC8i1La@QCpd;+cqUibZ7Y1o^6Dbv)iMs~F8#dJjz@W> zcF57A$|`_0VigEu5Tm)2@_3XsY?^7Tg;~X25avzF8ZeTD3FcgdCw$7#v3$}8Q>&Lr zdY6-~1RpN#9vjKzYmN2$SqxsORX=>A0EIQT*wL3Y@0h{GV_8)=%s^2sz78}rb0Nno z%dD~Isiwez!m4n{{ys&asrQnnR!~v*gFC@pfeW%309byLh7?#}g+A+|r5TF~$CVc` zzbSJO8oL2R&e&08rwm%k^`}xfB(;AF6sSPnfx=-Jj zEbymGWoqa}snvxNMG3Ff1mgRw?Lz`VbGY}rBDB5-pm4S@UYmZ&gQs^mc|mIRnT08~ zQWd*K!LrCK_p^*qP`qC)z%<0@eMWiVxN3?^4OQ07hMGjf2E8vThCV=pI1+h)gg@+i z4+wB>aDX$ND64U|I7S+9>0dM-mhF)q&6~yi1dp!v2Gqp)nq*6m-lest?R9}G zyBYdf5s1=bJJm%Z*r}0|EhklZL>7PlN66U-_siz8jlrHuEK#2a68A|OYY>5~q&SH5 zpXbV?r6*^Q*}Et_LqYmLsZ7uygFADA5}8yG?tNUQ@kit$OX36Ck`uq(s4byajDVR_ zsyqW>yh_|ge9rEb}P7; z58uS6*o>-fWlB1O4p~#k7JFHwB8g`5iK^GQaEYp6ja|dU2tRsYV~veUPXiJ?6r~(F=<(kXkrx^up=*GR&>EX0DTA;w9f`^D`bO z<8GO#2eD#*R*n`q|p)dLyK9;_{?oyFx*c}Qq3%`TfHeW*4 z-;U9?5Y`{_Gw~z-#J0$g1C@im=;{k;t$c>g!4|c^%@X6lrHJg3o4AA1vn3Jb3Bs@Fiy4;zF{^jj@Uh|ALY0L$J z+R;-st^mA5PkCFSr<`ZBXBY>8|D7bp)F<4msxCFV^CXmQ-O=j%Q4w|2r@ioXMik$*8xeTak%~ju5olnIow5Z@5~( zj>GwZO&JTPfimN2rkAP?;RtRauhL-*eYOiIx*rrAp*`%eN(3nQ_L0^r2XJTUFYd_L zC>(7}B_^ki#4cwJo|5t)xjk{IHPcgTrg6KvR!u#w(A6Od$IPNXD`zS5yHCJofCLZA z)7&5|t+@9;(D?oYjLjN9%D_tdyTVDumJGlz5pTEXQq~McvH}OCx@t}gw1gRi#%FIv zpwi17DVJ<=-7xccb%}?+e-y$Ryl$qvag$8>Ge8BZaP`teDb*ZP?Ph4Rjs?9LoPZye z?N7UiGneeP)$#I>_48ru9mPj6Sim&=6wt5>XKIruoQbDuip1B3tj`VFXd3+;dE#xt z7FbtuuOU=4mK&>aYgltEg=CI47p+7{xJbit!z>Sza?IrHItflSWG=cj%@ALORCl$OTD>y0V;OUo z+ObsrO3jvrNi<#KD*P@1_Gjq@DqP9SKP~@)bpA4xKS$-yM_IV;6k@cEMX)6Lyfa!i z*RC|HwbB9XiVkW;hPrid>67qcho7|YbT#~4EE1v6XC?Bf$Y_&_T>4a_O$3Q9O>_v2 z`wHE7pgF1tL7e;?RDLA@^VchYX}OV06TkTww}c8uW(pW8{e-xXI5!gb*l}O2VpCL` zKNCu5uAYuCQ>p9|tx!Z|i&MV=j>%;>?9XfvM?$xN|5fJq1l=3|YeM5mLGw+5=AssV zzWHtS;r&Z*Z~Q1zzsUTS;CkR&@?CdBxbi@fEQD9F{I;2IULU{N|JM7X_c(zi7b8#} z5c!&i^@YjPXl|8pbHTpRZT`Wxy)&<4AkTa&i?F5Re-)_Aub(34CjaUJv&;OIZ~NYy zjuSb>{gY0hh9EFXUTFTN_$~8SllGE#-Pv*!^WWsXy*+(k^B4(CF_u_g&@5s#QG(kIpQodUyI zq*#!sFg823GX84oTPR(KA_Im`zGya`G&kJJU(TPcLS;AXgotv2Bq_E<=y`05I982q zDYXAeo-J}w7~3Fz*B!Z_Iyk#)V_T$-I|%c+L56P=ZgayR?-+1xxNk&Sy?Pho8Q9WF zuQfK|_ziS8uw|$G99wN2Zl$NHqk3I+_l9XSMHtf-0auy8Q@pG05P!tZg#AF?VN=z& z+B5vz%Qu#Z1eE`N_Xf#A%j~AVYbybkFn>JcHWz5_H2?X`Dx5jE`5I>7y{C% zZ&FEBct9vsOwq0G4QbE5*1^kVRg0e*hIyH6x!Ro-+5)8aQaPfVz($eOX%8IRu!4_n zeHF4v5I?4pTOW-oWqR=q9t!s;TDXoHWed3>9e*KHd_89A0lS7wVjwuNADj<`_J<5u zyPc|rxzvCuy0j~htCjFJAFmP`)WKFq-6MpKAKc^!9c@;PXyO?9dCY=v1xvTe`a3dW zXbwA2#1(6m!%I9!=$epqHg_Y&MGP8cQ0d>*`c&bdgpaMpo#CMMSf1LES)86gZ~!%( zoTcd|})6j7_OPgr!kRy^U zoYO|tSgZaF80E&Ae%sct;`ZL|H}^`Vdv&+DH<{~1uZle^o3>e5i1Bl-*YZhhu@*qFb?MoD|#g1Y<3I1G`ao>07HuFTSPP zN-}HoKd?oz0>~|bI{Io@0b{o`m(p@ZJuV!Cv0E62ly8dPE%TQ4X0aj|MV01mWLeo;M-7L4kSs+C`D; zP{*{M`n+_LuH#`QznF+(;nzSqYj#YI9^PagsY4qIA`%1Mo`(7VCYUZKbm1_UDw}hB zg8(38ZNG|(mM(!;wY8OZWrG-TFSWxAdyTE_@bj2a4%xxS#Ez6bb!n%vea|ttTKVM` z?0x^O9n>(##^ymMjQb=s9W+=G%!>%&^h=`OF^KapRR>68g-kSdfWQQitF2Anv!+AC zS#Lu1ZNYtb{!{Z^;g8Pe&oB4`7cFf0w-v3*S1V8Aw`znzer|1w8)_$-E+KTAMUucZ zYO^dI-^-0JFc6~0*53}Wwmhh&McU&gMZ&1y7Y!EyZM19l)6WY=UdM>*W1C{J(h1B7sOZ(T9bH@*&kA^fy z26P>jlhZyJ+X5b#C<1h)UhbjaRVo~_6BwzM`+w^z%r=!gfbX?YDZA4I9p(e~Q=&wb z{JiJHb4JItMGVJzJ_=xzSLO238;;YM}kHQ#fld2N6-mKKk1r8w)F_^&o z77p5?ckHpg2Lu&-f53~QKCE3;ZC+mth3rL0ct( zYVm>Pb_^@(Pgg8wW>rTeFEX1G@M>6wnK}KpXLJ@HWJdo))be3Zf_A8Ri6kolr}~gc zaMs@-8vcgtA>%W<3fOD?&pggV8y2=$6@&{QsA|GB%0 z-Ruoi9u@L*RFNtu6Ym4+eayD5N{&$0QP9DdD?bp0$)zf~l&0r~8+=X8tcn}7dv4IQ zcx9g*DOn^&`cdnlD_~BJiBPG_7yT940{Wn@=`~(Z$FQ}v6$uLH-jNZL_X`yYHZfU5 zOwMwa{%iigOkY&m5{0a9^6chLX1FHfLTJNXXY_!GJPlAl=|e$j7t!7HL9OEd-u6D@ zf3~ePGvICk9v*Y$0tot^W;JXwC?E}47hf)9P$r?;n#6nB6kBaITz{~gDMwpuXRk^L z+0NY6VHE}SworPpEW^&eMS?M0rF>YuehU?i*v%So8&ObGjT?s0Wr`;RXNv8>z-&{w z9L7Z8e13SwzrwD}w7y*gw`x_flEAvy)ef&A?B03dd^^k6RhAic7UN=~!!Av}UD{QD z5N~y=jzwf(zy1?z(IK5-?r4tp)J|%zEwdRH*-}pn>0DNwW}f?r$ul6P(sJZQ(HdV3 zqDVrhDk4>lb*MHPSv7o)Tvvq*mk?6cqqhnCl(B?5EY#rmD!kW=rq0wI&akx^Txx~e zC2dSP4TYS}ti&5kk$hXq0Ik2hlm-*uG7~>l-^`P3xAGC?gb#n9kDA|=bwxrX8xc2m z)KX~YP$48cgVdQERnb^NJc~hX26Bise@|W#aZ^dfP$j5LlP{B+hO>&uV$I*XSdMcd zndF{vG-x-eT@uOS_pHCCf1lHW`tOA)oh4#Oz- z-vKHV6^kyMCu=V;0kI(TmnqBYt}@Y=AGBVF*I}-O8&K~ zxZai9*s6G?B_Y)P=G$h47jjv8qP}2VwOQeZ*wl~3pH8LM_tYL@iSN7rS`)7XTD`g0 zTl!J`+3PMe@A0#K>&0Ud#zIf+iN1Ni&s^+|`Hg_MvN1cfkld(b#E5k3N^V_yeSD?c z97`1eyNZj}<(v2W**WVcQw0HOrHZwFytbSjzsHS(6t2`eG;eIao12Q9#4=D6zY9zJ zu^ZV%+_5|Y#@r#EbgbowH*JBih=202yhJsN(W=?53Do(uJ8bEh5P31Hw}*A3hY$J{9|Gh!9~ zZQ8;b?2G)`AdIWPYCDI-};{FD1D=0wA6sZkyt@;v|SONjh2e9kr)wf z(R@+SR?V(qCfM()*2l<6DqoaYKu8!DkpRjVu8=YGo8{7f*h^-NSeX7mP-bi&585<4 zFc+RE9y>I6kCpz^O0PBWv7!U2q!hb)9bSP{vCBplyKjokVNEd?d1auB{EX3d2n28D zNnUJrCGL{R5H>EG`?TZ)wolcu$7w;lG(l{TL31#<(q_Tbu|`hOKW7|BEQKKaP+l3r zzEo+)x@+s_&=p>0bJN-3dvcGthsvkfO^9=nbwh577!hbB+OU33h~j)C`7bJb@M>I% zN&BKhUwTS&M>3P$=0f2W3(T9?o*a(|1?4DOKpsROmK zwfTfZX1J1sC)94KfmHF9WG_@gD-)O2*&O-8uY%aMPP2m7%IOezc@k@>Yg=-!>C_ha z+S)?G`4TryDc&v;Fz{-=^D+LeScisd8=%p6~vScIT*>Ewb2=a@MtNFI^Dn!CAx z-`%I5LulAyd=igFTyBb6Y}IXF7<}fnT&KU)Y&5i*j8*N1F>FV@qV`{Yw!5q)fkC_ z$ec;3nkYsU~Z0WX|~Ck@^)oHOKsDQ&z|L-`7QE>!%`h4r#krT3}RH#H>(|7@1E*o1{@USc1@cR#+zx(+g#WDX19|17c*78ng zJJj+?9eF|_(21xK?R5p}TJh|kbP_E>Ra+95MdYx0oTmL?zm+Ym1xQ2{6q!8n)rVFL~My@J_dVmj2PUhUra$?^mF8l-;AF5`D^kBGU62N z4(^m1B<~!fVJFv{7x0@leNnNrk2M@vpAvG>aJG>uU+Y=lEkBYu>$?vK4QV(aeL@*- zr>Spm!47I0>mk}NWO+$@>06?qJ#*j8H#wFEUoiBys%+!6e0OAUI%s@DaW0H$Orp`?F@{p?S8W`a^3kcoigEXLc5M zY=T$HN8;AMdaU$L?S%IeR7qTY2q8uaVY=t)kAVq_8GaYHYx`> zLk@(je?7@^0Pog7qX*F6gPGf#8ht>W`;nf8tUrl`0-M2Evg`UIqiW6m51+eZxe)J2 z@zONMez#FFQU8)}M}?;)H0th-_dM0U9e*GF%k}TIW3*u;T+6kI>l2N50wNwzqD;RI z$T`ueTPn`ZtC)~ik)KyFKCj}eyozyo75=;mUtY!7yoxb-72dpx(Rmeld9UkvjrUE= zK+=IS`z1!WW4h63FgNTSYW26PeV`sh-UtiBLHBjf}$h3YA zukj@Vw_xCK3y$JqbpxrDb5biy7F)mglCU-CFX&&xWgB8KPB1I%<0VD2RSX`{gG1eB zE6n{LbtSmLZF-$oJ1xSIZJd-m%Z`#{Z^f}TIr(w(?YN^o{w~KJqgOV3bqHh^LHxr~ zK0EaEcFxGD5Gr3dk5snF?C)$QBR|4oI8GF0i%+edZavV#2DW-eZ0+O3sNB_8xj$R5x%S-eU!3hP%@UnFrK0^zH*^9W7-xXEWGEXR0KFiU)fuV_&mpC9V6GS(< zM>!&3aR4)d8%m~azOH!#7gT%fs}lyJe~KmzNTvci0m&{@dT=f ztEa*(oflv0SIA_&V+#P~@^}GRm_TmbmQNRpO(t3Otg4C`u8L&dQKQC#1{a-nQ`5DP z`N~g|2!&)(*H~|?P`tU+c1!{7sD5_1415)f#W$45JTf;Sa&)STLy_uw2>MF95b9oN zCNb~X=~Am_Sx=2)|AS_8@S`PyTA)kT4#VNZRE$+(h7DQUYpqrp+ntQraQpCp`{GNE zu*UlM-*XF?e7vV>QhR*Kix=*(Cnn;rih#s377HSW3K))veC(rUxqCPLX{?QQGij5O z7tI}?HHw?Cx%oWwNh&z;YOgb8g_I;;cBEu!5<<2=Rz7D~tYY-dIgNqhgi0Wgpg)3! z<6iTGb1&DAYgStb{(xK+HFz`DRUm)!u?NO)&S=S9*woH^pOCPn4$?5o@cVgbS#h$H zncN$)9=||NB68GY!F9R0-ehmtOJ+`p5{ISQZDxRonGotL5p#|O+&2R{(wAu@!luDfwNrxHT= zKbpDEdPUBMVh4$`jP(^H0%~)xRo7=CMJ=j9IGSNzyDo2-9HoI`9tVcKQ%ln)QH-@j zNnN+yFv@{d9MXz|+YlFh_HKf(-kn*4Rq-M(ehXzU`xlW*>t57^Ic*$FUTLgFnm;LA z1fdBDyl|+P|1(xZTN;dqeDnMd)Nz15xMFeE}6zc#Ap8zg7I((%07n zAS_ws?!_2bd$PJiR&yb(J6Vjoks%A;mUTidEeQX}KPW>Upow?RWOt~YKF^#(6Og*<$XF2+F3r!E1VCyOM7M}JrTh>)X zqoh6s?Dc&mklYc=1KEw}@p}XU(7}S(uKk>XG46P*hbNYE@;BZme|L!lAhxSt{XMGw z_R8N9Vh)N~>12CXxWRrF6ZyVFzVIMma=vxi-{g~U%Vt!D&Xoif#Jp55HY+^V6Yx+@kA2Zw zq=JFr3cfj9!PP?*1XdPlpG&RVGotcAbV+|F+go_=aBZ_jbk*Xc z-5(4DDKPV$z|taLQz>NJuG$&t*5Ts+P(4+F$c__cM^zw2&6U$*yDVOqmb($|IAT>> zSD}Jz=wq12tyi%@i!2j;jGyr)OX?j>uGB}HAC~s4$u#@Rliv8fT&R$ig*Xu^AmZ5} zJ4X~ZPl>SR7)(%PS+#X?fkVT_MlPtf{^I=77Mooo&yw*4t~AX>(2E(S00);?+o%Nz zw)snKQp>o;kCt(G`RD@O-Q`+VhU-Uv**r9f^gnh1qz|jZ1p>XDJKDn03Ink*wzuzL8b zX;?*h`~L!~nChLtOAe(1uQ!Ah5t^^ywafXXRen0W>=`sE|G$IO@g!!RGPqBGSnCP2 zWzxX1L6>GM{jxs9I?7a-XqHU|11=1OA37828g-{gb^PYq{1tpMeu4R-o)f z_j;`lX3G>wtW9l|wVQ7>r32bc*0xzJ%6q+WMZ6+eA$zE7uFF*OezQOMwRn7xHWm-{ z&dy`*wMxk2&=P&eZCQ z&0H*gDL}2~C8}9zjyvnx$fV`TnKteu`}hIRMTJ7+oyosxxWbB|3bo?6qW2-oAnkOz zIlMoxr=gKB&y4P;Ix{Z&fSncTZd~n8_@Gz3<;Y#dR5deYakaIfJ9~SY32U6@@H*_} z=>BlmT!DbTP;H#t$HGEZZBnvm(}#wP9P0C91#+6K^u*VA5JUzxH9`+iTm}^bn_T?$ zMH~2w>>Wm<3Xe?IVXw>#oG3aNzNRnm5nTu6<<%@NK=vjk`jt|oD4N(a-_?Rb0_;e>&aenfv@Q{%5|3)P?0O~GJhIN zaegG)=A6XK3-yTsEC$aa0~?(y_TW)AjzlkCNui)CaY%Zw2t%jB(#nDQG2)i~=qk8l zZlDGT=RGr9Ru$4$0e7HT;H6IuGz$!Md{qiVS7SY|P+0&rb00^f%0Xpd(JeeGUZs(S zT(Z3IobsZKI`1WQN6!fk1Qr!yB1gY+=>;`m;la!u9UUCN;+9hC+>I-TJl&5OW_fJ$kI*&IwuJe3BOA5axI$dEwoC^a%0=~92<9@3Fu zB@m+!k0_Br)3}zFK=rDD^(5Q)L3DECZ5LQFCQBH~@@chj`iX1hd+M#-^IiYaKHv2i z|1a&B?`mVE+|09%=QsE-JTp!tv_OS+MTPd63T;w_Hm*X;ZSCW5RoB_tdc#ffcny}2 z$1;z4Y_oqg+K(0LK}F2=EOiFeF0)Uh7tK9O4yIFBLQkzch08+S6YeE9N&|;LXo*o! zP&VXIetlm%!ydtKJN|;brq678@K!JaQnDHC>y-Jk=|CuQMRly9F~+$u_-t%54p#6F zj1Pg7wVMM>w7u5ss)bk5=HUC)7Dx=8PJ^uoLvkaN65kyK+Bh7QlL!5wR_ib0K_t{i zzA;o5;iEElir*)`WL4ho_<|W}1zN7qsZ-l-Mx_U~!&#N7iwl)tqxph}YiOxL?vbx~ zOFx0H1j$+45uP)?+!bF?LQORM{8CKT8ybi6@jKxDTtoSmiv~qhaey6+yAB|V` z#G<$IzBCpW$0hN28Gq3XXN>K={NJsI1)RK0H( zSw)nPEGfbK*k%MHb&TOeh|esp286A$)mAoQq2@LWnlPXEUADLgCa)GIi-H3Sz;=K;4rP3Fb-F z^;D=#`ds%YU<@Co4|M7gmI9q3ye72->b7flrS$E0i!?kVHK7mz=iRYjTRgZegcI1{ zP5}FCjdd^G2CPzQ1Esj~ar>h6yh%Qar}P(9z8i=0P39}2{LuDs1#W5X`4Zm+W6kmiSY zOX+Q?3AZvP-^=~gG5yiBgeCZ-$jt5`N4#_YW>>h(MuV6L=)ujRksVLHBsHX` zC|pR^!~#<6bW?vV-1nSZ(Dk~UT=due2BsZTIO|ual&PP4T>TX7YdyEMhe(S_Z)-25 zli95Yc!a`Fs;VBNDjD^brBEep46+!7gv!z}9^4Dw4+D03xQR00@P0T5>HOIvJ{E;< zoh5EXtXP#+)1AX7>YKKYww)M^fd zP&$LoK@a+evJQ~dKO!rRKazV{pDP6VVNkYlM7LIi7ubC+aQcj$-B2TxOt*)CGX0vk zh>EaM&I8^7IBHKTS>v70aqt}$6Y+s^%wxJ!vASO5w<^KzTCA>5%ta&zoha7rXj zstF%o(&R=3TR3AC#e=6&k#+w%L`B|U!fYziAyWqx(Wm%!1b2qHVFFA0p0#^$Cq00n zPP}es%G9{%4(`H#G5rtkBvbP3GpJ3^(5!)YxK)Mj+SI1UrZy+PH`E7ZjVRRSQflWu zFYtt{210Msg?O}rNfr99@M{RQ?A?c9Xa)D~>np zeAdPy6y6(pGBkXJ_NWTc6Sk{ME-}TIX|H5WBYjETPUu8f0O@b!I=1yzUbXDj5+0$j z*Xhp}#o|J2HxeQ@2_JdJo}5mS#qhH?c~Q8Pw1kKn6!Ijq!;g@F&bP{PCUK4ACjJ5; z{Dk>lN&X?y3X&x@GRzTEzRYR5LiNZW$z48_`&0J?j*)kB(;I>IpT2QW zYx3veLE-vX1iu$=QfX=r6h;#EA++FXZ=^@*d~UFmT%BW%aFD_Q^t z#!-a6A_|X12cTKn6%rp!BmA-w)-Sg@&XFpWn#Vy-vVvM?rBqgAs1&e+mm-qj9S&yD zdC+&}2sw}xK6NA{QKUG;X+DMu07v-Xvts)a+-?R7QLr$BMRLZU4DTxhQ7wbE zGQd!6UnpjCUQgmJbX%3V)MI~+)xE&Na$G^qe1}bIFKqK?%^(^k+D%;hRm9`MFT&8g z7_#2`vYKQBIQb46iDl4efUO{W79$@LNPI9+X4K9lnkZQ)t;7|>1M9ipZk$^}{Sdc= z)p9?`gp7;Kznyz2hxOnF;b)O7F3*-@5*-URBdDosjOk6z7R>FR^%B2S%s|pjvr`?m${U zP&5TsPqVIzFr3x1Vr!>4QZmsa;D%h8%!uxQs1*$9227((f3>v^&_hQD?KxBW=k~hr zh#X664MZ0OO8~=#c&TN1Fd1bz|+N~CauLa#R@#Fi zq}(!pRcfGntPs)IDMx;G1PAmsN-Hi^mPiZXlfdX6Y093yk+<}mO~az`K-+FEwQVGx zXd|)MsZFwxIA1QS;p&Hrg0(4$tB!x29xlbJta%C{^6zj|u8qDD1C=_ZmW&R2JlK0j zYITW-9=WieHDC1p8jfJEYyDZmI<1~=+;xZ**c%sjafj7ddhmdbpwik$hT7UVQnz?z z{$e#!PrUNb;t;xv@yfl6am}WNfbM|}NXDU%C*0^DlgWQ8Gxcxez^VHl`d-%EZEFrf!TZi zh%LT2<2H{mcEd##n2DBK-jgD-=Zis?s^pM81`@9SG7B@{$v_vcqegN1honhQwL z4`WuwbL{H3kd(e)@#=ewFxW?|I5r6o5Km;XRVPc+%J_+s;I~9BQENT-BUTW){Y%*e zQLJU0#T&(wq-dh*O`^v!zihc4GM7UQydf8gZuSWinXtM*wZVU+cVBt$Z-FUl}W zyR_Vp)gVbvPwuXCJyXb^P-=EQkJM~Gf31$@j|FEy$$)-@fZ0|yxvlB^NnS3l?L6FG zR~|;4=lSnbOKqolmxU)wjrzZ3Q3c1A5 zFN%1V2eK^^wJ}xJhcpAO+^|A%}u67E%AqcG>8C>bl$jjPpYa342b8WljqDL=MUP$PC_Z<$pc@ zTgtO8JlMQ2%lNB;-UkYLKOa%G^v%gLJXe3sG(J$X&^#jNBO~%L0!HY}*}hn+Z-O zC$&jcsoCo9h>uW1aioe<(+n=6&v_0)l;coFYc$^i4M*6=+LPx>Ymc)J)OIS#K`saI z)RH6U^_N+{_&1kp4{Aw5qUgCfrmvNwO(2B#A@grvKIYBB3a;H-+O?|h%lo`pm7e8T zZe+`6Tn*rUd$x=(rTQe}bA5;L&8AA@u3lsfUZKOM+`gs{pf1L#EML=q^McA@>ASwB zZhB~(oM1adGftlEYkEngSYi&rZoR2aXaa%rZK!A?f`|07Pd>_B*_G~cp3vK>m6#bkj+W&1=u z%{YPMmCH#n+TF?Xu^<^+Mtm*4beRWFO*H(2_SPxX%%)Tfss%LO)wAoI($SQwJUT>e*O$pA;Y3{2En0ZS!%YRq&;tT z4VR@e$cN;VGcb`Fyy*;rqG>D}EA!LPOXPXPpve-Z8&FJV`oOf48Th|CnWarJPL9#e zHBS200+(@X{nqOj%I?T6?y|lM)VRj87Q%0IMhe4)fZRDfZ-H1n) zPW(g^cW4*z-@||2_4(HAV2DY`qaL>Ee7O*m8#J|+o|b+lm!#InRG$YYS{q;KA>8+3 zyd7IU?J5E2)C%n^t8}(`n$ zuOLiV_retq30O&)ZjR{%@nDL~F-LgGQa=Ngha1i@D-W|E&6;Jg1>^Aee>nMjtKjL8 z1VD&`)G;NshVX_f7nvVlvZx;zWEPws6JFcI#P| zoXwBO`GeD@*WBCqUe?Ta8c$^EW&h>@Aedru1~soOhH+Xuy@m_X2N22EhOEE7NMA6c z>qecn+}qTCzt8CXSVTg(#v*Sac1(9rP>#(oJ!WT`W0Gdj4;fW$&1NjM$t$WYx%Cja zlhX2>a=hH@Dx=x_YU?Z-3R$;7L28vPvDlx%Kf!pH2}*q*rqw~I!!WF0kdZ@qXC8~` zy`{6;VR?OVgGQcy@z<5Excdbh0xUQ2@a;9UYKGy1#G%yr#9T<8BQ!n#SVtxSajYwxPkPoUxLLf-cxb6S*@OiYGG1vhHS2|H zt3Wl+_OX>fSForS4{_`zuoSJDh+K zDPqfe5=#rNH43azg+mMYH$YOB-G5RgIv{AzN*;}2dTK0*hg6F`%&~>uGX3i{)>ko~ zQ81ch44fj$z=4jBvdz85ds8~z%gORSwiTu`nf*#=N2Tl7yrOkF(I`{eIg(X{-OM(6 zr*!n@WVz#Z##WWFtf*1Tx7JJ<>d^w}5tk={x+D69HC7?0Cs%8J3C!lLv2;)bP~gYq z`wA&1p9z$m-*;GHx&T))r?jgf*X(*mzC`d)F;#G? z_8FN@GM$exeoP^juXNS_IdW<_ zIU31PV`7+?ZMvf}X7eNCPg6Snlw-Pc1vDOxTyEORj9p3b>(`&?r9k~J?*Q{Vl~Hfw z+*uGS4wTk|?Xn3<->k2HC{wKVds$#=e5L)XE?9r+0Bx^1*ZgHMF;26M4*z1S6tcX2 zk=ND8(2{vZS0Q`AQMQ@%$pnVM7|6%)s@;zw8kx}@USDD7=kOBr8tsJ;Nh#u-WhkLW zUfQv0%3Rf8!TLMBsdb_xz(7?+eNY+>&34&=5oIe;?Pq_^Zy4{CQJviNKeIch9`mLm zPfb;I%Q&;X$WI8FueaQj(R55(Vjky9eoHQ=glqO_6LF6)rX|Pzk%yN5hs$pVhMjg& zm!62PO|^VJv+0O7O_DONc};I?nU_VWf|k2eMh6MnyUFK)`t5hL>`7dPAV0n^#g9(2 zTmC|Ww#jNbe=G2T0-uxxwGZF2lf?taMC;YbL%7=v2)Q!(n@cSwY~?q%qt5?(mY?n~ z{hKVU4h`>!UhQ`=9p^At%W4&#<5;;YuxiWe26BQL|GzJ=vxhtRUu@6DT}L2J>?7Bt z=*?BQNx3i29P8VWF)ubYiO0cz$EO1nrs$&QP`5*OfcOL&z~% zsL}kVSa@J$we_a#*1}Hi6}bKP76lDL_&nAwr)8^U(h$IEq%T9{2iGoGg-b5&cZ%lR zQDdDD()Pax$@eAe|AOZDqB^uzXy_>QcMA&^;mE~D*aAT`#0sjstijF1F9^TW>P;P%9L}OYox>FGB-F0yf|c)%4=!& z>T}GT#yKT(iH1goko6r(vt0v5AO1s>)%;ub?TML#5>H0*D05@U+`ZjcNSW!ASPd@%I5V6yHqi4bdvek zPm@{pCeNd^eBenA61mnUsX?~!L3@unC5xmB_g8n(5u(c?pqWWOM53m}u7-R-GqJp( z&$?e_)qagKrbRFwOz?Y3|DgT4%KFSMR`ALU3E)_d-Hk}Ba>Xc5pJ@5i@C0KmH?NqE zu-Q+lst#Fx8)oF1Dy?)Y`<{lOEf-OfLh|KwyA$bZO^tN}yDK9&wN-|dK7X;>={{>) zfk08VX*py?+wb#~W}DjS7-~U;|}eJdtgB)xO9M>1$h%;Wm29hDk1{ zFu|%)B^BFUNJ*9r8Or=luJC=^xM`R$2)Sk6CxpZNgmllce`hm6sRK?{nXJ7sS&}%x z^1rjnuB`Vu%$ZEXXUtF2%3BPX^@-jNb7 zAKsI|8r(dhBP;GbGE)aZ!cyJ4sxQ6m7;_(?cP{Omusp3lQl&73xHO|bl2mJrBQ5+8 zLiq4k_+vdS-4(&zt<^Q*KQ=CKSzcCT>k7WLh55sJDDA?5tQan25_Y27U3zNO-;B90 z$U3`Yxi%>*Z`K1&OWp{FSmbyUBvqz}qsuhG%4@#IoO-M*0fA5gPS}C$Ijl*aij(^xL+@~gUX{USEDIS74lG^zCEaS& z8Tc$5a2t<55(k>+G*XiNeG^hHGrz*=RajJvgjOaBUQ}4EYa0fsgVrH zXo*58zu{UX!TN^tQ`KZ$$q7mdeWQgoY+3wIL4p0PpKV>>dgj2(9O1GL@pt-97x31@ zTklWg?J#fWsI*?*zDe3MM|kPZw)p##mnBOdZ(CI6e%@T_?I>>#{dj>h4(oB6QuH?4 zdh>OpSMNJRku)8}4zE?603Y#;i--iejXIOZ`mH2^`IR+EiBy+SE+lhUR_tb(DS>oa z8eLXx-37J@;-6=n>RtUtwY5ZkTVF;RpB6sLZJl)+326~S$jajv!sX=q*7c{Q|6Qcv zVhNXg-QHySZ2ysLsWc#yHW8CBdN$D-rCLywN{cC>X z`)PxpLz=j`5}#uYN6mLJ-Yw^HeIO~G!NlND{J1~?&XWp+!w!_(J+|2xwLLz)y*_Ly4qUyH-N}8Z;(h7=1FbT z%s0)>VfMUA8lVJ-52zhsQ2@jZ*FB1ax*RmTC=+t4*$6BP5f6nC3rNM zjCjKpLL??Y7Ujt1Mbk(3Ym;R&%D4Be0_(?|`u0=4>olWdNT;I=r8@y_s#WE_*C)9 z_(E(R-K+E}>q!7$_VBy5wCCQ6Ru_j?UhpoE)mhrP%Ez6=pmh&DRpj;T__n{q4+G+AC-(sh#k0X&Xr%O-^O67-PNhzJ|onQ^MT_!20t*V>WDj1Xmzt^ zViwS!7C=dPl^JBrjudd5!eCbpJpec?0DkdN_UA8Q2_z&~)|ODGPhu?&kg?OMAg2u? z$@?;sDQ z@sWGgmB-&U-pkUw#Rr>nl~h|bFfDTZ`YXCoZ4IDR7P1a} zRWKeaq5HF`0jJ^RlUZVf54-b^fa&hZY*%-CxhxQZ0T`PFj9>i@WjIO8@dH7OVyxjK zMh~~#1HoavC&$PEgjj1*1)Ti-6zr_Fo{+^TQ&4Tq0jMJ2a5}X=%xo_?-+q0|+5*wF{hN=m>Qq5kA6N2q z@VsP-UTEDgR9WPdT;Yd>#kRJ*p@>5A8IaeHm&cB71+ozB(yjtTFEX+O&xQ@9J+LB&cv z*Yf;^d^w`Akv(lEAMvb(Xg>YjV}0?LQV($%JjcpbW+M5lSeZ#98Oc25Tdd42AG?;< zr6v1DpU?}Uz*u)HTGel~ZU-b8Yf;Q){NjgEa6gY`={xAr2<~u?=<&VmuK0|6ZWOng zxoDjjpI`a0tW7p-W9}31Fh zdSP$#5B}Qjg8#HG7`++)tOK}Y8PNeUr<;#{a`T^u9^n7(^yV`K0-jH4KJ)*j`ON=I z^Y6n3{g39A*VWjePaeJd|D}2N|D}0R%NWtTjRK9#w*Vm5>A@K&AfNwPAI?Al$)4`T zr=Y;^Io^)wg^dDO?R%`Iw>}vNo`2SXGf}{kZvInHVEHFC4|>9veoFIbyMFo-IJ0?< zRrUh-l;+<>nRUeI?K#MGmZ9v_nmv$NgD{@mEmFNB9MmUpiF z7~z;)kQoj6F0MTr@-yoX@V98)>$1%tMX72zzb3vm!+6D}ZWBej%D1C4f>7h~gF?`b z2zm3H-xBi12k6!HMlXINwCt8C3zOZACoe;#y|N%Pnca92H&-O05y~B5^Uc!i09QQa z>ZQo{@LXOX>X$a2oS}{C4(8`kW%9EvxpVH*#>`o&l01@hA>Y_CT?kMI{5nBZX6SyE z%ROhQp3`zihA1&8rWr!|GwB$XqrM$)_+IudG7lQ>yETGWzhNY1B+ps@o{(Z~M*PO7 z8c&=<>Y6MgQD}7RE3M4G_gwmo_xizA)AVf2D_2kDw_BaYE<~U8=4~FmP_gk@NS6d$ z$=h-F-I`e5Y% zTAGg8+Z7k8LA2^*Ub3~#GL9&WSYS#j=p=*_@eM4&v8~*5(W|;kGbP-Oxv<`I`jPE5 zwgkgzCZ7|e@#ZL^@(yVpXp zB<6Q;QaIKO?=ZvPwgi(T!KodR+OxHDQChP6hXr}OId!kI-a6~IPqhEB(6a43 zvIHLII~qCn+(>l|1>7j`*;NOxCugONzyj6uV8%PmTdBele2JjJc276o3G)3c3dJKb zc1=Ldz%q!Q^q83+CbKlz*gHX>t^JF{=g6xkeh{U5wj!zfocE~P*gcD{W*ApY9O{FYWqluBGl(HwfAaliLzNC^gjiaowxVy6M!>*%g?|<8Vi( z3S1%I&FXwob#~S5a@PM`*K@ez;H9}I=Z3+-e^H1b-P_Umd&|S`cKyOL@=&4$RG)2@ z(04j@Sj^exmct$4V^MTGrv61n$iF-uo%NqEFoKrj&b18QrOt`NH^a2!+0K8@Qs?r$ zS1om}ZCdJF5Z9$6KHt04dEn)z{JQs<6lYfcE!nbjBM zTu(lU^wPn1aQ%6IzOhS9p~*O#=6v5qF+dQUXup*O{S$T{v2wvd$)f^=%yC` z<7sq*g?Y&-M$V9UPUJkuw6~wy0ob^{ZXD>{VV(Mldk;dd^UXj{a8O67(bD|Bt7K4z zG4RFE*|TdA;5(J^3KD0hy`P4>-Jy&<8Le`O_@2dTt@Wf#kcaz#Ja8UY`&Wvt@$9Tv zd=qzD#*AJpzJ856tWT!C@4kq;t-m!Z7eT`bIz&)BL9Yk@r(&@Q^9%$40e!|7=A&00 zyLSV#&3B3KMw{<0yRX{eyVV8Z@y$qTn~^&C%9$l?GjvOrJSOe+%}AEZpaE?&QW)8x zU^WM7`=DL!fieSpGt%b35Xj{v1;gWvdS2$ZM`GmMotEOiYohmb{EE0g$5W2j9!zhd za{e?WE;1IS-O!e|`9hl4miLU*g>5qP@x1wHl7~NUvypBrPhOHeMLyj_i%YQdUwN4o z31oHceygS8Chu8UTW6*gsc$hp2cfoT%uLOZrXa~QGmU_u_#_S{8Z%Q63RvDH;|La= zF*8YxAcJwhxY1_ZWjCskKucT1Zb9h%tuF6QTj^Lmi)5U5RywTly?d0^tg{19O7qi_xY`XXK zrPZJM3qJCm9k?U*5f z5)nW9EW5R$ItwYE4F3#k_KxaFIpiC=d;(j$`ReOn!K*Kq8*-(zz*ylxlK`ydDrO) zG`A;VyCoOGH-M11?G`$>_BDPiC6yM+7PGPHN};5hGwG}oIw$_n)^x4JBa~F`S|&6CrLCYlLYXPN@qbqH(x?Ni2?b!Phss#?Dnavk7ynVe4An3 zo)Mmb=77v>U_LO6u?w8tg2sY4k2sV`rm9&LKxwMgtCdG}Uf;7K&E96}E?be@5djHg zK8!+65->pu>qOL1zG97nTwh^>Q6s4K<=v0ZE;R$1giT!zI+?u1_H3U_H6<#Y5C7^+ zZWKz@e4t^21N%oBa2X9CBO-(sJ+7NdV0|7Cl)zX%q6T+G11A$m!8-VqUjJpl)Q=)m z?Uh3(Ftj6!a!B1stmc|t=+9e^0-iJoO(@L5hz=L(zxWn&fqqn{vErV}4sn=RtRC7Y)gDpn^|M1Y@MItM-iOLHXnG-H@iZ0THDdar6W*NaAx9Y_dk^YT>rC)(z*l=~f z;8~&$KMIVPk6;k&Y_v>U*p9%u_6xwvnksB@m)fy7DVg3I{oiP-*4udnLUpwvc zfXI0nc^d=5-14Eu^Sb)OheG2pN6B=7+Awjlc;li{=1k5Fz)EDlpi3kuA{sCNWFd&B z($~UmWFEh950SzsRYJt}u3^NP%-J<|vEyzMu4HuwXX-HF%Bm*~(h+rn_5teGQUJ%3 zqrBhZDzqYJ>Tu>LeE}YOKU&s$?F%WX@JAFg3y0xw1=!JLam9 z?oelh(Vl7ZAS!5Qwx}TAzD(cwcriG)DM!@J04+@!sGAa5dqmCWU`8mt#XYjXJ+Qzt zdiyfyb}(-HA|6#k7Y7~N=gQmQ;0cz_$bfltqn>imzU%$@*2V(NS1)o8z|nw;PPCNYN|?&-GluY+j}A^c*JZ1*@sn%D-DLzoI~Lf-C=_CzaYsp&8WGZ zM;(1Sqo{Wg?4d&Tm?hq1klZm!Ugl8u0 zCcG$^uNqpBIacl|T?+kU1PX_9lT>2tQF6b<04j6VQ@N$MR6RuNWxBcFp<@_BIqH>_ zvSZ;Dj>r*q&~O>DDkgcHRfE-Y(&@hZNf4R$aYc&+Qz>0~x!Ig)M2c&Tlv4Gphe;=R za#6%MiV%~(!yC>Iigb#jME&X)8WpS*J0s(3G^uDLI}2tfGr5vGkL=@ar*Cr5m2r^P zZdgZ|*u(A;y%^Pb7sF7GKCN0Knl+Uoq{6*21i-GPLEun8{pp#M%87#Fo5>?6mMw$q z0>sU$>;kxo`TQj7tQIwC2dM!OIA^lNsBEc}0p?I0q%bU+h!g&SgfsW__^!#3QEu_9 z(c`*mD8AMniL`Gq2q-6Zqa>NO$UPL#l!II2Bxn&)6+F3aVT>bkT9vx>yL_jMIw2Ss z3n460A?Pgg6jUYYK`zDL))_9|JtWJv)>QqZ*4K1gODrZ1<&{ygzQa}8wREGWgAwUqV<2S5H zdf2?GwoBGb*gEPN-h9c3Q6qmr)cy^**u{O|OcHQJE*7Pb zVG%V`S4n80oe|RSl1nBnqe?x)Ohz1!2{%)~HRp@S(F$K%n<)7BIC3;WXaYSPKHG?B zxI^wJBTc*OAbGcmq%I;+VW~us_~p!dCQgg}KBA?0V~m%z%o zL_{`)CC(B~#+uOQvM6>2==s908>m0T7A%9#sXqQ%k8>*Yu>n%LKc4 zO|P-0I{;y{WS5_)#^d@4Ove3LNFw&IJ68-anooI77|nQSMPB6uCZBf%2W^#TZCJM@ zJFj=;O;Glp5_M4r=qge}dce9q^WH5Tyu_NSzHxRymY@PJJ8e!?xTfOys; z#DyVGZtrEhW-q5d5XL+raxIr5)#AP+%aiQ6RF{t9Wps#GUY~u(EPTf&(T;pTR@Ww# zOMa$7vMT4OVT!u2kM1Y!@)oO;c_@pl198$3NW1848zh@KlA_tnCH+QF*+-^W2bi}> zDz^`UL=6FC44sdzh)`rCU2%t@P5;=r&Qe}q*XeKt>ks)`&sw6QcZFZhxcEl<^D@mhQ#40LMuST zW0^}Rs&jjRt>(Qi8VaKO>_H#{G@kyxOfAvCXprhmgp>#7gM;uaa};CJL?0VK_Eg{u zPpAX{l{M>jR&qojo_~WJ+UH)@V%wTn-(nkQ(-O7flpcCq^RNlJ|BUoNspHfR5#I9H z(`VZP6L>QcjO*-1M|vktBTnv!bx$+i6m<`ix8VKj*yg{+pPY52tp+CBzU;lrv4C4M zb)d&Ob4K=?)t`|^YvGSES^^!EU$=kNC+bHZMc@o@`o&YQgX=h9_!*^$q*7O59BAdJvg8y zbD$?SlxNRHQQ`Qh*$zu83qY<+4n4o!W+p981F_H4Dj~A=idr@KP;p#D19pR4oE~~LDD-&e` zef_oYAd-(uWKHQuUn5J(2})y9aGfrx%`qUXM_C=cZ0%=73zu@gDXSf>$64<1qp03s zo>|egxZPzbD^c+;GYs+_Wvr-nZ&$AbTlP;6nc_wE|Dm~qzueqE1f$Je$9gDWeI3OIsP;hbSt~kUXJb5X>-N7I zZa?Hi3&D-mvl}i%R0uADg^#}*#==_3BMa+9sryF+i%P;dqD{$aavua=usq33*sKSX zOY5H^l#3#2uIDXY(BI1y=MYK$*=KXW*18pO!58`T{_U*R&3Jfs1V+`?E_{aRo1n>M zwM!kxcYw`#j*~4md_U~6`SX)dhz(u}V-cE^TB?3b&HC67inFt$mpxnXe6(=vAUZgp zc9#W`=fjsC4&CrF5ie?U5n>o=bKAPAAL|e{ z?e5*t`<#1d^uKYR<5?IeV{`SN-Y>?H7ehIRxtpop!I{InT6D z5cs{0sDBN=KRvflweiJ%`28>Nwd=pYmxsJzeEkJ*&c&CX5OX{(_|kYhrtvlQa7T3T zY$NTqREvyA%d=qYPkes`#*Q8C2)?4m5c#j+?6z}@Rd;L;rV@DYgyPm~#o{*6_V@ zs$3Ns?a}LU&&48NV5yOrdo9!4-PG9?d|vH;;a^4M=yPjPNm+o{!-3(sS^+s~<)$Bi}Zmtp3DQ!Du?)D>J{0(TgG&b=x|F z!5y6+2e+$xDE(g>m@kvEUmfZIhob+F@R=23{g21z2Ucrjd=3S|bMg5CFq-)M+Lz|D z>W95`fNzeZ;r=7C*rY|9%ybvG|k>O!tcn$mg`MM|5QW>fDml@3!^fXq#(3 zWl!&>F8%iWC-8Xt{YA&)uek*JH`Zro{as|}FK=-(*Ii#JZ&9No`pH|kk+_-Xh)<=a`VAMLD#*MG-I@bKcNj-r{iFdIGh~#WG&v zMb<)+A(GKg)?(X6f&x~sX1=Zd7I z4I6;W$)^aHoZ#IZ6>oX-0*%O=Py(_LT7Jeogap>w&qX?>^W)Ws1A(WB?O>34-UNaL zaorkKJK|EQA9j)!|F z;oq2F?0+vtF!MiMKi`11g;7@xH0RQ%^9V8N(_BH`xikvgb+2<*m?)gy`4NL1rNywY z+%$6f6N|tg+fo=fS$vx*M+RRvF?ODb$Pp&SUOES3!Evf#OCRNb$xOOk(tL>EnHD*V z*0qI;1%<#U-R@cJb%y58M{-haL26yDhSpw$x4pHa@w?|ak37XXwrZr>G?>2K z=?WGcj%#n?tTlkhLvdZ7VQrK3M+7ekprEReRdzMWDTz~pV@l1!U!?Go!{t52>McAS z9L~cjU=kJ@!otS$OG^7g`;1N!fwrd~v@6Zh21P*46i_D!sFxkgbCsS8$0(JjK~4_j zSv5~>5#=JBa}{5JT51CCJ(>*cF0%J)!YG=Mp_`Bv5Z+qn$8QJT?K-)0*4y3;F@6oIJ?)dZsWKb1!Iici5TD5`h%YF z>QgxL;YqOlHY8!>auEp*QCwg`aB8EQc1M(s@R+_E-Gq42P59A9*&?Bs;M{`K+jbI) z-j%7C5St&|B}q|bK;EW9V}Vl;)g~CzZ3x>Z7}lq9W8gI=c7A-g{16cZzOlhsPu61C z^qNZ#$1Q_mdCp@eI_fD4qsX0hc)F|e@my2xbDh>QN>JHiucaVm_ znl&9-_d++}Fg9c(4yBjAAW{pO2t=*})hjR}X+-!Y(0eqs7_p8j96^@(G38a>b^O;{ z6EIo89?S{=)2u~ETfFnrzU~n3PwWhTmxkBciTLy4j-q9I=rnbP@V*ZCP z)z-ZVojHA@;ada|q23dG;`Jf{9o@#9r(t zu|cdF+6*_6`>pJ!ES>>ICn}wuMZs~6BQPw3?U|g0k*5Bq`{Hn#56m=~#w(&BI!q_j ziAbFwilQGiIB%+8(MJiiVI)u2O%;nA3p+~l47H?4`X7X$1@0=IqU0*3|^$I z??iNF-Rbnf<>%t<7VrClHL=^Hlab3Oa(g$O2cJ(~3Hcetxk ztGM><{MejS(fNnX9aL}WAhfDRsD&gkFQdjUW-_z}95D#Iq-om-C2Cv?5Ww%(_lXBE z#ES+g9>4QWz_?#GVm0a;xuxR$Pz{b06MWv=ldyW=x{qp4@40aLk5_(BTv~+$NXC0s z0elMP0XfBH7#?G4u#sS*lHZyR%<%JN*ze5<9HpqT`5of_LSWFhxNCoJm< zSK}9QIl5XswQT}}ci{=v0@S5g2)TZ_Gj5J|SMPLBV%3rjWv5PaStPo0ad&Wr+VE!$ zorFz~JtO&oR}vS=9LYKGpXTJgxR*9U-Vp~!cJl;&&DLU&2y#O8mmzDMTEssjN{qR zWK|~xBNuHe+i>bM;$@XCSY^~&>MKcB-wfAk-%#1jO*yp=C!|;ML9oX38*Vp5A-?R?-m>xN6q{rpg&-MQ80eNR zU2_7V1ANC0Qy*~!YmT$$7RfjZE+~$Uvgex^W%wiHw(VWd5Va$kbUjIf6OEZRV^DV6 zy7<+@viDRwWqgfU$IuIXFZahQhNvG$k{hiz$reBv>{-P6x*E#HQj09TODBjEbaiPY z&uwaZTYFBu>?5ZVYFQ>iAGK% zk|N!cO4M+(I5$>OIgQ*IABjd=Ou=J0I*9rHHAYSR$G zyJ0GQi8JXt2YH*OdE0h!A#@-Vj$1Sf2z!uOAWIbkuWH(`x5+X=vWSU|JF(BE^C0XJ z&2&*XlRc6tS!e3bl1yBiOQvLRo8rUFluVJwW>Qmo{r=VIkf>emF$fyOHdiIc9Jg{+ zRg!F-hnb6jxHqofzwR?;>#pUWkjOvFny{fN!A!;#BPp@1vA?$YJD`j_-lnmkdAMYB zwB@_xayz)KRQ^=rjS=025_Jdr@P5O!;vWpxx&1bB83z&H^p!Uu^p9NIXqCAqx+RID zWbex%V@Ke22&6GPNxEVOW;wmh&mrFK-5V<5()+%viL7?io|a2F=Y1FJq{!K=#!2{~ zwfP&W9FQ5~l;Ey{paoUEo@h}W}=_6LlaidFnW6l(Zs52b+{)5Nn@k%^(u=d zamC(!;y3X!GcJ+4)U|eR-cE>QJ0f%fg|U#dWte>)(~O%FGS80_%3VBc-}Oa46bpvU z0GbYCw!^n@HzP@^+Zqee-aTvwTejWm_;f8i36NWbmhT>81|QPFmC~2Mr!xTLupN@6 zhPZGMvE@6fEW`5JD@tmE@3L>MN*>e7ey)NP;GQe_w>Ok9nx+jq05K~Fhsv0aZ7vyh zplTYSSDK*-I&jzl93uD@zK&5$_xIH8SfBCdH5I8*iF)E9E{rEAl^On;g|`psCOjaOp~9mGI*!iX zgQF}aWa)hM8MhQiw~8{z{Gw9)Rj7&5 z(4Az)xlOP7*+ww6Sev}p8z>g8(C`#cMJMtmX7$Ca43f%t6In)q;yl#!$r(;Bas+ru z`v+Na{yxk6`G~kid!(>8qbWUZJ@@rv5+CF@<78}JPf4ZgB8z3%YxK*IK`59-7!6;} zc`~Dk)WcreB>8=2esS!gK?Ci8J=Cl0wV8(xi>yVF`t_rFU?4bKVjOdiC~X|UmVdC3 z)i5$-%@5f{p!VqEut7C3`*Vy9=)zts)w-v6v#iF|D@Iif+;G#WGc`LVH;l*+4KRkl zaf$POZe95|90FZEuhG>wxM9S+2E<=ltB(aQ%f4dy#CiS_EB0wdnmLWJVC=6vAyR#E-En_q9w9OnZ~3?XOT z1N>s?+F7@P{TkM;ops;QFUjsIuS#*}6}ZP?t=U=c7BVYqkh7tTS8vZq=L1E&XkTx} z3M56G4RR9po*m?TKqxdGK#T={s0<9JIAa9@g3g9i9Ut#}U}Q8tCGeTNC$w57gc3r7 z0^RbpLM+}i91}p#QcZvtqcu#|cQC4A=HFnv5|}UXs?b^YKQy5#UhGq^EGTeK;@?r= ztZyMY@GZ%j&${Mp*u*Oioga9ZC!IRlUl0lo569gXj$0?m+qHcjXG1j~IYK|34}4R{ zuMrN#y{xPir_N^YbKWn^ncP4%zhb7**)W|{-kxmd1DU)8MCwh8EIJz|nh}AQS%Pr_ zo%0~{$$9@!LUT5amGW6dEgPzqux=qbXS`Bn^EM6pcGHsB9YMFZ=R3{^&LiGg2WyoE z-{`EHpkET4buF~Kz*+aWJlqQl+?VLC+Qp}_B1Lcrd9c);H5>6u-YFi1jjGsSim}4M zV&uI4enP!x$2uSIN-nWmRTXoix<;s9;5Mm;;}C3@;?ffLG}B7VLJ8doPTjY8vn|+a zrt?yz^UP#b+Lp`YNFryw03Xb(vIKYNVX_K~X@k}!o5LeBa8jz3;js!CqxiKW)x@^w ze&DnDB9s+)SCTNAlKv17_KaD|TT;q?8WWfUqP=RF>7v=I65Qnl?%V=*T7joU9f5_V z?6OJOi*#3hDx%^@&KWI6d9RW5v*23ol6#dwt4;J9udw+zBg~Y(W+zlx0~b?Al|?ho z!b4_()Y`*X{su4P$3S)9CFx&t@J^9v8N8Et0eFGdZv042!NGXrM?aT#w4m1UEXy5+ z3ej|lE)A3WHcOi9JG=o=DuK%g6D*l2&GD0kJ_S;I$USThM%}hPDa8&pw#q=D_^lgx zdbf)B6jFM%x)&WWk4=QYdg2~S(+anx_Qo>HMBFrx$GqfHsTJRZ_!!lDw}=NwU>CQlu9viigP+sh|K-nQW{%!nj-E zY8+_{ZWt1ZpB)-R__|=oqf|ay0&%V2zkMetWy#EVRekOMWNFXXpEb<=fp4KQ_Dr9V zX?1^&#{uW|cJJvW&IiOvud}W|z&?GEv+fPS-s$Nk&%%4UzFc`PRTh9$}YPo4*qn&6lK%D{v18`Xb>4ff&LoGg;?L)o;fO;|-b^=WUA% zCRJXgLm!HS#^cHbMTyPJ0&-Yig z?spW?uXRRzqqAS@JX-=IDP?wGNVt78Zft>jFr-+xlbfdpzCr%Yw`jj)k+v)ee2qZ3 zRjSfiCoagmD$ZGlOd2ovqBy_{KEoxj{$2_}A-=%vETBlynA}_z=pn)8JGIef#o zeGmhNiMBO7(YDG&V{LWT*T@UQ=5FV9aluifE`hE8cOA&^{Hi9hF#VsI-+Aw2yhPCS zS18NhmCiH=rU%exMD-1n>Lz0ql(2q72&S~?y)qeJz1f!-j zUi}7xC}HmKU2}zpepGnqDs22Gm+pau@8HxnUft7|^t!)KnnY3vm8&5c8*z1i10iUL zQN;k5#zu|IalJ$BMRW4rM+IH+=xg6OZGw9`fH45sv>9BiXw;rB%$dU86(gYa=!q52AfX{S9aVugY4-x7P>Hp*;5X2Nz*tm6a#nedCsmS< zflvva#sPTne98N6*dAr@O;x3%Mi8a0{>GP4sJY|1FF40Bi24cF-zYP2XRo*$fzU#^pZ}84 zE(}G_pxN1LT&v%w>hcy-=dAGB$oU=RPbASR*8?q_EK~}A%UJL@;Op+hQG|!JG)o5$YpsO%$yubDLj=RltdevMYQuiT-o42W`b zfExlf6Ap`i+T_Nuo{`?3T&K5|u$nWMxmOpJRONCA2xgPQ>KQ@g^2(Ysi`};s(JjPz zaWHp2aWS6x7;;)Zw+=lLcQuWbB4LW7j%T}2atiQk&x`KfXKQj#DAn^6zxtQL`}Hg|@{5e~Ch3!#+f@`g0Con1RurlFAF&V{`3o4ueZdRVcXcq< z|CTPWc$WfYevxl&0d{Y13}avYZnluuZZ(UPQh1IOj;l(ps3_>INcj`O<)0J0Kn*s7 zD}5CUd=+zj6-B;^0=bgX{aJgIoBVTq&q^2LHDyhbPdknlW!)DR(f>Z}1XmrK23MhB zC%Jrn+3@)r+Ijas^gO?DvYh#}FIiu`=vT7eu6vv??+fCCnnhJyaL6qJ`vTr-u9@j6 zu33wx_rl7`k5FyLR@SqUQq8|D+&`X+xIi4V)R(Z-H#>%Zo1wt~hq26lLxUKYNm&tO z-2*eZM18s#H%wkYD)ZGBQDAo4@<}D3X9XsOtuWoaraLD>Z;;T-qoI0MJ~5X-i@*L3 z9^7+wg;_Apdf5q?!9~S5nK)nHI?I?81UUZ$&sd|yXALJR4cGbtYYsG|<{Aq&X2LL4 z4>Gish3(>=Gq(ua4JIrvJuIz5isPQ zmEH*HZ}m$v)~vb@t7mSBVAXEu{s}rXt0>UQBt-Wha-BL7_C<7nw1eDpw%=TomHHl8 zMix4mU-d2wT%!kz7>oES^4E(E;G#;wzF*tJzA8MD49(WDhF>Znfp2Dk^G~|{K5JEc7!wR>V%1=(U;ubu5CFMX90gtt zjWX{OQl0R?jr&eW=mXvSh5@{9uY{D?vR!y=c7=4q(Hi$lnZBRo@@o{?#O{M%-Z?dR zUy#z`d_R#Ct6xHsL+1fMyCE!Gv1z&nLtW}&ER zU1hrvReI3f8_};!sas@sl$EuK1ra7B`doljUkx(M!n$e+fC@~t#1GlIcHqKC>Hph zl>q?m)i}R&nDlg+*(W|LGfX1$Z2`P}hH77s3~3m)bzf%ap5TlS8wy=@HZF3& zw#x#^Ia#MFLUUC8#2FzLF1|K$4^ft-W8FhSI-9rEQF~SvzO}n%n(L~%u?rOSWSqqQ z#97Y(siwY`!o4pD8I4;vs}v$3GfWeQB6XOx*W8^fF#M9l(3okc%aKHpN$(cgOK-Zlx~Azt4&7Ng>zKpP{Xc~g^zvvygQ5*^}-3-$=$p9 zBeCquI2_=D?gj=e+o>*Dx_(cD>_hQjAyb1iDpl?$HP(IFsxqa%kVC0#r67A2|Jpm) zMLm8umojSGo#fu>IGK;-=dYiP6RXfx&(}g%SBf2JRYRJxvd84zXplA1mniC8hTb;# z5>s1vuX&pAO%r+5aE|1QlVABEY-i9^s{YnA3PC&j2=C?kJvbP5)KpxoUgx(gYNf_O zUQSf1{%S<5$lzVN>=SdVgJ4*(>|FhYN_9U@zm(gz%M{LjXSqJvgl)7U2c@w6T&(;6 zE+-!3pc0K*+2kMubpytn8H!G$cDDpMgMQ`*o*?&)J1;9i%1(VBM_-&Vublt0RNxP*imyBf-STl2oK zOy}GQRbFQEFYKv`y&hNDz4J>#%QV2M<8mReY0{hDV+@LE*e%@X4sdQMJdHWOLCs+h z3%lhA*T-55o6L3rmcQUd@99x1hj^Q!hH_hkl18q41c71vZQi8uS9?Yf_!a1jDOU6D z`fBvWnCRO}%QX7_mzOW2ZzExH$lfaB!n*dW(YNN*KSAHg-~UVKtF$nfBPjgIWlBrN)`&_wBLo%EJ}=Zg9+EHX821ksP_?@Ep4dCz7`64~&5s zuV`D0+6H6B9&g0_qPxquwwLn9Um0|dY7V$~b?_P!Y>!%0T&xW$>fc^|f%jjNw=zOn z(8__}lNPl4)SnMo6-lcwi^avLafz+>yB>pBW8=gQvt;4sD7_n(Elh!4nLj-;f3`Ay z*9FVP%nm%=Zg{YmwGnN7D64AVo~^7bm=RjWZ0Z(edWZbjE5$wn`?ESd4^m;QB&tt; z7pWuosJH2?S%+ycKGJ(pX~80yG$JjCN^XtN=g^h1Y=pJaO=DKW)T5MWN|Ss?_PnjZ zT;EvP$~v-N(MiNN8q5dteIGHNq=-j=mdsJ;wpT_Tl5HG9`h*1Rf>^Ftvx_lz&!vG6unewc$?*C(<`we@HH5e{G zqDKFa0?b~}hJ}Qm;Nou8L?xGiOGB^WTfR{Y1DryhYt;!U-vdw7OfW!Gf^pWJBDGoj(rxb8%7i#`lH z6kkiqvfw)>^BgrOE_aTZ*(-ndjy=v`qullqX)#Ecf=rRe!579+N}1X_tEz z?mD z;^Q)ltm3*XSFAJY=3#K)cfSEclhu5al92AIz(E-k`m?>nGAeH%o5@D@>!H4fji8(E%xk37gP#;a0P z7R6yRYb=j2ijT6u1x`afvd_4?Di;W6No8FbUbIK3&z`3K81XlDmN(zzz-uJss6Ev) zT5}fTGAm--otm+oeg(O_>gHgadYak8KFL@A5Ec9DpX9fQMRWKpxgV*2oKMl5ukV6p zRTgPx)*}+AnxqI>%I@>)R7I8OOR)LxVQ_MK{tXXt5bqM!=e=YuQAI_%Ut`?^)No?S z`hDujr5={96}M;Ua@~&5v%36iYZ)+AAwU!NN|nzi$ktV$W71oEkL={l_eeXx4UfDo z@T{4{{ffpR?o4*3_-3d2O4EFpKDdteiN5P51>~OAti)NjN2ZWj(R(#i6xdF{DP6vW zj&m=rePK7HvbEUgDfapWqEK;FE_+#drF~Ob@0mq%DCF`vru2hK67_>>!9RgYZh!v+sJ2`ZhAP=tnv(U%(_yGK_dzvLLp7-%RFbG4 zRNEOK{`#-R)h~(r51>koKsC``#Xr}JvtbO$#4GS6h;gubNfS(o5Y0JHQAq#lAh6N1#qB?c za%_a^Ku8PpfRMLyrA=a_7)_f^5-WN$BFdR@u%uMZn0r7z@^O$ex^Ex8L&t;#7$1CUVA9Pn$ab3(wV!MQ3@xaO(WCo(md_LcF`C&JTG8 z!R)r-TcLVK@G|F?+>mq2oKP^Ix3j#R4Nl|j3*Np6UddZ8Z@tLM>e>uXZ!ob@T-y$r zI>eKhn?F7Kc=adZiFQ|ua|`?Z0qM=bW9+at$`0$1i)DwUokh!rsTEy}um37Ca+Ko= zy@d!aRs-&XmZjbl+rqI-B{k5qVv0!}yBA(SOObkwofx-4{yaw!J0!b$I~+cSb0T-< z>SgmAo(TI)^D+R^7m9kFz6mf|)Z?V$;3HLx)m60UvBAD1V^>z(&k=-jKGnzBCtw(-i4FFVJSUuZ-mu-k+Bw{-N2d ziN=XmHSu{A&cRilZiEZ}kjLGlQ9JpP(#hzXfCatjjcfK-)a~|`+7Lm<+AJ*@g%@KgD2-a_l5F|vAEBdC-&-cYUbE# zjDh~SSEMx#srgH7&CAw?A;F8z4ZWx4<(QzVxy80FnAjInb3skL+%SprYN{x2kx@Ru z(!>>lR2|+RF@9xUtBX0Uhj%?EFJoqo5EI~uH@}W>nq7z(W=ET3K+U}fQk3V&(a>L& zqk+E^riH-H!-j=39<(4?y~zPKT;wK-gdPUgTgY8*_ntY+(P4{@A3#v>{rZFWJ3UYP zJ55xN^hLac{d-V4%|z*O6QxE1?oKD$U=z3x6swagtJ=Jlkst<_tlFemvAT@`sO|0r zooa5hK(VY7+0P4U6sw2ZFBCRLxxH9j%a*2}*(7YRPS%BEtgA>Hn?`iWGvH)R9XYMc zVT=={oXnkNXvtwN{6{p3^WNlo_J$2*m%z+R*xCO zrWka63=ag{oFE8+TJhq{(_^NgyeE=XTvFPkK>T4$0mDn4=(Rb8~6;E{eFaue0J`yyJk zi+R&*TG;X!qb0@$lWTmN`;DM=dQDcU`}0QYv|BLMUhN(+ZKdbFs+gPbtFZrqg^oez zi3!o*ZN|I7k09~4GiALh)m`jWgWNe@b+vm)f%_u)NYXNI*FxoltLK^ETjK~`$`X}g zyjA;t=tXuFWBD4)*DEqtf;eEC?;HIJzxGml+VHD0hTwmetf zLr0lJ6@4y!^N0>2oTz+Zq{Kpzom&R_?|gBFHzc3Ua_L~h>-gJ?)0-pbD7h#WS_y|C znG-KVPisFOe>6J9o8Y7UJ%?ePtoPc*Q+r?1pO7@{Q>s5V;(FojtxCc!K}oSH1hMcS zu1J3e%4y4>Vi*q(1*sZ8N%7{Vk53Lf`AijCc8~k5^d5|Yp5v@4x(|V6VEPieh#d?D zC8zd5lK?b&X((^W%5%7nln3^KU{1=K7jjmREj){`j+{PK&PNoal;z>`6?d@k_-zA= zk?t!A#-bC)@@%}FeQM>nu+I-pc1YpvgvhRqG2V&Ad*P`SL0QQc+Ko?*Hf)z(fRy%m z#w+Q2bpFQV#w2S)inYO&JI`~>OqhN;`}38*LTg$4Nrd5uJi@13;SuVs6>JF{CX8n2 zqW|@aXzz?;0bX1o`OW~oR}RNf7JElV+Xp6^w7Azk<@{Yo?7QqK7jhbxmQNBf$`%gM}g6nRZ=NpUpaC5F!T4jMLR(%Dh{qb&4S_PZ-mVr6%{e0V>AKgxc0JPXr^>|*J{Ko0#xh)(*vne@TFq^-*bgGfp0=?M%aDX*wI6(BX`YaQdjo%4)Kgum0KADCy0%*oUK%i zK~2KB;G#XR7dK<=k&AyV2PK>>SwdEhP>*waWwJi2WqofAybXTjKA=>|ou?e_vdbOI zIeVqZzT571XNSCJ;;U!C$6b+=aWI$;Kke`Y*?v&lxSDHj@La^T+45voh>ZPJ1Itc* zI#bL4lXqVBspb151y&8?mXAQnM@@)Ue>_d950+QmdQ)rsEy_Uz%*i~vis6l|Mitke z53Cm4uvQFIM-i(P#f^d9Gk3d(HJm>aiL?&FxCN8lV{o{X-bO&11rCixJuh)WYr>mQ zS(8{KlGG-h#$5jafvngC_pzZwa6|1fX^d=RVV;UsVpU~ju8g<@nhfFdt$C2uMl81f zJfkVh6ZVW%w@@g2z1e+bCsDQxKUhkZs>!J7jo>%}mG_3u0>l+&`jI-l-ku)FKC{}M zoujv>Not50f9fG=kB7 z?j97Pxn2EJgkx|Y<&_2hNTes>&z4j+9&vvbhVoM1JR}w$^bJP46v;+D@&CgwY>|1e zMdl6kRZR3%OhPZzSCQtcNcL5vNEvotMN(iXa~%gF4~e4^4ZMbE0T4-FjL&-r)z`pu z5(%RvKc0U|%pb_VEtel=!N#J#d_{UI?5vZmlk-pc@h9^(THOhWv=mqqx9}iOd{+50 zp2V#3tpb676ui-&cRy-Y&-CLviC%+0?{z}&Cp5yHdxp>|O6FL{&pYySNPgaypEu>_ z^&-_Y(&T#Or}|3LvdW+K49hCt%x;bEd~AWIp}`xe@#%gwiU`Wz*Er)}sc~MU#$;bf zN>=&fQsa~18Yk)+Cq-&}ykCufg|Pm8jeCXM{=c>H5b{03Z_J_)fIc zm?)Mz50@6#mC-qGtnAHqBiyO=(g!uINt(?an&VW*skgly7T>I}X{cFg$;1sKDyc6@ ztVAUZYVwRh-9Jgx+Swv}Dpzs*?#S4G-JSD-xIEL53({N?u`jrO2Kja6`l+}Z?Nwm_=lY}em>9f+3#^7m@r-P^Kx;qn2y?v^~`?h8AO*>rYSWDZz zyM)38l8IENE7FjNdp$eVbYp3I3E}NVt2|@(1!wb)6&7i!q}dnPcTj`13$Tu(;s!*d zphc(t8ivdPWKJNnuNW{dod`fm$~efIoi|4qGM458C_qt91t4zCWvy!2x*lPj2y-L4 zo!(UsErdKDgzuNCe)(W@jr<VbT0ji-d6lG`8#mo;SFZIgz#4?)lF3^Gnpu7j#9EyeI_!&nj%!cO%0AE5 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%0AS z{~`t*l3-~W(rszAvuS@P%ao`6BjL0rGxy9_LNC%3^L5IQ?B598**}dgj-=eJJtp8SU*JwNF=dzxLKk&;h`x1;OVv@SL-Sk z9t&0}Gt&t*Rn$oZ2f5 z;qqC_JGZMiN9M?pk-RNU^6cOid_=7t_40!P?s)tJUmqT&4M)^q?_`Yop-02_-|`J4 z_)R04Yjn6j^K<{$+;VsgvPJ2Ofe_swZVAfWFlBb-DWYd48jiSzMigB1+Z`>Nlj#;- zRztv@dW+aKP~3hRO^pa%8dQk-$y4*vN~b$8qo|!papHX3n;vf;4@bT3mReIZhE+sp z*NfvB-bKP4j-&l(+pp5HBG!cn=P?ga?8N6N-oOmO9gKbUV-mO=@^CyH<31F@LYxJ% z&=2?^(bLHFzIvYd4;i9V2Fols*vFk_18ouj*bC~5k?If)U3W7^6}%Skh1X9vlCp7R zS@O$qqA*@D;kNnUXf`B{TVvc8KmD{3Vac=J@=I2|i_7YZ=F9H#54n?o zs@Sr<6UF~T%^s^k5*gg$^5;P?I2kZKRW?FJSgINlCd}H!Ydm}6yLIO1_Cb`!Xr8}I zkBs_3uV((!?WY?HxcPWA+MjLsP;UVpYYihD$H-pK6)E|9bk1Re=2F}h4wpSf*bmu; zu*fI`gF<3z8*S_(r#P$hR!JF9r9Qew1yM;PKFJKi8UQrs0NVMbghj5gTWL5hMD~kl zAA#U}e~F+p1nfmiXYmf_x$;AdT8p(0B6)?q;XOi7d5HT{z#vHZlTPE}A|g9_Yqw|zq6;B*p#5)#AP@~Cer2QqbWAd5xq zxIk48_csW-jdxjzmO|R|uq}_(uPGCQ55sdov)}qz@j}eEMBRh0aZV+{zPP__qn<|1 z512Y*hywn*(h`T*_m;sFv<$u|f#dcavp#flaC~Gvu>eHoV+qemv?bJ3$0p&x3vXqN z4>iIZWzs%!RIbnrVhT!mzA!V&+TrDvvI+2Q#7+;8wz9D3_NzGadJO$Dv{?JVPuS@#aA&XlfoV zUi1PM)o6NGChqIZ(qwHGf>Gk3gTa0-JXe`}RXd?*<&(t%%s9x|@P}@;$%ySKyudfx zFMV#y$7}kd_%18Z7!>DKYcZ_}oJ>ak_#iq06DQsy1Eb|R%?jNo<8v5~!C<_&5uJ>G z<%pM@PPJmBf%@>}hpio;7woWoG~KKg=?v-@1I4Y537!E$oW5~Fg6Lzx^89H_uM&Jq zUkn$oS(S~|QYDq;0;pA=hd^?0N@2_h)!dA9D7HTw@dP1aOU0d&Ev z&Q+6{FQT*=?JeetH`(31zp=WuvA){BvwCZ@f9ux6JN*ZnYY+O^bXr~8{QVy`HXp2C zYQ_YxuOF=cVSVGl*Zr>_tlcND)&AEHZ`}g0`>X4JxP{y`cUiF4jDHN%CB|G~EWZVH zQ}_%IK6xp(6;hcKM7=27#-d+-oAM(DClx3c(69o3n?eP5c|8PXZF{Ng1lR50q{u0r zy~OLiFgxww^z;?Nt@$+@?!lhy83O!7sxSUi>>*wlq@4zhh@lJo@KrTCH+WUeLnPW2mQRE;CG3qU+emAPV zKoy(hG5(q#zYvrZ(^kJ&ld&1F80c9vaWcR;fWzY+bCx@TN2W@4LbLz1;k~HyABLn@ zF>)V<==^!&m+N%CQS~Qu-mtkw=iMF%GGQDvbUaeyt6KfRu(_^zi^CC?1sB!7;5c5V z`!9P(Cw~N|MM?d=tAaQ9dp$F(7y%ctMdHe=;bCi(uUNvlV!|u)wP+ zN_79_i}TfoiyC=#{Qt1`?(K2jMxN;W%}>E?M=Nq7QCB;TBYKzO#nv;r9Z|M(j+OD# zVmGB8lil3zrY__0cR#;hU4Q~!yiHPevODKY@+4xv01AadRiRKQ6uim~tC)(C!HCkI zj^Epz#b4HzNPG7N+|2*L)={brZmgwOUiJI;lg0V)Wc^Up3n_~_NMCj|pGX>2w*AIp zkk`AFp~gfVYhGJ4ozX{^u5;cX#V4bm=n+~ND!=eH+o-((B|A(NJ=YGW*h+h10J?6Ly zfxqM|dFW;O(yrQFGi^aLh-(+g30xEx$_eXST28+FFF7%LCapS=pIfY4iB-+i{~6`v z&ybUQkP`|+kDMSNc$J`#=|qJ^@lqkYw?)lODe4G?Eca1<;;C4YGO1;v(=t%I2B>bN zu%TGOF9-PYG$Q|YD7H4RgjxlMj#i?Z5O0Ea$n875eW5J>TsuuyDRdzDw}Zxaw-MCJ zwB->wnzrCuHP0*3>TJD}HBXnk#8;V*+`WYx8wX?Zi+IW( zZ%$^fhbIe60_`?OXZ)U#ut{oNHdKuRd-?nnM$NGJB|%4vFxBi>3Cw5{>* z=&kat?oMzzN&F^yH6bKTq|3n1tZ{skPBC@jY@AGO$QfRRvR`_@RxMX&&K1QOxY|jk zLU#1kM@AQo*YwtP^1u&xAjQh_dgEHaMhx}uVrK#$H($D_$`Io|UOQWT*A zB!!dG1G4!BfQ|K?lA_t=;jt6!IiDRrIY3x0I)v4Yjl_6<2-@K{F8mGOj7R%^-V9x* z)UUK$fhY%zL>*unA+jEJ6+||zb)Ag0ZGi(`zbVuOd~qVF-b>;f=0Pp}uqFT<*`B+| zRVUmMo8pJg&H4F$_bGQEFTp-Ge49;=AK*Io*N4yk%6mrjV+^#?Gzk@f1KuFo| zcX#uXh56%OpFG|hE{C@9n$2^`598N|X6<9;Sn*8~_( zbUI&H=74U6{t^s=C+pQ1_$hX(J(+njlqXQkYj0Jnl^Jyrc%Pq~*8>kE3Z))})0>#04_=-9c(+^ht4uzX+1)YYQq+RUet zeSvNp(E&IZDTCIni-LBeDTtmo(>HE|y?_>cUWS{S>n|+$=sBXA++3(am14>tB$JV5 z>`p}sYzAJEI>v`$5<^p6U^uH36t;_5H=u|TI2nk<*hd)D14mc@*jd6u`x<$?>9TZE zqz8+mX*bqK8As_=Mz_AamC1MkKH{gNCk7lUdgEWSDYo5|L;b6p%}u{6n#8etD6*cz zm`LlUT3j)1eGE<42{FQjl0I1ocM`MZ(g=t#RaiTjnmRiMA5!>PIXIrxa0gX(`4uAn z#t6#9<8b#>Q$!glXVZB!nzC+a8n5jN#cgS8_&rdB#QpB`Zxr?NYi04UDJ;BO}VWKXY>oJqQqrm9X5WD@ubu>7M+lk`t4MXwOJ zt0C5t%>@O_BTDdh*yu&FI4W^m3Rg^qTRvA|o}$GYCriY~)&Tg&D;maD!g)a5yeY9r zX05mD?{||ufBBw6Bkh>tDHA#fMOZCm07N?s7Bxx>^h*7fO|^GSFsDNzlNpV)RlONf zU{?Z&ICk(1mh@F{49&XK35Bumfu$5Mia&o3{QNQ_)K3{l&bjibn@>wuA5EE%8&FBBzH$l)I0kAEe`#j&u4Go z3?!J?7CQy#N%&J2v-uvfL`|hzajN>0OxSz&RXIid)8WYreOQsWAnEnw2trVfD&_th`2D8c6+3947$sgjT2&gP(PUYsx{77fiyv>)nQkxHd z8?Su=!7oX#7EzizY`Owbz71773cng{rFpX_qO%lt2-Q{m73^N+pS(3!={+^-_M3`&d!$xV zUr^O$Ak{@ntQ#rN640nWn;M1B4>ZL5ppOkcA%j}Q}d}FtdisGLSj{1h=5wfgNl1QFAruXqqN>E=O1M; zIsAC~T32)A3N8t$2O>{!IE2m3Y7P6zlwM8N9*w5GQR1^Ui!23?PseJ@N=WB#GMr|W zVT~`Lbf|K2_o~2x!YPVc$|hG>p=ffYixImN<~g;)CG; zn@r>eXC_##plTp6PUJSAfEEWtI<(SzEroXjR=YqS?93<)67IxdWHw1R|y~%#wGXyIg zqjm|=s@2PstIlwH$h{+i zNVm>P^wY`nD$FyUQaz#QffZb@bo<1r-5N)%>!iw!NJTV9=5-aoB!2yl~_-LDLn$aqv~t^5Aj*^(zUB*Sa^^za+r z8OgMqDfk55l?l8#>T5G-O3xx`1c712x%K3EKF|D2dI(or@DS2YauGh$?%XM^&_F`I zonp|^`!T)4i<>x(t=wTUV}fiSF-~Mv614Fo7Vhdyd0)m{{gP?ITo!^h-d_ayG}Q6!Z-O78f@eJ z<44ma-0z!s@A;*~KyvlkB(woednhWLi3s46CLjX16y4+UT5`mM5n{iU86uF&;nO*( zsIb!V5ucVy9I9*~-?DBNzyM6su-04{iDk2Gw2Lg!nNSv=KI9;mbYp*b#$O~d>L&y=MtQp2!pe9ch z90F&HYRyWMY-o9+Sv7}-adYs}@>1OA?h0{-=%gucVIwL*d|b|PtP6XFk=yb(YglWD z`Y}BzzTU`6ft3n(Fd9$YI#4r+3RU7|;5h82cvXYSE9U$0I{=18U`lF|)ILi|MX@I~ zBpGXyZVASvxZby1U1^GhG$9Q-yOK_24{Rn2iRF-_X_|inEH@#B6(| z!3IH*l|$B2AaBguOZ-*rN`hn%tN6APTB%VW%CZ0hW(~~Kd5lu)Ay86`)D(aetd)U! zYhfzoCk^p87=!WWutRkoAr8FWFxen1@S`2T`hDOO<6z#V91ALe4$#Gy2qlwSwGu;C z1V*ST_8t*=)pdC(`$>$5Bar=J+XG*J1B~urb!1@>_EJZAH1((rP=Afq1AnjDz(^%d zKDRHv@yRWzTlg?JlByNw=(>B6;o)GpI%MA--1G5O7JlRCT?YwKBNE=%!|oBiYJBan zTe>}vpw!-Ou@Ax~2P`D+(}J*gQynbZd~Aj&iE(qJZK)Txet7hB@7WKBChZTo#R{OC z5`M&Y+t&xLB;P`ZdE!NjL=DcHtC{+eg4lpU35Ems9S!f9c|v4Dy$t&So!KW3cMor@ z-^CUr=UWRkW`GI8)}jkb+oK@hc!c6sr+K}c5ZlB}G|9GbH%_fxe$*&%TP21VF5Q?rwvV+XDv1vh_C_C?<(M=wfg?1v40)Md=-N>QjGt&&~u0)9hfADk&ofMx{kR zYRAhY((1-pD_IOr*p!I5wbusW6j8QuNrZ~CE*%;)Ro`|ap$|Kbi?L#*s>p|LMa?x% zS0cL?$Ka(x#T>s`;*(grYo6u-GjRLH8WTO}Unv&^eje9aY215ekoc~c z6`>m+I`~t%kmny62Ph9I-RbHVO;a1ObCz?Z+)2R;*jvJ#8U(8KgQ`}Lz+}W^BNbal zEnMCOi#S|LGQo;2el!5&Z#A^c)m0ZpcaBhkB`d6!}VSV7YF zinD$F6qL1TXU}k<^G(}1{;ojyZ{VSJtQlFUv$NK)tVBn`5GbI%X0~ZUn(XTnSipHx#8KZn% zffk<7^g&8!DojHq5H0ES(UmLLJ3S(B>)hBZtQvbOV=tXnOB}M!ahi@x8!++FuN%)2 zw5j2)Z9A_KI#jWSEN5~zqQ0x1n2B16)``L)f7Q%L?|dK=LZSg2Mfg1QF3Jmq)lZpk<=!s zyH?5v%AX98(A7(fg~Nt+zrto4u7}BV_r*&X8}sG)S>GV)aB(FoMG5$&U~&Y4OE7ub zYzM*LuR*x1Q@Pd}2bo^hk>&6)p7pq~ew&gGhvur@28a9KD!)0XuT6Q~E4ZwSM4$Y2 zE~U9`pAIx!xxsbm%c-g<4E5xEG)~vqN-D4@Uv*o_JKX^K$j(WWp(>BKOo=of3>WhE z3Tbw*XN=1aqMQx7gHGiB#WDz=RTc4`m_+P)DK{Tvu%lJd_Ay!xj*6``rP>?FPWPB#&}ipH;I7o zITfVI6MqWRpO7xrqzFGCmpTq$7ph*b>#WmqDkW@V8|%Y+4!dw80Hq3A_1@j*I5QX! z9~-^Obf{%pLuA2_6!MC^Q>anf(JT6Rb3KY2%4P#sDkMb&Nm>Ioj!BB7$r#SFgoIt{*$Ewb}>Th^b%Qc?!Q5 z6Qxa{N8LdEmCCw^L~nQR3pwJvzukGUzxVjj!!`n@6#3N0YaF3~3rRYjBWTF(*6=k_ zQ7t9=d?acfm#{KWN&v)7C1?64KJQVC z#CI+VmB=j>$Czf$hX*8^X;V93%4JPG)l31TP?Ux`Pzr7`m6&2l$fIS=!DSk$?Xi~X zBJ$w5y$m1`2d`e?Y5C}rk+14G6OR?*6uMcDoIVOx1w1Hn&NK+%S2-$f(vgYz?E@<$ z$gOwrAgX)hXgGb`g}J%z{zY*edOL)hVXj0WRgD~NsoBKZkI%!cmkN7Kg)>t-a;Ys6 z37tj{tF^UZ_TLp3mv=Lj`3PJoKUs)|m9rEn z6YHFzcMwDIWnk52EFbqpjOC;8j^f0wt}lxlpk9kW>OFb4bu%I^>Iz$mzJ#;C--!?8tpSxR^{Tin!j&QDJG;Sf=-+Xz&| zt=;ix`);q#!+IHq4H8Th7fYMBIEH|gGp1@(G`pQADX4kxBHw=Fa7ybfsS!pv)DgPS z6@pQr{&n`Ob_U(=J5s-~Qc@d>lbPHHck>>C?C_)k_>Rg(9L8pZkdZr!fC57!aT$G# z^MfKaX3WvuAAnQ$gk}oPYz?3VUv}!m$t}`}H%X@ptkB~P?az#vNOoy`kko-nUHTZt zO{u%$$O)Fhq60T^lc+snM_qutPR=$sOVy!xtDcdN9tlR<@##-YSYprUa+6ahjj;lt z3sM28Ze;Ud81ZNO$uJC1l)Z$Ef>)PtCoMLL-YspWj@iz2_1V5wwRD=9f?V9(l4O+H z9!sXi$5aq}k_7?sia$YS78@3DVQ|%EI=2KNRhd`DGn1qb4{jCRR|`weMf)`OdZ5W{ z4>|n*&<^>nvN_@R?@Q4Un-%YintD=|S ztw0bO!IL@o1!5vqs=}_8!}hsumbVF=xk_~r)+4)bm(weB6PvE;iUtR>2YVVJ91n4? zZ(p|uzg%1VO3i{}nXU8lNjHm`=}18lmB^4_jmWrcI&G<7YnoMmbmJf{y*h`)7m#W^ zJ;J3$tqGz2OzNd0K?oe=1 z49r)EaG5U`?qG(<{PbaDv+;;e$4DZ` zJSRZM=0uc5jHP=yvvw|w)_c+yu0WC+bCrZ6LmRTh2H2Elw&2(8fu?|7=gSVZ*$C~s zw_;Ur5xIapP9qWtx?!#vW4sDPP$RXJonGh-&Bl?oH|VVI45U1V-?c{zC`QTL7jIs^ zPEcqo{s1)7UNZmSI>b&UuDh}}Wb+kTrby!*g#yt7@ba1W(WYsOAqBEcVNF=w9)tabwQJ}~uEX#Z#ORGjUgus4V6j+B+s6Aiy~iKT z-er7*rX!MJ{jF&~TMdd16H+Jv%;cIcmw3K79!PVpioJ5)TpCUeDEbrf!Bc?v)D1Yu zZ>Q~wolB92DWmJ2f|iM&kvxGS~N3k}){y*rXVwGXnd-|aA zW-rH3xVQ|aV*}f87UvVW?wvn>@x>inuXJaf(yk^5rc_VQ^|6DFLRT_c!j#K0jCN&> zya#8RzG(*I{HZrUm&P4;LD>Z9SC){v2QR(8rex%&Tg5k$rP7zZdB&7WbuN+@LEZ%t zVTLc^_!yI8f!Mt+1AQ~|J%gTu*C0#q%f38kE_T7MTA}XQ>yte34-1PyQv2jT0v*1y zMECWysLw~E3QcLP66IDJut+Ce6ft8Uj4AEz`ogtEbtTxEYZ>n6sr^9tXQ>}$xJQ!; ziWNQL=lSlpUc}F>#WoWdLx)`g+l6tmmMbngZh0-r%*;j~j$piwDC)5dR=1CR;S2CI zQAfH7Q{wdU?R<9rCMWq-!f3w`P@;LIjzh2mR7N#4L{KO$E)f-LnL>$*(_{b-XW{WG z1_xdL)7I_ld`Jtw@9FP5{+lm9UdIzz{+lmZUB^>E*F9tvsn+RtCzB(FjoSF^M-y&a z*WI>)k<4H+%hi{7J+t}&vi*6c#vd%*o;YS%r5lHqIfIoA?8>FnU`Xn~irZx^bz`ZI z=T(QCFjFEqtw1YTBZ8LH0jXjTb{quPM;t%QhZew+>fcX6+g&CJW zZ9LnC)BmFxbA)Z%OM8o(ckX_Eckn+v%dE~x_sJ)DB`QBhdIaA7fFvI)ujzD?S?65V_oMgo}N~>H33Rv4Z0ZM07d;7jamw8oRvhGB4WeTqXaX>_U8|u(1ZV z%#fYO5ciyL8{>)6qF7}E;F6Ef{(f+)=+-%|T`CUDR1{x(a(a0CT0@8Tyu4~8T?-UO zDNBg?D_ZUa%!z7dfd%0@d^>x;gCx?J8JxhRTW12tQFCd4swTG-!>_1blnFky2P+Am z?YXsufHCyF+aQ*O*j*@}=G$O8FKLKFgY@^#oN{XgVb9UXlT>u-<7~=MQPYH}nop_1 z&J~bwBUHb9#{Q@FfY=bw;9L}wtL=s(7_mGA03S$S0t@NHAg1oQOi2OE6uOdv-nOdV zXL_9(4^_l;0I_v@YbZ59{cfi?-3cA?;X^3Y?%_^mmTu1gv7*;7wW)V=&4Xa$>ARZZ zp@9#)O>DNMPYrKPi&h~a)pFfqTovFf_Mm5;jFI~?j4{BMq9AN!75|?;7y3_U5lgP!N_LS zp!6lDzoHg^E((&^+OR(zrHa(Oy83j;n)*~T!X8G(QM^lm^qY#HYfg>D*!K4K`e7WLlj!{skT$5{>c35=PH2Ycqcn$SJ)s z6`7tU+k>Yq+_$z-m{JI*NqB$VTzmf(v|Pt`Ij6_$!Xr9e<`)R1fqyp4;k2{_JTw(Q z%#Jr;s{syficIm^+?l5cz$DM!;boyvIPo$Z!9rS!G6X!Zt>Ac;aHOK~(XO{yR|zYR zHh~xY9Oskiso=0fC9RyWN$vcb9qu@P*%WirrQ1_9tgCP_;Ep%pCWmUQMQQfx_Ln_n z^oMI38(TLwuWj<4!L@7G?p(WuxFg%Ei+peB3Ed{pJCwv z0N=Uiu{mZiNL>?Q^7`r7^yDMRKtoAdrCmlfcw1pMjBD;@$OgHE{kbmSo znKS(5WKJj%Bu#}{1YD&YT8=tlu%$WFhaMGV@%+p|Vc5YCwM8 z@Up1=a2kNBNDN_%Nrleszj<1j^#`?}-$`ZUdC^3)g%NhaCv6-*=Y+WD@g>7ogWcu~ z$(k`AdnGKO7ie?2OsyI*s9m?wd+-8>UgNBbv{j@3Te0eia#NzpcvUI%sQ@=d%0HT^8u(Fucr3%RJ+SlV%mK>86`e@ zinpo24|3rcJg2jKeZNxlC}|>w(97VCh)U+7T@y5}Y(xHFx8 zt-Z13lb{%2(gJB?D;rW-Wn5@YeWSKny&Gwp#^}}Qrmac%nj0q(S(8;#+~hsvYm(4h z7A-f9($n_+%w|19Vub<^ z$&Ds9Mi^&Zc1w$FZd5DTHk(?k zu_`iCwc>kyojGENEC1&bn`|ZQHh5dA@TdV=;vk@q7LZ?3^A+>hyB}%w6om*_`|%j9 zyECN1MxHGT#_N5d^-=@6LB;6uF2vA1X6mxD&n#7Yi(l()kLZ)~NXdKb(=g2mS(vBr z;zz#;eE_y{>S5{N=+lTnvUTfChbpQnvIo zpD99`6>(|A1O-u;#dck%{5Z!A(4(adoz)b> z@WCeN8*G|c4y}t@Vm$fgFYx>xk|4jCBJ==n%8lpzSVV+NElUB+g9-jt2C8E!8zmT> zmK8SrJrCjd4|Y8bX8E%g^6$s6)|G) zf|ynnN#&`FAzJ{@17Qw@|Eop5QT6f!EgD~jn04<#1zvW#wVs=CIsrT9%h@+$(ek^q zvyU%l&&unQoD&rd#&78_J(XB~cc!aDF4nOAN6aP2nt(gTA~h3fdW_sd_@LlfinwwU zKhG?tTcXUb8Vo82bGo9K#%%9na0P*JxK1aeha2Iz1%7!R_UO<_GnESYOKc&YEf_0k z3vrcLeLd8x-ymT<+)k0(Mh==;88D4A+)Drwv4$NhUE9KcZ}G4wIlE~<@fBY*fajAf zVN;5gnM&kvklnqLqb=SL4V~K#2VHxgQcbv3M=-(F2b8I;vBgpIOHNm%wJ`oh259R+3=1e2`blnA}iP8 zbdrr~`bsX>c`iayE;zTon~$&oGA;Zh8>gTo6^a>U+$QTfZn3oq>w5B6ka`FJ+KbDh z8+#oK%S6p>Nmcn996r-q^BSR??a7~+*!r_4f4LN50&~uCuWp<3m8qlGe)?eiB({%O zgT|}j1BeiC)E_!x(!u2F!WCFJiQdWTE}je&j4qK#Jem};(W-|=2oXt`BihJZ5R2v4 zsK_T1jScD^HrG-efcHvuPZzB4?PW16(z=2gL19|rF7ht2tl-(PrOJQ(4P-4G641tU zA;&w+#+UMB`-?H3`2G594$ENq;8y&G-GbG$U~ma*{`&rdTg7iw!z8d9yZ<%#Zn_vA zk1ev=Kp^sQ_FfAfVs3w4e9gn92e-Q40gqHMm>TcZj7)dkLm7N2mp?3K-9pj5i*}iH zV^)h;O}ok+&#^H)MJ83xveBBORrQ@Er4Ic;S?FvYts^MJG5mbinW`a0p(<(5=|$m) zacE-jDK8a-EgrH>n#`U@kZty+$a|$GR>i z+I&N}9b}eS)sq&BP}P^TzI2&V{mSd|F#%TSRIyl5 zfmjJ1NyvL3{b8dY%I1SxJ+0FGE2cfQ6w98%fFUKYC52tLiuw(}N*%|?Wfv4rfq zS+3#Tgl)4mIytd-QUVSNd+qsr@(#59`hW%zok;rA;sQ)(+)5)8?~*8FIjyE7O221oz8UhNOQ#Z=zXO%)7#ao&U|?Dc^1L(sxW4=RI}>SZ z%&+_?YRy6gSkzQ=n6+%2ModynKv=bOBFmVF0&g=5*qg%gv)&f8$e9{9UtOo-dWCa;1XkdOI4m7EOHhw&Q#%|>J#{h zBgq>FSJ1v)s=V>KKu`rE0B8bbZ!Q3N*hPK^TG9d#`SHq0OMtQRl#r`Tj&@4lzhGQ{ z1Ip|u!D{>dTAYYhIwd-B#y6D{JIvcf)3&|MNqdDyV|ijAXQW$*g4(Fm1t2mUkA9sV zn+ilO-M@;Usb>(NEdAQZhbsrz0dz`fJU~D@Ga0S#IXZH7j{_6VXfa_tu1cB@Fk!RvAn*m*Bl|$^3Nkq4yIb2(aqM!$> zXiVQonl5r&lNGptr9%M41R|a02P%e_spAB3lXwtYef{~JyAN)apH>h7CcGVY6s)Hv zw`_qpl<*VdFsC6*KxX=ocJ1M~uB?fxZaLR@9lCl!QoxC%ULw@gGeXz*@RZ0>-y_K= z4F^FwR$D&gei7~3%b&ZI(2}%pG9V_QBUSC?Cs43Ddn>{9b1dr7n&EL!F}00;paE+-+TS# z&DTdqf4=$p_5IgJcfL5f`}zGZfBnlZ2Rr+>@9*#4zIpHVor9Zq?(E&W`S9TW!<)Bn z@7}(D@TWiTA3WU6hF6Baf`yCYxPmT4awM6G@{7qNjW+eDV&P6gYMbKKI<+`W{HclN@O_Ymo8&9Aog=t`_%GkgHn+?rtgPQNRTShQx!)33Nlv`Q1wl# zDp&W#NE~8tJdHJHEITkVef^GFO0B8-*p>XBU|o9j5GmPBh^h`cm^;~)4zBvP=3+sq zwyUuVHE0yH3o!h?(ucBZy=B6^HVGPcbAMOI|_mh3aly&l)~ zYm0KR=CK{3QiSAKuEoI*3=)L@cJn4e3)Yd|d2;-5{UcJmt&2Irv*jbaQ3ORd8tM1t zaPc#aI~E9_T<6<$Gej}I#qCywz5W{U0q^C;8{GY{5qRTmvfP5y>vjgYt=HF|p~V~- z15PIh7m=eLNzIKLI@sAS@Bt{t249+Cfa(B7b`eh4A_7Wr9)WFY|@Fy ztXu+m(0PhjrMM5x82WTuWWN%%4^0YZtU(F$ArxA^5~;}3SapP*eUw=8Ix#xN{SZdE z5LqTV04;RCp-*|(QR$gf4%9&0_Jic_qg< z{Osg>NlL=#7Y!tbzI-OBw2tKqEk!>RTn0ATbvJytYC7I51~N z0cVdjbeX&YSBoFO;n0}Mv;b!Z4Htr|<>lIjW}9AqRB$1*QFT!=j7+X{9XZ$0Pfx8Elb1oMjr0Y(JjZgOn_I3fBbx{cbrq znJhnw0i}JN45x3-@wk^*Xy}Wzm~fx}d=~04LNnpCc65}{J6#+N@CzoH>Qph52B!;L z{*m@5m`#81t9vN*y|3Pka`8-ojp5t1S};Q4m2IYn?E1?ry{o zmx-e_>tps3CbU()h9Q940cRj~;fF<=!QCx9_>N3M@hm_gq7Z3sx9;8k6K=rZ&K#|H zNQC=)SqW9{;EnCIcTkQfqM>8hNSTR~DxBo)lp1JxUwRfcj4&0f7XFGWTL0uroexh} z9rV3&KjZ^X8=?#MJJ>tplnrp zAb7P(7aa3CTBGnM6iYrRl-!SRPG+wWxWhVltP-lvE=N7*n!>L-GS5z@{xzHmi(@6X zdTdI?lZ@t)eLq@_MZiqFB8P9s<7EOxO9naBk)Mst^*oPwXzIIEZGzi!5>q=NyUAy1 z(2X@C7*2;28#R)XKtAf29eb6bP>_&MB~@0T?95Zi%Qphs9y&uJIpi?NRX6X_94d6> z9b3Z4hj#W5bKI3L!1Ud9i^tk>mEbqtep{j2p`W(O67>&# zxhwT-K`Xjbu#kF7D`&U!(gkT#{>mtx44aE6=xw~8z zZ^koYx)CR5!wI6H6Z+w<3YH4&QlU9qKNjSt8_NT9U_0j^z{QW+@NY^28&>+rLuSII zgHUoidc0XNqE3+7ML5vbM3&q#8?t!K3b-`$Do}o)E`B+Jp-0d^3WW3njWr^vc5YUE zl;(V@oaWMfp@Frlr7SY_DzR18QH!h2hVuz`UKLzAD&&#{&)JpFF6lFuRoJMhN-(X{ zpLSvy7ByRYRxN7At33UeB}E>k=H-UHbG^bX51G+iXR$pP&OfaoEsoX+jIMe*JyJP4 z={F=c*HXPL#K+J)Z1I(ov?aeu){h>Ce;Bk1QfEDlM1WX{Zvg+M7iiA5zI*xT@uQdj zw~Av}_X~gwGmzn%k`g^XUJ3~qbbC=dEWvV+rOy*#ohLASe0Kcg_$d9ovpnJ7xJ`0+ zenz7~e&L7}JU*Udq33VcMF|BwZqSnipVg<#|AFWnc=Gyh0urIemxhx^y@hi4KL#xK6Z!^_r_W27wNw-w`J;rQrWR(=KAWJyIl zb4)rF;zH^xRP(9J2ES5^G*wOA%cc0T5}q2yCop9V!Ua!6x2AzJX%LTQJs2HVr&CrJ z2>C0}u;cf~xVXjddUPnq2n@#H%|iG&G}3{uG6+h|Hq~uKw6fO%p+#1;lg)VOOXNf} z&#DEY66eMi=hG#c4i7p4$nio6P5#l6-6MZohIRd^Ly(6l3HXV!jVChj7f6}Jr~t}+ zq{<$v;ex=)?4v-dv3NW~($=O>HAa7Vxk~mZ&9rKph?IA<97Vl`FzsHsYamjKUZWQ= z3%S^WwZVdnyfU4N- zVI4{g)M3|PdB9-<0SRwZkw4rtsn5 zE|r>9spDMnyG3~V!K%SzIKm}DS?vUw5rYFB;o3iwWx@k;Ab+rHpzrSiKMZgDvS=2b zXXkHM%W`8F+LCWh@H^ICB$xx84(ztNba^_NLaI+*pl76F7kKr1_xz~$9PEikewgbU zmTFCk8knISh|7GL_{us+w2A~47{|BJ&QLIdhBc%)%aO9)>+@rTZ6T57`5X>ynLmD3 zKG}uw`O|V|LCwB=G<7rh_+$nWP2W6cT-_6-l@PmiGDSCIAK?CnGvq%&|ANev+_gV_ zJ4ATc=n<}Q&yjQog=W;A0`JLl=MvS7G6`&q5J7QCr6;<0ITo&bmKnqE=ntfc0#>`T z={tl6O4l8~QsNGkwWQW|T}4yod+deOw$@ff<7&;R)cq;}_Npr+#;auB?hyhI6dCP& zC2+Qcj&=yP{G=6tO4FXf!%d~Lt-n5e_Sbt~+?J3__ssJ6kJcm`*{#UQ!U57FXzDh( zY*KEJPTXB@ioKxq9I~NWP~D>Kuok3Hu6)}(&FTwFlVK2aZeeeQmzcsHvr*f1aW$!6 zGc4HETp|O>2kxFHF{8RJ?qpS%()!QzXA|7La2c{OQ`(76kW$p)qhmMjrsMHw0a=rN z9|JAt>!!u4Acc?-+s5ctj7`_yu!TN+x%2YT?&C)fJDceAWGqMSTLsw(2Sv*=)1%|) zMuzNGd+Xl>E-I3e^0CCHrd(6ZpRJoA;tTzPT@lrv<_n19don!pEf)fxVV~ty&%cXy zA*}h$7_tw^SnObF7wb`XbM|T~5y=XZT_kPUGz!TP zD$dSa9*KZm_iqzlg6^=II&>~4y~O?kk@YGrr$Ku_-hLk@UOib?pnl}$p2>LqcbkjX zzi}#FUpNy|!zUuFIKHP*%@nnVEHst&P)+A;!chfM?@At~;Fsr`#brnHr2{gLV7VJe z9*7N1-K6;i9H`x1ERG+%4EtEyIuH(GvS5bbL7cFqFf{BM8OO^-D79~_LQiZ{M+zne z-5BIG+$&H$Fm6O$rN~Nk?b=39Exs{RMBOF?u%(vRR+Tik*Bm;#_vzukVT!_5Q)fwM z;XO>kc*wuLfjo^U2B{qcChdTb73 z4x>OK!@pUz(*+M$%1XG2wZKLgbx3vvl;XS`?rZ@A*3xfb?H8yUQi$ozxt)@opc`0@ zhvtBult?Q(BhkOH$2Fc=nFUIm%tYP7+X?Q8VlCkOZ*G|va7lA6(qu(Ue6nO3Hkgr# zcK8ThkNkxSFnmB3Ca+UXvAZjDe(5lsfVN1fA%WH`T`)FYXO=%vir^;k=u;G4;FE}f zRQ+-CH|K)OuM_MP!gZzr`h+9V`LO%tm_P$WG7`taK4;kNpdv8vdIw|}i_#)EM??aW zoL^2x5;z-D$T0)n0lnN% zRfRS+Y{2g8pXryx#92jfbTSN63AnQkrjhEUC|_k&RSpxPI>Yx`#GSg%k`;4xV+7(6 z9jHfU(xX|X%g5AMg`&@W9;-V z8qK3Tl%Os<#@2*V2wu~Ma-%SPcqS*BqJyM@8EL6Jo8gkAc+pibwTikl5%ch1)2BI6 zn}f2QR0T<7iz6Iynz&UcOdTkyL0C)qD*?jfN)Jg2xvkF{rFy%XMVhRYSIC3>3h{b3))V)1j3JT_hJq&1rX_U+^EF#a*j=0Q+SX3h zNV;^lZWgUJnkr4t>jMYm=wLfxf|bpaoFl-xr`_%a)(zD zDMM+1xa_D}8ojHBTPEaXM_nNo^s(@~o3@xTKP%xWv^x|yYaNn3F_ZMFQ||44U*aSK z`LYxt8lOytxCXUNY*l5+6z8h)lZNg8q<6{|+=f}X_*0C<^^?d+Y7Mz*07wgx`8FYUp%iA){mnH+@kdnrTS7;FVf6sog)1^t#=c+LQyt(9 zG_EyLstRKvi;hGnYa3Y@6_&iyNKFZcW}1eL;f?jzNzDvhiQ+}Z*Zz0r;Vz*Qoc2)J zo8k!h_`TOdz`nrrDYig^U>#|$Ns@4-bL(I>mucfL%;}Ph99b~AG!&hrwL;hsd@4Ka z$pTkG2}G83fn>*`M$xbpNY_f~x0Z%)$3r|Kv!bb6+*MQ8dMi7w)msGvqQ0`Z=z?O` zr1#-u_@r-Oke+RjaW67h9sTU$!#;!AC{@J!q6Pm@lkpPA(mx7<;;=pd<^#O#34Zq_ z{O@B9%KZV-jIrZFys$k`o@_fSDrB*k5MNq@t#~cYA^%qxZzeQjJ~mRhr8q&ZIMf4| z?D4L39}F%&c0n7@xB<4@CCoUfjODdy!V#hxa1mxX9vp>S1 z*|Bhf%hLcq!7hReLf^P9URR;-t?Ld+P@nq<)GntD-dQ+X!tTiKu^88&8lpbc7nizQLcC2T zFALhzDmP`u7Ws?y%zmqak(MB)eXRWR)KIxE5mIm9)W_tLKh2>ZDnsL-v(L1Cns{$s z>73%wQ|iFECaH#!%P1bLMvB0W^^?`V6ep{(5)W1dtXlFFvu9G9 z(lcFS(L2t%;-}1VC*&xNnSX3aF{A?a=VHi+B!*gqGqNyMkL%zi$NM_#hv0;!YAZee z#v1OCQqmD0ao+M20s*46xZyL!t>Cx14LFPma01%d^J}LLKs&j@#0yr2X;`gI*f;F( z0*-nNjc6?rVNGVHKcoFs#zD1ZO)fVK*M{u@V4S@J=*E02_P)bH_^rf-*unzUZ=uI& zkR-gO4t_c-g2!p%u6*xC{GtZ#E9j)f`w4Uf-Wo*w_F&WYT44eavt7lfJL92^giPD< zMWx?_mGbPX-@o?+PC0MF7YrAI;b*k6i?2z4E0wHnVI8G_BWY}AlN#(1R1bqHiXHw0 zCl)-f9oO1DNS%z_k4U;BR`ic7t_Bj-47bU{_nJlQjeqP2q~9mH{%Zbe3at=k(okv* z(7~y=)nmb>n1boV@rSPeE&(O~sm8aZw=nzUjh}X4J_mAplapMP7wfp#m-FJ7k zm3nQi)eCMrvWXO{k6pNX!E~djlXR+J10n~o6v;quIh-6&i zHx0^P)>6JO{2J_i#98g+$Tk^B)09$+u{8bQy=oNhrle#nMKUtnEHHhV8A z%DRP~mW(C-H`?&vuKHxj%J|jumeJo+5N4Va7;%_RAQ>XF8cVDsVm>Py=}7MxMXLDR z`)X)a;9h^sw}v!`RQM351>nIRrcl6+$KdvdYq#%zz|SQ@TqVL%nWV`j?W=qpB!e4- zaAzl;4~xp(EZ5p4LQ<&NTD%}>vLqeDH-#I7!h=VDs-j8<&rU{%%a3pyM*(8m6gc&c zcx6l4efaW=pT4+Hd0azYE|a3{YqZZZP8yC4Y>60;#H^5EhL&T5iou7D@!-ndxxhc$ zqQ_F9Y{Y@n*B*XL zB5t(*d>Yd`_w@xKunq|7tf2GWT3z8<#I0zZW}6VZ(I%&~exuF8vdzs0-wzs9ww-?D zBLh(wpe^{$`M1OQXb;cvVUdqAwD)ebk9&+FyG5)2XFQ)Bj>oc^Gx14~yW9_t5_0JO zA2wc$PiM<9UnAMvM!sg={ieaWN%u!`3})OLM&zoXI?||EHf&umiTD6jL8f~r_iEE+ z3OS2K8THinf7Pd_{gnxOjUc@|^p4tQXY@`ke10!*kYQphH$oSQ`4h0aZD{zcytWG3 z-2{#}7qWy^Y2dOXfWQ{o=i%W#fMctfe%>p79`2XF_wR4riO3+#dkifahkwSSOqwaUGUtMx@2_%_wGjz!# z8BmsRQ%pUKDyE*<+I{x)@Y&=2o#)R9p)b!H&<0l1!3zO4uZ%h)7=*@u`=V!qXs201tufi9;O;CwPLIMUgO%QifR%%2P(5&&EZUqR z9-5$t(`tX(jO}Y2Z3?69GFBaEi!lc-Ua@P*x~NK-lXzNo^O7wj*R36azI5r<5|=wq zuw@hOtr}u?_s_r$PG|gIsk*bwSD5(xX(znb^oNb!%A4(ZAU(N;5GOxb4s*-JqF7?~ zW=H2-tqfY2(e73KL@5fB7q=C_LFb;o53bX;sd#!a0u&fX9q3VI5|yQ8GOW!(NA>T% zx*KbI8uHD{Wdr{kmhZmZg68LEcxu~!Ka#uzsIYUsoXJ8m{djl|qX;qQ_*xjkTKB+` zGysC;Fz{guVqy+E+GY}0ngS+ZPA;L7nD{&Us->1~nmf+w^u0R16pj$`vk$MOK>b(d z_sBG?kK7BgM<)l-+(=k;T!c~$Tg>Z!xgLBO(DEW+g1T(NJBZuYm1t`nMY@L4LHRrG z^)EtLq15Qs(_-@)vvXu-TxCwzTH84!LUJZqp}zXAz$+4A)I6dKGH5o1#$Rh zvE};_y;){+7BqqP?bku`z|&IubmoN}mF)<51xF;WQdpiVa_1i9LVTk`T$Nv}=t`QU zo_I>sR+sGy^Qk}KSgivW3v;C4KvFN&XGu}bW3`|qNZ59p;tH8J&}W6XEaE*ho~v&m zoj1?O%?*%OfQ`)`tr0@!zrw}_&k+xP{MW6&{qYZjO^fi(6@ZBxfDfzJ$8!y=Ogvx> zlnH$FNKy%S_8wEAiV|W+K-yjfAPq;gKm~qM44A&4lQdEzK%gt?-GSTl9SjM^d@%{y zh%(Qx_e*oYBT2Pv6i?I7nPet-wZRU*-FdOU$7B^S&19DS6e_juaHLW(m8<8*VhL7o zr6uet5V?3mDtkTT*yENIBqa8jB<%E$L5>b;yHaEhDiSOa3lUM6-lDac>YDJX(~=!p zF05u5rCZCh4;OiZ6LAoe)-M-kI<;j73p|ossUTr)b=KMO;F1xwES7si&&pb`lgki0NKQDphvDGf4^- z^^9HG&M$ai5!Gw8ihG`D$d*PM0%+Uv?IeA7l79-{nBJzJo3CQ0N2{GP5Cf)j;2GDE zR*U($eiO6So%OS-_jWm6_1YIRtJieWna3_LQiof;$raeun|vz2di(#K46AeXTiNxp z3ukQ%>x5YAQs;{8lJBu|IbxK`Qq*q>9d3(|?o_Bqbs10#P2#I6IR;o=>ae=n9*EU+ ze<2Ohsea<(je%{2*g-)0FMJ(OHa{%5RK!#iLrLx%@zq!QYR!`{*5bk`{77H~lwQ5U z53gA3P59`_#DaOvyvl|KomOxX0{s?_B?ec{Hv@WsL#rF>%*`vA8T8Meak6V#t_EUMbR2sASY=Z~=!$&P-sZ+9h!sB?y+xT>5|2|>)^qlVXPc#>tt z_X={JU8SZ9#A0+tXkU^mZ_ZT$kA~B#zVsK|DnWw~GaDF=cR=Uy^axuuwumYFz>6M1 ztx}PUInFMu@*ol@iLwo4yBoQe;H6BT5Y2 zJj)Vl1B5i2tZf)Wt?K;sY-{&VonwHqi_W-PLu+L5(*fF&bPP?QdoqFW9B3yD#4zpGShJu!NQy!-6Q-pGpt+;sPb{co&5%NX3Up(zHE* z4nI5_9&z5_+Z>PZW%xn5dd9BD;7h0k z@NPP3=X;w3kcZLcSMfOMoat(T5LOsHAcHH2Guz?l7A6WR>Ph6p$6|k=iYCn-5@yK$ zK)@;vQLH6Imn%!=8>|h{xGv&iA`_&hsjtiGmC80K-~5Qgp!wHN3aq6UZ{zlh2SpO9 z*B02xm1S2o604_nBHncIBiusYU&H`<1-)SrRH4qEoKkKJpIUn*0cllFqm?*9EQ*E0Jn%?*T!kBt5WBr>b{L67lOvx9r&Z> zjT%S-;Dh7d*_fkJGGLH1-x*|^+BQxw!(r{=I9uN}|G&-=T!&vtp_{8nYh~-ynt_#y zTL=l7+(yLoMW{-|+|vHC$Cw9TgzHe)Hc7df+OGC{Q_>6Yk}77PHLA@)p#AlpN+r)Z z=tRG;N_a?l4b{Hda3Dv%%>nT0MbQzgtp`nyffR4mfZhq2R_Ow;dH zN7|RPy`XYQb*a7I9ZKOX`5=yhOSn+gr;BP7+`CS{2)*&0G4qc)v$53D@bQzxi6K#FMS32Do zr104Zr^*aJVBR#odkaTDI2_-&j@N}i}^nB3_ykg$sJuL z8PjVE&3Y@?(7?lx6|($jQC1quqr0{%NRS(66(DA)KUnd2Qv0X~ns-iL-5w4y>jTC= zZ20QB$>#;`e(5bz-WP|!hsd^|nK)LZ(O}P(m?11`t6C&UaF1Cf z!KqvN{u&;)c8@)kQ)gkP*czhx0X&IFyNk4`D=S~Ni{}V^hwajaZH1SIC0eNumJ}vf zrs6=?wu(yx2Vd9p_B^eqQ&=sHsvpxWTD>0KJH2Ws=5Pl)HiBHrrp=tT>~5G|FlyKF z;JbgrgCblF;!Qf;72)2IoyD7DVf8a|Iu()g^%`$9aBz-Kj_=cr3h@ijpLRyp z2PY`5ik6KR$RhjbR-6C-{l(jDqUU?4huxRWxDoz@3s0RvHb8d?*4@LZWn&My5cn-Fpx(CDZ^A z9Ra2a<4GExF_G=3hP0(>A(E~5)-Ws-S$lXXBCG|cL)_|<%b35c;S!RlG5z${FTa2e z(~C**Gp_tGD#o-(rg%Pw6j4@wX*p_q8K5O!yv63u&;m1Yi^ls>!8HnErq?opL8K(H zAv;BT69EScMLU-52PU#ugB51AxsXY!ryR@I@#KT9NRbtI?T{N6WvSRJ-7GYzI`3>1 z;-DJi0EX-dD>E3C(Nik+DiUL+zw63Eni+@!Yz|Na|FFB#Ir5Tt47jNW99{{rF8moy zr{s#zao#su{?K@kF*08AuQNVEf!(09oxjwM>2;4!u`a(Gzh{<%zy|dyAp>b);Uf@6 zYm2rFKuK%k?wf>Nb@Ziq@CEF>PmCz8lyxuiXSWl_Yz1w5-Vh*q9Ul>S(&{I4Qgo5> zO8QQ0*k?L+D8T2|V zv%fGf(6(W51_vFzr6nL|$`mSM&>H!SI!X;#Jv)AKeAJMhCkMM7TLpbfb??%Zm?}N9 zwABE{9O!S<^)v=OnM?$Uon;w0GhCjuyWe^F*t_S%qh3=*0O%ZR%Y2sHD0G3i!=#8$ z#;B}nJ08}UQSRp`p>)=ghE%2a@_aspe%v`Zae)G!Fc#)Rs!VB(Yxu<#F{>zLJ}9** z{G`zZ;cs$2C>8IS-#V;KA5Ks9#z)AXrU#}HYJ7U~-SYTLyjxJ2$Vqy2C>8@=Im%#) zsfce6=-t6jaHZW0*!+*+8hUkod;1j@?N`_75K~D@XH4oR)W*`Ax!MBe9(uqfx6mx2 z{BK}^+Ybe5+{ z&a;kKh`$b1oX*8e|ALAm<~Q?T<3{kb-?pM;(4i9Ctp1KCGL0*C3mk=^uiHgLW=f;d zc)tP+C_rd3GKD#B0-P~j#YVzcLdKXn^)CP77ICTs5}jtSuFdGE&#?3{*-4^Lkf5 zMIqEu#!fELq7!$D#!_PM-zzmh{g}t6Q<+ba?ZUks8sk0hIbs|08z`bk34C2nYi%>V zP1UsyT22?+gSX4&*;lu2Es$aQbch>l6RP6b@siJM-x}ea#}m4)Z=Ej0_`Y@b_U(Jj zohAlqXZ}X6Ov{r$1x)Xgu8>aa{pq{Od^Tm+Xs7JS7_ajd6*})M6{A-X?~#?F zrU^~O4&^`2(Cgu`Iq0AMG{d}scw7ss8kZIzP2s=W4iXe=)o=jO9|S;n*|At z#$A*O6r>5$u2P{O2qwST$%d-%tN|4UZGi$a>qWG6vjD3bpeqYjv@6i{0dmH>IDL%G*F;taya5$<8@ouvZD8b%k-P7UDNvDi~* zun*;tSyFWsWo!9NxF<4j`em0XGveHk*2ywBO8S>6ZH%$*t2@R{jmt7f5b897O#Sin zU7)^>L%uckJTd|nf`YH6unJ9J)f(U9WTLahqv_i*9^X~U7%cgR&VyIeKWr4Uix#ew zunXdRG^8a|>QW{af+*~&54Alk&Z6nEK-|4iNoK7HzZU1igIfjGok||Kasf}(?N-f* zdk!k{{zJx~=HNdmKXmQEGc{Din6kgkI>R2E)*0@L;*V9(}z+f=GUY*2^@k8x*cI74-^0`~lJC z_FN>~4JnhY@K92I4%1kmQW65m-nmJ7;z0C^*m(A5SG&|GNMq9v>iF=jh@$qrt{ zgG;M1bN)$=j)G=hDi)J@&9>Yl`EGId_MO}IE-jW=KJurj1zR=f=s`{)si(6lezyx- z1W#OS9L=_{Xqvqibv?G3DK$rS^I66H6S-(gkAWV9F1}&14gSXJfZ;EmP16@9wXh!@ z|ACu%8|V&OpyV&^aUxjv2yAnm%zxV!To_)&v2TocNO=t1lv9r&%;^})Ku>e^K`AJW zpg|*4#lPd-#}2@yYJD9(=;+VBws;sj+y1cI~b^;2m8tT^$`J7ql zzYz?t22v{E6sJpTE^)0OoW-~H5IBx0P+9Hc98>CxZJ=>E@BLIx^%^eUR3_}AG&Lpi zJO`sK?paxcObl<#0mz9vAS&-?Y~+Or#JA(}l| zIoL&P%rz!R*;ud2!#LC|$se#!&Ec7mV+75fA}p4GX7Bby?1E}huA=%XRnFJp*-;)v zMRk-}D{GaC4GN7K`zSQu*L;VQ(95sDyH;8i_?FUi`2~~XD9vQazbp%+40%x7{e{yXR~C~ zK8TaUr6>8$fY`_I~N*-uIKhRIlX0?vxwJv@u=*jC zmuq0M1tqQN%i-c@R^iI?Qozn zY@fq2NKD6osj{x`3e)CNi!HPLD5bVf+eb#=>(;Sa=X-Zv#Jr@m4JR9lGOPMxTtR?p zA~EE@+5dac!ZkRtv%ZguEn{F4#FJn1U61bXJ#wVTS5+ zfy=nLpDI-61Eu}q>z^2N=|2itGY3cqaAUsO``%)E zt79!bts1QHUu|O*L&kKp>@Zy-!7B`*ZPwVtlL#<7QN=2_aQ&r4fF2+XG8}n#mC@M7 zx~kMdyQ=bucvnywh}ZU5;?}eWHV)BQOkX$uQV}p~CrG-v;VRkFl_&L}Mukh5hA=EY zu3`<-(uAPq89#74R`}D(%_}ob!%MOu8`R0dTe$bh)&M4(_FGp56Iz~@LE69qh&R?9 zG>`XiKtDc7=Xywwb^S4#gO~8{YyN{(m4B`ON<4z~gEFR5Xc#@J>=#>2f*9)t?>ej- z1ikBZI_Q6fhch7?tRJ8!wo#`TSIt%yFOF6fpG;n3dC|oe1A>i{H~H0s+j5v@`~f}n zSRdE%KSZ<6=CD(?2VA*q&^Nypj6FvJ#^yCYVr)oYfc)9L>}95Z=uMq1F7fN@*~Hl% zd^>sbmZ@BXqU-A~ajVc-vE_KF`$n8qv91^&<<8TX0>ai;GURByR_nGMh+NWUO|Uaj z=&s^_tgk+Ux=YElDa0zA&B!ck@B!17x}rOqZe+A#W5}531ts}4%)E{gb_@aLd}fq6^X393R4;ks}O zY4w?958-?z9pu!*>e-qk8soB4bMI0KwpZJq&u8+ zI9=!nOIIzZ8o8vD{G6XAT4_>Po?QV z!ii5%?uK@8Dj*=!I>zmki*@1<=EA~WKAY)kMCggn=3lNYlGH(bdCP$^8O(r;ly%me zGfHZjF8b`vQpA1y>C_pSH00{8qMq zAWlZuedEQ;8F@FaIUThjod%s7mwQF%LO)f~HZB**hGE|{)AbbsJe6beq>C7?SC6*t zY;kge-6Lpk5B^m+Krv8GZ3-sRxjtuHql&avXO34I*QJFdX&UCkjAJddKtt%3B=0{7 z8Q;^Rd?`Ar3-wa8>RUcQB!%Ks8a&Y7u3G-%Iu0!DQ@?6SM^OsK310VBNjh@ zomPOWm}GQbpsiqUCPf;O?{qbgf91I&j5{o&X)V6+%n|kBJN-S+8!Z;h{I^^I^>A%3 z#k+{(mc}OQ@LxLe`1dhHe&4r${BWd!(0T!`;Vx#)SOYcK?tdIj4W%#q(1 z=%D3f&h!xMKu=#F$#LNXafECG%C3T}#gc0f(Ih#hfdfO2%!>`*O6`_oGS5Z6yo}$>EW^da%T9;+K+d5 zv)~umscjFwk#{b!G5Yn!+K+c*2|Pobuyw92P)bM}#7lVM&-RIwRtN{(GF?QZwssRc z5I=FRpg)F41w`ORNtY1tV0>yq503b1(*B|Wvs#3#wSaNs+>hKYKJkP0iZcaZ=JtXq z&L1{z4-rOnWK>d0sD2HVBI@$D?2~vU8!V2i%P>_yif#J@7Xs`}umS#GBI0bHlVaUoLx9G^ zY04hO->`cmba4ZXKut}5hQD)!+zB#irY4$^;4wZm8*<7BNki`zk_=%Wo1g??JUu_{ zwgsaq=&A_TG8wUAMrJ~a6)8B!$eHBC;}dw@L+Ew6C0?;2k@cxW(YNE1GgzWaSmE1) z+pDw<8wP!o;iTPVis=k&9U?ukZ<0Ni0LlTN%H9~TM6Bt!6aYtc#Jo!S(Ii;8+}`I4 zN~$}#NrOBL^A3i``cTo+gy8V~1kbh#p6UZ5stfr@6+8G*LLUEyiwLSn6!m~Zcdio- z`+*IbIAAkKQBi4-jwlbrKz~??q9a*s=}$M- z@gw=FwWRP$6aDWQFX{@z)Z2)=XtdSI6H<*AKjOpRA`^7iE*+Cp>?6L9)GFnyZb5&A zxhf!1e&QVI-&o<|G&D3*OD5A4s(N%eY))d|Sjwron34L_PK8UqLpGzM#IqsbaU)Q$ zgndWnp-gd}A2)uzxq*B)5u4nOOw+utV$Wi78whsip(3!JR*lys zyr6e-F9q3VxLLQJj0y`&?S?fAHxjTeA)U%{u}&MFza?OK{Yb7$PX1l8X00!0O#Hhp zleKjUutVLU8+WRw(a?QB7s2)*efoBY$JM4e z?O1SKN{ZU@z&EY6m%>xy;2KpM!dqV zes#Y7GYN3PB>!0@`2Q4fZ8+x&p)D6{S5T^BgR$lgv80X)``;?6HRLdoJy)7}tJd05 zhgJLU;5jWuAUo&jlIqgCR`eTA@&aow4;$*jftQsqYL@XBJ!Wb4o)#F2qwDXnIP~I` z)PJMvimWZyYk~bL4rxW=v{@w8#0DYxC{oqmn^y|AdodcG!6k=$$uIxx48hj$#aPUi z?#Kd{h5c^k7uvoZSA=@Zi~g0G{ktwb+)ISX7Hw0;9xYys|JON!weU=%SOGpF-$1UL z@446;#NN05PJEe8L48Ln_Z8HppG20P{^HgLoN;}R(Jc!T5S6gviaW&Nu|c^cs_!^L8J`ugPK z_UYniHb-ov2n2N?jvmd=w^*K!CNsKk%Ul-b?K?u2jN6~1*pp)D2lo;lF^5Jdwe+(J zJ6>^|j^A6Nu3wPmXu{l(5($WG$dZWTF49#k-oh!!L7)WR!CmLWll4PI5FN43C@WCb z(XH-syxy&h0mNNG<(nA@YhX7KhameFjRg)`X7CF0`E`ZaLAsX z7?12H0=DqT3_@mEc8HAjV_YtlAD-ob1x#SWf4^H!PA1Eba+;)loeZaM&T+ymeVocuK=La1^(1iD-3hWbcDhOD0RQl z#`~Y)YV}DZ$!~w2lDi$wPR@A+M=OCp2*vn3!jR-|5eD+7_^GW`*Th@~f(vkLPx&s9 z2mn}lLu**`U7np>JeVU^YYssGTr>`8-ojp5tG6T$q9B4a);eM2j5zszhG~NqE8~&ngoFvz-Sg;|;TfJxL~soL zHQQ+K+3ru@y?9LRdWek7d>vtd=MmmamT%8r^YT3QhLVZU|GkOb+xXV|$-}x z=I{gsXIpqk&i?u7i~G1R&dL*ntjNY?ZE_E<&dHdh-tctv#eM%N^*`LZE2gIcx_Ohw zYi7I)1nRBt?LU99zq|8te{byr+9qJ$+poQ&ToS>a!Ew0l(cvi`G)qqp;ZNPl z;UmV@+Z&^FMw5B$@k}?B_~i7YNlz=fXI^B-uRIjtTyk2l@jRIv$(bZt%cXnx=loA> zG^cofkl)Wf^56Z_*I-HfaR5u7|LR^e=Z5AtKIB4=-W5eU@ zh&;;Fne4#V=e}r@T_28eo>OnOb%A|_gnRe zbu^vg!p(1&yWV+`ZYmR}!$7~wSorkIN{anXibF;uiUaSygI|}kBe8Rm=yitYLHa8U zK> zn1BwR!Y+L`el|T3+w;kAildE@{k*7q@>Hc0JJbv+vCV?3*_s=)mBYhcZ>&^b4G5dD z*>e1LhFckzn*2(;tOmXqbLYnKT|zuQg$xV00+;7!e{Utig9rEwE-{ECBo&=FI5{=B zaBCn8%ntuCn)rBlezNrQlgI+yZ!Ex^dm*iG)?S(^n zJXtQ)G4fEnU8@JQoPRu>(ivJh{cNVugtZCL{DJ=f*p9$Usv!n z^b-SJTtcnccBRt&{ZLPatJV~{{7TvuJim*~cjhFMUAg{Wxi=r|`QwP`^*&H3f3+tQ z`E6e$;qY)D5gYkG6}VIh;VS)=J{+B#kH#tAt3YQ8oA6wC6WIgA)1PoypmwechabP= zPV>*j$CKG`c`&5ik};`V6N3X*I)qdBC|0WmMaVBFr(<5zIkig?#Mz9#0)FlMK&3M> z#sII#%Rg96C(q}zBV<6E&220!P^Y zvI1nb4-LID9qlF!jj?xt;0lFmRKRfBbSla5$8#zQvCZL4MV2P`V<$_}LwnP_O%et~ zcPk=%VJ>2w)Y;HFpwi@cEaoGsJi$95r^AyMU^}>1wMJ{`9dw@Weyg=#oMZ7h9Y-3x zc=_^C9!ZmRp3WZP&hB`AIK~^!2uzaZ3NSN`)1pJNXQz{;Eg=}}d^i`Q-}nJ~B{%Fg zRi+sq;&t#`u^OI3!d)G1{|#JK>BSgPEZB39{4)9YFou)f2;$AER$Sp6U`Dg9^md52 zu<-~M=!EN?fY(!k1Rai_kEgG3K2EBAHytqr#(1Q;q~v`|{cirW+!g++dUMB7QKzni zSCgOM!8HQ?;rRjoL9p1JJO0Og{DEaIp3I0A@X3U3gpMyhfeiYgqe1L@p+V^F)@i}v z&G!0rpCY_F;h#CBv53E8F(gww1 z>gww1>i3WyQ1wu&S&OgNhcXM^~_3@-X z`lE+bjpP>aW=m=2?MoV422>5+e3>nE4yFVe&Ozo5U105n*+VccZ40W$D_;ort1z@+ ztkF3BWLl`S!|*LIKTt{}DOI3Fi4Av@uLqoG(u>g}TPdL;!}Yi?-tE-o^`$}p3Vs8L zlRH-utjp^D4vj?o=*=}A+K@TB&tKZz0Y1gGDl7uS<;W5*@s`J*Z}2fshtQe$m4*`Q z^t-PooCtjZ#4o$(%IO;yxMqPD=pK0bm_aH)>84|00xjt(7nl_;DO4Gx8zWxG)78hhz@H{fr}(@V-jhxqoL4f)w8PFW+2v=H#bo$&fm3**5==>hg^~V&K+cvf3N;&I6g7v$oseH z{3;pRg-P9ItC8{l0X%_MGo%BH?CzSleolX;W(@dx8Z0{S^;D_}6o_r)rt%A$ zGgza^Pq?;B4o+?_w?4iZeY|;_7cb^*g!CTRpR61z(63~bP~d;QRYKu@4XcDg{u)*Z z`nY_7qi?wMjce!Uym4*stjphfy!A0bybjqBBGTFD^lD)@jbW-Eccjry_h>kRXYkQ! z+kha-DswcdrbW$`ERPpEM=WY^HCC_PaW%{1#x?2OPG2%%TY)oIsr-GZXt2eLZTjo2 zb?4`U%vuwrd_|x~!BHMl9la5+eseP_&xn1a1O3157dLO~gJFdfkZrs^RfL##gZtO7 z-n`A=stTj~7BG}G5EZ&TxH^zns_o%uR&?Lq!x>kv-FmtHU}JOZ;nABe^bFiVzj^EX z+js8%u!>l;^)11vLvV_Kf4KU?N&(zjtF0BBd*M#du#6sfOxf)oF}Z&0>h)W($^sRB zxOzQlmW~@IPVA`|>L-cRZE1o~!-fYQ4NN2{q^D#nvSZJI^ zR(>zG#2`)Qb97khBWK|DR$?(&|MfR66!;^nu{bMW*S){xpIn;py}xBYwr+K}g3np4 z-*fwwp;hHrnQ7|2E0x z$3H>msx-WS%P{@K@P-^+OcD6Dbe>nI#Fb%+cGhl{cF=_;;QUrEWvz&5E-jm1nX>X( zVA^V(u+_5SPxNs*TyCU}0%avDmp5=KTz=Eqlmo z4H?wRkz3J<=WkibijQ8=Vp8f9l9gx6VgB)qoCyKh91F0%gm0JamhBhClS)#-bT~wo z;m%s13-Np8$?gEysQZtT0YioZ1w_(+IOv~3*vgpe*0Z3T32($EYq7{xyr>o8iRr>D zRc$!6bXrD(bY(1Mg?xX%vLv}S%$8|iQd_$fF#eUQMZ0yZZd#0=6FshKQ5W!br#2}~ z**PCH49mf_ienT$Zt(VDJ)O#;Rr@20%bgYJPL;N$IzRbGJ ziTCaDxnUTRnwRY3ZZKT~x!mV{ss;jtIxQAji1|w1P>tO)!+No76_yFTIujO|l1d6hGRKVc-)iblzAsN~aX3=e zN}&o-Zy`)`vp7{Zc{h3m0aIOgh0D`-Oy@Q z)+ag3t}xmW*N4$?sS-}H%L78u4$Zj~a^=_co#$IfPSr&uZ@e9iz~e{7#u^+e3h01z zE1wi@4*=RTd`YiSodOD)VJV6QsZ5Pi!Gg&)1 zW|&1Swuj4wbo30c2#m!p=<6~4^s6IrfCn&VMUd3TlhIiSFQpnj;@C`!K3@u+(vNfw zIl0TI67%8qP7Md}CDejhgnm@)Y22AYoBWZF|Il@?7)*<0Y*FZq@qOp?{Al?C6yD-d zr)noHmMk_ZfQMM7a-WtvI6GXBIppIy+SZwMA++|NFZ&4f-y#f96;r?52j|tTo^DG=Q zl%}JcBCuWX?Dm5v#rpPdJ{RR=!LoL7C-A}kCN%W^O#Z?E_;Awi{D7f+75#qNF)&a1JUbWXmN3(zoIezmtg|J>MLnu2L)kz{#I zl)17=%XP3hi?b>eVexVYK#hBAAqRO)ftK%k(c2Jvru4jqm%QGzEC~}_tw=?yGlf$< zW{`x!av;G=aZw;gDGa6aJuvO=J}jvY6l<{t`wc)-G7`+F9rn!)% z0WK|f1G%^yTVCcYH!MS5ENC6TOFS8{oLw?XcJw1I1<8*7!<6I-*axN@5<8ZV<4B^5 zzJ6ZfUj)RKt4*eJ2E|l@V?+O%9|L>bIUDuprh!O%O1Kci`i1*eEEEWP4xl}a5|@O8 z9t}5W0S_&p2VvVNk#}pLiOoFJ$Z!&1)=COW0@pTyYQ*Y5f;}z_M~f$&``uqr4qfUV zpMk=Rj-`tb=*JVUK;$kRFFjaR5bdlrLR z-XR+<8Cby3gRG8f#BDrN`kz;zN(yNA$5vx!(+$rNX=>=-G=^#f2hjqz44#X*Ns zR*3@&$+Nh8ZZ;(p$vC&{;fE>M`<;x#+=87MuhQ4SYoP^h?wjZ?U`s?#ni4YMp9Fs= zS*f*}l2y!W3h_v}jCoBlZ2RW-p(MGM%n7X>*3iSqjL@_JtXjf{Uh{nl8Z$$nseDM~ znWfZ-8qEo9iWmxC?x2I+nqWVY&oX?K$!inK< zjK?#7`FM8f-a_|V*Ae&^ekA~ht?K>O^Mi-0cU!;kDH`n=Ij;8x4YpcZeFJo&HgfpF zms%Vro#ClJ$h(5C@i647e(k?F*m-du_82@`a<%a3aTU)u5@u*&0_cHcos-Gvd`v6l*CB= zL-BHRu`b4p`>nr1YXiNOF$RYp+jyUT`6rvX38nXdlTi7}6fez6(=vGj5?2dtT_gha zDctxUilb0UH8Iux?)dsjHH8&vN+U+XbbNa{EPnTkYfD(_xV-Vj=Qw)(qwZVv1(4y3 zE=mp>Ai3Q7Czo6QEn%LiWP5_6@zN7st9&n^l6`(xTn`Ur)YLauD~fskht{*&Ki@BI zXdBh}RigtW&@i=Rq#iIL#FHa<=YHfQx*Uwpm%OGP$^ zzb~D2y1E%eZ&!AeJpTM&rAg>CfCSt*@lur&+@;aN*GqJ9om>0E%@{#BizPExv)vL2yL$wrt zRaJRaOR+@Y)H>DZvCX)OBbD*&ttbNWi%P|>1H?i-I^FaD4pHkNZHA~Oda!ges=fV> z18TEA#PE!70KZm-Zxkb_%C4gc$V1HDh?i(Nf*3XsTzd^SxIF6Z{Nj4epfD0B_GO6n zlF}Gt2 zZ*G(8!Z{*LId*yL&q}!o9zl>q&CqDOZ!sd$St@<9Rr@oP$I>WVjY&#`B%zEU-8xER z8U_=CFZX41Icr}1Mei%EtJy*w=0(mH@sVTrs0anLPl*N+b)`%f)hVdrwfpg-_-KPb z>bC-PVR&fk$KMd+ux(I8o0YOs9|jj_pYRBhbc13!=(=hs>Weg8!TS9pv`TAI8|1mo zWt*H2_-K0OeZeZIjUm_qkA~zxOjgF6h=G@BXG&%lKa=^z&q#0Xe(4fpeA;^~K_b*T zg;snq#qzjsP@=51pSVjKi*`*>X8S6hXx11U4=hA6U@{=jUuKA2H_WgjjzpysR zJ4xbJCNt7lBi*xCcGo`JteNs;bHFw;p)#f-zQpV4Ea3`lFh#t{b_A#DycQW(ah-gg zoT(J`JVu7I;(^KWO~oc*FfTzB11QUKx1%a}y6|wi3TqpLxBxp|Fk*lrDFHe1X7sQ* zhRUMDM5TfQlykN$< zfK!-yxr{BbU^1DBNR*9`)rMJ;hD)#st8P~{GZ%x43SnYnQaDJWm|CV&)D2qzqb0qb!n0k`+DvGSZACu|$f+zJo zKOJ*RnwxYatYIN%80aXFbK(xBC+7n+ii^2C46W2pEJT!3R0GQZ`VtAg=gpImWwGwy z21yp!T`L+CY_V+p^~tt-J{zCUxZ_u~vSIR3qM5R(#O zCLt^PXIi>Comq13d}e{|>7(b{drCb+da8FZabSc3T#(IEQ~6Y<2WFh|G=3<%UM=bv ziGtdA3a7q-W1trMm_t!b29RGi8oCN6`)<5BHJFTsq>xHP7o}SSJO^z~~lN1<5U zcdsRA)yQ_C3*IZryCNftRE*0rd8bInM1Ma<2sZ5&M=qxE_CmrKs7|$tmWOQ!V7S-f z?JUVBrko#SaA_az$o3XeJ~LFHmWrsIvIK$8GI3L>K2H%c({+-UDu~-?@|aiNa8ypE z@#HzBsHI}qMTK-)soOWZJpK8~^e5PTz;Pf#nvRZVyH<0=?$Dj8PGBW#Swf2h9Z`Ph zJ_R;4yHXQUvS!lWK=WB3J>+=$8eFw|d!Q+nLl!dmpxvuWpVz&n7CAaK9jF0c-vM!1 zh%Zr9I{@1{pQ_4`FQ+Ypc&ViZ#7m$9(k>+eU(`%Su)_l$*6U>SaYCvr>L%)vjgrH} z7Fp^Mr0JibaNK|>Gv%-{4bw;j;U&@L?WCT(Y&jId@QeeqI{30SnPNg-<9~_lWFW=5 z9wPaoE_%%c`dEhcr*|^NrKXp9M3?uox)-Y+<>gzk4LRr&C~-s@Eeb+DQS4N}__m6J zo{{z{_Db^qzO;zXT|-UD^RcefG`_@=RBf}wvq@cN+S>l9Z-}TgBFCir&VA&>ECJJ2 z`WDM?&;c?npCzEY^eC2prqdyx-K4gKSTXv4x2{e)^xgY(I-oUzBA??8%-ZLdgnpMr&+hbbX$9?D*XM>ZsyiW=*yxEBNd5h_| z-yL9kPg@vOaqlng>rF<}PN(xrpnswU<$zV2k*jc1xinV-CLoN{LJQ7l$(arCk%-<9 zN510dcqFGaL=ls3!c!UABIhmUev+STPPxHIn!_1Y?6Tr!n-~`4&FmBS;yO*x6dsIi$l)8Z%#y#Z9iv9( z=HR0kj_>3U726~oTl!*z31b8+yD$j%%W>@^IU@DSTFC9lS4hQ5je%=ak`w(nyLQKF0%BV$&sFDGh_~EGICMVb93m0tdof zkM*5dJR{*IV+qhW2qKvE!c7?-8>=^uhz)gv;m^eFg`YI5PBlGxSnxX_Ts=TmQ!O3D z*kSPTkY11>QegBCNefs7#KCZs_i~gTH8X6Te#sT_|zhdcE~iMh8U* zGWQ0A(}fT0`sAixYy zs>#-$pKdPG`4ZZ;XWn)O@A?}ohCm&&1AD;l*AR{XPR1nLq<;cmJ6K>oBit1o^oy3= zu!iD(bJpnm|_nxG+I)?Nr0gO8d>F-Q%8Vm5=! z2E9rVDSBs&7SY-qoZyAzQ-poML2(<2An` zLd*=cirZObyJ(3!&l<*su_RhWyyE6r7?!3i3`#Xi-H4}aC(?lmP|topot^gvqfj4L zcfx&M#^32tl8wf?nT+Uqbt~f4Il4y5Ga2T_`xrdpi7oXoe8e*y_?{(bj;UUjhMFjC zX}Bn=z&KL)u;i#jgz@$YqMk_|h*xN8md@eS1j&n^mM^4~EbTshuiC}3BrkKwjteV- z>uQ5jrJ3FZ;6t8(-s8THoH^@5@9qEl`Cy7`cXF!>F5d=;qfbKW$W<@otF1^}QEH2j z*Qi4L4mfE6VX;onuIZaxu-VUvj_4L)iYU>cDCvP>vJmTh(b+W}$-*iguSO$CA5chQ zUoWQPgJ={KqLFlJ7Jj9owIp!GPOt4~%OqC9c{~|GHe?$9g=ph9>mz}GDC`hK9bs&h z%;OHVA4Yp=>+m6e#4~eVK}TVyNqYpx8@&)n#SlhZxm-;~RYR{zc~-?QVf>KoVn@0!`04O~8iW!%#+KMGdy%TrDGY&h zfJ5P(aAi}XgCj1HZrLsxDaAtI*|;=evN@QDMXQO%;EYTjGf26jaRGM%{R2-I&~9Mbda740pDl{_B?@ zm~d0J9#oeLN;@6q#;uMq6!9BZAlWDBh_+hVg>H8N3%vn##fGAp!XQ+K=&K3mk8 z|HxI=3e@bz@4_Nx&H|{k5JN1KNxdQ>7TF*<5{W?p;_T*9S{aPYm(-8sqHZ5Ap75vW zu2P&P3z?-%w)qJ0R1`2A+}CNyoG84?ZR@I1YJ0K$0ee*xaU!M-f`7PEGw92$Z~uF1 z*>wLp3iwnh;h`;9V5|M&yZf^I3j@lf-h?bEgpPe+VASX+W8X}BV^=SBOYTE=tsdeQ8vjWhCUwv7Uu4_F=9yzDhzFK)EqNhs7?I(M? z&kkzH=)jw3A|j`RmV%5j8I*yHHu-#Iir+qLl-)u+{xBRwo0ag1 zh%D3Yy54}Z$;A@Vm*Hzu(?D>bj|FI%;iwX{jI~=qnZ;dglvqY_Qe`JDRXf`cbjdOm z(pM@ap)00e+E8q#q1jZyPPCXZ=lcTi#Uuj&>hr4FQy0L8X$7>q$f)rLhbENcf-lQ9 ziBW|xzn^s~d049pH;AJjr!)bpqYm<`^_Loi|>?Uq9#O7Dvcg`CRxUUe38iPBh z6APouV#6({grTV7ld}GTcx6@U@xu(^ERp}H-!F!1nKdI1k)p;G%3fMj59q6&7P82X9<0D$E-Faixmg@Pg^Z>&3F#1&VW%$)I* zX3buzceQQ$U?%Mu(8zvFr5AgP;2lmQ2Zk8Y&&~l+SE%+Dk&hq?L3rIk+*Q zs_ctc8( z)I!I>jR&|g*`GaPu+o}dP$d$3|J6d`nNH_0gGyxRfU?t=;KTup|94bp<818AQAAae zm9Uf});DA7|TwOD=VRj}nGvSxuYZ9mFp1wee*iJRPBPUW9%|)CmMoA7k zI;4l6#XiE@)MBh@ zTwVSN7eY&Pkb8qQ$xs651(29`p=8N?M9wl<-YtR^9I6D(aM-TU`)7jtX{{#1mAdnx zEPyn*N;j+Hk~Ohc88&O8CZnkd25{c=yYw0K2WigF9b6E~5}E)yzbGt~cb*1W_ql+r z{C;cm$tE7ShKGCie(TXDoHh}>1V8CTMt2h%N9ST0z3_pNaey(%q*~C`5MNn3Q}%Rc zFicQYTPy_B+-d5Tfpp14n$N=gsqwn$Duz`);8QmdbQ`t@u^6Y_Ib2u~lVSFRiwn>G zgdt3I3tvDgKu%{VMsP%vn{7aMh`(>Qz{ZDwm^9o zTbWZZjTu+h5m~gi@VpdH#A+m#ut|f&O2(7cOY??@tV%LeN~H-VpU7)^aO|$lE}eq7 zsZbw3FsCCFD2(E(ZSV}Nx7qm#5E zRU<=YRN91T_C)yf=PNzC0j{43g`}>WoG8NS_q8Van2B75M5$sAC+87GLwM22(c}}H zY2&>gmZZ`sexj3nj+sLu7fKq4hskeO64Ozp zEj!*zBu28pNr->0mZ}cK5_-7_`ifxCoC~CK&<$9{iD;8BMGg{)wu#TdoQ(wN3sbpE zFPR|(rRAWs?)@N@7!r?#Ak6u)36(P_Q!x~;R|zn5gk>J@YRefc5?C^=qQP}A_Y1a0 z^u*)JfAa|t{2%@Vz+xi_Uyhhp5Iq@I5K`z|PXV?i0bl^;ARk42z+A@E(zzVTJ&hzJ zfg)qtCRPMqt^tNOLE$`+rddQMea{Huj!bD$UY5*vDA?7d7I@IIz#-orWf znW}cH_k$^7{AQM`W_uJv%pmkqS4~La%j`(DjzL5$>e`)Kqe!%OSA{n;UM-yS-%oE` zyY@XaRQ+|=e_g*8eo>W`-0L^PukY#0PaCw(vG;l^o>;iRK$ww8Z?sJFxiHEbbg!$tOif-eqChu4Jum&&Z zkfK+8>C+XG3?B5Mcr++hJJy8+@M(1F_GE>WYh)n|rG6`UT9I zcC~k5KfL_Y0(Gqaq0)7%J=PM_s1ujtn(p4CuR9&zDswoaUVlJstJD26ltz)Pp=r7cP}_gX!&CZzKTwG_4D@ z^W*JXt+-*8ohrh@olT)e;)c%=Y>C}>-1?Jn+TVhfL5=G$HtfS4^`u8QRE|xB4GK0I zKVSQ4jen>NsA-5AD^uk!k{xGz>yw;+#1mXkm(>ladZiFX@u9>JvdAxVhFg{*2{?l6gK+ntvItRUfuzs+;0cW2IWK@SgXDwuqYXQiQ*Pm@|)2!eJqvF+tG_CBFw<@4e~rNgW!Z4FBv(w9XcEQhxRIbSnEFNFca%K)E%F*Kl~HB zGnoE%_x9oKThg8I5deySs{=NeV!M3)kpTT?3KUONYZiZ`8OE5_oPUM(ETO(ddmdf^ z`$r1g9&OhG{t*jIyKnn^V0Xd-@go+HQw5l!R zA#0bh-X}8_LX-B972r!slL7DSTcISOR4^1sC=aN+=MJC0vN{sXM1vGK3Jh;zDY58q z^hP2XfRNpHLZCdQLZB@4K^={N*FHjlci(PJCL2_Kb~AL0eeQ?tFiuqt)!(r_Q3FjiWYkbw0NA3@g(o;6FDtUh~2_#f$-)~+;gZHYR98LE&y%1T*Z~zc_i{RQ9Y5r3N)D#t*2d0} z7}o~}NgBQfMg3>_WQxpSj@e{%Kd7pQH^OFff+I4H5|;gBLzT9QodH84vk<($pKNZ^ zDt5}pl2$&bqVww2o5AqaD+Uih^yNlC@Xe=*j@ScBoNF>9GHir!WT?lFYRR@$YAS<6 zAAkVNlJ(E_Gj#H4K57ulsaocfNZ-(Z>hXb!_2q48W!`sa1kPOuwwU$#(38@{kwf=wy6f-re2_Q(q%2qgr@Sn(QgYN%K%0Tp!$)d zvF0%&5gU9Hn7(?2>jvUK^puEn{x%&A8)u^E&~k#6P%b9&=9O+lx#89uJW@I+#0^YC z)qK#S14^ieEvXvOn`mS5wv0`hT*4>Kx&R|98ga6O1S{L>^v=)5hw3xV6)*h+8Lbcw z#{d9(mVqvy*>@}k4;Td4faKy%m+N?zkgQe`n;uK{xU(O&wUF8*p00*ZM}UHL24`j9 zjBBWhWj*fCdK!(~L<8R*38?C5+8ZWmhR#4Gt7E=XO$>eVa#%hl+owWLbyl@@>l z%Z+QdZi+4>H9etR@abq1fp{4DHI_}%%Ehl)91P1mzoh}hZIeSS|CErRSawy5If|Vwh1!JY1J)^ ztlVi^v=;T?)=k#3Q_T7?_I6O(AbY1PZU7e?)mO@s!&A1QG!{jX79UJij(^^(Vmm{8p;E4dvdanFF^=giZq;huj^bn_^ zh;m5*m7bYcP#P16CFd{Ivv?-1p!n;Lzv5em30o33B-cCSJ;vRwYfUM?qkvV=9e zvP%{8us>xfEJ`GNe8KmItUEF`84{@%jvte9Tyy}<&yD)UHD1vCr_B1$DMnM!zUR7jV=7uj+J zM+v14<}FS^i|(ww{LS)J_ME-5cZu`n!pF$-@Z=exnM#JQVf>k_`i2;({h<>r&swM}@Zx5RcjCtV52_j~x# z+e>0Q(lo45Tp|=BsbeXXl7Q8TZ%%$*I+}FfBEn#Ic0M8Nd|vu^_cs3)t<|%eG<98N z3XVWLk!QC^#Q)3Yh*g45B+9f_HOyGqHF6cI8qydPG_bgLjy52}NtG|9i0rTc(zG4y zUwK+XLSb}+l1$!Ksj_j%K#bX z^u`pnq{T1jSOx2F*%dl(>dvLwV6Kq6-i}#^($eown00hSvbm|3t%Y2e;_S3UjkwS* z2XH0{%^M_AynbZ4E73vIy#%5ke{!J(<^23qLL7J)1K9+)HXJLcYAczMCCXhMyg`8z zZVnj85S@maX8vz7J)#So01|3Ij!`Ny!5tv5EmeQ_pm0mB@_U@&r8D%5tlBT&0iBT! zp%+qBTHrsnpYX6%rXn=~U&WndfG^kPZ4Q&15L>ATV@a~VO{y{lKOrJEEy?LdZUG8% zd4yNPG0!9Dizi#Ty8GmjE}^V?%nAfxA0 zdB!=kjG#|4suzg0q^mNSQpw&R&LXKx^9`B_CTD-x)mwpoj@07BH*twT!lxn}#9CLL z^dw$(|5S|XN&ij5>P`x8Wxi-yI7`sF2tQo`J&q&hCO zaw!<{yio)W{q$75Q?&F|5dHnS13NklEMPrZK%~|@8EEY_N*9cYsjSdfyKmbC-unUn zn1#H(f*s?uI~j=41LQI15Cn(LJc%7)F$#86ZA~>qH99nwg1#t|!jx3Kpl>t?AeX46 zs+hqz&e5!>Qf3;}nd(tjms}+AVV?Nj1ocUrLZi-Rcy)qle0pLtJuzb5gmb$ShU8z>H;bvH5A^ZUAv(r^SDG;(#8@)5 z90ZtnNy$*{4yC|uu{sc!4-|QLE&-QXt7+ms+^Q-i_s1|^S5kqBI2Zr{gMPfXjjNr+ zG5A4{P0YF}06q**KrXt(&up_G8=?N}l8aenOfh?z)?=Q9MvP>}sukp}~ z_D;Hk))#?+fbK0UgxQRF8xM#wE)Du5^Kph6C3QXA&0|v@Rp$KrIo@zpw^OTZinz6i zL@uVX9d7`L7lA|@tpgYp`${kJ8I*M+9IRivYF^ll zxlFW9+x`PCAG{M=w_7o-*h(hbF|S+QYq|2fylQ3ci-uw!fqA6KnqD_lHw=>wCK_tc z(tP@mnHis0&wMZLpBGI!=t9h9 zDa;Krlex_k15UGp3W}8@m&tCHyXkGyJ+pbn3QC0PR-!ymx(#gWCeDgu(a>qcR1q~C zRa%=o0xr=0oLX3H)YBrVx|&qOAn`~k-wKq$2P2D07u4agokP*Cv5qJP4Y)9m_^U;L zUp_!g<<>MnkbADFfl8iT%d<`QqCGPh;|K_F1l~)w@Y<)o*nY}b1vR{crTjtbA6hj79)7i!r=Nfx2s0O!Uc)hF)R7f;cC_~^{k3Ybvzucs`KosI6b1w z7wAjq2E^NHS!=@F(jW?e`fF61j(e2DbZ|#{t^V}z2p$qbfMfiEIw&tx?c*9~*V9ko z&bW$5brS=UD_6(IQhgU*gsuzi-Y8Z<94P<&RiE^*SV0*A>ROtrU{u0x)|Zb8*|ecR zRL&Ye%v03fi^(wTe$-;R{_Ago;n~sqkHB$%e@j2%ovoiY!Z-E&vc4D9yBCb+XBq7bt1*EB@?ij``SRF*#ncV<<{crxp{(3ABI+;ietNKcT-RH2Mmp+l6h0v+pPavEymd|7jS zGU7o!7acM3L**cm12*UQv*Ga5ldDIchWbvWp_ENrajo5HNG~eY!|5G_d$Lh82qjy( z@(vjbr58BxB#ZosN1i@>JYUnjjUx1a*J&q+YWm9sn`auo#l7xQ=baq0|99d!%*~K) z7iv-J3H9Si#+;Hy$jhI4lG9U*f=H99AWMs+a=^_6sMaV7(z-#a%`rL=d|> z#;yiCg?{@=BqV`8(EZAG3bY_TeAC${aX@R0aRcLHYl-Q9*0E4-u(;F#5W@*PpY{uR zrI^dmFU37tHE7OQJ;LVo41RNyRX>{mOSsYEasLRule7RdofuUt8NI=jZg^(R_yfj_ zld>73-ipz9_!Es6W1OK48C+m?pLUF5Rj+v9G--Nt3@gOgEgP5#3)n9}pTt-}(?(*f zz*n?P{0F}hGXy@-MCot{S{UEE#S!Z&{NDPf_mQs!FR($(W|RBhl`IiQl32D!gw#5# z#095N;WbX&b-~FByyT7w+>^m2ivkJ=Zd8DeXk3F@T zXKVNp8^$Ig#Wq_-zNYo!@o{6zf5>R@xVcA{GgcUj{oRZeVl$;b#FtttN&pty&HF_9 zdzmY2{(P~$BCCI?F86m9VqtIM?PJVcBRkSS)Nt1(O9!e@&A`urpvS5(gb@ zQ>g>GM{>3aH`Fh?2~YYE)YZ5Nm)y$cR#eo+Gn}3KjZVl(PIW789ry!V@p^2(>QV2BsxEzA!V&Gs32wdl{~+&^;QufZ2DN^BxmVD${|FASj6OKTJ@~=Vv{?Rl zbcT>paFjXk4Mxkw(ey+A^c1&_mcm=!1{|=TAjJA6J%z-pFY(KiA}HV+$|5Pb_M5g) z>`N2qhfGy{jS4iwC8j~|kho0^3~uFYz;y>9_z_Z^mQMBg?Dy<5tZ&QrlKghi zX!s%t(d)vw{ox%Pa>CRKx4fdNN7jLMV@ zvkwcy+0m~W6A9_98y)V*k<~lz&OF`5uXX)e2mgnB58Rm+K;`S4tG1VTN-rA!9|2#J zT-E9%@)U1+IOJO$ghpNxzDZ#s8&z*fn__3Pc^w84M>0XQw40u)(iLCabpEM2?`zqB zB=Rdod8p}xR}e7g&|dyU`EmF_x?Q>yzXyjyX1#t*O8O{kl9|`y=mZA09E2q$pJ!Dq zt!kR{Ye<%(MpCJ&KcoCS>m=d?yvD#`xJjVwiVMhi^YGE>=*`jTKF&kv!(Lk)*C;7N z5fM;gx#AWCjm6NvVLg5 z@0{b+Sh&twfPW@?d5fQ*2YqRI=@z?aurw^Sa6D2Q!cucb@NhCZgP?~)UVWdgB7n>A zCaxa?^Z8w~mRsw?PsPUG^P2e2Kqr7JV`VG~(eCoX7>QTx%Cr^6B>fiOQKo4Cv@dFOyVNhyI3W zc5P3+3gO%^Gl6lCc3zxZ(!dMG;CiE=LU8Hng#^IqxFExT_w40CdUt`j_QW^Rh*u)-CBSm!8<@j4D!0a*3 zLw$el^!x}UF)?!nSK8|OtSR#rVF86zD6H7cE2+^~mP7m9xK3)roIS}J8b7UG>E(y` z_F77P#v@Y0Y`Z1bM$qXqU#R!u$}4QnRT5%VR!O5jS4c%dnF0&sSw|CG0!ARdLZAq- zohnaqeGFmaJqk#|$cCQkXA)jv`KMn#o}Ct^&)sibhZ=_PUfod-x1{g4&S%G~cU!*@ zlv2u~m8sTA&8HFj7pJGP=&%yQw)X#)(An8l%b>_AQ`m^#FaRJyztin?~A5b z0O{fMe(UXQHomtep@FBNpkUo>F@8jjqc$29 zy6T{zqfSPp^u;2R0zSOIm?+wO^FY%XKso5;G1*wwpKH{z=nrCv_b0KK@6%$64nq94 zL5&IW(Bl5-(6sNEk?cl&!Q`CwE@Q$QQe`&AK-tp;5|CD&Jteasoxy>!^}E1VZ$KRr zW~Wz(dYI*|yjrFX_-Yw{TM~35%jTdh%aLM)?n+$+uxC_ZdX9jD!UKH=@aDe<5&JAp zFvNf^mhma{nlwwesGDgoVeY29B-6OUOGtHsSDp(r-VrZ$UYL!82v@f8`D_mk=;btS z(_)&Ub;t-XF%il=hPd0GPDcp24S!h~D0zRwn00hM>Bi?DV@*HTj45_LEa$Z`m44!- z2LcsxCHhpX6SH<;sok~MU10*nY&?|7K(w1Nd`CSHiIH|eDR>cJAoap^gdz%l{+?fH ziZl$jTGZ+$N};iAM9AyJkg|>Z*wBD&VXTF*P(NC{vnq=#E2L!* zgp5*>W&9`C;BqmI#55O@G%>HKXMGKT=isG+JVx5|Yv_gl3aXxv#!LAjl6Y zV6(akqGRfV^b*8QS7c+2ZN%*evdZoz5=i1UDGkV-J&1fP{>W`B3fRoyBP`Dn(JBMT z?v%Pz4#hCP6ts+EhVoz!Rj*{c<>6~tyyCOtIttm7-2R@;V!CM@ zM(VLTiYlSVochZe_EnA@VPOUnli#vH{=;7v$BviS2(lVyF5COcOq_OXqK93RhOtT>y1LrNo~7Dw%amnxf#yr{Mmg8^REA-Eojljw8fAqJq1MI-Vq>Cj<*MF%NURPu z*QceGmAMz{F&=}+UBLJZ3$FFmzAU1jW?8fWmMV3~N++VyQhtY_x)CpwF$A?Qv(l~H z#ex*Vkk3naz7h!|l&_3))BfPj zB{x~Nd~#wT1&~!c30skGq+IFcQjm>;FRxCpV&;`y=$wTC5R-L*@MT$0wER{CFyk}; zT1Wxh_Yw<|Y0>mxxC@H|41}&pF(@k32|~w9BAn8~zm37|>Z;uq6&aA*n1PzLXRe z92|PdfgiU4Ngd@X=ToQwrkkf5$x9-Y9S#Xjc}f+fnnR@qynsAu&Yi4cWrKlUdwM=} z7ru0-{q5RjI0I@jXkyz>zUJylMVFhMB!VY{9#g9L9-2GPh@MQ9LpY|vO-A4`xuqK-)N6p72b-LOBGE+n78uq5fU z-KIfDE>vso>TPqWYN0}8a?*f&q5&eC;z#APfge);PXP256LDl?g2Lum!qIsO`UR}!ymjtUyVkgob`AzX+_vXhOG4QfwH_?3niE!6 zPbh^Lw`4F|K@*j|crBH4&LuccK?kg!jzukNsuJT?i%;2@@8@P28TfJ<8d=7Usebai z`6eZXjdX!Ws5mCJ7YQom4#_#JASf_IjX3~hj- zUBIAlj69W~<+-fnr6`1e?bJQk6}H2a;?~@BeJU@fX{6suBJjvVS7W#q7etUu$;qJsueE21co5}cu+Zy`js8Gqr$MarigrS`c zPb3P0adfJw$q)rVbJ)0K0L<7JypxoWfGY zX>9-}v)N!#7%XeG6A0BSFPH#`vw=v=GQDb1I>UXJ8-xXehhfqL=OQqMk*d8Mc#v8o zrO-HtNy~u%$=m^rMm!|7K1tkuS(>~`fT3+j-fsH-0#+zS6$)#bRRrzr)dhzn1o4mi zh5w398UeO$sJ+1bBFQkr7Rct=D#ldAi&%7paD8$jPjsm;X~+U28z7}Yt?)>S^8LW8Ep)%(8hmP zX>(elO^S`vCQVy_Hk+x%LpVpp0(p7r2lPB47GF~{L5i1QUqpo1#O+%pq}1f}&|0)# zND}!H=2kxHt&(#7gGT=R(J_Kyl0_1crY!_HW<5v8OCu$pK1#TA5+ltC1TndwGIbNwS?EB$^Bf<*EBdTV!Qlu_hN#*3 z*bOeWYZzq&qMl9D#2zlN1L5fZEQ|t)S8}G8iNTj~_S7~9D!Nfi?Ko9$FoDEnbxSPKe1opvCEO#oCY#a$M=F@F@ zLR+WTAqC24*inDBJnzC;YL#I*284feO+8<4+N8O!5qjPmSSmJzY6r>9h9Hln< zU@%;rfTB)+hJa}H@erI1Q@nV5gc1iwgHv}1@-a%h|6aIvw|bM)OQ=7_^eLq`xYvYM z;9JZaA0nBfYhB2O0ey_a=;>Sdwgt#AXTZC>y==BiPI|ho)fi+09Cn7VEHXKaXmpkf z5WQ;Rz!Rz(aZ)oSZe4N$~du=Zd~;Mj*H$!9`k_^1_5MHR`IzH6iMze z-|A`mkO>75=KoY)sc+BeAtVKF&0r`ZaaXDB&9VkC}+hJ;hDX#kxf zDo7OHV_UeYj>SQ&pruf%=9DS&afcv z*H3RoN0VMHxIuSV-;Skb1lcclK*HaNi@{*(_~>TFWKhdfr`ZLLID#)_7mMNUhvzDy z%R=c?T3KT-<)Ns<#q5<+J3r=D4w>|)KhpSPnPOe^rB0v-bD@;jsU5#?T1*Wef}@n9!LB97 z6f=(LM&-ST>?4K}*J667$$jZ?E7KZ#pSy8Vpag7*vHxddDLYU}1WN5P{xWJDOgx*~ zpJIBIUMhK8783}L^iLR;&V~kY{P*5fiIkE^lFIHg}VaZj- z6bQtdN;yh2`yUu0ErNE~h!ztWr{(4qn{wudVw{(_z2U-BBx1;HYKn5g|Ccv)G(GF! zKgFmdE|x+zL$vxWYp@?=_PJPFY}+!*HQ7NO37N?#7On z8uM-=dMLKNiaCl%wO1r;&^qAh4Lc40!d@Kv;>R=A*M;DEg+H$7&<(XsJ&^V zU0{PZXIy*(c!j`30r27IeVTj3JMB1SWAHGn@E^O3f;N*bp!H*UF%}$#G^{a4rz4sd z!iG*}R?~_@*|j2Z?u1r4GfP5Sgw!60Hsf8T4N+}^r_i)LIzC3jBD3(k_T;Ku&v#vT z;;vLY`{rV!Ru5opt4EL*=5oby7#5nEq+Jz$0gTmhK@_0rN&h8*X(bUx^)KeuJEM^m zOl1zMHoGPtgPyLtrX|M(-fQVzwqC`to;ZT+ptPqS5?4gLfBu)Roz+{0Qcl@Z4QT;-NDi625d1VpO;?^m#H@{ zzrqhNt4+1BmtEmYv;rsN^i``8ARLj{>$$W5 zos)ay@4XZH^De)9wcL6IO!0>GtauHA#O6ceQeNm$VtvD^kHf#={8mC6mu*6Y&fxgd z{+w3eWxcE{W)A}2(>KPJ|Lx_Kqbt3`&f4qmzI8`zrvhHc>+rH82Qh;UXsu=Gt`Wbn z|J`%Q;In<04To5KE=EzwH^aT(FbZWvuY4z{isH#~!rXr%%3}&D@2|x2%AP3J6Nvo9 z$}_^!B)ll&{wt98Iw-48Ni-&TG!_m!x-Ir*?7 zh_u(os+}ZQAvlG?>pn1glSX}B?J)kg_84ELt)k*sD%f0f=wQJ43_kUIIK<%y>J8WI!7bnsy_JTgAe5tAXc6EfuA^Y8P;mKF6DxF-Dol6)A8~487 zk$_62-d7tGTZ^<+(%}~Bud9$$coSP{lPTNlJUCu~?^zx3^3 zv*B5lcGa|@1!R|*Y;%;oOK@>k1^;Be6>pXUb^@%0)lZie#Ni=pqXc4SVcHEaW8%&q zxpGcuwfLvgd5`7pFZf@!;uHF63|7)$>12C*q@_^Sp+{Ag?zJB}8ojbR${{UG{ zIGT9l`t94-Z{EIf`+Amq>-P6rwzgCCmU!6NRl{X};0ndwxaHYKD3~8>Bep0()C$01 zgLgMAh^kiVpaNcgYkm6i`fIT(hiE8FabmwYhhG&=4dkK%CzcqDbOzx!GljDB^3#VN z<`hDA%DJp87Aj&FUhOucNu_b`6Kf^987Bcq=0^vjxPxs1-?4Z*0>c94(+0JGk$yr= zzh9^*Ri2YVtc$6DmMI=F4&lp*^zK=!?f3@7>_Dwo51DSfmou1cY@ zXftwSLiHM|HM+CF0w?&_2qga@*B|&vMS_FBHjM+#;jF`RP5v>VM?t7ZPF4se4R2Apd;m2E zZQY27K)~W{R*hV>y{Y>f!6xjO9e8E-b_O_))9xsgZQT41b*t(=W_rN13XH6;$iguQ z^Fx_BA3YT=(vv?tco{73$NvUncm2;9I~V2N^RG67RN22o9#v;gE>bQjm@Wc$p@iZh z6pTxWaKb_gp7%)tp?!>#7uP+aRH|LP8rH6QW1A5%%xo3os%**%>Wf=21p+Bqz3Y~_ z()?*&;Z)>>iII`vN4z4yUC?00WD_pf?L!Zh$QRqgZQKg|2>M+6QFKR@4kFX+r&{a} zcnW>Lc<_9C=iqSf+3x1^jf4He&FyFDQkkuJS8eU6+1S*W6ohCZVQMm6!ZKg4TbI?f zT8&R&&MC>QFhyRuNVqR*%eLB6Y*-Vi&TT^EA3OBQ<)MlH`mt24*jfW|y_;bn@r0u{ z5+skhQ;^TTl0dny6w6R8tvo8h%UaTW9y-O-9{)NVeHbQ86wXD)Z}>DlRr=OKEVRG- z{Mp9V;j`V{gOqmyr4qFXhWdJ=UfRLAOe4|rjKZ!H=!&eXSsdZSsI5>$n{c3{SlV3~&ElP06J=-aX;FNzRVsDHD!j_dyBzmn+6zHAb$$d`ZHTK zm=`xxO{>H)R;Xb7Qon+lwLl2eIOoApHFdxM5PRNp{{6x&ShluaO4}*z!sYeYK1L;XWZZD$t zQG;C6hh;ClE}PdUN7Hv;n;X|}-MMx5=IvW|Vkt5LE$(e>G0L`sXqAH>GtCHdR58py z+q~;cLT_;+B5d=qHO>0Wg9YI(tCTE6k$J#46_jlG`-dTfeqqBZhaLKJaz5N0o_>1B zm~7+I(Wf(PLHBS=0f;hG8xA)>-D^g0-^`(EVkU@`nZrA7F{oM#9!*B)<3tB{tqASH z)KsS61qLBi`9!$zmhd++NNz%)5_WB+a9u8_*6&5AhEsMvl`0azF;QERDd18T)+UEi zTK&ylBl4X3U#;Q?`h~f)r+Pilwb^55th_Z7&}lvJW?mzcmCA)W#9_h-rQ_U*WRdAZ zOD(Ug(B49_CC5@374^zWK0p4l#u*W+LM2MSL<9>(6(M0iU%*tEYa$bv)fNq>6Y-bT zN@2w%1qkR$oSf(i;?lft+1}g21NypYS&|ZcIh)K8O)RoxsQ{9`q!6G2FUPVL{e!V%3+D`a0gZw9}^GV(D`d zW{J!?3X3CdTWP!`g2cA;LRdb;pidA!6(Qo5B=8=3<@Tf?K~h>qK_ZJFY%(#B`VO63 z-3%&(uvb>iu}8gN**lnKQ=kQ6>$M=*g256!GZVJExa^zLhfQl`azR1V8`lOvmdYS3 z<9J0%;xJUM3c4Z>AXx5yxP9%;`qp&>)80UM@2&5zUEA2ae)G<49uMqUP2h(0(}h{k z5!{8DLOCc0@SRO{pHO(;Je8B8I!UM0l9~|bbih|Exx^ze-E>&VABTA)Zm(T8q}nIt0U!o0Seb#g*!r1W-y;*-R8= zM`tW&^S-(U?Wr zB*GbsSUN8BF2O?lW^g)~efl-N1N56*w!PW8(TXTSEbn)ZhQogE;b^jDf#4~&lhcqh zoFA$-;H!u%Rh(RCnd)T;fw2w&LO>YvwxmVyd9vO{84#CTC8$*oJn5^*7fBTxr|+*W zgK*pt=RL8+%##)Ev)~E$Lbg@b>Ky&*nKQ^BQ-g${K1e;1!x6VX%IR2geovMw7qd}< zdA~;ph)ef}I7%w@7NJAF=dVat8Mv?}CJF|PUdlreAD8j)q50-UIT#GZ!+3|6Z9ZyFgjAyWXp;~4-xr$PaS_>lK@qFXHn*B`InE}0bZqkt0LWZF?Sg6_p!?bZktv%b#CFKkQV4~xoPH}S2T}!2z?EiP!fHDCT=IY%Ut|*_ zK(YpA`yW`@OCQ5twLJ{jW$|F2r+$(gSN zh8$p5Mgc5Hk#ym59&*_pq(*IPe?)Eo16Nh_=U`~>j+j0oo@!Rae^ZqJIn^#EdWGj` zFjMMq=^g5n6V#MVZqL@HZ_(#0SEp}4s$!m02EsgntV0k4wMl@zaRI4jt3qz_ z`P^!x$I&GwOnKRa zXf1E$oJ_j#zaaE<9f9IvhL)22tV|X)$HY=O_&>A?M^g{D;4^nGx&|lq9^-KLH?83O zM&t8DWteF}!UYfDyK z*Y`P+O$Spr-ye2qJ8`J8BZKRLU)-^6Tgh1!i-cqZV^DS^1!QXla@Yb!J-%!oNV^gl zss7}L7w3}|T!4DX=3O0Y$%b5hH0|dgt8@7rH-F0iQ<;PZ>NKg5)f5 zxgA0?oP@RNrP6_jfM{!6n8m(eS8AIxl{#+1EHPioUiGF>lU>3QwGb;RLAj5S_cAu9 ztca159i*Zz+jpR$+v!F3q*^!KlKx3M&2snt2q(>lHJ_V)+mKZ&J9{})fZ!@$ZPY== z6nd9LD#iTk z2nmM9=Z_AzpFZ4u_Cyr(L;a_1o6Q^MmyVJ6rHQ-FmqFn>1SwLDUA_nm|XiF#Kjt z3&*nYxGsqT87n;6 z*f`w$>(lio+Z%^ZcMtcrH?l#ZffUaB5+6dhQL!pVWp8JD|KRZ9_Rf})Mh@=8caZia zjZo_Six>Sb|s9k5*Gci7E=hMlWkeE6$F3KcF6)3)3e@20F@jhV= z1=lW_>kL8|NgJB`dt7gqx1a7GtncgyGfRI{gkxNPKfnbAo?;_m2bdwmA1QN4Z3^u{ zp3n+Oo2#x`OviL{@mzKLxxnrrLeKOh^D&s2eK$s83cd%K$DcAUu>=1BH~FOl3iNab zE-Hx00Pvz0CP4db^Lgu|IC}HlZxJgsdvI28`uKtDIwBRMa@+Osd8>2^$DAo6lWzUC zvGaU$YxB@NJ;|zvVD~K*MrqyB%rI|rDXh$0k{k>%!4+u9?=bJ1Vis;x38D0|n+%Dg zCF@bG8pfHgnzM>0D!V}%;D@hdx?ipn*>QE0CLJe?=VvIXHHyhC__`S44qa~9q(!lX zE=1|Vt|LQ7wy5bs=(?(TDA!?lhy|ETFRP05NjcB4AgUe_gV%yp6zFjp@-WMvVk!7_ z>rhsg^^Jq)>pLsBcKq?~Z3c@$iNVdgw>9DL_AMqL3%`)`d&aeNYEWzU!M|87Taf3j z^BcQ+e?8oLyuQDMv3Rz!~dBc)aKkB4cZhM!-a0Ar{t;nkNw&K|MP-*v`9BOAM9AGnraSrl+GV zJbSu6>_HtvR0xD@5qm~$L(oeOL54$&$HDf~=eiOv{}mEWh-WQ+5jil38;$fZWk;Xi z=s(f-cJvVthzoo5V|faZ;jexm+1~uX6Gu}-z6lS7T*vk9ymPx4f+ySmLzTXrtzWlx zgphm=0Iz+pIhis3ErD>Z`4}M#mcDZsmOyfZlXh?8aUD6K;%)3c+2aDC+TP*gt@X_< zRi2cdIf~U%Y$dc^!@8(}Wo2V)e}DJc;U+Z7r`wUySlOP}iL_{u<1qst?C$IXt?gge z54JEO2V2jcBK#E;7SpC<|K!CNe;B5&p9jyj)(;L}tUr6Y{q)iP;rjmJ*0X23&y3px z-{gH|@x%28yUz~}pKTpH$H&26_fl4?DgOK^RR7JxU)P^)b8_iK5ctYEb{Pypj3Pc! zg@V2;^wiZt7oMbw9u^F)N^paLMiWW18Ty3vlQdY{r6Igy{;uEo_j6ou?X};l?iuly z{fZ8~Z(-u@r3BG8LZ9H>EDFzMIy22`)%B-T!n>3w&+8Q?Ki{Xd(*?Wm%|7HHOl`^! zAu6R{0{*r=7{2Y}oT%Shf!Q?|&hu!NwJVZyn_qzi9rg-D{*vp zwjVrOfA-hWD)aTR|+Q$)NR6!3C8{M+4gDSiPV4U2`yH9uidI$~1wHYa; z@9Qa#s@9FG`tqWZXwvf90n{;0B>chrcYkCFy{X#LOFZjC5xa^jUNIt|Xh%d-CE>%< z(b4Q7N-<;}%JXxT5e54pvL2>Osr)`7U3IO-=xi`sJ?7Pm)$s^%jrtRjNwLP$k$45} zX=W1WjC+2-{%lb_hz}%xdX7BsTL@ znNKh30aD#`Gh|w;c&!Ylj4UP7i`}tfgGF#qyPSG6@~}jGz9LQt{raXHS7aWl@&=EY zN_@k!0QwqJjk`IvMD>>P>{PVq{5lWUC7BKLNl zV@c&dE)(LC20H`-F$D$cA`RM9WSPEh?g)!m+|4IOp8!$mU>$%xYseU2;-Rqh5ofs- z3y-baDN8S}zJS%FSbYHt%j8Ir{wjM?6TSZ@Zb};s=a)XRTf~JSEJx(pe7|2ZsB32J zHu^wp|5e*8=ac{Ug~)_~UL2df@}}NVFzJ%3AWi@iCA3V_cT{4|)OGekqxiLw6~ldJ zE(Ugat2hmM3BMpr6_&DOmWQBJrbj@jKRQ31Z5*G_+=a50qY6~kC55r3g13pU>rN~# zm>LBO3z7t{^M0ujwd#u6 zu&XeldpzNp4PI`xUCJ(Kj_dkmHq<1Y#+rsN+XD8?ktAx z$z&`=!^K^>fa@h+Iw%>|*Gr@dtutOrwkqL^Dg}sakM&BE>Mw!ilo^cZm;uD`uvfO5 zU`5M(f0hc0iIgAEmUdb2osB>p(po4ZNwi7hRad+^NfuFRfhI-_=>eyhSw_OZ5Qy`K zp>ExaltjLuBi-OFf%kgZ#M31cJ~_(7GQdP(s$teKE~h=bCYZkJBX>Zj1$RN*7lO;h zDj|v(ML_%l&VhO<1hu|hEE!CpW-AFpsQBP1E;CB@0Ptjdb5m3kmA;(Y2?_a$-SY6A zobs!5N$m#AUkUc?tWzPd;Y${Jt$SW$#FUA$N(mbYXba`Z5d~I6#D+yXC zGqf9>k@M!*MpE9S6Vf14L{s(QFjf&i6K8Jto@yajFDP;ROkA~Xn*l7u!$iJY?K2iO zkYsEqzU+uSHI7(JUutmJaaT+wncR>GET`zw1eq~_`m{XNrGV`$nH>1oH8Scjf-mF; zi^wpeHqiA&xPGJzZ#c#WhV|JdFtiQ&_M&})kU%>isAj}e?LRWmYMROcuuEc6OWf!r zy0F1xGhkjI(!(4kfxRIe7-aB%&V`j(E~%|6pjVz-n?-ADEBP;Io3&ApO)IIf!2AvE z!R1E|0Kz^^99GbdoJw;o4>?y!G<8vNAe0e=pZBs=@6HSxOlNbiXr}$%?wwW3+^o{hh=jxOg6ME z0>FeZREmd#Ap(p5HQSR z$t+zb0@_1ES+eKh-I5XzH(@xPz`zE4**|-OwGFZRWvOLwzoS`!&~eaR`aP^`yte%T zCorH9&{9J}2Lm*v7hF_}Fl`xh6)~*&*pFFRK-ns6n8uhk`SK8!0i7^PWSdz!MnWa^WR5|nH9)dSSSi8z zAcVC!6DEY``u5AYq8iZ}ARs8DJTzq3e;H@0B%CDIq~fIiA70+{X%wGR9>Ku8e29rK zuRIE&d0;zu;$@pH9S5N&U~0On94%(h6gy#13HI%)(BT7^Qv-|B%)bh$J>yhvRsbN zE2Y=)^BnI!1HA+Yp=spWCEp~^M!Ko_+6yLmqxk8x+aKhaU9w0EAu>$%EB&H#ABc5SWr=WqY={NUl;zkK`8bSbmfZpFQf zkKEc*4)Nx`+{KsoZ}GA(p5USa7fP$I8SCj$RjhXFHcf#JUUSo`s!aw|t39!oUtnNd^A~s~ zr~Mt4nScP9nPhy_eaH6!1;PY6HSBF?9qp^uC~;GsDUV*bjKl#yP;gxwU)Wv9Q?%Tm z8DY5}P6~;_&VOWYM*yiOo&w~*IQVU87*7Jw*kqck-(Wi>92YpiuhtO|GA34%c*?9< zYT3|g1B7rD6P^DOv!r4;W5~8qgp=%E$u7VEH%^Js3`>OcO_D_+QbfCN&xd$y2+s(i zFsUzW#($)^Wb1y_mO4q12?qU!)dZMjw(v;Vj8K?EA4y`3pHiNaQiK;WV7Hlvd_7jJ zZz)83dh_pjH58Co!e}Zan>Pz!4 znaVwWINE^CKgVTbRn50TV%f9{ucWC3@7E7bvCvb*mN3vs%-1Ue3OdquTqPnTwpME9 zmVBEtk1qqECb$M9#~{L-#YM(5xEScj9VW~Pu1E?jy@B!eU6|iCbXj>Bv@9ioa9v-$ zLOrJ=Hv5oVb(OLb(qsv$%Y2Xi+)nc`rITK8iq%i+q)=te0h3aQXkZL*0nw&=*zQv? z{Mqk&7(3nXwP3k25~8XaHNd;O!*0KAg~1EL!HASpyy+vl0}L7vF_753AB%IWQj*Ih zw13pYzBE+x#u$qltNQ9q2rV*=H*_TNbUUyEcvF?`fUPr*%D5nqAmeI-t&Y(BUQ+^FTAH ziPjBfvIZ?WeN7&=;CMMCANnkX`a~wYY6&>|ADo=@p@x%8OGn_Em z_PePaGU~dwGgmyw^ioWE9&8pmFLiqON{=RO>hreWE>`2_`u`{GD*&QQ-v5U#K@2QV zS8)-8G7vFfrKMpJM3Gz?7FiH5Ft9!QRE$$>ITaH{#lk)eOvC{7%rh`B&-j1ljok(H z?*6~;;^V|S`8>}&GxJP!5p)&USX*1;0v8@B&eBu~L_|!AtP4d2pPT~u3e_G&B-P&i zU{c#1-n2Lw5=E~{{UA{rOg%VXr2#$lX)wxEipt`H3sXPwhJ7s?t6^`+r9}k*wNf#` zcyU63+Ijxvf-1695T1|1f5SwSA0yL2HWjzwR7n5^`LQliuK%=VxQpEv!!~iAoU|3NvrPu^Xa!frROam~?NrQNL8Sc^^1#+t{*5x*1$uS+Q0*vP~3IGWyPXXWOW-1Cm0UWL2St7&5!DeglQv^LFP)+{#!_P-R-}H z%}z=F$IAEk$FDvA@#}Yd6^(~lQmw)ngO4fiOA=BOcmX(0mvBSDF&&we1oYC-0MQk{ zQBWMEQ765B7!FCw1Qob?@AULATsPF8(fK-CLxd8xDv9}l^oL|qyqNSyIo0G3qnd@H!pW3?=?^! z*aa6|NiTguet|ut+Lg3I_-xqI9-tgLgv7ueU+YRN>?^nT9gh!7i|HBNfQ2 z6YMX0x{;kILL=BW^>QOF%?SC>8vbr>#18r1f!%zB8|jbzsb^u2k9Q-z5Vr*Of>bxs zvMtI3d&w*}qL1=Shy8TE8#$v#NCxcr>)gmebwY;29#ZH=Iswn_uus_MMz$Lf(hGL$ z3vNUm{sP$TYTSr7>evYO>G$1;2I}>)6>$F4jqGoNGQjTl#f>-tw_9M(*KsFHIwN1$ zt!>}u8Uqi< zVL#H>gY=k9NIvWzPI?d>;4mI`?Ta3y8)(!YcDoxM#0370U=O+PLDEftb0b$$K?ajd z*pI;O-gYo)1RNH?9@1ejv4?#E?D<009s&FHE`!No(9xaxcO6VbK7?4qekXe{d9Dh6 zgS}$RU~(RDKQu>OCJZKzQ0D8fPoFxNEb9vXhuwU~V4@EHBd}ZV8BG2JKW~A(Rmost zW=zPhusdEJOp1Z$v9N!5FqoX}2>yrtw6-U?4E`Aodx423Sp%AS!R~J1NmLu7Jh1!q z_av`@=jPPk(UYvC^lj!!9=mxGQ_$rW?1o96q!q%Ph21>Wla!-g+hP9zdm;SuVc(SQ zN$y1h53tX>=1HXB4Zo&nJCBhs?8!9DM^DljvWl5V6su^^Vj3U#(2JxEW| zi}WV8qz|zpeThBkNBWZiWFT=MjzmNT5hvnITnHo(aVH+&JWt|9yonF-C4R)81du=? zCP8Ef2__+ACMi6${bLSjiAi6;ppktC61l0s66l%$c7B%R1e z2FWC&NEXQ^Ib<{$L&lPEB$ud~o+6*g6LOE-CwIsL@`(IJo|4C;7Bcl2IZjTHGvpyT zN$SWu@|yfjK9X4FANrj35N@Z2@QqKg}sE`g(gBG>@OT43>St9#li$( ztT008CrlQ`3FCz^LWyvwFhm$23=}2_6NRmWjfB&MlZC$s=LshWcc|5ng=$CC)~X#- zD<;R)HmK#R6{_u4YuE9lTCrM}j*%UA5D7XOfoTWR_r$&9cG9}zUec!Hc)?CmAS@s@ zmOU)(zzV@wZ;FG)NhZVCFoy2Z8I^!#QUV>-_nrtJ07b6_UNFnSz9Q^w93_DtuFg-- z!PN@VR6&X)BVJ11Cdz=eEiDbtP$Mmu)C}y?Qqm#g%{+J$r^wXK8Fb$g2HDJxC8QOa zkjAGBZ3#x`GVDQuiVvR%qqL>l$C&jyf-*wkCqRqgV=!Tu0Xlr*GU+-RjmIe4u=XMm zxcH)_5-4ghT*p?jpA{Hk8k9L2_khIFGJ8WwAdSWy#|g=vVtrq z<)J{3(P9y&04Kf}pee=~oQu+n{}3pVB=L5-?XY2jv{E#&0D3bK{aC;FOr;qd;5=G_ zMN9%7!&54ctO3<2efZo6xv%X-N&zbX695^2c))OgAD}zH1fUK0pyfrb08Rr+00n@t zfMh@jz!}gB&Bc)_Z;QleLRtR`!^F(_mf6t(bzc;5HGO2MZA4|9VnS8xR=I|Pq3;Ne?4IOZC^A_tWGka3)Kf%B9 zbc@J}!^L&GJD48dHDu|c{TCXqKUlJ|MAck-x<>fUszxU}J<;1SZLHL)iC28c=C+YX z2Ux`JnJ2n6N^|5*l~Tc_{H}&qYiCT^F|vK}9?kXl53lNZrR4FNGg{fbK9a_BHt8&G zm2YtOfPUh5ivcOxOOj*es|=5RSm&RV1eLDIb!*8K9}@NY`6A8aG3!-~kJf2V3O?TW z?a8X`62B*VoBmaDXx7;2`##sSy&dIYal`1%*vr32ysrEm61mg+ynnHM1}R;8&-%a> z(fXRfm5Z(qNI8CS-QRWBE+;-oaQa-8+RJr%+}4Vch#N8sb>|0d)p~||>HdCZtp4r( zBQ^Yf7pZnOG}JpZRnX{+usA+=*A%Hh=Su9pRre#$8+@!Dk$!+gpsz%tsiM7rH(Sb^7T%)%QHep-!MEo_;#GMX5Yt;wTI?79opOS>YVKnkJnzi zmb>uc>f>eC?E+rc_`Zrea4{~pbi-}UVh2y#o$fcf>0kFU*4_4Qu$pbeXm!!C+K8H< znz&81b5d<`4kft$vMaK@O}#Rg(aKCC=up4?C(QK@ z?pzSMyPJCAuHhTMRhHRYs3@MbvZ{OAqUvGW%VL(By^emiVr^ok?!pw+LQS0&4z>nQ zr^IQcHwz{jlLjAN)O>Wwy`pYA#@HF}X|#OKr3Lzju0GgXduwcmnwxr8E?u5F=-!oA zA9mf2PtCj0{#=Vg6Nj1Ydv`Z$yEMyfZ>xu)+SAh#8-M$wpJwcEJ(VWkR!Zh36h(cw z{4FWcxH`lH>};=NyD~c|3b~mb6tX~ z#fRgnOf5&p?kX7^d0f>vKJ3?S(yo0D>Fr)Ur_nLv8jaA|wW=0WCWvf|TThCz?Qty7 zqMQ1OJgHS7S$^}A#r9?8wuNC~ zSr1K;lfTtCh_0+O2tBu^)8s{e8m;<8;JR~TWLDv!4R;^EdQ|b|ai_fMW0IXGZv0*p z7WQsqr@E9~S*aoTfhNmAYWH(d|x zDYIFVIp1VPuL7-kf0wRmxqtR#gPiI@pmt*`;C$d)?Ra%J$;G6;`x60mDNoO&z`#U>F%?I<)7XTuZ&7>`!FY| zx>)SEYO?RpkfsJLTALa*zL93vX}QRBz{aF6l82!W#|m}IgJbL}eAX7tSGl)pW~&Zo zH};J9QrdOf-A-FyR5~edR(st$*=88) zwC&xssru{EK+j#X-2>99B{?>=xe;IAJbZMx?911&^DC|nC@4Ss$#!Pm0j>GVvc;u4 z`bsu#^32ccr(2lc@yw@Uo$2L8hQ497;ReZduIC)8QhqTg%W!HM`bO1M^w-g}^X*|@aLOwq_;2SVfXA7?pLRV9bE^R+Mv&$Vr|!os-oZ4)xE zDaqd#Xp>hkFREzP#lYePEl$+k4z8;`{_DoF+N+DJ-aRSRD%v#LWN%Wn&5EwIU8g+H zN%~`pd)j5Gao7jTuC90Q+E&LFXq^}zEq*NSD0$=k;LT3eb!COdaq}lzn-#3;Qc`r{ z{>N3-U+mAmxi;p@;|rxpg%iGn?p!)hXVuQ}c9S=6?_|>bm62BO9CiinTE?)0mIycsM{<_XxXCAy$TK;6E-&)pT{wvko)UzjRti+kcJD%lu9vpf%*5@?{kHA0*0k@^ zHlp1YJuBnokDRrRe#?K~Y=ha3CiA^yhRs9!8<|>vZ9aNVNel1$ zqg&o_^|q_*KDY0j1!wy0`=Dpv|An)I-sGtR1MH9Vm-wj;2x&RORyuA)AKPO$daD$+ z>NWXru+6Tki>&`jy4>ToN|T=R9wc?zIJZ#v)uy)dnPC=YUfxlrV>%af?6~xy!01h< z4(7YFySA_1-_14RbC;321I_D9Mp_&jwX6HG({C-euIXcSWcISO_m4tG77cADTiWwh zx`}XMRySY&QR%N*X1FZBnwfoTMy~H3&+#p^^~ZIHx-fQK#)O=O?FME4QJ_Bh%O5Al zY_}{;p5~mJQvJzJ`efdx)a0qfNyDCHC8`G4#P_y)lb}6*Ta<%QN_6bzZjt^+pF~`# z+#vb$U`)(@wT`i~6Yj(b$}8Plt~T=UX&>mBlR1Cz=jdwRavc+&1$#ri*5A(e&R=%i zb=yl#w|72{E=M~}a(3=q%yROJe{)-_i*F1}?i+Fzjp4H>a z)1N2tb;OCz zzpgl*+x5mt564!g&JGDK`@8?5V{0Z|KDy{}lOvn9d6%y`F&C6NbNW>iy)zkF&S#xc zrk-na`N#!}eX8dj7jK)N^*Lpp<)Cg0TAM#vxMJXj#hb-3OJ4uganXqhcYghFs&v(b zt+^`~H?v!@I_J}GoutM2%`~!>4nAPBeB8x1%dC6Pn5`A=`OApA`g0OyU6}jqw+SEZTv6E5DkHBo$a;pFHI{!{E*wVbA(esyX=#l6BM z`vsfMtH=KSF?HSMvDr_HJezje)^v+>tMKI3Ev+WL+GzE(=Y~;1nd?Ljd)FWD@}c03 zll|)7zl>e`+mb_TDrCotAGOxpeQ2ZOo*CyR?QL}P+|GVG8t;l~?6D(AGHZK$$I1iY z?ne7H-vyS~teC%V_sr_jygMcbZ;S{%{JdBGA=>^Wait}*PV4;sVq0<3;3ZLWd%Udf zb1OVaxX-Tgw_5YvCuaI;kBhl;P^vObrLyGkwZXTqC%*2PRdZ*EVRXo<;MRVhtk*wo zzRK{^$PZfvojx+AX6wdNaZcLlnP$@S=hDV+U1Zd%iN)W0*Ey`LXf>_#;|pyD&6Ta$ zA~?DIjN54Kf!lf%3_CriRdHND-3l^oXM&xdRip4{OYXfKI%V3D2Lmonn=09T$NqMx z@7xOx<~_5f8s7iw&#aID{p-&i;}83PSpA{f%j2t-xOcVg80s6m^4>eC$M}WXZ%>We z=yj)>Vmm-hVLJ{ZyFHNe0hk&CeuCh z+S*)xzj{XEg;C8LZ~9})U9ItlCPy68yp&cjVsA^6heJyW>-yIic};m#cJa=H+yn!w z@-a#7S;y8i)-OL5zeCpLlzOCBK}prye5v!iZ^cjtWu=8hVBPS$Q; zw|06XlQ!FLP8?qu*LQyQrEYcYQx~eeH|rNWZ&}`S2dnwdLl$-sM>y}c(fZJ+W|Mcj z{TE(scviFE>x>dh*SMC;#j0tYpB-?2IkMWy>x}h;k2ixJxkRrha7g-iD(`a3c-y1t zjc4YR_X)dSD$$J$>LREuV0xy&}g0H9g$o4cFx79M^E=u zhX>5jDeLp3cytw1=%pP>EB>;nnLc+&v~}diYaP{BCN4X;;h@&_qbi4OQ+IC-)X_Ft z=9Av`TbJ|en@kDTrK@X`)^?_&)=$WcJ$cXq6_KE&&dAh z_-b9S+u~NWg?+bvIXj|>i{=aOQPDGAou6&yeCx63LyUip)yH1#7K(1{Fbh0dFY@fn3#89)ciYtHhVXG*q5PCJn{zyz3QMjDcL!4;FaIc&pLUbuura? zX#BM>vty~dW{etp?ZqF*rPtaH)!niB?)`Sn-%QNe%l7p>nX5A4 zYvGCqON~0|*%sKQ`kTzz*dlgn*~l9MyH`uQd+fXX>&uDiI*T5b>=@&rzqXy_4rBL$ zmz*qyrv82G-OVQ(=EwQBFWi21^!Y{^zeetheWj^UP1}E#mi6Kn29e#D>iF;1N;%#- zEwOIylj!xmSH>(_YjAUVkDOa2>+W2A(r(G6s_8m=yt?J?7<=$hiG|j@!)@oc-D?<= zxLxr2&AyTDlMjii+uXP^F6H+9r*&6~{qrtQIn^vVe@INyrXydXK8~I#IrFT!%5dLk z&E%?2jR!=}*4BU9FI8~bE5UHY)dWl*=&63i?UMeKFY9%SlX@3#`ZQ=~ ze)7!&XRd82{pi@^dh(wxHN!J+UDLm?`Qm_~W>wZ({Huxm=}P|zhbtmmbl6>2JY?5# z(+m3-EiE~?zOlJ#$;xnz>Dnh7RqfoN_oS1RbnLW{c&{c$BinA?6KgSG)Gg6Gm760q z^DhZXYp)u19l2x549z{o?N=SXzy5K_m7dvJXVx?(AA2p<*)->_L4K?8iTVe$QwCVf zk4awgFnYL3Qj&k2NpfV=6p8iq*HOeLS#!~IW0mz|CTZ6lecSkWuw;AH$)){SN$izc^?7UDbk`dZB^A!<7P6jdZ6Exu>lJ=mf9x4QjgkF3tBQUj2)Mj{dLu??{Al~wyEDVGm_nEk@sh`UejM=`c2kPNgOyj zF?7>?g9~~Kb-w+kONu&=(^|RXW#fg;)3n!KYNzr#K0&kW>-(tSunCg5^47_=BU6(! zAAP-IJZi?}Zg&iCj1G;vJ^1X$eKpcKhiX5z+cswjhjt#+Gw-%LbiwdliRxvQ z-!>LkT(Ie0wQ|<5>Y}#GW6HKai+*jEnYea^YRW?06*`)QPYrAx(zW8IXprD$iw+N- zbgyJ|^D#TR6*bypY`5UjoaGO$9?~Cst9Gy6&6*BVFJHRy>dL)A@wazg8G z=icoz8z$YJb+^@Cx2);fp%1?`PE3o{?Dt0#6}{neB`d#uh$>2mO!{`YMe+rg0^NJr zmHL-n_^9WJ`>O3K+ZbmSSrO6Vy+?wZ_rTPwn?)BB2UlGSz2#V=7u)B0zn6ujMS;}^ zR-SO%d11VD@wX=j556|}V}IGqz+DTiJMCV(VSk0K#<@z(h2rYqE~Zs+hj+z}wmcp= zxFjszShcIP+poLz4)ri+SLRvFnU-&IVQ^Vf|G+9!!|b}W z%aOIB1(rpXL4ArJHaE#HuGGkzym*pv{?O&5u+?^pPd5u~%a=XO3Jd#|oNRJMCN;qjY_N5`u3I^8(2QxX)5Ig|k|fp#y1se8#-?n~43qhp^RxksHaYpL z(M*-u1_vBBm_E)sY*$rgS8zhV!+|<4-NhT{Hk-Zp{P43x$EDK7J@r%6tgO3%f9yXH zCSF^RY&3ng!?pQ~4VF|_=KGyGTiE2;-A|X^ekxy>9#uI!Dd%BZM{#lWP~XX`S{O79 zX>4TLx|3bnjRB^j<&rN+8^=Nc5L~V!^r^6mQJG(~w$;p4_j+zT+o5aemx!&M?rz)d zQ1N0_(>#l*Iy;lkxOduI5oq++-?^?`?%{B>l|#-u+fMF#+v*r+s5kA}+cU8Ab%6Wq zT{)8Kw20hVn@11deEs^R?C{l!`D4$P7YxXoY5Qr}e60gJO2yfmHcI;T%ggudm|v)? zQ~c?SVNvF}b}jpENDVvk9D46g6)_ zap1+@}IaX@yO7(iA8F{z%GsemTv3%ZD&y>0Q^Z zma)~gcgLU5D!}wV+WU>9qw3B#4~z@T)>%)UAJ=77f!X~NMI~RVSAD$p=B)jN$6v-w zC`>9{x-<04&Q&@CH&3=3-`%9s_TE}XuiABW?V)9pC38=^yW2mh;_YbHJlp87omu6d zDt#{9ec1RT6aaTBC(qutxar_MvrYAWD@Z#%`G9DKnrWD88@psJ8zYC~<^~2+;(YT5 z<%$c{f^t3`@ro*+IMMDz`+U>75xWdF{`R}k;#&{I#Q3wXO=x9Q)Y9`gf!96m`nL4@ zlsjZhrNyGCvnE$8X3uQaYw>}A_6Hu%*DR>27?JztnVY0+YqI}6|+|#`BEKK^|02odFkDQ`Wq`g zo6XE~aG1X{H?5-6zJzk44}%`M_8aykYxFHiQt^r0(7G3aI(^=|+l?yGDcZ5R>8h7A z9nSV#*y&3;ZT~7|iG9>2UrAMUJv3BHXVWds^0KGuv&Zh#@NF^0pqYP3
~>Mxmc ztx-_zU7a=`W3;a?4Afm|p{qCCZGef{+O)R!&$zW;lhv+WMB6ULR(f07Jda%7YI99l z>xAOBO?$sS-Ryn-wwm;PV1TNh#CAl>kUlHMNqgToX4|V(p^8oL;mOvEuI}n_Iq9#S zO;m1oN_sF)SU7iM=USVuW){QFm_~Vfbu8#SM(}WH#}1v|7W;J+X;RmH*QjHbZ%;3?>a%8R+OpY4Mut3kFKainDE(H?rCAGwCZqg)yJfU|m7aNZ zxl8VhTiN41_xO&}*KRTPLR5#G2^s6M2en%`TD{i zPm+qKCMRY+8y0U9pqlW;u6NY7@!HWTMh=nPHpfOhIqEOjPP9o6>7-AS13 zURf^iFk0QxGqAnS;Q5(3zSYs6eN1%9y+Zdc@Xo)z-u3vhd^gRP+gu!d-Z@X|bX0V% zhqGhj5ZNG)hh3d!{nA$aD&8-sr)peqX6e8od#~vPemL?=fc@_W{KhuF=YJ^oYUsVb zkB12YYlg-?pBl1m+K#ZN^Lq{N^0(RusY_`1R;!e|y^SZ_c|UURy&V@`{3%;s^|1f0 z;g7ynB|RvK>v4ayzDBLtV7nLh1&yDrSvll+L|x=#t9$pKJfD8~>1NxRek*eYEk%mB$Bt7+#e5hCFe9U6wcg<>UcouUvzh)ai(R zeOumb?fcn_KE3n(cCIQrEaLk9KEXFW&oH<-@Xx;0Bj1+R>{>PJ_S+7ZZuRkeP?^-| z`nAH?+AFo!_guBuIk6&Yo%+Rs^F1#=OiR4fsZH345nm0DulTj|$s1jBPqlLNC<`8P z_SmBSe;>U(Y0Z%)j~A7DZ`<_8+!L!#pBZ!Vj9!yhXPvb&&P`2mx^U!joAavsEaq=p z>^LvwbJl`xgDe+5F>k$i!@w0wV#J#lb^Pn~uXiS#SXFxJ!^+&P7gpFcTm0LnoYnco z(oRdWG@329IWTzHn~URS&**Lai)Xmj9R0f^=3bbUFmu9h&t?sJe{+Vq$E4{eO^frE z#Y~?RVsLmuyX_Ar-nwyd^1`#?DgGOxr?qTlKlN(5e&M}}f=z<`OMZ`4Kfifh>c^s| z*<-hLY3jLEx~1usttW*WUrlVaq32Vpb(uk<*6(!?6@2J&e6_vPo3&%V{J!SUlHZDt z%PMwjwtlq7apR%Alg`c9dG2PTU5$72+u_kTYWpln(1FU1@%xS3!%G6+Y3`f9!ltx( z=I(ZB){vNp4GH?+l#qTOM?4Uzw9AQ3cvMRrQN<0yUlCI zY5UHU9=sD%2?fC5Ylll-CtkmOrzWdsNVMS)zt+L493Vb$kDw)~aGwoY+9RIT0ht=*&Rvi!RXx;VR%3$B|9@2NG-fAzr>bP-S%I71kdatVRnQgka z+p5K_PIT@%zF_|sx7Mm6!C1q(xeGSAKYqWwdB_0MO%5S8ZRhQovHJbx=A$koZuw(V z<3r=M?rI*3m^`8&?b1V&mV4_8ONM$G)%3qu_Gn5%?u0vI%B>8JWw|Gn>o;B_+Yx^% zQvFnys*(aPXKDW1&zHZ=dlBoGJLEoh)3J=)Tvi`BNbK7)I79Q9`A$|j5RyB*3FEU9XnU3bRwh51hs^DG?PKJ!#Fgq=PyifOIeLBT?o?YNZJofj=|0QWpYQT*@0h7g8lSqG zvB0qET-Pm!Hrcgq;yPjdDAVgFV>2U0s~DzVDEj(`?9B4ub+0@#GUdm({d>zUQW#iOtFrDmP~t?A%wjdbmpN$-XNJzfS06wDf^(fvw&g6aUny zu`M>;gJZK4K@NNX<81Bti)#sZ2I=?ZPCNprl(*qHkDc= zOEc31ZrE@^chcatJnzW#B!MU<8Ru(>@~_)j5mCpVHek^?YS$o!aItnxBETPOSBJkL zSymy!S3}01w@)AwIDY|bM1}fOo2m*?XYHygup3f4zb`0)?j+Op0~nI#+A`8qt3B*# z0PJSdIYJDzuz65B0w939045DT0pJMt9el^uGi_{E({2U#Jkm_7AMDux>^jn^AWgKe zSx!41U=H_om`Ff-I=~(7mx!+pyBN@%7-|2B_}yT~b{_3s_fS4!}+joqW<=@o@_rUk#$X^fkC_qQJ*TKZD5$#EUL2%zkd>~Le6wn6lUy;8P?4tqL7^`yy z`D4SPb|L^9Aa!=br1+c(7z}qE;$t(U_7Fe|;)tp=)9MNPD1a@#pGE%I*r*)~FoSyw zOp5QR09Ux5AwD*GYL5V5!?4Z@}&XXPTk@$2j`S;07IZPIC08 zI5mZP156q|58wp%L&T@_9|i!Pbry5<9|LzkxUX^aPl6kKt+NLv<)>KyPq^P9KCMqM zprsQ1v*7N7@8>!C$HCnh?jo2pzi9wBxL+VX#b-DG?N(fS4lsdxDM$aYaQBD1 zilcur+}+{c2eT327l0Ss9}%C@^Jne<1V{fUgz1Rz>tU(_CIJS){Q&VPJwgF(;9kVh ze>B|oa9`! zpdH-5arDoHdm!AmIr^u7yNy|F}-~sm=#HaN9S^F>N=r2JSA;NElN%1uW-~#tk z#HaKR1GI&EIY<9-a1Vg{CP)7ixGms508<|@8{iH1--u7?|Fiagilcut!k8lbMwm2w z9>59iM~F}9KMY_D_Y#i&W8m%wcO^&vB)Gf5y%(k)U>3j=?)QjK>+`ere}SWa9Kv)) z_-!z0e$xPMaMvO}#V6nXS8?>`+kXv5e<{LPA^c&OjRA83zHomdh8ilQrG|=1GmR$1 zSVP6IiG~Jgt)ZfBq#+`0HB=l8HPlEe4Hebq8Xbs3*Ijl+KBk zU6LsY*pG}Yw>Z~qA&s?&!X{%{9C_MNxLumd69;y2CAHEwCJpu@pEaS?!o68Jd?cJi zmsc6D9Y^74sXT4w)utE$lP4D*9i39%v@n8(w-e43Dk;9>%9 zW&zTP=`ztu!QTY@&4M0G3h0d(fK&p%|L;FqK3X=KKm9dA?!N%AfWbO&q!Bm`AV3+QBVY|63UChq%#j6v0Kg?c55P`9I^Z=x7cdhr z81M(6E8urPBH%AT8^AI^DBuRb9b_%m8=*&H%aq3IPd#CxF&~rGTM;DnMVrK0prO zBR~T%1>gcW0T2S#10;Y403*O6KoH<6pf{ixkO_DT&EC5>pDS+pIwt(LN zVSw9!0f2*maeyy?W~f0k6&) z_Jer<<^h;vV2*+LH_X3b(q2Ui<}{eoV7kF{gLw+(DVUvMc80kT=0=!tFyml8g82w$ zOPDQTE`hlOW-!cPn3XUqVfKO92j*Uwdtqk5%!2tI=6jfpVK#<27v@};zA$}ZUVwQ4 zrWH&pnA>1(gDHh6g;@);7G`^x?P0Ehxe8`D%y5`BFl%5sz;u9l80KM^<6(}6`3>eb zm{bxt0tA2vfFZySU=2tE(0;TySb$~OV6CeiA93Tet0%QQxkU}27 z32+Qx3Rnw>2K))2lGc#nVhyCNf%G(xh6d!424s&0NYA|MAE4YE7FpYmT20el56POYYaI!LN0LUz>mV8UM@ABZ#9f0z$VZJm^njg)J=0o!k0BG8dfC#_@z!3l~^o0LI0(AVDf{Ry} zx3;+J)@X83nX$3ZwQ?u-=y+5HpM>ZHoEgL^#uVJiN|>1g7XlZ&NFq}d;py2t-o<}Q zjUj~Iw2qNBbHxeH{gLYqIGYC8b*94loZe0T2(M-vkM%|E4#try^EkB&H_h z8XZgMLeA-~*AnusJ>+dS^uhfge*+dA&38@I$!2Tb;ZhmO%Rv^WcZrP3%FcnZ1-v8=CmQ60N3-4BJqCMvdHeYK z`3D4wgN6i$3=O5>%<(2b7bVlfwiof}*@IXLlR;IS&4wX~l+k0XsnF8Pk8I+GkQmTT zkV4Nyavy2WQztI<^gOhPjqDN9>1$D=Npm z@Ji3maxGs`Uok3ZFW^tw(tBR&=h@&$E@8v-RK=SWsWK`*JSd&mZyqRE91bVrY;QVq zK@@SOCuEt+mQiQs+%V&hW4_VMdkl!m#T7-<3nT?Y5~Nr=0^N9j=5#PU=Il!E2BhJ= zq;Wu2j3hOIIrd8efl97cm_$>BMmk<$NsXbp1ZgaTRYr_)GKxRqOFU$fa}?q3NTAuG6&pt$6R&j&_yYp zEFKSoVXn`U+DnN~DegyR;*xM=LAgGe-kTyPmUm=!LP}-|n<3Q{C}Gfp)8}|Oi~Iy& z1B#=dRPdHGE|qz)45*L75omWY7#fT~&yrIv6>}7{z~OZ%#TMfErAu+OV~T*jhQaZp zm%vHHU_|i4igqD>4N(>yiT6t~a9gS%GLzl`hnIlS&|}y{<8WX;l~0nB0W$C>t_P+^ z;lYONLshu2i$z3qLK@!d_)*#DU2e$?vXlr$7<|){?zjas6|4{~Nf5!T?>^(r7XC_J zWJ$jNu4vtXtbAmz(g6bSC7u?{JXOl+mT>nv?6fjeR@1b;V_DFaiV=FN0OSXK3x%GO zr}RBMrPCUvWybRu&(?n z17BXUFlCF3Vs2LuM9~FgL1Y?UYXPTGq0dWqif<9h$lMSKDZyWd$4Oh%hq;=7#}6-J z32jUE5YqI92fh)qemrxdMo3%Ew^XtVBANDSj~5;k_ZDz`jms8r83WV!sq~=bV)%gV zr}$x%;(iC*Lcugd=nyj~17N9~b`O5Ofnpk0AuG^`@faUp0eZm_1U(1_oX`kthf5ey zk6|G6p)rC0mq0OJDWp~Jo1brh@;CZ60)5SprqB1EzHo!^+z3%lW3UIk(*d0tFu@X9 z(c~yTtds~u>kyR2$Wd0n3e53N4~7Ei8CFpeuqU1i%%F)`4P!ZPlnH zlLK<5H!(C!pOJUKdm3)gkU-Kx%Pfn;BQyMX#6OcZ4<0G;Wmn45yjq zL@Pr@GOYl`5074YKMF%dI$8l;nEr$x1+l9wgpMIO%CO_TU<}mgY79T1rNxq$8u|0z zdErjK^A)8x#Weg59Md4o*qqjt8+Xg)K%kUf=|k~~kPuPyMw&s8aU&r=A`xE9uQSmh zG**o;hGIs7?8JkYn&>l;2`0g`|$I@DywWnNNg zngg~iI4R~e>5^DF^FsdeR-;rFd_^~a!LW>4>vdAP@q7w!k?c7D87Ma zoa%tNY+AWYY&XHJdnuKb`g5H%>L$scmvAa>Lqa2^i-o+uGFo^)4lP6!6NAt!!6HXt zK+YkL_vcFsegkqCTCmM67T5V;pIJj*;p6?}Gf|8;>c>>zCsWa4fKSk#%?}t={v!A1 zMpg|zGyKGh1|-9{(M)9Yp;qobhf( z7PH^v;~<(3^R7U8W*T$z6_pe0nkg$GgfY0^*)$u2+CUelaF=ioFE1B2kyp64OJJbL z%|&2toh`KP6+)p4E{hh&qn>QcOj#yU&k;zYF*cR4!+wm!FhXV~2UcRQKukU9BhH8- zA32yyEaNO0Z3QlL#WnP757Wg`;7tb~xCa=_h2d-tGmYUnjTOog0YnHmQYK&@9igu< zVoH@Pjbr36Ex$*&hY#MJ@$+&KyM#LhxH#hyI}edpAW+2A&m$by+PS#-!c*)b_w(@$ z_X-rzIlR~?h@kXfjs2tP=61fAVqL4PkD*> zWE%S8nH(l}8kzg%G#~_9mLMNj4j$>55I7cvol4mi-J$6zqcQrHStAL2F8@aD;k1aKA`FPhEx8ga)Y7}?T9*k zDT$QwLfwLWTyRSyLnm)En(#q95qLi@u?OT3-uZ9>?Zkn6SXQovi@d}x3fTeNib8-C zSC@bQh$~1ICr;w<Ey-PXm9sxRU!Lj1R;lu;v?};13VTD_2(!Cx$J(UA%n*6tq+7AGj_~Ii6fn|ByEt z^o??yg25R%Oq(xl0el^4n|BKkIlF*vVi%`+vW*HmH?|Ec#0^(3rEhGrl>7fUA5ORh z4u$OY=BdlYaSHGa41~<~@BI|QIeGcGRNAqfNe~?j@bzMNL@sH$G-z0P z0-T@7hYDOjkrUN_)$;?1#3C<7XUh5y0>xYcz^{-6-pm)yUxYr#)6IkL+Xlfs$iv4O zd?%NoA}=@EK;6BSBow`~Ga(~Tg0V?LMhHlgp3YsoP7c@M1(q=nUOLRo$i9sP}*>DUS9+Me2FsJndL|Ks>ng8+R0G#%1E6)Q#D zcpp28$(?at#5|W_CAhF=J6vIBJpK>=Q8f^amL8o#$;HpLfH$Cv4#McGNmK>VNAku-l6Z; zvq~XQ1Dr}#ap6#^V{<5-`_L!i=+ujUk&ogyHY3eZk{y|nhBqLfeI${o($pO2%j@wZ z=%vs%Q6^U6SN}IXc)Bw;TsX;NjL?aj3NROh-<hPYTo0u{IO~JuzA))+6Y;F_4iBnkdC*nmY}klm_K*2ouV} zRM(8QDb0+F=easv0=nvAJqi~j(}l0@0$EZ*8iNbJgfz%F$SnF^E8~r(Gdh!LD}n5q z3td~L33D}Mm$NO9qQE>yl7W!_8Vo8i0j^F0Tf08JXwGPJJ$e(WPoO-?n7w#2l6B)q z664=Ho}hJpM>9yPc&b7~BT1ITQhi(oUe3@Z0eD#u`c9@G8B)r-x+G1S)|2Mx=j+## zPN-!m8FX6>3G^2GQMZS;h>?lZq;9${L%&m#x}80om^mXgsT=K$>XWIJ^vCMeKuqho z6)++kHbU3RA&eSSbP%Bpx(QwM6Ob^N;CSVS->8UU z7>?y9?D3&1AbcA|BFV|pER>d`7YM?R7Xl<`36w3F`?(oqk~~%iuHRwTcR^uFMEoeh zsmaU#U}S}5I;NF&N87-v5*=zla}p^?m1HTE1FLyCS&=zNg>6TQ5>lyxHbz&c>7pK5 zhg|BW(I(C}YIbpoK0BM90Ua9Q`V3ke=2!n7b)<#9p4Lj1hNTvWJ2Z#^eBB#_WvKSE zuukBw@H8o2Q4?Zu3Tw46@Mal<506x4uM3(Qw-gSkO83)*)9L{sRN;h?l%vDVK9 zTBwCWHz{8?5k$t)VIq~1P5;TlC4?WgIwV1`7Y2BXOMzoo;B@?w9MsFR#K z6pK1PDI8<~?dm8-|E(U736#iD>3E~dp5KNfOzSQH)+xPMzN2-TFxgVnRY3X+$Up%Z zBOv4W|M6`Y!=ea{7EkvB(C`^jjD^u5NwCqt8Ja`tC*N0sg&QiFs9ykf>@ccAB|mO0 zgjmPWc%cTSfJPzNx1G-D;MnB>!WA|}n$ zAg1mZr1|1)gK*s8$i$Wrtm#|OHpH#B5Zb9?PQVv};VrtqglbILeOYW-SZPjhZUOJY zFhfjs3`n0&pm{O#9|@JY);)R-8_`c+S1=$1z1IpMMr{jxGgYrOeAo{@C-5Os1(v3Q?X>r_{i*R zJjjbT%A#df^n(S9XqjbvMoKaQGg@axF;3ehhFf%>6HtN0b}sJ@0+$%9Tw^gi2Mdn^ zy4NQiYtxpxcpnL6!B7u1#$L;~R4JZ)jpNkL94^D@G8IF9%F6P29IKk9GFcXhB}lGJ zRFpFuPvtBfgC)dv;CYS)r8`kPsDjD`s#lL8F5%F%1k#CFEGAtsoMh*Cln<{ITpp6a zBi+Ekmz5znPz>?Kq(d8q7qbqmcHH?o(g#j^d3sQ%I6Du0>3N=BvTe;WbTi@a){;1r_|rDjE0(v z_`VQR4tW~LygMGGMKhA7GCeKi5C(A=0VUh>v|?HVc#>N*R$3&YYt?jH5XLOR(adtS zFgcU$QkBzT0{m-irYA-@75O6`vkmPZqB7s*nXzB?Dk-m4jd5`;c3d~ zu9SA{aXT>Uh4)T~PM6B0m?=O>!EOcQG-v`peu)(p`cMzu8mNTBO!+QeI+l&5Y|ZUd zQj`HbSwd_MGa*5fV0NQGK|&Ytu%yRf6MJu@Dc~FIoM!|zosZF}VKUv9$UfJ{s<;@5 z#(s@Tq^EFcBV|UVn3E$X<*Ldo1)^jbvt5bmQIMOD2ZK;W+2ksg?_)!vjiNPTHn`DU ztL%735trG@N?Yka#-&0*5hwlok-eOh+z_iCk3uuRtf+D=ik5}JfV|;Cbem%rYns5u zswXq>RpiCTr5niERac5%`V>Atudm}m==FW7( zihe~d%M|Sx9NMrcD~0<3ntsBMJ-*{d?$kG4s^Vl9$MBH+XhQ5pe}1;C+-4MXV^W|` zUDZ!OseI7keE*%wR!+grPd%0E4pxFU7!lO@E^SDG*l4=DmY<<2aHdo)Ne0yJ+>UpQ zG?5m+#Y?Gd4a0M@W)9nE+W!z1?LU^)96~3>C=Y*L4!X|{(`sz0V9#Xy1ea`?>9n41 z;#Uf-9R9!4yC+X?3Enx*u%feaI;ceg0y-|G8W?623#Mmu>x%L#=Ak_IGi}72ojcRs z9dSm-UD7qg8n^(;F-FeJ&X5kpEp@(Ai28uke zp-U2nFKidUQcsz0Smi!KN!d^s>NIG6awSncnf`-#P}H!yYrv_{w9;1oGa1cn_+=2p zbeU`gX}@1D4+XDrm}2D4k3^)RzPv3Q;&BwCE=$d1^||~Pd$378y#HtU@&i6np!Yi& zFULDN*Y9I0(}1>TbO9JOWaOZ!aylwS(r8un@X~-ljJUzj_h02>gL?m8<6#spp(AZ7 zeCx^W2I>E_e`rvCFdl6h^?9W}&(pDzV)USlJ4Sm(*(n_I0y0?Mh*(zSbdd_$|1>;Z z#-Q6%oQAMV@(t?tFY!cfA`c(sa-oitzr(q0kC<38=V~~lDaymu6Z2W_#0%YO$(;8= zWv~@IJ%NsVAzmAl2aSzxdW^=jM0wLJv!M-L3+;{?#8%|VE`c;`257bXR!HS0uOx@K zkq*_rGAlAnD@Kjj*-U-A`IVioRCAhG+7KCB6K0pS@EhoMO`S_m{|cs zyYJikcOzaVpC5#y9SNQ464`fs5HpDWVLv47LzP@HMA(xt1w!i{)DlnIr;xGQb6&hj zh=qkc^N$JBiw5^2LdFzxrW+U6QfN&-yCE&+yLWwmZ{9zN2z%3jxO;^y2*t7BCsz7} z>iy;aXgS~~6o|1$I$3}p>;cSKEbuezA=sWABM^uv$H(DF6|@_03dBGd4b7XJ1q~Jw zG((qu`p2I$bEHJT9W6mRT=qyG119{u=;{-j9VJ@Vt|%2w=Fmx#{6r(ujnTdyst6el zoY2KgiV8$)S`N4X8#7m|8x{Z z6|8}XPk)`lyvUBuPUKyGCsNqUiSb+Bmo*s&{xj$Nc{erbVx9_M0)YOmU|+?L(sAVC z#=`tjItP%5D&kKB2xTH1MZ`duJ?UUC7!)bPnPO(C9D0Q89PD49HK7Wp0Os^4KX_(W zRH(e6m1NfFsDrNFQRzbujnV^8IJrQ*85J4j6@?f@y6nOqt7UzEsQN6b^CDRM5=72X@UFsqj72M$udiU z2d{(1;RYGB5OQ}+CVP+$V{j%}w)pJ22Ew_}GYsgPAxl{$3ES;4w5QDM3Ym(=jM+Og zk>J!Xj6N|cA&xu72!*w1l$5@+jDvo34G{eg)z>h=xO=k9=}B(%WWty(2u{QpH^}GU z%!+aS@c~3WGmifc;TXN5OLiLO1@;0PYisEFfuPh(3EerN>_)bP3#YWE4LLx&sniS$ zFXqNIgX9smt_%1Pbt$*i`l5*6)DTG@aDd8z6j6z z)C*0QcOd-fwyFQe-gk#Z(KHVZ3MwiJf;q5=prT|H#D!jxf`DMatYi=cM1rECtYD59 zUUR^JIp?tMtT`(RViquG5fBAMuBxYZLDc)b&v$o!-1B^cYfW`^sIIQ=u8t!z0xiRL z>;;7XL_NLxSFZiz&SaSLrwcn!qHyYvPG{i^1(Y0UD<0zug9NF*{=S}vipk1SsoHe? z1kWHU3j(}w7Fu;_K8zBDeJ4uUP+3$xm1&-6I)40kQ{0AN3d=2ERlz!I2o0nRBgoTU zq>Qs#`oAPyIj;?^lSml@rmDP#EfOZ;4PY+>Ozq=0vn#o$_9W_5_4xg&qKItRrR4AIIqRA^&x&=3(FgSHed+^MWv zV|lw{=j~h(X73P{0T=C?L{W$CX`2pvwdYs8AE#% zE8Ku!>c-B`+rvyYoS|eYE!;DqWb2Q!=~PXycsLgD4{<8_sgeqloxoS6JFpIUV*9=5 z@vm4_8`GEJ=%>nFF%FI@z&;z{OtG(Df6m5T@~k?*#_mnjK`9)9vmmh6 zNJT^sztf(VzTr3wrqtmg2QV9j4jCtnVRe;m+*Iye!7Biuqp`HGL?&=;4~;r(pDX)Q z)!f`h%3=F9KHq5al-$w<}F-Uz2$qo2O0FxEJ>;u1Y#ggn0D?E%?Eu0S;RPw?)Rcs= zLkLG(J^BXaKo=AR;{i((*C%7?J`kEKD=aJOUm2eE?t%^hbI@LNFpBA@996*1DQNiN zcrV;EZx0k~K+Iu0+Y$CdC^rORb%1?*aDOShz*b1fY+5ZbZu-9M{9boo?JfrBB23Y!F!s0e# zFv{pzS$g?MtZ76@9NjATf4~nr*$C0F5*LhRTuB-q3kQ0YN0&P*UvQ%uc7U)g)`ljI zXNvLYFOwuN&rX&r_qu|Vu>q*6W5R}E)rO#7m93JOD&+vW)&bW@@${r}w}dd~3|*#K zm7g*npnOpYuxp&QpH$zl8UY`bcPG(0pfl#9BA0F z4hVAS0&8ioGcOP(cwh_yuAoaGGLQw`f+I8~RDPh=xL+1~64tO|1;KONV_@?gltUoB zhX5C0p^|veqoJ^l4GlwN#Aq~+<43|49#kKe1tD&_T@exs#5Cz{40Ak;0mqqfvoXDU z2zU6<6e<^s$Iysa3{>f%QK@Xw&0rnj-|~w2sx0%$_NNQ1O$V8(I#Ec3)%iclT$!ie zf~aKw=QNb6QyF)qKV^BcxT|?pwsFY+pW2%)RpdeS%EAhc`&uR9*yjJ}g|&hII$hLf zq1pU*d{)krR0f2^REm#-%2)-1fnLf0Z2%4#lz#22#R2zb(ES^g z^$m4Fhyx7vO2bMSy^4l5XC)c#prSkXD#Nl0Ei{~HAgQ));Jg^_E)jNufHf>wR3b+a z96b^Zg$?6yVjUeFz(5&}b`G^eAs@o_5+6^j18^FyHyqYe)@1ZnDPw9K3mf-gV;*i* z5&8(h`eH!^TM4>+X!(TeIYgigu<@V9)!z@|_wtAHZ~fgwaWE-`x8p&=U?ow*S>Q>@ zh4QYY5aAjUm9&(+|HWU`iEmoC)%}OTvMk+l4vL6-s)RLGklC1+Kv+DZtAu7ES6F@# z(M^-UVh7>gfS`nMk)d@rx{vmkkaVO#&l%8s(s?bm3$`+PC^mXAkSViNg|Q6S+*I{Z z*2)|SK5?dsjnW|2zBuRid!o=gvxy||Bd~$GiOS*X)7uTsrqGUD8FS?%@~`ey)Q+0^ zv^bRQzH%-`83||#EqWEd(5q7ey6W5l=0`dH#X)W5$XJz6aKn)@%y+@g1h{cAZlqwW z)5t~f3Aja$HqF!<#8EkiUG-g<^TzZl>B7u5y0LRmu%|c}DsL#K>^+eN_b1T%V?>&8 zUXPC4IZilAh16g6se^R{8!gA1!E`=c1_FIGJ#Hivt~snFspj%=^$dIQNSI@zLk1w? zj(CjEC=q8!;A|b1rRrud)tn-@z_$bF2`5(GXebGj|Nmy2HU}q^gj*1mSDyfXboCG8 zfOKIXjQfP(kRlym3zrsR<4jNJ!8jW)Yz2Q2V}j!&RRN(nfSZKy+DoCW6y`iJkAL%r zwVBRvsQCXqivAFu_399_((Y1DTHqcQVVx0*z1lo%b-#F$qtY*&@Cbx4K0WiItO}(v&M)a!b0!#*U0DBHr=S=BrAyg!l{iED(kHUj79o#;Od;J0hrM0%Of&2(H zoDP&BKH6lmMq72*3l5~AQY#OA(N!N9cEN1AnFtIO9F;;mV1=5|e4{Z*^CK9hm<8oJ zE3OsdB&#q11?joL9hab;?AR(U;eu_b8gGU`yn(RtjyGX~FFXM$`hc8n?O zHn4>Pvs_r0z_x_#>j8Cwwz{&-gjHlX2Z2WYA42~J{3M`F3s+47Z#bHUeY1gy%3M}D zqR3SHk38z4XKDE+*6IL_e_8j~^2)i)JfK$$% z2$NOp91u*sLz62k9?>kZ_5e@iQjLf6DQvFsmvFRHSdRv4?}BgCW{d>ZgoKfZaAO{t zBvltSKwee5=3iR`Iv&BZflxgSgfnr(*jzXj7tF!&KCT}%7X-tDPRc{7FqcS+9`5TB zHn$?7vnU+z>}6Z>D4pKB3StBM4UAFc+yq2G8wE(#zH(j6o82eb0j7I8f?wrblS-=r z)C|fUPif-fhH|DH_{MXlc)}FY2O}7&9yCiJ4`jfl(q9Oy#^Ce_oD|1;6$lv$g?^94 z1fG9eHxw4yppwz4Va~|RMCePZuP@StLcte(t=#e&CTuwnb)ZKM=tL!604$8VtNB%0 z=~Ql%M(0L>NxUgBRH$m^W@a4x=sL1F*!bq~T2bwB4Go4d<~YtLI3DJbk z3BPE#4|D?O6cY;&?mG<);(7%}bN%4tDmZif@Y*{12JLQa1byp260TWdZUaL@qC*+d zACBXpvp00GG%Umo;V~Svoe3QH<-iZpvDmn8tG&2l_!YqKJ^Wt7?>YSP;CByxneaOY zzhm&*2fxkmTLZrp@LLMMH2BSf-z@k|gP#x$x+q3dgz-;*7xo5c zuVC(5`8W$x;M_To+dwD59lnyrIWhMFe0LSx55c=|TM3+bSA%!vj(%L2|B>MC!ral1 zH*?>N@5~+j_%ioAd}r?H2X4@S*x_h58;)T7v3>~56WM80|d$+w${)G<=>mVqnv%%JIczJy?eoXANH;d@AOg` zz_USC{h0d-co(F=aVT5(QXG9yp77N?`k*{%p#z3;8^qjEo_Ie4J}4hrpaM$&*N6Y% zD{b)YAwf>d0Um~5HvEd3a=yZ-zbS=hnUm>sGyr&ZU~)F{r>6niD*JGz5mCfut{ zuS=jO7jc3Z{0RLQu09Llp;x3UTEeP5x(e}V)m2iUUsvvjvd1}C7{cMa68Ka45W>>$ z0O0;t^Qef#(2(w;AiN9##yM=!w=E>74Dm~xbYlS8KHcdV8VB%*xk65j;(m)p6-V_{ zRnb5?s(JL0aN`DSQG_y!WcP}2$}{|687VhkSM?RgHlkO#FIzbV5o~&t8{U5y%p_Nx z+OHqX$k9O>t~>p5^h!CFr?wiMHG^Hn;Jey&HT<6*ysnQ|TzXXRlqgw`TR z3}zmbvzb+v!Z=Ztna65J5GrYCT!rI}OB{zgTa-cQV6nP+ z#PaeCjSYgC0orB{WSjnAv=@n&7*rcOgek`vLRW|?V``;5nuh)0-~3ab)+(R&qJH!X zEe=MBb-6)4cnhHw2iKF*8}E=OC^1-j0QK5-mY*Lj0;?xC%l1O>jm5C!5`cl zNMXTNFZgDTu*dT?dk2$!22O^ zuMJQNzp9S|*L9f7m{_;OhcfV;0L8OST%+M zB47o?8X1E}2?eZx7odeQuvEY~X$3M=5qmvDS&#)-^>MHn4i1!e}9CBb~JcRyb@WwOeI{wIEw{y45We~cnk z`cMyp)m9}^qY0;O;L0_5;L7d2FTi*PmH2MJ@pqR&^jpZMR<3imr)9SU3|Q} z=w-X$PVeT5M<2%k*V)oa|OX|v`nTDEH4Mqgym*07zCar+J(O*(ZpH8ZcA7Ps#% zc5oz;zuU({hYcU$AMp2GT)(y%#TG)$W*Zx({K3-)TEWeS=pY)}Ayec2uRbiM^c zKmfY4SD?Y|UV?A9CmMQAoR`9>D#0>B+!?QP5hg|}?^1^?Ie6JrUzox%rP~6j?HV@$ zw&!5kEBjxZ*Ty)2S9%#aUG>44#gNc(5y7FtUO~#Mkh(`SSpTtO;3N)C7JHccQ0onj zgW!E)?3+bsGt%z{t8C`DO1>)HaB{kmACMBP|1kk0KRD@B>45wtz&s#hi}Q#=E}+}P zd; zaHO`fB&p0`5eBCAffY2nLP6e`7L|16#osWG4GSu0RKt!4wuHwy#llA^V6RkFJ@_?` zxW@>O3_!%dj|XnuGzUuzfHD%gFITt@ymI*^7zS)KPlCJ{YqWe(ev~(exl*!K*M(4t zL8$P(FEA^heNTXI*~Y{7WTT*+7r`$U{;=H_K?*Rwp*;-rBb*oK1K)`2_lqBa+7Cwd zy7gu55u}zt<43v((j7xnMSf!7 z4`UQUL;xik`c)C+26HKJ9R;p&6i1(ioJ0h#288ajDeh^9FSA=FXSwc zrmU2cDU}n-G6MXB0?#7&E~7cPMnY^I0Sklpq5(%~AWv2083@?#l8UB0qUK;IL05$T zD@($a^5hM?Azx-HJyMppm8!g>AqJE{DELEZg+pFNkOK5!5Wi5qLhO-17jlcP7;hL& z9d3tIaj(=nWjdCsbpEVY7|XBajd3gG?ZWkiG8cg^A_q!}AYqgh@@Mw{L@%o6!$Or0 zB~MDZ{V4|_)#Po(*{Q-~X$R6;A>;>Z*Pr4LQJq7*Rq}%Efgo2a_--+}VtrNe@$brS zJf!vK6n`(ns_Aw857NV$gmv^kNw144y%^9*q3p*&T(J;m0?02Ca{hbGQP#yui7Dk} zql)j}%gY})j|L4(gmmMf&Z2~r80x696f09xmX9TT2V7Y`e=6@WP^ws7LMw{(c?@kG zu$6>6%pg6~>_5f(s~#aY7!$SwLfeAv6za^M+WN}!w5*~($lverM1hpCmBXBmr1B4> zZI{pnjQ$_v|4;Pg*OWr2yaSmOgmScmzDg-qls>i!@z9=PJ312lW6u)=xlzhiXqizm zN?8i=SX3#Wf3FW1tDu9Z7ua88&n?8PjJL9U{(ZcGkc)7Tw=%{!6}L)#vfwJ)>o6#n zF;q6#YG7X)13128D~`Pr_H=?|Dq9C33~E=UEKnbCOe;MijA=Un)C4^9urRKj1rW!x z765h7{g4-Ybr#lC0P3PUz-9my2fg6yuW*MZz!m^GfGq)}9q^*xB9;JbgYE!v&fac6 z+7A%lJ}=GyVBQ{>QwFF22vcF)W`Gj`&I0%YpcG&QzyN^Wv~Hk?D3ocbHD=+XB1d>K+V=DOlWE{Q2n1ue}x=Reu#(+%G7uqw}QVVt&#x)v# zW8e$%(H!2Sjb-y|3T_Ziu-y!3+`hlWW>51Ba|()jG&Bca$mJAlxXvxB@;)ElagG6> z1y$Y`R(VgW^1i6b`{F9^ORBsds!w2X*%MZk`hu+pBUZ2p;k&x9 z;^YN?`1FX3>k%6Yp;bTiwmgO#`1U7W6DF*Fj|GJE(RY&epkOsj&Hk`84&l&c0{g@DF>mMz(A}K6VOU>q!^eq1SEyy!exvP+ z_B=klL37a7t?K4O+wCzbU;TiNHg{EDP9Q~W8?Z0Mrx%r~puhNzZ8ttnRCm$FL>^Jc zgP}!)G6OnlJ=PAT-uHrcEFGnbz^{@=7^_geV1AYIgK;Ad%CrR-&C)?mgtV3ED$_)N zm=4B+Jty|!*rp4-_W&%S3f>>MMIUih+y+AWAvA}TuKmFm+ThBVyg{xw5>Uq559q(* zm^Si+>ESpE(}8t$8aLt?AM%dzAg>r6)=k~*qoVBTu#gLZr?bc#9udAwfQR$;HV+9g zhZlH!q4=HP2lMZtQ84p~Zm^F*^$z9#iw~48-6KH7cm|yqtS>;xz4z3gVl#td1t=u~B0%Z;H$wVn1Snl8KyEB^cW1Z(!%JTad}Ikwv5Vm|1t<+< zP|Vz$Fh9nY$XpUp}YtD6TNLSAdd#1jtQd?g0$%DL|a{!Ea^QvpgZGkm`Qxs?o`%IFcyy)T2^8EnU(mH?$CPlb5%1jt=s@DOufCqTt4 zhQ~2Df}@}>(^;~=ZD{$1owXtU zc&`ED&XJgftJ|$V3;YM9g}5uulaXEhr(~b+0C?i3&9yI*Z!cR9emlbl(mPu=*y|D* z-)n!LtYIz?|E^Jf3oaAwj{|PaYGvcV<#noQaq|iZUBo}Jwl#zBdvvX|u8|K<=kAv^ z_5?g9r_|#*>1ev)%)rB#KhrsvQ*V&MW?Hwtn7BgtWzSq?H;HZkunwgMdjj57GdnSp z)EL~TPRVCG2QZ3_ZZx_@UYu}i*lIe+x8T|Mdb@6sO;gnCX)h-Z+`ijs87{ZU@a#9Q z6IKJ=cggO74{sC4Gjj~T*p$N7pr!IbW3$MU;%Cmcnt;6a`MXZ5l})04eD~b2x`zXo z*=$4hs%(;Rtwx;fb(ELR)1jt!h^OPMh9Rl;kpGnMXZ#&9Wb#{wVF@09$1R=GCx@I1 zw{P2F4wR?%r^W4`=8$e_QyR4Mv4s5HO1?MtE_oQ8Wx02bkpmagar9j79vOH4%DiJ5 zO+X$QgX|aFBe`SE239N=0lyLJZneBm!Y`COcRUH@p)KDzblZKBb0Dzps#%C%^}lWX zfaJ{Yd_Q3jlt;kj1?KVxB=y?UG|Taj-%Q8$q3#b!fc`qoUWXxn+KCOOWIiOKn_8{T z%rOQ$`b5CsN95f^k1k>$B$ZNv;Sx9~DCS1@79c9KUv&h>fKXheGlu0#L%@zOlZ=Mz7FjmU~owhmnS!Qr3E^U2tIYSW)MgMMj?E{zmFB@;6` zE{d-Y=}U*C8%}&mw&)$Oc)QOF^3$c&+Jz7Jek*)@zNq&&#qE2xr&i+!yma1yhf6A4 zPjMC*bDpod&wnX*;O<5@IK_!_2X-^K&nJ_Xic!rRfv!HM?e=?o>b?0lMKX_5oT3jO zZE=rZrr{oKe97$;mzJzyf9x*rX6w5CYjKxTT>1~&ElziNt!4%5i;X0wVA1K-%BwlN z3AgpmkWNmgxXga9zx2=Hx5oCG$6bWYYzQf19I$^13 z-R%^|r4C@Q72dJNRX_5@_#~l9FxN{b7xwv)S(`c(e~Y(LY<0Zb1M;`eC#y@uEq?Q~`8F5&7(n{OUh{h;Up}(3~>k z2Cw*0QM6@DSIB?VPv2eFc}>y6lhZ;VKB?pD6CE_X`hh1@cdK z*WA7R67M&pFyzE+FW|53X3?FCyhBEvOxID6A1?Xy5%r7w$D9FCQhO*L$&oby)))9z zr>8VE`fLsK(G|Oc&+}*7F0E}_#~bvcA|>OWbA0i-7~LhOKtIwu8XdWCmLJA1OWAkZ z8Th+BDzWqoZ`jrS%&b1$PjLb9HHu8n@D9U$&pdOt0RFo7pBH$Vzt!@{rkrEIFK4{* z#WDq75@>3;;)y5F2MnvXhUW(aWgJblf%GIF7cZ?N=Vv6}`7zrM^1}^!aUxO1FF!rA zX6r7XZ<3O-x$jT#t_|MqysC@xjqo@y;yB;)?#csY?V)_7=}t?skMe#yzRJFR>=5@p!e4Q0Q}gx?OQ65K-SfgB{;1C|opUblK%X`)?c{urZ}u$Q-lHYtM>6DQf^0v( zJawJ!fyuy+^wGC%_WSq_{rA2xumpXRE-YRUy_=T}AJ<3R5%iNAc~?GW2jA{)(!;P; zSe_}T%M-WqR{i!C&at%tx?fwf2Zls=QPLj?cQ7;a3UDx`=>`3A4n>Mae(9}gXIkVVDLMGWek=w_>IA@43;qXg~4J5 zix@0q@H2x241QwpBZD6pe9z!J2H!IHhQZeizGCntgD)6-&fqf!pE8)wU><|H3_fA- zF@uj7e8}Jf2JbU?kHNbP<}i4N!E6Sz1Sq}D;4KC-8NA8h4F<0>c#XlU3|?XIGJ}^G zyvX1M2G28ij={4Go?-B`06A@;{1pw^IFUgKgB*j328_<2gh7r$g%+bTC}EIeP*I=J z8I&-{F{r4==nP621K?#E#gNhoA&Y*-rjzNVQqcbRBkYiB6 zF*<`12BFOm#wCAh8aQcEM_&Wt7idwUscGN^IJ$$>kNk#H7yd&hICJJB9!%zBm;EeuGX`9t)y;SqNiNQv zd9`;pr03nx^e4Hy-GZ!!I|2Uf-KmlQ(yGzXJ7I<%fajI19~ne^tkRmg2Ur81zIOhD zU=nJz{Al1$OTY`VXLyAYD|rfEqc7N>+=>lzj^0C#@`F(>0La^aZ(kqscVsrfD}enF6jj+Gu7Zkv%WHHft!@^IYbHKBZB_ zaetenfp*B>tUIemk0ECq8;yN@0PH<3`^C5D7&1|$7Bxu=(~sZNvBOxR9o6|uzn@^w z!S=|2{IO)w(#fIvHBnyK+t;j$CFzr=*oWPB1KjuVlYVi8zmSPdXbH ztV(%=>F?Vge<7Z{2)%Wv_W}v}?{_IVfsBYDV{8`V_@vHxgKp!Kv(IAqSwDS46NyEmdd3eIgMG>kI&`|t1aiK{;d6Fe zW5D&qcK0R_gQguOIb3%KT(s=aqKV{0NavpVr=0=MKGW5661ly$@U5FB#=rE8Ts?`5 zms`)We1-aT=pQe665+p%&>m!p<-bClH-0j)XqC3kU^>b_{pbYCDI}@wxxL@}pgy&$ z-Td7Ya-wMT?6BI%-?UEh&B7MM*XiTa)5Y|o&4?F`4vok~uJW_?;4hIm0z-`7)# zr$*e9W3v(Of5y%&g{*PV);nGX<4G>9$Y5g%ne(M%o#nYb0ngEHP?16mdo;K=Qw#NF zK#TIBsU$gndA5sg35?h5wLcw8C8J9Rd@BBm{2VEK)_58zD{T7h&R~?^x6=<}rxCre z{41OGIDRmjl5=w!+3>E7Ls~zu|G8Q1vpY{GwkN)A8N8>Gx0`;f5y>M;OmEGfb z&!ZQHrf&fIiCfe2W}k6*%ijOTZ( z9=F=CHrl6=#+R9KKq_>`{~ZKrnt{GRRc#&P_-WnDEkCAb0J zVb$K_v3$Zfvo`r|odJ)Zzj=5p|I%yj*>O{S0GH{kP>ba^U0QXwUQ7$XUmMTK7|XkG z)7y6Wj`=CRHqm1&Kju}|<5zXie|F7LA7Xg*Z4JL~D?~i$>cB;SYhBu-Fh~0_&(O6? z4DVC1^QO5q;swn|92mpvrPTM3?=b*8K+Cc$npfA`=(^tp`K!}b%{iK%ozT4Q2m{13 z2i}++#Xl~Uo0?t+dzf3XXT_~Zep>HC?+Rnk-t#pMXdcNg{wmcuvl8rk?zOyK;AnpP z!C6~-@6!R?F7f5IQT&0S4b-(v!QSQU`eqbF@Dt|jnX;n|%J-62pj`w%bm9G76MLXN zm>J$eI+7nPF3OVFVR^W3%DfoPPqs~cu=u?Z;B_ie8;0{y;n|kPJJH_fCfN)OmYO2nucXHa{!a0sWple>`ul1% z%NfR>nyazt+D2MFU#vri^0OYF+&bD3#*>`LuvhV5UeCCW#v@bY&v(I))IogI&wDo0 zJ#aiBu?=lBkZ*Oxr#yY5ImXv|)CNC(^&yXyk>wa)np1>De}3w~vGsN&AV29FgZRGu zt0qZNukBHu3dw-peRz`8^Nc(M%QL`s)(Icp?$8aJdqr3t(y&4Iy!ee1=iPI*#qv#W z(7MEfkFjZMG`AG>KfpXkw>2xz#5+pH@n05jFalT(`(O9 zx9j`(-crmD*S&e;ruoHuH;W`48Y73BS$Z#!&*B79ot^g&P46n`b zS_0%W1SqY^@EQ!~7+#?#lt;M$B|jKm#_&=Ba^D0fEn)ZLV(g^ z3_r^7!wf$pK*a$8O7=5+FT?i;klQUl=}w04VE8rxO1276k-_lI4ByD`4FcrS1t?v| z@U;wIEkMaC0V-B7d^yAa5ukLb0J$X$U&QbZIP%@dhCoy*hC6fePI+4*QFgk;hL`EOa=;H(^VNjaD+~WnvF(`=> zaA_=~k7aZQB{9r>40C5t5-s4;C`ONDbOt4(8GRIUXHXKs+(!yf5zgogO2QaDl+i;N zok3|Za}Q$f3`zn8TpGaW{*2C`WCWuRXYLG2hB5b{0#poPbOt4Z8GR6=4`g%(r309| zA9H6=(qF)({TRJ3qcbS!!`ywDJA)D*0hjh>bZ1y01N3%yqA_u<2@e$&;97jEzyFI8jj%PToCU@6y z<;4*mUM+CE!tGP%9y@Nj-XUU|F^+$@ku|0Hj^QsKulH?F!^fy|&mAAUH0gNjyDQS~ zX>hL`YnB@yXjO{iRW7kM_tw#@`?BuK}BhG0`iXCTYA6a$vJC2vQfVzq= zjzMW(bC*GTchF;883-E0$%Utz>7`RS+;5V<7w5S3q@CW;D2g9V>nN5r2$g9BomKP87|*aRaUfnSabLKBZ4Pqz`JSs6l)qoEJfm##r>YkP@K zEui7E8wb=P@1lM@y{k$6`!*HTCS82=LyT5xqW@*h6t&5-S+NDh-#@^3mg~?$T8Efi zaSsnnr|Dg2DbXZ5T~4fNbB&g7Y-_GAdH5x6YSud^3~!>Zs7n^N=-EGFFU2>C0_u_3 zp6l<--A2nhwymf>dFdK+AYiO6`uA#=SD*YSoN~G3E|r&!ak>^cpmj1|<0bW<-Cojw z+wre&lfQ=FWqn#+OWPKo)w$3Ut}#;zD>Vpx;vW81cwx@5zs<8@PpQ9Q=bLXRYQ*bXr)q2+b9U78*lalGZr zK-XRvUu)w6JyLMSv2%M%%CB>KNn@fr)qY*4-c*0Lc1Ukbq?QwRpO8@hx+Yu`GIz!P z&p!{)`ZB#!Koc^4iJuLbt%mXa=&Wc$Tt6Lb*ytzK@9t*WO-Z|3L8nu=Mo5>N$22A3 z9Xkw78svz$yJcomvdb}iKo;Y9sM#G!fNSl!$-$m+9-%>HZ=ey)J zBU2mf4&6Ep*4H^M%vREzBn_REGR1_-vq87?=HzEa^OyIJ)AEeBFKAAB4$pa7KAVds%k^LCBmJnWs1-TvkZ?_Ooz~BVJ*2J3wFu+wg{C;a#YMX3wIX-FjFFem zqvcuQVbPj+^lxW-qz}d4c&4=`nQI?hA2uE5*SLG$1+9rieCBesM^yiB`1rOVb)U9B zb-6X=KcP>08?yPQjge#zZNJ9#Vx!VXKfLAGkim>A6b}x>0VPi5xIO}fyag=l+K%t6p@0hT}q>_((=7+zCuJE z+!U>>lTY>OwZ$b7*|mR5qkYpUf440QL?o^4iR1aY6#r-?G9a=K(g_*uU_GCc*0+KA z;3EGR8a0)VL<;@VzSyKb43KNpbr%%k#I<^yW$24T+6) zlWDvb;?f&ViH0Ph_hb|G1*rd0J(q2Uq@z66c5p1tmq~}a-ZLbvYtA$CbfEP+){SdN zYVBToC02_1AyxFSXh*CaEI+0Wq3v@c_kea}WYXL^=NxExg?ps6Bl&M1ZSP%#^5FPh zigskWO=x<(Gqk?vdA@E(DxOW6Cf&U72{BZTUYdVkKCOd0H% zq_0&Q{m1!P7?XkLPM&(xf#!GHfI-HjsPCEgvpp!kZ3fK(dTT{POnXbUfE0hx$*tW8Q>6v8{gTjSz37 z+vHR<=EKkI*S*^u=bN~KlxUEXlK|ET*5Y5LK5`nr5Z+KdjJ+(byPpZ}>5Z~At?lqCPwh;Pg18}aX2J5N66 z?}WI^(}j(APlHF><_)I&JbLQih}Ub_eRy=M&@@dc%Z zA1ijdBR%SQt`5J<^nKmDsZ{=IFZSy2`vrnqIq?K03UP z?$KIjrxl_+4!qRY;m^uH^>%Sx5D_Zz2dcb$>|Q|>P}Ri170uG z=KtA})3rrYst@~LkJ09@*Lu4vy+19lZf}S-Z=CS5Z2x{U49~x5sLj`$(&I;*J@r2$ zn{UWpX`uN*V{0#@&%5K_kYDh`OY6D^m2X;3MFZa9lqA)n3Dv)}yXzb9TiVSqEAROo z`JH!_UkGB`mug}e*Nm*R-Ut||I8V#xIlW@Y65$I<`EK=C9zTejWbq?OhjIY;A?{A9)4ZnwZzxd}MuF z#O+=u*XF&}UK}^PnH%C|uk~y5D+jE2T>m5uf9wrki&s17TuU*I@*n%wzZU;0c*B>M z`)PV6?jY@NG(eR7k6Aj+J#iG7@GH81u`H-v5KU%Q9 zT|*6=&*t8LNLJ??crJci<5qjbhkYdK{M5`Hll}>!`LFRQwHDBThy2O?@^#%lkfS>f7F4_9WngV0=@>nr_-qS&JU>klRo>`;Ohm9)_6XZ>UX2U z3N_xSeeBly&XnIRh3nOLONcD67$vmiMxv3XXqf*d~I%W{B~N ziq~^|_c>2S+&fC^*S2E9@m)Iv^eSCS^>x@=zCwP)-T73T#$C{Vz`Kf{@_;ArPMBHJ z_HEdE@>AYt+krX_c*wEx0FQil=g;<_FeVU8MQD^dmW6 zej}r)+s<{ge@ic`$d%s>$Z%+oOZ$uT?-h^aSHJ7HIV9D^_@qB7?#mN$b-iavYa=cx zugH4NXvu!S#ecfnCddNe_z@j zNq<&cl%M?ebb5XWm4~RJ;_Z z+ZSM=@@aDHU{H4QIr4E}$g(YGCpZQlnrqV2_b^}EDWZpqSq?AwtlVGF#rpephb9H& z==Ec(ItH#52TI2~uIgMshSwR|FEwqfY&7kxB>M9B=B+lR$>OIs&e}J)fP@}O z*!(nZzW7PW^JJG+Cp2@LSwJeL9q^RT2o$FlUAW@7u7Gq2v}~5> zzDV3~c4_3G!v&;n;G+`h9qc&;cjkmI_-ajiKeJ7o7-_%|r zZkhFSZ`k(&GU-(Bb01cZmh~ChC{s=MGwHV4wVU?&WwL9Qk&06$pUK6H$b))^`^fT4 zx9?fy{F$ul`gs*^zC_k%LB^#OLp~GDoga^nlB9?y^_eU_7W+$@7sOle~s55N8ilpO$y>GpSu-)@4S&m9ibjM_SIz z{!GLn8@Xt;b>i0df3)@e@R`g#I;qBr+(ojSc|o(f*D54Sr}dheaB;qP*`vveJoF36 zhm565r)*CV+XW>=PqZr}u^JbTOxd?mOtu{GxzVSPY%VUA`<1UWU>~SXYaL2mj6Wm%i48?#IMory{{Y15U1ULkePg}kZfvUm-DEu zldN9N=Ub-VE+pAb5BvA5ktQBs?znyL`$Cdxc*m{bm9gT+M=k6AtW`vwr&!(|RXjs% zdC%)dj6o4eQg624)tWitiY6fk>WGU-#^A2g4B9Ude_p@X|NMX=(xFH1VIPOhm0jI# zZ@YDD5!lnt{9F5Fvaov^QG4bU5t;f*@%(?*$-b_CVe@cn5qbJ0FsJMD1lfyix@S$# z7Ll_ZhueOuSSM?1)5vSflOl3*U4f3~gE`_>(p~CqWksZ@bU>+L=5m>d*;j+QO^Qk4 zVvAN0MI&U(xB1@xVp&X9Oz?m9_~KNV>FmIOI=zd@P3b4~iL2ek1G&~8oJJLsadSd$ zc`jWe&J>?Mym3Y`DF{kCvgvf3_(|5?0+UU}WPtouQP9yj($y4X|dzZUR z7Hd5&UwPnBF|ke@C42aOg?MY{wc`$y7L#WK2jA8_xK!pGc5~x{CSSJpjg>@}MnE+xcj z_Syuo`#hOZTfY>$pb}!;YVb_WBdcX`+r6^=rk0Qp$FHt?>;lBsyC;XOOD`dQAqRAA z9WJOsH9NaEVMutD} ziI9FJotxCCdn{~)c&6IBIK2&DiTO(PkK-FplUbd%Q2TKDE4ky{X_2Qu3H@g-+ z{Ys`xXndl^@ECEU7LNVftA8UV%cFv3BrTTd-tbyE+vpp)Yt=ZrwbxqN?u&*!TJ-!z zzF&9RG%aVA?89Q$)%Qn!BPU9-SAV;(UbZr9&i#vXz7hMwNkwOtt`t8^H*tQk>l-ol zoH5|@n`Pp8u7{gg-TX#&JbPm`;!cdL>-fei_k8|FB9}kgsC#X?_(H{^dPDU}iJ{RT zvk5tCWiQTO-)C!EN={BWJoTb~xU6B{OIKZol#*@*8OxG9$H{zqKUtqLxs+s1Z<#c- z*;?6&+E-#er=v*n07mnT6BPmG?WA5g`uS-d^*UQ8!?GnYI zFNRMFt6xT}?z9^2F?fm0+O*gE)fQ!BXV*uQhgmEW4>xi=P}8rBbE(&tC#z-O8~YsFX#JhkzB|oggfvKIKlsJ`*ume) zv#1j%bH}cc^&IiNa9r|tV!x~Z6rVu}vR<_|SnSLAPRu&?Z;fJGn!l}Ung7BclzVi&3}-`?!L1_wWo?FW>)y`l>8udFQn$# zx~&#_-Wq83Is6CIFZT-XS&PMoU)5R~weSaV9VT^`?HVhNNc;3ibo2*#=<(*()tU+7 zva`ee>gE0*v1?QMb-y=XmNdI|FVouPWX;40F1E5YvclO~b!M8ElkwBnj-BMbRyK3< z_eaeJm6KYwL+{r3kRo1@db!CnX*qeF`(f_sHj8A_tsd5VxxJiN9gd3N4A+PQ4yhFx zWR;UM%?c6+K3FXFUp>is`Hylk)U%n-^^8TbjvKz{^)UWPmg!BL+WyFLSqYi@%FOpC zS$J)`boRPbajMtF?|mlzB>D5}Uuk=1vG_sS=8bzd|0GK~tZ8bvW}WPF_ySY+n?K3C z-8zSgmaLJr9}@VnW!X=%@5tsE#TVC#m!BAI+sUYcxGd1(Gd3&{OWdM|j`OV`b2i*F z&CgmX)|0QvzQh!DBl7GsH;Fd>fh9<@+gL7(n+|(RbZZg~|mIA;1 zcU@H^`l6_)=yGPH!Nvy-FITV_3P>GwIL8b>PQAYHQ-vuY$u*Sz9VLRSJ~0lJd03$k zyswZ5P$>%m6aH783scexDwsQqOH|b}zDwaB(4^o`0Z;*uKGG|N9%JG6Ily_N7X0Q9 zF8X#xKRQE=!Kok&OFVo1zkdpdWmHsCv*U4m=R+N3Tbdpx;6JZfdq*6{!c#!LN9d{5 z+P#FYw1#X(2JcQ2`BH@wpmq>E;2jSvHbr+~yyI6pLe@p=Bz$UWV< zU!>>yM30T;s_5k#clP_Kb)C;?t!Y%`MbAZwM%5mvqFa6Xv2sGn6(aPDRBuH#kLR-V z^T?p_?Ur7%K24mOHXbdN(Q~Gv{PQU)`pkJRR~?MoMK*0{&@pT^J@1-lQPPdYpGSJH zNlWhBYc0S3l=SlfJ9^Gmx<7B6Dty8ax6lMQKha~p)y>gq^t`U<<-mAVc++pY##yFs zCJ#(63~*Xc&;91@517g5ndDCR;0F4wck%m%eZ9Fni0&U3H4REo(S6MaHw@jdnm0DO zwQ0VvFJ4kIc@|4wf%2^KRE`Ujjx0R+OL(58PyUiV&-my6!avXQPyUjBp2?5=MSeV! zKmQl`^Q`>%zmy-(%AfyB`SVPF$Y1n_XZlC}qJKQoU-B3I<(dAIzvw^D>JRx#{oz^t zBY&xXJgdLtFZGvKmh+!sLG|$HAL~EUuY&67BOU9%ie8O>q+|V8(W~X3#t-#hMXx45 zq+|V;0feWZy8I~}>c5I!t^6n*>c5I!t^6q+>OV_Aue$zFI@Es^y_)_Z9qT`fKd-v} zA|30$DttBlr}0DmSB0-ue`x$r{~0~Adi|r}q5iAr)#@+OvHr946^K`Pl=qHSI#p{w zs)w)M{!~w&RBOMGj_sF{KT@szqv5OMzk2(L^s4eB)!JVge--&xZ@+2$RmzW4YyT;| zO8Jv&{RgF2(Vy!552aVpKT@s#qVy{IORDvMNYAUH|D;;~iS(-Vr+WX3^s4o*djC!1 zuTp=BAAQcFJ3M*34t=IF_YBe^T@C)3@J%C6H;FtwfVa6gAmdrS|GU9)5*Jg`Y)AKu)a8ufMY7K!7U&E=S8*nSD zgf{@X@ciet8;jr<@L&7szxETgzy51K{n`Gm-hX2|P}P3_ul*#9pOp3=w$oMH|LXQ5 z(yR6#)#Zou|JqNL_Q!wir(egfRDb?!KdHtq|KHnBf<2>}EraU+>r777K-FwVTO+G^`hHB_6dKN-N!C{V?FE^2A z58i0yss)o;S6b`u*|wK#G#xtcWY^;)@gKYYoyr;k%rd?@+dw66V- z+BQ2>?q#8-F8$QDs_+^;TFm}bb1nIn(K+Y-_$#ok=6^7B<8o3q$jYV9&3i=i{=&o0 zW-TOdTa8!izyAzbU_PK|;KEtNaBBxeL)(j_p!BH7t5{0jjC3*Bk$Z#$H=Etz$e{_O z;G}8O1y_%dL6&}bUlJ}8z1L)L))zAszrN?6)U4^eS;dEvU&nrWOU^GisdCTkxxc?3Z-3~KZ@2yAr!V_7I9d4qqTQT6dM;7kl>vuofa=Rs^UY*uX9Y%fB`?QsoeW?8?eJj?Xn6Vp47m> zTH`!1Tm516eOSOxI`_)ox9~K1VRU-g{SQycy^}SDj2$K?qRw4s9If+!eCXop>6~?( zERuM5p3=EbaVm>!U zC0|=Q-F#lfhmv2l7d5Xn{G6+DcYD3rwfm9BDt!I!k+z#-ACfDrG98YWzaTmtT5mZJ zd!N+X?KYrv{2Q|Kpl;@-d3T9kX+3`N=jX)YRX^{5OsI!xbBXoJ=cJDLv8N_h*`&+1 zu7mU8UZK^kF6{q)@HWwy(eu-~(0uaVrcU#tE%M1*qa)Wn2P{y@_gT}}eV^Uwe5{gH z3Nt-AcUtqLP{rR0nV<0>$08NJQ9q)>YRfn=7*0YUAsZ;17C{B=Cr%T+Vx=_ zdO`2>7X6D!*0oV~um(>ahnciBI9yDojNjh2X`Mn6-7CHC!lqw{CAZ_TtwAA4%I@i^ zmh^?RPF~YSXGtMRD?Ms*Ebs;SJb8`i{5Iu0X92k&i*dTQ_>qbaCDTK^cV28aqK-s~ z58vwe#$j1K6+WbJ>(ZyT4JB6tgFL5|ej$zStsSy&hmNEfcQ!ubOBs3gx^wc}pSqH= z{tJHE#Fdlzfm-49H#Ct9iaGAxD36mocFk?)zoxn5M)YL(j&w~)%G{2r-alGNa?-M! zH=m~=@$K;3gmZaIUWyjz9E+OB9`BK8L!OKDiFEdc_C$zuDD%{Za zda843XC*EX+FvV)FizKybZhQrv#gb^Wakci>Pm$6*Fhq*zd90qk=@oCC!Hm=hVIiC zy05WBXn%W3g!Z>3i}$zoR+%1G{mDA!?o;~KT9uD6gTB^(drYJ%2c6kQnMEh+@^98Z zH=H+QCvVoapJ`*Q630GEn;0C3-9TjCMkfzv<;xdzFMas%;xxWq@F9&5>+6nNcdz=` zu3J1=p3-Z=@uNrO%fB|x`{Fd5AJD7C^Y6nqIriCj=K0Qz9)!y)9dg6t2H)H^eqO+_ zHZZRsJU4^gTP{tx%lHuTg9}b+_lEQnE$O7>NsfPxVyEQxj;H^Ok0hZ3+pX%8Xs~TtNv1cB6T!bz9oIB&YrdM zgW6~AhaX01J=UR%X)CzJTNUK$_dGu@^Q(luEF=iW#98E?AlnDg2CV=?pt zvsOIX)@?Q~KXy2KM~|_LZ=aB^(#?8O6$)8rox>Bny>>cIzx zC2!{sO>iU?v#-QF>`LHx_cq;+3O?U+qr>{SbiX3yHzM-7PPy9e{4V!w+(K=%j*4H4 zan7cEPc;?4mqd2QvqPTBo1Kh2IdA7uezEubS#t+uIwm!Y3s}8>1=0Dw|G97J0eSrT zn{BTfjOMo#kY4LN);r!v?NokuM+n&)Hz_#DJyqUfaN8G)6@-_)9<*VPeY9hl`Rf$4(8c{=^fBCDUKn;*X-`$^Z^+da=jOX=sQ4Y@uD+3l;}M7Kkt>gN2K~Jft#>Y+pLb{S z^@hH9{y=!XU)nf5?|-rPCU7-<-~aG#q7pJsA%qMiWWKd-8i-0NW!9~(iY5&zW5_%c zGKUaClsWFr7($egBq@qCcQbp|*>|6$&#%w#`#jI<|NlSF>*r=!XTA46`>eh8+WYLY z@4jcv_@};nI?t~)sqV9JmaIl!9_RVu9%dOTy4Q{6>z~_e{Dx0=*_?CptoM3j_f`st zvm8bLNT0ebw6jg7lX0UG!>z$r`}`xFFGoJU|5IOP-x~euv9B?+FVtgSV`g8d$G*nQ zzEF>Sf!VjlAL_F&^WU0!*5kj%%zvRC|21a*3-$P~G4o%j$A5wOZ;e0H=f7-xsL{8c z@xhpl4^YqeV9dq`sAqgIX5$0YGd=(tA8PciZ+u|mZ;ih7jK9Wg{DpePUt>1@LOtWJ zF&lrOp79sh_*|`|7!0vA~`qp=U zWAld^ee0P&0GmHRJ@W@+Hh+M6<`2ef{s8sNAArptYV@sd{=nvEHTu>wKLa*DgL>v? z#%z8D^~}$V+58OZnV$ihpIzn0v-;*|Z2l|d^VKu|<1=L;!&zL3=Od?97e7m|9OFQn}GLR!!Bg@ip{u;e9Y`y3iUl7v-O7>ed}3&kg)X!Nj>Wi61M&zsb~E` z!qy)o^{hWg*!n|_ed}9)VCy?I`qs0)BVp@1l6uy6By4?0QqTI1gstyL>RI2Bu=Sl9 z`_{LY661F}msb_ss!qz8i^sR4wlK;M*=kjqaq-H-TzF(VuUyso- zUweHpx7%4z zOG@ghs`FexT%LJrxSfS{?x)AMzKz#g&{i}g`YaR_Uf!74Axl6+SHfKL&O&2@Mx$p$ z;d=x$U!-o*iHB(uI%-4HWC0nvc7nt$9u_QISaArR3do?M<|Wbbu&B>&)vR(XuWg&g z+WGO&%fR^b$dmU4>)cHI-;L_6sc%O3FpGJSaRa&ZC}ce%Hr`Mm-G3Gmu{`EUY= zZ@9WFn)66NUcNk9nx6pvTaRbm3%f2L7Dt=v_BaQVWxITo-#ihJp2aE7GtYrxhVqbE zxl#c+m-=?sk#o?;Gya#_gc|}<U!p&D#4`ce{7Jt>&+{ zPFw;(M!#h-S(tx#lW2#Jm%t)$pyMCM}^UvwG1CGOcZN-a@9?rHRIs&@rMS%r%a=%T(8 zT0Zjfz5<>OYM)>;`d70ny;DwJ0mrwGdO!PmUO<9}jMgi@0w-IqpE$)LK|mTL_1UDK z2opDGx0>yP`OP=IsPsvMmk!5t*Y`nt-_D*e<#ZxstnQHBU=Q|}p6{b?lqABepe}|N zx1s*6^Y7^yT!oA_G1Ui4(7(pFO4;dm6;v+guaKAlpql7WTgeJvS-d{+gyBAeLv(O~p76k3XFtck_0@doz zt17x-`)02ma@#uz?gTej65AO4>)p~7qEksQqic?-^e0~5YvOc;k|fx0dXG@$7{+nf zG(Yulzw4kAGqi2_bbN2gG>>8%zw6+ll{m5Y#$N(baro}{xa)9CYvGO=kFE*G<=X+L z%dSK9WmUg>ft3QX+T-WU0XN{nL7j67jyPUr8_w?*a04c6O#b4oj`df0^DQs_2JF1h zIrvOG>NiGz%ZbVxU>VhJvW5)n-}}S3;6XRx)5;(E!cBPnuwskR7)QfK?PdOo3hXZz zyR7bX;U>IQnI$E(=d^^1@MgLw=c=GZsxDg_@NUp~6-xi$N|Lqo}kNWbc2U<3M-@hYXKX;()=8`)Q9-}X6KLN|{a>hL8`W@J7xh-Z@C5}&zUq4V#PKGZT zchoMteJmi-SqFNVC&RdwKNDh;exm)HAGc7kN zfAw;ye4;LKT?rji)`EO5gX*}UR9Gd!mUbiLHIDWUg zyMFt9=%3i6#g1#(-e+u9wt9Xa-Uf@7x4DS+`En#Kx?KwV_)yltW*F92lrwR}loZ%? zbazzhd&}GBo2euz%!a`{o~i2-+_*AMW(Q_8k^K<$lpaC{$a! zAaD8|9KREzFX=ymWyZekXT@TF)sLGI=l2Nu+n2`gOv3tKoOs~$*+-zYb>D{@UTD9H z9g8khJ_29;kh58>FunW025ucvVeg91Ew0WdM#ND2 zVSTAWd!f6U5$UASRP;C%M&&nEjGl+`s%f|5T091Y?NNINuWW2Yd^5+iaC{77HdJVz zbx|=QJq;^YMLvdp=Qagq8)JQfKeccE@-c`$I;UhjLw`9mqwVRAPoT5tmD(wBLnE?H zV&Uxk1e*8z+OG9X?t0x6dK`KJ+XmTtI~Zbqrxl0DyC-0GZeGXJC6@$5`|+Am-89I} zZgY0-B=k>dR!iCJH1Nxr)a0XnBO`JoG^*L@G*~_~zGvhT?0;i})|-~6!L08sA_Vg_ zjL3i}!MZ`|utVwDjjL{Wy>{tMi$c<&psT3O>X(=<{OakNm<~s~Z=6y&Ox1|wHalJZ zD;;LrX{K4M$NP8cV6$DOPvO>n^{m(#INuo*vvKmur;vPL^=y^in19Wq&jas2h4sDr zgm~)W{p-xAf*wsX;NBg7b+1rmBQiYi&OrMNnAc26edVklI38S7oU$VW&g|^DB>x5a z--s?MdtYWiLyz$NTW@1|i<1RkJ3oWfyDNsb*n{aO&$JD2dj?GowJ91HhxShbHPvI! zVE&#i-d9HAcr7pvyY%T9>}u4zZR7xK-$#X|D+fFWSL+9%zN4BN5yvl&0)n5z(6OB^ ztkuEsNcrg2g^AC>^u3Z-%rErsN0;IcE4+ZRjobB_uZsV~cix+Tr+qx5P=HvKV zpi^qM?geD6iRm@+KI$LYP5H&+7jWn6$D|u=@%~*>;JUa?CV+O#&qa^X-wtotXfZ7l z689eMaW1zB#&uCs>vt#F46Zd-wKSmDT)5QYy z4KfHm7xWTVS?~O~eG|6tiP_G&i7#Pu*01=Y=Geas!;K`0Suoabt&(Drk`Wozb?sbj(_Qz8dEl9!RzB;r`otk1Z2(F&Z1{o&_QIOIOG!A*Rk=e^_^Zpgu`jA zU7i$ma>p60hzf=?P_>7s92snKkX>$yZrXJmnqrs>3(KNr&U=0_->tbTD^v~ zK8xqAevbVuqL+5$wAXNS>CSf^x6t1uJ%0{4@)|;?c}UwgRlxo+$z8eRH8je$f9%=> z$3K^a4SsdVfrdNJ>13Y3^bw~XZxQCeII|6xHuvgaME3tEH4^8*@bPie%%PvyYwUL!UA&bKonz3d9czsrH5()jt;%F1wlYbDuZ@CM4Z zT$qsB5$}&J+}_yCe*>4UWVojH$NJ3tv48gMH{dxgVTD4kmPX`oytk}bF0AjQez(*P z{mpAiPWiN4=#-*!YmcX<5ee=W?{+*Fu6^!!(R3N=w@df#xawR8TAJ8D?-eI6?|0Gc zEvPitzTB=yM5Rg^5RuTDqs9Y#Xsi!ypePH5^e` zmXG%Ds6B1_;ymcI=FlmAtb6WSwWwTaN%z&FO;OGrpRjxD2dJ9v+tzgi_D98@%{o+k0QI1Re*SOJp5Gs# zYkh>}p7&B;^~do~<^G(ib04AKiWBFbHN)?P=O+dPv?~Hf#~xK}7Nfm0yQR)vR0LCY zsz#}`$NsuISGh8;2tW>anWx#^LA4}m!-15CwFb+$%jb@XFA-|Q8+2S0=V~Jee z@18z#KUQeYH>Z)j}T8Ci?ltq7txPUmB)>{QQQH?sG6s%l=#1x3e)$OTUl@ zE@O}M-#0lDtvw9ZQ~ZcEX}z!Q0>_xy!x23R1!`@JgRFvf40Q4u*n z3AynKhZEB=j?48RwaynYj?0pck?WfxHw?^?xnVq)4UMi(zKHQ$bTzdusUdf=e9&wX z#&v1gF2U^x#&vl<|J0c>jO(&Mb=T+N$lH|K4_k`yU9x{%47h{wT@-g5KB|s<{pG6k zu^8tC6qbKmgK=KG_Ud;?#yBs}CO;UcgnZ+^5#|Dn_i}Hh{kQ=9UE9qu#p7cz-piJG z`BpD6-ixxNnNS1y{Lry|Mqu2R8;52!@xZt*C66o$w_w~CJ>3geu3+4kgFai9=VII! z;g3@m4UzA^mHV?7#(zn(RXR21Q3;qz^6fn_{>$Rz>7~mt{!6PXBbP;`lz`^~vBo8g z|FUA$uCbXUj1Di)-t=`wfs!%-_?c)twR;I&7I&7mNclv$;oX zAB+PN*FfvdK#T*^%fwfGIL3jgSkhnD7~{Y+?=)bz5aYlY{{o>vX%gp<#gK;Et%ee@DaAb3a5tm-r92X7XSzkIp` zvPSu>4m?=`Wyc3B?QsJ2k$oAK8dCxz+m)Z1a|He27ra)FE`hnL6z=XmPy(?_t!L@% zFM;<_1CyfnV7UQ__qBGFfQC!q%5^(Rz;S;RlJ>F-+F<;pE+1X15^@W zfuSX^P74+q&nmC!G;?R{X+Aq;!MjD2-39gTyBp3D7kYiXk-cWPY~=cH7pfN&pglC6j?U;?0y~EfTH3K!30S_^+H7ifY~Q{QD>ip2fe&#PyGuHj zfK8Lm(Qn(8fR5_T*}qzqK$x#6w0ZLq=-o2ru2z#0*mDjhby6>Z2Nkz<+BCp^1!=ks z6-%J_eyOPVM=^XJ78-xCx)_GFYCO!Yq!_wyd2g5et{5y%A9~w98{af^N%+9>X)(-d zt6k=R@nYkZlnewnilOrW)mgtT6+@EWu|@mhilI&4OIGcU7K8BpjI+Lbi($xtcIyvp zEr$I)<1d|BT?|_tN44CsxES7>2|^|Z6@&9sq4e{tV(2w()a^OW#n8xVrR%K;#c*m& zkYB}^VlbU_{pL3)hL2?8kZi+Z=A->zQ8Fm|NcBLj?2+rzA4Z&dSQ@S1QXyRbnq zTrf9q)A;rY#!fONswJP`%W&oJtlUo^Ox+_{o$(3w7h5fDdhZi-D--YXzWNC|>sdTK z6!!@#%p885IrIr0I(>b+WBVuQ-S~j@gw>xQW!`a>5A#1k(>$;A2|k}deZ1b1Nas&r z{Jq_iGj^ZAahut?17@GV*J)3H``}M7q3rz_CEZWZ)>x7j*zOYyNC|&j=|AJ^ zvu{P9(|bUxyG3}v2;1>;!>b~&x$;c4*TW*%wI$ba$F(Bx(iyer#i=5A@v+a~l6^%` z7HDDkd_xgvrab8zf%lnnhu1vm>Qe-*1bZ@;O)G*0ucHdiTj6h(`0~c^{$dzNOyR#~)#-&b)1BBp>0^ zu&Emg4t<0T8O96r7kvbkT)oZ5oj$^*=~DwH8GMA{c7BJ3sD1?R11|GSUVng5Uk!T( zocjQlPeNmp*L;BPipO6W&G-N%DyCB(4)_4c<6*qEMMEDB*sg;)FOE%APS;&4~(Hw93(9R7=EA{V!3EH<51q>E>CdI!C=P14R}=ELr;d+hzU#Rp*yV zKBzCV?|1A<9$Y;X8nVDQ4{Y}h)^_WX2hApj`ddDJ3+KNbJketDTiEy`?d;LsZ$aH5 z^UnLUTqw(`=n{|nBA<6oouA(+7xtbqSmh{v1FMF1w0trB4V)}EZ8G9(4oJ791e{4LQ>z2d?#OrV`}y8qS@OX%D6 z+WYa#GT~#t$R^iaUVyFRz;D|49MkZc{p#Z43~20^`>9~tQ*c}&x_qi@I$Un*;H9&wIZ-0)+?H>R&F{UW4D6qlN$W zv;Ez-U|i8no1&YWYx3*(V-)w8m9T3k_gM#j>?g+y$@Sp(6KWFq`yW;a@into2e_ze zu=Ky{`+wK>|E}--&G#_y4Z%|6SkzyT1Q-egE(JKCbKk zUElw^zW;Z9|L^+#-}U{!>-&G#_y6av@5|Tw44$LI-z5m7|FqdTBEy++5z{=S9N=+b3k(V zVvfNA&6#j@>=`>ppB0ji4x9qNufNE$ZQXa!>o*-e^3Vvpev>nj;+uGV)%8v1 z7w$dS+M;WA1Z$zxPkkftxgsC>~|uBozGeo8Pkw4zTQ0lGnEhnR!^Rnvhzz9 z^Y0nw`Gi}I)grMyT6EIJt2~kfEqrQyYr-wbQRX-H^HxNnpMVy5xGMVQinauN|LV0;S-^FB}k7hE@ztZ<$bCIW*9(A}2lX>2j$vnsJiK%^f zzJ|#>w_q~Q6`9QQ>-0U{gz$VRlX*Up$vkhsWS-y4mtUXf8<@;Q<=>3!A$0Pb0+h=h}}ncevipKKf+|5 zhclVyE==b6NG9`Ko5?&UOs?VbQ9=H{;7rW5jnKko(V3oiv+?(9A+2}M+Yis)cj)<| zw+@bP*So!#c@&a#wED%A;=V^=vm^tJ(;zgtY`-D~<5NmqcegQ*hg4fpn$k!kBjT*G z&aUJ-gX&I-&C{;bu~63IlcWFcE1K$xR=0mgnnH2IY zL&Ccz2=IJojkKND;e~2eD6z)!!hHSLj=Kp7yZe|%%TSJbKQ~U{HsmM2PJd>H*S8(t zS}pDl9BS|`EzAY?T?&<>cG=#A+k>p9xOW00lB(&rT86)4=%al3r=p| z(}t>%#i)<=?0GADKZN$GD}$GG8)`%hihZ76cm$^3y0v@M8S}@@FH}C93T7If?;;FP z-^lx?v}QhrwX+&(5G_62cUtmoNv|ic^ZT)d^G>(H^4=uo7CwRN9oIM4Fu?kczT&8L zG!2%8$DH%MiTj=>?z!Gbln!?uj96wp1Ft94+}g3@Q`oSl@xiZggN#V&{+k`~eOPJJ zzpgtW>}fkjT0 z*`bv)_7pV3-x;)Au*2*nyu{zu8P3A?Xxnq&gAXrZ{O*-6eb(T}W(%@?QzJyoLCQ7e2h)iuQ15KYQ2nw_w~UX2yd%*nVV1<)aRH5Z=4Vr3_#E z9Y&V$(G=G_IC-ym`qKimhmN63!J#~G3$NaKY#i3#E2LFwK^}A)Y>+BFgZ00;yN7r0 ze7L(>=FwFVum4%=*=DbN*yl6&@#*=vZ(e!W6x$Q|@YPi;o9BZ2g4^mGUs{|G*DNwM zhALutb>=Vf8O!ha4;>SvFXiJQa!ocL;yI>=;W>+Ic*uU+7G`NMF}``{{v|j*u#ddl z-~aQtoY$F;{F#UnKM&%0{qvzO4|m*dxq6V$Xh|Shnmw3&aEU(``uFC;=>M=?SphNX|y`d^NK9KD5d!5#T ziov&^YO~S)VcWA$`9(m-H=8v=z7NB6;|=VRYRX;x&1qU!L?fBlf zubjBvuKs!mplV5(%V6yP(vnG?+8o8-IX;5+SJB_e9mP$?$6-ZUYO>RlE;t_C&>J}5 zBy=`=@%iOEJU=SKubFNf%(XqOyS4&l=dz;Cd(J@m1p7{qgZfFuKRUFEhi&fbl*4jy zymG!3)^lqDR2+7B5PP#9>RUKHK;=B_UwEL~qZ>FrMU7b>Jo^I7^NDI+poIJErFk}u zGA_bWE1Q&jg7p#VbWIp|83sAI8~T-T!#9v>3n{(b$W zy&mK5@S?nu5=LHwLhJPvP4m0s^=F+?SucU3!50o5-q0JzL&2@x-cm6C`lfjO5*!am zcC2yZBsf*N?7sP$PT1cATfxO7NdL99tX(7gT}A3Rm7n9UgEUxIs1}RkMNXxbLG^Vo zac$rDP8IsQZD>=!h#TPM-#!!y(chvH>;rq<1jDh3x6~eT_W1c#=iW^i@9}P=sW#5f z4b++kx!eN1Hpkv z4;+LpG1@qO*lPXSmT(7d4czR}R{`r6^>F4vNQV90R<208t&QWgqehdIWOyC*=s?0- zv{&l;lGl^&LVnJ#d5YTH{qM=B&V_eDTc_Ns$w2fEq0-uDpL?))N}o%yA94IHwYznJ z+=qbUZdRU^cs;)_3*N1|5B^ahUAz54dkOU~zip5L3$9Lh(CR*CKdfFLxcOEkJ!XdA8dz?=kG0s@Em79Q}V{tiil< zk6}^xFBjuSXpf7-TfHoO46mDLbkm=R_ruX6$2IBk1io~R*413p3d?JD#Ki@F$JS0m zzkOVDBl6r-Iw$f8gbvvk>p2X^`>;lHlb${SiE7hp*&l|ZKU_H)uaO1=o}X{Ga|`z8 z|7!fIHU7~dVmuoU880o!q~izAbHd~@&!wH^GS8!~y`cGd9yU!b^W0WRF7sUbnEZK| z=Q$JPGS78?$=?&mbLZ1?ndgx+59s+km+p|u zJhz=BmwBGkUM}<8`E3e4pXa5~a+&9T-g24eq@P^od06#*dOpvIR4&(Wobzz@z)u+c zpVZ7peo1kP!(qRbK5{;M z#J{C$>rwNB){u^$t_4~cN{FSYPl$uE9pA

    iwBR+3Q>#GEgPn{0_+x^3G%l?Ik=VC@b*tA3ZJmC+*m~tudd<0bjVtPJWi}4Ie#L~I>>q%iwmnn#(YkjHtf|#76(>|^jg?9 zWnI4mf_pUXs}fl|eQiLmCr1S`8s}Ascw6;8I(q+dfjq9O5>eT*x4Xr~7(p)@$5oj$ zkG<~v$<ZB?%u&llom)&*GA*60;cP~ zRf#~i!Jf;`hXi>v?x-3$?(#+ZaltmhI2$g`s2b_{aC4vUr{@UdaYfb0RsCHP4ZU{@ z+-Mw8brKeNao2*L+XPc-+)#BAKRLiB+%ufT2~{U62j1Tj+*<1*#UtCjr-Y%Ja{!j{n@WTfjrJHq^%n6tb9IDAdj=zg!Hgf+tSl_v)~1dtJ#F8Y9BXA zys<$bkE7Xy6fb|=|Crkv7B{mg+52F#^@!EM0(qRwrmWkS((#Ot|NeUlZq)eot7NhK zL~fm(8=DLS_uQP6Ihx@k4ha;^3>5nlGQ-Q)-34>Z2=zhgk7Ph*c!c`-1|sGvatXk+ znQ}%PCKF;Gg!FpI7Cdj3q2iiZ#ODW<^KPl{m~|M|8xoeS2yLql1HPD z{M%nR`RCuC`InI2e+uM3`>S2TQu6yxk^EjXG|BH{ z`H=$sYA|fc(q-YxSFBvMdd=E(>o;uNw0X`VAfBE|D`;VW$h=QV$vPy%7s%q+u zG#WQ)s@bf0iDo=Fdyk&Fy?XcQtEb=3p#Ok@hJywV89HqE z2!W9?2t_WgZsM8l9-gyidwKi#`pxkV2n?DV91=Qj%G7DoXE@iNK7YZ&MT`GW*Z=?Y z_5WYn-(;kznYqQN(UxPzT3OqSvmI||?=Zp9Y2u{Ga{Jex{{IR42l;pgirw@A0!4vh zZXUwq*`7Y`Zrm&)(BIR?(@o^2-9tOj*G1&+i+KWkg91JDX8Zb!MeJBK)8Ero#0{%7 zO}kc_cC9oo-?^gMg!l!C{R4gV@DyL-=db7L;ps!q_4C)RIrf=Hh>ti}Z=P7>CGv42 z9=<;Acu603yoQIb7scFBfk15+f6qV>#^fMG?Bh;x*Lh-BF2W;U7@tGrEv9M)1&Bxx zRyGKA2?+KK;OZR^EOzq@@X(v-=|js1@DurP@?5cxcwUg$i&K!tg8YNrgG8YTzb2p9HRul+8yp)OOV{=n`vtjpdE#u6zb*#V z3>0xytfjB3ua~d4izj!P-}yW|y|_syf1Zo4m*-r}!pkCmcd<{Pyutl^{R7dG;sCLp zi@#`|rP`u``YjR#p7Jx;g4sbhjER@ z%bxz?nq%}fPZt+4H9DWp`4)eS3VY7O#^hx*!tY~wU!v{h78Hmksi_|AcU+?e`eXeA zJ$-$!xwyW_VHmvCU4#wK`N(g~+t15$rl%O6PI!##@2tD?7{`%3NR45!4F0OLfv5}M z+6>dJR`b_j+N?5oY7NF6>&&$#<~9?ECgb0OzHCZqtljnzn!MP*a+9QowYqe(jD zmLvta>1ca$k>Sxy-o(-uP}zZaA?M1Oh@88g73C&GK)Dq$pxl&bQ9hDrQf`TZ6_J&{uGKoTe)MPewQK=v@c4!MQhNV0%(Q{q9n6`4r6JsFMM%-n<+Qf^AL zDYqh;l-uJCfV-Y0DGjhDmJaqL54p`aJCe$HBIPzD8o8~*NU{mJxxGCJqkJUsquh#2 zrF5mN3*43OJ9S`c02X6E)phr?|~5pBvR5G}@ABA;MyLNt(%8fizAk(-XT zA>Zd9pN#q;=kPqnvyj_ZnUPfFqsNXSH#vE-6_GNYfSfx&hVebfZS5>c1af=Fu_PS% zWD^S#f_yC6)q}}XnLHY~gTpwgFL&LcD05sFIj1M5Kh;;Gy+%XL!O9w{ddf=58k(A_ z9aYDf+7c5ao0{>|re-`HB@VRp_jMHq1UPy6xcLU#;{*VEDnWcgfY^VW%Pg^Lpry}D zUmP~M1Sjkxm}Vsk2sCjG^qecU_4Nz#qnKQl7elPEM3K9Aq;H55nLzA`Ik6)H$pE5H z%!n2K@t+1^VJpIxgyB+)(u%MZOT${KsF<6ZFJHb~1y@lF!feA<5mlnwbEvIT7->j` z7#P^vuEKM*b;DML;aSAl!`Z{bLshk5h@W4upP#BK!ThSEA#(n6al()Nus3*Q_cLQZ z;rD;sCyHC&NtjY~8g%auwkdJ{!tgi_*J)dP0UWnF2d-*ESe%uM93FZ3sRSaE2l&hv zsW4p1;RVGRH(*7_#%rxpKC^Oea`@=^m+nBL`G(D&`*&jblR4b>*{1u@Rn}EgWot`@ z)AjVvK~o;V#+SV_8Ye3PVyW%t-uaQF2ZSwe@_EI-{hrTR+v8lKFY zdMzrdH^b?Eu82kWzP}i~W1rj2?7(okuPky}_cvgsc5c+RY+yLu&lb}t=M5~Ix_f_B zwK2o#zPX7Tw&lW_{zZ-7s&->I-JhpbYW^1Xs4nrSzTJ-Dbl=}aD0>S}a^qKKKWV{m zx}Pv=} z&h&l6|x=}Km>39;LBl}Su|2$I9M!NFX+bGxsuDTliLK}_q6b=+pJZ*{uEDf!uLEqTh+qaF@(266_>y7XMAr| z|Ml&L`nK=O^r5)fE1hCcbG_Q{vO4b%GA_SRdqFWoRD}##5YwOKr}%;wsl}j`@uJf( z)#gn9YA(N@b~k)KnWf44wLwNKKgClU;d{zfg^(8sO$}N8&ouuTd~ciBZKkBhUDl7n zDBib4gHn*JoOvbghzZO8h0E_D>0JtQ%NkxzmGSncxQ@F`DcG4$z1SpmEX)6u%YU=Q zoKomH{f+8lOLL|V#mydWDTUqpdx-X3AI1x#=kh;4TwV&(CO&Xg{KfiX7{$p)%`#9;O+U5pVP{tU4=(>_v3?npSaxu8 z+Q#Y?M)CBHW6R*!lk6rBH}U=YCzpR>JNGh(IA_>t6Ymch~~5ALi`7{ki{ z#pQ2XwWkdFuSj^;$$-@>jN+T#oG*h199$T=_cV`;|iz z(=o@Ee`C0i;-3@D%VAygittsNnLc3@FWNGt95xJWY5rtBtFM&e4kdo&5Me*l@}NEM z&x&066CW-whmnJOeZ?1U%dab>_~(JU%E35uN%Xa=Lzw;)SJgRH4gtC<(ONrMy`&Tu z9!x3+$NTDovt}~CB}zhq8+Oj7m&2Cl^P8M{tiZ~b<4*6(;q@K8rDNQ+S@{%S74fAU z5`T6TW!f@7lu|szyHN%7wO_qFGnyYyl)3W1=V?{I(!mc3JzUs$D5N;~saF9HXZLM$ zy&0=l7{w=E!T6$Q4605nt!8>kDSol@xC+?)EX;D^Bi^4?xbmfXGb-SDQk(R~>a4wl z6fb@6Qvsj89qBlrIo~fRe$jSO1w_xiicl1UIDK6yE$%cI+EFk;szBLD_}@wjQ)p7ZRNO>;=s7xD8DY1 z5OgR1vG6VHcT$QA{q!o~LNmwaMPJxBNz^#~qlXTwgai4D)5{VD$?GMgxZu87B~+hp zaXai8@1GR+=w(|8s&>w1_r|e)A*Fbj!<0%G*8LG#zl+yjohv`pdS)fGi+>x@FNgPk zibu4bQwfPTwsg$K*Zg5V++9F%<+%BkVEArr#(+^Qzm(!u9adDrjitwazFE+Z*`LOR zT{me{CA|J74JfPeAByM9-c<=NN^fj=BI4~s@rm})l@Ovk@W<{T-hU|mUGr2W%uO2C z*VBc+zi0?itK`EMDxt&A9##*wm@@lN{9^N@O4#{$VcWOgteE~3mrlG_30A%bSFO9i z<|k4)9+HObnBL)0)J}eW(wHkhDj=&823uH~bpVD7DL!;eekH8idE%OT0AD`E-F|$k zgl4TGqe3;={7_2qg7vaWFy7zeior0ZCuzc!AMyQXB`B*$d=uQ_{gdLlV;WY0rsc-g zj%qA_7{#4~n^wV<@af9J!~FO|@z3EH=XYhdOAopqXZ9pbx$^e}bglv=vfcVyC)Vyl ziW9S*Rq*iCrSbXcddxl)zbVtNf?_%=CAr_~?iBRdCFyMP!jG zo6m$%d}!9>Do{^edUVc-5pq4FC?1jM!j!(_$4b}Nb#`V z%c|g0H^cBN11#nFohcr%X>}F&cG&nd&zJS`g|f0$VX=N9Qp%U&~mgcSE^o>K+6UxRinc+JKK zXNq4m&#wZLjzdGO+A}{1qqx-LLlsD44g3GN!s}1*l=&r9p!a22S|4BD{uI|)Tv-Jn z5nDeuS7!5#9E!ILz9?PaiY;ksqdIvOzlq4>=Pon>%(=>?0a{5+Pl;`9%k z-%SR;4nI4s+?TgM#SPx}l)-BAZQ9e8u>L5dcwghbGT2g-y#iXX`;jxnqt+S7;L2%F z%Q;Q?`zgh5J~WiUI}cICm6Lq`rFgRPFd2MVZ?b9K1Lo&ais$JY$si?qti`Y3@63NF zZf0#Fg9l%gJ61>LvUPygoc?W{&1E3++iYoYip^WJDIV!=DTC;p!}mVF!NxZs#fx06 zWpKE>d#mxyo5=0sOmX3a@iMRq9hAAtm)D=-$s;DnU~Z;+l)*-JUyGu6Oq)qEm^C+B zV*=m5q!iaIoGOFV_fOvb3T5MM4#oS%Im^JLyLIT2OfC6!NgGaoEpIm&lzuBdyzeKk zKgBh*J!JSk;Rl`5D%p4?q`1M|*)o`2+(c{hLe}q`DZaUYg!ye4#lwF3 z%OG<1XT^oz86HJ(vUaWv`Yf+%?75xyABqc`%#*=Km$H#PjhMgXP~3UdLK#d}y_@$S zj~_qVa{90O5+;NGr%G2xZe_SO#j`}=GO){C)N1{+Jb8NwDIS=#QU>E~9Mp~%F@JNW zcu3o|GRSZmsO(zE-%ly7;l4oz`F(WvtvM)@mlH*Cvy+=;FlT-8^)ZRe&Qgk7eTJs^Yb5gWE94P@hnGsSI>N6TRPhD3|5j?4~W6c4*}R0hiz?jC5cP*1K; z6vc%}$7Qf`k%e05Ce|;c6pu?fDFZLHPIjFYb(#JYFSr~hgRe1DQ-?UKGXH7M=}%6^ zV?T9sPuN+_%F(8H%gFOGcr(I&Zk&+SOGt6Sf=lQRACfy)hci8$DIPH?QHJr+b~GCy z;h&2s-q%1PgCl~u8sBo+eI$zFI^;U`)6+}(`Q7L$*GEe6b$4&dVC%PEQ+2iY@rU9I z*4>f8lmML*>#CUDNC!@TP0M>SIN`Q3Ey9t_>$EBE@GC_Imrq6;^s?gTEfn`S{YVDY zy*3USmCTPn6rVWhi44{($ZUUa9)JI(xbR2144lqoU)ycP=CM%}H`x752J17w6z(0& zo(H8A7YxjlLDZ`8TP`Fr|IDFy$gM0H4DpT4?{|XPjc9TDe;@x^21m!bW=@V__0^_$ z`tvt3_%=^(hlv6|Z>M<6$$2v9I#Q*~%$1)%$n!saCxd65vYjn==^JCYINzqYwpAgH zOPwnf-3q(Q@hFOGT>XgUJoD-rtX(PZ7gCDH=oZVMeH=W~D(@oCpF?rwjioZ!xO~?1 zU+tNFNJk-FWoT(RuE#vuH~Q;xUVn;PSyjnk*V3ciS1xAvO(De{4pqzGK<67{9`)hp zZxnZ{`XYl7T3#~aAFP}(iieNHfCG%+6AZ3m=kd za9HVecI_tKe<=Q0L#Y~qI~n@4Q{vZuI&u1wQ7YB2-PdN9(H`FaDekeLVKw};dNRNB zNj7c^DK0pvRt+Otto7*>#QP7$*S%;|4L{DNJFn>5M{c(;in}Q^sfJw%`HfU=v;0vM zPuJ0`1}}v(8SS*S<@u!)&ogaa4T~1{nZ9Ec^OGEk$4+lq4UcWdO2?ZKd4AHF)4y*} z>uQ)jzo2QiK-Mp`DZXH3+iG|_-Ei#V`>cE+#iO>huZHEth6l%~v+>!P;xYTRs$rse z=GMd7y#G@?`f#Ue(7ofHe(5oL?vA2(64X#D?RR zHWpO2v@xUHp5k~&MsxrDKm3%QwI)$ptcg;s^EFo}6K9Ds+4M%a7W(_}C+;rgq!h+E zIX1(TNRhY?pPpJPox|0#{ylw8_Mhqe{(HVW&742eYhRx$Kkbb?ojcx-$NYKeb@b?- z`)4_I(}%zPGrjJ0;@|z5Ubmi?-v4|0{enN!>t6q0;h*Vs?Xa!r&-A+I|0?8=p9_jpNdR@CUarra7uHC%c<>`6M-XV4DKFI6O^Xr!1d#PE? zm@ur?aov1H%YNtkT}^o~3JJze+kpXs&r)H-fPw2^A}v)buX zPMQ%Pq}u6q^-H?;XL{ZGy}JHqdR;#|ef!V!y5|qPSAY7gTr=_lskVLzb=p&@;CDM{ z);g|RkDDLl<#1)~#ADvS>*||V{^#}Tmh(#8{11KVrtjAHGrhLG4-YjbNl4s>zkc2N zG&1@#z4rOsc?l+erq{J+)qj&7u=?N6U%2+q^yE7B9=Tqg&grsfoq0_?>e_MMHggiW zw=tKEe&XR=Hc}~);(^9Q z3#m8KV5HGVlac(9)*wY8T||0Hd zA*>6M5NRTk8sDOZvU=$RFJ0|A--PXfdlm2yu3&YMcij( z?dulgCAPr5q&B#l&xDX^3Kn!L65C&dh$5Gd+mB@K?~j{WF%YbUzgTSLiCaniLy17i z%2$N12A~q=Hs^A4JDyD3-28Em5`Mj>Y%dNp4f4kgoq=Y!Ez&j6*FO|<`k`iiq1>fS z$TbB#>%Yhoz?CL{q~P{QkygKT9*w(|xl_p@4s#Uy2jK20^AHmvtyLD=dPVX%j9w}b zH+s4R;T~)}bAW;c?#Z(7#GU+dHHbb%Ouc*q#Ke>y+u+a3Sfa9>*xPrmxON@Jn%mi! zTQP%@Mch^7+FFb8I<8pz3HIi8eEMMGWN%{W>l)~Vi)P%8RCRAV5$^6it8DKj z7W&2SYz4Kf zuQzV+#TNHLYrh)!m@+S5t#h4HCo8ks^++yoxk1oV*p(DeTti+w1Y3 zA?>hUp8Qrk@`P$-Czk8jR@pAlYl2TOIs@*aqpdH$G>InizQgd!=SFP>i-O-EX>NxoRRuVT=)WWTN(W-nl@`P&Q zk6RBNLjACf2hx5}(@QufBny~bYWIcD+<6v3US77MKo2&W6j2NnsO29cLz&^odL>)2 zcs7^S&DPUTOe*-?+=aVdUC$gUBwCAftr@M(H01Fx`|CaME(xG)_w)3TXLOZoD#HEvew<01$YbUsb)EQ@vV&KE+&#%1?iiJE z6nO=SNirv)0&?j#C(-V8i_@2lp$;B6jQUy4;HiIjS@se-jdFEB2=wPJLX( zR4=sWR=G#AF@cbzTBR}X$KsTgECZP2>u-T~l^}nyEe`XXW2PzB+gOC)d1hjlAa~s6 z&*zsaJK%2x@D~b!SOnc6OUN#IRW<_H5)xZW##a1`H2U2%x&EzL%4IsnOk$m>ZmPR*VE0E8?11b zEjhrC1Du=UZ^|(*H=NLPUiUA`P9o1h?7sFmT6&4)J9}}Qm)o9G*o3$%)%cf#FYk0j zs$_?)#pS@?C-c3SA0){cB|DL401p1F1K>tkd0TmlC;R%;?pcKF=2EzQ#b)A}BJ^Y{ zQ%f`4IQpkOu>UqzF!u@amX8N=Lvi;*4ZhxTh={TXjq-01H_9J%ybz0VPULm_hE zY-le}aT_;NZm}_(mdt~=yAdH9YuVh1+(#+YFVGH$Vo?D4I}WNLfh0+ejuQLW;Q+(^ z0xM3An7Gaf!dVK-hgOM~9B+C)*7)NXoIWL#Z!~uc+zBsyZKZLm{$51s+ zw#DBYc@q;eM-y91{=QD9XaB$duQb=3cr>>lVT18E6@#qs*QSJYLc)0{AtS8FMZ~yI zCnSm?H^98yrv(zub4ewxwXS+*O4fcdB@ghK_c|WidRmduNcdRy3yZ7yNS|8MV~)#z zS;~?$YqHcF;M|$iKDQ=;9dPL!{r&v4z<+81n|H!1XWB{3f+F#^cS!P24*2;7(?ibR zS|jnkh0k;JSQ&X+Bo!p?$qb+A2tMCY|JOjSio|ga<2XJW(zHg%`82Lv?p%&@eTlmU z=k^@d3<;kJDRFogBn}^h#K|U1=2p8o8EBe9*)H6vl*!u(mp01K+fqCjl^B=C=!?N0uooJ zhe%xdGbAp(Ee;r*eK_LmqR%KS!J35M`R{2l`-EfuRhYkC!gTI~zoVm^{||qk$sbaV zZ~Oj37S%aHRObZl_29Kn2$)GGwm}6F?Q%6bc`KCS`Y+55IP7Qa}aZy z7(3b&bLb!l9dpbv2Wj&VbIkWW75et~_1FLX?){#7?{oi0J(gXmR8`K|d#|!H&R!zVNrL!8i{V0kfXl z6Qe&&gL%Q+VJ@(|)&8~|nDv~DkK<;HiLe-0I4lTe{l5061OGT$@jlwxNdLu~^?K{} z$Co>N{NdC1>35%g{xts8K$;VrTgvPdi#y&m& zzjt)|%Uk~6_4v!%fA4YqPrdtJUsNLh2>$w_2mez?_}~9`{&EXgsSmfm+yWlJkq^7#!uK7T8oe|%}q((<<7mfl|4>95~^^b-3kS_8nfzR>l8hwa-7 zeJ+qcKmSzLmF!pOaT%R|WLEvG5uTO35P1>y43-PK54#P^fhEAQV41LVSPCo|wj4GO z77vSqO@YP2Vqnp*C|D#c0u~MngH1`r?_iOzaG3S{P>jK_AecYQ4@O~iVBRn(w5Y}rOi7WhQA%RE8lGJqd(rvGJpIDuPZRC z+#etLM}Oy!zyH5-|3A8lmE+&toIc+E{`|}e&#KtcsChEQT=)V^NIR7%kqGfze7{nHViT=!>y3 z#%35T4!0Sj2Sy&F#dFdyTHI$jM$`dq$)PRn94s6^TZ=sfqs5hy@VLb>6ERwxD*=yN z+an&Mr}Z-)uZD3RMlb7ejMXtt!B_)hG{%p&Xsd1Lvgb@zpRK%R=mI0o}!t+B;@Jz(F%toQiTr-8fqw?s$Z z{5$wRqrku4f9>-7ecuGv-|q+PEB^a^uV*Db-H)C#uk@$;9;v&^<==PSeXznb-nzf! z!I5JX_MU3x>yf)?OL*<1wfleU?VH)Y$+=bW3}s91riwbn24eYHE$ z@4=W7)5nb6?z>w%v-0?d=2as1p7I@VAbZN4=z~pn%t~sII=*kan)1|_;n`6QQ!h`u z^6JMo_eTHRy3vxGLvI{;QmcNPcGZe@PXTjzFTfBI{`dq16i`tshj79(aKZya*u z*BQlDu1hR;V_B1;A!S^LjF~WG=)q6l#LJCw*2Y0F8cm1>f}W;JAUZ0 zGIxnbTHuN)QnwTDCU=~iRlUo^R~LKzJUj1c&D~2gx?GO#?|*RNT#rePZGzLQ55f7` zjvhIBB>(ot9HKwDaf2V6L(|5(s zzIo7`nch|%;&;@2*Mjxtm0mmI<;H6(Z#W)rdR04cJ#~l5cAGrH?AETsp3xiHMwR&G zTl3t*`cn(;nmNAI8$Z*_TyaNUQSi!>+V%F02^4a_JUwJ#^!jKebux*I}Dmo$AeV>Wci=ZPy*^TYY*5 z=jCZv_KtdU`#|MIw_-bfGeg@QFwV1VtFJ=3zZ*AweZlxqU*^=kviR7^4Cl)$v;GCv zZ>`Md+yCYaAY|d@V9!5@Pto=t@!zM%t+gXa@?VEn4#vgXP-q@*e;u3ZefE%JPob>@9+J$FaG`g|L}}I{dKMW-yEw}|M!!|%eDHS=F2!12Kmv1a~7DL67k|=4?H&VE?S2`%YlWNh?G>+b+ zPw6{aRjw_sm7SCZ$^d1JvQxRIc&mciQ;kuR)Ni$5eV{%{w;5hWYh#4rZjLfD%^cHy zRTU55BK*C!%t$7UDaiKWB)%=*nSajL6VmZ{%4nmAS==mXmN6@sRm^H;O%vA;!p5_X zu`$E4lh{4%DYhwDPIzt*H1tnXfmTBI(Yxw{^kMpGy|D4hsAq07)6J9SW%G{t(8RS?d~G%jf6sv_ z$P{4+qcdMK9hpdG6mx*7%}yc;S4x;HOc!PebA^S%Vqux^ldxKNCHRPVQ2=lmhGUE) zDM$*FVx$BqP0EwX#FNw@KBOKYL?jA1OeF3i_loPvFXa#NS^Q1@8Sf}m6?}zng?_?B zVZD$p+!nmW1>yxUODaX@(T?&)`G$O7j#B0;hm<^}nHr)lR|{!g8m~oZsoG)flJ-<{ z)jf4zy^X#}Ptog{r%n4eiv)wSJU>?GPw`-MKK{8wAJMLIe|eFdEmu)krG?T1@A!*yUg6c=SeKis zO>@&!El%^&Yw3sd>-t;$jIjmZ8%N8M<$#!y?&>$Q^X^f!@^Q?iP9MPf_zUdr#06Cv^qv#1IL$$ z3(8>F!we*IrJYhu*-ws;ciWHBOJNjKX{mHohABiK)z|0;^uyTmZg}5m#uDR=QN`?KhM6PH4JQ6Tvi+Z}3e$_3&TL@LF@;&3 zZO(RPM`BO!W6O{Qzd^Z0Z_Jxl?g+@Xf;TvJJkRT*s#kLE( zghRq{;k0mFcp$tHiecBQ;tug^DNA}Rt)+V@D;LADcTy%OyOp=fTJ@mnqb=8VYR9xr zdXzp%pQo?Xx9Ugr%lZSosPWQ}%qC_VGsKKAW6U_~c+>LNZ6Gt0nZ)d6er4`3?rcqV zD=U#-$tLb7mnIOg1H7wPt zmYp9rYO;;FbS_oAC`L*p={mXq9w8{3lv~OxrIFfK4bXqoZ|Uod%GNpL=KFCTQJunAciOq@u3z^f5 zKRb~9o}I@YW|K(<_k=6Q&lI|g4e4~cQqGXC$}O~bEks|dZ$w0yWGpl?5%chwJP;!< zyoWa_%YDbq;LdY*xIlgc|41w)otGTxEAPs57kTcR-0=Bv`Jcm)*jzYFk zhH3OLB8)@E1*4EDn&Zq^a~k%-R`ZZ)zao;agKeHQAB@aIF*BG&%qnIJbCfxYz4ZjS zpg3ENt-}iJV0JE>!k%YKkTRqa@gkITBeO_0AzV1OmP^Av3gGARC;2Wys4!euB}9n( z#ro2I$&(JC-_up}87&|em3`zU@>s;KzRFVU&`WAX&Cq_)%IO|Dr_V)vxug3UZ4e=G zKmiW6Bn&oY8MBV%NMWur=fmCP1B7RYA)~M&snSMzlAfd2=`H$%zNC)w7jg-?jO;1b zlm%Il8_O-^c5<*hP>zx(%X8$V$c@|ObU9PLCg;j;;fr2M6Qwu2ah|eG8K{m`=c}vL z4QiTtOnt2u)V|c}XfYbTB}2>6s_H~zAe#UH;FsqtFt>X-Kuu`FIDpP^$ zk6CESPvCupkwO{qniwcGq@Cz4x?8@hbW=BAMM~nkwjAsna~Hdo1S4Nvklg54IYf=p zj_6r>F21`e|NSas-NS^_(sk^nJmtOOtQN!m@l@-mqN=G4)s|{o^=C^oh;y*VdCJZq z^*DihBvq!>X)%2$VxKM1!RC&qWHZ%RMI5hHGHaN&L1$S3lv_$~Y{tnn58F8`D-ER+kUg5BCS-2;>6l|i8NJT%fr8q$BOC#xcI-8C{BwlO%oy>e}dyOqX zz9a*LXkj6ZF>oEZYzLc_rVOSfvx6CqK0`byUJ{>) zBV?lE+xH;0INIu9sKnLaG;TTff`7+k0x%}OU9}J`OdG6?(8g%7 z+H`G>_9HUSYHg#oT}#t`#Y~<7Qn{hs)gEhk+6S$mUQ~D2D*(6D(ixnip*Pn3;Q<}> zZhELb0K03H9-~jzXX^9yM4a0?eT$x|?*m3Sfn9u6zljX?On;+08ikO1%NUi7>P8)d zGZdqN(aiYTXm4~edLkze0umiu@XME&e&*dHFg-gjJ?JI zc-%4Lq;VEe?22*SxM|!q9vV-K7shMjz2RsUGz*)>%o1j4v%Fc^^u#{*G3%KG@lG)f zvmx?m3$qn+X?wGy+12cBerNVE`5Q&O0rI_-J7gLX+Ohd+>Y0m^ReV7Pl zG!x6rWD=N_Ofs{BNe52KVy-jynHP+WEzG*J4cKOEOZFSK8?xXK>2hFdxO2pI+G$mtmQtURD(1mO-KvUinJl^Nk`I^bSK}DKBPYxM23

    %5Ji|Tvo0qd%!Qefnpe$m#M4)&G^Ab{N(^SP!58p1j{|)En#vvFl8iiL$n+t z$I4UWI5}RPCnv~>@^U#zULz;Vo8=TaRZc_B$Uuh8luyf9@+F|q9Qig7POkh+&O;ut zDb9+E;;OhQ?n+suqT+$P;;qyHPURJjAB2?AyhR(dL-N|+L^L@1F; zloGAPD6z^MWr=b|DGzi|TV)a78mTSRc4|L0QXQ?1SI?>0@M;6zI~81M2XfK{?SOH@ zxMNSL{oYy8FT?q zRvxV)&y|mX!90`8Db*FC7|4jNfotj`8*Wv-wIx>5AySot5T$oBsQ)V$!lx@WZvYpsqHiR9)X0z|vnxrKOCd)`N*+!-#GM2#JO6GU+ zO@tt!4|dBmAyL=}mU9-o>b2l1R>tmV2qf4W5qm0P^cn1fOu4r@NnNIH!&%!9dq(PG z^|Q#71&v0CBNGq@O2T&+n#rd9ik89o$5a-%qbt*onaXIS1H2=e%mA7{LOu{5t|1r5 z{Q^eRix1;Rf}^bC&+{#WUczAP+?B$9;RNzb7qJI2$7pdT_GF}VKzb$lP#y7jAzUd2b^cZqcpdJYvzf|9i2v`6yPcnvBF+beVjuE;uJK3t-BjJVc zHEmC?(GNfl!NprErncCNv>(&bWpk|-INgEuYSrvWr#9d8KsN?`<$puRc0u&!KZ(ON32j*DQkfgwW6duK%f+K$){asU$z2MNdPv1-f4YOdq9rjO{_+8w zi!(giRNBCIhv66#l-0^Ezbr79 znQP1~=05Wj^bD+TqNAN($jB92kP)1~IJWqKI ztlp1r#`^>32l7FPFTs3IXbK@vD6R?3#5v*;C=(3g@*p}4n$$Qt8OJnJE~&b= z>LvAhdT)IqILdzgr2bTAj22MQLX22rld;G6!u-b0PHowamNa7P%p7K(Gar~vh=XCQ zL9UUaTo@P4E#;1J1Nc<_Eni7!EOdr)FyEdV3xmx`K*(doAAw0*O9K&aGNo+kOIm@} zrfrbv65z8RXd$_@Tm$*64?HkKJ}F;8^eK!yGZJiyQ9G$8)mzw!OTc*F=*z9Rlj~?Z zf}t8S9>}8&JC0q)o+UN8`5ZVm^8G3>w+-ADZacS=+r#bW4njdV!JUDRT;{HUdEVh3 zK=F7EMeH5-jQ12;LQ&f;oD%Aa8Y1*SVChAe;iqDCDOj2!Ed+YqDczSGXe~sfiSz(H zMc>fs$ivg+)p84X{3_*%QcaCgrz5uBW_Nk zi8O`&hW%R$Q7}MGf|hYqIRzfpP~8X4O0-_knNEOxh&`tQs zAgFq4O#2nrJ)G=0w;Y znaMxlD+-os^#ihQGUlMTSQ=f9VHlhx7%o(I!OmbVTyYaxZm>>V)%c z4X=m?Pq?Dp(jI~#^fh)H4-6HEItEzT#yHt~k*l&2YqBFr4p63yEc-Rrf!iiD7RQKN z5WUJsJ*6?y5}FRqUL83l7W<-*QUR#rl47VmfO3|pb-_~-kWE)>N8o)Iw0Bx_eKzLT z!>DBtLp6MjAh3c1#%1_iRkMNF7E0c9=)>3-zE1YIUxKO3)MUm%!MMUaW)`t-#FvDS z-$*6wi9qb;hWuCjH~e={Q=<53$oxHlLRJZTfK(p}h2e$6#CbT@!{TqEJ5=^Q(g10w z6o{NUj|Rf;h5`|ufL{4Q9<6MI`f~tEX>)ayx<@s%9@=PaHt^DW%~v0%r|3E&T9`4) zhzDX~%qXbswg4x5%Fkx2&G<1rfJ_{*Z{wldU54)boJ-?>#!=+qD5?Sd%!T5cEFKh( zLGyhpI!L9YdJ-pfl4gS;-ba2CknPvdBT#UifOXHwB4WT^rMPMWD}4!$cTwA{zt<0d zElo8yndePguoFI6WV0=0&NI{5`G}q^NM~{ex{41cbGtDwz4?k&s z?MJSXSH#AB!ByqF5vfH^=TZ>`pK`_cD!j-y;lJiPVl5`~i}|hCrN?+zp&s^Vdtr(& z2j{;-tR^*-u1YR62w7z%U5&V%j=cArzNVf)>Ca_GX{8KRrUM()03wKh|D3`3^I*Q0 z5Kp{x1zfc*A_))WYrb`i(N6Z4&qLFCN6K?NH;|i# z*f)?b>4hJdJinZzJ3oZcH?;f%&?dI-+AIGZ;Q-zv_Qt{<&>nMv@=M zRN&p4@fqbX(N1<+_!)Tv{tF zm0zNg)DU`NC+Pq45$%dVqh7A3>&Jj?ac#6@CtCuh^ELAo+m8Jfcz+tZh~32=VlT3{ zke!Q=iKGDdWp!w%gSpYr&M%-Qw20phy}1ZfqmDvvMB#Gaf1|~0u>|!2I$Z^YBbQbJ z`Wzwugbeou*i#Jf;4#G&tSD4XR=2C~;b}oyPi?HWO}nnO)5G)+dJkv^n~kebs7oO# z;CrgmoNO+@&);Kh?*Jn_CeN`8-w_9{0CGbu%!R}mTw`$F5!^y9kMqa=%jWMP!*PP2 z5P%xeN@1IDQ82(n)&u`LOU0z}zz{@gf|$@t8Y#s}v!s>MW@(pn3hLP%>85u3bj#EudG_YhbT6gc{RB57)=&Q=!46LS1T$Xj9p2 z2ZbZT9AnzQ{UFoH=8JhK1_k0OaHcbK2R}A|4M%O`HCqr$ZZ)Ekrce$BLn~N>xc#0K z!3+(=E?L7F&@uzDVypOG@W%O=la0t47FW9>+z}XL4pSVC)fjRcZk(F;Utm zDKw160RPRx93&u@9z>KX`X_ci;&k#18JJNHoiJ|nka#neWN`xn>ktfv>+9B;65W_RgVnhv%?ojpi8BL)c z^nvzw3&G#Ged+c9o3zeL>#BTcJ#W1NrgOF^3Ppg7yg|#TCfQ4W)C^ zcAAD-@>%LFw*dLNB?hK2nQ9$!xFxiink~ztq1))LdyCHriUO z0-CL}Rc5qRWxSadK$Kym7u4O0+#KlIKMV6w4cY^}sXVYO0i!vO8pA8_e%8+VyUBg! zLEyyWfZ=Asmu00X&}~of)&yl8valmq>2P(jI!E1)y?GrtmuQ=`{n|aPm|jk=4c{FL zb)byV714YoRL_%!Y&OEa8)i;57o#%y3zSBihqFCTm1j6+8*_v?W5+XZ7*Dnja#kVe z<;i3(G`yl*6^XFUFHppIg#FbJt zFtjFeL1nRp-hio{?e+iSSm)D1b$Im&@q<_h@lHdQ8z>EfS8tHENt!kb>Qgskn8hu8 zo$a{R0oDGSoD10CcR*Azd>VfdT2phd>Pld$zeu~~M{;v8=Ed00A?lCnX|Qz{xMyjhlduDdho|T(b(YRbPoyyDFPA8lzk(_; z3@9~2o~0BR*IR)-?liKDj^WPj0j+s+fd~2ZYZ?Q-E+L3oG z(8o-E9-n|ti=X(l=x^D>pW`nBkK6@MdC7l(!dyfskNQ$|;K5ed$6?Tw6NC-+{qPnU zxuPUV)1)NnFskc0K*Y}^8+?_ejc5S0wPY~-H2NAiy(m=K%HYUNp*eL@Mnhp*1mvCq zym%UXj;d2oNlHb<` zanAN0t3>cnPd1M9;S`+P82H^ael+-1me59w0*1FLMLoeG=7aHdM8?a8KNMD~=%s)V z?cb!7=xndQmPP%w5*fk|=SSgP#-rXgm7jqb+KzX;!@sbrw>O1%K#uQ3C#jHB9E_l% zWaSc8qLK+@(n@MCbp>M?EJaGAfly{h37DU?;N*Ly4CxqV>7MkG7Q~#0$TAI-uc5!K zS4OC})xug?RNB3?EFg?WT2Z~KUK98(-*<|FsjOlOiHF4T(8yht62M}cfUVzX<@F)R zue(w6vHB|%<128pZ?W&jK$HCqO6FVOFlSpTrYeTngX%{!=&-Y}_kSiSWDk06K7f0; zb5>og1uCa2fDa#VT~LYN#}lD7(Dq5;H`K;Th~-63WX?9|AQ}cuX9Cd10%Xy<;v2Cz z_|VUY3r&EqBzZm5#|x+}zd_#Qz*NH2A>h-$s3)L`r z)9N28!E}H+){O~adPDIZh_0OBU|?gQ`b=Qv3?jyr31Iw)< zO~O$g0ERVbC{048aX*-qhf)*%(n=YGsJ%~X1T|(4Fw_%!&iclR{<+Tfy69JIKXxTz z!2|XsTa0k1Mmce>xxv`C+xVqGv(_iGgRuUuxRE@*DnPsi=ClH+xi+Q1gJtAx;BPgt z52rx|{{_753#~rz+jC&tFQK>bdUJHIY{Cvxi~u9pSZw4O1%mwBy zaIFhlmi1y~(iqi`ZuWRIpX|c16bFNQ02QPVUy85BH{`n@{`BWNLBYC++B88Os)@K9 z-AI?g_FbeQ(ggG?oItOR11(BRL&2I2&Ab@6SxvbI^85mH5S)_>q7GkL-Kg$R52#*1 zUtOSB#A?g5KroSLAkGBrs9JV(+1&WmIBuLn@602kv`MX);ZeYzOJbNQ=r-EUlt-i$ zSzkohKI~BF)$7Zsw&NLzHigR79m*C9p4C8Z z4&FHcn#N`MF;I9Rr55T^3y=$UE61^4?{!CV?i&@L2XTxqDpYOIG1whBJOWB`928oMy9S|)Xf*QL zBGg=~BA<;!?Q{y*&^&ZUHHJ1Z9Q|9PC9GXQ0eipRNv<9g@b2h|n1JYfoVSTzh{b{J ztB8%obx@8@qIUTLyQ#cXM>0@L=nma^f|Mrd%1U&Zd{C~b)AT^24?1#28>^spA3`^v z{hQ2!3)p)eyiiB>XHtMHhC|W3%uePqxUt};NBOh7htLys)ons1Fp(hkM13k)wT0*V z*w0v}jaaE2SgXC*n};xuC&7y@0LxrQC*NK5A#msmu!i@lqgGHWtQFHrXr;CCi2R22tXu-N-o~30Q*r{pkRItPKBn`XoJFYA0WV?`Wm!aQOL{3Zc(4Zvm0rl+7NUd90wyPg`8R$9z72EG#=W_DpdLR z8X3UBS*Y#bMqU4nQP3=cDnMnkme~{QI}ch){&_9{{`iTlPgWy~oFm`EzdOLIzela} zJSqUw#5Lk=sT`2NT__1}X%X23TI?u)C+|bv^Fp=tmf{9Jl?J8pjCRAqv55ujp9Kkr z5@>O>S;#KWMNepzx6oO2gT~84l%i@$^r`LuF6;@ldW%N&ItGs%cfj)LWL(!0Lsy`~ z0&Ees9J>WxTo7ol33_7wQMK&^dN}%^3+frv-(je6Z9paIEtI?0stY*m3T-X$TSxRp zj6nV@VDDAC21VsQ`-F7@>OV!^fTMeJ!!6Ef^`2xFuz#K@0$PT3O-wi7x^NN!To#3z zXAB~KKIZgA&Al0v-T-JCL8!UMh_T`nF%FgYc|a+Nh=WO(yJT@QdNWh8kJH5r^k`;^ zr^PHFm~8Co+fX8N(e;uCJ<=vQOD?F+yP;lI7C6L1@{+u<;~9wu8quU?V7LKNpcDk; z9*nsRmBP@m906n!B}GdyQfD<7eaWH7(c#eSB2g2F2B(h&8jDlo)p>{piRhzE!tP1N z%%=dMrGeLFs7Ju3PD3BRq*7A@s`WFQAwve3fo71|89G=`GZfvO;ZQ*GtnRkl0#>_| z&6ROu+>yuYFbup)LoD!Pn!(Egm_Xp)&ZxrmWI~xRCLEC=AKk~GS~i85hyIO3W;v6D z+@H*BhF7MdKRO*q`3RGVN>mnj@*nYhGP+<>NGkj!on)ZaoC(E0i(G=Dn1jfDpX9=S z^1y8KF~2M4#^s^{nTNP-6PyJX!Bub*+|gH2QScDFppn%P7=ecxs-d#whb}9BXj6fx zoOc$25eY(piNl2mArcC9GO7tt@@`GzYScHt3Ffn z&^=_+oHZBC6`jBCz=ahx4V%QXQ#L(BCfXfw&sj#GfL)1WJ2FWU;* z>)w>rkQM#VA>$9VDiATc^Y6SWoQ+^3foP(^Mq;7g#ynXewGtz*KbJr=yZ^+ROqD%trtIZLkRY zUUw^Kj}_qZj0=;$QEaj3gmo{$7T*bFbQe8BPmYyamkx0zgID~koYfCIY&i+KQz)nOUdT1RUYtu?e( zFcdt}T0Lv+td+CY&04i&b~6DFd}%<9xYhP=o`yATAj7voQ3vMsiVH3>VAAaq;NHO@tD*2DSMVbi1ZQ>C5D@ zxJz6Pcbm)oSbMk0&a#XA&vzo(JY4O)o8IUY@K*_TEiveRF~L z?Q87oYX6L@wSLwb+XC``&eTq8*&5b0+|}M^lJ9l-{+6xhfLGiH!*Mpe(Syezb7`of zH8b#iKyj}2&s6+ZJl>Y*YKy?1yp77Twf=d3ql37!dC)c8(68l9dFo63p@%2`2mMsh zIPWP+9L{~-U-Vhql3nc>DF>P88M2TwGLSp6j~6lzkF4W|tP_Zg(-YYy0+}WTT8h=n zWy^K7e}>9OtS1st6z`&9_{8c3$0vx(;v5Py#lWFTGd}3zBd9Oi0&pE?JZ|k{Z~IQ> z?R)v}W0EZ#*G$Iq7(^3aM3Mkx)?mbtaKw*jT;xz2 z@~0berw8&TgPiG$oEd<88H`*RjyxF+{uqaz&_r_t#$TNx160_0O>wz;4MzoB? zIi}#e@__Rxjz1E!o+z!s(cVVY&YSw-xO(E4VsRW9_}i9;c%w5f0G)V|=(kI;ch%)V z|EJjhky!iX=&8rSB^R~DevDPtUa!b_AWHph-nJrCEIN7O_;|aP^eOKDIp#NrRZFu1GU7!4%+CAOR?&|@lMh8K|3P#^;C@MwaU?7o3lo4&jpo`@; z@|Fwol{e7T-y$hnT2VWfx^Iv1&h`jj(H`G9L}%2jVT(_VexY41At}&ol6O20qWg=Nb4s1D|K$^9+2RfzLDWc?Rq=@Nekx BfsFtF literal 514560 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,jV*)uZk&RJ9MdBa9i6-or}V*qO~P+QuGw>QqRf) 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%0D`kMbsU`+gzZ=vGyUm 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�&r14gN%}@g_?|@iABl9X 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 From b90f767367a6ccb4afaea0e8af924141b3eb3620 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Mon, 2 May 2016 02:03:51 +0900 Subject: [PATCH 027/483] Cosmetics. --- loader_example.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/loader_example.cc b/loader_example.cc index c44e0e76..0aec2d1f 100644 --- a/loader_example.cc +++ b/loader_example.cc @@ -55,10 +55,12 @@ static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector(f), static_cast(fnum)); + // For each vertex in the face for (size_t v = 0; v < fnum; v++) { tinyobj::index_t idx = shapes[i].mesh.indices[index_offset + v]; - printf(" face[%ld].v[%ld].idx = %d/%d/%d\n", static_cast(f), static_cast(v), idx.vertex_index, idx.normal_index, idx.texcoord_index); + printf(" face[%ld].v[%ld].idx = %d/%d/%d\n", static_cast(f), static_cast(v), idx.vertex_index, idx.normal_index, idx.texcoord_index); } printf(" face[%ld].material_id = %d\n", static_cast(f), shapes[i].mesh.material_ids[f]); From e9a7c76c235da94916cdec478552251f8fe8957e Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Wed, 11 May 2016 23:38:36 +0900 Subject: [PATCH 028/483] Add build script for Windows. Fix build on Windows. --- examples/viewer/README.md | 17 +++++++++++++- examples/viewer/premake4.lua | 43 ++++++++++++++++++++++++++++++++++++ examples/viewer/viewer.cc | 2 ++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 examples/viewer/premake4.lua diff --git a/examples/viewer/README.md b/examples/viewer/README.md index 4e0e0872..8cb41c17 100644 --- a/examples/viewer/README.md +++ b/examples/viewer/README.md @@ -1 +1,16 @@ -Simple .obj viewer with glew + glfw3 + OpenGL +# Simple .obj viewer with glew + glfw3 + OpenGL + +## Build on Windows. + +### Requirements + +* premake5 +* Visual Studio 2013 +* Windows 64bit + * 32bit may work. + +Put glfw3 and glew library somewhere and replace include and lib path in `premake4.lua` + +Then, + + > premake5.exe vs2013 diff --git a/examples/viewer/premake4.lua b/examples/viewer/premake4.lua new file mode 100644 index 00000000..66da6f9a --- /dev/null +++ b/examples/viewer/premake4.lua @@ -0,0 +1,43 @@ +solution "objview" + -- location ( "build" ) + configurations { "Debug", "Release" } + platforms {"native", "x64", "x32"} + + project "objview" + + kind "ConsoleApp" + language "C++" + files { "viewer.cc", "trackball.cc" } + includedirs { "./" } + includedirs { "../../" } + + configuration { "linux" } + linkoptions { "`pkg-config --libs glfw3`" } + links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" } + + configuration { "windows" } + -- Path to GLFW3 + includedirs { '../../../../local/glfw-3.1.2.bin.WIN64/include' } + libdirs { '../../../../local/glfw-3.1.2.bin.WIN64/lib-vc2013' } + -- Path to GLEW + includedirs { '../../../../local/glew-1.13.0/include' } + libdirs { '../../../../local/glew-1.13.0/lib/Release/x64' } + + links { "glfw3", "glew32", "gdi32", "winmm", "user32", "glu32","opengl32", "kernel32" } + defines { "_CRT_SECURE_NO_WARNINGS" } + + configuration { "macosx" } + includedirs { "/usr/local/include" } + buildoptions { "-Wno-deprecated-declarations" } + libdirs { "/usr/local/lib" } + links { "glfw3", "GLEW" } + linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" } + + configuration "Debug" + defines { "DEBUG" } + flags { "Symbols", "ExtraWarnings"} + + configuration "Release" + defines { "NDEBUG" } + flags { "Optimize", "ExtraWarnings"} + diff --git a/examples/viewer/viewer.cc b/examples/viewer/viewer.cc index a86c853b..31606432 100644 --- a/examples/viewer/viewer.cc +++ b/examples/viewer/viewer.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -19,6 +20,7 @@ #include +#define TINYOBJLOADER_IMPLEMENTATION #include "../../tiny_obj_loader.h" #include "trackball.h" From 48839e3b07f754cf3c6350746e55d31b900f7219 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Thu, 12 May 2016 01:13:47 +0900 Subject: [PATCH 029/483] Add screenshot of glviewer. --- images/sanmugel.png | Bin 0 -> 192538 bytes tests/README.md | 12 ++++++++++++ 2 files changed, 12 insertions(+) create mode 100644 images/sanmugel.png diff --git a/images/sanmugel.png b/images/sanmugel.png new file mode 100644 index 0000000000000000000000000000000000000000..32ea150f3ec53aa87d2db29b37f3eb4649d6a674 GIT binary patch literal 192538 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Ü}<5eA%8+6G^k5U9v3B9+oDi-RDOSj4De0>SG7bo zWtsM2pLW}()^&lneG-1^n*C5!>FUiaa7;0ENXF<40r!lEr@U)& zp`NhqrI6Y_x0>{jAB(u?=78C=7;nLJb=4gmxE$&lrznNh+1AID$Lc%ut!(>KMUqa% zgdZnY>nd6n_X`dj%o{P>g60Db3``i1&6Q*p(c3Tk!avcI;%0l1!abMs3@3Ij8b!$* zxrEJo+7kv?dAN{3huzr5F5&@B#u`SuNz+WiM9Qpc1C?Vg7r$7eT`Z~RXtan zj4gmdNUTr*>h3GsT2`-KIRAFTZPZHk@qIoa8v~e@bfz4OannvZ6Xbs<=<7LKDoQc8 zB;>*zaOhFS0wwc?&l9Uf7fEsVU3E;FMK~N!c5-(Tq2~D5)~7UbNBJImF*e|WB_ByA zAX^r(1r6H{n&(h{U^Lcs8@&=#W0@58Dd9zv1@OMFO4^hVOE#FuAnRJGyJ#jytv=^+ zM+%AG*Le|Due)x|8~J-E0jj#w4yMb! z#rHqyXdEScy5ucr=Gy)x<5=20_DPP#QU2O%o^ilw+;;W@mWWWybql#%c9L>&6Q(c= zeP1w5v}zyx|X@O%{HP z`0*3W+ck@eUEfZ8eYoDkA6~N)=kv~Wf$mU8>SqNVC1C!P-FA;ah|s-bSYEW1_6Lk3 z+Xmds-n-y|Na`XUe<9(`TgpB|d)Ug-d)vR+#WaEg))JAl0dQxT4vREKW5y`^$s>`x-Np# z>urAzDbmJ(|u1PM2P_%q?cTb>e<%=PfHi0 z9zYEEn^5n-�iO5=}k;C%ehUi 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